summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2020-07-11 14:19:38 +0200
committerMyles Borins <mylesborins@github.com>2020-07-16 17:09:11 -0400
commit1bc4def18ff7a3f7607a82c0193294382238b85c (patch)
tree1062df5fed0f91658611e04cc0ff565bd83077d0
parent060c95a3b1b1d26396df7cf6d19472a8bcaad9e8 (diff)
downloadnode-new-1bc4def18ff7a3f7607a82c0193294382238b85c.tar.gz
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: https://github.com/nodejs/node/issues/34309 PR-URL: https://github.com/nodejs/node/pull/34310 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Yongsheng Zhang <zyszys98@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
-rw-r--r--lib/internal/error_serdes.js5
-rw-r--r--test/parallel/test-error-serdes.js9
-rw-r--r--test/parallel/test-worker-nested-uncaught.js14
3 files changed, 26 insertions, 2 deletions
diff --git a/lib/internal/error_serdes.js b/lib/internal/error_serdes.js
index 72e8c12e9a..5e18448da7 100644
--- a/lib/internal/error_serdes.js
+++ b/lib/internal/error_serdes.js
@@ -14,6 +14,7 @@ const {
ObjectKeys,
ObjectPrototypeToString,
SafeSet,
+ SymbolToStringTag,
} = primordials;
const kSerializedError = 0;
@@ -116,6 +117,10 @@ function deserializeError(error) {
case kSerializedError:
const { constructor, properties } = deserialize(error.subarray(1));
const ctor = errors[constructor];
+ ObjectDefineProperty(properties, SymbolToStringTag, {
+ value: { value: 'Error', configurable: true },
+ enumerable: true
+ });
return ObjectCreate(ctor.prototype, properties);
case kSerializedObject:
return deserialize(error.subarray(1));
diff --git a/test/parallel/test-error-serdes.js b/test/parallel/test-error-serdes.js
index 262afc9f38..f01dc0d6a8 100644
--- a/test/parallel/test-error-serdes.js
+++ b/test/parallel/test-error-serdes.js
@@ -16,12 +16,17 @@ assert.strictEqual(cycle(null), null);
assert.strictEqual(cycle(undefined), undefined);
assert.strictEqual(cycle('foo'), 'foo');
-{
- const err = cycle(new Error('foo'));
+let err = new Error('foo');
+for (let i = 0; i < 10; i++) {
assert(err instanceof Error);
+ assert(Object.prototype.toString.call(err), '[object Error]');
assert.strictEqual(err.name, 'Error');
assert.strictEqual(err.message, 'foo');
assert(/^Error: foo\n/.test(err.stack));
+
+ const prev = err;
+ err = cycle(err);
+ assert.deepStrictEqual(err, prev);
}
assert.strictEqual(cycle(new RangeError('foo')).name, 'RangeError');
diff --git a/test/parallel/test-worker-nested-uncaught.js b/test/parallel/test-worker-nested-uncaught.js
new file mode 100644
index 0000000000..00bb683220
--- /dev/null
+++ b/test/parallel/test-worker-nested-uncaught.js
@@ -0,0 +1,14 @@
+'use strict';
+const common = require('../common');
+const { Worker } = require('worker_threads');
+
+// Regression test for https://github.com/nodejs/node/issues/34309
+
+const w = new Worker(
+ `const { Worker } = require('worker_threads');
+ new Worker("throw new Error('uncaught')", { eval:true })`,
+ { eval: true });
+w.on('error', common.expectsError({
+ name: 'Error',
+ message: 'uncaught'
+}));