Skip to content

Commit b353e31

Browse files
committed
lib: deserialize to native errors in error_serdes
1 parent c1f090d commit b353e31

File tree

3 files changed

+49
-11
lines changed

3 files changed

+49
-11
lines changed

lib/internal/error_serdes.js

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const {
66
EvalError,
77
FunctionPrototypeCall,
88
ObjectAssign,
9-
ObjectCreate,
9+
ObjectDefineProperties,
1010
ObjectDefineProperty,
1111
ObjectGetOwnPropertyDescriptor,
1212
ObjectGetOwnPropertyNames,
@@ -15,11 +15,12 @@ const {
1515
ObjectPrototypeToString,
1616
RangeError,
1717
ReferenceError,
18+
ReflectConstruct,
19+
ReflectDeleteProperty,
1820
SafeSet,
1921
StringFromCharCode,
2022
StringPrototypeSubstring,
2123
SymbolFor,
22-
SymbolToStringTag,
2324
SyntaxError,
2425
TypeError,
2526
TypedArrayPrototypeGetBuffer,
@@ -28,6 +29,8 @@ const {
2829
URIError,
2930
} = primordials;
3031

32+
const assert = require('internal/assert');
33+
3134
const { Buffer } = require('buffer');
3235
const { inspect: { custom: customInspectSymbol } } = require('util');
3336

@@ -166,16 +169,17 @@ function deserializeError(error) {
166169
switch (error[0]) {
167170
case kSerializedError: {
168171
const { constructor, properties } = deserialize(error.subarray(1));
169-
const ctor = errors[constructor];
170-
ObjectDefineProperty(properties, SymbolToStringTag, {
171-
__proto__: null,
172-
value: { __proto__: null, value: 'Error', configurable: true },
173-
enumerable: true,
174-
});
172+
assert(errorConstructorNames.has(constructor), 'Invalid constructor');
175173
if ('cause' in properties && 'value' in properties.cause) {
176174
properties.cause.value = deserializeError(properties.cause.value);
177175
}
178-
return ObjectCreate(ctor.prototype, properties);
176+
// Invoke the Error constructor to gain an object with an [[ErrorData]] internal slot
177+
const ret = ReflectConstruct(Error, [], errors[constructor]);
178+
// Delete any properties defined by the Error constructor before assigning from source
179+
ArrayPrototypeForEach(ObjectGetOwnPropertyNames(ret), (key) => {
180+
ReflectDeleteProperty(ret, key);
181+
});
182+
return ObjectDefineProperties(ret, properties);
179183
}
180184
case kSerializedObject:
181185
return deserialize(error.subarray(1));
@@ -196,7 +200,7 @@ function deserializeError(error) {
196200
[customInspectSymbol]: () => '[Circular object]',
197201
};
198202
}
199-
require('assert').fail('This should not happen');
203+
assert.fail('Unknown serializer flag');
200204
}
201205

202206
module.exports = { serializeError, deserializeError };

test/es-module/test-esm-loader-with-syntax-error.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ describe('ESM: loader with syntax error', { concurrency: !process.env.TEST_PARAL
1313
path('print-error-message.js'),
1414
]);
1515

16-
match(stderr, /SyntaxError \[Error\]:/);
16+
match(stderr, /SyntaxError:/);
1717
ok(!stderr.includes('Bad command or file name'));
1818
notStrictEqual(code, 0);
1919
});
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
'use strict';
2+
const common = require('../common');
3+
const assert = require('assert');
4+
const { isNativeError } = require('util/types');
5+
const { Worker } = require('worker_threads');
6+
7+
const validateError = (error, ctor) => {
8+
assert.strictEqual(error.constructor, ctor);
9+
assert.strictEqual(Object.getPrototypeOf(error), ctor.prototype);
10+
assert(isNativeError(error));
11+
};
12+
13+
{
14+
const w = new Worker('throw new Error()', { eval: true });
15+
w.on('error', common.mustCall((error) => {
16+
validateError(error, Error);
17+
}));
18+
}
19+
20+
{
21+
const w = new Worker('throw new RangeError()', { eval: true });
22+
w.on('error', common.mustCall((error) => {
23+
validateError(error, RangeError);
24+
}));
25+
}
26+
27+
{
28+
const w = new Worker('throw new Error(undefined, { cause: new TypeError() })', { eval: true });
29+
w.on('error', common.mustCall((error) => {
30+
validateError(error, Error);
31+
assert.notStrictEqual(error.cause, undefined);
32+
validateError(error.cause, TypeError);
33+
}));
34+
}

0 commit comments

Comments
 (0)