[Transition Tracing] Add Tracing Marker Stack (#24661)
When a suspense boundary suspends or commits, we need to notify the corresponding tracing markers so that they know when to log that they've completed. To do this, we add a stack of tracing markers. In the begin phase, we will push the tracing markers onto the stack, and during the complete/unwind phase we will pop the tracing markers off the stack In a later PR, we will store the active tracing markers on the suspense boundary, and during the commit phase we will process the active tracing markers by adding/removing the boundary as appropriate.
Luna Ruan committed
Jun 9, 2022 at 17:10 UTC
a8555c308e06eacf807ec47caafd1e0e789d2c54
8 files changed
+124
-2
packages/react-reconciler/src/ReactFiberBeginWork.new.js
+7
@@ -258,6 +258,7 @@ import {
258
getOffscreenDeferredCache,
259
getSuspendedTransitions,
260
} from './ReactFiberTransition.new';
261
+import {pushTracingMarker} from './ReactFiberTracingMarkerComponent.new';
262
263
const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
264
@@ -887,6 +888,7 @@ function updateTracingMarkerComponent(
888
return null;
889
}
890
891
+ pushTracingMarker(workInProgress);
892
const nextChildren = workInProgress.pendingProps.children;
893
reconcileChildren(current, workInProgress, nextChildren, renderLanes);
894
return workInProgress.child;
@@ -3678,6 +3680,11 @@ function attemptEarlyBailoutIfNoScheduledUpdate(
3680
}
3681
break;
3682
}
3683
+ case TracingMarkerComponent: {
3684
+ if (enableTransitionTracing) {
3685
+ pushTracingMarker(workInProgress);
3686
+ }
3687
+ }
3688
}
3689
return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
3690
}
packages/react-reconciler/src/ReactFiberBeginWork.old.js
+7
@@ -258,6 +258,7 @@ import {
258
getOffscreenDeferredCache,
259
getSuspendedTransitions,
260
} from './ReactFiberTransition.old';
261
+import {pushTracingMarker} from './ReactFiberTracingMarkerComponent.old';
262
263
const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
264
@@ -887,6 +888,7 @@ function updateTracingMarkerComponent(
888
return null;
889
}
890
891
+ pushTracingMarker(workInProgress);
892
const nextChildren = workInProgress.pendingProps.children;
893
reconcileChildren(current, workInProgress, nextChildren, renderLanes);
894
return workInProgress.child;
@@ -3678,6 +3680,11 @@ function attemptEarlyBailoutIfNoScheduledUpdate(
3680
}
3681
break;
3682
}
3683
+ case TracingMarkerComponent: {
3684
+ if (enableTransitionTracing) {
3685
+ pushTracingMarker(workInProgress);
3686
+ }
3687
+ }
3688
}
3689
return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
3690
}
packages/react-reconciler/src/ReactFiberCompleteWork.new.js
+2
@@ -165,6 +165,7 @@ import {transferActualDuration} from './ReactProfilerTimer.new';
165
import {popCacheProvider} from './ReactFiberCacheComponent.new';
166
import {popTreeContext} from './ReactFiberTreeContext.new';
167
import {popRootTransition, popTransition} from './ReactFiberTransition.new';
168
+import {popTracingMarker} from './ReactFiberTracingMarkerComponent.new';
169
170
function markUpdate(workInProgress: Fiber) {
171
// Tag the fiber with an update effect. This turns a Placement into
@@ -1585,6 +1586,7 @@ function completeWork(
1586
case TracingMarkerComponent: {
1587
if (enableTransitionTracing) {
1588
// Bubble subtree flags before so we can set the flag property
1589
+ popTracingMarker(workInProgress);
1590
bubbleProperties(workInProgress);
1591
}
1592
return null;
packages/react-reconciler/src/ReactFiberCompleteWork.old.js
+2
@@ -165,6 +165,7 @@ import {transferActualDuration} from './ReactProfilerTimer.old';
165
import {popCacheProvider} from './ReactFiberCacheComponent.old';
166
import {popTreeContext} from './ReactFiberTreeContext.old';
167
import {popRootTransition, popTransition} from './ReactFiberTransition.old';
168
+import {popTracingMarker} from './ReactFiberTracingMarkerComponent.old';
169
170
function markUpdate(workInProgress: Fiber) {
171
// Tag the fiber with an update effect. This turns a Placement into
@@ -1585,6 +1586,7 @@ function completeWork(
1586
case TracingMarkerComponent: {
1587
if (enableTransitionTracing) {
1588
// Bubble subtree flags before so we can set the flag property
1589
+ popTracingMarker(workInProgress);
1590
bubbleProperties(workInProgress);
1591
}
1592
return null;
packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js
+36
@@ -9,8 +9,10 @@
9
10
import type {TransitionTracingCallbacks, Fiber} from './ReactInternalTypes';
11
import type {OffscreenInstance} from './ReactFiberOffscreenComponent';
12
+import type {StackCursor} from './ReactFiberStack.new';
13
14
import {enableTransitionTracing} from 'shared/ReactFeatureFlags';
15
+import {createCursor, push, pop} from './ReactFiberStack.new';
16
17
export type SuspenseInfo = {name: string | null};
18
@@ -71,3 +73,37 @@ export function processTransitionCallbacks(
73
}
74
}
75
}
76
+
77
+// For every tracing marker, store a pointer to it. We will later access it
78
+// to get the set of suspense boundaries that need to resolve before the
79
+// tracing marker can be logged as complete
80
+// This code lives separate from the ReactFiberTransition code because
81
+// we push and pop on the tracing marker, not the suspense boundary
82
+const tracingMarkerStack: StackCursor<Array<Fiber> | null> = createCursor(null);
83
+
84
+export function pushTracingMarker(workInProgress: Fiber): void {
85
+ if (enableTransitionTracing) {
86
+ if (tracingMarkerStack.current === null) {
87
+ push(tracingMarkerStack, [workInProgress], workInProgress);
88
+ } else {
89
+ push(
90
+ tracingMarkerStack,
91
+ tracingMarkerStack.current.concat(workInProgress),
92
+ workInProgress,
93
+ );
94
+ }
95
+ }
96
+}
97
+
98
+export function popTracingMarker(workInProgress: Fiber): void {
99
+ if (enableTransitionTracing) {
100
+ pop(tracingMarkerStack, workInProgress);
101
+ }
102
+}
103
+
104
+export function getTracingMarkers(): Array<Fiber> | null {
105
+ if (enableTransitionTracing) {
106
+ return tracingMarkerStack.current;
107
+ }
108
+ return null;
109
+}
packages/react-reconciler/src/ReactFiberTracingMarkerComponent.old.js
+36
@@ -9,8 +9,10 @@
9
10
import type {TransitionTracingCallbacks, Fiber} from './ReactInternalTypes';
11
import type {OffscreenInstance} from './ReactFiberOffscreenComponent';
12
+import type {StackCursor} from './ReactFiberStack.old';
13
14
import {enableTransitionTracing} from 'shared/ReactFeatureFlags';
15
+import {createCursor, push, pop} from './ReactFiberStack.old';
16
17
export type SuspenseInfo = {name: string | null};
18
@@ -71,3 +73,37 @@ export function processTransitionCallbacks(
73
}
74
}
75
}
76
+
77
+// For every tracing marker, store a pointer to it. We will later access it
78
+// to get the set of suspense boundaries that need to resolve before the
79
+// tracing marker can be logged as complete
80
+// This code lives separate from the ReactFiberTransition code because
81
+// we push and pop on the tracing marker, not the suspense boundary
82
+const tracingMarkerStack: StackCursor<Array<Fiber> | null> = createCursor(null);
83
+
84
+export function pushTracingMarker(workInProgress: Fiber): void {
85
+ if (enableTransitionTracing) {
86
+ if (tracingMarkerStack.current === null) {
87
+ push(tracingMarkerStack, [workInProgress], workInProgress);
88
+ } else {
89
+ push(
90
+ tracingMarkerStack,
91
+ tracingMarkerStack.current.concat(workInProgress),
92
+ workInProgress,
93
+ );
94
+ }
95
+ }
96
+}
97
+
98
+export function popTracingMarker(workInProgress: Fiber): void {
99
+ if (enableTransitionTracing) {
100
+ pop(tracingMarkerStack, workInProgress);
101
+ }
102
+}
103
+
104
+export function getTracingMarkers(): Array<Fiber> | null {
105
+ if (enableTransitionTracing) {
106
+ return tracingMarkerStack.current;
107
+ }
108
+ return null;
109
+}
packages/react-reconciler/src/ReactFiberUnwindWork.new.js
+17
-1
@@ -25,10 +25,15 @@ import {
25
OffscreenComponent,
26
LegacyHiddenComponent,
27
CacheComponent,
28
+ TracingMarkerComponent,
29
} from './ReactWorkTags';
30
import {DidCapture, NoFlags, ShouldCapture} from './ReactFiberFlags';
31
import {NoMode, ProfileMode} from './ReactTypeOfMode';
31
-import {enableProfilerTimer, enableCache} from 'shared/ReactFeatureFlags';
32
+import {
33
+ enableProfilerTimer,
34
+ enableCache,
35
+ enableTransitionTracing,
36
+} from 'shared/ReactFeatureFlags';
37
38
import {popHostContainer, popHostContext} from './ReactFiberHostContext.new';
39
import {popSuspenseContext} from './ReactFiberSuspenseContext.new';
@@ -44,6 +49,7 @@ import {popCacheProvider} from './ReactFiberCacheComponent.new';
49
import {transferActualDuration} from './ReactProfilerTimer.new';
50
import {popTreeContext} from './ReactFiberTreeContext.new';
51
import {popRootTransition, popTransition} from './ReactFiberTransition.new';
52
+import {popTracingMarker} from './ReactFiberTracingMarkerComponent.new';
53
54
function unwindWork(
55
current: Fiber | null,
@@ -154,6 +160,11 @@ function unwindWork(
160
popCacheProvider(workInProgress, cache);
161
}
162
return null;
163
+ case TracingMarkerComponent:
164
+ if (enableTransitionTracing) {
165
+ popTracingMarker(workInProgress);
166
+ }
167
+ return null;
168
default:
169
return null;
170
}
@@ -217,6 +228,11 @@ function unwindInterruptedWork(
228
popCacheProvider(interruptedWork, cache);
229
}
230
break;
231
+ case TracingMarkerComponent:
232
+ if (enableTransitionTracing) {
233
+ popTracingMarker(interruptedWork);
234
+ }
235
+ break;
236
default:
237
break;
238
}
packages/react-reconciler/src/ReactFiberUnwindWork.old.js
+17
-1
@@ -25,10 +25,15 @@ import {
25
OffscreenComponent,
26
LegacyHiddenComponent,
27
CacheComponent,
28
+ TracingMarkerComponent,
29
} from './ReactWorkTags';
30
import {DidCapture, NoFlags, ShouldCapture} from './ReactFiberFlags';
31
import {NoMode, ProfileMode} from './ReactTypeOfMode';
31
-import {enableProfilerTimer, enableCache} from 'shared/ReactFeatureFlags';
32
+import {
33
+ enableProfilerTimer,
34
+ enableCache,
35
+ enableTransitionTracing,
36
+} from 'shared/ReactFeatureFlags';
37
38
import {popHostContainer, popHostContext} from './ReactFiberHostContext.old';
39
import {popSuspenseContext} from './ReactFiberSuspenseContext.old';
@@ -44,6 +49,7 @@ import {popCacheProvider} from './ReactFiberCacheComponent.old';
49
import {transferActualDuration} from './ReactProfilerTimer.old';
50
import {popTreeContext} from './ReactFiberTreeContext.old';
51
import {popRootTransition, popTransition} from './ReactFiberTransition.old';
52
+import {popTracingMarker} from './ReactFiberTracingMarkerComponent.old';
53
54
function unwindWork(
55
current: Fiber | null,
@@ -154,6 +160,11 @@ function unwindWork(
160
popCacheProvider(workInProgress, cache);
161
}
162
return null;
163
+ case TracingMarkerComponent:
164
+ if (enableTransitionTracing) {
165
+ popTracingMarker(workInProgress);
166
+ }
167
+ return null;
168
default:
169
return null;
170
}
@@ -217,6 +228,11 @@ function unwindInterruptedWork(
228
popCacheProvider(interruptedWork, cache);
229
}
230
break;
231
+ case TracingMarkerComponent:
232
+ if (enableTransitionTracing) {
233
+ popTracingMarker(interruptedWork);
234
+ }
235
+ break;
236
default:
237
break;
238
}