From 7df27582bbb896ebb72697da58209976a0b4daf6 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Fri, 5 May 2023 22:14:54 +0200 Subject: [PATCH] bootstrap: throw ERR_NOT_SUPPORTED_IN_SNAPSHOT in unsupported operation This patch adds a new ERR_NOT_SUPPORTED_IN_SNAPSHOT error and throw it in the worker constructor. PR-URL: https://github.com/nodejs/node/pull/47887 Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Chengzhong Wu --- doc/api/errors.md | 7 ++++++ lib/internal/errors.js | 2 ++ lib/internal/v8/startup_snapshot.js | 10 +++++++- lib/internal/worker.js | 5 +++- test/fixtures/snapshot/worker.js | 5 ++++ test/parallel/test-snapshot-worker.js | 34 +++++++++++++++++++++++++++ 6 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 test/fixtures/snapshot/worker.js create mode 100644 test/parallel/test-snapshot-worker.js diff --git a/doc/api/errors.md b/doc/api/errors.md index c0952792727e53..09f866fc2869b5 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -2420,6 +2420,13 @@ error indicates that the idle loop has failed to stop. An attempt was made to use operations that can only be used when building V8 startup snapshot even though Node.js isn't building one. + + +### `ERR_NOT_SUPPORTED_IN_SNAPSHOT` + +An attempt was made to perform operations that are not supported when +building a startup snapshot. + ### `ERR_NO_CRYPTO` diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 79c4c7fd024156..ec03ead14623f6 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -1469,6 +1469,8 @@ E('ERR_NETWORK_IMPORT_DISALLOWED', "import of '%s' by %s is not supported: %s", Error); E('ERR_NOT_BUILDING_SNAPSHOT', 'Operation cannot be invoked when not building startup snapshot', Error); +E('ERR_NOT_SUPPORTED_IN_SNAPSHOT', + '%s is not supported in startup snapshot', Error); E('ERR_NO_CRYPTO', 'Node.js is not compiled with OpenSSL crypto support', Error); E('ERR_NO_ICU', diff --git a/lib/internal/v8/startup_snapshot.js b/lib/internal/v8/startup_snapshot.js index e5154446b01a3d..5de746293d06e8 100644 --- a/lib/internal/v8/startup_snapshot.js +++ b/lib/internal/v8/startup_snapshot.js @@ -6,6 +6,7 @@ const { const { codes: { ERR_NOT_BUILDING_SNAPSHOT, + ERR_NOT_SUPPORTED_IN_SNAPSHOT, ERR_DUPLICATE_STARTUP_SNAPSHOT_MAIN_FUNCTION, }, } = require('internal/errors'); @@ -14,7 +15,7 @@ const { setSerializeCallback, setDeserializeCallback, setDeserializeMainFunction: _setDeserializeMainFunction, - isBuildingSnapshotBuffer + isBuildingSnapshotBuffer, } = internalBinding('mksnapshot'); function isBuildingSnapshot() { @@ -27,6 +28,12 @@ function throwIfNotBuildingSnapshot() { } } +function throwIfBuildingSnapshot(reason) { + if (isBuildingSnapshot()) { + throw new ERR_NOT_SUPPORTED_IN_SNAPSHOT(reason); + } +} + const deserializeCallbacks = []; let deserializeCallbackIsSet = false; function runDeserializeCallbacks() { @@ -102,6 +109,7 @@ function setDeserializeMainFunction(callback, data) { module.exports = { initializeCallbacks, runDeserializeCallbacks, + throwIfBuildingSnapshot, // Exposed to require('v8').startupSnapshot namespace: { addDeserializeCallback, diff --git a/lib/internal/worker.js b/lib/internal/worker.js index eda9dbcdeb5c04..401bc43550ea7f 100644 --- a/lib/internal/worker.js +++ b/lib/internal/worker.js @@ -60,7 +60,9 @@ const { deserializeError } = require('internal/error_serdes'); const { fileURLToPath, isURL, pathToFileURL } = require('internal/url'); const { kEmptyObject } = require('internal/util'); const { validateArray, validateString } = require('internal/validators'); - +const { + throwIfBuildingSnapshot, +} = require('internal/v8/startup_snapshot'); const { ownsProcessState, isMainThread, @@ -129,6 +131,7 @@ function assignEnvironmentData(data) { class Worker extends EventEmitter { constructor(filename, options = kEmptyObject) { + throwIfBuildingSnapshot('Creating workers'); super(); const isInternal = arguments[2] === kIsInternal; debug( diff --git a/test/fixtures/snapshot/worker.js b/test/fixtures/snapshot/worker.js new file mode 100644 index 00000000000000..c95c9bde96f5ad --- /dev/null +++ b/test/fixtures/snapshot/worker.js @@ -0,0 +1,5 @@ +'use strict'; + +const { Worker } = require('worker_threads'); + +new Worker('1', { eval: true }); diff --git a/test/parallel/test-snapshot-worker.js b/test/parallel/test-snapshot-worker.js new file mode 100644 index 00000000000000..6fe5aa9638a8c5 --- /dev/null +++ b/test/parallel/test-snapshot-worker.js @@ -0,0 +1,34 @@ +'use strict'; + +// This tests snapshot JS API using the example in the docs. + +require('../common'); +const assert = require('assert'); +const { spawnSync } = require('child_process'); +const tmpdir = require('../common/tmpdir'); +const fixtures = require('../common/fixtures'); +const path = require('path'); +const fs = require('fs'); + +tmpdir.refresh(); +const blobPath = path.join(tmpdir.path, 'snapshot.blob'); +const entry = fixtures.path('snapshot', 'worker.js'); +{ + const child = spawnSync(process.execPath, [ + '--snapshot-blob', + blobPath, + '--build-snapshot', + entry, + ], { + cwd: tmpdir.path + }); + const stderr = child.stderr.toString(); + assert.match( + stderr, + /Error: Creating workers is not supported in startup snapshot/); + assert.match( + stderr, + /ERR_NOT_SUPPORTED_IN_SNAPSHOT/); + assert.strictEqual(child.status, 1); + assert(!fs.existsSync(blobPath)); +}