Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib: set properties in error #26752

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions lib/_stream_readable.js
Original file line number Diff line number Diff line change
Expand Up @@ -309,15 +309,13 @@ function addChunk(stream, state, chunk, addToFront) {
}

function chunkInvalid(state, chunk) {
var er;
if (!Stream._isUint8Array(chunk) &&
typeof chunk !== 'string' &&
chunk !== undefined &&
!state.objectMode) {
er = new ERR_INVALID_ARG_TYPE(
return new ERR_INVALID_ARG_TYPE(
'chunk', ['string', 'Buffer', 'Uint8Array'], chunk);
}
return er;
}


Expand Down
4 changes: 1 addition & 3 deletions lib/internal/encoding.js
Original file line number Diff line number Diff line change
Expand Up @@ -394,9 +394,7 @@ function makeTextDecoderICU() {

const ret = _decode(this[kHandle], input, flags);
if (typeof ret === 'number') {
const err = new ERR_ENCODING_INVALID_ENCODED_DATA(this.encoding);
err.errno = ret;
throw err;
throw new ERR_ENCODING_INVALID_ENCODED_DATA(this.encoding, ret);
}
return ret.toString('ucs2');
}
Expand Down
69 changes: 56 additions & 13 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ function lazyBuffer() {
// and may have .path and .dest.
class SystemError extends Error {
constructor(key, context) {
const prefix = getMessage(key, []);
super();
const prefix = getMessage(key, [], this);
let message = `${prefix}: ${context.syscall} returned ` +
`${context.code} (${context.message})`;

Expand All @@ -56,7 +57,12 @@ class SystemError extends Error {
if (context.dest !== undefined)
message += ` => ${context.dest}`;

super(message);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change? I'd prefer to have it there.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer it that way as well. The problem is that you may not use this before calling super() and we need the context to be able to attach properties to the error from within the function that constructs the error message.

Object.defineProperty(this, 'message', {
value: message,
enumerable: false,
writable: true,
configurable: true
});
Object.defineProperty(this, kInfo, {
configurable: false,
enumerable: false,
Expand Down Expand Up @@ -150,7 +156,14 @@ let useOriginalName = false;
function makeNodeErrorWithCode(Base, key) {
return class NodeError extends Base {
constructor(...args) {
super(getMessage(key, args));
super();
const message = getMessage(key, args, this);
Object.defineProperty(this, 'message', {
value: message,
enumerable: false,
writable: true,
configurable: true
});
}

get name() {
Expand Down Expand Up @@ -204,7 +217,7 @@ function E(sym, val, def, ...otherClasses) {
codes[sym] = def;
}

function getMessage(key, args) {
function getMessage(key, args, self) {
const msg = messages.get(key);

if (util === undefined) util = require('util');
Expand All @@ -216,7 +229,7 @@ function getMessage(key, args) {
`Code: ${key}; The provided arguments length (${args.length}) does not ` +
`match the required ones (${msg.length}).`
);
return msg.apply(null, args);
return msg.apply(self, args);
}

const expectedLength = (msg.match(/%[dfijoOs]/g) || []).length;
Expand Down Expand Up @@ -608,8 +621,10 @@ E('ERR_DOMAIN_CANNOT_SET_UNCAUGHT_EXCEPTION_CAPTURE',
'The `domain` module is in use, which is mutually exclusive with calling ' +
'process.setUncaughtExceptionCaptureCallback()',
Error);
E('ERR_ENCODING_INVALID_ENCODED_DATA',
'The encoded data was not valid for encoding %s', TypeError);
E('ERR_ENCODING_INVALID_ENCODED_DATA', function(encoding, ret) {
this.errno = ret;
return `The encoded data was not valid for encoding ${encoding}`;
}, TypeError);
E('ERR_ENCODING_NOT_SUPPORTED', 'The "%s" encoding is not supported',
RangeError);
E('ERR_FALSY_VALUE_REJECTION', 'Promise was rejected with falsy value', Error);
Expand Down Expand Up @@ -652,7 +667,16 @@ E('ERR_HTTP2_INVALID_PSEUDOHEADER',
'"%s" is an invalid pseudoheader or is used incorrectly', TypeError);
E('ERR_HTTP2_INVALID_SESSION', 'The session has been destroyed', Error);
E('ERR_HTTP2_INVALID_SETTING_VALUE',
'Invalid value for setting "%s": %s', TypeError, RangeError);
// Using default arguments here is important so the arguments are not counted
// towards `Function#length`.
function(name, actual, min = undefined, max = undefined) {
this.actual = actual;
if (min !== undefined) {
this.min = min;
this.max = max;
}
return `Invalid value for setting "${name}": ${actual}`;
}, TypeError, RangeError);
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);
Expand Down Expand Up @@ -685,7 +709,15 @@ E('ERR_HTTP2_SOCKET_UNBOUND',
E('ERR_HTTP2_STATUS_101',
'HTTP status code 101 (Switching Protocols) is forbidden in HTTP/2', Error);
E('ERR_HTTP2_STATUS_INVALID', 'Invalid status code: %s', RangeError);
E('ERR_HTTP2_STREAM_CANCEL', 'The pending stream has been canceled', Error);
E('ERR_HTTP2_STREAM_CANCEL', function(error) {
let msg = 'The pending stream has been canceled';
if (error) {
this.cause = error;
if (typeof error.message === 'string')
msg += ` (caused by: ${error.message})`;
}
return msg;
}, Error);
E('ERR_HTTP2_STREAM_ERROR', 'Stream closed with error code %s', Error);
E('ERR_HTTP2_STREAM_SELF_DEPENDENCY',
'A stream cannot depend on itself', Error);
Expand All @@ -709,7 +741,11 @@ E('ERR_INSPECTOR_CLOSED', 'Session was closed', Error);
E('ERR_INSPECTOR_COMMAND', 'Inspector error %d: %s', Error);
E('ERR_INSPECTOR_NOT_AVAILABLE', 'Inspector is not available', Error);
E('ERR_INSPECTOR_NOT_CONNECTED', 'Session is not connected', Error);
E('ERR_INVALID_ADDRESS_FAMILY', 'Invalid address family: %s', RangeError);
E('ERR_INVALID_ADDRESS_FAMILY', function(addressType, host, port) {
this.host = host;
this.port = port;
return `Invalid address family: ${addressType} ${host}:${port}`;
}, RangeError);
E('ERR_INVALID_ARG_TYPE',
(name, expected, actual) => {
assert(typeof name === 'string', "'name' must be a string");
Expand Down Expand Up @@ -812,7 +848,10 @@ E('ERR_INVALID_SYNC_FORK_INPUT',
E('ERR_INVALID_THIS', 'Value of "this" must be of type %s', TypeError);
E('ERR_INVALID_TUPLE', '%s must be an iterable %s tuple', TypeError);
E('ERR_INVALID_URI', 'URI malformed', URIError);
E('ERR_INVALID_URL', 'Invalid URL: %s', TypeError);
E('ERR_INVALID_URL', function(input) {
this.input = input;
return `Invalid URL: ${input}`;
}, TypeError);
E('ERR_INVALID_URL_SCHEME',
(expected) => `The URL must be ${oneOf(expected, 'scheme')}`, TypeError);
E('ERR_IPC_CHANNEL_CLOSED', 'Channel closed', Error);
Expand Down Expand Up @@ -926,8 +965,12 @@ 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_TLS_CERT_ALTNAME_INVALID',
'Hostname/IP does not match certificate\'s altnames: %s', Error);
E('ERR_TLS_CERT_ALTNAME_INVALID', function(reason, host, cert) {
this.reason = reason;
this.host = host;
this.cert = cert;
return `Hostname/IP does not match certificate's altnames: ${reason}`;
}, Error);
E('ERR_TLS_DH_PARAM_SIZE', 'DH parameter size %s is less than 2048', Error);
E('ERR_TLS_HANDSHAKE_TIMEOUT', 'TLS handshake timeout', Error);
E('ERR_TLS_INVALID_PROTOCOL_VERSION',
Expand Down
8 changes: 1 addition & 7 deletions lib/internal/http2/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,6 @@ function validateSettings(settings) {
typeof settings.enablePush !== 'boolean') {
const err = new ERR_HTTP2_INVALID_SETTING_VALUE('enablePush',
settings.enablePush);
err.actual = settings.enablePush;
Error.captureStackTrace(err, 'validateSettings');
throw err;
}
Expand Down Expand Up @@ -1216,12 +1215,7 @@ class Http2Session extends EventEmitter {
this.removeAllListeners('timeout');

// Destroy any pending and open streams
const cancel = new ERR_HTTP2_STREAM_CANCEL();
if (error) {
cancel.cause = error;
if (typeof error.message === 'string')
cancel.message += ` (caused by: ${error.message})`;
}
const cancel = new ERR_HTTP2_STREAM_CANCEL(error);
state.pendingStreams.forEach((stream) => stream.destroy(cancel));
state.streams.forEach((stream) => stream.destroy(error));

Expand Down
6 changes: 2 additions & 4 deletions lib/internal/http2/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -515,10 +515,8 @@ function assertIsObject(value, name, types) {
function assertWithinRange(name, value, min = 0, max = Infinity) {
if (value !== undefined &&
(typeof value !== 'number' || value < min || value > max)) {
const err = new ERR_HTTP2_INVALID_SETTING_VALUE.RangeError(name, value);
err.min = min;
err.max = max;
err.actual = value;
const err = new ERR_HTTP2_INVALID_SETTING_VALUE.RangeError(
name, value, min, max);
Error.captureStackTrace(err, assertWithinRange);
throw err;
}
Expand Down
4 changes: 1 addition & 3 deletions lib/internal/url.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,7 @@ function onParseComplete(flags, protocol, username, password,
}

function onParseError(flags, input) {
const error = new ERR_INVALID_URL(input);
error.input = input;
throw error;
throw new ERR_INVALID_URL(input);
}

function onParseProtocolComplete(flags, protocol, username, password,
Expand Down
17 changes: 9 additions & 8 deletions lib/net.js
Original file line number Diff line number Diff line change
Expand Up @@ -968,19 +968,20 @@ function lookupAndConnect(self, options) {
if (!self.connecting) return;

if (err) {
// net.createConnection() creates a net.Socket object and
// immediately calls net.Socket.connect() on it (that's us).
// There are no event listeners registered yet so defer the
// error event to the next tick.
// net.createConnection() creates a net.Socket object and immediately
// calls net.Socket.connect() on it (that's us). There are no event
// listeners registered yet so defer the error event to the next tick.
// TODO(BridgeAR): The error could either originate from user code or
// by the C++ layer. The port is never the cause for the error as it is
// not used in the lookup. We should probably just remove this.
err.host = options.host;
err.port = options.port;
err.message = err.message + ' ' + options.host + ':' + options.port;
process.nextTick(connectErrorNT, self, err);
} else if (addressType !== 4 && addressType !== 6) {
err = new ERR_INVALID_ADDRESS_FAMILY(addressType);
err.host = options.host;
err.port = options.port;
err.message = err.message + ' ' + options.host + ':' + options.port;
err = new ERR_INVALID_ADDRESS_FAMILY(addressType,
options.host,
options.port);
process.nextTick(connectErrorNT, self, err);
} else {
self._unrefTimer();
Expand Down
6 changes: 1 addition & 5 deletions lib/tls.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,7 @@ exports.checkServerIdentity = function checkServerIdentity(hostname, cert) {
}

if (!valid) {
const err = new ERR_TLS_CERT_ALTNAME_INVALID(reason);
err.reason = reason;
err.host = hostname;
err.cert = cert;
return err;
return new ERR_TLS_CERT_ALTNAME_INVALID(reason, hostname, cert);
}
};

Expand Down
Loading