Fix ReactErrorUtils injection (#9247)
Dan Abramov committed
Mar 23, 2017 at 19:13 UTC
d6a2c669d22e0bf0bc839493b863673df09c99c9
1 file changed
+64
-66
src/renderers/shared/utils/ReactErrorUtils.js
+64
-66
@@ -16,6 +16,66 @@ const invariant = require('invariant');
16
17
let caughtError = null;
18
19
+let invokeGuardedCallback = function(name, func, context, a, b, c, d, e, f) {
20
+ const funcArgs = Array.prototype.slice.call(arguments, 3);
21
+ try {
22
+ func.apply(context, funcArgs);
23
+ } catch (error) {
24
+ return error;
25
+ }
26
+ return null;
27
+};
28
+
29
+if (__DEV__) {
30
+ /**
31
+ * To help development we can get better devtools integration by simulating a
32
+ * real browser event.
33
+ */
34
+ if (
35
+ typeof window !== 'undefined' &&
36
+ typeof window.dispatchEvent === 'function' &&
37
+ typeof document !== 'undefined' &&
38
+ typeof document.createEvent === 'function'
39
+ ) {
40
+ const fakeNode = document.createElement('react');
41
+ let depth = 0;
42
+
43
+ invokeGuardedCallback = function(name, func, context, a, b, c, d, e, f) {
44
+ depth++;
45
+ const thisDepth = depth;
46
+ const funcArgs = Array.prototype.slice.call(arguments, 3);
47
+ const boundFunc = function() {
48
+ func.apply(context, funcArgs);
49
+ };
50
+ let fakeEventError = null;
51
+ const onFakeEventError = function(event) {
52
+ // Don't capture nested errors
53
+ if (depth === thisDepth) {
54
+ fakeEventError = event.error;
55
+ }
56
+ };
57
+ const evtType = `react-${name ? name : 'invokeguardedcallback'}-${depth}`;
58
+ window.addEventListener('error', onFakeEventError);
59
+ fakeNode.addEventListener(evtType, boundFunc, false);
60
+ const evt = document.createEvent('Event');
61
+ evt.initEvent(evtType, false, false);
62
+ fakeNode.dispatchEvent(evt);
63
+ fakeNode.removeEventListener(evtType, boundFunc, false);
64
+ window.removeEventListener('error', onFakeEventError);
65
+ depth--;
66
+ return fakeEventError;
67
+ };
68
+ }
69
+}
70
+
71
+let rethrowCaughtError = function() {
72
+ if (caughtError) {
73
+ const error = caughtError;
74
+ caughtError = null;
75
+ throw error;
76
+ }
77
+};
78
+
79
/**
80
* Call a function while guarding against errors that happens within it.
81
* Returns an error if it throws, otherwise null.
@@ -36,8 +96,8 @@ const ReactErrorUtils = {
96
typeof injectedErrorUtils.rethrowCaughtError === 'function',
97
'Injected rethrowCaughtError() must be a function.',
98
);
39
- ReactErrorUtils.invokeGuardedCallback = injectedErrorUtils.invokeGuardedCallback;
40
- ReactErrorUtils.rethrowCaughtError = injectedErrorUtils.rethrowCaughtError;
99
+ invokeGuardedCallback = injectedErrorUtils.invokeGuardedCallback;
100
+ rethrowCaughtError = injectedErrorUtils.rethrowCaughtError;
101
},
102
},
103
@@ -52,13 +112,7 @@ const ReactErrorUtils = {
112
e: E,
113
f: F,
114
): Error | null {
55
- const funcArgs = Array.prototype.slice.call(arguments, 3);
56
- try {
57
- func.apply(context, funcArgs);
58
- } catch (error) {
59
- return error;
60
- }
61
- return null;
115
+ return invokeGuardedCallback.apply(this, arguments);
116
},
117
118
/**
@@ -92,64 +146,8 @@ const ReactErrorUtils = {
146
* we will rethrow to be handled by the top level error handler.
147
*/
148
rethrowCaughtError: function() {
95
- if (caughtError) {
96
- const error = caughtError;
97
- caughtError = null;
98
- throw error;
99
- }
149
+ return rethrowCaughtError.apply(this, arguments);
150
},
151
};
152
103
-if (__DEV__) {
104
- /**
105
- * To help development we can get better devtools integration by simulating a
106
- * real browser event.
107
- */
108
- if (
109
- typeof window !== 'undefined' &&
110
- typeof window.dispatchEvent === 'function' &&
111
- typeof document !== 'undefined' &&
112
- typeof document.createEvent === 'function'
113
- ) {
114
- const fakeNode = document.createElement('react');
115
- let depth = 0;
116
-
117
- ReactErrorUtils.invokeGuardedCallback = function(
118
- name,
119
- func,
120
- context,
121
- a,
122
- b,
123
- c,
124
- d,
125
- e,
126
- f,
127
- ) {
128
- depth++;
129
- const thisDepth = depth;
130
- const funcArgs = Array.prototype.slice.call(arguments, 3);
131
- const boundFunc = function() {
132
- func.apply(context, funcArgs);
133
- };
134
- let fakeEventError = null;
135
- const onFakeEventError = function(event) {
136
- // Don't capture nested errors
137
- if (depth === thisDepth) {
138
- fakeEventError = event.error;
139
- }
140
- };
141
- const evtType = `react-${name ? name : 'invokeguardedcallback'}-${depth}`;
142
- window.addEventListener('error', onFakeEventError);
143
- fakeNode.addEventListener(evtType, boundFunc, false);
144
- const evt = document.createEvent('Event');
145
- evt.initEvent(evtType, false, false);
146
- fakeNode.dispatchEvent(evt);
147
- fakeNode.removeEventListener(evtType, boundFunc, false);
148
- window.removeEventListener('error', onFakeEventError);
149
- depth--;
150
- return fakeEventError;
151
- };
152
- }
153
-}
154
-
153
module.exports = ReactErrorUtils;