Skip to content
Closed
Changes from 1 commit
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
Prev Previous commit
Next Next commit
errors: implement new error handling
This implements a function based system. Instead of passing in the
error code as first argument, the error code itself is a error class.
It already contains the correct error type, so while adding a new
error no one has to think about the error type anymore. In case a
single error code has more than one error type, the error class has
properties for the non default error types. Those can be used as
fallback.

This prevents typos, makes the implementation easier and it is less
verbose when writing the code for a new error.

The implementation itself does not interfere with the old
implementation. So the old and the new system can co-exist and it is
possible to slowly migrate the old ones to the new system.

PR-URL: #18857
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
  • Loading branch information
BridgeAR committed Mar 21, 2018
commit cc63116880cd7f4d39bdc527a9b9f3073f983af0
56 changes: 50 additions & 6 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

const kCode = Symbol('code');
const messages = new Map();
const codes = {};

var green = '';
var red = '';
Expand Down Expand Up @@ -194,6 +195,54 @@ function createErrDiff(actual, expected, operator) {
return `${msg}${skipped ? skippedMsg : ''}\n${res}${other}${end}`;
}

function makeNodeErrorWithCode(Base, key) {
return class NodeError extends Base {
constructor(...args) {
super(message(key, args));
}

get name() {
return `${super.name} [${key}]`;
}

set name(value) {
defineProperty(this, 'name', {
configurable: true,
enumerable: true,
value,
writable: true
});
}

get code() {
return key;
}

set code(value) {
defineProperty(this, 'code', {
configurable: true,
enumerable: true,
value,
writable: true
});
}
};
}

// Utility function for registering the error codes. Only used here. Exported
// *only* to allow for testing.
function E(sym, val, def, ...otherClasses) {
messages.set(sym, val);
if (def === undefined) return;
def = makeNodeErrorWithCode(def, sym);
if (otherClasses.length !== 0) {
otherClasses.forEach((clazz) => {
def[clazz.name] = makeNodeErrorWithCode(clazz, sym);
});
}
codes[sym] = def;
}

class AssertionError extends Error {
constructor(options) {
if (typeof options !== 'object' || options === null) {
Expand Down Expand Up @@ -296,12 +345,6 @@ function message(key, args) {
return String(fmt.apply(null, args));
}

// Utility function for registering the error codes. Only used here. Exported
// *only* to allow for testing.
function E(sym, val) {
messages.set(sym, typeof val === 'function' ? val : String(val));
}

/**
* This used to be util._errnoException().
*
Expand Down Expand Up @@ -412,6 +455,7 @@ module.exports = exports = {
RangeError: makeNodeError(RangeError),
URIError: makeNodeError(URIError),
AssertionError,
codes,
E // This is exported only to facilitate testing.
};

Expand Down