An error occurred while loading the file. Please try again.
-
Joe Haddad authored
* Browser sort is not stable * Fix ordering of final message * Register the warning capture * Display only createElement warnings * Use different method name * Fix regression * Ignore errors with only node_module files * Ignore null files, too * Revise count * Revise warning * Update overlay.js * Add support for https://github.com/facebook/react/pull/9679 * Use absolute paths * Trim path if it's absolute * Make sure it's an absolute path * Oops * Tweak for new behavior * Make it safer * More resilient warnings * Prettier output * Fix flow
76d2d848
/* @flow */
import {
register as registerError,
unregister as unregisterError,
} from './effects/unhandledError';
import {
register as registerPromise,
unregister as unregisterPromise,
} from './effects/unhandledRejection';
import {
register as registerShortcuts,
unregister as unregisterShortcuts,
handler as keyEventHandler,
SHORTCUT_ESCAPE,
SHORTCUT_LEFT,
SHORTCUT_RIGHT,
} from './effects/shortcuts';
import {
register as registerStackTraceLimit,
unregister as unregisterStackTraceLimit,
} from './effects/stackTraceLimit';
import {
permanentRegister as permanentRegisterConsole,
registerReactStack,
unregisterReactStack,
} from './effects/proxyConsole';
import { massage as massageWarning } from './utils/warnings';
import {
consume as consumeError,
getErrorRecord,
drain as drainErrors,
} from './utils/errorRegister';
import type { ErrorRecordReference } from './utils/errorRegister';
import type { StackFrame } from './utils/stack-frame';
import { iframeStyle } from './styles';
import { injectCss, applyStyles } from './utils/dom/css';
import { createOverlay } from './components/overlay';
import { updateAdditional } from './components/additional';
const CONTEXT_SIZE: number = 3;
let iframeReference: HTMLIFrameElement | null = null;
let additionalReference = null;
let errorReferences: ErrorRecordReference[] = [];
let currReferenceIndex: number = -1;
const css = [
'.cra-container {',
' padding-right: 15px;',
' padding-left: 15px;',
' margin-right: auto;',
' margin-left: auto;',
'}',
'',
'@media (min-width: 768px) {',
' .cra-container {',
' width: calc(750px - 6em);',
' }',
'}',
'',
'@media (min-width: 992px) {',
' .cra-container {',
' width: calc(970px - 6em);',
' }',
'}',
'',
'@media (min-width: 1200px) {',
' .cra-container {',
' width: calc(1170px - 6em);',
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
' }',
'}',
].join('\n');
function render(name: ?string, message: string, resolvedFrames: StackFrame[]) {
disposeCurrentView();
const iframe = window.document.createElement('iframe');
applyStyles(iframe, iframeStyle);
iframeReference = iframe;
iframe.onload = () => {
if (iframeReference == null) {
return;
}
const w = iframeReference.contentWindow;
const document = iframeReference.contentDocument;
const { overlay, additional } = createOverlay(
document,
name,
message,
resolvedFrames,
CONTEXT_SIZE,
currReferenceIndex + 1,
errorReferences.length,
offset => {
switchError(offset);
},
() => {
unmount();
}
);
if (w != null) {
w.onkeydown = event => {
keyEventHandler(type => shortcutHandler(type), event);
};
}
injectCss(iframeReference.contentDocument, css);
if (document.body != null) {
document.body.appendChild(overlay);
}
additionalReference = additional;
};
window.document.body.appendChild(iframe);
}
function renderErrorByIndex(index: number) {
currReferenceIndex = index;
const { error, unhandledRejection, enhancedFrames } = getErrorRecord(
errorReferences[index]
);
if (unhandledRejection) {
render(
'Unhandled Rejection (' + error.name + ')',
error.message,
enhancedFrames
);
} else {
render(error.name, error.message, enhancedFrames);
}
}
function switchError(offset) {
const nextView = currReferenceIndex + offset;
if (nextView < 0 || nextView >= errorReferences.length) {
return;
}
renderErrorByIndex(nextView);
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
}
function disposeCurrentView() {
if (iframeReference === null) {
return;
}
window.document.body.removeChild(iframeReference);
iframeReference = null;
additionalReference = null;
}
function unmount() {
disposeCurrentView();
drainErrors();
errorReferences = [];
currReferenceIndex = -1;
}
function crash(error: Error, unhandledRejection = false) {
if (module.hot && typeof module.hot.decline === 'function') {
module.hot.decline();
}
consumeError(error, unhandledRejection, CONTEXT_SIZE)
.then(ref => {
if (ref == null) {
return;
}
errorReferences.push(ref);
if (iframeReference !== null && additionalReference !== null) {
updateAdditional(
iframeReference.contentDocument,
additionalReference,
currReferenceIndex + 1,
errorReferences.length,
offset => {
switchError(offset);
}
);
} else {
if (errorReferences.length !== 1) {
throw new Error('Something is *really* wrong.');
}
renderErrorByIndex((currReferenceIndex = 0));
}
})
.catch(e => {
console.log('Could not consume error:', e);
});
}
function shortcutHandler(type: string) {
switch (type) {
case SHORTCUT_ESCAPE: {
unmount();
break;
}
case SHORTCUT_LEFT: {
switchError(-1);
break;
}
case SHORTCUT_RIGHT: {
switchError(1);
break;
}
default: {
//TODO: this
break;
}
}
}
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
function inject() {
registerError(window, error => crash(error));
registerPromise(window, error => crash(error, true));
registerShortcuts(window, shortcutHandler);
registerStackTraceLimit();
registerReactStack();
permanentRegisterConsole('error', (warning, stack) => {
const data = massageWarning(warning, stack);
crash(
// $FlowFixMe
{
message: data.message,
stack: data.stack,
__unmap_source: '/static/js/bundle.js',
},
false
);
});
}
function uninject() {
unregisterStackTraceLimit();
unregisterShortcuts(window);
unregisterPromise(window);
unregisterError(window);
unregisterReactStack();
}
export { inject, uninject };