36
if (enableComponentStackLocations) {
37
if (prefix === undefined) {
38
// Extract the VM specific prefix used by each line.
39
- const match = Error()
40
- .stack.trim()
41
- .match(/\n( *(at )?)/);
42
- prefix = (match && match[1]) || '';
39
+ try {
40
+ throw Error();
41
+ } catch (x) {
42
+ const match = x.stack.trim().match(/\n( *(at )?)/);
43
+ prefix = (match && match[1]) || '';
44
+ }
45
}
46
// We use the prefix to ensure our stacks line up with native stack frames.
47
return '\n' + prefix + name;
77
}
78
}
79
78
- const control = Error();
80
+ let control;
81
82
reentry = true;
83
let previousDispatcher;
92
// This should throw.
93
if (construct) {
94
// Something should be setting the props in the constructor.
93
- const Fake = function() {};
95
+ const Fake = function() {
96
+ throw Error();
97
+ };
98
// $FlowFixMe
99
Object.defineProperty(Fake.prototype, 'props', {
100
set: function() {
104
},
105
});
106
if (typeof Reflect === 'object' && Reflect.construct) {
107
+ // We construct a different control for this case to include any extra
108
+ // frames added by the construct call.
109
+ try {
110
+ Reflect.construct(Fake, []);
111
+ } catch (x) {
112
+ control = x;
113
+ }
114
Reflect.construct(fn, [], Fake);
115
} else {
105
- fn.call(new Fake());
116
+ try {
117
+ Fake.call();
118
+ } catch (x) {
119
+ control = x;
120
+ }
121
+ fn.call(Fake.prototype);
122
}
123
} else {
124
+ try {
125
+ throw Error();
126
+ } catch (x) {
127
+ control = x;
128
+ }
129
fn();
130
}
131
} catch (sample) {
132
// This is inlined manually because closure doesn't do it for us.
112
- if (sample && typeof sample.stack === 'string') {
133
+ if (sample && control && typeof sample.stack === 'string') {
134
// This extracts the first frame from the sample that isn't also in the control.
135
// Skipping one frame that we assume is the frame that calls the two.
136
const sampleLines = sample.stack.split('\n');
148
}
149
for (; s >= 1 && c >= 0; s--, c--) {
150
// Next we find the first one that isn't the same which should be the
130
- // frame that called our sample function.
151
+ // frame that called our sample function and the control.
152
if (sampleLines[s] !== controlLines[c]) {
153
// In V8, the first line is describing the message but other VMs don't.
154
// If we're about to return the first line, and the control is also on the same
156
// the control. I.e. before we entered the sample frame. So we ignore this result.
157
// This can happen if you passed a class to function component, or non-function.
158
if (s !== 1 || c !== 1) {
138
- // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier.
139
- const frame = '\n' + sampleLines[s - 1].replace(' at new ', ' at ');
140
- if (__DEV__) {
141
- if (typeof fn === 'function') {
142
- componentFrameCache.set(fn, frame);
159
+ do {
160
+ s--;
161
+ c--;
162
+ // We may still have similar intermediate frames from the construct call.
163
+ // The next one that isn't the same should be our match though.
164
+ if (c < 0 || sampleLines[s] !== controlLines[c]) {
165
+ // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier.
166
+ const frame = '\n' + sampleLines[s].replace(' at new ', ' at ');
167
+ if (__DEV__) {
168
+ if (typeof fn === 'function') {
169
+ componentFrameCache.set(fn, frame);
170
+ }
171
+ }
172
+ // Return the line we found.
173
+ return frame;
174
}
144
- }
145
- // Return the line we found.
146
- return frame;
175
+ } while (s >= 1 && c >= 0);
176
}
177
+ break;
178
}
179
}
180
}