@@ -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
@@ -122,8 +121,16 @@ import {
122121import { LegacyRoot } from './ReactRootTags' ;
123122import {
124123 NoFlags ,
125- PerformedWork ,
126124 Placement ,
125+ PassiveStatic ,
126+ Incomplete ,
127+ HostEffectMask ,
128+ Hydrating ,
129+ BeforeMutationMask ,
130+ MutationMask ,
131+ LayoutMask ,
132+ PassiveMask ,
133+ PerformedWork ,
127134 Update ,
128135 PlacementAndUpdate ,
129136 Deletion ,
@@ -132,11 +139,6 @@ import {
132139 ContentReset ,
133140 Snapshot ,
134141 Callback ,
135- Passive ,
136- PassiveStatic ,
137- Incomplete ,
138- HostEffectMask ,
139- Hydrating ,
140142 HydratingAndUpdate ,
141143 StaticMask ,
142144} from './ReactFiberFlags' ;
@@ -1969,7 +1971,35 @@ function commitRootImpl(root, renderPriorityLevel) {
19691971 firstEffect = finishedWork . firstEffect ;
19701972 }
19711973
1972- if ( firstEffect !== null ) {
1974+ // If there are pending passive effects, schedule a callback to process them.
1975+ // Do this as early as possible, so it is queued before anything else that
1976+ // might get scheduled in the commit phase. (See #16714.)
1977+ if (
1978+ ( finishedWork . subtreeFlags & PassiveMask ) !== NoFlags ||
1979+ ( finishedWork . flags & PassiveMask ) !== NoFlags
1980+ ) {
1981+ rootDoesHavePassiveEffects = true ;
1982+ scheduleCallback ( NormalSchedulerPriority , ( ) => {
1983+ flushPassiveEffects ( ) ;
1984+ return null ;
1985+ } ) ;
1986+ }
1987+
1988+ // Check if there are any effects in the whole tree.
1989+ // TODO: This is left over from the effect list implementation, where we had
1990+ // to check for the existence of `firstEffect` to satsify Flow. I think the
1991+ // only other reason this optimization exists is because it affects profiling.
1992+ // Reconsider whether this is necessary.
1993+ const subtreeHasEffects =
1994+ ( finishedWork . subtreeFlags &
1995+ ( BeforeMutationMask | MutationMask | LayoutMask | PassiveMask ) ) !==
1996+ NoFlags ;
1997+ const rootHasEffect =
1998+ ( finishedWork . flags &
1999+ ( BeforeMutationMask | MutationMask | LayoutMask | PassiveMask ) ) !==
2000+ NoFlags ;
2001+
2002+ if ( subtreeHasEffects || rootHasEffect ) {
19732003 let previousLanePriority ;
19742004 if ( decoupleUpdatePriorityFromScheduler ) {
19752005 previousLanePriority = getCurrentUpdateLanePriority ( ) ;
@@ -2288,17 +2318,6 @@ function commitBeforeMutationEffects() {
22882318
22892319 resetCurrentDebugFiberInDEV ( ) ;
22902320 }
2291- if ( ( flags & Passive ) !== NoFlags ) {
2292- // If there are passive effects, schedule a callback to flush at
2293- // the earliest opportunity.
2294- if ( ! rootDoesHavePassiveEffects ) {
2295- rootDoesHavePassiveEffects = true ;
2296- scheduleCallback ( NormalSchedulerPriority , ( ) => {
2297- flushPassiveEffects ( ) ;
2298- return null ;
2299- } ) ;
2300- }
2301- }
23022321 nextEffect = nextEffect . nextEffect ;
23032322 }
23042323}
@@ -2498,32 +2517,6 @@ export function enqueuePendingPassiveProfilerEffect(fiber: Fiber): void {
24982517 }
24992518}
25002519
2501- export function enqueuePendingPassiveHookEffectMount (
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-
2514- export function enqueuePendingPassiveHookEffectUnmount (
2515- fiber : Fiber ,
2516- effect : HookEffect ,
2517- ) : void {
2518- if ( ! rootDoesHavePassiveEffects ) {
2519- rootDoesHavePassiveEffects = true ;
2520- scheduleCallback ( NormalSchedulerPriority , ( ) => {
2521- flushPassiveEffects ( ) ;
2522- return null ;
2523- } ) ;
2524- }
2525- }
2526-
25272520function flushPassiveEffectsImpl ( ) {
25282521 if ( rootWithPendingPassiveEffects === null ) {
25292522 return false ;
0 commit comments