@@ -57,7 +57,7 @@ describe('ExceptionsManager', () => {
57
57
test ( 'forwards error instance to reportException' , ( ) => {
58
58
const error = new ReferenceError ( 'Some error happened' ) ;
59
59
// Copy all the data we care about before any possible mutation.
60
- const { message} = error ;
60
+ const { message, name } = error ;
61
61
62
62
const logToConsoleInReact = ReactFiberErrorDialog . showErrorDialog ( {
63
63
...capturedErrorDefaults ,
@@ -73,6 +73,11 @@ describe('ExceptionsManager', () => {
73
73
'This error is located at:' +
74
74
capturedErrorDefaults . componentStack ;
75
75
expect ( exceptionData . message ) . toBe ( formattedMessage ) ;
76
+ expect ( exceptionData . originalMessage ) . toBe ( message ) ;
77
+ expect ( exceptionData . name ) . toBe ( name ) ;
78
+ expect ( exceptionData . componentStack ) . toBe (
79
+ capturedErrorDefaults . componentStack ,
80
+ ) ;
76
81
expect ( getLineFromFrame ( exceptionData . stack [ 0 ] ) ) . toBe (
77
82
"const error = new ReferenceError('Some error happened');" ,
78
83
) ;
@@ -149,6 +154,10 @@ describe('ExceptionsManager', () => {
149
154
'This error is located at:' +
150
155
capturedErrorDefaults . componentStack ;
151
156
expect ( exceptionData . message ) . toBe ( formattedMessage ) ;
157
+ expect ( exceptionData . originalMessage ) . toBe ( message ) ;
158
+ expect ( exceptionData . componentStack ) . toBe (
159
+ capturedErrorDefaults . componentStack ,
160
+ ) ;
152
161
expect ( exceptionData . stack [ 0 ] . file ) . toMatch ( / R e a c t F i b e r E r r o r D i a l o g \. j s $ / ) ;
153
162
expect ( exceptionData . isFatal ) . toBe ( false ) ;
154
163
expect ( logToConsoleInReact ) . toBe ( false ) ;
@@ -164,8 +173,16 @@ describe('ExceptionsManager', () => {
164
173
expect ( nativeReportException . mock . calls . length ) . toBe ( 1 ) ;
165
174
const exceptionData = nativeReportException . mock . calls [ 0 ] [ 0 ] ;
166
175
const formattedMessage =
167
- 'Unspecified error at:' + capturedErrorDefaults . componentStack ;
176
+ 'Unspecified error' +
177
+ '\n\n' +
178
+ 'This error is located at:' +
179
+ capturedErrorDefaults . componentStack ;
168
180
expect ( exceptionData . message ) . toBe ( formattedMessage ) ;
181
+ expect ( exceptionData . originalMessage ) . toBe ( 'Unspecified error' ) ;
182
+ expect ( exceptionData . name ) . toBe ( null ) ;
183
+ expect ( exceptionData . componentStack ) . toBe (
184
+ capturedErrorDefaults . componentStack ,
185
+ ) ;
169
186
expect ( exceptionData . stack [ 0 ] . file ) . toMatch ( / R e a c t F i b e r E r r o r D i a l o g \. j s $ / ) ;
170
187
expect ( exceptionData . isFatal ) . toBe ( false ) ;
171
188
expect ( logToConsoleInReact ) . toBe ( false ) ;
@@ -186,6 +203,55 @@ describe('ExceptionsManager', () => {
186
203
"const error = Object.freeze(new Error('Some error happened'));" ,
187
204
) ;
188
205
} ) ;
206
+
207
+ test ( 'does not mutate the message' , ( ) => {
208
+ const error = new ReferenceError ( 'Some error happened' ) ;
209
+ const { message} = error ;
210
+
211
+ ReactFiberErrorDialog . showErrorDialog ( {
212
+ ...capturedErrorDefaults ,
213
+ error,
214
+ } ) ;
215
+
216
+ expect ( nativeReportException ) . toHaveBeenCalled ( ) ;
217
+ expect ( error . message ) . toBe ( message ) ;
218
+ } ) ;
219
+
220
+ test ( 'can safely process the same error multiple times' , ( ) => {
221
+ const error = new ReferenceError ( 'Some error happened' ) ;
222
+ // Copy all the data we care about before any possible mutation.
223
+ const { message} = error ;
224
+ const componentStacks = [
225
+ '\n in A\n in B\n in C' ,
226
+ '\n in X\n in Y\n in Z' ,
227
+ ] ;
228
+ for ( const componentStack of componentStacks ) {
229
+ nativeReportException . mockClear ( ) ;
230
+ const formattedMessage =
231
+ 'ReferenceError: ' +
232
+ message +
233
+ '\n\n' +
234
+ 'This error is located at:' +
235
+ componentStack ;
236
+ const logToConsoleInReact = ReactFiberErrorDialog . showErrorDialog ( {
237
+ ...capturedErrorDefaults ,
238
+ componentStack,
239
+ error,
240
+ } ) ;
241
+
242
+ expect ( nativeReportException . mock . calls . length ) . toBe ( 1 ) ;
243
+ const exceptionData = nativeReportException . mock . calls [ 0 ] [ 0 ] ;
244
+ expect ( exceptionData . message ) . toBe ( formattedMessage ) ;
245
+ expect ( exceptionData . originalMessage ) . toBe ( message ) ;
246
+ expect ( exceptionData . componentStack ) . toBe ( componentStack ) ;
247
+ expect ( getLineFromFrame ( exceptionData . stack [ 0 ] ) ) . toBe (
248
+ "const error = new ReferenceError('Some error happened');" ,
249
+ ) ;
250
+ expect ( exceptionData . isFatal ) . toBe ( false ) ;
251
+ expect ( logToConsoleInReact ) . toBe ( false ) ;
252
+ expect ( console . error ) . toBeCalledWith ( formattedMessage ) ;
253
+ }
254
+ } ) ;
189
255
} ) ;
190
256
191
257
describe ( 'console.error handler' , ( ) => {
@@ -208,19 +274,22 @@ describe('ExceptionsManager', () => {
208
274
209
275
test ( 'logging an Error' , ( ) => {
210
276
const error = new Error ( 'Some error happened' ) ;
211
- const { message} = error ;
277
+ const { message, name } = error ;
212
278
213
279
console . error ( error ) ;
214
280
215
281
expect ( nativeReportException . mock . calls . length ) . toBe ( 1 ) ;
216
282
const exceptionData = nativeReportException . mock . calls [ 0 ] [ 0 ] ;
217
- expect ( exceptionData . message ) . toBe ( message ) ;
283
+ const formattedMessage = 'Error: ' + message ;
284
+ expect ( exceptionData . message ) . toBe ( formattedMessage ) ;
285
+ expect ( exceptionData . originalMessage ) . toBe ( message ) ;
286
+ expect ( exceptionData . name ) . toBe ( name ) ;
218
287
expect ( getLineFromFrame ( exceptionData . stack [ 0 ] ) ) . toBe (
219
288
"const error = new Error('Some error happened');" ,
220
289
) ;
221
290
expect ( exceptionData . isFatal ) . toBe ( false ) ;
222
291
expect ( mockError . mock . calls [ 0 ] ) . toHaveLength ( 1 ) ;
223
- expect ( mockError . mock . calls [ 0 ] [ 0 ] ) . toBe ( error ) ;
292
+ expect ( mockError . mock . calls [ 0 ] [ 0 ] ) . toBe ( formattedMessage ) ;
224
293
} ) ;
225
294
226
295
test ( 'logging a string' , ( ) => {
@@ -230,8 +299,11 @@ describe('ExceptionsManager', () => {
230
299
231
300
expect ( nativeReportException . mock . calls . length ) . toBe ( 1 ) ;
232
301
const exceptionData = nativeReportException . mock . calls [ 0 ] [ 0 ] ;
233
- const formattedMessage = 'console.error: "Some error happened"' ;
234
- expect ( exceptionData . message ) . toBe ( formattedMessage ) ;
302
+ expect ( exceptionData . message ) . toBe (
303
+ 'console.error: "Some error happened"' ,
304
+ ) ;
305
+ expect ( exceptionData . originalMessage ) . toBe ( '"Some error happened"' ) ;
306
+ expect ( exceptionData . name ) . toBe ( 'console.error' ) ;
235
307
expect ( getLineFromFrame ( exceptionData . stack [ 0 ] ) ) . toBe (
236
308
'console.error(message);' ,
237
309
) ;
@@ -249,6 +321,10 @@ describe('ExceptionsManager', () => {
249
321
expect ( exceptionData . message ) . toBe (
250
322
'console.error: 42, true, ["symbol" failed to stringify], {"y":null}' ,
251
323
) ;
324
+ expect ( exceptionData . originalMessage ) . toBe (
325
+ '42, true, ["symbol" failed to stringify], {"y":null}' ,
326
+ ) ;
327
+ expect ( exceptionData . name ) . toBe ( 'console.error' ) ;
252
328
expect ( getLineFromFrame ( exceptionData . stack [ 0 ] ) ) . toBe (
253
329
'console.error(...args);' ,
254
330
) ;
@@ -317,13 +393,16 @@ describe('ExceptionsManager', () => {
317
393
318
394
expect ( nativeReportException . mock . calls . length ) . toBe ( 1 ) ;
319
395
const exceptionData = nativeReportException . mock . calls [ 0 ] [ 0 ] ;
320
- expect ( exceptionData . message ) . toBe ( message ) ;
396
+ const formattedMessage = 'Error: ' + message ;
397
+ expect ( exceptionData . message ) . toBe ( formattedMessage ) ;
398
+ expect ( exceptionData . originalMessage ) . toBe ( message ) ;
399
+ expect ( exceptionData . name ) . toBe ( 'Error' ) ;
321
400
expect ( getLineFromFrame ( exceptionData . stack [ 0 ] ) ) . toBe (
322
401
"const error = new Error('Some error happened');" ,
323
402
) ;
324
403
expect ( exceptionData . isFatal ) . toBe ( true ) ;
325
404
expect ( console . error . mock . calls [ 0 ] ) . toHaveLength ( 1 ) ;
326
- expect ( console . error . mock . calls [ 0 ] [ 0 ] ) . toBe ( message ) ;
405
+ expect ( console . error . mock . calls [ 0 ] [ 0 ] ) . toBe ( formattedMessage ) ;
327
406
} ) ;
328
407
329
408
test ( 'handling a non-fatal Error' , ( ) => {
@@ -334,13 +413,16 @@ describe('ExceptionsManager', () => {
334
413
335
414
expect ( nativeReportException . mock . calls . length ) . toBe ( 1 ) ;
336
415
const exceptionData = nativeReportException . mock . calls [ 0 ] [ 0 ] ;
337
- expect ( exceptionData . message ) . toBe ( message ) ;
416
+ const formattedMessage = 'Error: ' + message ;
417
+ expect ( exceptionData . message ) . toBe ( formattedMessage ) ;
418
+ expect ( exceptionData . originalMessage ) . toBe ( message ) ;
419
+ expect ( exceptionData . name ) . toBe ( 'Error' ) ;
338
420
expect ( getLineFromFrame ( exceptionData . stack [ 0 ] ) ) . toBe (
339
421
"const error = new Error('Some error happened');" ,
340
422
) ;
341
423
expect ( exceptionData . isFatal ) . toBe ( false ) ;
342
424
expect ( console . error . mock . calls [ 0 ] ) . toHaveLength ( 1 ) ;
343
- expect ( console . error . mock . calls [ 0 ] [ 0 ] ) . toBe ( message ) ;
425
+ expect ( console . error . mock . calls [ 0 ] [ 0 ] ) . toBe ( formattedMessage ) ;
344
426
} ) ;
345
427
346
428
test ( 'handling a thrown string' , ( ) => {
@@ -351,6 +433,8 @@ describe('ExceptionsManager', () => {
351
433
expect ( nativeReportException . mock . calls . length ) . toBe ( 1 ) ;
352
434
const exceptionData = nativeReportException . mock . calls [ 0 ] [ 0 ] ;
353
435
expect ( exceptionData . message ) . toBe ( message ) ;
436
+ expect ( exceptionData . originalMessage ) . toBe ( null ) ;
437
+ expect ( exceptionData . name ) . toBe ( null ) ;
354
438
expect ( exceptionData . stack [ 0 ] . file ) . toMatch ( / E x c e p t i o n s M a n a g e r \. j s $ / ) ;
355
439
expect ( exceptionData . isFatal ) . toBe ( true ) ;
356
440
expect ( console . error . mock . calls [ 0 ] ) . toEqual ( [ message ] ) ;
0 commit comments