Skip to content

Commit 003f6ba

Browse files
committed
sea: allow requiring core modules with the "node:" prefix
Previously, the `require()` function exposed to the embedded SEA code was calling the internal `require()` function if the module name belonged to the list of public core modules but the internal `require()` function does not support loading modules with the "node:" prefix, so this change forwards the calls to another `require()` function that supports this. Fixes: nodejs/single-executable#69 Signed-off-by: Darshan Sen <[email protected]> PR-URL: nodejs/node#47779 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Michael Dawson <[email protected]> Reviewed-By: Joyee Cheung <[email protected]> Signed-off-by: Darshan Sen <[email protected]>
1 parent ef85828 commit 003f6ba

File tree

4 files changed

+40
-15
lines changed

4 files changed

+40
-15
lines changed

lib/internal/bootstrap/loaders.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ const {
5858
SafeMap,
5959
SafeSet,
6060
String,
61+
StringPrototypeSlice,
6162
StringPrototypeStartsWith,
6263
TypeError,
6364
} = primordials;
@@ -257,6 +258,20 @@ class BuiltinModule {
257258
return !schemelessBlockList.has(id);
258259
}
259260

261+
static normalizeRequirableId(id) {
262+
let normalizedId = id;
263+
if (StringPrototypeStartsWith(id, 'node:')) {
264+
normalizedId = StringPrototypeSlice(id, 5);
265+
}
266+
267+
if (!BuiltinModule.canBeRequiredByUsers(normalizedId) ||
268+
(id === normalizedId && !BuiltinModule.canBeRequiredWithoutScheme(normalizedId))) {
269+
return undefined;
270+
}
271+
272+
return normalizedId;
273+
}
274+
260275
static getSchemeOnlyModuleNames() {
261276
return ArrayFrom(schemelessBlockList);
262277
}

lib/internal/main/mksnapshot.js

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,10 @@ const {
77
ObjectSetPrototypeOf,
88
SafeArrayIterator,
99
SafeSet,
10-
StringPrototypeStartsWith,
11-
StringPrototypeSlice,
1210
} = primordials;
1311

1412
const binding = internalBinding('mksnapshot');
15-
const { BuiltinModule } = require('internal/bootstrap/loaders');
13+
const { BuiltinModule: { normalizeRequirableId } } = require('internal/bootstrap/loaders');
1614
const {
1715
compileSerializeMain,
1816
} = binding;
@@ -97,13 +95,8 @@ function supportedInUserSnapshot(id) {
9795
}
9896

9997
function requireForUserSnapshot(id) {
100-
let normalizedId = id;
101-
if (StringPrototypeStartsWith(id, 'node:')) {
102-
normalizedId = StringPrototypeSlice(id, 5);
103-
}
104-
if (!BuiltinModule.canBeRequiredByUsers(normalizedId) ||
105-
(id !== normalizedId &&
106-
!BuiltinModule.canBeRequiredWithoutScheme(normalizedId))) {
98+
const normalizedId = normalizeRequirableId(id);
99+
if (!normalizedId) {
107100
// eslint-disable-next-line no-restricted-syntax
108101
const err = new Error(
109102
`Cannot find module '${id}'. `,

lib/internal/main/single_executable_application.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const { getSingleExecutableCode } = internalBinding('sea');
77
const { emitExperimentalWarning } = require('internal/util');
88
const { Module, wrapSafe } = require('internal/modules/cjs/loader');
99
const { codes: { ERR_UNKNOWN_BUILTIN_MODULE } } = require('internal/errors');
10+
const { BuiltinModule: { normalizeRequirableId } } = require('internal/bootstrap/loaders');
1011

1112
prepareMainThreadExecution(false, true);
1213
markBootstrapComplete();
@@ -33,12 +34,13 @@ customModule.paths = Module._nodeModulePaths(customModule.path);
3334

3435
const customExports = customModule.exports;
3536

36-
function customRequire(path) {
37-
if (!Module.isBuiltin(path)) {
38-
throw new ERR_UNKNOWN_BUILTIN_MODULE(path);
37+
function customRequire(id) {
38+
const normalizedId = normalizeRequirableId(id);
39+
if (!normalizedId) {
40+
throw new ERR_UNKNOWN_BUILTIN_MODULE(id);
3941
}
4042

41-
return require(path);
43+
return require(normalizedId);
4244
}
4345

4446
customRequire.main = customModule;

test/fixtures/sea.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,23 @@ expectWarning('ExperimentalWarning',
99
'Single executable application is an experimental feature and ' +
1010
'might change at any time');
1111

12+
// Should be possible to require core modules that optionally require the
13+
// "node:" scheme.
1214
const { deepStrictEqual, strictEqual, throws } = require('assert');
13-
const { dirname } = require('path');
15+
const { dirname } = require('node:path');
16+
17+
// Should be possible to require a core module that requires using the "node:"
18+
// scheme.
19+
{
20+
const { test } = require('node:test');
21+
strictEqual(typeof test, 'function');
22+
}
23+
24+
// Should not be possible to require a core module without the "node:" scheme if
25+
// it requires using the "node:" scheme.
26+
throws(() => require('test'), {
27+
code: 'ERR_UNKNOWN_BUILTIN_MODULE',
28+
});
1429

1530
deepStrictEqual(process.argv, [process.execPath, process.execPath, '-a', '--b=c', 'd']);
1631

0 commit comments

Comments
 (0)