Add plumbing for onDefaultTransitionIndicator (#33150)

This just adds the options at the root and wire it up to the root but it
doesn't do anything yet.
This commit is contained in:
Sebastian Markbåge
2025-05-08 20:42:50 -04:00
committed by GitHub
parent ac06829246
commit 9b79292ae7
18 changed files with 92 additions and 4 deletions

View File

@@ -13,7 +13,11 @@ import {
updateContainerSync,
injectIntoDevTools,
flushSyncWork,
defaultOnUncaughtError,
defaultOnCaughtError,
defaultOnRecoverableError,
} from 'react-reconciler/src/ReactFiberReconciler';
import Transform from 'art/core/transform';
import Mode from 'art/modes/current';
import FastNoSideEffects from 'art/modes/fast-noSideEffects';
@@ -21,6 +25,10 @@ import {disableLegacyMode} from 'shared/ReactFeatureFlags';
import {TYPES, childrenAsString} from './ReactARTInternals';
function defaultOnDefaultTransitionIndicator() {
// Noop
}
Mode.setCurrent(
// Change to 'art/modes/dom' for easier debugging via SVG
FastNoSideEffects,
@@ -75,6 +83,11 @@ class Surface extends React.Component {
false,
false,
'',
defaultOnUncaughtError,
defaultOnCaughtError,
defaultOnRecoverableError,
defaultOnDefaultTransitionIndicator,
null,
);
// We synchronously flush updates coming from above so that they commit together
// and so that refs resolve before the parent life cycles.

View File

@@ -16,7 +16,10 @@ import type {
import {isValidContainer} from 'react-dom-bindings/src/client/ReactDOMContainer';
import {queueExplicitHydrationTarget} from 'react-dom-bindings/src/events/ReactDOMEventReplaying';
import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';
import {disableCommentsAsDOMContainers} from 'shared/ReactFeatureFlags';
import {
disableCommentsAsDOMContainers,
enableDefaultTransitionIndicator,
} from 'shared/ReactFeatureFlags';
export type RootType = {
render(children: ReactNodeList): void,
@@ -43,6 +46,7 @@ export type CreateRootOptions = {
error: mixed,
errorInfo: {+componentStack?: ?string},
) => void,
onDefaultTransitionIndicator?: () => void | (() => void),
};
export type HydrateRootOptions = {
@@ -68,6 +72,7 @@ export type HydrateRootOptions = {
error: mixed,
errorInfo: {+componentStack?: ?string},
) => void,
onDefaultTransitionIndicator?: () => void | (() => void),
formState?: ReactFormState<any, any> | null,
};
@@ -92,6 +97,11 @@ import {
} from 'react-reconciler/src/ReactFiberReconciler';
import {ConcurrentRoot} from 'react-reconciler/src/ReactRootTags';
function defaultOnDefaultTransitionIndicator(): void | (() => void) {
// TODO: Implement the default
return function () {};
}
// $FlowFixMe[missing-this-annot]
function ReactDOMRoot(internalRoot: FiberRoot) {
this._internalRoot = internalRoot;
@@ -178,6 +188,7 @@ export function createRoot(
let onUncaughtError = defaultOnUncaughtError;
let onCaughtError = defaultOnCaughtError;
let onRecoverableError = defaultOnRecoverableError;
let onDefaultTransitionIndicator = defaultOnDefaultTransitionIndicator;
let transitionCallbacks = null;
if (options !== null && options !== undefined) {
@@ -217,6 +228,11 @@ export function createRoot(
if (options.onRecoverableError !== undefined) {
onRecoverableError = options.onRecoverableError;
}
if (enableDefaultTransitionIndicator) {
if (options.onDefaultTransitionIndicator !== undefined) {
onDefaultTransitionIndicator = options.onDefaultTransitionIndicator;
}
}
if (options.unstable_transitionCallbacks !== undefined) {
transitionCallbacks = options.unstable_transitionCallbacks;
}
@@ -232,6 +248,7 @@ export function createRoot(
onUncaughtError,
onCaughtError,
onRecoverableError,
onDefaultTransitionIndicator,
transitionCallbacks,
);
markContainerAsRoot(root.current, container);
@@ -288,6 +305,7 @@ export function hydrateRoot(
let onUncaughtError = defaultOnUncaughtError;
let onCaughtError = defaultOnCaughtError;
let onRecoverableError = defaultOnRecoverableError;
let onDefaultTransitionIndicator = defaultOnDefaultTransitionIndicator;
let transitionCallbacks = null;
let formState = null;
if (options !== null && options !== undefined) {
@@ -306,6 +324,11 @@ export function hydrateRoot(
if (options.onRecoverableError !== undefined) {
onRecoverableError = options.onRecoverableError;
}
if (enableDefaultTransitionIndicator) {
if (options.onDefaultTransitionIndicator !== undefined) {
onDefaultTransitionIndicator = options.onDefaultTransitionIndicator;
}
}
if (options.unstable_transitionCallbacks !== undefined) {
transitionCallbacks = options.unstable_transitionCallbacks;
}
@@ -326,6 +349,7 @@ export function hydrateRoot(
onUncaughtError,
onCaughtError,
onRecoverableError,
onDefaultTransitionIndicator,
transitionCallbacks,
formState,
);

View File

@@ -211,6 +211,10 @@ function noopOnRecoverableError() {
// legacy API.
}
function noopOnDefaultTransitionIndicator() {
// Noop
}
function legacyCreateRootFromDOMContainer(
container: Container,
initialChildren: ReactNodeList,
@@ -239,6 +243,7 @@ function legacyCreateRootFromDOMContainer(
wwwOnUncaughtError,
wwwOnCaughtError,
noopOnRecoverableError,
noopOnDefaultTransitionIndicator,
// TODO(luna) Support hydration later
null,
null,
@@ -277,6 +282,7 @@ function legacyCreateRootFromDOMContainer(
wwwOnUncaughtError,
wwwOnCaughtError,
noopOnRecoverableError,
noopOnDefaultTransitionIndicator,
null, // transitionCallbacks
);
container._reactRootContainer = root;

View File

@@ -98,6 +98,9 @@ function nativeOnCaughtError(
defaultOnCaughtError(error, errorInfo);
}
function nativeOnDefaultTransitionIndicator(): void | (() => void) {
// Native doesn't have a default indicator.
}
function render(
element: Element<ElementType>,
@@ -148,6 +151,7 @@ function render(
onUncaughtError,
onCaughtError,
onRecoverableError,
nativeOnDefaultTransitionIndicator,
null,
);

View File

@@ -113,6 +113,9 @@ function nativeOnCaughtError(
defaultOnCaughtError(error, errorInfo);
}
function nativeOnDefaultTransitionIndicator(): void | (() => void) {
// Native doesn't have a default indicator.
}
function render(
element: MixedElement,
@@ -162,6 +165,7 @@ function render(
onUncaughtError,
onCaughtError,
onRecoverableError,
nativeOnDefaultTransitionIndicator,
null,
);
roots.set(containerTag, root);

View File

@@ -80,6 +80,7 @@ type CreateRootOptions = {
unstable_transitionCallbacks?: TransitionTracingCallbacks,
onUncaughtError?: (error: mixed, errorInfo: {componentStack: string}) => void,
onCaughtError?: (error: mixed, errorInfo: {componentStack: string}) => void,
onDefaultTransitionIndicator?: () => void | (() => void),
...
};
type InstanceMeasurement = null;
@@ -1141,6 +1142,9 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
// TODO: Turn this on once tests are fixed
// console.error(error);
}
function onDefaultTransitionIndicator(): void | (() => void) {
// TODO: Allow this as an option.
}
let idCounter = 0;
@@ -1196,6 +1200,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
NoopRenderer.defaultOnUncaughtError,
NoopRenderer.defaultOnCaughtError,
onRecoverableError,
onDefaultTransitionIndicator,
null,
);
roots.set(rootID, root);
@@ -1224,6 +1229,9 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
? options.onCaughtError
: NoopRenderer.defaultOnCaughtError,
onRecoverableError,
options && options.onDefaultTransitionIndicator
? options.onDefaultTransitionIndicator
: onDefaultTransitionIndicator,
options && options.unstable_transitionCallbacks
? options.unstable_transitionCallbacks
: null,
@@ -1262,6 +1270,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
NoopRenderer.defaultOnUncaughtError,
NoopRenderer.defaultOnCaughtError,
onRecoverableError,
onDefaultTransitionIndicator,
null,
);
return {

View File

@@ -254,6 +254,7 @@ export function createContainer(
error: mixed,
errorInfo: {+componentStack?: ?string},
) => void,
onDefaultTransitionIndicator: () => void | (() => void),
transitionCallbacks: null | TransitionTracingCallbacks,
): OpaqueRoot {
const hydrate = false;
@@ -266,11 +267,12 @@ export function createContainer(
hydrationCallbacks,
isStrictMode,
identifierPrefix,
null,
onUncaughtError,
onCaughtError,
onRecoverableError,
onDefaultTransitionIndicator,
transitionCallbacks,
null,
);
}
@@ -300,6 +302,7 @@ export function createHydrationContainer(
error: mixed,
errorInfo: {+componentStack?: ?string},
) => void,
onDefaultTransitionIndicator: () => void | (() => void),
transitionCallbacks: null | TransitionTracingCallbacks,
formState: ReactFormState<any, any> | null,
): OpaqueRoot {
@@ -312,11 +315,12 @@ export function createHydrationContainer(
hydrationCallbacks,
isStrictMode,
identifierPrefix,
formState,
onUncaughtError,
onCaughtError,
onRecoverableError,
onDefaultTransitionIndicator,
transitionCallbacks,
formState,
);
// TODO: Move this to FiberRoot constructor

View File

@@ -35,6 +35,7 @@ import {
disableLegacyMode,
enableViewTransition,
enableGestureTransition,
enableDefaultTransitionIndicator,
} from 'shared/ReactFeatureFlags';
import {initializeUpdateQueue} from './ReactFiberClassUpdateQueue';
import {LegacyRoot, ConcurrentRoot} from './ReactRootTags';
@@ -56,6 +57,7 @@ function FiberRootNode(
onUncaughtError: any,
onCaughtError: any,
onRecoverableError: any,
onDefaultTransitionIndicator: any,
formState: ReactFormState<any, any> | null,
) {
this.tag = disableLegacyMode ? ConcurrentRoot : tag;
@@ -90,6 +92,10 @@ function FiberRootNode(
this.onCaughtError = onCaughtError;
this.onRecoverableError = onRecoverableError;
if (enableDefaultTransitionIndicator) {
this.onDefaultTransitionIndicator = onDefaultTransitionIndicator;
}
this.pooledCache = null;
this.pooledCacheLanes = NoLanes;
@@ -157,6 +163,7 @@ export function createFiberRoot(
// them through the root constructor. Perhaps we should put them all into a
// single type, like a DynamicHostConfig that is defined by the renderer.
identifierPrefix: string,
formState: ReactFormState<any, any> | null,
onUncaughtError: (
error: mixed,
errorInfo: {+componentStack?: ?string},
@@ -172,8 +179,8 @@ export function createFiberRoot(
error: mixed,
errorInfo: {+componentStack?: ?string},
) => void,
onDefaultTransitionIndicator: () => void | (() => void),
transitionCallbacks: null | TransitionTracingCallbacks,
formState: ReactFormState<any, any> | null,
): FiberRoot {
// $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
const root: FiberRoot = (new FiberRootNode(
@@ -184,6 +191,7 @@ export function createFiberRoot(
onUncaughtError,
onCaughtError,
onRecoverableError,
onDefaultTransitionIndicator,
formState,
): any);
if (enableSuspenseCallback) {

View File

@@ -280,6 +280,8 @@ type BaseFiberRootProperties = {
errorInfo: {+componentStack?: ?string},
) => void,
onDefaultTransitionIndicator: () => void | (() => void),
formState: ReactFormState<any, any> | null,
// enableViewTransition only

View File

@@ -60,6 +60,10 @@ import {
disableLegacyMode,
} from 'shared/ReactFeatureFlags';
function defaultOnDefaultTransitionIndicator(): void | (() => void) {
// Noop
}
// $FlowFixMe[prop-missing]: This is only in the development export.
const act = React.act;
@@ -515,6 +519,7 @@ function create(
defaultOnUncaughtError,
defaultOnCaughtError,
defaultOnRecoverableError,
defaultOnDefaultTransitionIndicator,
null,
);

View File

@@ -98,6 +98,7 @@ describe('ReactTestRenderer', () => {
expect.anything(),
expect.anything(),
expect.anything(),
expect.anything(),
null,
);
}

View File

@@ -102,6 +102,8 @@ export const enableSrcObject = __EXPERIMENTAL__;
export const enableHydrationChangeEvent = __EXPERIMENTAL__;
export const enableDefaultTransitionIndicator = __EXPERIMENTAL__;
/**
* Switches Fiber creation to a simple object instead of a constructor.
*/

View File

@@ -85,6 +85,7 @@ export const enableScrollEndPolyfill = true;
export const enableSuspenseyImages = false;
export const enableSrcObject = false;
export const enableHydrationChangeEvent = true;
export const enableDefaultTransitionIndicator = false;
export const ownerStackLimit = 1e4;
// Flow magic to verify the exports of this file match the original version.

View File

@@ -76,6 +76,7 @@ export const enableScrollEndPolyfill = true;
export const enableSuspenseyImages = false;
export const enableSrcObject = false;
export const enableHydrationChangeEvent = false;
export const enableDefaultTransitionIndicator = false;
export const ownerStackLimit = 1e4;
export const enableFragmentRefs = false;

View File

@@ -75,6 +75,7 @@ export const enableScrollEndPolyfill = true;
export const enableSuspenseyImages = false;
export const enableSrcObject = false;
export const enableHydrationChangeEvent = false;
export const enableDefaultTransitionIndicator = false;
export const ownerStackLimit = 1e4;
export const enableFragmentRefs = false;

View File

@@ -72,6 +72,7 @@ export const enableScrollEndPolyfill = true;
export const enableSuspenseyImages = false;
export const enableSrcObject = false;
export const enableHydrationChangeEvent = false;
export const enableDefaultTransitionIndicator = false;
export const enableFragmentRefs = false;
export const ownerStackLimit = 1e4;

View File

@@ -86,6 +86,7 @@ export const enableScrollEndPolyfill = true;
export const enableSuspenseyImages = false;
export const enableSrcObject = false;
export const enableHydrationChangeEvent = false;
export const enableDefaultTransitionIndicator = false;
export const enableFragmentRefs = false;
export const ownerStackLimit = 1e4;

View File

@@ -115,6 +115,7 @@ export const enableGestureTransition = false;
export const enableSuspenseyImages = false;
export const enableSrcObject = false;
export const enableHydrationChangeEvent = false;
export const enableDefaultTransitionIndicator = false;
export const ownerStackLimit = 1e4;