Skip to content

Commit

Permalink
Add support for facebook/react#9679
Browse files Browse the repository at this point in the history
  • Loading branch information
Timer committed May 13, 2017
1 parent cd9c43f commit 83e6324
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 33 deletions.
33 changes: 30 additions & 3 deletions packages/react-error-overlay/src/effects/proxyConsole.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,42 @@
/* @flow */
type ConsoleProxyCallback = (message: string) => void;

type ReactFrame = {
fileName: string | null,
lineNumber: number | null,
functionName: string | null,
};
const ReactFrameStack: Array<ReactFrame[]> = [];

export type { ReactFrame };

const registerReactStack = () => {
// $FlowFixMe
console.stack = frames => ReactFrameStack.push(frames);
// $FlowFixMe
console.stackEnd = frames => ReactFrameStack.pop();
};

const unregisterReactStack = () => {
// $FlowFixMe
console.stack = undefined;
// $FlowFixMe
console.stackEnd = undefined;
};

type ConsoleProxyCallback = (
message: string,
frames: ReactFrame[] | void
) => void;
const permanentRegister = function proxyConsole(
type: string,
callback: ConsoleProxyCallback
) {
const orig = console[type];
console[type] = function __stack_frame_overlay_proxy_console__() {
const message = [].slice.call(arguments).join(' ');
callback(message);
callback(message, ReactFrameStack[ReactFrameStack.length - 1]);
return orig.apply(this, arguments);
};
};

export { permanentRegister };
export { permanentRegister, registerReactStack, unregisterReactStack };
8 changes: 6 additions & 2 deletions packages/react-error-overlay/src/overlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import {
} from './effects/stackTraceLimit';
import {
permanentRegister as permanentRegisterConsole,
registerReactStack,
unregisterReactStack,
} from './effects/proxyConsole';
import { massage as massageWarning } from './utils/warnings';

Expand Down Expand Up @@ -213,8 +215,9 @@ function inject() {
registerShortcuts(window, shortcutHandler);
registerStackTraceLimit();

permanentRegisterConsole('error', warning => {
const data = massageWarning(warning);
registerReactStack();
permanentRegisterConsole('error', (warning, stack) => {
const data = massageWarning(warning, stack);
if (data == null) return;
crash(
// $FlowFixMe
Expand All @@ -233,6 +236,7 @@ function uninject() {
unregisterShortcuts(window);
unregisterPromise(window);
unregisterError(window);
unregisterReactStack();
}

export { inject, uninject };
52 changes: 24 additions & 28 deletions packages/react-error-overlay/src/utils/warnings.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,38 @@
// @flow
import type { ReactFrame } from '../effects/proxyConsole';

// This is a list of React warnings to display
// There must be zero or one capture group; and the capture group is assumed to be a missing stack frame.
const warnings = [
/^.*React.createElement: type is invalid.+Check your code at (.*?:.*)[.]$/,
];
// This is a list of information to remove from React warnings, it's not particularly useful to show
// This is a list of information to remove from React warnings, it's not particularly useful to show.
const removals = [/Check your code at (.*?:.*)[.]/];

function massage(warning: string): { message: string, stack: string } | null {
const nIndex = warning.indexOf('\n');
let message = warning;
if (nIndex !== -1) {
message = message.substring(0, nIndex);
}
let stack = warning.substring(nIndex + 1);

let found = false;
for (const warning of warnings) {
const m = message.match(warning);
if (!m) {
continue;
}
found = true;
if (!m[1]) {
break;
}
stack = `in (render function) (at ${m[1]})\n${stack}`;
break;
}
if (!found) {
function massage(
warning: string,
frames: ReactFrame[] | void
): { message: string, stack: string } | null {
if (!frames) {
return null;
}

let message = warning;
const nIndex = message.indexOf('\n');
if (nIndex !== -1) message = message.substring(0, nIndex);

for (const trim of removals) {
message = message.replace(trim, '');
}

let stack = '';
for (let index = 0; index < frames.length; ++index) {
const { fileName, lineNumber } = frames[index];
if (fileName == null || lineNumber == null) continue;
let { functionName } = frames[index];
if (functionName == null && index === 0 && index + 1 < frames.length) {
functionName = frames[index + 1].functionName;
if (functionName !== null) functionName = `(${functionName})`;
}
functionName = functionName || '(unknown function)';

stack += `in ${functionName} (at ${fileName}:${lineNumber})\n`;
}
return { message, stack };
}

Expand Down

0 comments on commit 83e6324

Please sign in to comment.