@samitouri / QOS-React / commits / e0c421ab71

Include SyncLane in includesBlockingLane helper (#34543)

This helper weirdly doesn't include the sync lane. Everywhere we use it we have to check the sync lane separately. We can simplify things by simply including the sync lane. This fixes a lack of optimization because we should not check the store consistency for a `flushSync` render. https://github.com/facebook/react/blob/d91d28c8ba6fe7c96e651f82fc47c9d5481bf5f9/packages/react-reconciler/src/ReactFiberHooks.js#L1691-L1693

Sebastian Markbåge committed Sep 24, 2025 at 09:34 UTC e0c421ab71e26c05afe506662a4574070c13d131
3 files changed +13 -19
packages/react-reconciler/src/ReactFiberLane.js
+6 -5
@@ -611,10 +611,6 @@ export function includesSyncLane(lanes: Lanes): boolean {
611 return (lanes & (SyncLane | SyncHydrationLane)) !== NoLanes;
612 }
613
614 -export function isSyncLane(lanes: Lanes): boolean {
615 - return (lanes & (SyncLane | SyncHydrationLane)) !== NoLanes;
616 -}
617 -
614 export function includesNonIdleWork(lanes: Lanes): boolean {
615 return (lanes & NonIdleLanes) !== NoLanes;
616 }
@@ -681,6 +677,8 @@ export function includesLoadingIndicatorLanes(lanes: Lanes): boolean {
677
678 export function includesBlockingLane(lanes: Lanes): boolean {
679 const SyncDefaultLanes =
680 + SyncHydrationLane |
681 + SyncLane |
682 InputContinuousHydrationLane |
683 InputContinuousLane |
684 DefaultHydrationLane |
@@ -697,10 +695,13 @@ export function includesExpiredLane(root: FiberRoot, lanes: Lanes): boolean {
695
696 export function isBlockingLane(lane: Lane): boolean {
697 const SyncDefaultLanes =
698 + SyncHydrationLane |
699 + SyncLane |
700 InputContinuousHydrationLane |
701 InputContinuousLane |
702 DefaultHydrationLane |
703 - DefaultLane;
703 + DefaultLane |
704 + GestureLane;
705 return (lane & SyncDefaultLanes) !== NoLanes;
706 }
707
packages/react-reconciler/src/ReactFiberWorkLoop.js
+4 -9
@@ -1898,7 +1898,7 @@ function resetWorkInProgressStack() {
1898
1899 function finalizeRender(lanes: Lanes, finalizationTime: number): void {
1900 if (enableProfilerTimer && enableComponentPerformanceTrack) {
1901 - if (includesSyncLane(lanes) || includesBlockingLane(lanes)) {
1901 + if (includesBlockingLane(lanes)) {
1902 clampBlockingTimers(finalizationTime);
1903 }
1904 if (includesTransitionLane(lanes)) {
@@ -1963,7 +1963,7 @@ function prepareFreshStack(root: FiberRoot, lanes: Lanes): Fiber {
1963 const previousUpdateTask = workInProgressUpdateTask;
1964
1965 workInProgressUpdateTask = null;
1966 - if (includesSyncLane(lanes) || includesBlockingLane(lanes)) {
1966 + if (includesBlockingLane(lanes)) {
1967 workInProgressUpdateTask = blockingUpdateTask;
1968 const clampedUpdateTime =
1969 blockingUpdateTime >= 0 && blockingUpdateTime < blockingClampTime
@@ -1987,10 +1987,7 @@ function prepareFreshStack(root: FiberRoot, lanes: Lanes): Fiber {
1987 lanes,
1988 previousUpdateTask,
1989 );
1990 - } else if (
1991 - includesSyncLane(animatingLanes) ||
1992 - includesBlockingLane(animatingLanes)
1993 - ) {
1990 + } else if (includesBlockingLane(animatingLanes)) {
1991 // If this lane is still animating, log the time from previous render finishing to now as animating.
1992 setCurrentTrackFromLanes(SyncLane);
1993 logAnimatingPhase(
@@ -3719,10 +3716,8 @@ function finishedViewTransition(lanes: Lanes): void {
3716 // If an affected track isn't in the middle of rendering or committing, log from the previous
3717 // finished render until the end of the animation.
3718 if (
3722 - (includesSyncLane(lanes) || includesBlockingLane(lanes)) &&
3723 - !includesSyncLane(workInProgressRootRenderLanes) &&
3719 + includesBlockingLane(lanes) &&
3720 !includesBlockingLane(workInProgressRootRenderLanes) &&
3725 - !includesSyncLane(pendingEffectsLanes) &&
3721 !includesBlockingLane(pendingEffectsLanes)
3722 ) {
3723 setCurrentTrackFromLanes(SyncLane);
packages/react-reconciler/src/ReactProfilerTimer.js
+3 -5
@@ -18,10 +18,8 @@ import type {CapturedValue} from './ReactCapturedValue';
18 import {
19 isTransitionLane,
20 isBlockingLane,
21 - isSyncLane,
21 includesTransitionLane,
22 includesBlockingLane,
24 - includesSyncLane,
23 NoLanes,
24 } from './ReactFiberLane';
25
@@ -114,7 +112,7 @@ export function startUpdateTimerByLane(
112 if (!enableProfilerTimer || !enableComponentPerformanceTrack) {
113 return;
114 }
117 - if (isSyncLane(lane) || isBlockingLane(lane)) {
115 + if (isBlockingLane(lane)) {
116 if (blockingUpdateTime < 0) {
117 blockingUpdateTime = now();
118 blockingUpdateTask = createTask(method);
@@ -220,7 +218,7 @@ export function startPingTimerByLanes(lanes: Lanes): void {
218 // Mark the update time and clamp anything before it because we don't want
219 // to show the event time for pings but we also don't want to clear it
220 // because we still need to track if this was a repeat.
223 - if (includesSyncLane(lanes) || includesBlockingLane(lanes)) {
221 + if (includesBlockingLane(lanes)) {
222 if (blockingUpdateTime < 0) {
223 blockingClampTime = blockingUpdateTime = now();
224 blockingUpdateTask = createTask('Promise Resolved');
@@ -239,7 +237,7 @@ export function trackSuspendedTime(lanes: Lanes, renderEndTime: number) {
237 if (!enableProfilerTimer || !enableComponentPerformanceTrack) {
238 return;
239 }
242 - if (includesSyncLane(lanes) || includesBlockingLane(lanes)) {
240 + if (includesBlockingLane(lanes)) {
241 blockingSuspendedTime = renderEndTime;
242 } else if (includesTransitionLane(lanes)) {
243 transitionSuspendedTime = renderEndTime;