Skip to content

Commit 1fb0d06

Browse files
authored
[Devtools][Transition Tracing] Add Transition callbacks to createRoot (#23276)
- Add the type of transition tracing callbacks - Add transition tracing callbacks as an option to `createRoot` - Add transition tracing callbacks on the root - Add option to pass transition tracing callbacks to createReactNoop
1 parent a6987be commit 1fb0d06

File tree

11 files changed

+129
-8
lines changed

11 files changed

+129
-8
lines changed

packages/react-dom/src/client/ReactDOMLegacy.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ function legacyCreateRootFromDOMContainer(
127127
false, // isStrictMode
128128
false, // concurrentUpdatesByDefaultOverride,
129129
'', // identifierPrefix
130-
noopOnRecoverableError,
130+
noopOnRecoverableError, // onRecoverableError
131+
null, // transitionCallbacks
131132
);
132133
markContainerAsRoot(root.current, container);
133134

packages/react-dom/src/client/ReactDOMRoot.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99

1010
import type {Container} from './ReactDOMHostConfig';
1111
import type {MutableSource, ReactNodeList} from 'shared/ReactTypes';
12-
import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
12+
import type {
13+
FiberRoot,
14+
TransitionTracingCallbacks,
15+
} from 'react-reconciler/src/ReactInternalTypes';
1316

1417
import {queueExplicitHydrationTarget} from '../events/ReactDOMEventReplaying';
1518

@@ -25,6 +28,7 @@ export type CreateRootOptions = {
2528
unstable_concurrentUpdatesByDefault?: boolean,
2629
identifierPrefix?: string,
2730
onRecoverableError?: (error: mixed) => void,
31+
transitionCallbacks?: TransitionTracingCallbacks,
2832
...
2933
};
3034

@@ -158,6 +162,8 @@ export function createRoot(
158162
let concurrentUpdatesByDefaultOverride = false;
159163
let identifierPrefix = '';
160164
let onRecoverableError = defaultOnRecoverableError;
165+
let transitionCallbacks = null;
166+
161167
if (options !== null && options !== undefined) {
162168
if (__DEV__) {
163169
if ((options: any).hydrate) {
@@ -181,6 +187,9 @@ export function createRoot(
181187
if (options.onRecoverableError !== undefined) {
182188
onRecoverableError = options.onRecoverableError;
183189
}
190+
if (options.transitionCallbacks !== undefined) {
191+
transitionCallbacks = options.transitionCallbacks;
192+
}
184193
}
185194

186195
const root = createContainer(
@@ -192,6 +201,7 @@ export function createRoot(
192201
concurrentUpdatesByDefaultOverride,
193202
identifierPrefix,
194203
onRecoverableError,
204+
transitionCallbacks,
195205
);
196206
markContainerAsRoot(root.current, container);
197207

@@ -260,6 +270,8 @@ export function hydrateRoot(
260270
concurrentUpdatesByDefaultOverride,
261271
identifierPrefix,
262272
onRecoverableError,
273+
// TODO(luna) Support hydration later
274+
null,
263275
);
264276
markContainerAsRoot(root.current, container);
265277
// This can't be a comment node since hydration doesn't work on comment nodes anyway.

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ function render(
221221
null,
222222
'',
223223
onRecoverableError,
224+
null,
224225
);
225226
roots.set(containerTag, root);
226227
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ function render(
217217
null,
218218
'',
219219
onRecoverableError,
220+
null,
220221
);
221222
roots.set(containerTag, root);
222223
}

packages/react-noop-renderer/src/createReactNoop.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414
* environment.
1515
*/
1616

17-
import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
17+
import type {
18+
Fiber,
19+
TransitionTracingCallbacks,
20+
} from 'react-reconciler/src/ReactInternalTypes';
1821
import type {UpdateQueue} from 'react-reconciler/src/ReactUpdateQueue';
1922
import type {ReactNodeList, OffscreenMode} from 'shared/ReactTypes';
2023
import type {RootTag} from 'react-reconciler/src/ReactRootTags';
@@ -64,6 +67,10 @@ type TextInstance = {|
6467
context: HostContext,
6568
|};
6669
type HostContext = Object;
70+
type CreateRootOptions = {
71+
transitionCallbacks?: TransitionTracingCallbacks,
72+
...
73+
};
6774

6875
const NO_CONTEXT = {};
6976
const UPPERCASE_CONTEXT = {};
@@ -980,7 +987,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
980987
},
981988

982989
// TODO: Replace ReactNoop.render with createRoot + root.render
983-
createRoot() {
990+
createRoot(options?: CreateRootOptions) {
984991
const container = {
985992
rootID: '' + idCounter++,
986993
pendingChildren: [],
@@ -995,6 +1002,9 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
9951002
false,
9961003
'',
9971004
onRecoverableError,
1005+
options && options.transitionCallbacks
1006+
? options.transitionCallbacks
1007+
: null,
9981008
);
9991009
return {
10001010
_Scheduler: Scheduler,

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
* @flow
88
*/
99

10-
import type {Fiber, SuspenseHydrationCallbacks} from './ReactInternalTypes';
10+
import type {
11+
Fiber,
12+
SuspenseHydrationCallbacks,
13+
TransitionTracingCallbacks,
14+
} from './ReactInternalTypes';
1115
import type {FiberRoot} from './ReactInternalTypes';
1216
import type {RootTag} from './ReactRootTags';
1317
import type {
@@ -246,6 +250,7 @@ export function createContainer(
246250
concurrentUpdatesByDefaultOverride: null | boolean,
247251
identifierPrefix: string,
248252
onRecoverableError: (error: mixed) => void,
253+
transitionCallbacks: null | TransitionTracingCallbacks,
249254
): OpaqueRoot {
250255
return createFiberRoot(
251256
containerInfo,
@@ -256,6 +261,7 @@ export function createContainer(
256261
concurrentUpdatesByDefaultOverride,
257262
identifierPrefix,
258263
onRecoverableError,
264+
transitionCallbacks,
259265
);
260266
}
261267

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
* @flow
88
*/
99

10-
import type {Fiber, SuspenseHydrationCallbacks} from './ReactInternalTypes';
10+
import type {
11+
Fiber,
12+
SuspenseHydrationCallbacks,
13+
TransitionTracingCallbacks,
14+
} from './ReactInternalTypes';
1115
import type {FiberRoot} from './ReactInternalTypes';
1216
import type {RootTag} from './ReactRootTags';
1317
import type {
@@ -246,6 +250,7 @@ export function createContainer(
246250
concurrentUpdatesByDefaultOverride: null | boolean,
247251
identifierPrefix: string,
248252
onRecoverableError: (error: mixed) => void,
253+
transitionCallbacks: null | TransitionTracingCallbacks,
249254
): OpaqueRoot {
250255
return createFiberRoot(
251256
containerInfo,
@@ -256,6 +261,7 @@ export function createContainer(
256261
concurrentUpdatesByDefaultOverride,
257262
identifierPrefix,
258263
onRecoverableError,
264+
transitionCallbacks,
259265
);
260266
}
261267

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
* @flow
88
*/
99

10-
import type {FiberRoot, SuspenseHydrationCallbacks} from './ReactInternalTypes';
10+
import type {
11+
FiberRoot,
12+
SuspenseHydrationCallbacks,
13+
TransitionTracingCallbacks,
14+
} from './ReactInternalTypes';
1115
import type {RootTag} from './ReactRootTags';
1216

1317
import {noTimeout, supportsHydration} from './ReactFiberHostConfig';
@@ -25,6 +29,7 @@ import {
2529
enableProfilerCommitHooks,
2630
enableProfilerTimer,
2731
enableUpdaterTracking,
32+
enableTransitionTracing,
2833
} from 'shared/ReactFeatureFlags';
2934
import {initializeUpdateQueue} from './ReactUpdateQueue.new';
3035
import {LegacyRoot, ConcurrentRoot} from './ReactRootTags';
@@ -78,6 +83,10 @@ function FiberRootNode(
7883
this.hydrationCallbacks = null;
7984
}
8085

86+
if (enableTransitionTracing) {
87+
this.transitionCallbacks = null;
88+
}
89+
8190
if (enableProfilerTimer && enableProfilerCommitHooks) {
8291
this.effectDuration = 0;
8392
this.passiveEffectDuration = 0;
@@ -116,6 +125,7 @@ export function createFiberRoot(
116125
// single type, like a DynamicHostConfig that is defined by the renderer.
117126
identifierPrefix: string,
118127
onRecoverableError: null | ((error: mixed) => void),
128+
transitionCallbacks: null | TransitionTracingCallbacks,
119129
): FiberRoot {
120130
const root: FiberRoot = (new FiberRootNode(
121131
containerInfo,
@@ -128,6 +138,10 @@ export function createFiberRoot(
128138
root.hydrationCallbacks = hydrationCallbacks;
129139
}
130140

141+
if (enableTransitionTracing) {
142+
root.transitionCallbacks = transitionCallbacks;
143+
}
144+
131145
// Cyclic construction. This cheats the type system right now because
132146
// stateNode is any.
133147
const uninitializedFiber = createHostRootFiber(

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
* @flow
88
*/
99

10-
import type {FiberRoot, SuspenseHydrationCallbacks} from './ReactInternalTypes';
10+
import type {
11+
FiberRoot,
12+
SuspenseHydrationCallbacks,
13+
TransitionTracingCallbacks,
14+
} from './ReactInternalTypes';
1115
import type {RootTag} from './ReactRootTags';
1216

1317
import {noTimeout, supportsHydration} from './ReactFiberHostConfig';
@@ -25,6 +29,7 @@ import {
2529
enableProfilerCommitHooks,
2630
enableProfilerTimer,
2731
enableUpdaterTracking,
32+
enableTransitionTracing,
2833
} from 'shared/ReactFeatureFlags';
2934
import {initializeUpdateQueue} from './ReactUpdateQueue.old';
3035
import {LegacyRoot, ConcurrentRoot} from './ReactRootTags';
@@ -78,6 +83,10 @@ function FiberRootNode(
7883
this.hydrationCallbacks = null;
7984
}
8085

86+
if (enableTransitionTracing) {
87+
this.transitionCallbacks = null;
88+
}
89+
8190
if (enableProfilerTimer && enableProfilerCommitHooks) {
8291
this.effectDuration = 0;
8392
this.passiveEffectDuration = 0;
@@ -116,6 +125,7 @@ export function createFiberRoot(
116125
// single type, like a DynamicHostConfig that is defined by the renderer.
117126
identifierPrefix: string,
118127
onRecoverableError: null | ((error: mixed) => void),
128+
transitionCallbacks: null | TransitionTracingCallbacks,
119129
): FiberRoot {
120130
const root: FiberRoot = (new FiberRootNode(
121131
containerInfo,
@@ -128,6 +138,10 @@ export function createFiberRoot(
128138
root.hydrationCallbacks = hydrationCallbacks;
129139
}
130140

141+
if (enableTransitionTracing) {
142+
root.transitionCallbacks = transitionCallbacks;
143+
}
144+
131145
// Cyclic construction. This cheats the type system right now because
132146
// stateNode is any.
133147
const uninitializedFiber = createHostRootFiber(

packages/react-reconciler/src/ReactInternalTypes.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,13 +268,68 @@ type SuspenseCallbackOnlyFiberRootProperties = {|
268268
hydrationCallbacks: null | SuspenseHydrationCallbacks,
269269
|};
270270

271+
export type TransitionTracingCallbacks = {
272+
onTransitionStart?: (transitionName: string, startTime: number) => void,
273+
onTransitionProgress?: (
274+
transitionName: string,
275+
startTime: number,
276+
currentTime: number,
277+
pending: Array<{name: null | string}>,
278+
) => void,
279+
onTransitionIncomplete?: (
280+
transitionName: string,
281+
startTime: number,
282+
deletions: Array<{
283+
type: string,
284+
name?: string,
285+
newName?: string,
286+
endTime: number,
287+
}>,
288+
) => void,
289+
onTransitionComplete?: (
290+
transitionName: string,
291+
startTime: number,
292+
endTime: number,
293+
) => void,
294+
onMarkerProgress?: (
295+
transitionName: string,
296+
marker: string,
297+
startTime: number,
298+
currentTime: number,
299+
pending: Array<{name: null | string}>,
300+
) => void,
301+
onMarkerIncomplete?: (
302+
transitionName: string,
303+
marker: string,
304+
startTime: number,
305+
deletions: Array<{
306+
type: string,
307+
name?: string,
308+
newName?: string,
309+
endTime: number,
310+
}>,
311+
) => void,
312+
onMarkerComplete?: (
313+
transitionName: string,
314+
marker: string,
315+
startTime: number,
316+
endTime: number,
317+
) => void,
318+
};
319+
320+
// The following fields are only used in transition tracing in Profile builds
321+
type TransitionTracingOnlyFiberRootProperties = {|
322+
transitionCallbacks: null | TransitionTracingCallbacks,
323+
|};
324+
271325
// Exported FiberRoot type includes all properties,
272326
// To avoid requiring potentially error-prone :any casts throughout the project.
273327
// The types are defined separately within this file to ensure they stay in sync.
274328
export type FiberRoot = {
275329
...BaseFiberRootProperties,
276330
...SuspenseCallbackOnlyFiberRootProperties,
277331
...UpdaterTrackingOnlyFiberRootProperties,
332+
...TransitionTracingOnlyFiberRootProperties,
278333
...
279334
};
280335

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ function create(element: React$Element<any>, options: TestRendererOptions) {
479479
concurrentUpdatesByDefault,
480480
'',
481481
onRecoverableError,
482+
null,
482483
);
483484

484485
if (root == null) {

0 commit comments

Comments
 (0)