Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make onUncaughtError and onCaughtError Configurable #28641

Merged
merged 7 commits into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions packages/react-dom/index.classic.fb.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,8 @@ Object.assign((Internals: any), {

export {
createPortal,
createRoot,
hydrateRoot,
findDOMNode,
flushSync,
render,
unmountComponentAtNode,
unstable_batchedUpdates,
unstable_createEventHandle,
Expand All @@ -41,4 +38,6 @@ export {
version,
} from './src/client/ReactDOM';

export {createRoot, hydrateRoot, render} from './src/client/ReactDOMRootFB';

export {Internals as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED};
4 changes: 2 additions & 2 deletions packages/react-dom/index.modern.fb.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
export {default as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED} from './src/ReactDOMSharedInternals';
export {
createPortal,
createRoot,
hydrateRoot,
flushSync,
unstable_batchedUpdates,
unstable_createEventHandle,
Expand All @@ -26,3 +24,5 @@ export {
preinitModule,
version,
} from './src/client/ReactDOM';

export {createRoot, hydrateRoot} from './src/client/ReactDOMRootFB';
2 changes: 2 additions & 0 deletions packages/react-dom/src/__tests__/ReactDOMRoot-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ describe('ReactDOMRoot', () => {
expect(container.textContent).toEqual('Hi');
});

// @gate !classic || !__DEV__
it('warns if you import createRoot from react-dom', async () => {
expect(() => ReactDOM.createRoot(container)).toErrorDev(
'You are importing createRoot from "react-dom" which is not supported. ' +
Expand All @@ -57,6 +58,7 @@ describe('ReactDOMRoot', () => {
);
});

// @gate !classic || !__DEV__
it('warns if you import hydrateRoot from react-dom', async () => {
expect(() => ReactDOM.hydrateRoot(container, null)).toErrorDev(
'You are importing hydrateRoot from "react-dom" which is not supported. ' +
Expand Down
8 changes: 7 additions & 1 deletion packages/react-dom/src/client/ReactDOMLegacy.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import {
getPublicRootInstance,
findHostInstance,
findHostInstanceWithWarning,
defaultOnUncaughtError,
defaultOnCaughtError,
} from 'react-reconciler/src/ReactFiberReconciler';
import {LegacyRoot} from 'react-reconciler/src/ReactRootTags';
import getComponentNameFromType from 'shared/getComponentNameFromType';
Expand Down Expand Up @@ -124,6 +126,8 @@ function legacyCreateRootFromDOMContainer(
false, // isStrictMode
false, // concurrentUpdatesByDefaultOverride,
'', // identifierPrefix
defaultOnUncaughtError,
defaultOnCaughtError,
noopOnRecoverableError,
// TODO(luna) Support hydration later
null,
Expand Down Expand Up @@ -158,7 +162,9 @@ function legacyCreateRootFromDOMContainer(
false, // isStrictMode
false, // concurrentUpdatesByDefaultOverride,
'', // identifierPrefix
noopOnRecoverableError, // onRecoverableError
defaultOnUncaughtError,
defaultOnCaughtError,
noopOnRecoverableError,
null, // transitionCallbacks
);
container._reactRootContainer = root;
Expand Down
61 changes: 53 additions & 8 deletions packages/react-dom/src/client/ReactDOMRoot.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,21 @@ export type CreateRootOptions = {
unstable_concurrentUpdatesByDefault?: boolean,
unstable_transitionCallbacks?: TransitionTracingCallbacks,
identifierPrefix?: string,
onRecoverableError?: (error: mixed) => void,
onUncaughtError?: (
error: mixed,
errorInfo: {+componentStack?: ?string},
) => void,
onCaughtError?: (
error: mixed,
errorInfo: {
+componentStack?: ?string,
+errorBoundary?: ?React$Component<any, any>,
},
) => void,
onRecoverableError?: (
error: mixed,
errorInfo: {+digest?: ?string, +componentStack?: ?string},
) => void,
};

export type HydrateRootOptions = {
Expand All @@ -44,7 +58,21 @@ export type HydrateRootOptions = {
unstable_concurrentUpdatesByDefault?: boolean,
unstable_transitionCallbacks?: TransitionTracingCallbacks,
identifierPrefix?: string,
onRecoverableError?: (error: mixed) => void,
onUncaughtError?: (
error: mixed,
errorInfo: {+componentStack?: ?string},
) => void,
onCaughtError?: (
error: mixed,
errorInfo: {
+componentStack?: ?string,
+errorBoundary?: ?React$Component<any, any>,
},
) => void,
onRecoverableError?: (
error: mixed,
errorInfo: {+digest?: ?string, +componentStack?: ?string},
) => void,
formState?: ReactFormState<any, any> | null,
};

Expand All @@ -67,15 +95,12 @@ import {
updateContainer,
flushSync,
isAlreadyRendering,
defaultOnUncaughtError,
defaultOnCaughtError,
defaultOnRecoverableError,
} from 'react-reconciler/src/ReactFiberReconciler';
import {ConcurrentRoot} from 'react-reconciler/src/ReactRootTags';

import reportGlobalError from 'shared/reportGlobalError';

function defaultOnRecoverableError(error: mixed, errorInfo: any) {
reportGlobalError(error);
}

// $FlowFixMe[missing-this-annot]
function ReactDOMRoot(internalRoot: FiberRoot) {
this._internalRoot = internalRoot;
Expand Down Expand Up @@ -156,6 +181,8 @@ export function createRoot(
let isStrictMode = false;
let concurrentUpdatesByDefaultOverride = false;
let identifierPrefix = '';
let onUncaughtError = defaultOnUncaughtError;
let onCaughtError = defaultOnCaughtError;
let onRecoverableError = defaultOnRecoverableError;
let transitionCallbacks = null;

Expand Down Expand Up @@ -193,6 +220,12 @@ export function createRoot(
if (options.identifierPrefix !== undefined) {
identifierPrefix = options.identifierPrefix;
}
if (options.onUncaughtError !== undefined) {
onUncaughtError = options.onUncaughtError;
}
if (options.onCaughtError !== undefined) {
onCaughtError = options.onCaughtError;
}
if (options.onRecoverableError !== undefined) {
onRecoverableError = options.onRecoverableError;
}
Expand All @@ -208,6 +241,8 @@ export function createRoot(
isStrictMode,
concurrentUpdatesByDefaultOverride,
identifierPrefix,
onUncaughtError,
onCaughtError,
onRecoverableError,
transitionCallbacks,
);
Expand Down Expand Up @@ -262,6 +297,8 @@ export function hydrateRoot(
let isStrictMode = false;
let concurrentUpdatesByDefaultOverride = false;
let identifierPrefix = '';
let onUncaughtError = defaultOnUncaughtError;
let onCaughtError = defaultOnCaughtError;
let onRecoverableError = defaultOnRecoverableError;
let transitionCallbacks = null;
let formState = null;
Expand All @@ -278,6 +315,12 @@ export function hydrateRoot(
if (options.identifierPrefix !== undefined) {
identifierPrefix = options.identifierPrefix;
}
if (options.onUncaughtError !== undefined) {
onUncaughtError = options.onUncaughtError;
}
if (options.onCaughtError !== undefined) {
onCaughtError = options.onCaughtError;
}
if (options.onRecoverableError !== undefined) {
onRecoverableError = options.onRecoverableError;
}
Expand All @@ -300,6 +343,8 @@ export function hydrateRoot(
isStrictMode,
concurrentUpdatesByDefaultOverride,
identifierPrefix,
onUncaughtError,
onCaughtError,
onRecoverableError,
transitionCallbacks,
formState,
Expand Down
Loading