From 394c61caf981c90f4df2d002143c77f12a528ab8 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Tue, 11 Apr 2023 19:55:41 +0200 Subject: [PATCH] bootstrap: support namespaced builtins in snapshot scripts PR-URL: https://github.com/nodejs/node/pull/47467 Reviewed-By: Colin Ihrig Reviewed-By: Chengzhong Wu --- lib/internal/main/mksnapshot.js | 18 +++++--- .../test-snapshot-namespaced-builtin.js | 42 +++++++++++++++++++ 2 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 test/parallel/test-snapshot-namespaced-builtin.js diff --git a/lib/internal/main/mksnapshot.js b/lib/internal/main/mksnapshot.js index a0a917c7eed157..6dee4334fbaa4f 100644 --- a/lib/internal/main/mksnapshot.js +++ b/lib/internal/main/mksnapshot.js @@ -7,6 +7,8 @@ const { ObjectSetPrototypeOf, SafeArrayIterator, SafeSet, + StringPrototypeStartsWith, + StringPrototypeSlice, } = primordials; const binding = internalBinding('mksnapshot'); @@ -95,7 +97,13 @@ function supportedInUserSnapshot(id) { } function requireForUserSnapshot(id) { - if (!BuiltinModule.canBeRequiredByUsers(id)) { + let normalizedId = id; + if (StringPrototypeStartsWith(id, 'node:')) { + normalizedId = StringPrototypeSlice(id, 5); + } + if (!BuiltinModule.canBeRequiredByUsers(normalizedId) || + (id !== normalizedId && + !BuiltinModule.canBeRequiredWithoutScheme(normalizedId))) { // eslint-disable-next-line no-restricted-syntax const err = new Error( `Cannot find module '${id}'. `, @@ -103,15 +111,15 @@ function requireForUserSnapshot(id) { err.code = 'MODULE_NOT_FOUND'; throw err; } - if (!supportedInUserSnapshot(id)) { - if (!warnedModules.has(id)) { + if (!supportedInUserSnapshot(normalizedId)) { + if (!warnedModules.has(normalizedId)) { process.emitWarning( `built-in module ${id} is not yet supported in user snapshots`); - warnedModules.add(id); + warnedModules.add(normalizedId); } } - return require(id); + return require(normalizedId); } function main() { diff --git a/test/parallel/test-snapshot-namespaced-builtin.js b/test/parallel/test-snapshot-namespaced-builtin.js new file mode 100644 index 00000000000000..f3989273070333 --- /dev/null +++ b/test/parallel/test-snapshot-namespaced-builtin.js @@ -0,0 +1,42 @@ +'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 path = require('path'); +const fs = require('fs'); + +tmpdir.refresh(); +const blobPath = path.join(tmpdir.path, 'snapshot.blob'); +{ + // The list of modules supported in the snapshot is unstable, so just check + // a few that are known to work. + const code = ` + require("node:v8"); + require("node:fs"); + require("node:fs/promises"); + `; + fs.writeFileSync( + path.join(tmpdir.path, 'entry.js'), + code, + 'utf8' + ); + const child = spawnSync(process.execPath, [ + '--snapshot-blob', + blobPath, + '--build-snapshot', + 'entry.js', + ], { + cwd: tmpdir.path + }); + if (child.status !== 0) { + console.log(child.stderr.toString()); + console.log(child.stdout.toString()); + assert.strictEqual(child.status, 0); + } + const stats = fs.statSync(path.join(tmpdir.path, 'snapshot.blob')); + assert(stats.isFile()); +}