Skip to content

Commit

Permalink
Make onCaughtError and onUncaughtError configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
sebmarkbage committed Mar 26, 2024
1 parent d1ea74f commit d597ebd
Show file tree
Hide file tree
Showing 15 changed files with 527 additions and 146 deletions.
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 @@ -33,7 +33,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 @@ -45,7 +59,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 @@ -68,15 +96,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 @@ -157,6 +182,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 @@ -194,6 +221,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 @@ -209,6 +242,8 @@ export function createRoot(
isStrictMode,
concurrentUpdatesByDefaultOverride,
identifierPrefix,
onUncaughtError,
onCaughtError,
onRecoverableError,
transitionCallbacks,
);
Expand Down Expand Up @@ -263,6 +298,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 @@ -279,6 +316,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 @@ -301,6 +344,8 @@ export function hydrateRoot(
isStrictMode,
concurrentUpdatesByDefaultOverride,
identifierPrefix,
onUncaughtError,
onCaughtError,
onRecoverableError,
transitionCallbacks,
formState,
Expand Down
14 changes: 6 additions & 8 deletions packages/react-native-renderer/src/ReactFabric.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import {
updateContainer,
injectIntoDevTools,
getPublicRootInstance,
defaultOnUncaughtError,
defaultOnCaughtError,
defaultOnRecoverableError,
} from 'react-reconciler/src/ReactFiberReconciler';

import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal';
Expand All @@ -43,13 +46,6 @@ import {
} from './ReactNativePublicCompat';
import {getPublicInstanceFromInternalInstanceHandle} from './ReactFiberConfigFabric';

// $FlowFixMe[missing-local-annot]
function onRecoverableError(error) {
// TODO: Expose onRecoverableError option to userspace
// eslint-disable-next-line react-internal/no-production-logging, react-internal/warning-args
console.error(error);
}

function render(
element: Element<ElementType>,
containerTag: number,
Expand All @@ -68,7 +64,9 @@ function render(
false,
null,
'',
onRecoverableError,
defaultOnUncaughtError,
defaultOnCaughtError,
defaultOnRecoverableError,
null,
);
roots.set(containerTag, root);
Expand Down
14 changes: 6 additions & 8 deletions packages/react-native-renderer/src/ReactNativeRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import {
updateContainer,
injectIntoDevTools,
getPublicRootInstance,
defaultOnUncaughtError,
defaultOnCaughtError,
defaultOnRecoverableError,
} from 'react-reconciler/src/ReactFiberReconciler';
// TODO: direct imports like some-package/src/* are bad. Fix me.
import {getStackByFiberInDevAndProd} from 'react-reconciler/src/ReactFiberComponentStack';
Expand Down Expand Up @@ -47,13 +50,6 @@ import {
isChildPublicInstance,
} from './ReactNativePublicCompat';

// $FlowFixMe[missing-local-annot]
function onRecoverableError(error) {
// TODO: Expose onRecoverableError option to userspace
// eslint-disable-next-line react-internal/no-production-logging, react-internal/warning-args
console.error(error);
}

function render(
element: Element<ElementType>,
containerTag: number,
Expand All @@ -71,7 +67,9 @@ function render(
false,
null,
'',
onRecoverableError,
defaultOnUncaughtError,
defaultOnCaughtError,
defaultOnRecoverableError,
null,
);
roots.set(containerTag, root);
Expand Down
6 changes: 6 additions & 0 deletions packages/react-noop-renderer/src/createReactNoop.js
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,8 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
null,
false,
'',
NoopRenderer.defaultOnUncaughtError,
NoopRenderer.defaultOnCaughtError,
onRecoverableError,
null,
);
Expand All @@ -996,6 +998,8 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
null,
false,
'',
NoopRenderer.defaultOnUncaughtError,
NoopRenderer.defaultOnCaughtError,
onRecoverableError,
options && options.unstable_transitionCallbacks
? options.unstable_transitionCallbacks
Expand Down Expand Up @@ -1028,6 +1032,8 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
null,
false,
'',
NoopRenderer.defaultOnUncaughtError,
NoopRenderer.defaultOnCaughtError,
onRecoverableError,
null,
);
Expand Down
8 changes: 3 additions & 5 deletions packages/react-reconciler/src/ReactFiberErrorDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,14 @@
* @flow
*/

import type {Fiber} from './ReactInternalTypes';
import type {CapturedValue} from './ReactCapturedValue';

// This module is forked in different environments.
// By default, return `true` to log errors to the console.
// Forks can return `false` if this isn't desirable.

export function showErrorDialog(
boundary: null | Fiber,
errorInfo: CapturedValue<mixed>,
errorBoundary: ?React$Component<any, any>,
error: mixed,
componentStack: string,
): boolean {
return true;
}
Loading

0 comments on commit d597ebd

Please sign in to comment.