[Transition Tracing] Refactor Transition Tracing Root Code (#24766)
This PR refactors the transition tracing root code by reusing the tracing marker code. Namely it: * Refactors the tracing marker code so that it takes a tracing marker instance instead of a tracing marker fiber and rename the stack to `markerInstance` instead of `tracingMarker` * Pushes the root code onto the stack * Moves the instantiation of `root.incompleteTransitions` to the begin phase when we are pushing the root to the stack rather than in the commit phase
Luna Ruan committed
Jun 30, 2022 at 11:16 UTC
401296310fbc6a9e769936eda6a6d0269e9c84d0
14 files changed
+309
-179
packages/react-reconciler/src/ReactFiberBeginWork.new.js
+28
-9
@@ -27,6 +27,7 @@ import type {
27
OffscreenProps,
28
OffscreenState,
29
OffscreenQueue,
30
+ OffscreenInstance,
31
} from './ReactFiberOffscreenComponent';
32
import type {
33
Cache,
@@ -262,8 +263,9 @@ import {
263
getPendingTransitions,
264
} from './ReactFiberTransition.new';
265
import {
265
- getTracingMarkers,
266
- pushTracingMarker,
266
+ getMarkerInstances,
267
+ pushMarkerInstance,
268
+ pushRootMarkerInstance,
269
} from './ReactFiberTracingMarkerComponent.new';
270
271
const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
@@ -779,7 +781,10 @@ function updateOffscreenComponent(
781
if (enableTransitionTracing) {
782
// We have now gone from hidden to visible, so any transitions should
783
// be added to the stack to get added to any Offscreen/suspense children
782
- transitions = workInProgress.stateNode.transitions;
784
+ const instance: OffscreenInstance | null = workInProgress.stateNode;
785
+ if (instance !== null && instance.transitions != null) {
786
+ transitions = Array.from(instance.transitions);
787
+ }
788
}
789
790
pushTransition(workInProgress, prevCachePool, transitions);
@@ -909,7 +914,10 @@ function updateTracingMarkerComponent(
914
}
915
}
916
912
- pushTracingMarker(workInProgress);
917
+ const instance: TracingMarkerInstance | null = workInProgress.stateNode;
918
+ if (instance !== null) {
919
+ pushMarkerInstance(workInProgress, instance);
920
+ }
921
const nextChildren = workInProgress.pendingProps.children;
922
reconcileChildren(current, workInProgress, nextChildren, renderLanes);
923
return workInProgress.child;
@@ -1313,6 +1321,10 @@ function updateHostRoot(current, workInProgress, renderLanes) {
1321
const root: FiberRoot = workInProgress.stateNode;
1322
pushRootTransition(workInProgress, root, renderLanes);
1323
1324
+ if (enableTransitionTracing) {
1325
+ pushRootMarkerInstance(workInProgress);
1326
+ }
1327
+
1328
if (enableCache) {
1329
const nextCache: Cache = nextState.cache;
1330
pushCacheProvider(workInProgress, nextCache);
@@ -2098,10 +2110,10 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) {
2110
const currentTransitions = getPendingTransitions();
2111
if (currentTransitions !== null) {
2112
// If there are no transitions, we don't need to keep track of tracing markers
2101
- const currentTracingMarkers = getTracingMarkers();
2113
+ const parentMarkerInstances = getMarkerInstances();
2114
const primaryChildUpdateQueue: OffscreenQueue = {
2115
transitions: currentTransitions,
2104
- tracingMarkers: currentTracingMarkers,
2116
+ markerInstances: parentMarkerInstances,
2117
};
2118
primaryChildFragment.updateQueue = primaryChildUpdateQueue;
2119
}
@@ -2188,10 +2200,10 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) {
2200
if (enableTransitionTracing) {
2201
const currentTransitions = getPendingTransitions();
2202
if (currentTransitions !== null) {
2191
- const currentTracingMarkers = getTracingMarkers();
2203
+ const parentMarkerInstances = getMarkerInstances();
2204
const primaryChildUpdateQueue: OffscreenQueue = {
2205
transitions: currentTransitions,
2194
- tracingMarkers: currentTracingMarkers,
2206
+ markerInstances: parentMarkerInstances,
2207
};
2208
primaryChildFragment.updateQueue = primaryChildUpdateQueue;
2209
}
@@ -3509,6 +3521,10 @@ function attemptEarlyBailoutIfNoScheduledUpdate(
3521
const root: FiberRoot = workInProgress.stateNode;
3522
pushRootTransition(workInProgress, root, renderLanes);
3523
3524
+ if (enableTransitionTracing) {
3525
+ pushRootMarkerInstance(workInProgress);
3526
+ }
3527
+
3528
if (enableCache) {
3529
const cache: Cache = current.memoizedState.cache;
3530
pushCacheProvider(workInProgress, cache);
@@ -3694,7 +3710,10 @@ function attemptEarlyBailoutIfNoScheduledUpdate(
3710
}
3711
case TracingMarkerComponent: {
3712
if (enableTransitionTracing) {
3697
- pushTracingMarker(workInProgress);
3713
+ const instance: TracingMarkerInstance | null = workInProgress.stateNode;
3714
+ if (instance !== null) {
3715
+ pushMarkerInstance(workInProgress, instance);
3716
+ }
3717
}
3718
}
3719
}
packages/react-reconciler/src/ReactFiberBeginWork.old.js
+28
-9
@@ -27,6 +27,7 @@ import type {
27
OffscreenProps,
28
OffscreenState,
29
OffscreenQueue,
30
+ OffscreenInstance,
31
} from './ReactFiberOffscreenComponent';
32
import type {
33
Cache,
@@ -259,8 +260,9 @@ import {
260
getPendingTransitions,
261
} from './ReactFiberTransition.old';
262
import {
262
- getTracingMarkers,
263
- pushTracingMarker,
263
+ getMarkerInstances,
264
+ pushMarkerInstance,
265
+ pushRootMarkerInstance,
266
} from './ReactFiberTracingMarkerComponent.old';
267
268
const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
@@ -784,7 +786,10 @@ function updateOffscreenComponent(
786
if (enableTransitionTracing) {
787
// We have now gone from hidden to visible, so any transitions should
788
// be added to the stack to get added to any Offscreen/suspense children
787
- transitions = workInProgress.stateNode.transitions;
789
+ const instance: OffscreenInstance | null = workInProgress.stateNode;
790
+ if (instance !== null && instance.transitions != null) {
791
+ transitions = Array.from(instance.transitions);
792
+ }
793
}
794
795
pushTransition(workInProgress, prevCachePool, transitions);
@@ -909,7 +914,10 @@ function updateTracingMarkerComponent(
914
}
915
}
916
912
- pushTracingMarker(workInProgress);
917
+ const instance: TracingMarkerInstance | null = workInProgress.stateNode;
918
+ if (instance !== null) {
919
+ pushMarkerInstance(workInProgress, instance);
920
+ }
921
const nextChildren = workInProgress.pendingProps.children;
922
reconcileChildren(current, workInProgress, nextChildren, renderLanes);
923
return workInProgress.child;
@@ -1313,6 +1321,10 @@ function updateHostRoot(current, workInProgress, renderLanes) {
1321
const root: FiberRoot = workInProgress.stateNode;
1322
pushRootTransition(workInProgress, root, renderLanes);
1323
1324
+ if (enableTransitionTracing) {
1325
+ pushRootMarkerInstance(workInProgress);
1326
+ }
1327
+
1328
if (enableCache) {
1329
const nextCache: Cache = nextState.cache;
1330
pushCacheProvider(workInProgress, nextCache);
@@ -2114,10 +2126,10 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) {
2126
const currentTransitions = getPendingTransitions();
2127
if (currentTransitions !== null) {
2128
// If there are no transitions, we don't need to keep track of tracing markers
2117
- const currentTracingMarkers = getTracingMarkers();
2129
+ const parentMarkerInstances = getMarkerInstances();
2130
const primaryChildUpdateQueue: OffscreenQueue = {
2131
transitions: currentTransitions,
2120
- tracingMarkers: currentTracingMarkers,
2132
+ markerInstances: parentMarkerInstances,
2133
};
2134
primaryChildFragment.updateQueue = primaryChildUpdateQueue;
2135
}
@@ -2200,10 +2212,10 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) {
2212
if (enableTransitionTracing) {
2213
const currentTransitions = getPendingTransitions();
2214
if (currentTransitions !== null) {
2203
- const currentTracingMarkers = getTracingMarkers();
2215
+ const parentMarkerInstances = getMarkerInstances();
2216
const primaryChildUpdateQueue: OffscreenQueue = {
2217
transitions: currentTransitions,
2206
- tracingMarkers: currentTracingMarkers,
2218
+ markerInstances: parentMarkerInstances,
2219
};
2220
primaryChildFragment.updateQueue = primaryChildUpdateQueue;
2221
}
@@ -3510,6 +3522,10 @@ function attemptEarlyBailoutIfNoScheduledUpdate(
3522
const root: FiberRoot = workInProgress.stateNode;
3523
pushRootTransition(workInProgress, root, renderLanes);
3524
3525
+ if (enableTransitionTracing) {
3526
+ pushRootMarkerInstance(workInProgress);
3527
+ }
3528
+
3529
if (enableCache) {
3530
const cache: Cache = current.memoizedState.cache;
3531
pushCacheProvider(workInProgress, cache);
@@ -3702,7 +3718,10 @@ function attemptEarlyBailoutIfNoScheduledUpdate(
3718
}
3719
case TracingMarkerComponent: {
3720
if (enableTransitionTracing) {
3705
- pushTracingMarker(workInProgress);
3721
+ const instance: TracingMarkerInstance | null = workInProgress.stateNode;
3722
+ if (instance !== null) {
3723
+ pushMarkerInstance(workInProgress, instance);
3724
+ }
3725
}
3726
}
3727
}
packages/react-reconciler/src/ReactFiberCommitWork.new.js
+30
-63
@@ -2811,47 +2811,35 @@ function commitPassiveMountOnFiber(
2811
// Get the transitions that were initiatized during the render
2812
// and add a start transition callback for each of them
2813
const root = finishedWork.stateNode;
2814
- let incompleteTransitions = root.incompleteTransitions;
2814
+ const incompleteTransitions = root.incompleteTransitions;
2815
// Initial render
2816
if (committedTransitions !== null) {
2817
- if (incompleteTransitions === null) {
2818
- root.incompleteTransitions = incompleteTransitions = new Map();
2819
- }
2820
-
2817
committedTransitions.forEach(transition => {
2818
addTransitionStartCallbackToPendingTransition({
2819
transitionName: transition.name,
2820
startTime: transition.startTime,
2821
});
2826
-
2827
- if (!incompleteTransitions.has(transition)) {
2828
- incompleteTransitions.set(transition, null);
2829
- }
2822
});
2823
2824
clearTransitionsForLanes(finishedRoot, committedLanes);
2825
}
2826
2835
- if (incompleteTransitions !== null) {
2836
- incompleteTransitions.forEach((pendingBoundaries, transition) => {
2837
- if (pendingBoundaries === null || pendingBoundaries.size === 0) {
2827
+ incompleteTransitions.forEach(
2828
+ ({pendingSuspenseBoundaries}, transition) => {
2829
+ if (
2830
+ pendingSuspenseBoundaries === null ||
2831
+ pendingSuspenseBoundaries.size === 0
2832
+ ) {
2833
addTransitionCompleteCallbackToPendingTransition({
2834
transitionName: transition.name,
2835
startTime: transition.startTime,
2836
});
2837
incompleteTransitions.delete(transition);
2838
}
2844
- });
2845
- }
2839
+ },
2840
+ );
2841
2847
- // If there are no more pending suspense boundaries we
2848
- // clear the transitions because they are all complete.
2849
- if (
2850
- incompleteTransitions === null ||
2851
- incompleteTransitions.size === 0
2852
- ) {
2853
- root.incompleteTransitions = null;
2854
- }
2842
+ clearTransitionsForLanes(finishedRoot, committedLanes);
2843
}
2844
break;
2845
}
@@ -2896,14 +2884,6 @@ function commitPassiveMountOnFiber(
2884
if (isFallback) {
2885
const transitions = queue.transitions;
2886
let prevTransitions = instance.transitions;
2899
- let rootIncompleteTransitions = finishedRoot.incompleteTransitions;
2900
-
2901
- // We lazily instantiate transition tracing relevant maps
2902
- // and sets in the commit phase as we need to use them. We only
2903
- // instantiate them in the fallback phase on an as needed basis
2904
- if (rootIncompleteTransitions === null) {
2905
- finishedRoot.incompleteTransitions = rootIncompleteTransitions = new Map();
2906
- }
2887
if (instance.pendingMarkers === null) {
2888
instance.pendingMarkers = new Set();
2889
}
@@ -2911,56 +2891,43 @@ function commitPassiveMountOnFiber(
2891
instance.transitions = prevTransitions = new Set();
2892
}
2893
2914
- // TODO(luna): Combine the root code with the tracing marker code
2894
if (transitions !== null) {
2895
transitions.forEach(transition => {
2896
// Add all the transitions saved in the update queue during
2897
// the render phase (ie the transitions associated with this boundary)
2898
// into the transitions set.
2899
prevTransitions.add(transition);
2921
-
2922
- // Add the root transition's pending suspense boundary set to
2923
- // the queue's marker set. We will iterate through the marker
2924
- // set when we toggle state on the suspense boundary and
2925
- // add or remove the pending suspense boundaries as needed.
2926
- if (rootIncompleteTransitions !== null) {
2927
- if (!rootIncompleteTransitions.has(transition)) {
2928
- rootIncompleteTransitions.set(transition, new Map());
2929
- }
2930
- instance.pendingMarkers.add(
2931
- rootIncompleteTransitions.get(transition),
2932
- );
2933
- }
2900
});
2901
}
2902
2937
- const tracingMarkers = queue.tracingMarkers;
2938
- if (tracingMarkers !== null) {
2939
- tracingMarkers.forEach(marker => {
2940
- const markerInstance = marker.stateNode;
2903
+ const markerInstances = queue.markerInstances;
2904
+ if (markerInstances !== null) {
2905
+ markerInstances.forEach(markerInstance => {
2906
+ if (markerInstance.pendingSuspenseBoundaries === null) {
2907
+ markerInstance.pendingSuspenseBoundaries = new Map();
2908
+ }
2909
+
2910
+ const markerTransitions = markerInstance.transitions;
2911
// There should only be a few tracing marker transitions because
2912
// they should be only associated with the transition that
2913
// caused them
2944
- markerInstance.transitions.forEach(transition => {
2945
- if (instance.transitions.has(transition)) {
2946
- instance.pendingMarkers.add(
2947
- markerInstance.pendingSuspenseBoundaries,
2948
- );
2949
- }
2950
- });
2914
+ if (markerTransitions !== null) {
2915
+ markerTransitions.forEach(transition => {
2916
+ if (instance.transitions.has(transition)) {
2917
+ instance.pendingMarkers.add(
2918
+ markerInstance.pendingSuspenseBoundaries,
2919
+ );
2920
+ }
2921
+ });
2922
+ }
2923
});
2924
}
2925
}
2926
2955
- commitTransitionProgress(finishedWork);
2956
-
2957
- if (
2958
- instance.pendingMarkers === null ||
2959
- instance.pendingMarkers.size === 0
2960
- ) {
2961
- finishedWork.updateQueue = null;
2962
- }
2927
+ finishedWork.updateQueue = null;
2928
}
2929
+
2930
+ commitTransitionProgress(finishedWork);
2931
}
2932
2933
break;
packages/react-reconciler/src/ReactFiberCommitWork.old.js
+30
-63
@@ -2811,47 +2811,35 @@ function commitPassiveMountOnFiber(
2811
// Get the transitions that were initiatized during the render
2812
// and add a start transition callback for each of them
2813
const root = finishedWork.stateNode;
2814
- let incompleteTransitions = root.incompleteTransitions;
2814
+ const incompleteTransitions = root.incompleteTransitions;
2815
// Initial render
2816
if (committedTransitions !== null) {
2817
- if (incompleteTransitions === null) {
2818
- root.incompleteTransitions = incompleteTransitions = new Map();
2819
- }
2820
-
2817
committedTransitions.forEach(transition => {
2818
addTransitionStartCallbackToPendingTransition({
2819
transitionName: transition.name,
2820
startTime: transition.startTime,
2821
});
2826
-
2827
- if (!incompleteTransitions.has(transition)) {
2828
- incompleteTransitions.set(transition, null);
2829
- }
2822
});
2823
2824
clearTransitionsForLanes(finishedRoot, committedLanes);
2825
}
2826
2835
- if (incompleteTransitions !== null) {
2836
- incompleteTransitions.forEach((pendingBoundaries, transition) => {
2837
- if (pendingBoundaries === null || pendingBoundaries.size === 0) {
2827
+ incompleteTransitions.forEach(
2828
+ ({pendingSuspenseBoundaries}, transition) => {
2829
+ if (
2830
+ pendingSuspenseBoundaries === null ||
2831
+ pendingSuspenseBoundaries.size === 0
2832
+ ) {
2833
addTransitionCompleteCallbackToPendingTransition({
2834
transitionName: transition.name,
2835
startTime: transition.startTime,
2836
});
2837
incompleteTransitions.delete(transition);
2838
}
2844
- });
2845
- }
2839
+ },
2840
+ );
2841
2847
- // If there are no more pending suspense boundaries we
2848
- // clear the transitions because they are all complete.
2849
- if (
2850
- incompleteTransitions === null ||
2851
- incompleteTransitions.size === 0
2852
- ) {
2853
- root.incompleteTransitions = null;
2854
- }
2842
+ clearTransitionsForLanes(finishedRoot, committedLanes);
2843
}
2844
break;
2845
}
@@ -2896,14 +2884,6 @@ function commitPassiveMountOnFiber(
2884
if (isFallback) {
2885
const transitions = queue.transitions;
2886
let prevTransitions = instance.transitions;
2899
- let rootIncompleteTransitions = finishedRoot.incompleteTransitions;
2900
-
2901
- // We lazily instantiate transition tracing relevant maps
2902
- // and sets in the commit phase as we need to use them. We only
2903
- // instantiate them in the fallback phase on an as needed basis
2904
- if (rootIncompleteTransitions === null) {
2905
- finishedRoot.incompleteTransitions = rootIncompleteTransitions = new Map();
2906
- }
2887
if (instance.pendingMarkers === null) {
2888
instance.pendingMarkers = new Set();
2889
}
@@ -2911,56 +2891,43 @@ function commitPassiveMountOnFiber(
2891
instance.transitions = prevTransitions = new Set();
2892
}
2893
2914
- // TODO(luna): Combine the root code with the tracing marker code
2894
if (transitions !== null) {
2895
transitions.forEach(transition => {
2896
// Add all the transitions saved in the update queue during
2897
// the render phase (ie the transitions associated with this boundary)
2898
// into the transitions set.
2899
prevTransitions.add(transition);
2921
-
2922
- // Add the root transition's pending suspense boundary set to
2923
- // the queue's marker set. We will iterate through the marker
2924
- // set when we toggle state on the suspense boundary and
2925
- // add or remove the pending suspense boundaries as needed.
2926
- if (rootIncompleteTransitions !== null) {
2927
- if (!rootIncompleteTransitions.has(transition)) {
2928
- rootIncompleteTransitions.set(transition, new Map());
2929
- }
2930
- instance.pendingMarkers.add(
2931
- rootIncompleteTransitions.get(transition),
2932
- );
2933
- }
2900
});
2901
}
2902
2937
- const tracingMarkers = queue.tracingMarkers;
2938
- if (tracingMarkers !== null) {
2939
- tracingMarkers.forEach(marker => {
2940
- const markerInstance = marker.stateNode;
2903
+ const markerInstances = queue.markerInstances;
2904
+ if (markerInstances !== null) {
2905
+ markerInstances.forEach(markerInstance => {
2906
+ if (markerInstance.pendingSuspenseBoundaries === null) {
2907
+ markerInstance.pendingSuspenseBoundaries = new Map();
2908
+ }
2909
+
2910
+ const markerTransitions = markerInstance.transitions;
2911
// There should only be a few tracing marker transitions because
2912
// they should be only associated with the transition that
2913
// caused them
2944
- markerInstance.transitions.forEach(transition => {
2945
- if (instance.transitions.has(transition)) {
2946
- instance.pendingMarkers.add(
2947
- markerInstance.pendingSuspenseBoundaries,
2948
- );
2949
- }
2950
- });
2914
+ if (markerTransitions !== null) {
2915
+ markerTransitions.forEach(transition => {
2916
+ if (instance.transitions.has(transition)) {
2917
+ instance.pendingMarkers.add(
2918
+ markerInstance.pendingSuspenseBoundaries,
2919
+ );
2920
+ }
2921
+ });
2922
+ }
2923
});
2924
}
2925
}
2926
2955
- commitTransitionProgress(finishedWork);
2956
-
2957
- if (
2958
- instance.pendingMarkers === null ||
2959
- instance.pendingMarkers.size === 0
2960
- ) {
2961
- finishedWork.updateQueue = null;
2962
- }
2927
+ finishedWork.updateQueue = null;
2928
}
2929
+
2930
+ commitTransitionProgress(finishedWork);
2931
}
2932
2933
break;
packages/react-reconciler/src/ReactFiberCompleteWork.new.js
+14
-2
@@ -28,6 +28,7 @@ import type {
28
SuspenseListRenderState,
29
} from './ReactFiberSuspenseComponent.new';
30
import type {OffscreenState} from './ReactFiberOffscreenComponent';
31
+import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent.new';
32
import type {Cache} from './ReactFiberCacheComponent.new';
33
import {
34
enableSuspenseAvoidThisFallback,
@@ -164,7 +165,10 @@ import {transferActualDuration} from './ReactProfilerTimer.new';
165
import {popCacheProvider} from './ReactFiberCacheComponent.new';
166
import {popTreeContext} from './ReactFiberTreeContext.new';
167
import {popRootTransition, popTransition} from './ReactFiberTransition.new';
167
-import {popTracingMarker} from './ReactFiberTracingMarkerComponent.new';
168
+import {
169
+ popMarkerInstance,
170
+ popRootMarkerInstance,
171
+} from './ReactFiberTracingMarkerComponent.new';
172
173
function markUpdate(workInProgress: Fiber) {
174
// Tag the fiber with an update effect. This turns a Placement into
@@ -900,6 +904,11 @@ function completeWork(
904
}
905
popCacheProvider(workInProgress, cache);
906
}
907
+
908
+ if (enableTransitionTracing) {
909
+ popRootMarkerInstance(workInProgress);
910
+ }
911
+
912
popRootTransition(workInProgress, fiberRoot, renderLanes);
913
popHostContainer(workInProgress);
914
popTopLevelLegacyContextObject(workInProgress);
@@ -1579,7 +1588,10 @@ function completeWork(
1588
}
1589
case TracingMarkerComponent: {
1590
if (enableTransitionTracing) {
1582
- popTracingMarker(workInProgress);
1591
+ const instance: TracingMarkerInstance | null = workInProgress.stateNode;
1592
+ if (instance !== null) {
1593
+ popMarkerInstance(workInProgress);
1594
+ }
1595
bubbleProperties(workInProgress);
1596
1597
if (
packages/react-reconciler/src/ReactFiberCompleteWork.old.js
+14
-2
@@ -29,6 +29,7 @@ import type {
29
} from './ReactFiberSuspenseComponent.old';
30
import type {SuspenseContext} from './ReactFiberSuspenseContext.old';
31
import type {OffscreenState} from './ReactFiberOffscreenComponent';
32
+import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent.old';
33
import type {Cache} from './ReactFiberCacheComponent.old';
34
import {
35
enableSuspenseAvoidThisFallback,
@@ -164,7 +165,10 @@ import {transferActualDuration} from './ReactProfilerTimer.old';
165
import {popCacheProvider} from './ReactFiberCacheComponent.old';
166
import {popTreeContext} from './ReactFiberTreeContext.old';
167
import {popRootTransition, popTransition} from './ReactFiberTransition.old';
167
-import {popTracingMarker} from './ReactFiberTracingMarkerComponent.old';
168
+import {
169
+ popMarkerInstance,
170
+ popRootMarkerInstance,
171
+} from './ReactFiberTracingMarkerComponent.old';
172
173
function markUpdate(workInProgress: Fiber) {
174
// Tag the fiber with an update effect. This turns a Placement into
@@ -900,6 +904,11 @@ function completeWork(
904
}
905
popCacheProvider(workInProgress, cache);
906
}
907
+
908
+ if (enableTransitionTracing) {
909
+ popRootMarkerInstance(workInProgress);
910
+ }
911
+
912
popRootTransition(workInProgress, fiberRoot, renderLanes);
913
popHostContainer(workInProgress);
914
popTopLevelLegacyContextObject(workInProgress);
@@ -1579,7 +1588,10 @@ function completeWork(
1588
}
1589
case TracingMarkerComponent: {
1590
if (enableTransitionTracing) {
1582
- popTracingMarker(workInProgress);
1591
+ const instance: TracingMarkerInstance | null = workInProgress.stateNode;
1592
+ if (instance !== null) {
1593
+ popMarkerInstance(workInProgress);
1594
+ }
1595
bubbleProperties(workInProgress);
1596
1597
if (
packages/react-reconciler/src/ReactFiberOffscreenComponent.js
+2
-2
@@ -8,12 +8,12 @@
8
*/
9
10
import type {ReactNodeList, OffscreenMode} from 'shared/ReactTypes';
11
-import type {Fiber} from './ReactInternalTypes';
11
import type {Lanes} from './ReactFiberLane.old';
12
import type {SpawnedCachePool} from './ReactFiberCacheComponent.new';
13
import type {
14
Transition,
15
PendingSuspenseBoundaries,
16
+ TracingMarkerInstance,
17
} from './ReactFiberTracingMarkerComponent.new';
18
19
export type OffscreenProps = {|
@@ -39,7 +39,7 @@ export type OffscreenState = {|
39
40
export type OffscreenQueue = {|
41
transitions: Array<Transition> | null,
42
- tracingMarkers: Array<Fiber> | null,
42
+ markerInstances: Array<TracingMarkerInstance> | null,
43
|} | null;
44
45
export type OffscreenInstance = {|
packages/react-reconciler/src/ReactFiberRoot.new.js
+1
-1
@@ -92,13 +92,13 @@ function FiberRootNode(
92
this.hydrationCallbacks = null;
93
}
94
95
+ this.incompleteTransitions = new Map();
96
if (enableTransitionTracing) {
97
this.transitionCallbacks = null;
98
const transitionLanesMap = (this.transitionLanes = []);
99
for (let i = 0; i < TotalLanes; i++) {
100
transitionLanesMap.push(null);
101
}
101
- this.incompleteTransitions = null;
102
}
103
104
if (enableProfilerTimer && enableProfilerCommitHooks) {
packages/react-reconciler/src/ReactFiberRoot.old.js
+1
-1
@@ -92,13 +92,13 @@ function FiberRootNode(
92
this.hydrationCallbacks = null;
93
}
94
95
+ this.incompleteTransitions = new Map();
96
if (enableTransitionTracing) {
97
this.transitionCallbacks = null;
98
const transitionLanesMap = (this.transitionLanes = []);
99
for (let i = 0; i < TotalLanes; i++) {
100
transitionLanesMap.push(null);
101
}
101
- this.incompleteTransitions = null;
102
}
103
104
if (enableProfilerTimer && enableProfilerCommitHooks) {
packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js
+57
-10
@@ -13,6 +13,7 @@ import type {StackCursor} from './ReactFiberStack.new';
13
14
import {enableTransitionTracing} from 'shared/ReactFeatureFlags';
15
import {createCursor, push, pop} from './ReactFiberStack.new';
16
+import {getWorkInProgressTransitions} from './ReactFiberWorkLoop.new';
17
18
export type SuspenseInfo = {name: string | null};
19
@@ -100,31 +101,77 @@ export function processTransitionCallbacks(
101
// tracing marker can be logged as complete
102
// This code lives separate from the ReactFiberTransition code because
103
// we push and pop on the tracing marker, not the suspense boundary
103
-const tracingMarkerStack: StackCursor<Array<Fiber> | null> = createCursor(null);
104
+const markerInstanceStack: StackCursor<Array<TracingMarkerInstance> | null> = createCursor(
105
+ null,
106
+);
107
105
-export function pushTracingMarker(workInProgress: Fiber): void {
108
+export function pushRootMarkerInstance(workInProgress: Fiber): void {
109
if (enableTransitionTracing) {
107
- if (tracingMarkerStack.current === null) {
108
- push(tracingMarkerStack, [workInProgress], workInProgress);
110
+ // On the root, every transition gets mapped to it's own map of
111
+ // suspense boundaries. The transition is marked as complete when
112
+ // the suspense boundaries map is empty. We do this because every
113
+ // transition completes at different times and depends on different
114
+ // suspense boundaries to complete. We store all the transitions
115
+ // along with its map of suspense boundaries in the root incomplete
116
+ // transitions map. Each entry in this map functions like a tracing
117
+ // marker does, so we can push it onto the marker instance stack
118
+ const transitions = getWorkInProgressTransitions();
119
+ const root = workInProgress.stateNode;
120
+
121
+ if (transitions !== null) {
122
+ transitions.forEach(transition => {
123
+ if (!root.incompleteTransitions.has(transition)) {
124
+ root.incompleteTransitions.set(transition, {
125
+ transitions: new Set([transition]),
126
+ pendingSuspenseBoundaries: null,
127
+ });
128
+ }
129
+ });
130
+ }
131
+
132
+ const markerInstances = [];
133
+ // For ever transition on the suspense boundary, we push the transition
134
+ // along with its map of pending suspense boundaries onto the marker
135
+ // instance stack.
136
+ root.incompleteTransitions.forEach(markerInstance => {
137
+ markerInstances.push(markerInstance);
138
+ });
139
+ push(markerInstanceStack, markerInstances, workInProgress);
140
+ }
141
+}
142
+
143
+export function popRootMarkerInstance(workInProgress: Fiber) {
144
+ if (enableTransitionTracing) {
145
+ pop(markerInstanceStack, workInProgress);
146
+ }
147
+}
148
+
149
+export function pushMarkerInstance(
150
+ workInProgress: Fiber,
151
+ markerInstance: TracingMarkerInstance,
152
+): void {
153
+ if (enableTransitionTracing) {
154
+ if (markerInstanceStack.current === null) {
155
+ push(markerInstanceStack, [markerInstance], workInProgress);
156
} else {
157
push(
111
- tracingMarkerStack,
112
- tracingMarkerStack.current.concat(workInProgress),
158
+ markerInstanceStack,
159
+ markerInstanceStack.current.concat(markerInstance),
160
workInProgress,
161
);
162
}
163
}
164
}
165
119
-export function popTracingMarker(workInProgress: Fiber): void {
166
+export function popMarkerInstance(workInProgress: Fiber): void {
167
if (enableTransitionTracing) {
121
- pop(tracingMarkerStack, workInProgress);
168
+ pop(markerInstanceStack, workInProgress);
169
}
170
}
171
125
-export function getTracingMarkers(): Array<Fiber> | null {
172
+export function getMarkerInstances(): Array<TracingMarkerInstance> | null {
173
if (enableTransitionTracing) {
127
- return tracingMarkerStack.current;
174
+ return markerInstanceStack.current;
175
}
176
return null;
177
}
packages/react-reconciler/src/ReactFiberTracingMarkerComponent.old.js
+57
-10
@@ -13,6 +13,7 @@ import type {StackCursor} from './ReactFiberStack.old';
13
14
import {enableTransitionTracing} from 'shared/ReactFeatureFlags';
15
import {createCursor, push, pop} from './ReactFiberStack.old';
16
+import {getWorkInProgressTransitions} from './ReactFiberWorkLoop.old';
17
18
export type SuspenseInfo = {name: string | null};
19
@@ -100,31 +101,77 @@ export function processTransitionCallbacks(
101
// tracing marker can be logged as complete
102
// This code lives separate from the ReactFiberTransition code because
103
// we push and pop on the tracing marker, not the suspense boundary
103
-const tracingMarkerStack: StackCursor<Array<Fiber> | null> = createCursor(null);
104
+const markerInstanceStack: StackCursor<Array<TracingMarkerInstance> | null> = createCursor(
105
+ null,
106
+);
107
105
-export function pushTracingMarker(workInProgress: Fiber): void {
108
+export function pushRootMarkerInstance(workInProgress: Fiber): void {
109
if (enableTransitionTracing) {
107
- if (tracingMarkerStack.current === null) {
108
- push(tracingMarkerStack, [workInProgress], workInProgress);
110
+ // On the root, every transition gets mapped to it's own map of
111
+ // suspense boundaries. The transition is marked as complete when
112
+ // the suspense boundaries map is empty. We do this because every
113
+ // transition completes at different times and depends on different
114
+ // suspense boundaries to complete. We store all the transitions
115
+ // along with its map of suspense boundaries in the root incomplete
116
+ // transitions map. Each entry in this map functions like a tracing
117
+ // marker does, so we can push it onto the marker instance stack
118
+ const transitions = getWorkInProgressTransitions();
119
+ const root = workInProgress.stateNode;
120
+
121
+ if (transitions !== null) {
122
+ transitions.forEach(transition => {
123
+ if (!root.incompleteTransitions.has(transition)) {
124
+ root.incompleteTransitions.set(transition, {
125
+ transitions: new Set([transition]),
126
+ pendingSuspenseBoundaries: null,
127
+ });
128
+ }
129
+ });
130
+ }
131
+
132
+ const markerInstances = [];
133
+ // For ever transition on the suspense boundary, we push the transition
134
+ // along with its map of pending suspense boundaries onto the marker
135
+ // instance stack.
136
+ root.incompleteTransitions.forEach(markerInstance => {
137
+ markerInstances.push(markerInstance);
138
+ });
139
+ push(markerInstanceStack, markerInstances, workInProgress);
140
+ }
141
+}
142
+
143
+export function popRootMarkerInstance(workInProgress: Fiber) {
144
+ if (enableTransitionTracing) {
145
+ pop(markerInstanceStack, workInProgress);
146
+ }
147
+}
148
+
149
+export function pushMarkerInstance(
150
+ workInProgress: Fiber,
151
+ markerInstance: TracingMarkerInstance,
152
+): void {
153
+ if (enableTransitionTracing) {
154
+ if (markerInstanceStack.current === null) {
155
+ push(markerInstanceStack, [markerInstance], workInProgress);
156
} else {
157
push(
111
- tracingMarkerStack,
112
- tracingMarkerStack.current.concat(workInProgress),
158
+ markerInstanceStack,
159
+ markerInstanceStack.current.concat(markerInstance),
160
workInProgress,
161
);
162
}
163
}
164
}
165
119
-export function popTracingMarker(workInProgress: Fiber): void {
166
+export function popMarkerInstance(workInProgress: Fiber): void {
167
if (enableTransitionTracing) {
121
- pop(tracingMarkerStack, workInProgress);
168
+ pop(markerInstanceStack, workInProgress);
169
}
170
}
171
125
-export function getTracingMarkers(): Array<Fiber> | null {
172
+export function getMarkerInstances(): Array<TracingMarkerInstance> | null {
173
if (enableTransitionTracing) {
127
- return tracingMarkerStack.current;
174
+ return markerInstanceStack.current;
175
}
176
return null;
177
}
packages/react-reconciler/src/ReactFiberUnwindWork.new.js
+23
-3
@@ -12,6 +12,7 @@ import type {Fiber, FiberRoot} from './ReactInternalTypes';
12
import type {Lanes} from './ReactFiberLane.new';
13
import type {SuspenseState} from './ReactFiberSuspenseComponent.new';
14
import type {Cache} from './ReactFiberCacheComponent.new';
15
+import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent.new';
16
17
import {resetWorkInProgressVersions as resetMutableSourceWorkInProgressVersions} from './ReactMutableSource.new';
18
import {
@@ -52,7 +53,10 @@ import {popCacheProvider} from './ReactFiberCacheComponent.new';
53
import {transferActualDuration} from './ReactProfilerTimer.new';
54
import {popTreeContext} from './ReactFiberTreeContext.new';
55
import {popRootTransition, popTransition} from './ReactFiberTransition.new';
55
-import {popTracingMarker} from './ReactFiberTracingMarkerComponent.new';
56
+import {
57
+ popMarkerInstance,
58
+ popRootMarkerInstance,
59
+} from './ReactFiberTracingMarkerComponent.new';
60
61
function unwindWork(
62
current: Fiber | null,
@@ -89,6 +93,11 @@ function unwindWork(
93
const cache: Cache = workInProgress.memoizedState.cache;
94
popCacheProvider(workInProgress, cache);
95
}
96
+
97
+ if (enableTransitionTracing) {
98
+ popRootMarkerInstance(workInProgress);
99
+ }
100
+
101
popRootTransition(workInProgress, root, renderLanes);
102
popHostContainer(workInProgress);
103
popTopLevelLegacyContextObject(workInProgress);
@@ -165,7 +174,9 @@ function unwindWork(
174
return null;
175
case TracingMarkerComponent:
176
if (enableTransitionTracing) {
168
- popTracingMarker(workInProgress);
177
+ if (workInProgress.stateNode !== null) {
178
+ popMarkerInstance(workInProgress);
179
+ }
180
}
181
return null;
182
default:
@@ -197,6 +208,11 @@ function unwindInterruptedWork(
208
const cache: Cache = interruptedWork.memoizedState.cache;
209
popCacheProvider(interruptedWork, cache);
210
}
211
+
212
+ if (enableTransitionTracing) {
213
+ popRootMarkerInstance(interruptedWork);
214
+ }
215
+
216
popRootTransition(interruptedWork, root, renderLanes);
217
popHostContainer(interruptedWork);
218
popTopLevelLegacyContextObject(interruptedWork);
@@ -233,7 +249,11 @@ function unwindInterruptedWork(
249
break;
250
case TracingMarkerComponent:
251
if (enableTransitionTracing) {
236
- popTracingMarker(interruptedWork);
252
+ const instance: TracingMarkerInstance | null =
253
+ interruptedWork.stateNode;
254
+ if (instance !== null) {
255
+ popMarkerInstance(interruptedWork);
256
+ }
257
}
258
break;
259
default:
packages/react-reconciler/src/ReactFiberUnwindWork.old.js
+23
-3
@@ -12,6 +12,7 @@ import type {Fiber, FiberRoot} from './ReactInternalTypes';
12
import type {Lanes} from './ReactFiberLane.old';
13
import type {SuspenseState} from './ReactFiberSuspenseComponent.old';
14
import type {Cache} from './ReactFiberCacheComponent.old';
15
+import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent.old';
16
17
import {resetWorkInProgressVersions as resetMutableSourceWorkInProgressVersions} from './ReactMutableSource.old';
18
import {
@@ -49,7 +50,10 @@ import {popCacheProvider} from './ReactFiberCacheComponent.old';
50
import {transferActualDuration} from './ReactProfilerTimer.old';
51
import {popTreeContext} from './ReactFiberTreeContext.old';
52
import {popRootTransition, popTransition} from './ReactFiberTransition.old';
52
-import {popTracingMarker} from './ReactFiberTracingMarkerComponent.old';
53
+import {
54
+ popMarkerInstance,
55
+ popRootMarkerInstance,
56
+} from './ReactFiberTracingMarkerComponent.old';
57
58
function unwindWork(
59
current: Fiber | null,
@@ -86,6 +90,11 @@ function unwindWork(
90
const cache: Cache = workInProgress.memoizedState.cache;
91
popCacheProvider(workInProgress, cache);
92
}
93
+
94
+ if (enableTransitionTracing) {
95
+ popRootMarkerInstance(workInProgress);
96
+ }
97
+
98
popRootTransition(workInProgress, root, renderLanes);
99
popHostContainer(workInProgress);
100
popTopLevelLegacyContextObject(workInProgress);
@@ -162,7 +171,9 @@ function unwindWork(
171
return null;
172
case TracingMarkerComponent:
173
if (enableTransitionTracing) {
165
- popTracingMarker(workInProgress);
174
+ if (workInProgress.stateNode !== null) {
175
+ popMarkerInstance(workInProgress);
176
+ }
177
}
178
return null;
179
default:
@@ -194,6 +205,11 @@ function unwindInterruptedWork(
205
const cache: Cache = interruptedWork.memoizedState.cache;
206
popCacheProvider(interruptedWork, cache);
207
}
208
+
209
+ if (enableTransitionTracing) {
210
+ popRootMarkerInstance(interruptedWork);
211
+ }
212
+
213
popRootTransition(interruptedWork, root, renderLanes);
214
popHostContainer(interruptedWork);
215
popTopLevelLegacyContextObject(interruptedWork);
@@ -230,7 +246,11 @@ function unwindInterruptedWork(
246
break;
247
case TracingMarkerComponent:
248
if (enableTransitionTracing) {
233
- popTracingMarker(interruptedWork);
249
+ const instance: TracingMarkerInstance | null =
250
+ interruptedWork.stateNode;
251
+ if (instance !== null) {
252
+ popMarkerInstance(interruptedWork);
253
+ }
254
}
255
break;
256
default:
packages/react-reconciler/src/ReactInternalTypes.js
+1
-1
@@ -335,7 +335,7 @@ type TransitionTracingOnlyFiberRootProperties = {|
335
// are considered complete when the pending suspense boundaries set is
336
// empty. We can represent this as a Map of transitions to suspense
337
// boundary sets
338
- incompleteTransitions: Map<Transition, PendingSuspenseBoundaries> | null,
338
+ incompleteTransitions: Map<Transition, PendingSuspenseBoundaries>,
339
|};
340
341
// Exported FiberRoot type includes all properties,