mirror of
https://github.com/nodejs/node.git
synced 2025-08-15 13:48:44 +02:00
errors: improve hideStackFrames
PR-URL: https://github.com/nodejs/node/pull/49990 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
6b27f5b09e
commit
83e6350b82
41 changed files with 984 additions and 572 deletions
62
benchmark/error/hidestackframes-noerr.js
Normal file
62
benchmark/error/hidestackframes-noerr.js
Normal file
|
@ -0,0 +1,62 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common.js');
|
||||
const assert = require('assert');
|
||||
|
||||
const bench = common.createBenchmark(main, {
|
||||
type: [
|
||||
'hide-stackframes',
|
||||
'direct-call',
|
||||
],
|
||||
n: [1e7],
|
||||
}, {
|
||||
flags: ['--expose-internals'],
|
||||
});
|
||||
|
||||
function main({ n, type }) {
|
||||
const {
|
||||
hideStackFrames,
|
||||
codes: {
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
},
|
||||
} = require('internal/errors');
|
||||
|
||||
const testfn = (value) => {
|
||||
if (typeof value !== 'number') {
|
||||
throw new ERR_INVALID_ARG_TYPE('Benchmark', 'number', value);
|
||||
}
|
||||
};
|
||||
|
||||
const hideStackFramesTestfn = hideStackFrames((value) => {
|
||||
if (typeof value !== 'number') {
|
||||
throw new ERR_INVALID_ARG_TYPE.HideStackFrameError('Benchmark', 'number', value);
|
||||
}
|
||||
});
|
||||
|
||||
const fn = type === 'hide-stackframe' ? hideStackFramesTestfn : testfn;
|
||||
|
||||
const value = 42;
|
||||
|
||||
const length = 1024;
|
||||
const array = [];
|
||||
const errCase = false;
|
||||
|
||||
for (let i = 0; i < length; ++i) {
|
||||
array.push(fn(value));
|
||||
}
|
||||
|
||||
bench.start();
|
||||
|
||||
for (let i = 0; i < n; i++) {
|
||||
const index = i % length;
|
||||
array[index] = fn(value);
|
||||
}
|
||||
|
||||
bench.end(n);
|
||||
|
||||
// Verify the entries to prevent dead code elimination from making
|
||||
// the benchmark invalid.
|
||||
for (let i = 0; i < length; ++i) {
|
||||
assert.strictEqual(typeof array[i], errCase ? 'object' : 'undefined');
|
||||
}
|
||||
}
|
87
benchmark/error/hidestackframes-throw.js
Normal file
87
benchmark/error/hidestackframes-throw.js
Normal file
|
@ -0,0 +1,87 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common.js');
|
||||
const assert = require('assert');
|
||||
|
||||
const bench = common.createBenchmark(main, {
|
||||
type: [
|
||||
'hide-stackframes',
|
||||
'direct-call',
|
||||
],
|
||||
double: ['true', 'false'],
|
||||
n: [1e5],
|
||||
}, {
|
||||
flags: ['--expose-internals'],
|
||||
});
|
||||
|
||||
function main({ n, type, double }) {
|
||||
const {
|
||||
hideStackFrames,
|
||||
codes: {
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
},
|
||||
} = require('internal/errors');
|
||||
|
||||
const value = 'err';
|
||||
|
||||
const testfn = (value) => {
|
||||
if (typeof value !== 'number') {
|
||||
throw new ERR_INVALID_ARG_TYPE('Benchmark', 'number', value);
|
||||
}
|
||||
};
|
||||
|
||||
const hideStackFramesTestfn = hideStackFrames((value) => {
|
||||
if (typeof value !== 'number') {
|
||||
throw new ERR_INVALID_ARG_TYPE.HideStackFrameError('Benchmark', 'number', value);
|
||||
}
|
||||
});
|
||||
|
||||
function doubleTestfn(value) {
|
||||
testfn(value);
|
||||
}
|
||||
|
||||
const doubleHideStackFramesTestfn = hideStackFrames((value) => {
|
||||
hideStackFramesTestfn.withoutStackTrace(value);
|
||||
});
|
||||
|
||||
const fn = type === 'hide-stackframe' ?
|
||||
double === 'true' ?
|
||||
doubleHideStackFramesTestfn :
|
||||
hideStackFramesTestfn :
|
||||
double === 'true' ?
|
||||
doubleTestfn :
|
||||
testfn;
|
||||
|
||||
const length = 1024;
|
||||
const array = [];
|
||||
let errCase = false;
|
||||
|
||||
// Warm up.
|
||||
for (let i = 0; i < length; ++i) {
|
||||
try {
|
||||
fn(value);
|
||||
} catch (e) {
|
||||
errCase = true;
|
||||
array.push(e);
|
||||
}
|
||||
}
|
||||
|
||||
bench.start();
|
||||
|
||||
for (let i = 0; i < n; i++) {
|
||||
const index = i % length;
|
||||
try {
|
||||
fn(value);
|
||||
} catch (e) {
|
||||
array[index] = e;
|
||||
}
|
||||
}
|
||||
|
||||
bench.end(n);
|
||||
|
||||
// Verify the entries to prevent dead code elimination from making
|
||||
// the benchmark invalid.
|
||||
for (let i = 0; i < length; ++i) {
|
||||
assert.strictEqual(typeof array[i], errCase ? 'object' : 'undefined');
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common.js');
|
||||
|
||||
const bench = common.createBenchmark(main, {
|
||||
type: ['hide-stackframes-throw', 'direct-call-throw',
|
||||
'hide-stackframes-noerr', 'direct-call-noerr'],
|
||||
n: [10e4],
|
||||
}, {
|
||||
flags: ['--expose-internals'],
|
||||
});
|
||||
|
||||
function main({ n, type }) {
|
||||
const {
|
||||
hideStackFrames,
|
||||
codes: {
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
},
|
||||
} = require('internal/errors');
|
||||
|
||||
const testfn = (value) => {
|
||||
if (typeof value !== 'number') {
|
||||
throw new ERR_INVALID_ARG_TYPE('Benchmark', 'number', value);
|
||||
}
|
||||
};
|
||||
|
||||
let fn = testfn;
|
||||
if (type.startsWith('hide-stackframe'))
|
||||
fn = hideStackFrames(testfn);
|
||||
let value = 42;
|
||||
if (type.endsWith('-throw'))
|
||||
value = 'err';
|
||||
|
||||
bench.start();
|
||||
|
||||
for (let i = 0; i < n; i++) {
|
||||
try {
|
||||
fn(value);
|
||||
} catch {
|
||||
// No-op
|
||||
}
|
||||
}
|
||||
|
||||
bench.end(n);
|
||||
}
|
|
@ -19,7 +19,7 @@ rules:
|
|||
- selector: ThrowStatement > CallExpression[callee.name=/Error$/]
|
||||
message: Use new keyword when throwing an Error.
|
||||
# Config specific to lib
|
||||
- selector: NewExpression[callee.name=/Error$/]:not([callee.name=/^(AssertionError|NghttpError|AbortError)$/])
|
||||
- selector: NewExpression[callee.name=/Error$/]:not([callee.name=/^(AssertionError|NghttpError|AbortError|NodeAggregateError)$/])
|
||||
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.
|
||||
|
|
|
@ -72,7 +72,7 @@ const {
|
|||
traceEnd,
|
||||
getNextTraceEventId,
|
||||
} = require('internal/http');
|
||||
const { connResetException, codes } = require('internal/errors');
|
||||
const { ConnResetException, codes } = require('internal/errors');
|
||||
const {
|
||||
ERR_HTTP_HEADERS_SENT,
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
|
@ -452,7 +452,7 @@ function socketCloseListener() {
|
|||
if (res) {
|
||||
// Socket closed before we emitted 'end' below.
|
||||
if (!res.complete) {
|
||||
res.destroy(connResetException('aborted'));
|
||||
res.destroy(new ConnResetException('aborted'));
|
||||
}
|
||||
req._closed = true;
|
||||
req.emit('close');
|
||||
|
@ -465,7 +465,7 @@ function socketCloseListener() {
|
|||
// receive a response. The error needs to
|
||||
// fire on the request.
|
||||
req.socket._hadError = true;
|
||||
req.emit('error', connResetException('socket hang up'));
|
||||
req.emit('error', new ConnResetException('socket hang up'));
|
||||
}
|
||||
req._closed = true;
|
||||
req.emit('close');
|
||||
|
@ -516,7 +516,7 @@ function socketOnEnd() {
|
|||
// If we don't have a response then we know that the socket
|
||||
// ended prematurely and we need to emit an error on the request.
|
||||
req.socket._hadError = true;
|
||||
req.emit('error', connResetException('socket hang up'));
|
||||
req.emit('error', new ConnResetException('socket hang up'));
|
||||
}
|
||||
if (parser) {
|
||||
parser.finish();
|
||||
|
@ -869,7 +869,7 @@ function onSocketNT(req, socket, err) {
|
|||
|
||||
function _destroy(req, err) {
|
||||
if (!req.aborted && !err) {
|
||||
err = connResetException('socket hang up');
|
||||
err = new ConnResetException('socket hang up');
|
||||
}
|
||||
if (err) {
|
||||
req.emit('error', err);
|
||||
|
|
|
@ -663,17 +663,17 @@ function matchHeader(self, state, field, value) {
|
|||
|
||||
const validateHeaderName = hideStackFrames((name, label) => {
|
||||
if (typeof name !== 'string' || !name || !checkIsHttpToken(name)) {
|
||||
throw new ERR_INVALID_HTTP_TOKEN(label || 'Header name', name);
|
||||
throw new ERR_INVALID_HTTP_TOKEN.HideStackFramesError(label || 'Header name', name);
|
||||
}
|
||||
});
|
||||
|
||||
const validateHeaderValue = hideStackFrames((name, value) => {
|
||||
if (value === undefined) {
|
||||
throw new ERR_HTTP_INVALID_HEADER_VALUE(value, name);
|
||||
throw new ERR_HTTP_INVALID_HEADER_VALUE.HideStackFramesError(value, name);
|
||||
}
|
||||
if (checkInvalidHeaderChar(value)) {
|
||||
debug('Header "%s" contains invalid characters', name);
|
||||
throw new ERR_INVALID_CHAR('header content', name);
|
||||
throw new ERR_INVALID_CHAR.HideStackFramesError('header content', name);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ const {
|
|||
} = require('internal/async_hooks');
|
||||
const { IncomingMessage } = require('_http_incoming');
|
||||
const {
|
||||
connResetException,
|
||||
ConnResetException,
|
||||
codes,
|
||||
} = require('internal/errors');
|
||||
const {
|
||||
|
@ -790,7 +790,7 @@ function socketOnClose(socket, state) {
|
|||
function abortIncoming(incoming) {
|
||||
while (incoming.length) {
|
||||
const req = incoming.shift();
|
||||
req.destroy(connResetException('aborted'));
|
||||
req.destroy(new ConnResetException('aborted'));
|
||||
}
|
||||
// Abort socket._httpMessage ?
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ const { Pipe, constants: PipeConstants } = internalBinding('pipe_wrap');
|
|||
const { owner_symbol } = require('internal/async_hooks').symbols;
|
||||
const { isArrayBufferView } = require('internal/util/types');
|
||||
const { SecureContext: NativeSecureContext } = internalBinding('crypto');
|
||||
const { connResetException, codes } = require('internal/errors');
|
||||
const { ConnResetException, codes } = require('internal/errors');
|
||||
const {
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
ERR_INVALID_ARG_VALUE,
|
||||
|
@ -1218,7 +1218,7 @@ function onSocketClose(err) {
|
|||
// Emit ECONNRESET
|
||||
if (!this._controlReleased && !this[kErrorEmitted]) {
|
||||
this[kErrorEmitted] = true;
|
||||
const connReset = connResetException('socket hang up');
|
||||
const connReset = new ConnResetException('socket hang up');
|
||||
this._tlsOptions.server.emit('tlsClientError', connReset, this);
|
||||
}
|
||||
}
|
||||
|
@ -1724,9 +1724,9 @@ function onConnectEnd() {
|
|||
if (!this._hadError) {
|
||||
const options = this[kConnectOptions];
|
||||
this._hadError = true;
|
||||
const error = connResetException('Client network socket disconnected ' +
|
||||
'before secure TLS connection was ' +
|
||||
'established');
|
||||
const error = new ConnResetException('Client network socket disconnected ' +
|
||||
'before secure TLS connection was ' +
|
||||
'established');
|
||||
error.path = options.path;
|
||||
error.host = options.host;
|
||||
error.port = options.port;
|
||||
|
|
|
@ -108,7 +108,6 @@ const {
|
|||
ERR_UNKNOWN_ENCODING,
|
||||
},
|
||||
genericNodeError,
|
||||
hideStackFrames,
|
||||
} = require('internal/errors');
|
||||
const {
|
||||
validateArray,
|
||||
|
@ -386,19 +385,12 @@ Buffer.of = of;
|
|||
|
||||
ObjectSetPrototypeOf(Buffer, Uint8Array);
|
||||
|
||||
// The 'assertSize' method will remove itself from the callstack when an error
|
||||
// occurs. This is done simply to keep the internal details of the
|
||||
// implementation from bleeding out to users.
|
||||
const assertSize = hideStackFrames((size) => {
|
||||
validateNumber(size, 'size', 0, kMaxLength);
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a new filled Buffer instance.
|
||||
* alloc(size[, fill[, encoding]])
|
||||
*/
|
||||
Buffer.alloc = function alloc(size, fill, encoding) {
|
||||
assertSize(size);
|
||||
validateNumber(size, 'size', 0, kMaxLength);
|
||||
if (fill !== undefined && fill !== 0 && size > 0) {
|
||||
const buf = createUnsafeBuffer(size);
|
||||
return _fill(buf, fill, 0, buf.length, encoding);
|
||||
|
@ -411,7 +403,7 @@ Buffer.alloc = function alloc(size, fill, encoding) {
|
|||
* instance. If `--zero-fill-buffers` is set, will zero-fill the buffer.
|
||||
*/
|
||||
Buffer.allocUnsafe = function allocUnsafe(size) {
|
||||
assertSize(size);
|
||||
validateNumber(size, 'size', 0, kMaxLength);
|
||||
return allocate(size);
|
||||
};
|
||||
|
||||
|
@ -421,15 +413,15 @@ Buffer.allocUnsafe = function allocUnsafe(size) {
|
|||
* If `--zero-fill-buffers` is set, will zero-fill the buffer.
|
||||
*/
|
||||
Buffer.allocUnsafeSlow = function allocUnsafeSlow(size) {
|
||||
assertSize(size);
|
||||
validateNumber(size, 'size', 0, kMaxLength);
|
||||
return createUnsafeBuffer(size);
|
||||
};
|
||||
|
||||
// If --zero-fill-buffers command line argument is set, a zero-filled
|
||||
// buffer is returned.
|
||||
function SlowBuffer(length) {
|
||||
assertSize(length);
|
||||
return createUnsafeBuffer(length);
|
||||
function SlowBuffer(size) {
|
||||
validateNumber(size, 'size', 0, kMaxLength);
|
||||
return createUnsafeBuffer(size);
|
||||
}
|
||||
|
||||
ObjectSetPrototypeOf(SlowBuffer.prototype, Uint8ArrayPrototype);
|
||||
|
|
47
lib/dgram.js
47
lib/dgram.js
|
@ -96,9 +96,10 @@ function lazyLoadCluster() {
|
|||
return _cluster;
|
||||
}
|
||||
|
||||
const errnoException = errors.errnoException;
|
||||
const exceptionWithHostPort = errors.exceptionWithHostPort;
|
||||
|
||||
const {
|
||||
ErrnoException,
|
||||
ExceptionWithHostPort,
|
||||
} = errors;
|
||||
|
||||
function Socket(type, listener) {
|
||||
FunctionPrototypeCall(EventEmitter, this);
|
||||
|
@ -286,7 +287,7 @@ Socket.prototype.bind = function(port_, address_ /* , callback */) {
|
|||
flags: null,
|
||||
}, (err) => {
|
||||
// Callback to handle error.
|
||||
const ex = errnoException(err, 'open');
|
||||
const ex = new ErrnoException(err, 'open');
|
||||
state.bindState = BIND_STATE_UNBOUND;
|
||||
this.emit('error', ex);
|
||||
});
|
||||
|
@ -299,7 +300,7 @@ Socket.prototype.bind = function(port_, address_ /* , callback */) {
|
|||
const err = state.handle.open(fd);
|
||||
|
||||
if (err)
|
||||
throw errnoException(err, 'open');
|
||||
throw new ErrnoException(err, 'open');
|
||||
|
||||
startListening(this);
|
||||
return this;
|
||||
|
@ -350,7 +351,7 @@ Socket.prototype.bind = function(port_, address_ /* , callback */) {
|
|||
flags: flags,
|
||||
}, (err) => {
|
||||
// Callback to handle error.
|
||||
const ex = exceptionWithHostPort(err, 'bind', ip, port);
|
||||
const ex = new ExceptionWithHostPort(err, 'bind', ip, port);
|
||||
state.bindState = BIND_STATE_UNBOUND;
|
||||
this.emit('error', ex);
|
||||
});
|
||||
|
@ -360,7 +361,7 @@ Socket.prototype.bind = function(port_, address_ /* , callback */) {
|
|||
|
||||
const err = state.handle.bind(ip, port || 0, flags);
|
||||
if (err) {
|
||||
const ex = exceptionWithHostPort(err, 'bind', ip, port);
|
||||
const ex = new ExceptionWithHostPort(err, 'bind', ip, port);
|
||||
state.bindState = BIND_STATE_UNBOUND;
|
||||
this.emit('error', ex);
|
||||
// Todo: close?
|
||||
|
@ -429,7 +430,7 @@ function doConnect(ex, self, ip, address, port, callback) {
|
|||
if (!ex) {
|
||||
const err = state.handle.connect(ip, port);
|
||||
if (err) {
|
||||
ex = exceptionWithHostPort(err, 'connect', address, port);
|
||||
ex = new ExceptionWithHostPort(err, 'connect', address, port);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -457,7 +458,7 @@ Socket.prototype.disconnect = function() {
|
|||
|
||||
const err = state.handle.disconnect();
|
||||
if (err)
|
||||
throw errnoException(err, 'connect');
|
||||
throw new ErrnoException(err, 'connect');
|
||||
else
|
||||
state.connectState = CONNECT_STATE_DISCONNECTED;
|
||||
};
|
||||
|
@ -714,14 +715,14 @@ function doSend(ex, self, ip, list, address, port, callback) {
|
|||
|
||||
if (err && callback) {
|
||||
// Don't emit as error, dgram_legacy.js compatibility
|
||||
const ex = exceptionWithHostPort(err, 'send', address, port);
|
||||
const ex = new ExceptionWithHostPort(err, 'send', address, port);
|
||||
process.nextTick(callback, ex);
|
||||
}
|
||||
}
|
||||
|
||||
function afterSend(err, sent) {
|
||||
if (err) {
|
||||
err = exceptionWithHostPort(err, 'send', this.address, this.port);
|
||||
err = new ExceptionWithHostPort(err, 'send', this.address, this.port);
|
||||
} else {
|
||||
err = null;
|
||||
}
|
||||
|
@ -772,7 +773,7 @@ Socket.prototype.address = function() {
|
|||
const out = {};
|
||||
const err = this[kStateSymbol].handle.getsockname(out);
|
||||
if (err) {
|
||||
throw errnoException(err, 'getsockname');
|
||||
throw new ErrnoException(err, 'getsockname');
|
||||
}
|
||||
|
||||
return out;
|
||||
|
@ -788,7 +789,7 @@ Socket.prototype.remoteAddress = function() {
|
|||
const out = {};
|
||||
const err = state.handle.getpeername(out);
|
||||
if (err)
|
||||
throw errnoException(err, 'getpeername');
|
||||
throw new ErrnoException(err, 'getpeername');
|
||||
|
||||
return out;
|
||||
};
|
||||
|
@ -797,7 +798,7 @@ Socket.prototype.remoteAddress = function() {
|
|||
Socket.prototype.setBroadcast = function(arg) {
|
||||
const err = this[kStateSymbol].handle.setBroadcast(arg ? 1 : 0);
|
||||
if (err) {
|
||||
throw errnoException(err, 'setBroadcast');
|
||||
throw new ErrnoException(err, 'setBroadcast');
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -807,7 +808,7 @@ Socket.prototype.setTTL = function(ttl) {
|
|||
|
||||
const err = this[kStateSymbol].handle.setTTL(ttl);
|
||||
if (err) {
|
||||
throw errnoException(err, 'setTTL');
|
||||
throw new ErrnoException(err, 'setTTL');
|
||||
}
|
||||
|
||||
return ttl;
|
||||
|
@ -819,7 +820,7 @@ Socket.prototype.setMulticastTTL = function(ttl) {
|
|||
|
||||
const err = this[kStateSymbol].handle.setMulticastTTL(ttl);
|
||||
if (err) {
|
||||
throw errnoException(err, 'setMulticastTTL');
|
||||
throw new ErrnoException(err, 'setMulticastTTL');
|
||||
}
|
||||
|
||||
return ttl;
|
||||
|
@ -829,7 +830,7 @@ Socket.prototype.setMulticastTTL = function(ttl) {
|
|||
Socket.prototype.setMulticastLoopback = function(arg) {
|
||||
const err = this[kStateSymbol].handle.setMulticastLoopback(arg ? 1 : 0);
|
||||
if (err) {
|
||||
throw errnoException(err, 'setMulticastLoopback');
|
||||
throw new ErrnoException(err, 'setMulticastLoopback');
|
||||
}
|
||||
|
||||
return arg; // 0.4 compatibility
|
||||
|
@ -842,7 +843,7 @@ Socket.prototype.setMulticastInterface = function(interfaceAddress) {
|
|||
|
||||
const err = this[kStateSymbol].handle.setMulticastInterface(interfaceAddress);
|
||||
if (err) {
|
||||
throw errnoException(err, 'setMulticastInterface');
|
||||
throw new ErrnoException(err, 'setMulticastInterface');
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -857,7 +858,7 @@ Socket.prototype.addMembership = function(multicastAddress,
|
|||
const { handle } = this[kStateSymbol];
|
||||
const err = handle.addMembership(multicastAddress, interfaceAddress);
|
||||
if (err) {
|
||||
throw errnoException(err, 'addMembership');
|
||||
throw new ErrnoException(err, 'addMembership');
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -873,7 +874,7 @@ Socket.prototype.dropMembership = function(multicastAddress,
|
|||
const { handle } = this[kStateSymbol];
|
||||
const err = handle.dropMembership(multicastAddress, interfaceAddress);
|
||||
if (err) {
|
||||
throw errnoException(err, 'dropMembership');
|
||||
throw new ErrnoException(err, 'dropMembership');
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -890,7 +891,7 @@ Socket.prototype.addSourceSpecificMembership = function(sourceAddress,
|
|||
groupAddress,
|
||||
interfaceAddress);
|
||||
if (err) {
|
||||
throw errnoException(err, 'addSourceSpecificMembership');
|
||||
throw new ErrnoException(err, 'addSourceSpecificMembership');
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -908,7 +909,7 @@ Socket.prototype.dropSourceSpecificMembership = function(sourceAddress,
|
|||
groupAddress,
|
||||
interfaceAddress);
|
||||
if (err) {
|
||||
throw errnoException(err, 'dropSourceSpecificMembership');
|
||||
throw new ErrnoException(err, 'dropSourceSpecificMembership');
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -935,7 +936,7 @@ function stopReceiving(socket) {
|
|||
function onMessage(nread, handle, buf, rinfo) {
|
||||
const self = handle[owner_symbol];
|
||||
if (nread < 0) {
|
||||
return self.emit('error', errnoException(nread, 'recvmsg'));
|
||||
return self.emit('error', new ErrnoException(nread, 'recvmsg'));
|
||||
}
|
||||
rinfo.size = buf.length; // compatibility
|
||||
self.emit('message', buf, rinfo);
|
||||
|
|
26
lib/dns.js
26
lib/dns.js
|
@ -30,7 +30,14 @@ const {
|
|||
const cares = internalBinding('cares_wrap');
|
||||
const { isIP } = require('internal/net');
|
||||
const { customPromisifyArgs } = require('internal/util');
|
||||
const errors = require('internal/errors');
|
||||
const {
|
||||
codes: {
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
ERR_INVALID_ARG_VALUE,
|
||||
ERR_MISSING_ARGS,
|
||||
},
|
||||
DNSException,
|
||||
} = require('internal/errors');
|
||||
const {
|
||||
bindDefaultResolver,
|
||||
setDefaultResolver,
|
||||
|
@ -70,11 +77,6 @@ const {
|
|||
ADDRGETNETWORKPARAMS,
|
||||
CANCELLED,
|
||||
} = dnsErrorCodes;
|
||||
const {
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
ERR_INVALID_ARG_VALUE,
|
||||
ERR_MISSING_ARGS,
|
||||
} = errors.codes;
|
||||
const {
|
||||
validateBoolean,
|
||||
validateFunction,
|
||||
|
@ -98,13 +100,11 @@ const {
|
|||
stopPerf,
|
||||
} = require('internal/perf/observe');
|
||||
|
||||
const dnsException = errors.dnsException;
|
||||
|
||||
let promises = null; // Lazy loaded
|
||||
|
||||
function onlookup(err, addresses) {
|
||||
if (err) {
|
||||
return this.callback(dnsException(err, 'getaddrinfo', this.hostname));
|
||||
return this.callback(new DNSException(err, 'getaddrinfo', this.hostname));
|
||||
}
|
||||
this.callback(null, addresses[0], this.family || isIP(addresses[0]));
|
||||
if (this[kPerfHooksDnsLookupContext] && hasObserver('dns')) {
|
||||
|
@ -115,7 +115,7 @@ function onlookup(err, addresses) {
|
|||
|
||||
function onlookupall(err, addresses) {
|
||||
if (err) {
|
||||
return this.callback(dnsException(err, 'getaddrinfo', this.hostname));
|
||||
return this.callback(new DNSException(err, 'getaddrinfo', this.hostname));
|
||||
}
|
||||
|
||||
const family = this.family;
|
||||
|
@ -222,7 +222,7 @@ function lookup(hostname, options, callback) {
|
|||
req, hostname, family, hints, verbatim,
|
||||
);
|
||||
if (err) {
|
||||
process.nextTick(callback, dnsException(err, 'getaddrinfo', hostname));
|
||||
process.nextTick(callback, new DNSException(err, 'getaddrinfo', hostname));
|
||||
return {};
|
||||
}
|
||||
if (hasObserver('dns')) {
|
||||
|
@ -243,7 +243,7 @@ ObjectDefineProperty(lookup, customPromisifyArgs,
|
|||
|
||||
function onlookupservice(err, hostname, service) {
|
||||
if (err)
|
||||
return this.callback(dnsException(err, 'getnameinfo', this.hostname));
|
||||
return this.callback(new DNSException(err, 'getnameinfo', this.hostname));
|
||||
|
||||
this.callback(null, hostname, service);
|
||||
if (this[kPerfHooksDnsLookupServiceContext] && hasObserver('dns')) {
|
||||
|
@ -272,7 +272,7 @@ function lookupService(address, port, callback) {
|
|||
req.oncomplete = onlookupservice;
|
||||
|
||||
const err = cares.getnameinfo(req, address, port);
|
||||
if (err) throw dnsException(err, 'getnameinfo', address);
|
||||
if (err) throw new DNSException(err, 'getnameinfo', address);
|
||||
if (hasObserver('dns')) {
|
||||
startPerf(req, kPerfHooksDnsLookupServiceContext, {
|
||||
type: 'dns',
|
||||
|
|
|
@ -73,7 +73,7 @@ const {
|
|||
},
|
||||
AbortError,
|
||||
uvErrmapGet,
|
||||
uvException,
|
||||
UVException,
|
||||
} = require('internal/errors');
|
||||
|
||||
const {
|
||||
|
@ -402,7 +402,7 @@ function tryStatSync(fd, isUserFd) {
|
|||
const stats = binding.fstat(fd, false, undefined, ctx);
|
||||
if (ctx.errno !== undefined && !isUserFd) {
|
||||
fs.closeSync(fd);
|
||||
throw uvException(ctx);
|
||||
throw new UVException(ctx);
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ const {
|
|||
} = primordials;
|
||||
|
||||
const {
|
||||
errnoException,
|
||||
ErrnoException,
|
||||
codes: {
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
ERR_INVALID_ARG_VALUE,
|
||||
|
@ -283,7 +283,7 @@ function ChildProcess() {
|
|||
|
||||
if (exitCode < 0) {
|
||||
const syscall = this.spawnfile ? 'spawn ' + this.spawnfile : 'spawn';
|
||||
const err = errnoException(exitCode, syscall);
|
||||
const err = new ErrnoException(exitCode, syscall);
|
||||
|
||||
if (this.spawnfile)
|
||||
err.path = this.spawnfile;
|
||||
|
@ -418,7 +418,7 @@ ChildProcess.prototype.spawn = function(options) {
|
|||
|
||||
this._handle.close();
|
||||
this._handle = null;
|
||||
throw errnoException(err, 'spawn');
|
||||
throw new ErrnoException(err, 'spawn');
|
||||
} else {
|
||||
process.nextTick(onSpawnNT, this);
|
||||
}
|
||||
|
@ -506,10 +506,10 @@ ChildProcess.prototype.kill = function(sig) {
|
|||
/* Already dead. */
|
||||
} else if (err === UV_EINVAL || err === UV_ENOSYS) {
|
||||
/* The underlying platform doesn't support this signal. */
|
||||
throw errnoException(err, 'kill');
|
||||
throw new ErrnoException(err, 'kill');
|
||||
} else {
|
||||
/* Other error, almost certainly EPERM. */
|
||||
this.emit('error', errnoException(err, 'kill'));
|
||||
this.emit('error', new ErrnoException(err, 'kill'));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -876,7 +876,7 @@ function setupChannel(target, channel, serializationMode) {
|
|||
obj.postSend(message, handle, options, callback);
|
||||
|
||||
if (!options.swallowErrors) {
|
||||
const ex = errnoException(err, 'write');
|
||||
const ex = new ErrnoException(err, 'write');
|
||||
if (typeof callback === 'function') {
|
||||
process.nextTick(callback, ex);
|
||||
} else {
|
||||
|
@ -1121,7 +1121,7 @@ function spawnSync(options) {
|
|||
result.stderr = result.output && result.output[2];
|
||||
|
||||
if (result.error) {
|
||||
result.error = errnoException(result.error, 'spawnSync ' + options.file);
|
||||
result.error = new ErrnoException(result.error, 'spawnSync ' + options.file);
|
||||
result.error.path = options.file;
|
||||
result.error.spawnargs = ArrayPrototypeSlice(options.args, 1);
|
||||
}
|
||||
|
|
|
@ -49,15 +49,15 @@ const {
|
|||
} = require('internal/errors');
|
||||
|
||||
const validateParameters = hideStackFrames((hash, key, salt, info, length) => {
|
||||
validateString(hash, 'digest');
|
||||
validateString.withoutStackTrace(hash, 'digest');
|
||||
key = prepareKey(key);
|
||||
salt = validateByteSource(salt, 'salt');
|
||||
info = validateByteSource(info, 'info');
|
||||
salt = validateByteSource.withoutStackTrace(salt, 'salt');
|
||||
info = validateByteSource.withoutStackTrace(info, 'info');
|
||||
|
||||
validateInteger(length, 'length', 0, kMaxLength);
|
||||
validateInteger.withoutStackTrace(length, 'length', 0, kMaxLength);
|
||||
|
||||
if (info.byteLength > 1024) {
|
||||
throw new ERR_OUT_OF_RANGE(
|
||||
throw new ERR_OUT_OF_RANGE.HideStackFramesError(
|
||||
'info',
|
||||
'must not contain more than 1024 bytes',
|
||||
info.byteLength);
|
||||
|
|
|
@ -116,7 +116,7 @@ const getArrayBufferOrView = hideStackFrames((buffer, name, encoding) => {
|
|||
return Buffer.from(buffer, encoding);
|
||||
}
|
||||
if (!isArrayBufferView(buffer)) {
|
||||
throw new ERR_INVALID_ARG_TYPE(
|
||||
throw new ERR_INVALID_ARG_TYPE.HideStackFramesError(
|
||||
name,
|
||||
[
|
||||
'string',
|
||||
|
@ -403,7 +403,7 @@ const validateByteSource = hideStackFrames((val, name) => {
|
|||
if (isAnyArrayBuffer(val) || isArrayBufferView(val))
|
||||
return val;
|
||||
|
||||
throw new ERR_INVALID_ARG_TYPE(
|
||||
throw new ERR_INVALID_ARG_TYPE.HideStackFramesError(
|
||||
name,
|
||||
[
|
||||
'string',
|
||||
|
|
|
@ -12,7 +12,7 @@ const {
|
|||
ERR_INVALID_ARG_TYPE,
|
||||
ERR_INVALID_ARG_VALUE,
|
||||
},
|
||||
dnsException,
|
||||
DNSException,
|
||||
} = require('internal/errors');
|
||||
|
||||
const {
|
||||
|
@ -42,7 +42,7 @@ function onresolve(err, result, ttls) {
|
|||
result, (address, index) => ({ address, ttl: ttls[index] }));
|
||||
|
||||
if (err)
|
||||
this.callback(dnsException(err, this.bindingName, this.hostname));
|
||||
this.callback(new DNSException(err, this.bindingName, this.hostname));
|
||||
else {
|
||||
this.callback(null, result);
|
||||
if (this[kPerfHooksDnsLookupResolveContext] && hasObserver('dns')) {
|
||||
|
@ -69,7 +69,7 @@ function resolver(bindingName) {
|
|||
req.oncomplete = onresolve;
|
||||
req.ttl = !!(options && options.ttl);
|
||||
const err = this._handle[bindingName](req, name);
|
||||
if (err) throw dnsException(err, bindingName, name);
|
||||
if (err) throw new DNSException(err, bindingName, name);
|
||||
if (hasObserver('dns')) {
|
||||
startPerf(req, kPerfHooksDnsLookupResolveContext, {
|
||||
type: 'dns',
|
||||
|
|
|
@ -45,7 +45,7 @@ const {
|
|||
ADDRGETNETWORKPARAMS,
|
||||
CANCELLED,
|
||||
} = dnsErrorCodes;
|
||||
const { codes, dnsException } = require('internal/errors');
|
||||
const { codes, DNSException } = require('internal/errors');
|
||||
const { isIP } = require('internal/net');
|
||||
const {
|
||||
getaddrinfo,
|
||||
|
@ -79,7 +79,7 @@ const {
|
|||
|
||||
function onlookup(err, addresses) {
|
||||
if (err) {
|
||||
this.reject(dnsException(err, 'getaddrinfo', this.hostname));
|
||||
this.reject(new DNSException(err, 'getaddrinfo', this.hostname));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ function onlookup(err, addresses) {
|
|||
|
||||
function onlookupall(err, addresses) {
|
||||
if (err) {
|
||||
this.reject(dnsException(err, 'getaddrinfo', this.hostname));
|
||||
this.reject(new DNSException(err, 'getaddrinfo', this.hostname));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,7 @@ function createLookupPromise(family, hostname, all, hints, verbatim) {
|
|||
const err = getaddrinfo(req, hostname, family, hints, verbatim);
|
||||
|
||||
if (err) {
|
||||
reject(dnsException(err, 'getaddrinfo', hostname));
|
||||
reject(new DNSException(err, 'getaddrinfo', hostname));
|
||||
} else if (hasObserver('dns')) {
|
||||
const detail = {
|
||||
hostname,
|
||||
|
@ -220,7 +220,7 @@ function lookup(hostname, options) {
|
|||
|
||||
function onlookupservice(err, hostname, service) {
|
||||
if (err) {
|
||||
this.reject(dnsException(err, 'getnameinfo', this.host));
|
||||
this.reject(new DNSException(err, 'getnameinfo', this.host));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -243,7 +243,7 @@ function createLookupServicePromise(hostname, port) {
|
|||
const err = getnameinfo(req, hostname, port);
|
||||
|
||||
if (err)
|
||||
reject(dnsException(err, 'getnameinfo', hostname));
|
||||
reject(new DNSException(err, 'getnameinfo', hostname));
|
||||
else if (hasObserver('dns')) {
|
||||
startPerf(req, kPerfHooksDnsLookupServiceContext, {
|
||||
type: 'dns',
|
||||
|
@ -272,7 +272,7 @@ function lookupService(address, port) {
|
|||
|
||||
function onresolve(err, result, ttls) {
|
||||
if (err) {
|
||||
this.reject(dnsException(err, this.bindingName, this.hostname));
|
||||
this.reject(new DNSException(err, this.bindingName, this.hostname));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -300,7 +300,7 @@ function createResolverPromise(resolver, bindingName, hostname, ttl) {
|
|||
const err = resolver._handle[bindingName](req, hostname);
|
||||
|
||||
if (err)
|
||||
reject(dnsException(err, bindingName, hostname));
|
||||
reject(new DNSException(err, bindingName, hostname));
|
||||
else if (hasObserver('dns')) {
|
||||
startPerf(req, kPerfHooksDnsLookupResolveContext, {
|
||||
type: 'dns',
|
||||
|
|
|
@ -86,8 +86,7 @@ const kTypes = [
|
|||
const MainContextError = Error;
|
||||
const overrideStackTrace = new SafeWeakMap();
|
||||
const kNoOverride = Symbol('kNoOverride');
|
||||
let userStackTraceLimit;
|
||||
const nodeInternalPrefix = '__node_internal_';
|
||||
|
||||
const prepareStackTrace = (globalThis, error, trace) => {
|
||||
// API for node internals to override error stack formatting
|
||||
// without interfering with userland code.
|
||||
|
@ -97,21 +96,6 @@ const prepareStackTrace = (globalThis, error, trace) => {
|
|||
return f(error, trace);
|
||||
}
|
||||
|
||||
const firstFrame = trace[0]?.getFunctionName();
|
||||
if (firstFrame && StringPrototypeStartsWith(firstFrame, nodeInternalPrefix)) {
|
||||
for (let l = trace.length - 1; l >= 0; l--) {
|
||||
const fn = trace[l]?.getFunctionName();
|
||||
if (fn && StringPrototypeStartsWith(fn, nodeInternalPrefix)) {
|
||||
ArrayPrototypeSplice(trace, 0, l + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// `userStackTraceLimit` is the user value for `Error.stackTraceLimit`,
|
||||
// it is updated at every new exception in `captureLargerStackTrace`.
|
||||
if (trace.length > userStackTraceLimit)
|
||||
ArrayPrototypeSplice(trace, userStackTraceLimit);
|
||||
}
|
||||
|
||||
const globalOverride =
|
||||
maybeOverridePrepareStackTrace(globalThis, error, trace);
|
||||
if (globalOverride !== kNoOverride) return globalOverride;
|
||||
|
@ -151,30 +135,51 @@ const maybeOverridePrepareStackTrace = (globalThis, error, trace) => {
|
|||
return kNoOverride;
|
||||
};
|
||||
|
||||
const aggregateTwoErrors = hideStackFrames((innerError, outerError) => {
|
||||
const aggregateTwoErrors = (innerError, outerError) => {
|
||||
if (innerError && outerError && innerError !== outerError) {
|
||||
if (ArrayIsArray(outerError.errors)) {
|
||||
// If `outerError` is already an `AggregateError`.
|
||||
ArrayPrototypePush(outerError.errors, innerError);
|
||||
return outerError;
|
||||
}
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const err = new AggregateError(new SafeArrayIterator([
|
||||
outerError,
|
||||
innerError,
|
||||
]), outerError.message);
|
||||
let err;
|
||||
if (isErrorStackTraceLimitWritable()) {
|
||||
const limit = Error.stackTraceLimit;
|
||||
Error.stackTraceLimit = 0;
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
err = new AggregateError(new SafeArrayIterator([
|
||||
outerError,
|
||||
innerError,
|
||||
]), outerError.message);
|
||||
Error.stackTraceLimit = limit;
|
||||
ErrorCaptureStackTrace(err, aggregateTwoErrors);
|
||||
} else {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
err = new AggregateError(new SafeArrayIterator([
|
||||
outerError,
|
||||
innerError,
|
||||
]), outerError.message);
|
||||
}
|
||||
err.code = outerError.code;
|
||||
return err;
|
||||
}
|
||||
return innerError || outerError;
|
||||
});
|
||||
};
|
||||
|
||||
const aggregateErrors = hideStackFrames((errors, message, code) => {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const err = new AggregateError(new SafeArrayIterator(errors), message);
|
||||
err.code = errors[0]?.code;
|
||||
return err;
|
||||
});
|
||||
class NodeAggregateError extends AggregateError {
|
||||
constructor(errors, message) {
|
||||
super(new SafeArrayIterator(errors), message);
|
||||
this.code = errors[0]?.code;
|
||||
}
|
||||
|
||||
get [kIsNodeError]() {
|
||||
return true;
|
||||
}
|
||||
|
||||
get ['constructor']() {
|
||||
return AggregateError;
|
||||
}
|
||||
}
|
||||
|
||||
const assert = require('internal/assert');
|
||||
|
||||
|
@ -242,11 +247,7 @@ function inspectWithNoCustomRetry(obj, options) {
|
|||
// and may have .path and .dest.
|
||||
class SystemError extends Error {
|
||||
constructor(key, context) {
|
||||
const limit = Error.stackTraceLimit;
|
||||
if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = 0;
|
||||
super();
|
||||
// Reset the limit and setting the name property.
|
||||
if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = limit;
|
||||
const prefix = getMessage(key, [], this);
|
||||
let message = `${prefix}: ${context.syscall} returned ` +
|
||||
`${context.code} (${context.message})`;
|
||||
|
@ -256,8 +257,6 @@ class SystemError extends Error {
|
|||
if (context.dest !== undefined)
|
||||
message += ` => ${context.dest}`;
|
||||
|
||||
captureLargerStackTrace(this);
|
||||
|
||||
this.code = key;
|
||||
|
||||
ObjectDefineProperties(this, {
|
||||
|
@ -372,6 +371,33 @@ function makeSystemErrorWithCode(key) {
|
|||
};
|
||||
}
|
||||
|
||||
// This is a special error type that is only used for the E function.
|
||||
class HideStackFramesError extends Error {
|
||||
}
|
||||
|
||||
function makeNodeErrorForHideStackFrame(Base, clazz) {
|
||||
class HideStackFramesError extends Base {
|
||||
constructor(...args) {
|
||||
if (isErrorStackTraceLimitWritable()) {
|
||||
const limit = Error.stackTraceLimit;
|
||||
Error.stackTraceLimit = 0;
|
||||
super(...args);
|
||||
Error.stackTraceLimit = limit;
|
||||
} else {
|
||||
super(...args);
|
||||
}
|
||||
}
|
||||
|
||||
// This is a workaround for wpt tests that expect that the error
|
||||
// constructor has a `name` property of the base class.
|
||||
get ['constructor']() {
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
|
||||
return HideStackFramesError;
|
||||
}
|
||||
|
||||
function makeNodeErrorWithCode(Base, key) {
|
||||
const msg = messages.get(key);
|
||||
const expectedLength = typeof msg !== 'string' ? -1 : getExpectedArgumentLength(msg);
|
||||
|
@ -479,11 +505,16 @@ function makeNodeErrorWithCode(Base, key) {
|
|||
* @returns {T}
|
||||
*/
|
||||
function hideStackFrames(fn) {
|
||||
// We rename the functions that will be hidden to cut off the stacktrace
|
||||
// at the outermost one
|
||||
const hidden = nodeInternalPrefix + fn.name;
|
||||
ObjectDefineProperty(fn, 'name', { __proto__: null, value: hidden });
|
||||
return fn;
|
||||
function wrappedFn(...args) {
|
||||
try {
|
||||
return ReflectApply(fn, this, args);
|
||||
} catch (error) {
|
||||
Error.stackTraceLimit && ErrorCaptureStackTrace(error, wrappedFn);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
wrappedFn.withoutStackTrace = fn;
|
||||
return wrappedFn;
|
||||
}
|
||||
|
||||
// Utility function for registering the error codes. Only used here. Exported
|
||||
|
@ -492,18 +523,33 @@ function E(sym, val, def, ...otherClasses) {
|
|||
// Special case for SystemError that formats the error message differently
|
||||
// The SystemErrors only have SystemError as their base classes.
|
||||
messages.set(sym, val);
|
||||
if (def === SystemError) {
|
||||
def = makeSystemErrorWithCode(sym);
|
||||
} else {
|
||||
def = makeNodeErrorWithCode(def, sym);
|
||||
}
|
||||
|
||||
const ErrClass = def === SystemError ?
|
||||
makeSystemErrorWithCode(sym) :
|
||||
makeNodeErrorWithCode(def, sym);
|
||||
|
||||
if (otherClasses.length !== 0) {
|
||||
otherClasses.forEach((clazz) => {
|
||||
def[clazz.name] = makeNodeErrorWithCode(clazz, sym);
|
||||
});
|
||||
if (otherClasses.includes(HideStackFramesError)) {
|
||||
if (otherClasses.length !== 1) {
|
||||
otherClasses.forEach((clazz) => {
|
||||
if (clazz !== HideStackFramesError) {
|
||||
ErrClass[clazz.name] = makeNodeErrorWithCode(clazz, sym);
|
||||
ErrClass[clazz.name].HideStackFramesError = makeNodeErrorForHideStackFrame(ErrClass[clazz.name], clazz);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
otherClasses.forEach((clazz) => {
|
||||
ErrClass[clazz.name] = makeNodeErrorWithCode(clazz, sym);
|
||||
});
|
||||
}
|
||||
}
|
||||
codes[sym] = def;
|
||||
|
||||
if (otherClasses.includes(HideStackFramesError)) {
|
||||
ErrClass.HideStackFramesError = makeNodeErrorForHideStackFrame(ErrClass, def);
|
||||
}
|
||||
|
||||
codes[sym] = ErrClass;
|
||||
}
|
||||
|
||||
function getExpectedArgumentLength(msg) {
|
||||
|
@ -553,84 +599,67 @@ function uvErrmapGet(name) {
|
|||
return MapPrototypeGet(uvBinding.errmap, name);
|
||||
}
|
||||
|
||||
const captureLargerStackTrace = hideStackFrames(
|
||||
function captureLargerStackTrace(err) {
|
||||
const stackTraceLimitIsWritable = isErrorStackTraceLimitWritable();
|
||||
if (stackTraceLimitIsWritable) {
|
||||
userStackTraceLimit = Error.stackTraceLimit;
|
||||
Error.stackTraceLimit = Infinity;
|
||||
}
|
||||
ErrorCaptureStackTrace(err);
|
||||
// Reset the limit
|
||||
if (stackTraceLimitIsWritable) Error.stackTraceLimit = userStackTraceLimit;
|
||||
|
||||
return err;
|
||||
});
|
||||
|
||||
/**
|
||||
* This creates an error compatible with errors produced in the C++
|
||||
* function UVException using a context object with data assembled in C++.
|
||||
* The goal is to migrate them to ERR_* errors later when compatibility is
|
||||
* not a concern.
|
||||
* @param {object} ctx
|
||||
* @returns {Error}
|
||||
*/
|
||||
const uvException = hideStackFrames(function uvException(ctx) {
|
||||
const { 0: code, 1: uvmsg } = uvErrmapGet(ctx.errno) || uvUnmappedError;
|
||||
let message = `${code}: ${ctx.message || uvmsg}, ${ctx.syscall}`;
|
||||
class UVException extends Error {
|
||||
/**
|
||||
* @param {object} ctx
|
||||
*/
|
||||
constructor(ctx) {
|
||||
const { 0: code, 1: uvmsg } = uvErrmapGet(ctx.errno) || uvUnmappedError;
|
||||
let message = `${code}: ${ctx.message || uvmsg}, ${ctx.syscall}`;
|
||||
|
||||
let path;
|
||||
let dest;
|
||||
if (ctx.path) {
|
||||
path = ctx.path.toString();
|
||||
message += ` '${path}'`;
|
||||
}
|
||||
if (ctx.dest) {
|
||||
dest = ctx.dest.toString();
|
||||
message += ` -> '${dest}'`;
|
||||
}
|
||||
|
||||
// Reducing the limit improves the performance significantly. We do not lose
|
||||
// the stack frames due to the `captureStackTrace()` function that is called
|
||||
// later.
|
||||
const tmpLimit = Error.stackTraceLimit;
|
||||
if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = 0;
|
||||
// Pass the message to the constructor instead of setting it on the object
|
||||
// to make sure it is the same as the one created in C++
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const err = new Error(message);
|
||||
if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = tmpLimit;
|
||||
|
||||
for (const prop of ObjectKeys(ctx)) {
|
||||
if (prop === 'message' || prop === 'path' || prop === 'dest') {
|
||||
continue;
|
||||
let path;
|
||||
let dest;
|
||||
if (ctx.path) {
|
||||
path = ctx.path.toString();
|
||||
message += ` '${path}'`;
|
||||
}
|
||||
if (ctx.dest) {
|
||||
dest = ctx.dest.toString();
|
||||
message += ` -> '${dest}'`;
|
||||
}
|
||||
|
||||
super(message);
|
||||
|
||||
for (const prop of ObjectKeys(ctx)) {
|
||||
if (prop === 'message' || prop === 'path' || prop === 'dest') {
|
||||
continue;
|
||||
}
|
||||
this[prop] = ctx[prop];
|
||||
}
|
||||
|
||||
this.code = code;
|
||||
if (path) {
|
||||
this.path = path;
|
||||
}
|
||||
if (dest) {
|
||||
this.dest = dest;
|
||||
}
|
||||
err[prop] = ctx[prop];
|
||||
}
|
||||
|
||||
err.code = code;
|
||||
if (path) {
|
||||
err.path = path;
|
||||
get ['constructor']() {
|
||||
return Error;
|
||||
}
|
||||
if (dest) {
|
||||
err.dest = dest;
|
||||
}
|
||||
|
||||
return captureLargerStackTrace(err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This creates an error compatible with errors produced in the C++
|
||||
* This function should replace the deprecated
|
||||
* `exceptionWithHostPort()` function.
|
||||
* @param {number} err - A libuv error number
|
||||
* @param {string} syscall
|
||||
* @param {string} address
|
||||
* @param {number} [port]
|
||||
* @returns {Error}
|
||||
*/
|
||||
const uvExceptionWithHostPort = hideStackFrames(
|
||||
function uvExceptionWithHostPort(err, syscall, address, port) {
|
||||
class UVExceptionWithHostPort extends Error {
|
||||
/**
|
||||
* @param {number} err - A libuv error number
|
||||
* @param {string} syscall
|
||||
* @param {string} address
|
||||
* @param {number} [port]
|
||||
*/
|
||||
constructor(err, syscall, address, port) {
|
||||
const { 0: code, 1: uvmsg } = uvErrmapGet(err) || uvUnmappedError;
|
||||
const message = `${syscall} ${code}: ${uvmsg}`;
|
||||
let details = '';
|
||||
|
@ -641,34 +670,32 @@ const uvExceptionWithHostPort = hideStackFrames(
|
|||
details = ` ${address}`;
|
||||
}
|
||||
|
||||
// Reducing the limit improves the performance significantly. We do not
|
||||
// lose the stack frames due to the `captureStackTrace()` function that
|
||||
// is called later.
|
||||
const tmpLimit = Error.stackTraceLimit;
|
||||
if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = 0;
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const ex = new Error(`${message}${details}`);
|
||||
if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = tmpLimit;
|
||||
ex.code = code;
|
||||
ex.errno = err;
|
||||
ex.syscall = syscall;
|
||||
ex.address = address;
|
||||
if (port) {
|
||||
ex.port = port;
|
||||
}
|
||||
super(`${message}${details}`);
|
||||
|
||||
return captureLargerStackTrace(ex);
|
||||
});
|
||||
this.code = code;
|
||||
this.errno = err;
|
||||
this.syscall = syscall;
|
||||
this.address = address;
|
||||
if (port) {
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
|
||||
get ['constructor']() {
|
||||
return Error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This used to be util._errnoException().
|
||||
* @param {number} err - A libuv error number
|
||||
* @param {string} syscall
|
||||
* @param {string} [original]
|
||||
* @returns {Error}
|
||||
*/
|
||||
const errnoException = hideStackFrames(
|
||||
function errnoException(err, syscall, original) {
|
||||
class ErrnoException extends Error {
|
||||
/**
|
||||
* @param {number} err - A libuv error number
|
||||
* @param {string} syscall
|
||||
* @param {string} [original] err
|
||||
*/
|
||||
constructor(err, syscall, original) {
|
||||
// TODO(joyeecheung): We have to use the type-checked
|
||||
// getSystemErrorName(err) to guard against invalid arguments from users.
|
||||
// This can be replaced with [ code ] = errmap.get(err) when this method
|
||||
|
@ -678,20 +705,20 @@ const errnoException = hideStackFrames(
|
|||
const message = original ?
|
||||
`${syscall} ${code} ${original}` : `${syscall} ${code}`;
|
||||
|
||||
const tmpLimit = Error.stackTraceLimit;
|
||||
if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = 0;
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const ex = new Error(message);
|
||||
if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = tmpLimit;
|
||||
ex.errno = err;
|
||||
ex.code = code;
|
||||
ex.syscall = syscall;
|
||||
super(message);
|
||||
|
||||
return captureLargerStackTrace(ex);
|
||||
});
|
||||
this.errno = err;
|
||||
this.code = code;
|
||||
this.syscall = syscall;
|
||||
}
|
||||
|
||||
get ['constructor']() {
|
||||
return Error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated, new function is `uvExceptionWithHostPort()`
|
||||
* Deprecated, new Error is `UVExceptionWithHostPort()`
|
||||
* New function added the error description directly
|
||||
* from C++. this method for backwards compatibility
|
||||
* @param {number} err - A libuv error number
|
||||
|
@ -701,8 +728,8 @@ const errnoException = hideStackFrames(
|
|||
* @param {string} [additional]
|
||||
* @returns {Error}
|
||||
*/
|
||||
const exceptionWithHostPort = hideStackFrames(
|
||||
function exceptionWithHostPort(err, syscall, address, port, additional) {
|
||||
class ExceptionWithHostPort extends Error {
|
||||
constructor(err, syscall, address, port, additional) {
|
||||
// TODO(joyeecheung): We have to use the type-checked
|
||||
// getSystemErrorName(err) to guard against invalid arguments from users.
|
||||
// This can be replaced with [ code ] = errmap.get(err) when this method
|
||||
|
@ -719,78 +746,75 @@ const exceptionWithHostPort = hideStackFrames(
|
|||
details += ` - Local (${additional})`;
|
||||
}
|
||||
|
||||
// Reducing the limit improves the performance significantly. We do not
|
||||
// lose the stack frames due to the `captureStackTrace()` function that
|
||||
// is called later.
|
||||
const tmpLimit = Error.stackTraceLimit;
|
||||
if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = 0;
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const ex = new Error(`${syscall} ${code}${details}`);
|
||||
if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = tmpLimit;
|
||||
ex.errno = err;
|
||||
ex.code = code;
|
||||
ex.syscall = syscall;
|
||||
ex.address = address;
|
||||
super(`${syscall} ${code}${details}`);
|
||||
|
||||
this.errno = err;
|
||||
this.code = code;
|
||||
this.syscall = syscall;
|
||||
this.address = address;
|
||||
if (port) {
|
||||
ex.port = port;
|
||||
}
|
||||
|
||||
return captureLargerStackTrace(ex);
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {number|string} code - A libuv error number or a c-ares error code
|
||||
* @param {string} syscall
|
||||
* @param {string} [hostname]
|
||||
* @returns {Error}
|
||||
*/
|
||||
const dnsException = hideStackFrames(function(code, syscall, hostname) {
|
||||
let errno;
|
||||
// If `code` is of type number, it is a libuv error number, else it is a
|
||||
// c-ares error code.
|
||||
// TODO(joyeecheung): translate c-ares error codes into numeric ones and
|
||||
// make them available in a property that's not error.errno (since they
|
||||
// can be in conflict with libuv error codes). Also make sure
|
||||
// util.getSystemErrorName() can understand them when an being informed that
|
||||
// the number is a c-ares error code.
|
||||
if (typeof code === 'number') {
|
||||
errno = code;
|
||||
// ENOTFOUND is not a proper POSIX error, but this error has been in place
|
||||
// long enough that it's not practical to remove it.
|
||||
if (code === lazyUv().UV_EAI_NODATA || code === lazyUv().UV_EAI_NONAME) {
|
||||
code = 'ENOTFOUND'; // Fabricated error name.
|
||||
} else {
|
||||
code = lazyInternalUtil().getSystemErrorName(code);
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
const message = `${syscall} ${code}${hostname ? ` ${hostname}` : ''}`;
|
||||
// Reducing the limit improves the performance significantly. We do not lose
|
||||
// the stack frames due to the `captureStackTrace()` function that is called
|
||||
// later.
|
||||
const tmpLimit = Error.stackTraceLimit;
|
||||
if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = 0;
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const ex = new Error(message);
|
||||
if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = tmpLimit;
|
||||
ex.errno = errno;
|
||||
ex.code = code;
|
||||
ex.syscall = syscall;
|
||||
if (hostname) {
|
||||
ex.hostname = hostname;
|
||||
|
||||
get ['constructor']() {
|
||||
return Error;
|
||||
}
|
||||
}
|
||||
|
||||
class DNSException extends Error {
|
||||
/**
|
||||
* @param {number|string} code - A libuv error number or a c-ares error code
|
||||
* @param {string} syscall
|
||||
* @param {string} [hostname]
|
||||
*/
|
||||
constructor(code, syscall, hostname) {
|
||||
let errno;
|
||||
// If `code` is of type number, it is a libuv error number, else it is a
|
||||
// c-ares error code.
|
||||
// TODO(joyeecheung): translate c-ares error codes into numeric ones and
|
||||
// make them available in a property that's not error.errno (since they
|
||||
// can be in conflict with libuv error codes). Also make sure
|
||||
// util.getSystemErrorName() can understand them when an being informed that
|
||||
// the number is a c-ares error code.
|
||||
if (typeof code === 'number') {
|
||||
errno = code;
|
||||
// ENOTFOUND is not a proper POSIX error, but this error has been in place
|
||||
// long enough that it's not practical to remove it.
|
||||
if (code === lazyUv().UV_EAI_NODATA || code === lazyUv().UV_EAI_NONAME) {
|
||||
code = 'ENOTFOUND'; // Fabricated error name.
|
||||
} else {
|
||||
code = lazyInternalUtil().getSystemErrorName(code);
|
||||
}
|
||||
}
|
||||
super(`${syscall} ${code}${hostname ? ` ${hostname}` : ''}`);
|
||||
this.errno = errno;
|
||||
this.code = code;
|
||||
this.syscall = syscall;
|
||||
if (hostname) {
|
||||
this.hostname = hostname;
|
||||
}
|
||||
}
|
||||
|
||||
return captureLargerStackTrace(ex);
|
||||
});
|
||||
get ['constructor']() {
|
||||
return Error;
|
||||
}
|
||||
}
|
||||
|
||||
function connResetException(msg) {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const ex = new Error(msg);
|
||||
ex.code = 'ECONNRESET';
|
||||
return ex;
|
||||
class ConnResetException extends Error {
|
||||
constructor(msg) {
|
||||
super(msg);
|
||||
this.code = 'ECONNRESET';
|
||||
}
|
||||
|
||||
get ['constructor']() {
|
||||
return Error;
|
||||
}
|
||||
}
|
||||
|
||||
let maxStack_ErrorName;
|
||||
let maxStack_ErrorMessage;
|
||||
|
||||
/**
|
||||
* Returns true if `err.name` and `err.message` are equal to engine-specific
|
||||
* values indicating max call stack size has been exceeded.
|
||||
|
@ -1011,16 +1035,15 @@ function formatList(array, type = 'and') {
|
|||
module.exports = {
|
||||
AbortError,
|
||||
aggregateTwoErrors,
|
||||
aggregateErrors,
|
||||
captureLargerStackTrace,
|
||||
NodeAggregateError,
|
||||
codes,
|
||||
connResetException,
|
||||
dnsException,
|
||||
ConnResetException,
|
||||
DNSException,
|
||||
// This is exported only to facilitate testing.
|
||||
determineSpecificType,
|
||||
E,
|
||||
errnoException,
|
||||
exceptionWithHostPort,
|
||||
ErrnoException,
|
||||
ExceptionWithHostPort,
|
||||
fatalExceptionStackEnhancers,
|
||||
formatList,
|
||||
genericNodeError,
|
||||
|
@ -1039,8 +1062,8 @@ module.exports = {
|
|||
setArrowMessage,
|
||||
SystemError,
|
||||
uvErrmapGet,
|
||||
uvException,
|
||||
uvExceptionWithHostPort,
|
||||
UVException,
|
||||
UVExceptionWithHostPort,
|
||||
};
|
||||
|
||||
// To declare an error message, use the E(sym, val, def) function above. The sym
|
||||
|
@ -1147,7 +1170,7 @@ E('ERR_EVENT_RECURSION', 'The event "%s" is already being dispatched', Error);
|
|||
E('ERR_FALSY_VALUE_REJECTION', function(reason) {
|
||||
this.reason = reason;
|
||||
return 'Promise was rejected with falsy value';
|
||||
}, Error);
|
||||
}, Error, HideStackFramesError);
|
||||
E('ERR_FEATURE_UNAVAILABLE_ON_PLATFORM',
|
||||
'The feature %s is unavailable on the current platform' +
|
||||
', which is being used to run Node.js',
|
||||
|
@ -1163,7 +1186,7 @@ E('ERR_FS_CP_SOCKET', 'Cannot copy a socket file', SystemError);
|
|||
E('ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY',
|
||||
'Cannot overwrite symlink in subdirectory of self', SystemError);
|
||||
E('ERR_FS_CP_UNKNOWN', 'Cannot copy an unknown file type', SystemError);
|
||||
E('ERR_FS_EISDIR', 'Path is a directory', SystemError);
|
||||
E('ERR_FS_EISDIR', 'Path is a directory', SystemError, HideStackFramesError);
|
||||
E('ERR_FS_FILE_TOO_LARGE', 'File size (%s) is greater than 2 GiB', RangeError);
|
||||
E('ERR_FS_INVALID_SYMLINK_TYPE',
|
||||
'Symlink type must be one of "dir", "file", or "junction". Received "%s"',
|
||||
|
@ -1190,7 +1213,7 @@ E('ERR_HTTP2_INFO_STATUS_NOT_ALLOWED',
|
|||
E('ERR_HTTP2_INVALID_CONNECTION_HEADERS',
|
||||
'HTTP/1 Connection specific headers are forbidden: "%s"', TypeError);
|
||||
E('ERR_HTTP2_INVALID_HEADER_VALUE',
|
||||
'Invalid value "%s" for header "%s"', TypeError);
|
||||
'Invalid value "%s" for header "%s"', TypeError, HideStackFramesError);
|
||||
E('ERR_HTTP2_INVALID_INFO_STATUS',
|
||||
'Invalid informational status code: %s', RangeError);
|
||||
E('ERR_HTTP2_INVALID_ORIGIN',
|
||||
|
@ -1198,7 +1221,7 @@ E('ERR_HTTP2_INVALID_ORIGIN',
|
|||
E('ERR_HTTP2_INVALID_PACKED_SETTINGS_LENGTH',
|
||||
'Packed settings length must be a multiple of six', RangeError);
|
||||
E('ERR_HTTP2_INVALID_PSEUDOHEADER',
|
||||
'"%s" is an invalid pseudoheader or is used incorrectly', TypeError);
|
||||
'"%s" is an invalid pseudoheader or is used incorrectly', TypeError, HideStackFramesError);
|
||||
E('ERR_HTTP2_INVALID_SESSION', 'The session has been destroyed', Error);
|
||||
E('ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
// Using default arguments here is important so the arguments are not counted
|
||||
|
@ -1210,7 +1233,7 @@ E('ERR_HTTP2_INVALID_SETTING_VALUE',
|
|||
this.max = max;
|
||||
}
|
||||
return `Invalid value for setting "${name}": ${actual}`;
|
||||
}, TypeError, RangeError);
|
||||
}, TypeError, RangeError, HideStackFramesError);
|
||||
E('ERR_HTTP2_INVALID_STREAM', 'The stream has been destroyed', Error);
|
||||
E('ERR_HTTP2_MAX_PENDING_SETTINGS_ACK',
|
||||
'Maximum number of pending settings acknowledgements', Error);
|
||||
|
@ -1230,7 +1253,7 @@ E('ERR_HTTP2_PAYLOAD_FORBIDDEN',
|
|||
E('ERR_HTTP2_PING_CANCEL', 'HTTP2 ping cancelled', Error);
|
||||
E('ERR_HTTP2_PING_LENGTH', 'HTTP2 ping payload must be 8 bytes', RangeError);
|
||||
E('ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED',
|
||||
'Cannot set HTTP/2 pseudo-headers', TypeError);
|
||||
'Cannot set HTTP/2 pseudo-headers', TypeError, HideStackFramesError);
|
||||
E('ERR_HTTP2_PUSH_DISABLED', 'HTTP/2 client has disabled push streams', Error);
|
||||
E('ERR_HTTP2_SEND_FILE', 'Directories cannot be sent', Error);
|
||||
E('ERR_HTTP2_SEND_FILE_NOSEEK',
|
||||
|
@ -1270,7 +1293,7 @@ E('ERR_HTTP_CONTENT_LENGTH_MISMATCH',
|
|||
E('ERR_HTTP_HEADERS_SENT',
|
||||
'Cannot %s headers after they are sent to the client', Error);
|
||||
E('ERR_HTTP_INVALID_HEADER_VALUE',
|
||||
'Invalid value "%s" for header "%s"', TypeError);
|
||||
'Invalid value "%s" for header "%s"', TypeError, HideStackFramesError);
|
||||
E('ERR_HTTP_INVALID_STATUS_CODE', 'Invalid status code: %s', RangeError);
|
||||
E('ERR_HTTP_REQUEST_TIMEOUT', 'Request timeout', Error);
|
||||
E('ERR_HTTP_SOCKET_ASSIGNED',
|
||||
|
@ -1287,7 +1310,7 @@ E('ERR_IMPORT_ATTRIBUTE_TYPE_INCOMPATIBLE',
|
|||
E('ERR_IMPORT_ATTRIBUTE_UNSUPPORTED',
|
||||
'Import attribute "%s" with value "%s" is not supported', TypeError);
|
||||
E('ERR_INCOMPATIBLE_OPTION_PAIR',
|
||||
'Option "%s" cannot be used in combination with option "%s"', TypeError);
|
||||
'Option "%s" cannot be used in combination with option "%s"', TypeError, HideStackFramesError);
|
||||
E('ERR_INPUT_TYPE_NOT_ALLOWED', '--input-type can only be used with string ' +
|
||||
'input via --eval, --print, or STDIN', Error);
|
||||
E('ERR_INSPECTOR_ALREADY_ACTIVATED',
|
||||
|
@ -1383,7 +1406,7 @@ E('ERR_INVALID_ARG_TYPE',
|
|||
msg += `. Received ${determineSpecificType(actual)}`;
|
||||
|
||||
return msg;
|
||||
}, TypeError);
|
||||
}, TypeError, HideStackFramesError);
|
||||
E('ERR_INVALID_ARG_VALUE', (name, value, reason = 'is invalid') => {
|
||||
let inspected = lazyInternalUtilInspect().inspect(value);
|
||||
if (inspected.length > 128) {
|
||||
|
@ -1391,7 +1414,7 @@ E('ERR_INVALID_ARG_VALUE', (name, value, reason = 'is invalid') => {
|
|||
}
|
||||
const type = StringPrototypeIncludes(name, '.') ? 'property' : 'argument';
|
||||
return `The ${type} '${name}' ${reason}. Received ${inspected}`;
|
||||
}, TypeError, RangeError);
|
||||
}, TypeError, RangeError, HideStackFramesError);
|
||||
E('ERR_INVALID_ASYNC_ID', 'Invalid %s value: %s', RangeError);
|
||||
E('ERR_INVALID_BUFFER_SIZE',
|
||||
'Buffer size must be a multiple of %s', RangeError);
|
||||
|
@ -1404,7 +1427,7 @@ E('ERR_INVALID_CHAR',
|
|||
msg += ` ["${field}"]`;
|
||||
}
|
||||
return msg;
|
||||
}, TypeError);
|
||||
}, TypeError, HideStackFramesError);
|
||||
E('ERR_INVALID_CURSOR_POS',
|
||||
'Cannot set cursor row without setting its column', TypeError);
|
||||
E('ERR_INVALID_FD',
|
||||
|
@ -1414,7 +1437,7 @@ E('ERR_INVALID_FILE_URL_HOST',
|
|||
'File URL host must be "localhost" or empty on %s', TypeError);
|
||||
E('ERR_INVALID_FILE_URL_PATH', 'File URL path %s', TypeError);
|
||||
E('ERR_INVALID_HANDLE_TYPE', 'This handle type cannot be sent', TypeError);
|
||||
E('ERR_INVALID_HTTP_TOKEN', '%s must be a valid HTTP token ["%s"]', TypeError);
|
||||
E('ERR_INVALID_HTTP_TOKEN', '%s must be a valid HTTP token ["%s"]', TypeError, HideStackFramesError);
|
||||
E('ERR_INVALID_IP_ADDRESS', 'Invalid IP address: %s', TypeError);
|
||||
E('ERR_INVALID_MIME_SYNTAX', (production, str, invalidIndex) => {
|
||||
const msg = invalidIndex !== -1 ? ` at ${invalidIndex}` : '';
|
||||
|
@ -1603,7 +1626,7 @@ E('ERR_OUT_OF_RANGE',
|
|||
}
|
||||
msg += ` It must be ${range}. Received ${received}`;
|
||||
return msg;
|
||||
}, RangeError);
|
||||
}, RangeError, HideStackFramesError);
|
||||
E('ERR_PACKAGE_IMPORT_NOT_DEFINED', (specifier, packagePath, base) => {
|
||||
return `Package import specifier "${specifier}" is not defined${packagePath ?
|
||||
` in package ${packagePath}package.json` : ''} imported from ${base}`;
|
||||
|
@ -1669,7 +1692,7 @@ E('ERR_SOCKET_BAD_PORT', (name, port, allowZero = true) => {
|
|||
"The 'allowZero' argument must be of type boolean.");
|
||||
const operator = allowZero ? '>=' : '>';
|
||||
return `${name} should be ${operator} 0 and < 65536. Received ${determineSpecificType(port)}.`;
|
||||
}, RangeError);
|
||||
}, RangeError, HideStackFramesError);
|
||||
E('ERR_SOCKET_BAD_TYPE',
|
||||
'Bad socket type specified. Valid types are: udp4, udp6', TypeError);
|
||||
E('ERR_SOCKET_BUFFER_SIZE',
|
||||
|
@ -1700,7 +1723,7 @@ E('ERR_STREAM_UNSHIFT_AFTER_END_EVENT',
|
|||
E('ERR_STREAM_WRAP', 'Stream has StringDecoder set or is in objectMode', Error);
|
||||
E('ERR_STREAM_WRITE_AFTER_END', 'write after end', Error);
|
||||
E('ERR_SYNTHETIC', 'JavaScript Callstack', Error);
|
||||
E('ERR_SYSTEM_ERROR', 'A system error occurred', SystemError);
|
||||
E('ERR_SYSTEM_ERROR', 'A system error occurred', SystemError, HideStackFramesError);
|
||||
E('ERR_TAP_LEXER_ERROR', function(errorMsg) {
|
||||
hideInternalStackFrames(this);
|
||||
return errorMsg;
|
||||
|
@ -1794,7 +1817,7 @@ E('ERR_UNKNOWN_ENCODING', 'Unknown encoding: %s', TypeError);
|
|||
E('ERR_UNKNOWN_FILE_EXTENSION', 'Unknown file extension "%s" for %s', TypeError);
|
||||
E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s for URL %s',
|
||||
RangeError);
|
||||
E('ERR_UNKNOWN_SIGNAL', 'Unknown signal: %s', TypeError);
|
||||
E('ERR_UNKNOWN_SIGNAL', 'Unknown signal: %s', TypeError, HideStackFramesError);
|
||||
E('ERR_UNSUPPORTED_DIR_IMPORT', function(path, base, exactUrl) {
|
||||
lazyInternalUtil().setOwnProperty(this, 'url', exactUrl);
|
||||
return `Directory import '${path}' is not supported ` +
|
||||
|
|
|
@ -38,7 +38,7 @@ const {
|
|||
ERR_OUT_OF_RANGE,
|
||||
},
|
||||
hideStackFrames,
|
||||
uvException,
|
||||
UVException,
|
||||
} = require('internal/errors');
|
||||
const {
|
||||
isArrayBufferView,
|
||||
|
@ -348,7 +348,7 @@ function getOptions(options, defaultOptions = kEmptyObject) {
|
|||
*/
|
||||
function handleErrorFromBinding(ctx) {
|
||||
if (ctx.errno !== undefined) { // libuv error numbers
|
||||
const err = uvException(ctx);
|
||||
const err = new UVException(ctx);
|
||||
ErrorCaptureStackTrace(err, handleErrorFromBinding);
|
||||
throw err;
|
||||
}
|
||||
|
@ -361,30 +361,6 @@ function handleErrorFromBinding(ctx) {
|
|||
}
|
||||
}
|
||||
|
||||
// Check if the path contains null types if it is a string nor Uint8Array,
|
||||
// otherwise return silently.
|
||||
const nullCheck = hideStackFrames((path, propName, throwError = true) => {
|
||||
const pathIsString = typeof path === 'string';
|
||||
const pathIsUint8Array = isUint8Array(path);
|
||||
|
||||
// We can only perform meaningful checks on strings and Uint8Arrays.
|
||||
if ((!pathIsString && !pathIsUint8Array) ||
|
||||
(pathIsString && !StringPrototypeIncludes(path, '\u0000')) ||
|
||||
(pathIsUint8Array && !TypedArrayPrototypeIncludes(path, 0))) {
|
||||
return;
|
||||
}
|
||||
|
||||
const err = new ERR_INVALID_ARG_VALUE(
|
||||
propName,
|
||||
path,
|
||||
'must be a string, Uint8Array, or URL without null bytes',
|
||||
);
|
||||
if (throwError) {
|
||||
throw err;
|
||||
}
|
||||
return err;
|
||||
});
|
||||
|
||||
function preprocessSymlinkDestination(path, type, linkPath) {
|
||||
if (!isWindows) {
|
||||
// No preprocessing is needed on Unix.
|
||||
|
@ -664,14 +640,14 @@ function toUnixTimestamp(time, name = 'time') {
|
|||
const validateOffsetLengthRead = hideStackFrames(
|
||||
(offset, length, bufferLength) => {
|
||||
if (offset < 0) {
|
||||
throw new ERR_OUT_OF_RANGE('offset', '>= 0', offset);
|
||||
throw new ERR_OUT_OF_RANGE.HideStackFramesError('offset', '>= 0', offset);
|
||||
}
|
||||
if (length < 0) {
|
||||
throw new ERR_OUT_OF_RANGE('length', '>= 0', length);
|
||||
throw new ERR_OUT_OF_RANGE.HideStackFramesError('length', '>= 0', length);
|
||||
}
|
||||
if (offset + length > bufferLength) {
|
||||
throw new ERR_OUT_OF_RANGE('length',
|
||||
`<= ${bufferLength - offset}`, length);
|
||||
throw new ERR_OUT_OF_RANGE.HideStackFramesError('length',
|
||||
`<= ${bufferLength - offset}`, length);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
@ -679,31 +655,41 @@ const validateOffsetLengthRead = hideStackFrames(
|
|||
const validateOffsetLengthWrite = hideStackFrames(
|
||||
(offset, length, byteLength) => {
|
||||
if (offset > byteLength) {
|
||||
throw new ERR_OUT_OF_RANGE('offset', `<= ${byteLength}`, offset);
|
||||
throw new ERR_OUT_OF_RANGE.HideStackFramesError('offset', `<= ${byteLength}`, offset);
|
||||
}
|
||||
|
||||
if (length > byteLength - offset) {
|
||||
throw new ERR_OUT_OF_RANGE('length', `<= ${byteLength - offset}`, length);
|
||||
throw new ERR_OUT_OF_RANGE.HideStackFramesError('length', `<= ${byteLength - offset}`, length);
|
||||
}
|
||||
|
||||
if (length < 0) {
|
||||
throw new ERR_OUT_OF_RANGE('length', '>= 0', length);
|
||||
throw new ERR_OUT_OF_RANGE.HideStackFramesError('length', '>= 0', length);
|
||||
}
|
||||
|
||||
validateInt32(length, 'length', 0);
|
||||
validateInt32.withoutStackTrace(length, 'length', 0);
|
||||
},
|
||||
);
|
||||
|
||||
const validatePath = hideStackFrames((path, propName = 'path') => {
|
||||
if (typeof path !== 'string' && !isUint8Array(path)) {
|
||||
throw new ERR_INVALID_ARG_TYPE(propName, ['string', 'Buffer', 'URL'], path);
|
||||
throw new ERR_INVALID_ARG_TYPE.HideStackFramesError(propName, ['string', 'Buffer', 'URL'], path);
|
||||
}
|
||||
|
||||
const err = nullCheck(path, propName, false);
|
||||
const pathIsString = typeof path === 'string';
|
||||
const pathIsUint8Array = isUint8Array(path);
|
||||
|
||||
if (err !== undefined) {
|
||||
throw err;
|
||||
// We can only perform meaningful checks on strings and Uint8Arrays.
|
||||
if ((!pathIsString && !pathIsUint8Array) ||
|
||||
(pathIsString && !StringPrototypeIncludes(path, '\u0000')) ||
|
||||
(pathIsUint8Array && !TypedArrayPrototypeIncludes(path, 0))) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new ERR_INVALID_ARG_VALUE.HideStackFramesError(
|
||||
propName,
|
||||
path,
|
||||
'must be a string, Uint8Array, or URL without null bytes',
|
||||
);
|
||||
});
|
||||
|
||||
// TODO(rafaelgss): implement the path.resolve on C++ side
|
||||
|
@ -742,11 +728,11 @@ const getValidatedFd = hideStackFrames((fd, propName = 'fd') => {
|
|||
|
||||
const validateBufferArray = hideStackFrames((buffers, propName = 'buffers') => {
|
||||
if (!ArrayIsArray(buffers))
|
||||
throw new ERR_INVALID_ARG_TYPE(propName, 'ArrayBufferView[]', buffers);
|
||||
throw new ERR_INVALID_ARG_TYPE.HideStackFramesError(propName, 'ArrayBufferView[]', buffers);
|
||||
|
||||
for (let i = 0; i < buffers.length; i++) {
|
||||
if (!isArrayBufferView(buffers[i]))
|
||||
throw new ERR_INVALID_ARG_TYPE(propName, 'ArrayBufferView[]', buffers);
|
||||
throw new ERR_INVALID_ARG_TYPE.HideStackFramesError(propName, 'ArrayBufferView[]', buffers);
|
||||
}
|
||||
|
||||
return buffers;
|
||||
|
@ -802,7 +788,7 @@ const validateCpOptions = hideStackFrames((options) => {
|
|||
validateBoolean(options.verbatimSymlinks, 'options.verbatimSymlinks');
|
||||
options.mode = getValidMode(options.mode, 'copyFile');
|
||||
if (options.dereference === true && options.verbatimSymlinks === true) {
|
||||
throw new ERR_INCOMPATIBLE_OPTION_PAIR('dereference', 'verbatimSymlinks');
|
||||
throw new ERR_INCOMPATIBLE_OPTION_PAIR.HideStackFramesError('dereference', 'verbatimSymlinks');
|
||||
}
|
||||
if (options.filter !== undefined) {
|
||||
validateFunction(options.filter, 'options.filter');
|
||||
|
@ -827,21 +813,23 @@ const validateRmOptions = hideStackFrames((path, options, expectDir, cb) => {
|
|||
}
|
||||
|
||||
if (stats.isDirectory() && !options.recursive) {
|
||||
return cb(new ERR_FS_EISDIR({
|
||||
const err = new ERR_FS_EISDIR.HideStackFramesError({
|
||||
code: 'EISDIR',
|
||||
message: 'is a directory',
|
||||
path,
|
||||
syscall: 'rm',
|
||||
errno: EISDIR,
|
||||
}));
|
||||
});
|
||||
|
||||
return cb(err);
|
||||
}
|
||||
return cb(null, options);
|
||||
});
|
||||
});
|
||||
|
||||
const validateRmOptionsSync = hideStackFrames((path, options, expectDir) => {
|
||||
options = validateRmdirOptions(options, defaultRmOptions);
|
||||
validateBoolean(options.force, 'options.force');
|
||||
options = validateRmdirOptions.withoutStackTrace(options, defaultRmOptions);
|
||||
validateBoolean.withoutStackTrace(options.force, 'options.force');
|
||||
|
||||
if (!options.force || expectDir || !options.recursive) {
|
||||
const isDirectory = lazyLoadFs()
|
||||
|
@ -852,7 +840,7 @@ const validateRmOptionsSync = hideStackFrames((path, options, expectDir) => {
|
|||
}
|
||||
|
||||
if (isDirectory && !options.recursive) {
|
||||
throw new ERR_FS_EISDIR({
|
||||
throw new ERR_FS_EISDIR.HideStackFramesError({
|
||||
code: 'EISDIR',
|
||||
message: 'is a directory',
|
||||
path,
|
||||
|
@ -882,13 +870,13 @@ const validateRmdirOptions = hideStackFrames(
|
|||
(options, defaults = defaultRmdirOptions) => {
|
||||
if (options === undefined)
|
||||
return defaults;
|
||||
validateObject(options, 'options');
|
||||
validateObject.withoutStackTrace(options, 'options');
|
||||
|
||||
options = { ...defaults, ...options };
|
||||
|
||||
validateBoolean(options.recursive, 'options.recursive');
|
||||
validateInt32(options.retryDelay, 'options.retryDelay', 0);
|
||||
validateUint32(options.maxRetries, 'options.maxRetries');
|
||||
validateBoolean.withoutStackTrace(options.recursive, 'options.recursive');
|
||||
validateInt32.withoutStackTrace(options.retryDelay, 'options.retryDelay', 0);
|
||||
validateUint32.withoutStackTrace(options.maxRetries, 'options.maxRetries');
|
||||
|
||||
return options;
|
||||
});
|
||||
|
@ -907,13 +895,13 @@ const getValidMode = hideStackFrames((mode, type) => {
|
|||
if (mode == null) {
|
||||
return def;
|
||||
}
|
||||
validateInteger(mode, 'mode', min, max);
|
||||
validateInteger.withoutStackTrace(mode, 'mode', min, max);
|
||||
return mode;
|
||||
});
|
||||
|
||||
const validateStringAfterArrayBufferView = hideStackFrames((buffer, name) => {
|
||||
if (typeof buffer !== 'string') {
|
||||
throw new ERR_INVALID_ARG_TYPE(
|
||||
throw new ERR_INVALID_ARG_TYPE.HideStackFramesError(
|
||||
name,
|
||||
['string', 'Buffer', 'TypedArray', 'DataView'],
|
||||
buffer,
|
||||
|
@ -923,16 +911,16 @@ const validateStringAfterArrayBufferView = hideStackFrames((buffer, name) => {
|
|||
|
||||
const validatePosition = hideStackFrames((position, name, length) => {
|
||||
if (typeof position === 'number') {
|
||||
validateInteger(position, name, -1);
|
||||
validateInteger.withoutStackTrace(position, name, -1);
|
||||
} else if (typeof position === 'bigint') {
|
||||
const maxPosition = 2n ** 63n - 1n - BigInt(length);
|
||||
if (!(position >= -1n && position <= maxPosition)) {
|
||||
throw new ERR_OUT_OF_RANGE(name,
|
||||
`>= -1 && <= ${maxPosition}`,
|
||||
position);
|
||||
throw new ERR_OUT_OF_RANGE.HideStackFramesError(name,
|
||||
`>= -1 && <= ${maxPosition}`,
|
||||
position);
|
||||
}
|
||||
} else {
|
||||
throw new ERR_INVALID_ARG_TYPE(name, ['integer', 'bigint'], position);
|
||||
throw new ERR_INVALID_ARG_TYPE.HideStackFramesError(name, ['integer', 'bigint'], position);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -956,7 +944,6 @@ module.exports = {
|
|||
getValidatedPath,
|
||||
getValidMode,
|
||||
handleErrorFromBinding,
|
||||
nullCheck,
|
||||
possiblyTransformPath,
|
||||
preprocessSymlinkDestination,
|
||||
realpathCacheKey: Symbol('realpathCacheKey'),
|
||||
|
|
|
@ -9,7 +9,7 @@ const {
|
|||
|
||||
const {
|
||||
AbortError,
|
||||
uvException,
|
||||
UVException,
|
||||
codes: {
|
||||
ERR_INVALID_ARG_VALUE,
|
||||
},
|
||||
|
@ -119,7 +119,7 @@ StatWatcher.prototype[kFSStatWatcherStart] = function(filename,
|
|||
validateUint32(interval, 'interval');
|
||||
const err = this._handle.start(toNamespacedPath(filename), interval);
|
||||
if (err) {
|
||||
const error = uvException({
|
||||
const error = new UVException({
|
||||
errno: err,
|
||||
syscall: 'watch',
|
||||
path: filename,
|
||||
|
@ -204,7 +204,7 @@ function FSWatcher() {
|
|||
this._handle.close();
|
||||
this._handle = null; // Make the handle garbage collectable.
|
||||
}
|
||||
const error = uvException({
|
||||
const error = new UVException({
|
||||
errno: status,
|
||||
syscall: 'watch',
|
||||
path: filename,
|
||||
|
@ -244,7 +244,7 @@ FSWatcher.prototype[kFSWatchStart] = function(filename,
|
|||
recursive,
|
||||
encoding);
|
||||
if (err) {
|
||||
const error = uvException({
|
||||
const error = new UVException({
|
||||
errno: err,
|
||||
syscall: 'watch',
|
||||
path: filename,
|
||||
|
@ -338,7 +338,7 @@ async function* watch(filename, options = kEmptyObject) {
|
|||
}
|
||||
handle.onchange = (status, eventType, filename) => {
|
||||
if (status < 0) {
|
||||
const error = uvException({
|
||||
const error = new UVException({
|
||||
errno: status,
|
||||
syscall: 'watch',
|
||||
path: filename,
|
||||
|
@ -354,7 +354,7 @@ async function* watch(filename, options = kEmptyObject) {
|
|||
|
||||
const err = handle.start(path, persistent, recursive, encoding);
|
||||
if (err) {
|
||||
const error = uvException({
|
||||
const error = new UVException({
|
||||
errno: err,
|
||||
syscall: 'watch',
|
||||
path: filename,
|
||||
|
|
|
@ -89,13 +89,13 @@ const assertValidHeader = hideStackFrames((name, value) => {
|
|||
if (name === '' ||
|
||||
typeof name !== 'string' ||
|
||||
StringPrototypeIncludes(name, ' ')) {
|
||||
throw new ERR_INVALID_HTTP_TOKEN('Header name', name);
|
||||
throw new ERR_INVALID_HTTP_TOKEN.HideStackFramesError('Header name', name);
|
||||
}
|
||||
if (isPseudoHeader(name)) {
|
||||
throw new ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED();
|
||||
throw new ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED.HideStackFramesError();
|
||||
}
|
||||
if (value === undefined || value === null) {
|
||||
throw new ERR_HTTP2_INVALID_HEADER_VALUE(value, name);
|
||||
throw new ERR_HTTP2_INVALID_HEADER_VALUE.HideStackFramesError(value, name);
|
||||
}
|
||||
if (!isConnectionHeaderAllowed(name, value)) {
|
||||
connectionHeaderMessageWarn();
|
||||
|
|
|
@ -766,25 +766,25 @@ const setAndValidatePriorityOptions = hideStackFrames((options) => {
|
|||
if (options.weight === undefined) {
|
||||
options.weight = NGHTTP2_DEFAULT_WEIGHT;
|
||||
} else {
|
||||
validateNumber(options.weight, 'options.weight');
|
||||
validateNumber.withoutStackTrace(options.weight, 'options.weight');
|
||||
}
|
||||
|
||||
if (options.parent === undefined) {
|
||||
options.parent = 0;
|
||||
} else {
|
||||
validateNumber(options.parent, 'options.parent', 0);
|
||||
validateNumber.withoutStackTrace(options.parent, 'options.parent', 0);
|
||||
}
|
||||
|
||||
if (options.exclusive === undefined) {
|
||||
options.exclusive = false;
|
||||
} else {
|
||||
validateBoolean(options.exclusive, 'options.exclusive');
|
||||
validateBoolean.withoutStackTrace(options.exclusive, 'options.exclusive');
|
||||
}
|
||||
|
||||
if (options.silent === undefined) {
|
||||
options.silent = false;
|
||||
} else {
|
||||
validateBoolean(options.silent, 'options.silent');
|
||||
validateBoolean.withoutStackTrace(options.silent, 'options.silent');
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -946,33 +946,33 @@ function pingCallback(cb) {
|
|||
// All settings are optional and may be left undefined
|
||||
const validateSettings = hideStackFrames((settings) => {
|
||||
if (settings === undefined) return;
|
||||
assertWithinRange('headerTableSize',
|
||||
settings.headerTableSize,
|
||||
0, kMaxInt);
|
||||
assertWithinRange('initialWindowSize',
|
||||
settings.initialWindowSize,
|
||||
0, kMaxInt);
|
||||
assertWithinRange('maxFrameSize',
|
||||
settings.maxFrameSize,
|
||||
16384, kMaxFrameSize);
|
||||
assertWithinRange('maxConcurrentStreams',
|
||||
settings.maxConcurrentStreams,
|
||||
0, kMaxStreams);
|
||||
assertWithinRange('maxHeaderListSize',
|
||||
settings.maxHeaderListSize,
|
||||
0, kMaxInt);
|
||||
assertWithinRange('maxHeaderSize',
|
||||
settings.maxHeaderSize,
|
||||
0, kMaxInt);
|
||||
assertWithinRange.withoutStackTrace('headerTableSize',
|
||||
settings.headerTableSize,
|
||||
0, kMaxInt);
|
||||
assertWithinRange.withoutStackTrace('initialWindowSize',
|
||||
settings.initialWindowSize,
|
||||
0, kMaxInt);
|
||||
assertWithinRange.withoutStackTrace('maxFrameSize',
|
||||
settings.maxFrameSize,
|
||||
16384, kMaxFrameSize);
|
||||
assertWithinRange.withoutStackTrace('maxConcurrentStreams',
|
||||
settings.maxConcurrentStreams,
|
||||
0, kMaxStreams);
|
||||
assertWithinRange.withoutStackTrace('maxHeaderListSize',
|
||||
settings.maxHeaderListSize,
|
||||
0, kMaxInt);
|
||||
assertWithinRange.withoutStackTrace('maxHeaderSize',
|
||||
settings.maxHeaderSize,
|
||||
0, kMaxInt);
|
||||
if (settings.enablePush !== undefined &&
|
||||
typeof settings.enablePush !== 'boolean') {
|
||||
throw new ERR_HTTP2_INVALID_SETTING_VALUE('enablePush',
|
||||
settings.enablePush);
|
||||
throw new ERR_HTTP2_INVALID_SETTING_VALUE.HideStackFramesError('enablePush',
|
||||
settings.enablePush);
|
||||
}
|
||||
if (settings.enableConnectProtocol !== undefined &&
|
||||
typeof settings.enableConnectProtocol !== 'boolean') {
|
||||
throw new ERR_HTTP2_INVALID_SETTING_VALUE('enableConnectProtocol',
|
||||
settings.enableConnectProtocol);
|
||||
throw new ERR_HTTP2_INVALID_SETTING_VALUE.HideStackFramesError('enableConnectProtocol',
|
||||
settings.enableConnectProtocol);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ const {
|
|||
Error,
|
||||
MathMax,
|
||||
Number,
|
||||
ObjectDefineProperty,
|
||||
ObjectKeys,
|
||||
SafeSet,
|
||||
String,
|
||||
|
@ -23,12 +22,11 @@ const {
|
|||
codes: {
|
||||
ERR_HTTP2_HEADER_SINGLE_VALUE,
|
||||
ERR_HTTP2_INVALID_CONNECTION_HEADERS,
|
||||
ERR_HTTP2_INVALID_PSEUDOHEADER,
|
||||
ERR_HTTP2_INVALID_PSEUDOHEADER: { HideStackFramesError: ERR_HTTP2_INVALID_PSEUDOHEADER },
|
||||
ERR_HTTP2_INVALID_SETTING_VALUE,
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
ERR_INVALID_HTTP_TOKEN,
|
||||
},
|
||||
captureLargerStackTrace,
|
||||
getMessage,
|
||||
hideStackFrames,
|
||||
kIsNodeError,
|
||||
|
@ -552,14 +550,10 @@ class NghttpError extends Error {
|
|||
binding.nghttp2ErrorString(integerCode));
|
||||
this.code = customErrorCode || 'ERR_HTTP2_ERROR';
|
||||
this.errno = integerCode;
|
||||
captureLargerStackTrace(this);
|
||||
ObjectDefineProperty(this, kIsNodeError, {
|
||||
__proto__: null,
|
||||
value: true,
|
||||
enumerable: false,
|
||||
writable: false,
|
||||
configurable: true,
|
||||
});
|
||||
}
|
||||
|
||||
get [kIsNodeError]() {
|
||||
return true;
|
||||
}
|
||||
|
||||
toString() {
|
||||
|
@ -572,7 +566,7 @@ const assertIsObject = hideStackFrames((value, name, types) => {
|
|||
(value === null ||
|
||||
typeof value !== 'object' ||
|
||||
ArrayIsArray(value))) {
|
||||
throw new ERR_INVALID_ARG_TYPE(name, types || 'Object', value);
|
||||
throw new ERR_INVALID_ARG_TYPE.HideStackFramesError(name, types || 'Object', value);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -580,7 +574,7 @@ const assertWithinRange = hideStackFrames(
|
|||
(name, value, min = 0, max = Infinity) => {
|
||||
if (value !== undefined &&
|
||||
(typeof value !== 'number' || value < min || value > max)) {
|
||||
throw new ERR_HTTP2_INVALID_SETTING_VALUE.RangeError(
|
||||
throw new ERR_HTTP2_INVALID_SETTING_VALUE.RangeError.HideStackFramesError(
|
||||
name, value, min, max);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -58,7 +58,7 @@ function makeSyncWrite(fd) {
|
|||
const ctx = {};
|
||||
writeBuffer(fd, chunk, 0, chunk.length, null, undefined, ctx);
|
||||
if (ctx.errno !== undefined) {
|
||||
const ex = errors.uvException(ctx);
|
||||
const ex = new errors.UVException(ctx);
|
||||
ex.errno = ctx.errno;
|
||||
return cb(ex);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ const {
|
|||
} = primordials;
|
||||
|
||||
const {
|
||||
errnoException,
|
||||
ErrnoException,
|
||||
codes: {
|
||||
ERR_ASSERTION,
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
|
@ -231,7 +231,7 @@ function wrapProcessMethods(binding) {
|
|||
}
|
||||
|
||||
if (err)
|
||||
throw errnoException(err, 'kill');
|
||||
throw new ErrnoException(err, 'kill');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ const {
|
|||
} = primordials;
|
||||
|
||||
const {
|
||||
errnoException,
|
||||
ErrnoException,
|
||||
} = require('internal/errors');
|
||||
|
||||
const { signals } = internalBinding('constants').os;
|
||||
|
@ -33,7 +33,7 @@ function startListeningIfSignal(type) {
|
|||
const err = wrap.start(signum);
|
||||
if (err) {
|
||||
wrap.close();
|
||||
throw errnoException(err, 'uv_signal_start');
|
||||
throw new ErrnoException(err, 'uv_signal_start');
|
||||
}
|
||||
|
||||
signalWraps.set(type, wrap);
|
||||
|
|
|
@ -17,7 +17,7 @@ const {
|
|||
} = internalBinding('stream_wrap');
|
||||
const { UV_EOF } = internalBinding('uv');
|
||||
const {
|
||||
errnoException,
|
||||
ErrnoException,
|
||||
} = require('internal/errors');
|
||||
const { owner_symbol } = require('internal/async_hooks').symbols;
|
||||
const {
|
||||
|
@ -91,7 +91,7 @@ function onWriteComplete(status) {
|
|||
// TODO (ronag): This should be moved before if(stream.destroyed)
|
||||
// in order to avoid swallowing error.
|
||||
if (status < 0) {
|
||||
const ex = errnoException(status, 'write', this.error);
|
||||
const ex = new ErrnoException(status, 'write', this.error);
|
||||
if (typeof this.callback === 'function')
|
||||
this.callback(ex);
|
||||
else
|
||||
|
@ -157,7 +157,7 @@ function afterWriteDispatched(req, err, cb) {
|
|||
req.async = !!streamBaseState[kLastWriteWasAsync];
|
||||
|
||||
if (err !== 0)
|
||||
return cb(errnoException(err, 'write', req.error));
|
||||
return cb(new ErrnoException(err, 'write', req.error));
|
||||
|
||||
if (!req.async && typeof req.callback === 'function') {
|
||||
req.callback();
|
||||
|
@ -194,7 +194,7 @@ function onStreamRead(arrayBuffer) {
|
|||
if (!stream.destroyed) {
|
||||
const err = handle.readStop();
|
||||
if (err)
|
||||
stream.destroy(errnoException(err, 'read'));
|
||||
stream.destroy(new ErrnoException(err, 'read'));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,7 +214,7 @@ function onStreamRead(arrayBuffer) {
|
|||
if (nread !== UV_EOF) {
|
||||
// CallJSOnreadMethod expects the return value to be a buffer.
|
||||
// Ref: https://github.com/nodejs/node/pull/34375
|
||||
stream.destroy(errnoException(nread, 'read'));
|
||||
stream.destroy(new ErrnoException(nread, 'read'));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ const {
|
|||
ArrayPrototypeSlice,
|
||||
ArrayPrototypeSort,
|
||||
Error,
|
||||
ErrorCaptureStackTrace,
|
||||
FunctionPrototypeCall,
|
||||
ObjectDefineProperties,
|
||||
ObjectDefineProperty,
|
||||
|
@ -44,11 +45,11 @@ const {
|
|||
} = primordials;
|
||||
|
||||
const {
|
||||
hideStackFrames,
|
||||
codes: {
|
||||
ERR_NO_CRYPTO,
|
||||
ERR_UNKNOWN_SIGNAL,
|
||||
},
|
||||
isErrorStackTraceLimitWritable,
|
||||
uvErrmapGet,
|
||||
overrideStackTrace,
|
||||
} = require('internal/errors');
|
||||
|
@ -693,10 +694,19 @@ const lazyDOMExceptionClass = () => {
|
|||
return _DOMException;
|
||||
};
|
||||
|
||||
const lazyDOMException = hideStackFrames((message, name) => {
|
||||
const lazyDOMException = (message, name) => {
|
||||
_DOMException ??= internalBinding('messaging').DOMException;
|
||||
if (isErrorStackTraceLimitWritable()) {
|
||||
const limit = Error.stackTraceLimit;
|
||||
Error.stackTraceLimit = 0;
|
||||
const ex = new _DOMException(message, name);
|
||||
Error.stackTraceLimit = limit;
|
||||
ErrorCaptureStackTrace(ex, lazyDOMException);
|
||||
return ex;
|
||||
}
|
||||
return new _DOMException(message, name);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
const kEnumerableProperty = { __proto__: null };
|
||||
kEnumerableProperty.enumerable = true;
|
||||
|
|
|
@ -22,11 +22,11 @@ const {
|
|||
const {
|
||||
hideStackFrames,
|
||||
codes: {
|
||||
ERR_SOCKET_BAD_PORT,
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
ERR_INVALID_ARG_VALUE,
|
||||
ERR_OUT_OF_RANGE,
|
||||
ERR_UNKNOWN_SIGNAL,
|
||||
ERR_SOCKET_BAD_PORT: { HideStackFramesError: ERR_SOCKET_BAD_PORT },
|
||||
ERR_INVALID_ARG_TYPE: { HideStackFramesError: ERR_INVALID_ARG_TYPE },
|
||||
ERR_INVALID_ARG_VALUE: { HideStackFramesError: ERR_INVALID_ARG_VALUE },
|
||||
ERR_OUT_OF_RANGE: { HideStackFramesError: ERR_OUT_OF_RANGE },
|
||||
ERR_UNKNOWN_SIGNAL: { HideStackFramesError: ERR_UNKNOWN_SIGNAL },
|
||||
},
|
||||
} = require('internal/errors');
|
||||
const { normalizeEncoding } = require('internal/util');
|
||||
|
@ -157,10 +157,10 @@ const validateUint32 = hideStackFrames((value, name, positive = false) => {
|
|||
*/
|
||||
|
||||
/** @type {validateString} */
|
||||
function validateString(value, name) {
|
||||
const validateString = hideStackFrames((value, name) => {
|
||||
if (typeof value !== 'string')
|
||||
throw new ERR_INVALID_ARG_TYPE(name, 'string', value);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @callback validateNumber
|
||||
|
@ -172,7 +172,7 @@ function validateString(value, name) {
|
|||
*/
|
||||
|
||||
/** @type {validateNumber} */
|
||||
function validateNumber(value, name, min = undefined, max) {
|
||||
const validateNumber = hideStackFrames((value, name, min = undefined, max) => {
|
||||
if (typeof value !== 'number')
|
||||
throw new ERR_INVALID_ARG_TYPE(name, 'number', value);
|
||||
|
||||
|
@ -183,7 +183,7 @@ function validateNumber(value, name, min = undefined, max) {
|
|||
`${min != null ? `>= ${min}` : ''}${min != null && max != null ? ' && ' : ''}${max != null ? `<= ${max}` : ''}`,
|
||||
value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @callback validateOneOf
|
||||
|
@ -213,10 +213,10 @@ const validateOneOf = hideStackFrames((value, name, oneOf) => {
|
|||
*/
|
||||
|
||||
/** @type {validateBoolean} */
|
||||
function validateBoolean(value, name) {
|
||||
const validateBoolean = hideStackFrames((value, name) => {
|
||||
if (typeof value !== 'boolean')
|
||||
throw new ERR_INVALID_ARG_TYPE(name, 'boolean', value);
|
||||
}
|
||||
});
|
||||
|
||||
const kValidateObjectNone = 0;
|
||||
const kValidateObjectAllowNullable = 1 << 0;
|
||||
|
@ -309,7 +309,7 @@ const validateArray = hideStackFrames((value, name, minLength = 0) => {
|
|||
*/
|
||||
|
||||
/** @type {validateStringArray} */
|
||||
function validateStringArray(value, name) {
|
||||
const validateStringArray = hideStackFrames((value, name) => {
|
||||
validateArray(value, name);
|
||||
for (let i = 0; i < value.length; ++i) {
|
||||
// Don't use validateString here for performance reasons, as
|
||||
|
@ -318,7 +318,7 @@ function validateStringArray(value, name) {
|
|||
throw new ERR_INVALID_ARG_TYPE(`${name}[${i}]`, 'string', value[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @callback validateBooleanArray
|
||||
|
@ -328,7 +328,7 @@ function validateStringArray(value, name) {
|
|||
*/
|
||||
|
||||
/** @type {validateBooleanArray} */
|
||||
function validateBooleanArray(value, name) {
|
||||
const validateBooleanArray = hideStackFrames((value, name) => {
|
||||
validateArray(value, name);
|
||||
for (let i = 0; i < value.length; ++i) {
|
||||
// Don't use validateBoolean here for performance reasons, as
|
||||
|
@ -337,7 +337,7 @@ function validateBooleanArray(value, name) {
|
|||
throw new ERR_INVALID_ARG_TYPE(`${name}[${i}]`, 'boolean', value[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @callback validateAbortSignalArray
|
||||
|
@ -364,7 +364,7 @@ function validateAbortSignalArray(value, name) {
|
|||
* @param {string} [name='signal']
|
||||
* @returns {asserts signal is keyof signals}
|
||||
*/
|
||||
function validateSignalName(signal, name = 'signal') {
|
||||
const validateSignalName = hideStackFrames((signal, name = 'signal') => {
|
||||
validateString(signal, name);
|
||||
|
||||
if (signals[signal] === undefined) {
|
||||
|
@ -375,7 +375,7 @@ function validateSignalName(signal, name = 'signal') {
|
|||
|
||||
throw new ERR_UNKNOWN_SIGNAL(signal);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @callback validateBuffer
|
||||
|
@ -397,7 +397,7 @@ const validateBuffer = hideStackFrames((buffer, name = 'buffer') => {
|
|||
* @param {string} data
|
||||
* @param {string} encoding
|
||||
*/
|
||||
function validateEncoding(data, encoding) {
|
||||
const validateEncoding = hideStackFrames((data, encoding) => {
|
||||
const normalizedEncoding = normalizeEncoding(encoding);
|
||||
const length = data.length;
|
||||
|
||||
|
@ -405,7 +405,7 @@ function validateEncoding(data, encoding) {
|
|||
throw new ERR_INVALID_ARG_VALUE('encoding', encoding,
|
||||
`is invalid for data of length ${length}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Check that the port number is not NaN when coerced to a number,
|
||||
|
@ -415,7 +415,7 @@ function validateEncoding(data, encoding) {
|
|||
* @param {boolean} [allowZero=true]
|
||||
* @returns {number}
|
||||
*/
|
||||
function validatePort(port, name = 'Port', allowZero = true) {
|
||||
const validatePort = hideStackFrames((port, name = 'Port', allowZero = true) => {
|
||||
if ((typeof port !== 'number' && typeof port !== 'string') ||
|
||||
(typeof port === 'string' && StringPrototypeTrim(port).length === 0) ||
|
||||
+port !== (+port >>> 0) ||
|
||||
|
@ -424,7 +424,7 @@ function validatePort(port, name = 'Port', allowZero = true) {
|
|||
throw new ERR_SOCKET_BAD_PORT(name, port, allowZero);
|
||||
}
|
||||
return port | 0;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @callback validateAbortSignal
|
||||
|
@ -507,7 +507,7 @@ const linkValueRegExp = /^(?:<[^>]*>)(?:\s*;\s*[^;"\s]+(?:=(")?[^;"\s]*\1)?)*$/;
|
|||
* @param {any} value
|
||||
* @param {string} name
|
||||
*/
|
||||
function validateLinkHeaderFormat(value, name) {
|
||||
const validateLinkHeaderFormat = hideStackFrames((value, name) => {
|
||||
if (
|
||||
typeof value === 'undefined' ||
|
||||
!RegExpPrototypeExec(linkValueRegExp, value)
|
||||
|
@ -518,7 +518,7 @@ function validateLinkHeaderFormat(value, name) {
|
|||
'must be an array or string of format "</styles.css>; rel=preload; as=style"',
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const validateInternalField = hideStackFrames((object, fieldKey, className) => {
|
||||
if (typeof object !== 'object' || object === null || !ObjectPrototypeHasOwnProperty(object, fieldKey)) {
|
||||
|
@ -530,9 +530,9 @@ const validateInternalField = hideStackFrames((object, fieldKey, className) => {
|
|||
* @param {any} hints
|
||||
* @return {string}
|
||||
*/
|
||||
function validateLinkHeaderValue(hints) {
|
||||
const validateLinkHeaderValue = hideStackFrames((hints) => {
|
||||
if (typeof hints === 'string') {
|
||||
validateLinkHeaderFormat(hints, 'hints');
|
||||
validateLinkHeaderFormat.withoutStackTrace(hints, 'hints');
|
||||
return hints;
|
||||
} else if (ArrayIsArray(hints)) {
|
||||
const hintsLength = hints.length;
|
||||
|
@ -544,7 +544,7 @@ function validateLinkHeaderValue(hints) {
|
|||
|
||||
for (let i = 0; i < hintsLength; i++) {
|
||||
const link = hints[i];
|
||||
validateLinkHeaderFormat(link, 'hints');
|
||||
validateLinkHeaderFormat.withoutStackTrace(link, 'hints');
|
||||
result += link;
|
||||
|
||||
if (i !== hintsLength - 1) {
|
||||
|
@ -560,7 +560,7 @@ function validateLinkHeaderValue(hints) {
|
|||
hints,
|
||||
'must be an array or string of format "</styles.css>; rel=preload; as=style"',
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
isInt32,
|
||||
|
|
|
@ -46,7 +46,7 @@ const {
|
|||
} = require('buffer');
|
||||
|
||||
const {
|
||||
errnoException,
|
||||
ErrnoException,
|
||||
codes: {
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
ERR_INVALID_ARG_VALUE,
|
||||
|
@ -856,7 +856,7 @@ function newWritableStreamFromStreamBase(streamBase, strategy) {
|
|||
|
||||
function onWriteComplete(status) {
|
||||
if (status < 0) {
|
||||
const error = errnoException(status, 'write', this.error);
|
||||
const error = new ErrnoException(status, 'write', this.error);
|
||||
this.promise.reject(error);
|
||||
this.controller.error(error);
|
||||
return;
|
||||
|
@ -879,7 +879,7 @@ function newWritableStreamFromStreamBase(streamBase, strategy) {
|
|||
}
|
||||
|
||||
if (ret !== 0)
|
||||
promise.reject(errnoException(ret, 'write', req));
|
||||
promise.reject(new ErrnoException(ret, 'write', req));
|
||||
else if (!req.async)
|
||||
promise.resolve();
|
||||
|
||||
|
|
62
lib/net.js
62
lib/net.js
|
@ -106,11 +106,11 @@ const {
|
|||
ERR_SOCKET_CLOSED_BEFORE_CONNECTION,
|
||||
ERR_MISSING_ARGS,
|
||||
},
|
||||
aggregateErrors,
|
||||
errnoException,
|
||||
exceptionWithHostPort,
|
||||
ErrnoException,
|
||||
ExceptionWithHostPort,
|
||||
genericNodeError,
|
||||
uvExceptionWithHostPort,
|
||||
NodeAggregateError,
|
||||
UVExceptionWithHostPort,
|
||||
} = require('internal/errors');
|
||||
const { isUint8Array } = require('internal/util/types');
|
||||
const { queueMicrotask } = require('internal/process/task_queues');
|
||||
|
@ -425,7 +425,7 @@ function Socket(options) {
|
|||
// which cannot be opened. This is difficult to test as most
|
||||
// un-openable fds will throw on `createHandle`
|
||||
if (err)
|
||||
throw errnoException(err, 'open');
|
||||
throw new ErrnoException(err, 'open');
|
||||
|
||||
this[async_id_symbol] = this._handle.getAsyncId();
|
||||
|
||||
|
@ -434,7 +434,7 @@ function Socket(options) {
|
|||
// Make stdout and stderr blocking on Windows
|
||||
err = this._handle.setBlocking(true);
|
||||
if (err)
|
||||
throw errnoException(err, 'setBlocking');
|
||||
throw new ErrnoException(err, 'setBlocking');
|
||||
|
||||
this._writev = null;
|
||||
this._write = makeSyncWrite(fd);
|
||||
|
@ -533,7 +533,7 @@ Socket.prototype._final = function(cb) {
|
|||
if (err === 1 || err === UV_ENOTCONN) // synchronous finish
|
||||
return cb();
|
||||
else if (err !== 0)
|
||||
return cb(errnoException(err, 'shutdown'));
|
||||
return cb(new ErrnoException(err, 'shutdown'));
|
||||
};
|
||||
|
||||
function afterShutdown() {
|
||||
|
@ -698,7 +698,7 @@ function tryReadStart(socket) {
|
|||
socket._handle.reading = true;
|
||||
const err = socket._handle.readStart();
|
||||
if (err)
|
||||
socket.destroy(errnoException(err, 'read'));
|
||||
socket.destroy(new ErrnoException(err, 'read'));
|
||||
}
|
||||
|
||||
// Just call handle.readStart until we have enough in the buffer
|
||||
|
@ -747,7 +747,7 @@ Socket.prototype.pause = function() {
|
|||
if (!this.destroyed) {
|
||||
const err = this._handle.readStop();
|
||||
if (err)
|
||||
this.destroy(errnoException(err, 'read'));
|
||||
this.destroy(new ErrnoException(err, 'read'));
|
||||
}
|
||||
}
|
||||
return stream.Duplex.prototype.pause.call(this);
|
||||
|
@ -816,7 +816,7 @@ Socket.prototype._destroy = function(exception, cb) {
|
|||
this.emit('close', isException);
|
||||
});
|
||||
if (err)
|
||||
this.emit('error', errnoException(err, 'reset'));
|
||||
this.emit('error', new ErrnoException(err, 'reset'));
|
||||
} else if (this._closeAfterHandlingError) {
|
||||
// Enqueue closing the socket as a microtask, so that the socket can be
|
||||
// accessible when an `error` event is handled in the `next tick queue`.
|
||||
|
@ -1051,7 +1051,7 @@ function internalConnect(
|
|||
|
||||
err = checkBindError(err, localPort, self._handle);
|
||||
if (err) {
|
||||
const ex = exceptionWithHostPort(err, 'bind', localAddress, localPort);
|
||||
const ex = new ExceptionWithHostPort(err, 'bind', localAddress, localPort);
|
||||
self.destroy(ex);
|
||||
return;
|
||||
}
|
||||
|
@ -1087,7 +1087,7 @@ function internalConnect(
|
|||
details = sockname.address + ':' + sockname.port;
|
||||
}
|
||||
|
||||
const ex = exceptionWithHostPort(err, 'connect', address, port, details);
|
||||
const ex = new ExceptionWithHostPort(err, 'connect', address, port, details);
|
||||
self.destroy(ex);
|
||||
} else if ((addressType === 6 || addressType === 4) && hasObserver('net')) {
|
||||
startPerf(self, kPerfHooksNetConnectContext, { type: 'net', name: 'connect', detail: { host: address, port } });
|
||||
|
@ -1111,7 +1111,7 @@ function internalConnectMultiple(context, canceled) {
|
|||
return;
|
||||
}
|
||||
|
||||
self.destroy(aggregateErrors(context.errors));
|
||||
self.destroy(new NodeAggregateError(context.errors));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1142,7 +1142,7 @@ function internalConnectMultiple(context, canceled) {
|
|||
|
||||
err = checkBindError(err, localPort, self._handle);
|
||||
if (err) {
|
||||
ArrayPrototypePush(context.errors, exceptionWithHostPort(err, 'bind', localAddress, localPort));
|
||||
ArrayPrototypePush(context.errors, new ExceptionWithHostPort(err, 'bind', localAddress, localPort));
|
||||
internalConnectMultiple(context);
|
||||
return;
|
||||
}
|
||||
|
@ -1173,7 +1173,7 @@ function internalConnectMultiple(context, canceled) {
|
|||
details = sockname.address + ':' + sockname.port;
|
||||
}
|
||||
|
||||
ArrayPrototypePush(context.errors, exceptionWithHostPort(err, 'connect', address, port, details));
|
||||
ArrayPrototypePush(context.errors, new ExceptionWithHostPort(err, 'connect', address, port, details));
|
||||
internalConnectMultiple(context);
|
||||
return;
|
||||
}
|
||||
|
@ -1592,11 +1592,11 @@ function afterConnect(status, handle, req, readable, writable) {
|
|||
if (req.localAddress && req.localPort) {
|
||||
details = req.localAddress + ':' + req.localPort;
|
||||
}
|
||||
const ex = exceptionWithHostPort(status,
|
||||
'connect',
|
||||
req.address,
|
||||
req.port,
|
||||
details);
|
||||
const ex = new ExceptionWithHostPort(status,
|
||||
'connect',
|
||||
req.address,
|
||||
req.port,
|
||||
details);
|
||||
if (details) {
|
||||
ex.localAddress = req.localAddress;
|
||||
ex.localPort = req.localPort;
|
||||
|
@ -1631,11 +1631,11 @@ function createConnectionError(req, status) {
|
|||
details = req.localAddress + ':' + req.localPort;
|
||||
}
|
||||
|
||||
const ex = exceptionWithHostPort(status,
|
||||
'connect',
|
||||
req.address,
|
||||
req.port,
|
||||
details);
|
||||
const ex = new ExceptionWithHostPort(status,
|
||||
'connect',
|
||||
req.address,
|
||||
req.port,
|
||||
details);
|
||||
if (details) {
|
||||
ex.localAddress = req.localAddress;
|
||||
ex.localPort = req.localPort;
|
||||
|
@ -1852,7 +1852,7 @@ function setupListenHandle(address, port, addressType, backlog, fd, flags) {
|
|||
rval = createServerHandle(address, port, addressType, fd, flags);
|
||||
|
||||
if (typeof rval === 'number') {
|
||||
const error = uvExceptionWithHostPort(rval, 'listen', address, port);
|
||||
const error = new UVExceptionWithHostPort(rval, 'listen', address, port);
|
||||
process.nextTick(emitErrorNT, this, error);
|
||||
return;
|
||||
}
|
||||
|
@ -1869,7 +1869,7 @@ function setupListenHandle(address, port, addressType, backlog, fd, flags) {
|
|||
const err = this._handle.listen(backlog || 511);
|
||||
|
||||
if (err) {
|
||||
const ex = uvExceptionWithHostPort(err, 'listen', address, port);
|
||||
const ex = new UVExceptionWithHostPort(err, 'listen', address, port);
|
||||
this._handle.close();
|
||||
this._handle = null;
|
||||
defaultTriggerAsyncIdScope(this[async_id_symbol],
|
||||
|
@ -1937,7 +1937,7 @@ function listenInCluster(server, address, port, addressType,
|
|||
err = checkBindError(err, port, handle);
|
||||
|
||||
if (err) {
|
||||
const ex = exceptionWithHostPort(err, 'bind', address, port);
|
||||
const ex = new ExceptionWithHostPort(err, 'bind', address, port);
|
||||
return server.emit('error', ex);
|
||||
}
|
||||
|
||||
|
@ -2045,7 +2045,7 @@ Server.prototype.listen = function(...args) {
|
|||
if (err) {
|
||||
this._handle.close();
|
||||
this._handle = null;
|
||||
throw errnoException(err, 'uv_pipe_chmod');
|
||||
throw new ErrnoException(err, 'uv_pipe_chmod');
|
||||
}
|
||||
}
|
||||
return this;
|
||||
|
@ -2086,7 +2086,7 @@ Server.prototype.address = function() {
|
|||
const out = {};
|
||||
const err = this._handle.getsockname(out);
|
||||
if (err) {
|
||||
throw errnoException(err, 'address');
|
||||
throw new ErrnoException(err, 'address');
|
||||
}
|
||||
return out;
|
||||
} else if (this._pipeName) {
|
||||
|
@ -2102,7 +2102,7 @@ function onconnection(err, clientHandle) {
|
|||
debug('onconnection');
|
||||
|
||||
if (err) {
|
||||
self.emit('error', errnoException(err, 'accept'));
|
||||
self.emit('error', new ErrnoException(err, 'accept'));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ function getCheckedFunction(fn) {
|
|||
const ctx = {};
|
||||
const ret = fn(ctx);
|
||||
if (ret === undefined) {
|
||||
throw new ERR_SYSTEM_ERROR(ctx);
|
||||
throw new ERR_SYSTEM_ERROR.HideStackFramesError(ctx);
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
|
|
|
@ -74,7 +74,7 @@ ReadStream.prototype.setRawMode = function(flag) {
|
|||
flag = !!flag;
|
||||
const err = this._handle?.setRawMode(flag);
|
||||
if (err) {
|
||||
this.emit('error', errors.errnoException(err, 'setRawMode'));
|
||||
this.emit('error', new errors.ErrnoException(err, 'setRawMode'));
|
||||
return this;
|
||||
}
|
||||
this.isRaw = flag;
|
||||
|
@ -129,7 +129,7 @@ WriteStream.prototype._refreshSize = function() {
|
|||
const winSize = new Array(2);
|
||||
const err = this._handle.getWindowSize(winSize);
|
||||
if (err) {
|
||||
this.emit('error', errors.errnoException(err, 'getWindowSize'));
|
||||
this.emit('error', new errors.ErrnoException(err, 'getWindowSize'));
|
||||
return;
|
||||
}
|
||||
const { 0: newCols, 1: newRows } = winSize;
|
||||
|
|
42
lib/util.js
42
lib/util.js
|
@ -32,6 +32,7 @@ const {
|
|||
DatePrototypeGetMonth,
|
||||
DatePrototypeGetSeconds,
|
||||
Error,
|
||||
ErrorCaptureStackTrace,
|
||||
FunctionPrototypeBind,
|
||||
NumberIsSafeInteger,
|
||||
ObjectDefineProperties,
|
||||
|
@ -51,9 +52,9 @@ const {
|
|||
ERR_INVALID_ARG_TYPE,
|
||||
ERR_OUT_OF_RANGE,
|
||||
},
|
||||
errnoException,
|
||||
exceptionWithHostPort,
|
||||
hideStackFrames,
|
||||
isErrorStackTraceLimitWritable,
|
||||
ErrnoException,
|
||||
ExceptionWithHostPort,
|
||||
} = require('internal/errors');
|
||||
const {
|
||||
format,
|
||||
|
@ -278,16 +279,17 @@ function _extend(target, source) {
|
|||
return target;
|
||||
}
|
||||
|
||||
const callbackifyOnRejected = hideStackFrames((reason, cb) => {
|
||||
const callbackifyOnRejected = (reason, cb) => {
|
||||
// `!reason` guard inspired by bluebird (Ref: https://goo.gl/t5IS6M).
|
||||
// Because `null` is a special error value in callbacks which means "no error
|
||||
// occurred", we error-wrap so the callback consumer can distinguish between
|
||||
// "the promise rejected with null" or "the promise fulfilled with undefined".
|
||||
if (!reason) {
|
||||
reason = new ERR_FALSY_VALUE_REJECTION(reason);
|
||||
reason = new ERR_FALSY_VALUE_REJECTION.HideStackFramesError(reason);
|
||||
ErrorCaptureStackTrace(reason, callbackifyOnRejected);
|
||||
}
|
||||
return cb(reason);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @template {(...args: any[]) => Promise<any>} T
|
||||
|
@ -345,10 +347,34 @@ function getSystemErrorName(err) {
|
|||
return internalErrorName(err);
|
||||
}
|
||||
|
||||
function _errnoException(...args) {
|
||||
if (isErrorStackTraceLimitWritable()) {
|
||||
const limit = Error.stackTraceLimit;
|
||||
Error.stackTraceLimit = 0;
|
||||
const e = new ErrnoException(...args);
|
||||
Error.stackTraceLimit = limit;
|
||||
ErrorCaptureStackTrace(e, _exceptionWithHostPort);
|
||||
return e;
|
||||
}
|
||||
return new ErrnoException(...args);
|
||||
}
|
||||
|
||||
function _exceptionWithHostPort(...args) {
|
||||
if (isErrorStackTraceLimitWritable()) {
|
||||
const limit = Error.stackTraceLimit;
|
||||
Error.stackTraceLimit = 0;
|
||||
const e = new ExceptionWithHostPort(...args);
|
||||
Error.stackTraceLimit = limit;
|
||||
ErrorCaptureStackTrace(e, _exceptionWithHostPort);
|
||||
return e;
|
||||
}
|
||||
return new ExceptionWithHostPort(...args);
|
||||
}
|
||||
|
||||
// Keep the `exports =` so that various functions can still be monkeypatched
|
||||
module.exports = {
|
||||
_errnoException: errnoException,
|
||||
_exceptionWithHostPort: exceptionWithHostPort,
|
||||
_errnoException,
|
||||
_exceptionWithHostPort,
|
||||
_extend,
|
||||
callbackify,
|
||||
debug: debuglog,
|
||||
|
|
10
lib/zlib.js
10
lib/zlib.js
|
@ -211,10 +211,10 @@ const checkFiniteNumber = hideStackFrames((number, name) => {
|
|||
return false;
|
||||
}
|
||||
|
||||
validateNumber(number, name);
|
||||
validateNumber.withoutStackTrace(number, name);
|
||||
|
||||
// Infinite numbers
|
||||
throw new ERR_OUT_OF_RANGE(name, 'a finite number', number);
|
||||
throw new ERR_OUT_OF_RANGE.HideStackFramesError(name, 'a finite number', number);
|
||||
});
|
||||
|
||||
// 1. Returns def for number when it's undefined or NaN
|
||||
|
@ -223,12 +223,12 @@ const checkFiniteNumber = hideStackFrames((number, name) => {
|
|||
// 4. Throws ERR_OUT_OF_RANGE for infinite numbers or numbers > upper or < lower
|
||||
const checkRangesOrGetDefault = hideStackFrames(
|
||||
(number, name, lower, upper, def) => {
|
||||
if (!checkFiniteNumber(number, name)) {
|
||||
if (!checkFiniteNumber.withoutStackTrace(number, name)) {
|
||||
return def;
|
||||
}
|
||||
if (number < lower || number > upper) {
|
||||
throw new ERR_OUT_OF_RANGE(name,
|
||||
`>= ${lower} and <= ${upper}`, number);
|
||||
throw new ERR_OUT_OF_RANGE.HideStackFramesError(name,
|
||||
`>= ${lower} and <= ${upper}`, number);
|
||||
}
|
||||
return number;
|
||||
},
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
throw aggregateTwoErrors(err, originalError);
|
||||
^
|
||||
|
||||
[AggregateError: original] {
|
||||
AggregateError: original
|
||||
at Object.<anonymous> (*error_aggregateTwoErrors.js:*:*) {
|
||||
code: 'ERR0',
|
||||
[errors]: [
|
||||
Error: original
|
||||
|
|
|
@ -11,6 +11,8 @@ const errors = require('internal/errors');
|
|||
const { internalBinding } = require('internal/test/binding');
|
||||
|
||||
const { UV_EAI_MEMORY } = internalBinding('uv');
|
||||
const memoryError = errors.dnsException(UV_EAI_MEMORY, 'fhqwhgads');
|
||||
const memoryError = new errors.DNSException(UV_EAI_MEMORY, 'fhqwhgads');
|
||||
|
||||
assert.strictEqual(memoryError.code, 'EAI_MEMORY');
|
||||
const stack = memoryError.stack.split('\n');
|
||||
assert.match(stack[1], /^ {4}at Object/);
|
||||
|
|
|
@ -57,3 +57,15 @@ assert.strictEqual(aggregateTwoErrors(null, null), null);
|
|||
assert.strictEqual(chainedError.code, err0.code);
|
||||
assert.deepStrictEqual(chainedError.errors, [err0, err1]);
|
||||
}
|
||||
|
||||
{
|
||||
const err0 = new Error('original');
|
||||
const err1 = new Error('second error');
|
||||
|
||||
err0.code = 'ERR0';
|
||||
err1.code = 'ERR1';
|
||||
|
||||
const chainedError = aggregateTwoErrors(null, aggregateTwoErrors(err1, err0));
|
||||
const stack = chainedError.stack.split('\n');
|
||||
assert.match(stack[1], /^ {4}at Object/);
|
||||
}
|
||||
|
|
242
test/parallel/test-errors-hide-stack-frames.js
Normal file
242
test/parallel/test-errors-hide-stack-frames.js
Normal file
|
@ -0,0 +1,242 @@
|
|||
// Flags: --expose-internals
|
||||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const { hideStackFrames, codes } = require('internal/errors');
|
||||
const { validateInteger } = require('internal/validators');
|
||||
const assert = require('assert');
|
||||
|
||||
{
|
||||
// Test that the a built-in error has the correct name and message.
|
||||
function a() {
|
||||
b();
|
||||
}
|
||||
|
||||
function b() {
|
||||
c();
|
||||
}
|
||||
|
||||
const c = hideStackFrames(function() {
|
||||
throw new Error('test');
|
||||
});
|
||||
|
||||
try {
|
||||
a();
|
||||
} catch (e) {
|
||||
assert.strictEqual(e.name, 'Error');
|
||||
assert.strictEqual(e.message, 'test');
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Test that validator errors have the correct name and message.
|
||||
try {
|
||||
validateInteger('2', 'test');
|
||||
} catch (e) {
|
||||
assert.strictEqual(e.name, 'TypeError');
|
||||
assert.strictEqual(e.message, 'The "test" argument must be of type number. Received type string (\'2\')');
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Test that validator fn is not in the stack trace.
|
||||
|
||||
function a(value) {
|
||||
validateInteger(value, 'test');
|
||||
}
|
||||
try {
|
||||
a('2');
|
||||
} catch (e) {
|
||||
assert.strictEqual(Error.stackTraceLimit, 10);
|
||||
const stack = e.stack.split('\n');
|
||||
assert.doesNotMatch(stack[1], /validateInteger/);
|
||||
assert.match(stack[1], /at a/);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Test that the stack trace is hidden for normal unnamed functions.
|
||||
function a() {
|
||||
b();
|
||||
}
|
||||
|
||||
function b() {
|
||||
c();
|
||||
}
|
||||
|
||||
const c = hideStackFrames(function() {
|
||||
throw new Error('test');
|
||||
});
|
||||
|
||||
try {
|
||||
a();
|
||||
} catch (e) {
|
||||
assert.strictEqual(Error.stackTraceLimit, 10);
|
||||
const stack = e.stack.split('\n');
|
||||
assert.doesNotMatch(stack[1], /at c/);
|
||||
assert.match(stack[1], /at b/);
|
||||
assert.strictEqual(Error.stackTraceLimit, 10);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Test that the stack trace is hidden for normal functions.
|
||||
function a() {
|
||||
b();
|
||||
}
|
||||
|
||||
function b() {
|
||||
c();
|
||||
}
|
||||
|
||||
const c = hideStackFrames(function c() {
|
||||
throw new Error('test');
|
||||
});
|
||||
|
||||
try {
|
||||
a();
|
||||
} catch (e) {
|
||||
assert.strictEqual(Error.stackTraceLimit, 10);
|
||||
const stack = e.stack.split('\n');
|
||||
assert.doesNotMatch(stack[1], /at c/);
|
||||
assert.match(stack[1], /at b/);
|
||||
assert.strictEqual(Error.stackTraceLimit, 10);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Test that the stack trace is hidden for arrow functions.
|
||||
function a() {
|
||||
b();
|
||||
}
|
||||
|
||||
function b() {
|
||||
c();
|
||||
}
|
||||
|
||||
const c = hideStackFrames(() => {
|
||||
throw new Error('test');
|
||||
});
|
||||
|
||||
try {
|
||||
a();
|
||||
} catch (e) {
|
||||
assert.strictEqual(Error.stackTraceLimit, 10);
|
||||
const stack = e.stack.split('\n');
|
||||
assert.doesNotMatch(stack[1], /at c/);
|
||||
assert.match(stack[1], /at b/);
|
||||
assert.strictEqual(Error.stackTraceLimit, 10);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Creating a new Error object without stack trace, then throwing it
|
||||
// should get a stack trace by hideStackFrames.
|
||||
function a() {
|
||||
b();
|
||||
}
|
||||
|
||||
function b() {
|
||||
c();
|
||||
}
|
||||
|
||||
const c = hideStackFrames(function() {
|
||||
throw new Error('test');
|
||||
});
|
||||
|
||||
try {
|
||||
a();
|
||||
} catch (e) {
|
||||
assert.strictEqual(Error.stackTraceLimit, 10);
|
||||
const stack = e.stack.split('\n');
|
||||
assert.doesNotMatch(stack[1], /at c/);
|
||||
assert.match(stack[1], /at b/);
|
||||
assert.strictEqual(Error.stackTraceLimit, 10);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const ERR_ACCESS_DENIED = codes.ERR_ACCESS_DENIED;
|
||||
// Creating a new Error object without stack trace, then throwing it
|
||||
// should get a stack trace by hideStackFrames.
|
||||
function a() {
|
||||
b();
|
||||
}
|
||||
|
||||
function b() {
|
||||
c();
|
||||
}
|
||||
|
||||
const c = hideStackFrames(function() {
|
||||
throw new ERR_ACCESS_DENIED.NoStackError('test');
|
||||
});
|
||||
|
||||
try {
|
||||
a();
|
||||
} catch (e) {
|
||||
assert.strictEqual(Error.stackTraceLimit, 10);
|
||||
const stack = e.stack.split('\n');
|
||||
assert.doesNotMatch(stack[1], /at c/);
|
||||
assert.match(stack[1], /at b/);
|
||||
assert.strictEqual(Error.stackTraceLimit, 10);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Creating a new Error object with stack trace, then throwing it
|
||||
// should get a stack trace by hideStackFrames.
|
||||
function a() {
|
||||
b();
|
||||
}
|
||||
|
||||
const b = hideStackFrames(function b() {
|
||||
c();
|
||||
});
|
||||
|
||||
const c = hideStackFrames(function() {
|
||||
throw new Error('test');
|
||||
});
|
||||
|
||||
try {
|
||||
a();
|
||||
} catch (e) {
|
||||
assert.strictEqual(Error.stackTraceLimit, 10);
|
||||
const stack = e.stack.split('\n');
|
||||
assert.match(stack[1], /at a/);
|
||||
assert.strictEqual(Error.stackTraceLimit, 10);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Binding passes the value of this to the wrapped function.
|
||||
let called = false;
|
||||
function a() {
|
||||
b.bind({ key: 'value' })();
|
||||
}
|
||||
|
||||
const b = hideStackFrames(function b() {
|
||||
assert.strictEqual(this.key, 'value');
|
||||
called = true;
|
||||
});
|
||||
|
||||
a();
|
||||
|
||||
assert.strictEqual(called, true);
|
||||
}
|
||||
|
||||
{
|
||||
// Binding passes the value of this to the withoutStackTrace function.
|
||||
let called = false;
|
||||
function a() {
|
||||
b.withoutStackTrace.bind({ key: 'value' })();
|
||||
}
|
||||
|
||||
const b = hideStackFrames(function b() {
|
||||
assert.strictEqual(this.key, 'value');
|
||||
called = true;
|
||||
});
|
||||
|
||||
a();
|
||||
|
||||
assert.strictEqual(called, true);
|
||||
}
|
|
@ -225,6 +225,7 @@ const values = [
|
|||
const errLines = stderr.trim().split(/[\r\n]+/);
|
||||
const errLine = errLines.find((l) => /^Error/.exec(l));
|
||||
assert.strictEqual(errLine, `Error: ${fixture}`);
|
||||
assert.strictEqual(errLines.length, 7);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -279,3 +280,20 @@ const values = [
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
// Test Promise factory
|
||||
function promiseFn(value) {
|
||||
return Promise.reject(value);
|
||||
}
|
||||
|
||||
const cbPromiseFn = callbackify(promiseFn);
|
||||
|
||||
cbPromiseFn(null, (err) => {
|
||||
assert.strictEqual(err.message, 'Promise was rejected with falsy value');
|
||||
assert.strictEqual(err.code, 'ERR_FALSY_VALUE_REJECTION');
|
||||
assert.strictEqual(err.reason, null);
|
||||
const stack = err.stack.split(/[\r\n]+/);
|
||||
assert.match(stack[1], /at process\.processTicksAndRejections/);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
'use strict';
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
const { uvException, uvExceptionWithHostPort } = require('internal/errors');
|
||||
const { UVException, UVExceptionWithHostPort } = require('internal/errors');
|
||||
|
||||
{
|
||||
const exception = uvException({ errno: 100, syscall: 'open' });
|
||||
const exception = new UVException({ errno: 100, syscall: 'open' });
|
||||
|
||||
assert.strictEqual(exception.message, 'UNKNOWN: unknown error, open');
|
||||
assert.strictEqual(exception.errno, 100);
|
||||
|
@ -14,7 +14,7 @@ const { uvException, uvExceptionWithHostPort } = require('internal/errors');
|
|||
}
|
||||
|
||||
{
|
||||
const exception = uvExceptionWithHostPort(100, 'listen', '127.0.0.1', 80);
|
||||
const exception = new UVExceptionWithHostPort(100, 'listen', '127.0.0.1', 80);
|
||||
|
||||
assert.strictEqual(exception.message,
|
||||
'listen UNKNOWN: unknown error 127.0.0.1:80');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue