Skip to content

Commit 42a2a9b

Browse files
jdaltonTrott
authored andcommitted
errors: make code and name properties settable
For internal errors, make `code` and `name` settable while keeping them non-own properties by default. PR-URL: #15694 Fixes: #15658 Reviewed-By: Evan Lucas <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
1 parent 6e172be commit 42a2a9b

File tree

2 files changed

+69
-31
lines changed

2 files changed

+69
-31
lines changed

lib/internal/errors.js

+30-6
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@
1111
const kCode = Symbol('code');
1212
const messages = new Map();
1313

14-
const {
15-
kMaxLength
16-
} = process.binding('buffer');
14+
const { kMaxLength } = process.binding('buffer');
15+
const { defineProperty } = Object;
1716

1817
// Lazily loaded
1918
var util = null;
@@ -22,11 +21,36 @@ function makeNodeError(Base) {
2221
return class NodeError extends Base {
2322
constructor(key, ...args) {
2423
super(message(key, args));
25-
this[kCode] = this.code = key;
26-
Object.defineProperty(this, 'name', {
24+
defineProperty(this, kCode, {
2725
configurable: true,
2826
enumerable: false,
29-
value: `${super.name} [${this[kCode]}]`,
27+
value: key,
28+
writable: true
29+
});
30+
}
31+
32+
get name() {
33+
return `${super.name} [${this[kCode]}]`;
34+
}
35+
36+
set name(value) {
37+
defineProperty(this, 'name', {
38+
configurable: true,
39+
enumerable: true,
40+
value,
41+
writable: true
42+
});
43+
}
44+
45+
get code() {
46+
return this[kCode];
47+
}
48+
49+
set code(value) {
50+
defineProperty(this, 'code', {
51+
configurable: true,
52+
enumerable: true,
53+
value,
3054
writable: true
3155
});
3256
}

test/parallel/test-internal-errors.js

+39-25
Original file line numberDiff line numberDiff line change
@@ -307,38 +307,52 @@ assert.strictEqual(
307307
{
308308
const myError = new errors.Error('ERR_TLS_HANDSHAKE_TIMEOUT');
309309
assert.strictEqual(myError.code, 'ERR_TLS_HANDSHAKE_TIMEOUT');
310+
assert.strictEqual(myError.hasOwnProperty('code'), false);
311+
assert.strictEqual(myError.hasOwnProperty('name'), false);
312+
assert.deepStrictEqual(Object.keys(myError), []);
310313
const initialName = myError.name;
311314
myError.code = 'FHQWHGADS';
312315
assert.strictEqual(myError.code, 'FHQWHGADS');
313316
assert.strictEqual(myError.name, initialName);
317+
assert.deepStrictEqual(Object.keys(myError), ['code']);
314318
assert.ok(myError.name.includes('ERR_TLS_HANDSHAKE_TIMEOUT'));
315319
assert.ok(!myError.name.includes('FHQWHGADS'));
316320
}
317321

318-
// Test that `name` and `message` are mutable and that changing them alters
319-
// `toString()` but not `console.log()` results, which is the behavior of
320-
// `Error` objects in the browser.
322+
// Test that `name` is mutable and that changing it alters `toString()` but not
323+
// `console.log()` results, which is the behavior of `Error` objects in the
324+
// browser. Note that `name` becomes enumerable after being assigned.
321325
{
322-
function test(prop) {
323-
let initialConsoleLog = '';
324-
common.hijackStdout((data) => { initialConsoleLog += data; });
325-
const myError = new errors.Error('ERR_TLS_HANDSHAKE_TIMEOUT');
326-
const initialToString = myError.toString();
327-
console.log(myError);
328-
assert.notStrictEqual(initialConsoleLog, '');
329-
330-
common.restoreStdout();
331-
332-
let subsequentConsoleLog = '';
333-
common.hijackStdout((data) => { subsequentConsoleLog += data; });
334-
myError[prop] = 'Fhqwhgads';
335-
assert.notStrictEqual(myError.toString(), initialToString);
336-
console.log(myError);
337-
assert.strictEqual(subsequentConsoleLog, initialConsoleLog);
338-
339-
common.restoreStdout();
340-
}
341-
342-
test('name');
343-
test('message');
326+
const myError = new errors.Error('ERR_TLS_HANDSHAKE_TIMEOUT');
327+
assert.deepStrictEqual(Object.keys(myError), []);
328+
const initialToString = myError.toString();
329+
330+
myError.name = 'Fhqwhgads';
331+
assert.deepStrictEqual(Object.keys(myError), ['name']);
332+
assert.notStrictEqual(myError.toString(), initialToString);
333+
}
334+
335+
// Test that `message` is mutable and that changing it alters `toString()` but
336+
// not `console.log()` results, which is the behavior of `Error` objects in the
337+
// browser. Note that `message` remains non-enumerable after being assigned.
338+
{
339+
let initialConsoleLog = '';
340+
common.hijackStdout((data) => { initialConsoleLog += data; });
341+
const myError = new errors.Error('ERR_TLS_HANDSHAKE_TIMEOUT');
342+
assert.deepStrictEqual(Object.keys(myError), []);
343+
const initialToString = myError.toString();
344+
console.log(myError);
345+
assert.notStrictEqual(initialConsoleLog, '');
346+
347+
common.restoreStdout();
348+
349+
let subsequentConsoleLog = '';
350+
common.hijackStdout((data) => { subsequentConsoleLog += data; });
351+
myError.message = 'Fhqwhgads';
352+
assert.deepStrictEqual(Object.keys(myError), []);
353+
assert.notStrictEqual(myError.toString(), initialToString);
354+
console.log(myError);
355+
assert.strictEqual(subsequentConsoleLog, initialConsoleLog);
356+
357+
common.restoreStdout();
344358
}

0 commit comments

Comments
 (0)