9
10
import type {Fiber} from './ReactInternalTypes';
11
12
+import type {Lane} from './ReactFiberLane';
13
+import {isTransitionLane, isBlockingLane, isSyncLane} from './ReactFiberLane';
14
+
15
+import {resolveEventType, resolveEventTimeStamp} from './ReactFiberConfig';
16
+
17
import {
18
enableProfilerCommitHooks,
19
enableProfilerNestedUpdatePhase,
20
enableProfilerTimer,
21
+ enableComponentPerformanceTrack,
22
} from 'shared/ReactFeatureFlags';
23
24
// Intentionally not named imports because Rollup would use dynamic dispatch for
27
28
const {unstable_now: now} = Scheduler;
29
30
+export let renderStartTime: number = -0;
31
export let completeTime: number = -0;
32
export let commitTime: number = -0;
33
export let profilerStartTime: number = -1.1;
36
export let componentEffectStartTime: number = -1.1;
37
export let componentEffectEndTime: number = -1.1;
38
39
+export let blockingUpdateTime: number = -1.1; // First sync setState scheduled.
40
+export let blockingEventTime: number = -1.1; // Event timeStamp of the first setState.
41
+export let blockingEventType: null | string = null; // Event type of the first setState.
42
+// TODO: This should really be one per Transition lane.
43
+export let transitionStartTime: number = -1.1; // First startTransition call before setState.
44
+export let transitionUpdateTime: number = -1.1; // First transition setState scheduled.
45
+export let transitionEventTime: number = -1.1; // Event timeStamp of the first transition.
46
+export let transitionEventType: null | string = null; // Event type of the first transition.
47
+
48
+export function startUpdateTimerByLane(lane: Lane): void {
49
+ if (!enableProfilerTimer || !enableComponentPerformanceTrack) {
50
+ return;
51
+ }
52
+ if (isSyncLane(lane) || isBlockingLane(lane)) {
53
+ if (blockingUpdateTime < 0) {
54
+ blockingUpdateTime = now();
55
+ blockingEventTime = resolveEventTimeStamp();
56
+ blockingEventType = resolveEventType();
57
+ }
58
+ } else if (isTransitionLane(lane)) {
59
+ if (transitionUpdateTime < 0) {
60
+ transitionUpdateTime = now();
61
+ if (transitionStartTime < 0) {
62
+ transitionEventTime = resolveEventTimeStamp();
63
+ transitionEventType = resolveEventType();
64
+ }
65
+ }
66
+ }
67
+}
68
+
69
+export function clearBlockingTimers(): void {
70
+ blockingUpdateTime = -1.1;
71
+}
72
+
73
+export function startAsyncTransitionTimer(): void {
74
+ if (!enableProfilerTimer || !enableComponentPerformanceTrack) {
75
+ return;
76
+ }
77
+ if (transitionStartTime < 0 && transitionUpdateTime < 0) {
78
+ transitionStartTime = now();
79
+ transitionEventTime = resolveEventTimeStamp();
80
+ transitionEventType = resolveEventType();
81
+ }
82
+}
83
+
84
+export function hasScheduledTransitionWork(): boolean {
85
+ // If we have setState on a transition or scheduled useActionState update.
86
+ return transitionUpdateTime > -1;
87
+}
88
+
89
+// We use this marker to indicate that we have scheduled a render to be performed
90
+// but it's not an explicit state update.
91
+const ACTION_STATE_MARKER = -0.5;
92
+
93
+export function startActionStateUpdate(): void {
94
+ if (!enableProfilerTimer || !enableComponentPerformanceTrack) {
95
+ return;
96
+ }
97
+ if (transitionUpdateTime < 0) {
98
+ transitionUpdateTime = ACTION_STATE_MARKER;
99
+ }
100
+}
101
+
102
+export function clearAsyncTransitionTimer(): void {
103
+ transitionStartTime = -1.1;
104
+}
105
+
106
+export function clearTransitionTimers(): void {
107
+ transitionStartTime = -1.1;
108
+ transitionUpdateTime = -1.1;
109
+}
110
+
111
+export function clampBlockingTimers(finalTime: number): void {
112
+ if (!enableProfilerTimer || !enableComponentPerformanceTrack) {
113
+ return;
114
+ }
115
+ // If we had new updates come in while we were still rendering or committing, we don't want
116
+ // those update times to create overlapping tracks in the performance timeline so we clamp
117
+ // them to the end of the commit phase.
118
+ if (blockingUpdateTime >= 0 && blockingUpdateTime < finalTime) {
119
+ blockingUpdateTime = finalTime;
120
+ }
121
+ if (blockingEventTime >= 0 && blockingEventTime < finalTime) {
122
+ blockingEventTime = finalTime;
123
+ }
124
+}
125
+
126
+export function clampTransitionTimers(finalTime: number): void {
127
+ if (!enableProfilerTimer || !enableComponentPerformanceTrack) {
128
+ return;
129
+ }
130
+ // If we had new updates come in while we were still rendering or committing, we don't want
131
+ // those update times to create overlapping tracks in the performance timeline so we clamp
132
+ // them to the end of the commit phase.
133
+ if (transitionStartTime >= 0 && transitionStartTime < finalTime) {
134
+ transitionStartTime = finalTime;
135
+ }
136
+ if (transitionUpdateTime >= 0 && transitionUpdateTime < finalTime) {
137
+ transitionUpdateTime = finalTime;
138
+ }
139
+ if (transitionEventTime >= 0 && transitionEventTime < finalTime) {
140
+ transitionEventTime = finalTime;
141
+ }
142
+}
143
+
144
export function pushNestedEffectDurations(): number {
145
if (!enableProfilerTimer || !enableProfilerCommitHooks) {
146
return 0;
248
}
249
}
250
251
+export function recordRenderTime(): void {
252
+ if (!enableProfilerTimer || !enableComponentPerformanceTrack) {
253
+ return;
254
+ }
255
+ renderStartTime = now();
256
+}
257
+
258
export function recordCompleteTime(): void {
259
if (!enableProfilerTimer) {
260
return;