Commit Graph

46 Commits

Author SHA1 Message Date
Brian Vaughn
fc33f12bde
Remove unstable scheduler/tracing API (#20037) 2021-04-26 19:16:18 -04:00
Ricky
f7cdc89361
Also turn off enableSyncDefaultUpdates in RN test renderer (#21293) 2021-04-15 16:31:46 -04:00
Ricky
933880b454
Make time-slicing opt-in (#21072)
* Add enableSyncDefaultUpdates feature flag

* Add enableSyncDefaultUpdates implementation

* Fix tests

* Switch feature flag to true by default

* Finish concurrent render whenever for non-sync lanes

* Also return DefaultLane with eventLane

* Gate interruption test

* Add continuout native event test

* Fix tests from rebasing main

* Hardcode lanes, remove added export

* Sync forks
2021-04-09 19:50:09 -04:00
Brian Vaughn
dc108b0f55
Track which fibers scheduled the current render work (#15658)
Tracked Fibers are called "updaters" and are exposed to DevTools via a 'memoizedUpdaters' property on the ReactFiberRoot. The implementation of this feature follows a vaguely similar approach as interaction tracing, but does not require reference counting since there is no subscriptions API.

This change is in support of a new DevTools Profiler feature that shows which Fiber(s) scheduled the selected commit in the Profiler.

All changes have been gated behind a new feature flag, 'enableUpdaterTracking', which is enabled for Profiling builds by default. We also only track updaters when DevTools has been detected, to avoid doing unnecessary work.
2021-04-09 10:34:33 -04:00
Brian Vaughn
7c1ba2b57d
Proposed new Suspense layout effect semantics (#21079)
This commit contains a proposed change to layout effect semantics within Suspense subtrees: If a component mounts within a Suspense boundary and is later hidden (because of something else suspending) React will cleanup that component’s layout effects (including React-managed refs).

This change will hopefully fix existing bugs that occur because of things like reading layout in a hidden tree and will also enable a point at which to e.g. pause videos and hide user-managed portals. After the suspended boundary resolves, React will setup the component’s layout effects again (including React-managed refs).

The scenario described above is not common. The useTransition API should ensure that Suspense does not revert to its fallback state after being mounted.

Note that these changes are primarily written in terms of the (as of yet internal) Offscreen API as we intend to provide similar effects semantics within recently shown/hidden Offscreen trees in the future. (More to follow.)

(Note that all changes in this PR are behind a new feature flag, enableSuspenseLayoutEffectSemantics, which is disabled for now.)
2021-04-06 09:21:02 -04:00
Andrew Clark
a77dd13ede
Delete enableDiscreteEventFlushingChange (#21110)
This flag was meant to avoid flushing discrete updates unnecessarily,
if multiple discrete events were dispatched in response to the same
platform event.

But since we now flush all discrete events at the end of the task, in
a microtask, it no longer has any effect.
2021-03-25 22:05:59 -07:00
Benoit Girard
25bfa287f6
[Experiment] Add feature flag for more aggressive memory clean-up of deleted fiber trees (#21039)
* Add feature flag: enableStrongMemoryCleanup

Add a feature flag that will test doing a recursive clean of an unmount
node. This will disconnect the fiber graph making leaks less severe.

* Detach sibling pointers in old child list

When a fiber is deleted, it's still part of the previous (alternate)
parent fiber's list of children. Because children are a linked list, an
earlier sibling that's still alive will be connected to the deleted
fiber via its alternate:


  live fiber
  --alternate--> previous live fiber
  --sibling--> deleted fiber

We can't disconnect `alternate` on nodes that haven't been deleted
yet, but we can disconnect the `sibling` and `child` pointers.

Will use this feature flag to test the memory impact.

* Combine into single enum flag

I combined `enableStrongMemoryCleanup` and `enableDetachOldChildList`
into a single enum flag. The flag has three possible values. Each level
is a superset of the previous one and performs more aggressive clean up.

We will use this to compare the memory impact of each level.

* Add Flow type to new host config method

* Re-use existing recursive clean up path

We already have a recursive loop that visits every deleted fiber. We
can re-use that one for clean up instead of adding another one.

Co-authored-by: Andrew Clark <git@andrewclark.io>
2021-03-22 21:54:53 -07:00
Andrew Clark
be5a2e231a
Land enableSyncMicrotasks (#20979) 2021-03-19 15:28:41 -07:00
Ricky
e4d4b7074d
Land enableNativeEventPriorityInference (#20955)
* Land enableNativeEventPriorityInference

* Move schedulerPriorityToLanePriority

* Remove obsolete comment
2021-03-09 23:59:02 -05:00
Ricky
73e900b0e7
Land enableDiscreteEventMicroTasks (#20954) 2021-03-08 16:43:44 -05:00
Rick Hanlon
e89d74ee67
Remove decoupleUpdatePriorityFromScheduler 2021-03-08 12:49:57 -07:00
Andrew Clark
258b375a41 Move context comparison to consumer
In the lazy context implementation, not all context changes are
propagated from the provider, so we can't rely on the propagation alone
to mark the consumer as dirty. The consumer needs to compare to the
previous value, like we do for state and context.

I added a `memoizedValue` field to the context dependency type. Then in
the consumer, we iterate over the current dependencies to see if
something changed. We only do this iteration after props and state has
already bailed out, so it's a relatively uncommon path, except at the
root of a changed subtree. Alternatively, we could move these
comparisons into `readContext`, but that's a much hotter path, so I
think this is an appropriate trade off.
2021-03-07 00:37:15 -06:00
Ricky
c581cdd480
Schedule sync updates in microtask (#20872)
* Schedule sync updates in microtask

* Updates from review

* Fix comment
2021-02-25 17:25:25 -05:00
Brian Vaughn
9209c30ff9
Add StrictMode level prop and createRoot unstable_strictModeLevel option (#20849)
* The exported '<React.StrictMode>' tag remains the same and opts legacy subtrees into strict mode level one ('mode == StrictModeL1'). This mode enables DEV-only double rendering, double component lifecycles, string ref warnings, legacy context warnings, etc. The primary purpose of this mode is to help detected render phase side effects. No new behavior. Roots created with experimental 'createRoot' and 'createBlockingRoot' APIs will also (for now) continue to default to strict mode level 1.

In a subsequent commit I will add support for a 'level' attribute on the '<React.StrictMode>' tag (as well as a new option supported by ). This will be the way to opt into strict mode level 2 ('mode == StrictModeL2'). This mode will enable DEV-only double invoking of effects on initial mount. This will simulate future Offscreen API semantics for trees being mounted, then hidden, and then shown again. The primary purpose of this mode is to enable applications to prepare for compatibility with the new Offscreen API (more information to follow shortly).

For now, this commit changes no public facing behavior. The only mechanism for opting into strict mode level 2 is the pre-existing 'enableDoubleInvokingEffects' feature flag (only enabled within Facebook for now).

* Renamed strict mode constants

StrictModeL1 -> StrictLegacyMode and StrictModeL2 -> StrictEffectsMode

* Renamed tests

* Split strict effects mode into two flags

One flag ('enableStrictEffects') enables strict mode level 2. It is similar to 'debugRenderPhaseSideEffectsForStrictMode' which enables srtict mode level 1.

The second flag ('createRootStrictEffectsByDefault') controls the default strict mode level for 'createRoot' trees. For now, all 'createRoot' trees remain level 1 by default. We will experiment with level 2 within Facebook.

This is a prerequisite for adding a configurable option to 'createRoot' that enables choosing a different StrictMode level than the default.

* Add StrictMode 'unstable_level' prop and createRoot 'unstable_strictModeLevel' option

New StrictMode 'unstable_level' prop allows specifying which level of strict mode to use. If no level attribute is specified, StrictLegacyMode will be used to maintain backwards compatibility. Otherwise the following is true:
* Level 0 does nothing
* Level 1 selects StrictLegacyMode
* Level 2 selects StrictEffectsMode (which includes StrictLegacyMode)

Levels can be increased with nesting (0 -> 1 -> 2) but not decreased.

This commit also adds a new 'unstable_strictModeLevel' option to the createRoot and createBatchedRoot APIs. This option can be used to override default behavior to increase or decrease the StrictMode level of the root.

A subsequent commit will add additional DEV warnings:
* If a nested StrictMode tag attempts to explicitly decrease the level
* If a level attribute changes in an update
2021-02-24 16:14:14 -05:00
Ricky
4d28eca97e
Land enableNonInterruptingNormalPri (#20859) 2021-02-22 12:56:54 -05:00
Andrew Clark
3b870b1e09
Lane enableTransitionEntanglement flag (#20775) 2021-02-10 00:25:39 -08:00
Andrew Clark
d1845ad0ff
Default updates should not interrupt transitions (#20771)
The only difference between default updates and transition updates is
that default updates do not support suspended refreshes — they will
instantly display a fallback.

Co-authored-by: Rick Hanlon <rickhanlonii@gmail.com>
2021-02-10 00:00:24 -08:00
Dan Abramov
97fce318a6
Experiment: Infer the current event priority from the native event (#20748)
* Add the feature flag

* Add a host config method

* Wire it up to the work loop

* Export constants for third-party renderers

* Document for third-party renderers
2021-02-09 18:32:20 +00:00
Dan Abramov
4ecf11977c
Remove the Fundamental internals (#20745) 2021-02-05 20:36:55 +00:00
Ricky
e51bd6c1fa
Queue discrete events in microtask (#20669)
* Queue discrete events in microtask

* Use callback priority to determine cancellation

* Add queueMicrotask to react-reconciler README

* Fix invatiant conditon for InputDiscrete

* Switch invariant null check

* Convert invariant to warning

* Remove warning from codes.json
2021-01-27 18:24:58 -05:00
Andrew Clark
d13f5b9538
Experiment: Unsuspend all lanes on update (#20660)
Adds a feature flag to tweak the internal heuristic used to "unsuspend"
lanes when a new update comes in.

A lane is "suspended" if we couldn't finish rendering it because it was
missing data, and we chose not to commit the fallback. (In this context,
"suspended" does not include updates that finished with a fallback.)

When we receive new data in the form of an update, we need to retry
rendering the suspended lanes, since the new data may have unblocked the
previously suspended work. For example, the new update could navigate
back to an already loaded route.

It's impractical to retry every combination of suspended lanes, so we
need some heuristic that decides which lanes to retry and in
which order.

The existing heuristic roughly approximates the old Expiration Times
model. It unsuspends all lower priority lanes, but leaves higher
priority lanes suspended.

Then when we start rendering, we choose the lanes that have the highest
LanePriority and render those -- and then we add to that all the lanes
that are highher priority.

If this sounds terribly confusing, it's because it barely makes sense.
(It made more sense in the Expiration Times world, I promise, but it
was still confusing.) I don't think it's worth me trying to explain the
old behavior too much because the point here is that we can replace it
with something simpler.

The new heurstic is to unsuspend all suspended lanes whenever there's
an update.

This is effectively what we already do except in a few very specific
edge cases, ever since we removed the delayed suspense feature from
everything that's not a refresh transition.

We can optimize this in the future to only unsuspend lanes that are
either 1) in the `lanes` or `subtreeLanes` of the node that was updated,
or 2) in the `lanes` of the return path of the node that was updated.
This would exclude lanes that are only located in unrelated sibling
trees. But, this optimization wouldn't be useful currently because we
assign the same transition lane to all transitions. It will become
relevant again once we start assigning arbitrary lanes to transitions
-- but that in turn requires us to implement entanglement of overlapping
transitions, one of our planned projects.

So to sum up: the goal here is to remove the weird edge cases and switch
to a simpler model, on top of which we can make more substantial
improvements.

I put it behind a flag so I can run an A/B test and confirm it doesn't
cause a regression.
2021-01-26 12:23:34 -08:00
Brian Vaughn
895ae67fd3
Improve error boundary handling for unmounted subtrees (#20645)
A passive effect's cleanup function may throw after an unmount. Prior to this commit, such an error would be ignored. (React would not notify any error boundaries.)

After this commit, React will skip any unmounted boundaries and look for a still-mounted boundary. If one is found, it will call getDerivedStateFromError and/or componentDidCatch (depending on the type of boundary). Unmounted boundaries will be ignored, but as they have been unmounted– this seems appropriate.
2021-01-25 08:54:20 -05:00
Ricky
5687864eb7
Add back disableSchedulerTimeoutInWorkLoop flag (#20482)
* Add back enableSchedulerTimeoutInWorkLoop flag

* Nvm, keep it as disableSchedulerTimeoutInWorkLoop
2020-12-17 17:17:23 -05:00
Dan Abramov
e23673b511
[Flight] Add getCacheForType() to the dispatcher (#20315)
* Remove react/unstable_cache

We're probably going to make it available via the dispatcher. Let's remove this for now.

* Add readContext() to the dispatcher

On the server, it will be per-request.

On the client, there will be some way to shadow it.

For now, I provide it on the server, and throw on the client.

* Use readContext() from react-fetch

This makes it work on the server (but not on the client until we implement it there.)

Updated the test to use Server Components. Now it passes.

* Fixture: Add fetch from a Server Component

* readCache -> getCacheForType<T>

* Add React.unstable_getCacheForType

* Add a feature flag

* Fix Flow

* Add react-suspense-test-utils and port tests

* Remove extra Map lookup

* Unroll async/await because build system

* Add some error coverage and retry

* Add unstable_getCacheForType to Flight entry
2020-12-03 03:44:56 +00:00
Philipp Spiess
555eeae33d
Add disableNativeComponentFrames flag (#20364)
## Summary

We're experiencing some issues internally where the component stack is
getting into our way of fixing them as it causes the page to become
unresponsive. This adds a flag so that we can disable this feature as a
temporary workaround.

More internal context: https://fburl.com/go9yoklm

## Test Plan

I tried to default this flag to `__VARIANT__` but the variant tests
(`yarn test-www --variant`) started to fail across the board since a lot
of tests depend on the component tree, things like this:

https://user-images.githubusercontent.com/458591/100771192-6a1e1c00-33fe-11eb-9ab0-8ff46ba378a2.png

So, it seems to work :-)

Given that it's unhandy to update the hundreds of tests that are failing
I decided to hard code this to `false` like we already do for some other
options.
2020-12-02 16:25:55 +01:00
Brian Vaughn
9403c3b536
Add Profiler callback when nested updates are scheduled (#20211)
This callback accepts the no parameters (except for the current interactions). Users of this hook can inspect the call stack to access and log the source location of the component.
2020-11-12 09:31:27 -05:00
Brian Vaughn
393c452e39
Add "nested-update" phase to Profiler API (#20163)
Background:
State updates that are scheduled in a layout effect (useLayoutEffect or componentDidMount / componentDidUpdate) get processed synchronously by React before it yields to the browser to paint. This is done so that components can adjust their layout (e.g. position and size a tooltip) without any visible shifting being seen by users. This type of update is often called a "nested update" or a "cascading update".

Because they delay paint, nested updates are considered expensive and should be avoided when possible. For example, effects that do not impact layout (e.g. adding event handlers, logging impressions) can be safely deferred to the passive effect phase by using useEffect instead.

This PR updates the Profiler API to explicitly flag nested updates so they can be monitored for and avoided when possible.

Implementation:
I considered a few approaches for this.

Add a new callback (e.g. onNestedUpdateScheduled) to the Profiler that gets called when a nested updates gets scheduled.
Add an additional boolean parameter to the end of existing callbacks (e.g. wasNestedUpdate).
Update the phase param to add an additional variant: "mount", "update", or "nested-update" (new).
I think the third option makes for the best API so that's what I've implemented in this PR.

Because the Profiler API is stable, this change will need to remain behind a feature flag until v18. I've turned the feature flag on for Facebook builds though after confirming that Web Speed does not currently make use of the phase parameter.

Quirks:
One quirk about the implementation I've chosen is that errors thrown during the layout phase are also reported as nested updates. I believe this is appropriate since these errors get processed synchronously and block paint. Errors thrown during render or from within passive effects are not affected by this change.
2020-11-10 09:40:30 -05:00
Brian Vaughn
7a73d6a0f9
(Temporarily) revert unmounting error boundaries changes (#20147)
This reverts commits bcca5a6ca7 and ffb749c95e, although neither revert cleanly since methods have been moved between the work-loop and commit-work files. This commit is a mostly manual effort of undoing the changes.
2020-11-09 10:14:24 -05:00
Sebastian Markbåge
56e9feead0
Remove Blocks (#20138)
* Remove Blocks

* Remove Flight Server Runtime

There's no need for this now that the JSResource is part of the bundler
protocol. Might need something for Webpack plugin specifically later.

* Devtools
2020-10-30 23:03:45 -07:00
Andrew Clark
25b18d31c8
Traverse commit phase effects iteratively (#20094)
* Move traversal logic to ReactFiberCommitWork

The current traversal logic is spread between ReactFiberWorkLoop and
ReactFiberCommitWork, and it's a bit awkward, especially when
refactoring. Idk the ideal module structure, so for now I'd rather keep
it all in one file.

* Traverse commit phase effects iteratively

We suspect that using the JS stack to traverse through the tree in the
commit phase is slower than traversing iteratively.

I've kept the recursive implementation behind a flag, both so we have
the option to run an experiment comparing the two, and so we can revert
it easily later if needed.
2020-10-27 12:02:19 -07:00
Brian Vaughn
c59c3dfe55
useRef: Warn about reading or writing mutable values during render (#18545)
Reading or writing a ref value during render is only safe if you are implementing the lazy initialization pattern.

Other types of reading are unsafe as the ref is a mutable source.

Other types of writing are unsafe as they are effectively side effects.

This change also refactors useTransition to no longer use a ref hook, but instead manage its own (stable) hook state.
2020-10-19 16:05:00 -04:00
Dan Abramov
993ca533b4
Enable eager listeners statically (#19983) 2020-10-08 19:32:28 +01:00
Andrew Clark
ba82eea383
Remove disableSchedulerTimeoutInWorkLoop flag (#19902)
We found and mitigated the root cause of the regression that led us to
temporarily revert this change. So now I'm un-reverting it.
2020-09-28 10:19:14 -07:00
Luna Ruan
c63741fb3d
offscreen double invoke effects (#19523)
This PR double invokes effects in __DEV__ mode.

We are thinking about unmounting layout and/or passive effects for a hidden tree. To understand potential issues with this, we want to double invoke effects. This PR changes the behavior in DEV when an effect runs from create() to create() -> destroy() -> create(). The effect cleanup function will still be called before the effect runs in both dev and prod. (Note: This change is purely for research for now as it is likely to break real code.)

**Note: The change is fully behind a flag and does not affect any of the code on npm.**
2020-09-24 13:42:17 -07:00
Dan Abramov
6fddca27e7
Remove passive intervention flag (#19849) 2020-09-17 15:37:12 +01:00
Ricky
36df483af4
Add feature flag to disable scheduler timeout in work loop (#19771) 2020-09-04 10:58:17 -04:00
Dan Abramov
b754caaaf2
Enable eager listeners in open source (#19716)
* Enable eager listeners in open source

* Fix tests

* Enable in all places
2020-08-28 12:23:28 +01:00
Dan Abramov
848bb2426e
Attach Listeners Eagerly to Roots and Portal Containers (#19659)
* Failing test for #19608

* Attach Listeners Eagerly to Roots and Portal Containers

* Forbid createEventHandle with custom events

We can't support this without adding more complexity. It's not clear that this is even desirable, as none of our existing use cases need custom events. This API primarily exists as a deprecation strategy for Flare, so I don't think it is important to expand its support beyond what Flare replacement code currently needs. We can later revisit it with a better understanding of the eager/lazy tradeoff but for now let's remove the inconsistency.

* Reduce risk by changing condition only under the flag

Co-authored-by: koba04 <koba0004@gmail.com>
2020-08-24 16:50:20 +01:00
Dan Abramov
dd651df05e
Keep onTouchStart, onTouchMove, and onWheel passive (#19654)
* Keep onTouchStart, onTouchMove, and onWheel passive

* Put it behind a feature flag on WWW
2020-08-19 18:42:33 +01:00
Brian Vaughn
bcca5a6ca7
Always skip unmounted/unmounting error boundaries (#19627)
The behavior of error boundaries for passive effects that throw during cleanup was recently changed so that React ignores boundaries which are also unmounting in favor of still-mounted boundaries. This commit implements that same behavior for layout effects (useLayoutEffect, componentWillUnmount, and ref-detachment).

The new, skip-unmounting-boundaries behavior is behind a feature flag (`skipUnmountedBoundaries`).
2020-08-17 15:01:06 -04:00
Brian Vaughn
9b35dd2fcc
Permanently removed component stacks from scheduling profiler data (#19615)
These stacks improve the profiler data but they're expensive to generate and generating them can also cause runtime errors in larger applications (although an exact repro has been hard to nail down). Removing them for now. We can revisit adding them after this profiler has been integrated into the DevTools extension and we can generate them lazily.
2020-08-14 15:21:13 -04:00
Dominic Gannaway
f77c7b9d76
Re-add discrete flushing timeStamp heuristic (behind flag) (#19540) 2020-08-06 13:21:05 +01:00
Dominic Gannaway
b61174fb7b
Remove the deprecated React Flare event system (#19520) 2020-08-05 15:13:29 +01:00
Dan Abramov
332eceface
Revert "Statically enable enableFilterEmptyStringAttributesDOM (#19502)" (#19504)
This reverts commit 815ee89bf5.
2020-07-31 15:01:27 +01:00
Dan Abramov
815ee89bf5
Statically enable enableFilterEmptyStringAttributesDOM (#19502) 2020-07-31 14:57:57 +01:00
Ricky
74cd7e5f17
Use feature flags for React Native in the test renderer (#19486) 2020-07-29 16:31:05 -04:00