lib: validate Error.captureStackTrace() calls
This adds a custom eslint rule to verify that `Error.captureStackTrace()` is only called if necessary. In most cases the helper function should be used instead. PR-URL: https://github.com/nodejs/node/pull/26738 Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
This commit is contained in:
parent
bfbce289c3
commit
3fe1e80896
@ -15,6 +15,8 @@ rules:
|
|||||||
# Config specific to lib
|
# Config specific to lib
|
||||||
- selector: "NewExpression[callee.name=/Error$/]:not([callee.name=/^(AssertionError|NghttpError)$/])"
|
- selector: "NewExpression[callee.name=/Error$/]:not([callee.name=/^(AssertionError|NghttpError)$/])"
|
||||||
message: "Use an error exported by the internal/errors module."
|
message: "Use an error exported by the internal/errors module."
|
||||||
|
- selector: "CallExpression[callee.object.name='Error'][callee.property.name='captureStackTrace']"
|
||||||
|
message: "Please use `require('internal/errors').hideStackFrames()` instead."
|
||||||
# Custom rules in tools/eslint-rules
|
# Custom rules in tools/eslint-rules
|
||||||
node-core/require-globals: error
|
node-core/require-globals: error
|
||||||
node-core/no-let-in-for-declaration: error
|
node-core/no-let-in-for-declaration: error
|
||||||
|
@ -240,6 +240,7 @@ function getErrMessage(message, fn) {
|
|||||||
// We only need the stack trace. To minimize the overhead use an object
|
// We only need the stack trace. To minimize the overhead use an object
|
||||||
// instead of an error.
|
// instead of an error.
|
||||||
const err = {};
|
const err = {};
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
Error.captureStackTrace(err, fn);
|
Error.captureStackTrace(err, fn);
|
||||||
Error.stackTraceLimit = tmpLimit;
|
Error.stackTraceLimit = tmpLimit;
|
||||||
|
|
||||||
|
@ -158,6 +158,7 @@ EventEmitter.prototype.emit = function emit(type, ...args) {
|
|||||||
try {
|
try {
|
||||||
const { kExpandStackSymbol } = require('internal/util');
|
const { kExpandStackSymbol } = require('internal/util');
|
||||||
const capture = {};
|
const capture = {};
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
Error.captureStackTrace(capture, EventEmitter.prototype.emit);
|
Error.captureStackTrace(capture, EventEmitter.prototype.emit);
|
||||||
Object.defineProperty(er, kExpandStackSymbol, {
|
Object.defineProperty(er, kExpandStackSymbol, {
|
||||||
value: enhanceStackTrace.bind(null, er, capture),
|
value: enhanceStackTrace.bind(null, er, capture),
|
||||||
|
@ -117,6 +117,7 @@ function showTruncateDeprecation() {
|
|||||||
function handleErrorFromBinding(ctx) {
|
function handleErrorFromBinding(ctx) {
|
||||||
if (ctx.errno !== undefined) { // libuv error numbers
|
if (ctx.errno !== undefined) { // libuv error numbers
|
||||||
const err = uvException(ctx);
|
const err = uvException(ctx);
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
Error.captureStackTrace(err, handleErrorFromBinding);
|
Error.captureStackTrace(err, handleErrorFromBinding);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
@ -124,6 +125,7 @@ function handleErrorFromBinding(ctx) {
|
|||||||
// TODO(joyeecheung): currently, ctx.error are encoding errors
|
// TODO(joyeecheung): currently, ctx.error are encoding errors
|
||||||
// usually caused by memory problems. We need to figure out proper error
|
// usually caused by memory problems. We need to figure out proper error
|
||||||
// code(s) for this.
|
// code(s) for this.
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
Error.captureStackTrace(ctx.error, handleErrorFromBinding);
|
Error.captureStackTrace(ctx.error, handleErrorFromBinding);
|
||||||
throw ctx.error;
|
throw ctx.error;
|
||||||
}
|
}
|
||||||
|
@ -398,6 +398,7 @@ class AssertionError extends Error {
|
|||||||
this.actual = actual;
|
this.actual = actual;
|
||||||
this.expected = expected;
|
this.expected = expected;
|
||||||
this.operator = operator;
|
this.operator = operator;
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
Error.captureStackTrace(this, stackStartFn);
|
Error.captureStackTrace(this, stackStartFn);
|
||||||
// Create error message including the error code in the name.
|
// Create error message including the error code in the name.
|
||||||
this.stack;
|
this.stack;
|
||||||
|
@ -105,6 +105,7 @@ function fatalError(e) {
|
|||||||
process._rawDebug(e.stack);
|
process._rawDebug(e.stack);
|
||||||
} else {
|
} else {
|
||||||
const o = { message: e };
|
const o = { message: e };
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
Error.captureStackTrace(o, fatalError);
|
Error.captureStackTrace(o, fatalError);
|
||||||
process._rawDebug(o.stack);
|
process._rawDebug(o.stack);
|
||||||
}
|
}
|
||||||
|
@ -331,6 +331,7 @@ const consoleMethods = {
|
|||||||
name: 'Trace',
|
name: 'Trace',
|
||||||
message: this[kFormatForStderr](args)
|
message: this[kFormatForStderr](args)
|
||||||
};
|
};
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
Error.captureStackTrace(err, this.trace);
|
Error.captureStackTrace(err, this.trace);
|
||||||
this.error(err.stack);
|
this.error(err.stack);
|
||||||
},
|
},
|
||||||
|
@ -354,6 +354,7 @@ function uvException(ctx) {
|
|||||||
err.dest = dest;
|
err.dest = dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
Error.captureStackTrace(err, excludedStackFn || uvException);
|
Error.captureStackTrace(err, excludedStackFn || uvException);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -396,6 +397,7 @@ function uvExceptionWithHostPort(err, syscall, address, port) {
|
|||||||
ex.port = port;
|
ex.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
Error.captureStackTrace(ex, excludedStackFn || uvExceptionWithHostPort);
|
Error.captureStackTrace(ex, excludedStackFn || uvExceptionWithHostPort);
|
||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
@ -424,6 +426,7 @@ function errnoException(err, syscall, original) {
|
|||||||
ex.code = ex.errno = code;
|
ex.code = ex.errno = code;
|
||||||
ex.syscall = syscall;
|
ex.syscall = syscall;
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
Error.captureStackTrace(ex, excludedStackFn || errnoException);
|
Error.captureStackTrace(ex, excludedStackFn || errnoException);
|
||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
@ -472,6 +475,7 @@ function exceptionWithHostPort(err, syscall, address, port, additional) {
|
|||||||
ex.port = port;
|
ex.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
Error.captureStackTrace(ex, excludedStackFn || exceptionWithHostPort);
|
Error.captureStackTrace(ex, excludedStackFn || exceptionWithHostPort);
|
||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
@ -512,6 +516,7 @@ function dnsException(code, syscall, hostname) {
|
|||||||
ex.hostname = hostname;
|
ex.hostname = hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
Error.captureStackTrace(ex, excludedStackFn || dnsException);
|
Error.captureStackTrace(ex, excludedStackFn || dnsException);
|
||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,7 @@ function emitWarning(warning, type, code, ctor, now) {
|
|||||||
warning.name = String(type || 'Warning');
|
warning.name = String(type || 'Warning');
|
||||||
if (code !== undefined) warning.code = code;
|
if (code !== undefined) warning.code = code;
|
||||||
if (detail !== undefined) warning.detail = detail;
|
if (detail !== undefined) warning.detail = detail;
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
Error.captureStackTrace(warning, ctor || process.emitWarning);
|
Error.captureStackTrace(warning, ctor || process.emitWarning);
|
||||||
} else if (!(warning instanceof Error)) {
|
} else if (!(warning instanceof Error)) {
|
||||||
throw new ERR_INVALID_ARG_TYPE('warning', ['Error', 'string'], warning);
|
throw new ERR_INVALID_ARG_TYPE('warning', ['Error', 'string'], warning);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user