Skip to content

Commit 80208e7

Browse files
authored
[Transition Tracing] Add onTransitionProgress Callback (#24833)
This PR adds support for `onTransitionProgress` (`onTransitionProgress(transitionName: string, startTime: number, currentTime: number, pending: Array<{name: null | string}>)`) We call this callback when: * When **a child suspense boundary of the transition commits in a fallback state**. Only the suspense boundaries that are triggered and commit in a fallback state when the transition first occurs (and all subsequent suspense boundaries in the initial suspense boundary's subtree) are considered a part of the transition * **A child suspense boundary of the transition resolves** When we call `onTransitionProgress`, we call the function with a `pending` array. This array contains the names of the transition's suspense boundaries that are still in a fallback state
1 parent 30eb267 commit 80208e7

8 files changed

+498
-51
lines changed

packages/react-reconciler/src/ReactFiberCommitWork.new.js

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ import {
143143
enqueuePendingPassiveProfilerEffect,
144144
restorePendingUpdaters,
145145
addTransitionStartCallbackToPendingTransition,
146+
addTransitionProgressCallbackToPendingTransition,
146147
addTransitionCompleteCallbackToPendingTransition,
147148
addMarkerCompleteCallbackToPendingTransition,
148149
setIsRunningInsertionEffect,
@@ -1119,20 +1120,46 @@ function commitTransitionProgress(offscreenFiber: Fiber) {
11191120
// The suspense boundaries was just hidden. Add the boundary
11201121
// to the pending boundary set if it's there
11211122
if (pendingMarkers !== null) {
1122-
pendingMarkers.forEach(pendingBoundaries => {
1123-
pendingBoundaries.set(offscreenInstance, {
1124-
name,
1125-
});
1123+
pendingMarkers.forEach(markerInstance => {
1124+
const pendingBoundaries = markerInstance.pendingSuspenseBoundaries;
1125+
if (
1126+
pendingBoundaries !== null &&
1127+
!pendingBoundaries.has(offscreenInstance)
1128+
) {
1129+
pendingBoundaries.set(offscreenInstance, {
1130+
name,
1131+
});
1132+
if (markerInstance.transitions !== null) {
1133+
markerInstance.transitions.forEach(transition => {
1134+
addTransitionProgressCallbackToPendingTransition(
1135+
transition,
1136+
pendingBoundaries,
1137+
);
1138+
});
1139+
}
1140+
}
11261141
});
11271142
}
11281143
} else if (wasHidden && !isHidden) {
11291144
// The suspense boundary went from hidden to visible. Remove
11301145
// the boundary from the pending suspense boundaries set
11311146
// if it's there
11321147
if (pendingMarkers !== null) {
1133-
pendingMarkers.forEach(pendingBoundaries => {
1134-
if (pendingBoundaries.has(offscreenInstance)) {
1148+
pendingMarkers.forEach(markerInstance => {
1149+
const pendingBoundaries = markerInstance.pendingSuspenseBoundaries;
1150+
if (
1151+
pendingBoundaries !== null &&
1152+
pendingBoundaries.has(offscreenInstance)
1153+
) {
11351154
pendingBoundaries.delete(offscreenInstance);
1155+
if (markerInstance.transitions !== null) {
1156+
markerInstance.transitions.forEach(transition => {
1157+
addTransitionProgressCallbackToPendingTransition(
1158+
transition,
1159+
pendingBoundaries,
1160+
);
1161+
});
1162+
}
11361163
}
11371164
});
11381165
}
@@ -2888,17 +2915,13 @@ function commitPassiveMountOnFiber(
28882915
clearTransitionsForLanes(finishedRoot, committedLanes);
28892916
}
28902917

2891-
incompleteTransitions.forEach(
2892-
({pendingSuspenseBoundaries}, transition) => {
2893-
if (
2894-
pendingSuspenseBoundaries === null ||
2895-
pendingSuspenseBoundaries.size === 0
2896-
) {
2897-
addTransitionCompleteCallbackToPendingTransition(transition);
2898-
incompleteTransitions.delete(transition);
2899-
}
2900-
},
2901-
);
2918+
incompleteTransitions.forEach((markerInstance, transition) => {
2919+
const pendingBoundaries = markerInstance.pendingSuspenseBoundaries;
2920+
if (pendingBoundaries === null || pendingBoundaries.size === 0) {
2921+
addTransitionCompleteCallbackToPendingTransition(transition);
2922+
incompleteTransitions.delete(transition);
2923+
}
2924+
});
29022925

29032926
clearTransitionsForLanes(finishedRoot, committedLanes);
29042927
}
@@ -2975,9 +2998,7 @@ function commitPassiveMountOnFiber(
29752998
instance.pendingMarkers = new Set();
29762999
}
29773000

2978-
instance.pendingMarkers.add(
2979-
markerInstance.pendingSuspenseBoundaries,
2980-
);
3001+
instance.pendingMarkers.add(markerInstance);
29813002
}
29823003
});
29833004
}

packages/react-reconciler/src/ReactFiberCommitWork.old.js

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ import {
143143
enqueuePendingPassiveProfilerEffect,
144144
restorePendingUpdaters,
145145
addTransitionStartCallbackToPendingTransition,
146+
addTransitionProgressCallbackToPendingTransition,
146147
addTransitionCompleteCallbackToPendingTransition,
147148
addMarkerCompleteCallbackToPendingTransition,
148149
setIsRunningInsertionEffect,
@@ -1119,20 +1120,46 @@ function commitTransitionProgress(offscreenFiber: Fiber) {
11191120
// The suspense boundaries was just hidden. Add the boundary
11201121
// to the pending boundary set if it's there
11211122
if (pendingMarkers !== null) {
1122-
pendingMarkers.forEach(pendingBoundaries => {
1123-
pendingBoundaries.set(offscreenInstance, {
1124-
name,
1125-
});
1123+
pendingMarkers.forEach(markerInstance => {
1124+
const pendingBoundaries = markerInstance.pendingSuspenseBoundaries;
1125+
if (
1126+
pendingBoundaries !== null &&
1127+
!pendingBoundaries.has(offscreenInstance)
1128+
) {
1129+
pendingBoundaries.set(offscreenInstance, {
1130+
name,
1131+
});
1132+
if (markerInstance.transitions !== null) {
1133+
markerInstance.transitions.forEach(transition => {
1134+
addTransitionProgressCallbackToPendingTransition(
1135+
transition,
1136+
pendingBoundaries,
1137+
);
1138+
});
1139+
}
1140+
}
11261141
});
11271142
}
11281143
} else if (wasHidden && !isHidden) {
11291144
// The suspense boundary went from hidden to visible. Remove
11301145
// the boundary from the pending suspense boundaries set
11311146
// if it's there
11321147
if (pendingMarkers !== null) {
1133-
pendingMarkers.forEach(pendingBoundaries => {
1134-
if (pendingBoundaries.has(offscreenInstance)) {
1148+
pendingMarkers.forEach(markerInstance => {
1149+
const pendingBoundaries = markerInstance.pendingSuspenseBoundaries;
1150+
if (
1151+
pendingBoundaries !== null &&
1152+
pendingBoundaries.has(offscreenInstance)
1153+
) {
11351154
pendingBoundaries.delete(offscreenInstance);
1155+
if (markerInstance.transitions !== null) {
1156+
markerInstance.transitions.forEach(transition => {
1157+
addTransitionProgressCallbackToPendingTransition(
1158+
transition,
1159+
pendingBoundaries,
1160+
);
1161+
});
1162+
}
11361163
}
11371164
});
11381165
}
@@ -2888,17 +2915,13 @@ function commitPassiveMountOnFiber(
28882915
clearTransitionsForLanes(finishedRoot, committedLanes);
28892916
}
28902917

2891-
incompleteTransitions.forEach(
2892-
({pendingSuspenseBoundaries}, transition) => {
2893-
if (
2894-
pendingSuspenseBoundaries === null ||
2895-
pendingSuspenseBoundaries.size === 0
2896-
) {
2897-
addTransitionCompleteCallbackToPendingTransition(transition);
2898-
incompleteTransitions.delete(transition);
2899-
}
2900-
},
2901-
);
2918+
incompleteTransitions.forEach((markerInstance, transition) => {
2919+
const pendingBoundaries = markerInstance.pendingSuspenseBoundaries;
2920+
if (pendingBoundaries === null || pendingBoundaries.size === 0) {
2921+
addTransitionCompleteCallbackToPendingTransition(transition);
2922+
incompleteTransitions.delete(transition);
2923+
}
2924+
});
29022925

29032926
clearTransitionsForLanes(finishedRoot, committedLanes);
29042927
}
@@ -2975,9 +2998,7 @@ function commitPassiveMountOnFiber(
29752998
instance.pendingMarkers = new Set();
29762999
}
29773000

2978-
instance.pendingMarkers.add(
2979-
markerInstance.pendingSuspenseBoundaries,
2980-
);
3001+
instance.pendingMarkers.add(markerInstance);
29813002
}
29823003
});
29833004
}

packages/react-reconciler/src/ReactFiberOffscreenComponent.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import type {Lanes} from './ReactFiberLane.old';
1212
import type {SpawnedCachePool} from './ReactFiberCacheComponent.new';
1313
import type {
1414
Transition,
15-
PendingSuspenseBoundaries,
1615
TracingMarkerInstance,
1716
} from './ReactFiberTracingMarkerComponent.new';
1817

@@ -45,7 +44,7 @@ export type OffscreenQueue = {|
4544

4645
export type OffscreenInstance = {|
4746
isHidden: boolean,
48-
pendingMarkers: Set<PendingSuspenseBoundaries> | null,
47+
pendingMarkers: Set<TracingMarkerInstance> | null,
4948
transitions: Set<Transition> | null,
5049
retryCache: WeakSet<Wakeable> | Set<Wakeable> | null,
5150
|};

packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export type MarkerTransition = {
2424

2525
export type PendingTransitionCallbacks = {
2626
transitionStart: Array<Transition> | null,
27+
transitionProgress: Map<Transition, PendingSuspenseBoundaries> | null,
2728
transitionComplete: Array<Transition> | null,
2829
markerComplete: Array<MarkerTransition> | null,
2930
};
@@ -76,6 +77,19 @@ export function processTransitionCallbacks(
7677
});
7778
}
7879

80+
const transitionProgress = pendingTransitions.transitionProgress;
81+
const onTransitionProgress = callbacks.onTransitionProgress;
82+
if (onTransitionProgress != null && transitionProgress !== null) {
83+
transitionProgress.forEach((pending, transition) => {
84+
onTransitionProgress(
85+
transition.name,
86+
transition.startTime,
87+
endTime,
88+
Array.from(pending.values()),
89+
);
90+
});
91+
}
92+
7993
const transitionComplete = pendingTransitions.transitionComplete;
8094
if (transitionComplete !== null) {
8195
transitionComplete.forEach(transition => {
@@ -117,10 +131,11 @@ export function pushRootMarkerInstance(workInProgress: Fiber): void {
117131
if (transitions !== null) {
118132
transitions.forEach(transition => {
119133
if (!root.incompleteTransitions.has(transition)) {
120-
root.incompleteTransitions.set(transition, {
134+
const markerInstance: TracingMarkerInstance = {
121135
transitions: new Set([transition]),
122136
pendingSuspenseBoundaries: null,
123-
});
137+
};
138+
root.incompleteTransitions.set(transition, markerInstance);
124139
}
125140
});
126141
}

packages/react-reconciler/src/ReactFiberTracingMarkerComponent.old.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export type MarkerTransition = {
2424

2525
export type PendingTransitionCallbacks = {
2626
transitionStart: Array<Transition> | null,
27+
transitionProgress: Map<Transition, PendingSuspenseBoundaries> | null,
2728
transitionComplete: Array<Transition> | null,
2829
markerComplete: Array<MarkerTransition> | null,
2930
};
@@ -76,6 +77,19 @@ export function processTransitionCallbacks(
7677
});
7778
}
7879

80+
const transitionProgress = pendingTransitions.transitionProgress;
81+
const onTransitionProgress = callbacks.onTransitionProgress;
82+
if (onTransitionProgress != null && transitionProgress !== null) {
83+
transitionProgress.forEach((pending, transition) => {
84+
onTransitionProgress(
85+
transition.name,
86+
transition.startTime,
87+
endTime,
88+
Array.from(pending.values()),
89+
);
90+
});
91+
}
92+
7993
const transitionComplete = pendingTransitions.transitionComplete;
8094
if (transitionComplete !== null) {
8195
transitionComplete.forEach(transition => {
@@ -117,10 +131,11 @@ export function pushRootMarkerInstance(workInProgress: Fiber): void {
117131
if (transitions !== null) {
118132
transitions.forEach(transition => {
119133
if (!root.incompleteTransitions.has(transition)) {
120-
root.incompleteTransitions.set(transition, {
134+
const markerInstance: TracingMarkerInstance = {
121135
transitions: new Set([transition]),
122136
pendingSuspenseBoundaries: null,
123-
});
137+
};
138+
root.incompleteTransitions.set(transition, markerInstance);
124139
}
125140
});
126141
}

packages/react-reconciler/src/ReactFiberWorkLoop.new.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import type {EventPriority} from './ReactEventPriorities.new';
1717
import type {
1818
PendingTransitionCallbacks,
1919
MarkerTransition,
20+
PendingSuspenseBoundaries,
2021
Transition,
2122
} from './ReactFiberTracingMarkerComponent.new';
2223
import type {OffscreenInstance} from './ReactFiberOffscreenComponent';
@@ -339,6 +340,7 @@ export function addTransitionStartCallbackToPendingTransition(
339340
if (currentPendingTransitionCallbacks === null) {
340341
currentPendingTransitionCallbacks = {
341342
transitionStart: [],
343+
transitionProgress: null,
342344
transitionComplete: null,
343345
markerComplete: null,
344346
};
@@ -359,6 +361,7 @@ export function addMarkerCompleteCallbackToPendingTransition(
359361
if (currentPendingTransitionCallbacks === null) {
360362
currentPendingTransitionCallbacks = {
361363
transitionStart: null,
364+
transitionProgress: null,
362365
transitionComplete: null,
363366
markerComplete: [],
364367
};
@@ -372,13 +375,39 @@ export function addMarkerCompleteCallbackToPendingTransition(
372375
}
373376
}
374377

378+
export function addTransitionProgressCallbackToPendingTransition(
379+
transition: Transition,
380+
boundaries: PendingSuspenseBoundaries,
381+
) {
382+
if (enableTransitionTracing) {
383+
if (currentPendingTransitionCallbacks === null) {
384+
currentPendingTransitionCallbacks = {
385+
transitionStart: null,
386+
transitionProgress: new Map(),
387+
transitionComplete: null,
388+
markerComplete: null,
389+
};
390+
}
391+
392+
if (currentPendingTransitionCallbacks.transitionProgress === null) {
393+
currentPendingTransitionCallbacks.transitionProgress = new Map();
394+
}
395+
396+
currentPendingTransitionCallbacks.transitionProgress.set(
397+
transition,
398+
boundaries,
399+
);
400+
}
401+
}
402+
375403
export function addTransitionCompleteCallbackToPendingTransition(
376404
transition: Transition,
377405
) {
378406
if (enableTransitionTracing) {
379407
if (currentPendingTransitionCallbacks === null) {
380408
currentPendingTransitionCallbacks = {
381409
transitionStart: null,
410+
transitionProgress: null,
382411
transitionComplete: [],
383412
markerComplete: null,
384413
};

0 commit comments

Comments
 (0)