@@ -13,7 +13,6 @@ import type {Lanes, Lane} from './ReactFiberLane.new';
1313import type { ReactPriorityLevel } from './ReactInternalTypes' ;
1414import type { Interaction } from 'scheduler/src/Tracing' ;
1515import type { SuspenseState } from './ReactFiberSuspenseComponent.new' ;
16- import type { Effect as HookEffect } from './ReactFiberHooks.new' ;
1716import type { StackCursor } from './ReactFiberStack.new' ;
1817import type { FunctionComponentUpdateQueue } from './ReactFiberHooks.new' ;
1918
@@ -121,8 +120,16 @@ import {
121120import { LegacyRoot } from './ReactRootTags' ;
122121import {
123122 NoFlags ,
124- PerformedWork ,
125123 Placement ,
124+ PassiveStatic ,
125+ Incomplete ,
126+ HostEffectMask ,
127+ Hydrating ,
128+ BeforeMutationMask ,
129+ MutationMask ,
130+ LayoutMask ,
131+ PassiveMask ,
132+ PerformedWork ,
126133 Update ,
127134 PlacementAndUpdate ,
128135 Deletion ,
@@ -131,11 +138,6 @@ import {
131138 ContentReset ,
132139 Snapshot ,
133140 Callback ,
134- Passive ,
135- PassiveStatic ,
136- Incomplete ,
137- HostEffectMask ,
138- Hydrating ,
139141 HydratingAndUpdate ,
140142 StaticMask ,
141143} from './ReactFiberFlags' ;
@@ -1956,7 +1958,35 @@ function commitRootImpl(root, renderPriorityLevel) {
19561958 firstEffect = finishedWork . firstEffect ;
19571959 }
19581960
1959- if ( firstEffect !== null ) {
1961+ // If there are pending passive effects, schedule a callback to process them.
1962+ // Do this as early as possible, so it is queued before anything else that
1963+ // might get scheduled in the commit phase. (See #16714.)
1964+ if (
1965+ ( finishedWork . subtreeFlags & PassiveMask ) !== NoFlags ||
1966+ ( finishedWork . flags & PassiveMask ) !== NoFlags
1967+ ) {
1968+ rootDoesHavePassiveEffects = true ;
1969+ scheduleCallback ( NormalSchedulerPriority , ( ) => {
1970+ flushPassiveEffects ( ) ;
1971+ return null ;
1972+ } ) ;
1973+ }
1974+
1975+ // Check if there are any effects in the whole tree.
1976+ // TODO: This is left over from the effect list implementation, where we had
1977+ // to check for the existence of `firstEffect` to satsify Flow. I think the
1978+ // only other reason this optimization exists is because it affects profiling.
1979+ // Reconsider whether this is necessary.
1980+ const subtreeHasEffects =
1981+ ( finishedWork . subtreeFlags &
1982+ ( BeforeMutationMask | MutationMask | LayoutMask | PassiveMask ) ) !==
1983+ NoFlags ;
1984+ const rootHasEffect =
1985+ ( finishedWork . flags &
1986+ ( BeforeMutationMask | MutationMask | LayoutMask | PassiveMask ) ) !==
1987+ NoFlags ;
1988+
1989+ if ( subtreeHasEffects || rootHasEffect ) {
19601990 let previousLanePriority ;
19611991 if ( decoupleUpdatePriorityFromScheduler ) {
19621992 previousLanePriority = getCurrentUpdateLanePriority ( ) ;
@@ -2275,17 +2305,6 @@ function commitBeforeMutationEffects() {
22752305
22762306 resetCurrentDebugFiberInDEV ( ) ;
22772307 }
2278- if ( ( flags & Passive ) !== NoFlags ) {
2279- // If there are passive effects, schedule a callback to flush at
2280- // the earliest opportunity.
2281- if ( ! rootDoesHavePassiveEffects ) {
2282- rootDoesHavePassiveEffects = true ;
2283- scheduleCallback ( NormalSchedulerPriority , ( ) => {
2284- flushPassiveEffects ( ) ;
2285- return null ;
2286- } ) ;
2287- }
2288- }
22892308 nextEffect = nextEffect . nextEffect ;
22902309 }
22912310}
@@ -2485,32 +2504,6 @@ export function enqueuePendingPassiveProfilerEffect(fiber: Fiber): void {
24852504 }
24862505}
24872506
2488- export function enqueuePendingPassiveHookEffectMount (
2489- fiber : Fiber ,
2490- effect : HookEffect ,
2491- ) : void {
2492- if ( ! rootDoesHavePassiveEffects ) {
2493- rootDoesHavePassiveEffects = true ;
2494- scheduleCallback ( NormalSchedulerPriority , ( ) => {
2495- flushPassiveEffects ( ) ;
2496- return null ;
2497- } ) ;
2498- }
2499- }
2500-
2501- export function enqueuePendingPassiveHookEffectUnmount (
2502- fiber : Fiber ,
2503- effect : HookEffect ,
2504- ) : void {
2505- if ( ! rootDoesHavePassiveEffects ) {
2506- rootDoesHavePassiveEffects = true ;
2507- scheduleCallback ( NormalSchedulerPriority , ( ) => {
2508- flushPassiveEffects ( ) ;
2509- return null ;
2510- } ) ;
2511- }
2512- }
2513-
25142507function flushPassiveEffectsImpl ( ) {
25152508 if ( rootWithPendingPassiveEffects === null ) {
25162509 return false ;
0 commit comments