Commit Graph
15395 Commits
Author SHA1 Message Date
Brian Vaughn d1344768b2 Changed export code to (hopefully) support larger exports 2019-05-22 08:41:57 -07:00
Brian Vaughn ec44eb1e4c Tweaked did-not-render text color to be slightly dimmer 2019-05-22 08:32:10 -07:00
Brian Vaughn a03c3b5d14 Bumped Profiler exported data version 2019-05-22 08:22:33 -07:00
Brian Vaughn d09299bf85 Cleaned up some tests 2019-05-22 08:05:34 -07:00
Brian Vaughn 99b6a44beb Updated event subscriptions and getters to use new ProfilerStore 2019-05-22 07:40:41 -07:00
Brian Vaughn 2d4bb01c01 Moved profiling data to ProfilerContext to fix re-import bug 2019-05-22 07:28:26 -07:00
Brian Vaughn 95bd6c8f63 Added export to web shell and removed 'downloads' API permission 2019-05-22 06:46:42 -07:00
Brian Vaughn 36d51f4eb6 Added root selector UI to Profiler 2019-05-22 06:40:04 -07:00
Brian Vaughn c6de014a9a Massively overhauled profiling data architecture 2019-05-22 06:05:25 -07:00
Maksim Markelov f50f9ba5db Fix ReactFiberNewContext spelling (#15692) 2019-05-22 11:24:31 +01:00
Dominic Gannaway e180f656f3 Flare: change flushDiscreteUpdates invariant to warning (#15702) 2019-05-22 01:09:34 +01:00
Andrew Clark 7829d8cf99 Fix missing return pointer assignment (#15700)
* Fix missing return pointer assignment

I found a bug using the fuzz tester that manifested as incorrect
ordering of children in the host tree, but whose root cause was a
missing `return` pointer assignment on a work-in-progress fiber.

Usually return pointers are set during reconciliation
(`reconcileChildFibers`) but this particular assignment happens inside
the custom reconciliation implementation used by Suspense boundaries.

I would not be surprised if there were similar bugs related to incorrect
return pointers. You're supposed to update the return pointer
whenever a work-in-progress fiber is created, but there's nothing in
the contract of the `createFiber` or `createWorkInProgress` function
that implies this. I propose that we update their signatures to accept
the return fiber as an argument. I will do this in a follow-up.

In this commit, I rearranged `updateSuspenseComponent` slightly so that
every call to `createWorkInProgress` or a `createFiber*` function is
immediately followed by a return pointer assignment.

I hardcoded the fuzz test case that surfaced the bug.

* Update all progressed children in list

`progressedPrimaryChild` is a list, not a single fiber. Need to iterate
through every child and update their return pointers.
2019-05-21 16:56:52 -07:00
Sebastian Markbåge d7afe23f14 Rename "loading" to "busy" in SuspenseConfig API (#15699)
loadingDelayMs -> busyDelayMs
minLoadingDurationMs -> busyMinDurationMs
2019-05-21 14:29:41 -07:00
Dominic Gannaway ef4ac42f88 [Flare] Update interactiveUpdates flushing heuristics (#15687) 2019-05-21 22:03:45 +01:00
Dan Abramov 6d4f85b611 [Fresh] Set up infra for runtime and Babel plugin (#15698)
* Add a stub for React Fresh Babel plugin package

* Move ReactFresh-test into ReactFresh top level directory

* Add a stub for React Fresh Runtime entry point

* Extract Fresh runtime from tests into its entry point
2019-05-21 21:54:10 +01:00
Dominic Gannaway 121acae090 Flare: simplify dispatchEvent discrete argument (#15694) 2019-05-21 16:06:17 +01:00
Dominic Gannaway a398cbd5a7 Flare: update invalid accessor warnings + add no-ops (#15693) 2019-05-21 14:12:19 +01:00
Sunil Pai 9c9ea94852 flush only on exiting outermost act() (#15682) 2019-05-21 10:41:24 +01:00
Brian Vaughn 7ce9f4859c Renamed Store importedProfilingData -> profilingData 2019-05-20 10:45:16 -07:00
Brian Vaughn f1561e9e17 Merge pull request #274 from bvaughn/commit-priority-level
Show commit priority levels in Profiler UI (if available)
2019-05-20 09:56:58 -07:00
Brian Vaughn d440380719 Upgraded to canary with priority level info 2019-05-20 09:54:07 -07:00
Brian Vaughn 53de5b69cc Updated test snapshot 2019-05-20 09:42:37 -07:00
Brian Vaughn 16a81feb72 Moved priority level constants into rendeer interface 2019-05-20 09:39:26 -07:00
Brian Vaughn 9a6a19456f Show commit priority levels in Profiler UI 2019-05-20 09:39:26 -07:00
Brian Vaughn 50b50c26f6 Inform DevTools of commit priority level (#15664)
* Pass inferred priority level to DevTools commit hook in PROFILE mode
2019-05-20 08:37:25 -07:00
Dan Abramov 0bd9b5d006 [Fresh] Support re-rendering lazy() without losing state (#15686)
* Support re-rendering lazy() without losing state

* Clearer naming
2019-05-20 15:47:27 +01:00
Dan Abramov ec38def44f [Fresh] Don't traverse remounted trees (#15685)
* Don't traverse children when hot reloading needs a remount

If we're gonna remount that tree anyway, there is no use in traversing its children beforehand.

* Add a test verifying hot reload batches updates

Otherwise there is a risk of it being super slow due to cascades.
2019-05-20 14:55:01 +01:00
Dan Abramov 5731e522d4 [Fresh] Support lazy() and add Suspense tests (#15681)
* Test that state is not leaked between components

* Support lazy and add Suspense tests

* Nits
2019-05-20 14:11:18 +01:00
Dan Abramov 31487dd82e [Fresh] Set up initial scaffolding (#15619)
* Add a minimal failing test for hot reload

* Set up scaffolding for React Fresh

* Consider type family when comparing elementType

Rendering an element with stale type should not cause it to remount.

We only do this for FunctionComponent tag since checking is unnecessary for classes or host components.

* Add support for forwardRef()

Initially I thought I would compare families of inner .render functions.

However, there is a corner case where this can create false positives. Such as when you forwardRef(X) the same X twice. Those are supposed to be distinct. But if we compare .render functions, we wouldn't be able to distinguish them after first reload.

It seems safer to rely on explicit registration for those. This should be easy when forwardRef() call is in the same file, and usually it would be. For cases like HOCs and style.div`...` factories that return forwardRef(), we could have the __register__ helper itself "dig deeper" and register the inner function.

* Show how forwardRef inner identity can be inferred

The __register__ implementation can read the inner identity itself.

* Add missing __DEV__ to tests

* Add support for memo() (without fixing bailouts)

This adds rudimentary support for memo components. However, we don't actually skip bailouts yet, so this is not very useful by itself alone. Tests have TODOs that we need to remove after bailout skipping is done.

* Refactor type comparison for clarity

* Hot update shouldn't re-render ancestor components unnecessarily

My code had a bug where it checked for a wrong thing in a wrong set, leading us to always re-render.

This fixes the checks so that we only schedule updates for things that were actually edited.

* Add test coverage for memo(fn, areEqual)

* Explicitly skip bailouts for hot reloading fibers

This forces even memo() with shallow comparison to re-render on hot update.

* Refactor scheduling update to reduce duplication

* Remove unused variable in test

* Don't check presence in a set while not hot reloading

* Make scheduleHotUpdate() take named arguments

* Don't keep unedited component types in the type => family map

It's unnecessary because if they haven't been edited, there's no special reconciliation logic.

* Add signatures that force remounting

Signatures let us force a remount of a type even if from React's point of view, type is the same.

A type has one current signature. If that signature changes during next hot update, all Fibers with that type should be deleted and remounted.

We do this by mutating elementType scheduling a parent.

This will be handy to force remount of mismatching Hooks, as well as failed error boundaries.

For this to fully work, we'll need to add a way to skip built-in bailouts for all Fiber types. This will be the most invasive and annoying change. I did it for HostRoot in this PR but there's more. I'll add an automated test case that catches the missing bailout bailouts.

* Support forced remounting for all component types

This teaches all parent component types to remount their child if necessary.

It also adds tests for them.

* Remount effects while preserving state for hot reloaded components

This makes sure that changes to *code* always propagate.

It can break components that aren't resilient to useEffect over-firing, but that seems like a good constraint since you might need to add a dependency later anyway, and this helps avoid coding yourself into the corner.

* Add missing __DEV__ blocks to tests

* Fix unused variables in tests

* Remove outdated TODO

* Expose scheduleHotUpdate directly

* Inline isCompatibleType

* Run one check per component for invalidating deps

This also makes the bailouts more targeted--no need to remount useEffect for a parent component of remounted fiber.

* Resolve .type early

This moves resolving to set up the right .type early instead of doing this before render.
A bit more future-proof in case we want to restructure the begin phase later.

ForwardRef is special because its type is a wrapper but it can be hot reloaded by itself.
So we have a special overload for it that reconstucts the wrapper type if needed.

* Add a Suspense todo

* Use current.type !== workInProgress.type for ignoring deps

This gets rid of one of the sets.

* Use workInProgress.type !== current.type check for force re-render

We still use a set for forced remount though.

* Use wip.type !== current.type check in more places

This also disables the remounting tests. They need a separate approach.

* Use a dedicated remount mechanism

* Add a test for offscreen trees

It has a TODO because it seems like offscreen updates are incorrectly applied too soon.

* Enable offscreen test now that it is fixed

* Fix corner cases in the new remounting mechanism

* Remount failed error boundaries on hot reload

* Fix test now that act() flushes

This test is manual so I don't actually want act here.

* Nits

* Add comments
2019-05-18 01:38:13 +01:00
Brian Vaughn 146fd2ad3d Fixed snapshot diff 2019-05-17 07:54:07 -07:00
Brian Vaughn 629e500fe2 Merge pull request #275 from lucasecdb/fix/undefined-chartnode
Fix undefined chart node when switching commits in profiler
2019-05-17 07:52:07 -07:00
Lucas Cordeiro 1e025edb9a Fix undefined chart node when switching commits in profiler 2019-05-17 09:35:10 -03:00
Sebastian Markbåge 9c6de716d0 Add withSuspenseConfig API (#15593)
* Add suspendIfNeeded API and a global scope to track it

Adds a "current" suspense config that gets applied to all updates scheduled
during the current scope.

I suspect we might want to add other types of configurations to the "batch"
so I called it the "batch config".

This works across renderers/roots but they won't actually necessarily go
into the same batch.

* Add the suspenseConfig to all updates created during this scope

* Compute expiration time based on the timeout of the suspense config

* Track if there was a processed suspenseConfig this render pass

We'll use this info to suspend a commit for longer when necessary.

* Mark suspended states that should be avoided as a separate flag

This lets us track which renders we want to suspend for a short time vs
a longer time if possible.

* Suspend until the full expiration time if something asked to suspend

* Reenable an old test that we can now repro again

* Suspend the commit even if it is complete if there is a minimum delay

This can be used to implement spinners that don't flicker if the data
and rendering is really fast.

* Default timeoutMs to low pri expiration if not provided

This is a required argument in the type signature but people may not
supply it and this is a user facing object.

* Rename to withSuspenseConfig and drop the default config

This allow opting out of suspending in some nested scope.

A lot of time when you use this function you'll use it with high level
helpers. Those helpers often want to accept some additional configuration
for suspense and if it should suspend at all. The easiest way is to just
have the api accept null or a suspense config and pass it through. However,
then you have to remember that calling suspendIfNeeded has a default.

It gets simpler by just saying tat you can pass the config. You can have
your own default in user space.

* Track the largest suspense config expiration separately

This ensures that if we've scheduled lower pri work that doesn't have a
suspenseConfig, we don't consider its expiration as the timeout.

* Add basic tests for functionality using each update mechanism

* Fix issue when newly created avoided boundary doesn't suspend with delay

* Add test for loading indicator with minLoadingDurationMs option
2019-05-16 16:51:18 -07:00
Dominic Gannaway 1160b37691 Event API: Add responder allowMultipleHostChildren flag (#15646) 2019-05-16 19:03:38 +01:00
Dominic Gannaway 95e06ac3d0 Event API: isTargetWithinEventResponderScope on unmounted event components (#15672) 2019-05-16 18:59:59 +01:00
Sunil Pai d278a3ff8b act() - s / flushPassiveEffects / Scheduler.unstable_flushWithoutYielding (#15591)
* s/flushPassiveEffects/unstable_flushWithoutYielding

a first crack at flushing the scheduler manually from inside act(). uses unstable_flushWithoutYielding(). The tests that changed, mostly replaced toFlushAndYield(...) with toHaveYielded(). For some tests that tested the state of the tree before flushing effects (but still after updates), I replaced act() with bacthedUpdates().

* ugh lint

* pass build, flushPassiveEffects returns nothing now

* pass test-fire

* flush all work (not just effects), add a compatibility mode

of note, unstable_flushWithoutYielding now returns a boolean much like flushPassiveEffects

* umd build for scheduler/unstable_mock, pass the fixture with it

* add a comment to Shcduler.umd.js for why we're exporting unstable_flushWithoutYielding

* run testsutilsact tests in both sync/concurrent modes

* augh lint

* use a feature flag for the missing mock scheduler warning

I also tried writing a test for it, but couldn't get the scheduler to unmock. included the failing test.

* Update ReactTestUtilsAct-test.js

- pass the mock scheduler warning test,
- rewrite some tests to use Scheduler.yieldValue
- structure concurrent/legacy suites neatly

* pass failing tests in batchedmode-test

* fix pretty/lint/import errors

* pass test-build

* nit: pull .create(null) out of the act() call
2019-05-16 17:12:36 +01:00
Dominic Gannaway aad5a264d2 Event API: ensure calculateResponderRegion accounts for page offset (#15671) 2019-05-16 17:09:41 +01:00
Dan Abramov bb89b4eacc Bail out of updates in offscreen trees (#15666)
* Bail out of updates in offscreen trees

* Address review
2019-05-16 11:12:05 +01:00
Andrew Cherniavskii 4bf88ddeca Fix <embed> not triggering onLoad (#15614) 2019-05-16 11:05:20 +02:00
Andrew Clark f961050a37 Always flushPassiveEffects before rendering
I  mistakenly wrapped this in the revertPassiveEffectsChange feature
flag. It should flush regardless of the flag.
2019-05-15 18:13:05 -07:00
Andrew Clark b899819e77 Use dynamic flag in test renderer in www (#15662)
Uses a dynamic flag in www's test renderer build so we can condtionally
disable the passive effects bugfix. Matches the dynamic flag used in
the www React DOM build.
2019-05-15 14:55:50 -07:00
Brian Vaughn f10a6b379c Improve scanning Profiler chart for deep renders 2019-05-15 14:20:36 -07:00
Andrew Clark d34b457ce2 Feature flag to revert #15650 (#15659)
PR #15650 is a bugfix but it's technically a semantic change that could
cause regressions. I don't think it will be an issue, since the
previous behavior was both broken and incoherent, but out of an
abundance of caution, let's wrap it in a flag so we can easily revert
it if necessary.
2019-05-15 13:38:06 -07:00
Andrew Clark 668fbd651b Fix serial passive effects (#15650)
* Failing test for false positive warning

* Flush passive effects before discrete events

Currently, we check for pending passive effects inside the `setState`
method before we add additional updates to the queue, in case those
pending effects also add things to the queue.

However, the `setState` method is too late, because the event that
caused the update might not have ever fired had the passive effects
flushed before we got there.

This is the same as the discrete/serial events problem. When a serial
update comes in, and there's already a pending serial update, we have to
do it before we call the user-provided event handlers. Because the event
handlers themselves might change as a result of the pending update.

This commit moves the `flushPassiveEffects` call to before the discrete
event handlers are called, and removes it from the `setState` method.
Non-discrete events will not cause passive effects to flush, which is
fine, since by definition they are not order dependent.
2019-05-14 18:08:10 -07:00
Dominic Gannaway b0657fde6a Event API: ensure getFocusableElementsInScope handles suspended trees (#15651) 2019-05-15 01:08:30 +01:00
Sebastian Markbåge 8af90c8972 Add test for nested avoided boundaries (#15636)
* Add test for nested avoided boundaries

* Add test for top level avoided boundaries
2019-05-14 14:41:45 -07:00
Brian Vaughn 6fd2e72b5e Minor nits 2019-05-14 11:01:41 -07:00
Dominic Gannaway af19e2eb2f Event API: adds pointerType to Focus events (#15645) 2019-05-14 15:59:36 +01:00
Ivan Babak 76e569992b Cleanup profile export/import data types, add export/import test
Strengthened the I/O-boundary type conversion logic.

Fixed type inconsistencies uncovered by removing `any` and
by making explicit type annotations and transformations.

In particular, these were likely malformed when restored from a file:
- `commitDetails`
- `interactions`
- `initialTreeBaseDurations`

The mismatches were Map vs interleaved Array.
2019-05-13 23:59:01 -07:00
Andrew Clark cc24d0ea56 Invariant that throws when committing wrong tree (#15517)
If React finishes rendering a tree, delays committing it (e.g.
Suspense), then subsequently starts over or renders a new tree, the
pending tree is no longer valid. That's because rendering a new work-in
progress mutates the old one in place.

The current structure of the work loop makes this hard to reason about
because, although `renderRoot` and `commitRoot` are separate functions,
they can't be interleaved. If they are interleaved by accident, it
either results in inconsistent render output or invariant violations
that are hard to debug.

This commit adds an invariant that throws if the new tree is the same as
the old one. This won't prevent all bugs of this class, but it should
catch the most common kind.

To implement the invariant, I store the finished tree on a field on the
root. We already had a field for this, but it was only being used for
the unstable `createBatch` feature.

A more rigorous way to address this type of problem could be to unify
`renderRoot` and `commitRoot` into a single function, so that it's
harder to accidentally interleave the two phases. I plan to do something
like this in a follow-up.
2019-05-13 16:15:50 -07:00