Skip to content

Commit b204edd

Browse files
authored
Log Custom Reason for the Suspended Commit Track (#34522)
Stacked on #34511. We currently log all Suspended Commit as "Suspended on Images or CSS" but it can really be other reasons too now. Like waiting on the previous View Transition. This allows the host config configure this reason. Now when one animation starts before another one finishes we log that as "Waiting for the previous Animation". <img width="592" height="257" alt="Screenshot 2025-09-17 at 11 53 45 PM" src="https://github.com/user-attachments/assets/817af8b5-37ae-46d8-bfd1-cd3fc637f3f3" />
1 parent 115e3ec commit b204edd

File tree

10 files changed

+80
-61
lines changed

10 files changed

+80
-61
lines changed

packages/react-art/src/ReactFiberConfigART.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,10 @@ export function waitForCommitToBeReady(timeoutOffset) {
621621
return null;
622622
}
623623

624+
export function getSuspendedCommitReason(state, rootContainer) {
625+
return null;
626+
}
627+
624628
export const NotPendingTransition = null;
625629
export const HostTransitionContext: ReactContext<TransitionStatus> = {
626630
$$typeof: REACT_CONTEXT_TYPE,

packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5965,6 +5965,7 @@ export opaque type SuspendedState = {
59655965
imgBytes: number, // number of bytes we estimate needing to download
59665966
suspenseyImages: Array<HTMLImageElement>, // instances of suspensey images (whether loaded or not)
59675967
waitingForImages: boolean, // false when we're no longer blocking on images
5968+
waitingForViewTransition: boolean,
59685969
unsuspend: null | (() => void),
59695970
};
59705971

@@ -5976,6 +5977,7 @@ export function startSuspendingCommit(): SuspendedState {
59765977
imgBytes: 0,
59775978
suspenseyImages: [],
59785979
waitingForImages: true,
5980+
waitingForViewTransition: false,
59795981
// We use a noop function when we begin suspending because if possible we want the
59805982
// waitfor step to finish synchronously. If it doesn't we'll return a function to
59815983
// provide the actual unsuspend function and that will get completed when the count
@@ -6123,6 +6125,7 @@ export function suspendOnActiveViewTransition(
61236125
return;
61246126
}
61256127
state.count++;
6128+
state.waitingForViewTransition = true;
61266129
const ping = onUnsuspend.bind(state);
61276130
activeViewTransition.finished.then(ping, ping);
61286131
}
@@ -6206,6 +6209,28 @@ export function waitForCommitToBeReady(
62066209
return null;
62076210
}
62086211

6212+
export function getSuspendedCommitReason(
6213+
state: SuspendedState,
6214+
rootContainer: Container,
6215+
): null | string {
6216+
if (state.waitingForViewTransition) {
6217+
return 'Waiting for the previous Animation';
6218+
}
6219+
if (state.count > 0) {
6220+
if (state.imgCount > 0) {
6221+
return 'Suspended on CSS and Images';
6222+
}
6223+
return 'Suspended on CSS';
6224+
}
6225+
if (state.imgCount === 1) {
6226+
return 'Suspended on an Image';
6227+
}
6228+
if (state.imgCount > 0) {
6229+
return 'Suspended on Images';
6230+
}
6231+
return null;
6232+
}
6233+
62096234
function checkIfFullyUnsuspended(state: SuspendedState) {
62106235
if (state.count === 0 && (state.imgCount === 0 || !state.waitingForImages)) {
62116236
if (state.stylesheets) {

packages/react-native-renderer/src/ReactFiberConfigFabric.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,13 @@ export function waitForCommitToBeReady(
627627
return null;
628628
}
629629

630+
export function getSuspendedCommitReason(
631+
state: SuspendedState,
632+
rootContainer: Container,
633+
): null | string {
634+
return null;
635+
}
636+
630637
export type FragmentInstanceType = {
631638
_fragmentFiber: Fiber,
632639
_observers: null | Set<IntersectionObserver>,

packages/react-native-renderer/src/ReactFiberConfigNative.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,13 @@ export function waitForCommitToBeReady(
806806
return null;
807807
}
808808

809+
export function getSuspendedCommitReason(
810+
state: SuspendedState,
811+
rootContainer: Container,
812+
): null | string {
813+
return null;
814+
}
815+
809816
export const NotPendingTransition: TransitionStatus = null;
810817
export const HostTransitionContext: ReactContext<TransitionStatus> = {
811818
$$typeof: REACT_CONTEXT_TYPE,

packages/react-noop-renderer/src/createReactNoop.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,13 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
702702

703703
waitForCommitToBeReady,
704704

705+
getSuspendedCommitReason(
706+
state: SuspendedState,
707+
rootContainer: Container,
708+
): null | string {
709+
return null;
710+
},
711+
705712
NotPendingTransition: (null: TransitionStatus),
706713

707714
resetFormInstance(form: Instance) {},

packages/react-reconciler/src/ReactFiberPerformanceTrack.js

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,45 +1180,10 @@ export function logInconsistentRender(
11801180
}
11811181
}
11821182

1183-
export function logSuspenseThrottlePhase(
1184-
startTime: number,
1185-
endTime: number,
1186-
debugTask: null | ConsoleTask,
1187-
): void {
1188-
// This was inside a throttled Suspense boundary commit.
1189-
if (supportsUserTiming) {
1190-
if (endTime <= startTime) {
1191-
return;
1192-
}
1193-
if (__DEV__ && debugTask) {
1194-
debugTask.run(
1195-
// $FlowFixMe[method-unbinding]
1196-
console.timeStamp.bind(
1197-
console,
1198-
'Throttled',
1199-
startTime,
1200-
endTime,
1201-
currentTrack,
1202-
LANES_TRACK_GROUP,
1203-
'secondary-light',
1204-
),
1205-
);
1206-
} else {
1207-
console.timeStamp(
1208-
'Throttled',
1209-
startTime,
1210-
endTime,
1211-
currentTrack,
1212-
LANES_TRACK_GROUP,
1213-
'secondary-light',
1214-
);
1215-
}
1216-
}
1217-
}
1218-
12191183
export function logSuspendedCommitPhase(
12201184
startTime: number,
12211185
endTime: number,
1186+
reason: string,
12221187
debugTask: null | ConsoleTask,
12231188
): void {
12241189
// This means the commit was suspended on CSS or images.
@@ -1233,7 +1198,7 @@ export function logSuspendedCommitPhase(
12331198
// $FlowFixMe[method-unbinding]
12341199
console.timeStamp.bind(
12351200
console,
1236-
'Suspended on CSS or Images',
1201+
reason,
12371202
startTime,
12381203
endTime,
12391204
currentTrack,
@@ -1243,7 +1208,7 @@ export function logSuspendedCommitPhase(
12431208
);
12441209
} else {
12451210
console.timeStamp(
1246-
'Suspended on CSS or Images',
1211+
reason,
12471212
startTime,
12481213
endTime,
12491214
currentTrack,

packages/react-reconciler/src/ReactFiberWorkLoop.js

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ import {
7979
logErroredRenderPhase,
8080
logInconsistentRender,
8181
logSuspendedWithDelayPhase,
82-
logSuspenseThrottlePhase,
8382
logSuspendedCommitPhase,
8483
logSuspendedViewTransitionPhase,
8584
logCommitPhase,
@@ -103,6 +102,7 @@ import {
103102
startSuspendingCommit,
104103
suspendOnActiveViewTransition,
105104
waitForCommitToBeReady,
105+
getSuspendedCommitReason,
106106
preloadInstance,
107107
preloadResource,
108108
supportsHydration,
@@ -672,12 +672,10 @@ export function getRenderTargetTime(): number {
672672

673673
let legacyErrorBoundariesThatAlreadyFailed: Set<mixed> | null = null;
674674

675-
type SuspendedCommitReason = 0 | 1 | 2;
676-
const IMMEDIATE_COMMIT = 0;
677-
const SUSPENDED_COMMIT = 1;
678-
const THROTTLED_COMMIT = 2;
675+
type SuspendedCommitReason = null | string;
679676

680677
type DelayedCommitReason = 0 | 1 | 2 | 3;
678+
const IMMEDIATE_COMMIT = 0;
681679
const ABORTED_VIEW_TRANSITION_COMMIT = 1;
682680
const DELAYED_PASSIVE_COMMIT = 2;
683681
const ANIMATION_STARTED_COMMIT = 3;
@@ -703,7 +701,7 @@ let pendingViewTransitionEvents: Array<(types: Array<string>) => void> | null =
703701
null;
704702
let pendingTransitionTypes: null | TransitionTypes = null;
705703
let pendingDidIncludeRenderPhaseUpdate: boolean = false;
706-
let pendingSuspendedCommitReason: SuspendedCommitReason = IMMEDIATE_COMMIT; // Profiling-only
704+
let pendingSuspendedCommitReason: SuspendedCommitReason = null; // Profiling-only
707705
let pendingDelayedCommitReason: DelayedCommitReason = IMMEDIATE_COMMIT; // Profiling-only
708706
let pendingSuspendedViewTransitionReason: null | string = null; // Profiling-only
709707

@@ -1391,7 +1389,7 @@ function finishConcurrentRender(
13911389
workInProgressSuspendedRetryLanes,
13921390
exitStatus,
13931391
null,
1394-
IMMEDIATE_COMMIT,
1392+
null,
13951393
renderStartTime,
13961394
renderEndTime,
13971395
);
@@ -1442,7 +1440,7 @@ function finishConcurrentRender(
14421440
workInProgressSuspendedRetryLanes,
14431441
workInProgressRootDidSkipSuspendedSiblings,
14441442
exitStatus,
1445-
THROTTLED_COMMIT,
1443+
'Throttled',
14461444
renderStartTime,
14471445
renderEndTime,
14481446
),
@@ -1463,7 +1461,7 @@ function finishConcurrentRender(
14631461
workInProgressSuspendedRetryLanes,
14641462
workInProgressRootDidSkipSuspendedSiblings,
14651463
exitStatus,
1466-
IMMEDIATE_COMMIT,
1464+
null,
14671465
renderStartTime,
14681466
renderEndTime,
14691467
);
@@ -1555,7 +1553,9 @@ function commitRootWhenReady(
15551553
suspendedRetryLanes,
15561554
exitStatus,
15571555
suspendedState,
1558-
SUSPENDED_COMMIT,
1556+
enableProfilerTimer
1557+
? getSuspendedCommitReason(suspendedState, root.containerInfo)
1558+
: null,
15591559
completedRenderStartTime,
15601560
completedRenderEndTime,
15611561
),
@@ -3458,7 +3458,7 @@ function commitRoot(
34583458
recoverableErrors,
34593459
suspendedState,
34603460
enableProfilerTimer
3461-
? suspendedCommitReason === IMMEDIATE_COMMIT
3461+
? suspendedCommitReason === null
34623462
? completedRenderEndTime
34633463
: commitStartTime
34643464
: 0,
@@ -3530,16 +3530,11 @@ function commitRoot(
35303530
resetCommitErrors();
35313531
recordCommitTime();
35323532
if (enableComponentPerformanceTrack) {
3533-
if (suspendedCommitReason === SUSPENDED_COMMIT) {
3533+
if (suspendedCommitReason !== null) {
35343534
logSuspendedCommitPhase(
35353535
completedRenderEndTime,
35363536
commitStartTime,
3537-
workInProgressUpdateTask,
3538-
);
3539-
} else if (suspendedCommitReason === THROTTLED_COMMIT) {
3540-
logSuspenseThrottlePhase(
3541-
completedRenderEndTime,
3542-
commitStartTime,
3537+
suspendedCommitReason,
35433538
workInProgressUpdateTask,
35443539
);
35453540
}
@@ -3633,7 +3628,7 @@ function suspendedViewTransition(reason: string): void {
36333628
// We'll split the commit into two phases, because we're suspended in the middle.
36343629
recordCommitEndTime();
36353630
logCommitPhase(
3636-
pendingSuspendedCommitReason === IMMEDIATE_COMMIT
3631+
pendingSuspendedCommitReason === null
36373632
? pendingEffectsRenderEndTime
36383633
: commitStartTime,
36393634
commitEndTime,
@@ -3642,7 +3637,7 @@ function suspendedViewTransition(reason: string): void {
36423637
workInProgressUpdateTask,
36433638
);
36443639
pendingSuspendedViewTransitionReason = reason;
3645-
pendingSuspendedCommitReason = SUSPENDED_COMMIT;
3640+
pendingSuspendedCommitReason = reason;
36463641
}
36473642
}
36483643

@@ -3792,9 +3787,7 @@ function flushLayoutEffects(): void {
37923787
if (enableProfilerTimer && enableComponentPerformanceTrack) {
37933788
recordCommitEndTime();
37943789
logCommitPhase(
3795-
suspendedCommitReason === IMMEDIATE_COMMIT
3796-
? completedRenderEndTime
3797-
: commitStartTime,
3790+
suspendedCommitReason === null ? completedRenderEndTime : commitStartTime,
37983791
commitEndTime,
37993792
commitErrors,
38003793
pendingDelayedCommitReason === ABORTED_VIEW_TRANSITION_COMMIT,

packages/react-reconciler/src/__tests__/ReactFiberHostContext-test.internal.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ describe('ReactFiberHostContext', () => {
114114
waitForCommitToBeReady(state, timeoutOffset) {
115115
return null;
116116
},
117+
getSuspendedCommitReason(state, rootContainer) {
118+
return null;
119+
},
117120
supportsMutation: true,
118121
});
119122

packages/react-reconciler/src/forks/ReactFiberConfig.custom.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ export const suspendInstance = $$$config.suspendInstance;
9999
export const suspendOnActiveViewTransition =
100100
$$$config.suspendOnActiveViewTransition;
101101
export const waitForCommitToBeReady = $$$config.waitForCommitToBeReady;
102+
export const getSuspendedCommitReason = $$$config.getSuspendedCommitReason;
102103
export const NotPendingTransition = $$$config.NotPendingTransition;
103104
export const HostTransitionContext = $$$config.HostTransitionContext;
104105
export const resetFormInstance = $$$config.resetFormInstance;

packages/react-test-renderer/src/ReactFiberConfigTestHost.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,13 @@ export function waitForCommitToBeReady(
589589
return null;
590590
}
591591

592+
export function getSuspendedCommitReason(
593+
state: SuspendedState,
594+
rootContainer: Container,
595+
): null | string {
596+
return null;
597+
}
598+
592599
export const NotPendingTransition: TransitionStatus = null;
593600
export const HostTransitionContext: ReactContext<TransitionStatus> = {
594601
$$typeof: REACT_CONTEXT_TYPE,

0 commit comments

Comments
 (0)