From a07959033ea9fce98a1d907108d448a841987421 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sat, 11 Jul 2020 14:19:38 +0200 Subject: [PATCH 1/2] worker: fix nested uncaught exception handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- lib/internal/error_serdes.js | 4 ++++ test/parallel/test-error-serdes.js | 9 +++++++-- test/parallel/test-worker-nested-uncaught.js | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 test/parallel/test-worker-nested-uncaught.js diff --git a/lib/internal/error_serdes.js b/lib/internal/error_serdes.js index 72e8c12e9a7358..d0128cb80892c4 100644 --- a/lib/internal/error_serdes.js +++ b/lib/internal/error_serdes.js @@ -116,6 +116,10 @@ function deserializeError(error) { case kSerializedError: const { constructor, properties } = deserialize(error.subarray(1)); const ctor = errors[constructor]; + ObjectDefineProperty(properties, Symbol.toStringTag, { + 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 262afc9f389358..f01dc0d6a8a81d 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 00000000000000..2559b85ee1e6aa --- /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' + })); From ee7775abbf3500a7c519db588e59432e8e750091 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sat, 11 Jul 2020 14:27:15 +0200 Subject: [PATCH 2/2] fixup! worker: fix nested uncaught exception handling --- lib/internal/error_serdes.js | 3 ++- test/parallel/test-worker-nested-uncaught.js | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/internal/error_serdes.js b/lib/internal/error_serdes.js index d0128cb80892c4..5e18448da7046c 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,7 +117,7 @@ function deserializeError(error) { case kSerializedError: const { constructor, properties } = deserialize(error.subarray(1)); const ctor = errors[constructor]; - ObjectDefineProperty(properties, Symbol.toStringTag, { + ObjectDefineProperty(properties, SymbolToStringTag, { value: { value: 'Error', configurable: true }, enumerable: true }); diff --git a/test/parallel/test-worker-nested-uncaught.js b/test/parallel/test-worker-nested-uncaught.js index 2559b85ee1e6aa..00bb6832203442 100644 --- a/test/parallel/test-worker-nested-uncaught.js +++ b/test/parallel/test-worker-nested-uncaught.js @@ -9,6 +9,6 @@ const w = new Worker( new Worker("throw new Error('uncaught')", { eval:true })`, { eval: true }); w.on('error', common.expectsError({ - name: 'Error', - message: 'uncaught' - })); + name: 'Error', + message: 'uncaught' +}));