lib: refactor Error.captureStackTrace() usage · nodejs/node@bfbce28 (original) (raw)
`@@ -18,7 +18,7 @@ const codes = {};
`
18
18
`const { kMaxLength } = internalBinding('buffer');
`
19
19
`const { defineProperty } = Object;
`
20
20
``
21
``
`-
let useOriginalName = false;
`
``
21
`+
let excludedStackFn;
`
22
22
``
23
23
`// Lazily loaded
`
24
24
`let util;
`
`@@ -49,7 +49,15 @@ function lazyBuffer() {
`
49
49
`// and may have .path and .dest.
`
50
50
`class SystemError extends Error {
`
51
51
`constructor(key, context) {
`
52
``
`-
super();
`
``
52
`+
if (excludedStackFn === undefined) {
`
``
53
`+
super();
`
``
54
`+
} else {
`
``
55
`+
const limit = Error.stackTraceLimit;
`
``
56
`+
Error.stackTraceLimit = 0;
`
``
57
`+
super();
`
``
58
`+
// Reset the limit and setting the name property.
`
``
59
`+
Error.stackTraceLimit = limit;
`
``
60
`+
}
`
53
61
`const prefix = getMessage(key, [], this);
`
54
62
`` let message = ${prefix}: ${context.syscall} returned
+
``
55
63
`` ${context.code} (${context.message})
;
``
`@@ -148,7 +156,15 @@ function makeSystemErrorWithCode(key) {
`
148
156
`function makeNodeErrorWithCode(Base, key) {
`
149
157
`return class NodeError extends Base {
`
150
158
`constructor(...args) {
`
151
``
`-
super();
`
``
159
`+
if (excludedStackFn === undefined) {
`
``
160
`+
super();
`
``
161
`+
} else {
`
``
162
`+
const limit = Error.stackTraceLimit;
`
``
163
`+
Error.stackTraceLimit = 0;
`
``
164
`+
super();
`
``
165
`+
// Reset the limit and setting the name property.
`
``
166
`+
Error.stackTraceLimit = limit;
`
``
167
`+
}
`
152
168
`const message = getMessage(key, args, this);
`
153
169
`Object.defineProperty(this, 'message', {
`
154
170
`value: message,
`
`@@ -178,9 +194,30 @@ function makeNodeErrorWithCode(Base, key) {
`
178
194
`};
`
179
195
`}
`
180
196
``
``
197
`+
// This function removes unnecessary frames from Node.js core errors.
`
``
198
`+
function hideStackFrames(fn) {
`
``
199
`+
return function hidden(...args) {
`
``
200
`` +
// Make sure the most outer hideStackFrames()
function is used.
``
``
201
`+
let setStackFn = false;
`
``
202
`+
if (excludedStackFn === undefined) {
`
``
203
`+
excludedStackFn = hidden;
`
``
204
`+
setStackFn = true;
`
``
205
`+
}
`
``
206
`+
try {
`
``
207
`+
return fn(...args);
`
``
208
`+
} finally {
`
``
209
`+
if (setStackFn === true) {
`
``
210
`+
excludedStackFn = undefined;
`
``
211
`+
}
`
``
212
`+
}
`
``
213
`+
};
`
``
214
`+
}
`
``
215
+
181
216
`function addCodeToName(err, name, code) {
`
182
``
`-
if (useOriginalName) {
`
183
``
`-
return;
`
``
217
`+
// Set the stack
`
``
218
`+
if (excludedStackFn !== undefined) {
`
``
219
`+
// eslint-disable-next-line no-restricted-syntax
`
``
220
`+
Error.captureStackTrace(err, excludedStackFn);
`
184
221
`}
`
185
222
`// Add the error code to the name to include it in the stack trace.
`
186
223
`` err.name = ${name} [${code}]
;
``
`@@ -308,6 +345,7 @@ function uvException(ctx) {
`
308
345
`err[prop] = ctx[prop];
`
309
346
`}
`
310
347
``
``
348
`` +
// TODO(BridgeAR): Show the code
property as part of the stack.
``
311
349
`err.code = code;
`
312
350
`if (path) {
`
313
351
`err.path = path;
`
`@@ -316,7 +354,7 @@ function uvException(ctx) {
`
316
354
`err.dest = dest;
`
317
355
`}
`
318
356
``
319
``
`-
Error.captureStackTrace(err, uvException);
`
``
357
`+
Error.captureStackTrace(err, excludedStackFn || uvException);
`
320
358
`return err;
`
321
359
`}
`
322
360
``
`@@ -358,7 +396,7 @@ function uvExceptionWithHostPort(err, syscall, address, port) {
`
358
396
`ex.port = port;
`
359
397
`}
`
360
398
``
361
``
`-
Error.captureStackTrace(ex, uvExceptionWithHostPort);
`
``
399
`+
Error.captureStackTrace(ex, excludedStackFn || uvExceptionWithHostPort);
`
362
400
`return ex;
`
363
401
`}
`
364
402
``
`@@ -386,7 +424,7 @@ function errnoException(err, syscall, original) {
`
386
424
`ex.code = ex.errno = code;
`
387
425
`ex.syscall = syscall;
`
388
426
``
389
``
`-
Error.captureStackTrace(ex, errnoException);
`
``
427
`+
Error.captureStackTrace(ex, excludedStackFn || errnoException);
`
390
428
`return ex;
`
391
429
`}
`
392
430
``
`@@ -434,7 +472,7 @@ function exceptionWithHostPort(err, syscall, address, port, additional) {
`
434
472
`ex.port = port;
`
435
473
`}
`
436
474
``
437
``
`-
Error.captureStackTrace(ex, exceptionWithHostPort);
`
``
475
`+
Error.captureStackTrace(ex, excludedStackFn || exceptionWithHostPort);
`
438
476
`return ex;
`
439
477
`}
`
440
478
``
`@@ -473,7 +511,8 @@ function dnsException(code, syscall, hostname) {
`
473
511
`if (hostname) {
`
474
512
`ex.hostname = hostname;
`
475
513
`}
`
476
``
`-
Error.captureStackTrace(ex, dnsException);
`
``
514
+
``
515
`+
Error.captureStackTrace(ex, excludedStackFn || dnsException);
`
477
516
`return ex;
`
478
517
`}
`
479
518
``
`@@ -523,21 +562,19 @@ function oneOf(expected, thing) {
`
523
562
`}
`
524
563
``
525
564
`module.exports = {
`
``
565
`+
addCodeToName, // Exported for NghttpError
`
``
566
`+
codes,
`
526
567
` dnsException,
`
527
568
` errnoException,
`
528
569
` exceptionWithHostPort,
`
``
570
`+
getMessage,
`
``
571
`+
hideStackFrames,
`
``
572
`+
isStackOverflowError,
`
529
573
` uvException,
`
530
574
` uvExceptionWithHostPort,
`
531
``
`-
isStackOverflowError,
`
532
``
`-
getMessage,
`
533
575
` SystemError,
`
534
``
`-
codes,
`
535
576
`// This is exported only to facilitate testing.
`
536
``
`-
E,
`
537
``
`-
// This allows us to tell the type of the errors without using
`
538
``
`-
// instanceof, which is necessary in WPT harness.
`
539
``
`-
get useOriginalName() { return useOriginalName; },
`
540
``
`-
set useOriginalName(value) { useOriginalName = value; }
`
``
577
`+
E
`
541
578
`};
`
542
579
``
543
580
`// To declare an error message, use the E(sym, val, def) function above. The sym
`
`@@ -556,7 +593,6 @@ module.exports = {
`
556
593
`// Note: Please try to keep these in alphabetical order
`
557
594
`//
`
558
595
`// Note: Node.js specific errors must begin with the prefix ERR_
`
559
``
-
560
596
`E('ERR_AMBIGUOUS_ARGUMENT', 'The "%s" argument is ambiguous. %s', TypeError);
`
561
597
`E('ERR_ARG_NOT_ITERABLE', '%s must be iterable', TypeError);
`
562
598
`E('ERR_ASSERTION', '%s', Error);
`
`@@ -630,7 +666,10 @@ E('ERR_ENCODING_INVALID_ENCODED_DATA', function(encoding, ret) {
`
630
666
`}, TypeError);
`
631
667
`E('ERR_ENCODING_NOT_SUPPORTED', 'The "%s" encoding is not supported',
`
632
668
`RangeError);
`
633
``
`-
E('ERR_FALSY_VALUE_REJECTION', 'Promise was rejected with falsy value', Error);
`
``
669
`+
E('ERR_FALSY_VALUE_REJECTION', function(reason) {
`
``
670
`+
this.reason = reason;
`
``
671
`+
return 'Promise was rejected with falsy value';
`
``
672
`+
}, Error);
`
634
673
`E('ERR_FS_FILE_TOO_LARGE', 'File size (%s) is greater than possible Buffer: ' +
`
635
674
`` ${kMaxLength} bytes
,
``
636
675
`RangeError);
`