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;