Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ReactErrorUtils injection #9247

Merged
merged 1 commit into from
Mar 23, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 64 additions & 66 deletions src/renderers/shared/utils/ReactErrorUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,66 @@ const invariant = require('invariant');

let caughtError = null;

let invokeGuardedCallback = function(name, func, context, a, b, c, d, e, f) {
const funcArgs = Array.prototype.slice.call(arguments, 3);
try {
func.apply(context, funcArgs);
} catch (error) {
return error;
}
return null;
};

if (__DEV__) {
/**
* To help development we can get better devtools integration by simulating a
* real browser event.
*/
if (
typeof window !== 'undefined' &&
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code just moved from below for clarity.

typeof window.dispatchEvent === 'function' &&
typeof document !== 'undefined' &&
typeof document.createEvent === 'function'
) {
const fakeNode = document.createElement('react');
let depth = 0;

invokeGuardedCallback = function(name, func, context, a, b, c, d, e, f) {
depth++;
const thisDepth = depth;
const funcArgs = Array.prototype.slice.call(arguments, 3);
const boundFunc = function() {
func.apply(context, funcArgs);
};
let fakeEventError = null;
const onFakeEventError = function(event) {
// Don't capture nested errors
if (depth === thisDepth) {
fakeEventError = event.error;
}
};
const evtType = `react-${name ? name : 'invokeguardedcallback'}-${depth}`;
window.addEventListener('error', onFakeEventError);
fakeNode.addEventListener(evtType, boundFunc, false);
const evt = document.createEvent('Event');
evt.initEvent(evtType, false, false);
fakeNode.dispatchEvent(evt);
fakeNode.removeEventListener(evtType, boundFunc, false);
window.removeEventListener('error', onFakeEventError);
depth--;
return fakeEventError;
};
}
}

let rethrowCaughtError = function() {
if (caughtError) {
const error = caughtError;
caughtError = null;
throw error;
}
};

/**
* Call a function while guarding against errors that happens within it.
* Returns an error if it throws, otherwise null.
Expand All @@ -36,8 +96,8 @@ const ReactErrorUtils = {
typeof injectedErrorUtils.rethrowCaughtError === 'function',
'Injected rethrowCaughtError() must be a function.',
);
ReactErrorUtils.invokeGuardedCallback = injectedErrorUtils.invokeGuardedCallback;
ReactErrorUtils.rethrowCaughtError = injectedErrorUtils.rethrowCaughtError;
invokeGuardedCallback = injectedErrorUtils.invokeGuardedCallback;
rethrowCaughtError = injectedErrorUtils.rethrowCaughtError;
},
},

Expand All @@ -52,13 +112,7 @@ const ReactErrorUtils = {
e: E,
f: F,
): Error | null {
const funcArgs = Array.prototype.slice.call(arguments, 3);
try {
func.apply(context, funcArgs);
} catch (error) {
return error;
}
return null;
return invokeGuardedCallback.apply(this, arguments);
},

/**
Expand Down Expand Up @@ -92,64 +146,8 @@ const ReactErrorUtils = {
* we will rethrow to be handled by the top level error handler.
*/
rethrowCaughtError: function() {
if (caughtError) {
const error = caughtError;
caughtError = null;
throw error;
}
return rethrowCaughtError.apply(this, arguments);
},
};

if (__DEV__) {
/**
* To help development we can get better devtools integration by simulating a
* real browser event.
*/
if (
typeof window !== 'undefined' &&
typeof window.dispatchEvent === 'function' &&
typeof document !== 'undefined' &&
typeof document.createEvent === 'function'
) {
const fakeNode = document.createElement('react');
let depth = 0;

ReactErrorUtils.invokeGuardedCallback = function(
name,
func,
context,
a,
b,
c,
d,
e,
f,
) {
depth++;
const thisDepth = depth;
const funcArgs = Array.prototype.slice.call(arguments, 3);
const boundFunc = function() {
func.apply(context, funcArgs);
};
let fakeEventError = null;
const onFakeEventError = function(event) {
// Don't capture nested errors
if (depth === thisDepth) {
fakeEventError = event.error;
}
};
const evtType = `react-${name ? name : 'invokeguardedcallback'}-${depth}`;
window.addEventListener('error', onFakeEventError);
fakeNode.addEventListener(evtType, boundFunc, false);
const evt = document.createEvent('Event');
evt.initEvent(evtType, false, false);
fakeNode.dispatchEvent(evt);
fakeNode.removeEventListener(evtType, boundFunc, false);
window.removeEventListener('error', onFakeEventError);
depth--;
return fakeEventError;
};
}
}

module.exports = ReactErrorUtils;