diff --git a/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactFiberErrorDialog.js b/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactFiberErrorDialog.js new file mode 100644 index 0000000000..121a75e183 --- /dev/null +++ b/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactFiberErrorDialog.js @@ -0,0 +1,12 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + */ + +module.exports = { + showErrorDialog: jest.fn(), +}; diff --git a/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativePrivateInterface.js b/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativePrivateInterface.js index 855a43338b..9d49212e00 100644 --- a/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativePrivateInterface.js +++ b/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativePrivateInterface.js @@ -11,15 +11,15 @@ module.exports = { get BatchedBridge() { return require('./BatchedBridge.js'); }, - get ExceptionsManager() { - return require('./ExceptionsManager'); - }, get Platform() { return require('./Platform'); }, get RCTEventEmitter() { return require('./RCTEventEmitter'); }, + get ReactFiberErrorDialog() { + return require('./ReactFiberErrorDialog'); + }, get ReactNativeViewConfigRegistry() { return require('./ReactNativeViewConfigRegistry'); }, diff --git a/packages/react-reconciler/src/forks/ReactFiberErrorDialog.native.js b/packages/react-reconciler/src/forks/ReactFiberErrorDialog.native.js index e5f0cf4db1..d31a45fc8a 100644 --- a/packages/react-reconciler/src/forks/ReactFiberErrorDialog.native.js +++ b/packages/react-reconciler/src/forks/ReactFiberErrorDialog.native.js @@ -10,41 +10,14 @@ import type {CapturedError} from '../ReactCapturedValue'; // Module provided by RN: -import {ExceptionsManager} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface'; +import {ReactFiberErrorDialog as RNImpl} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface'; +import invariant from 'shared/invariant'; + +invariant( + typeof RNImpl.showErrorDialog === 'function', + 'Expected ReactFiberErrorDialog.showErrorDialog to be a function.', +); -/** - * Intercept lifecycle errors and ensure they are shown with the correct stack - * trace within the native redbox component. - */ export function showErrorDialog(capturedError: CapturedError): boolean { - const {componentStack, error} = capturedError; - - let errorToHandle: Error; - - // Typically Errors are thrown but eg strings or null can be thrown as well. - if (error instanceof Error) { - const {message, name} = error; - - const summary = message ? `${name}: ${message}` : name; - - errorToHandle = error; - - try { - errorToHandle.message = `${summary}\n\nThis error is located at:${componentStack}`; - } catch (e) {} - } else if (typeof error === 'string') { - errorToHandle = new Error( - `${error}\n\nThis error is located at:${componentStack}`, - ); - } else { - errorToHandle = new Error(`Unspecified error at:${componentStack}`); - } - - ExceptionsManager.handleException(errorToHandle, false); - - // Return false here to prevent ReactFiberErrorLogger default behavior of - // logging error details to console.error. Calls to console.error are - // automatically routed to the native redbox controller, which we've already - // done above by calling ExceptionsManager. - return false; + return RNImpl.showErrorDialog(capturedError); } diff --git a/scripts/flow/react-native-host-hooks.js b/scripts/flow/react-native-host-hooks.js index 946f699741..f93595a7e6 100644 --- a/scripts/flow/react-native-host-hooks.js +++ b/scripts/flow/react-native-host-hooks.js @@ -17,6 +17,7 @@ import type { ViewConfigGetter, } from 'react-native-renderer/src/ReactNativeTypes'; import type {RNTopLevelEventType} from 'events/TopLevelEventTypes'; +import type {CapturedError} from 'react-reconciler/src/ReactCapturedValue'; declare module 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface' { declare export function deepDiffer(one: any, two: any): boolean; @@ -29,8 +30,8 @@ declare module 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface' blurTextInput: (object: any) => void, focusTextInput: (object: any) => void, }; - declare export var ExceptionsManager: { - handleException: (error: Error, isFatal: boolean) => void, + declare export var ReactFiberErrorDialog: { + showErrorDialog: (error: CapturedError) => boolean, }; declare export var Platform: { OS: string,