diff --git a/packages/react-reconciler/src/ReactFiberRootScheduler.js b/packages/react-reconciler/src/ReactFiberRootScheduler.js index 8e0c65b8552df..a8542d0a0ea06 100644 --- a/packages/react-reconciler/src/ReactFiberRootScheduler.js +++ b/packages/react-reconciler/src/ReactFiberRootScheduler.js @@ -164,9 +164,6 @@ function flushSyncWorkAcrossRoots_impl(onlyLegacy: boolean) { return; } - const workInProgressRoot = getWorkInProgressRoot(); - const workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); - // There may or may not be synchronous work scheduled. Let's check. let didPerformSomeWork; let errors: Array | null = null; @@ -178,6 +175,9 @@ function flushSyncWorkAcrossRoots_impl(onlyLegacy: boolean) { if (onlyLegacy && root.tag !== LegacyRoot) { // Skip non-legacy roots. } else { + const workInProgressRoot = getWorkInProgressRoot(); + const workInProgressRootRenderLanes = + getWorkInProgressRootRenderLanes(); const nextLanes = getNextLanes( root, root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes, @@ -185,10 +185,8 @@ function flushSyncWorkAcrossRoots_impl(onlyLegacy: boolean) { if (includesSyncLane(nextLanes)) { // This root has pending sync work. Flush it now. try { - // TODO: Pass nextLanes as an argument instead of computing it again - // inside performSyncWorkOnRoot. didPerformSomeWork = true; - performSyncWorkOnRoot(root); + performSyncWorkOnRoot(root, nextLanes); } catch (error) { // Collect errors so we can rethrow them at the end if (errors === null) { diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index f0a0d4e228160..f27e3be006f84 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -1273,25 +1273,27 @@ function markRootSuspended(root: FiberRoot, suspendedLanes: Lanes) { // This is the entry point for synchronous tasks that don't go // through Scheduler -export function performSyncWorkOnRoot(root: FiberRoot): null { - if (enableProfilerTimer && enableProfilerNestedUpdatePhase) { - syncNestedUpdateFlag(); - } - +export function performSyncWorkOnRoot(root: FiberRoot, lanes: Lanes): null { if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { throw new Error('Should not already be working.'); } - flushPassiveEffects(); - - // TODO: This was already computed in the caller. Pass it as an argument. - let lanes = getNextLanes(root, NoLanes); - if (!includesSyncLane(lanes)) { - // There's no remaining sync work left. + const didFlushPassiveEffects = flushPassiveEffects(); + if (didFlushPassiveEffects) { + // If passive effects were flushed, exit to the outer work loop in the root + // scheduler, so we can recompute the priority. + // TODO: We don't actually need this `ensureRootIsScheduled` call because + // this path is only reachable if the root is already part of the schedule. + // I'm including it only for consistency with the other exit points from + // this function. Can address in a subsequent refactor. ensureRootIsScheduled(root); return null; } + if (enableProfilerTimer && enableProfilerNestedUpdatePhase) { + syncNestedUpdateFlag(); + } + let exitStatus = renderRootSync(root, lanes); if (root.tag !== LegacyRoot && exitStatus === RootErrored) { // If something threw an error, try rendering one more time. We'll render