Skip to content

Commit c31b6bf

Browse files
committed
worker: fix nested uncaught exception handling
We are using `ObjectPrototypeToString()` as a cross-context brand check for built-in errors, but weren’t making sure to set that when deserializing errors back into JS objects. Fix that by setting `[Symbol.toStringTag]` manually, to make sure that multiple serialize-and-deserialize cycles keep giving the same result. Fixes: #34309 PR-URL: #34310 Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Yongsheng Zhang <[email protected]> Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent ed65137 commit c31b6bf

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

lib/internal/error-serdes.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const {
1414
ObjectKeys,
1515
ObjectPrototypeToString,
1616
SafeSet,
17+
SymbolToStringTag,
1718
} = primordials;
1819

1920
const kSerializedError = 0;
@@ -116,6 +117,10 @@ function deserializeError(error) {
116117
case kSerializedError:
117118
const { constructor, properties } = deserialize(error.subarray(1));
118119
const ctor = errors[constructor];
120+
ObjectDefineProperty(properties, SymbolToStringTag, {
121+
value: { value: 'Error', configurable: true },
122+
enumerable: true
123+
});
119124
return ObjectCreate(ctor.prototype, properties);
120125
case kSerializedObject:
121126
return deserialize(error.subarray(1));

test/parallel/test-error-serdes.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,17 @@ assert.strictEqual(cycle(null), null);
1616
assert.strictEqual(cycle(undefined), undefined);
1717
assert.strictEqual(cycle('foo'), 'foo');
1818

19-
{
20-
const err = cycle(new Error('foo'));
19+
let err = new Error('foo');
20+
for (let i = 0; i < 10; i++) {
2121
assert(err instanceof Error);
22+
assert(Object.prototype.toString.call(err), '[object Error]');
2223
assert.strictEqual(err.name, 'Error');
2324
assert.strictEqual(err.message, 'foo');
2425
assert(/^Error: foo\n/.test(err.stack));
26+
27+
const prev = err;
28+
err = cycle(err);
29+
assert.deepStrictEqual(err, prev);
2530
}
2631

2732
assert.strictEqual(cycle(new RangeError('foo')).name, 'RangeError');
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
'use strict';
2+
const common = require('../common');
3+
const { Worker } = require('worker_threads');
4+
5+
// Regression test for https://github.com/nodejs/node/issues/34309
6+
7+
const w = new Worker(
8+
`const { Worker } = require('worker_threads');
9+
new Worker("throw new Error('uncaught')", { eval:true })`,
10+
{ eval: true });
11+
w.on('error', common.expectsError({
12+
name: 'Error',
13+
message: 'uncaught'
14+
}));

0 commit comments

Comments
 (0)