Skip to content

Commit a1c633b

Browse files
committed
Log suspended in startViewTransition phase
1 parent 7cc3919 commit a1c633b

File tree

5 files changed

+90
-1
lines changed

5 files changed

+90
-1
lines changed

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ import {
125125
enableViewTransition,
126126
enableHydrationChangeEvent,
127127
enableFragmentRefsScrollIntoView,
128+
enableProfilerTimer,
128129
} from 'shared/ReactFeatureFlags';
129130
import {
130131
HostComponent,
@@ -2098,6 +2099,7 @@ export function startViewTransition(
20982099
spawnedWorkCallback: () => void,
20992100
passiveCallback: () => mixed,
21002101
errorCallback: mixed => void,
2102+
blockedCallback: string => void, // Profiling-only
21012103
): null | RunningViewTransition {
21022104
const ownerDocument: Document =
21032105
rootContainer.nodeType === DOCUMENT_NODE
@@ -2131,10 +2133,10 @@ export function startViewTransition(
21312133
blockingPromises.push(ownerDocument.fonts.ready);
21322134
}
21332135
}
2136+
const blockingIndexSnapshot = blockingPromises.length;
21342137
if (suspendedState !== null) {
21352138
// Suspend on any images that still haven't loaded and are in the viewport.
21362139
const suspenseyImages = suspendedState.suspenseyImages;
2137-
const blockingIndexSnapshot = blockingPromises.length;
21382140
let imgBytes = 0;
21392141
for (let i = 0; i < suspenseyImages.length; i++) {
21402142
const suspenseyImage = suspenseyImages[i];
@@ -2162,6 +2164,15 @@ export function startViewTransition(
21622164
}
21632165
}
21642166
if (blockingPromises.length > 0) {
2167+
if (enableProfilerTimer) {
2168+
const blockedReason =
2169+
blockingIndexSnapshot > 0
2170+
? blockingPromises.length > blockingIndexSnapshot
2171+
? 'Waiting on Fonts and Images'
2172+
: 'Waiting on Fonts'
2173+
: 'Waiting on Images';
2174+
blockedCallback(blockedReason);
2175+
}
21652176
const blockingReady = Promise.race([
21662177
Promise.all(blockingPromises),
21672178
new Promise(resolve =>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,7 @@ export function startViewTransition(
673673
spawnedWorkCallback: () => void,
674674
passiveCallback: () => mixed,
675675
errorCallback: mixed => void,
676+
blockedCallback: string => void, // Profiling-only
676677
): null | RunningViewTransition {
677678
mutationCallback();
678679
layoutCallback();

packages/react-reconciler/src/ReactFiberPerformanceTrack.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,6 +1254,45 @@ export function logSuspendedCommitPhase(
12541254
}
12551255
}
12561256

1257+
export function logSuspendedViewTransitionPhase(
1258+
startTime: number,
1259+
endTime: number,
1260+
reason: string,
1261+
debugTask: null | ConsoleTask,
1262+
): void {
1263+
// This means the commit was suspended on CSS or images.
1264+
if (supportsUserTiming) {
1265+
if (endTime <= startTime) {
1266+
return;
1267+
}
1268+
// TODO: Include the exact reason and URLs of what resources suspended.
1269+
// TODO: This might also be Suspended while waiting on a View Transition.
1270+
if (__DEV__ && debugTask) {
1271+
debugTask.run(
1272+
// $FlowFixMe[method-unbinding]
1273+
console.timeStamp.bind(
1274+
console,
1275+
reason,
1276+
startTime,
1277+
endTime,
1278+
currentTrack,
1279+
LANES_TRACK_GROUP,
1280+
'secondary-light',
1281+
),
1282+
);
1283+
} else {
1284+
console.timeStamp(
1285+
reason,
1286+
startTime,
1287+
endTime,
1288+
currentTrack,
1289+
LANES_TRACK_GROUP,
1290+
'secondary-light',
1291+
);
1292+
}
1293+
}
1294+
}
1295+
12571296
export function logCommitErrored(
12581297
startTime: number,
12591298
endTime: number,

packages/react-reconciler/src/ReactFiberWorkLoop.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ import {
8181
logSuspendedWithDelayPhase,
8282
logSuspenseThrottlePhase,
8383
logSuspendedCommitPhase,
84+
logSuspendedViewTransitionPhase,
8485
logCommitPhase,
8586
logPaintYieldPhase,
8687
logStartViewTransitionYieldPhase,
@@ -704,6 +705,7 @@ let pendingTransitionTypes: null | TransitionTypes = null;
704705
let pendingDidIncludeRenderPhaseUpdate: boolean = false;
705706
let pendingSuspendedCommitReason: SuspendedCommitReason = IMMEDIATE_COMMIT; // Profiling-only
706707
let pendingDelayedCommitReason: DelayedCommitReason = IMMEDIATE_COMMIT; // Profiling-only
708+
let pendingSuspendedViewTransitionReason: null | string = null; // Profiling-only
707709

708710
// Use these to prevent an infinite loop of nested updates
709711
const NESTED_UPDATE_LIMIT = 50;
@@ -3445,6 +3447,7 @@ function commitRoot(
34453447
pendingEffectsRenderEndTime = completedRenderEndTime;
34463448
pendingSuspendedCommitReason = suspendedCommitReason;
34473449
pendingDelayedCommitReason = IMMEDIATE_COMMIT;
3450+
pendingSuspendedViewTransitionReason = null;
34483451
}
34493452

34503453
if (enableGestureTransition && isGestureRender(lanes)) {
@@ -3604,6 +3607,7 @@ function commitRoot(
36043607
flushSpawnedWork,
36053608
flushPassiveEffects,
36063609
reportViewTransitionError,
3610+
enableProfilerTimer ? suspendedViewTransition : (null: any),
36073611
);
36083612
} else {
36093613
// Flush synchronously.
@@ -3624,6 +3628,24 @@ function reportViewTransitionError(error: mixed) {
36243628
onRecoverableError(error, makeErrorInfo(null));
36253629
}
36263630

3631+
function suspendedViewTransition(reason: string): void {
3632+
if (enableProfilerTimer && enableComponentPerformanceTrack) {
3633+
// We'll split the commit into two phases, because we're suspended in the middle.
3634+
recordCommitEndTime();
3635+
logCommitPhase(
3636+
pendingSuspendedCommitReason === IMMEDIATE_COMMIT
3637+
? pendingEffectsRenderEndTime
3638+
: commitStartTime,
3639+
commitEndTime,
3640+
commitErrors,
3641+
pendingDelayedCommitReason === ABORTED_VIEW_TRANSITION_COMMIT,
3642+
workInProgressUpdateTask,
3643+
);
3644+
pendingSuspendedViewTransitionReason = reason;
3645+
pendingSuspendedCommitReason = SUSPENDED_COMMIT;
3646+
}
3647+
}
3648+
36273649
function flushAfterMutationEffects(): void {
36283650
if (pendingEffectsStatus !== PENDING_AFTER_MUTATION_PHASE) {
36293651
return;
@@ -3688,6 +3710,21 @@ function flushLayoutEffects(): void {
36883710
}
36893711
pendingEffectsStatus = NO_PENDING_EFFECTS;
36903712

3713+
if (enableProfilerTimer && enableComponentPerformanceTrack) {
3714+
const suspendedViewTransitionReason = pendingSuspendedViewTransitionReason;
3715+
if (suspendedViewTransitionReason !== null) {
3716+
// We suspended in the middle of the commit for the view transition.
3717+
// We'll start a new commit track now.
3718+
recordCommitTime();
3719+
logSuspendedViewTransitionPhase(
3720+
commitEndTime, // The start is the end of the first commit part.
3721+
commitStartTime, // The end is the start of the second commit part.
3722+
suspendedViewTransitionReason,
3723+
workInProgressUpdateTask,
3724+
);
3725+
}
3726+
}
3727+
36913728
const root = pendingEffectsRoot;
36923729
const finishedWork = pendingFinishedWork;
36933730
const lanes = pendingEffectsLanes;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ export function startViewTransition(
423423
spawnedWorkCallback: () => void,
424424
passiveCallback: () => mixed,
425425
errorCallback: mixed => void,
426+
blockedCallback: string => void, // Profiling-only
426427
): null | RunningViewTransition {
427428
mutationCallback();
428429
layoutCallback();

0 commit comments

Comments
 (0)