Skip to content

Commit

Permalink
[Devtools][Transition Tracing] Add Transition callbacks to createRoot (
Browse files Browse the repository at this point in the history
…#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
  • Loading branch information
lunaruan authored Feb 11, 2022
1 parent a6987be commit 1fb0d06
Show file tree
Hide file tree
Showing 11 changed files with 129 additions and 8 deletions.
3 changes: 2 additions & 1 deletion packages/react-dom/src/client/ReactDOMLegacy.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ function legacyCreateRootFromDOMContainer(
false, // isStrictMode
false, // concurrentUpdatesByDefaultOverride,
'', // identifierPrefix
noopOnRecoverableError,
noopOnRecoverableError, // onRecoverableError
null, // transitionCallbacks
);
markContainerAsRoot(root.current, container);

Expand Down
14 changes: 13 additions & 1 deletion packages/react-dom/src/client/ReactDOMRoot.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@

import type {Container} from './ReactDOMHostConfig';
import type {MutableSource, ReactNodeList} from 'shared/ReactTypes';
import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
import type {
FiberRoot,
TransitionTracingCallbacks,
} from 'react-reconciler/src/ReactInternalTypes';

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

Expand All @@ -25,6 +28,7 @@ export type CreateRootOptions = {
unstable_concurrentUpdatesByDefault?: boolean,
identifierPrefix?: string,
onRecoverableError?: (error: mixed) => void,
transitionCallbacks?: TransitionTracingCallbacks,
...
};

Expand Down Expand Up @@ -158,6 +162,8 @@ export function createRoot(
let concurrentUpdatesByDefaultOverride = false;
let identifierPrefix = '';
let onRecoverableError = defaultOnRecoverableError;
let transitionCallbacks = null;

if (options !== null && options !== undefined) {
if (__DEV__) {
if ((options: any).hydrate) {
Expand All @@ -181,6 +187,9 @@ export function createRoot(
if (options.onRecoverableError !== undefined) {
onRecoverableError = options.onRecoverableError;
}
if (options.transitionCallbacks !== undefined) {
transitionCallbacks = options.transitionCallbacks;
}
}

const root = createContainer(
Expand All @@ -192,6 +201,7 @@ export function createRoot(
concurrentUpdatesByDefaultOverride,
identifierPrefix,
onRecoverableError,
transitionCallbacks,
);
markContainerAsRoot(root.current, container);

Expand Down Expand Up @@ -260,6 +270,8 @@ export function hydrateRoot(
concurrentUpdatesByDefaultOverride,
identifierPrefix,
onRecoverableError,
// TODO(luna) Support hydration later
null,
);
markContainerAsRoot(root.current, container);
// This can't be a comment node since hydration doesn't work on comment nodes anyway.
Expand Down
1 change: 1 addition & 0 deletions packages/react-native-renderer/src/ReactFabric.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ function render(
null,
'',
onRecoverableError,
null,
);
roots.set(containerTag, root);
}
Expand Down
1 change: 1 addition & 0 deletions packages/react-native-renderer/src/ReactNativeRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ function render(
null,
'',
onRecoverableError,
null,
);
roots.set(containerTag, root);
}
Expand Down
14 changes: 12 additions & 2 deletions packages/react-noop-renderer/src/createReactNoop.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
* environment.
*/

import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
import type {
Fiber,
TransitionTracingCallbacks,
} from 'react-reconciler/src/ReactInternalTypes';
import type {UpdateQueue} from 'react-reconciler/src/ReactUpdateQueue';
import type {ReactNodeList, OffscreenMode} from 'shared/ReactTypes';
import type {RootTag} from 'react-reconciler/src/ReactRootTags';
Expand Down Expand Up @@ -64,6 +67,10 @@ type TextInstance = {|
context: HostContext,
|};
type HostContext = Object;
type CreateRootOptions = {
transitionCallbacks?: TransitionTracingCallbacks,
...
};

const NO_CONTEXT = {};
const UPPERCASE_CONTEXT = {};
Expand Down Expand Up @@ -980,7 +987,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
},

// TODO: Replace ReactNoop.render with createRoot + root.render
createRoot() {
createRoot(options?: CreateRootOptions) {
const container = {
rootID: '' + idCounter++,
pendingChildren: [],
Expand All @@ -995,6 +1002,9 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
false,
'',
onRecoverableError,
options && options.transitionCallbacks
? options.transitionCallbacks
: null,
);
return {
_Scheduler: Scheduler,
Expand Down
8 changes: 7 additions & 1 deletion packages/react-reconciler/src/ReactFiberReconciler.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
* @flow
*/

import type {Fiber, SuspenseHydrationCallbacks} from './ReactInternalTypes';
import type {
Fiber,
SuspenseHydrationCallbacks,
TransitionTracingCallbacks,
} from './ReactInternalTypes';
import type {FiberRoot} from './ReactInternalTypes';
import type {RootTag} from './ReactRootTags';
import type {
Expand Down Expand Up @@ -246,6 +250,7 @@ export function createContainer(
concurrentUpdatesByDefaultOverride: null | boolean,
identifierPrefix: string,
onRecoverableError: (error: mixed) => void,
transitionCallbacks: null | TransitionTracingCallbacks,
): OpaqueRoot {
return createFiberRoot(
containerInfo,
Expand All @@ -256,6 +261,7 @@ export function createContainer(
concurrentUpdatesByDefaultOverride,
identifierPrefix,
onRecoverableError,
transitionCallbacks,
);
}

Expand Down
8 changes: 7 additions & 1 deletion packages/react-reconciler/src/ReactFiberReconciler.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
* @flow
*/

import type {Fiber, SuspenseHydrationCallbacks} from './ReactInternalTypes';
import type {
Fiber,
SuspenseHydrationCallbacks,
TransitionTracingCallbacks,
} from './ReactInternalTypes';
import type {FiberRoot} from './ReactInternalTypes';
import type {RootTag} from './ReactRootTags';
import type {
Expand Down Expand Up @@ -246,6 +250,7 @@ export function createContainer(
concurrentUpdatesByDefaultOverride: null | boolean,
identifierPrefix: string,
onRecoverableError: (error: mixed) => void,
transitionCallbacks: null | TransitionTracingCallbacks,
): OpaqueRoot {
return createFiberRoot(
containerInfo,
Expand All @@ -256,6 +261,7 @@ export function createContainer(
concurrentUpdatesByDefaultOverride,
identifierPrefix,
onRecoverableError,
transitionCallbacks,
);
}

Expand Down
16 changes: 15 additions & 1 deletion packages/react-reconciler/src/ReactFiberRoot.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
* @flow
*/

import type {FiberRoot, SuspenseHydrationCallbacks} from './ReactInternalTypes';
import type {
FiberRoot,
SuspenseHydrationCallbacks,
TransitionTracingCallbacks,
} from './ReactInternalTypes';
import type {RootTag} from './ReactRootTags';

import {noTimeout, supportsHydration} from './ReactFiberHostConfig';
Expand All @@ -25,6 +29,7 @@ import {
enableProfilerCommitHooks,
enableProfilerTimer,
enableUpdaterTracking,
enableTransitionTracing,
} from 'shared/ReactFeatureFlags';
import {initializeUpdateQueue} from './ReactUpdateQueue.new';
import {LegacyRoot, ConcurrentRoot} from './ReactRootTags';
Expand Down Expand Up @@ -78,6 +83,10 @@ function FiberRootNode(
this.hydrationCallbacks = null;
}

if (enableTransitionTracing) {
this.transitionCallbacks = null;
}

if (enableProfilerTimer && enableProfilerCommitHooks) {
this.effectDuration = 0;
this.passiveEffectDuration = 0;
Expand Down Expand Up @@ -116,6 +125,7 @@ export function createFiberRoot(
// single type, like a DynamicHostConfig that is defined by the renderer.
identifierPrefix: string,
onRecoverableError: null | ((error: mixed) => void),
transitionCallbacks: null | TransitionTracingCallbacks,
): FiberRoot {
const root: FiberRoot = (new FiberRootNode(
containerInfo,
Expand All @@ -128,6 +138,10 @@ export function createFiberRoot(
root.hydrationCallbacks = hydrationCallbacks;
}

if (enableTransitionTracing) {
root.transitionCallbacks = transitionCallbacks;
}

// Cyclic construction. This cheats the type system right now because
// stateNode is any.
const uninitializedFiber = createHostRootFiber(
Expand Down
16 changes: 15 additions & 1 deletion packages/react-reconciler/src/ReactFiberRoot.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
* @flow
*/

import type {FiberRoot, SuspenseHydrationCallbacks} from './ReactInternalTypes';
import type {
FiberRoot,
SuspenseHydrationCallbacks,
TransitionTracingCallbacks,
} from './ReactInternalTypes';
import type {RootTag} from './ReactRootTags';

import {noTimeout, supportsHydration} from './ReactFiberHostConfig';
Expand All @@ -25,6 +29,7 @@ import {
enableProfilerCommitHooks,
enableProfilerTimer,
enableUpdaterTracking,
enableTransitionTracing,
} from 'shared/ReactFeatureFlags';
import {initializeUpdateQueue} from './ReactUpdateQueue.old';
import {LegacyRoot, ConcurrentRoot} from './ReactRootTags';
Expand Down Expand Up @@ -78,6 +83,10 @@ function FiberRootNode(
this.hydrationCallbacks = null;
}

if (enableTransitionTracing) {
this.transitionCallbacks = null;
}

if (enableProfilerTimer && enableProfilerCommitHooks) {
this.effectDuration = 0;
this.passiveEffectDuration = 0;
Expand Down Expand Up @@ -116,6 +125,7 @@ export function createFiberRoot(
// single type, like a DynamicHostConfig that is defined by the renderer.
identifierPrefix: string,
onRecoverableError: null | ((error: mixed) => void),
transitionCallbacks: null | TransitionTracingCallbacks,
): FiberRoot {
const root: FiberRoot = (new FiberRootNode(
containerInfo,
Expand All @@ -128,6 +138,10 @@ export function createFiberRoot(
root.hydrationCallbacks = hydrationCallbacks;
}

if (enableTransitionTracing) {
root.transitionCallbacks = transitionCallbacks;
}

// Cyclic construction. This cheats the type system right now because
// stateNode is any.
const uninitializedFiber = createHostRootFiber(
Expand Down
55 changes: 55 additions & 0 deletions packages/react-reconciler/src/ReactInternalTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,13 +268,68 @@ type SuspenseCallbackOnlyFiberRootProperties = {|
hydrationCallbacks: null | SuspenseHydrationCallbacks,
|};

export type TransitionTracingCallbacks = {
onTransitionStart?: (transitionName: string, startTime: number) => void,
onTransitionProgress?: (
transitionName: string,
startTime: number,
currentTime: number,
pending: Array<{name: null | string}>,
) => void,
onTransitionIncomplete?: (
transitionName: string,
startTime: number,
deletions: Array<{
type: string,
name?: string,
newName?: string,
endTime: number,
}>,
) => void,
onTransitionComplete?: (
transitionName: string,
startTime: number,
endTime: number,
) => void,
onMarkerProgress?: (
transitionName: string,
marker: string,
startTime: number,
currentTime: number,
pending: Array<{name: null | string}>,
) => void,
onMarkerIncomplete?: (
transitionName: string,
marker: string,
startTime: number,
deletions: Array<{
type: string,
name?: string,
newName?: string,
endTime: number,
}>,
) => void,
onMarkerComplete?: (
transitionName: string,
marker: string,
startTime: number,
endTime: number,
) => void,
};

// The following fields are only used in transition tracing in Profile builds
type TransitionTracingOnlyFiberRootProperties = {|
transitionCallbacks: null | TransitionTracingCallbacks,
|};

// Exported FiberRoot type includes all properties,
// To avoid requiring potentially error-prone :any casts throughout the project.
// The types are defined separately within this file to ensure they stay in sync.
export type FiberRoot = {
...BaseFiberRootProperties,
...SuspenseCallbackOnlyFiberRootProperties,
...UpdaterTrackingOnlyFiberRootProperties,
...TransitionTracingOnlyFiberRootProperties,
...
};

Expand Down
1 change: 1 addition & 0 deletions packages/react-test-renderer/src/ReactTestRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@ function create(element: React$Element<any>, options: TestRendererOptions) {
concurrentUpdatesByDefault,
'',
onRecoverableError,
null,
);

if (root == null) {
Expand Down

0 comments on commit 1fb0d06

Please sign in to comment.