diff --git a/packages/react-error-overlay/src/index.js b/packages/react-error-overlay/src/index.js index 86b82a853fe..e8fbbb0dfad 100644 --- a/packages/react-error-overlay/src/index.js +++ b/packages/react-error-overlay/src/index.js @@ -6,7 +6,10 @@ */ /* @flow */ -import { listenToRuntimeErrors } from './listenToRuntimeErrors'; +import { + listenToRuntimeErrors, + crashWithFrames, +} from './listenToRuntimeErrors'; import { iframeStyle } from './styles'; import { applyStyles } from './utils/dom/css'; @@ -47,6 +50,14 @@ export function reportBuildError(error: string) { update(); } +export function reportRuntimeError( + error: Error, + options?: RuntimeReportingOption = {} +) { + currentRuntimeErrorOptions = options; + crashWithFrames(handleRuntimeError(options))(error); +} + export function dismissBuildError() { currentBuildError = null; update(); @@ -64,28 +75,35 @@ export function startReportingRuntimeErrors(options: RuntimeReportingOptions) { ); } currentRuntimeErrorOptions = options; - stopListeningToRuntimeErrors = listenToRuntimeErrors(errorRecord => { - try { - if (typeof options.onError === 'function') { - options.onError.call(null); - } - } finally { - handleRuntimeError(errorRecord); - } - }, options.filename); + stopListeningToRuntimeErrors = listenToRuntimeErrors( + handleRuntimeError(options), + options.filename + ); } -function handleRuntimeError(errorRecord) { - if ( - currentRuntimeErrorRecords.some(({ error }) => error === errorRecord.error) - ) { - // Deduplicate identical errors. - // This fixes https://github.com/facebook/create-react-app/issues/3011. - return; +const handleRuntimeError = (options: RuntimeReportingOptions) => ( + errorRecord: ErrorRecord +) => { + try { + if (typeof options.onError === 'function') { + options.onError.call(null); + } + } finally { + if ( + currentRuntimeErrorRecords.some( + ({ error }) => error === errorRecord.error + ) + ) { + // Deduplicate identical errors. + // This fixes https://github.com/facebook/create-react-app/issues/3011. + return; + } + currentRuntimeErrorRecords = currentRuntimeErrorRecords.concat([ + errorRecord, + ]); + update(); } - currentRuntimeErrorRecords = currentRuntimeErrorRecords.concat([errorRecord]); - update(); -} +}; export function dismissRuntimeErrors() { currentRuntimeErrorRecords = []; diff --git a/packages/react-error-overlay/src/listenToRuntimeErrors.js b/packages/react-error-overlay/src/listenToRuntimeErrors.js index 8146b377c15..670dbb0f8e4 100644 --- a/packages/react-error-overlay/src/listenToRuntimeErrors.js +++ b/packages/react-error-overlay/src/listenToRuntimeErrors.js @@ -37,34 +37,40 @@ export type ErrorRecord = {| stackFrames: StackFrame[], |}; +export const crashWithFrames = (crash: ErrorRecord => void) => ( + error: Error, + unhandledRejection = false +) => { + getStackFrames(error, unhandledRejection, CONTEXT_SIZE) + .then(stackFrames => { + if (stackFrames == null) { + return; + } + crash({ + error, + unhandledRejection, + contextSize: CONTEXT_SIZE, + stackFrames, + }); + }) + .catch(e => { + console.log('Could not get the stack frames of error:', e); + }); +}; + export function listenToRuntimeErrors( crash: ErrorRecord => void, filename: string = '/static/js/bundle.js' ) { - function crashWithFrames(error: Error, unhandledRejection = false) { - getStackFrames(error, unhandledRejection, CONTEXT_SIZE) - .then(stackFrames => { - if (stackFrames == null) { - return; - } - crash({ - error, - unhandledRejection, - contextSize: CONTEXT_SIZE, - stackFrames, - }); - }) - .catch(e => { - console.log('Could not get the stack frames of error:', e); - }); - } - registerError(window, error => crashWithFrames(error, false)); - registerPromise(window, error => crashWithFrames(error, true)); + const crashWithFramesRunTime = crashWithFrames(crash); + + registerError(window, error => crashWithFramesRunTime(error, false)); + registerPromise(window, error => crashWithFramesRunTime(error, true)); registerStackTraceLimit(); registerReactStack(); permanentRegisterConsole('error', (warning, stack) => { const data = massageWarning(warning, stack); - crashWithFrames( + crashWithFramesRunTime( // $FlowFixMe { message: data.message,