Skip to content

Commit d57a242

Browse files
BridgeARMylesBorins
authored andcommitted
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. Backport-PR-URL: #19244 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>
1 parent cb732ae commit d57a242

File tree

1 file changed

+50
-6
lines changed

1 file changed

+50
-6
lines changed

lib/internal/errors.js

+50-6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
const kCode = Symbol('code');
1414
const messages = new Map();
15+
const codes = {};
1516

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

198+
function makeNodeErrorWithCode(Base, key) {
199+
return class NodeError extends Base {
200+
constructor(...args) {
201+
super(message(key, args));
202+
}
203+
204+
get name() {
205+
return `${super.name} [${key}]`;
206+
}
207+
208+
set name(value) {
209+
defineProperty(this, 'name', {
210+
configurable: true,
211+
enumerable: true,
212+
value,
213+
writable: true
214+
});
215+
}
216+
217+
get code() {
218+
return key;
219+
}
220+
221+
set code(value) {
222+
defineProperty(this, 'code', {
223+
configurable: true,
224+
enumerable: true,
225+
value,
226+
writable: true
227+
});
228+
}
229+
};
230+
}
231+
232+
// Utility function for registering the error codes. Only used here. Exported
233+
// *only* to allow for testing.
234+
function E(sym, val, def, ...otherClasses) {
235+
messages.set(sym, val);
236+
if (def === undefined) return;
237+
def = makeNodeErrorWithCode(def, sym);
238+
if (otherClasses.length !== 0) {
239+
otherClasses.forEach((clazz) => {
240+
def[clazz.name] = makeNodeErrorWithCode(clazz, sym);
241+
});
242+
}
243+
codes[sym] = def;
244+
}
245+
197246
class AssertionError extends Error {
198247
constructor(options) {
199248
if (typeof options !== 'object' || options === null) {
@@ -296,12 +345,6 @@ function message(key, args) {
296345
return String(fmt.apply(null, args));
297346
}
298347

299-
// Utility function for registering the error codes. Only used here. Exported
300-
// *only* to allow for testing.
301-
function E(sym, val) {
302-
messages.set(sym, typeof val === 'function' ? val : String(val));
303-
}
304-
305348
/**
306349
* This used to be util._errnoException().
307350
*
@@ -412,6 +455,7 @@ module.exports = exports = {
412455
RangeError: makeNodeError(RangeError),
413456
URIError: makeNodeError(URIError),
414457
AssertionError,
458+
codes,
415459
E // This is exported only to facilitate testing.
416460
};
417461

0 commit comments

Comments
 (0)