diff --git a/packages/react-art/src/ReactART.js b/packages/react-art/src/ReactART.js index d0d747396b979..f6756ba633e6d 100644 --- a/packages/react-art/src/ReactART.js +++ b/packages/react-art/src/ReactART.js @@ -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. diff --git a/packages/react-dom/src/client/ReactDOMRoot.js b/packages/react-dom/src/client/ReactDOMRoot.js index 940f0d4f3b124..ef2c9ddf193eb 100644 --- a/packages/react-dom/src/client/ReactDOMRoot.js +++ b/packages/react-dom/src/client/ReactDOMRoot.js @@ -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 | 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, ); diff --git a/packages/react-dom/src/client/ReactDOMRootFB.js b/packages/react-dom/src/client/ReactDOMRootFB.js index f2368c8cc4fa6..c3c519650239c 100644 --- a/packages/react-dom/src/client/ReactDOMRootFB.js +++ b/packages/react-dom/src/client/ReactDOMRootFB.js @@ -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; diff --git a/packages/react-native-renderer/src/ReactFabric.js b/packages/react-native-renderer/src/ReactFabric.js index d2f83d801aeac..3f77085c6882a 100644 --- a/packages/react-native-renderer/src/ReactFabric.js +++ b/packages/react-native-renderer/src/ReactFabric.js @@ -98,6 +98,9 @@ function nativeOnCaughtError( defaultOnCaughtError(error, errorInfo); } +function nativeOnDefaultTransitionIndicator(): void | (() => void) { + // Native doesn't have a default indicator. +} function render( element: Element, @@ -148,6 +151,7 @@ function render( onUncaughtError, onCaughtError, onRecoverableError, + nativeOnDefaultTransitionIndicator, null, ); diff --git a/packages/react-native-renderer/src/ReactNativeRenderer.js b/packages/react-native-renderer/src/ReactNativeRenderer.js index 035a9b3d45e54..8f26bfc314d95 100644 --- a/packages/react-native-renderer/src/ReactNativeRenderer.js +++ b/packages/react-native-renderer/src/ReactNativeRenderer.js @@ -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); diff --git a/packages/react-noop-renderer/src/createReactNoop.js b/packages/react-noop-renderer/src/createReactNoop.js index fc3c2fd3cde24..dd5173cd83720 100644 --- a/packages/react-noop-renderer/src/createReactNoop.js +++ b/packages/react-noop-renderer/src/createReactNoop.js @@ -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 { diff --git a/packages/react-reconciler/src/ReactFiberReconciler.js b/packages/react-reconciler/src/ReactFiberReconciler.js index bcc2500a320c7..dbba2329cfc54 100644 --- a/packages/react-reconciler/src/ReactFiberReconciler.js +++ b/packages/react-reconciler/src/ReactFiberReconciler.js @@ -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 | 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 diff --git a/packages/react-reconciler/src/ReactFiberRoot.js b/packages/react-reconciler/src/ReactFiberRoot.js index fe88b956267e7..cc2a528010e77 100644 --- a/packages/react-reconciler/src/ReactFiberRoot.js +++ b/packages/react-reconciler/src/ReactFiberRoot.js @@ -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 | 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 | 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 | 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) { diff --git a/packages/react-reconciler/src/ReactInternalTypes.js b/packages/react-reconciler/src/ReactInternalTypes.js index d083d189b3e5d..b364d4ec47abb 100644 --- a/packages/react-reconciler/src/ReactInternalTypes.js +++ b/packages/react-reconciler/src/ReactInternalTypes.js @@ -280,6 +280,8 @@ type BaseFiberRootProperties = { errorInfo: {+componentStack?: ?string}, ) => void, + onDefaultTransitionIndicator: () => void | (() => void), + formState: ReactFormState | null, // enableViewTransition only diff --git a/packages/react-test-renderer/src/ReactTestRenderer.js b/packages/react-test-renderer/src/ReactTestRenderer.js index 7d0561790b33f..b096f59292ceb 100644 --- a/packages/react-test-renderer/src/ReactTestRenderer.js +++ b/packages/react-test-renderer/src/ReactTestRenderer.js @@ -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, ); diff --git a/packages/react-test-renderer/src/__tests__/ReactTestRenderer-test.internal.js b/packages/react-test-renderer/src/__tests__/ReactTestRenderer-test.internal.js index 551c10fb5f3df..62bef5353eaba 100644 --- a/packages/react-test-renderer/src/__tests__/ReactTestRenderer-test.internal.js +++ b/packages/react-test-renderer/src/__tests__/ReactTestRenderer-test.internal.js @@ -98,6 +98,7 @@ describe('ReactTestRenderer', () => { expect.anything(), expect.anything(), expect.anything(), + expect.anything(), null, ); } diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index 9b0e0354e7ecb..142d1a2d2764e 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -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. */ diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js index bb867acdd87fe..0234e597e3182 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js @@ -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. diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js index b783f37d3dce7..65fe40ebaea95 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-oss.js +++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js @@ -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; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js index 5e0e229e03eee..5a9704108092a 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js @@ -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; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js index 6a93f47c688dd..980c0cdea9b62 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js @@ -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; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js index 205baff50b343..0ffb689e3bf5f 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js @@ -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; diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js index 7aed5a6ad3c08..bb5f09767df36 100644 --- a/packages/shared/forks/ReactFeatureFlags.www.js +++ b/packages/shared/forks/ReactFeatureFlags.www.js @@ -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;