Skip to content

Commit b225544

Browse files
committed
module: add prefix-only modules to module.builtinModules
Fixes nodejs#42785
1 parent 142adef commit b225544

10 files changed

+38
-25
lines changed

doc/api/module.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ added:
2828
A list of the names of all modules provided by Node.js. Can be used to verify
2929
if a module is maintained by a third party or not.
3030

31-
Note: the list doesn't contain [prefix-only modules][] like `node:test`.
31+
Note: the list also contains [prefix-only modules][] like `node:test`.
3232

3333
`module` in this context isn't the same object that's provided
3434
by the [module wrapper][]. To access it, require the `Module` module:

doc/api/modules.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ Some built-in modules are always preferentially loaded if their identifier is
513513
passed to `require()`. For instance, `require('http')` will always
514514
return the built-in HTTP module, even if there is a file by that name. The list
515515
of built-in modules that can be loaded without using the `node:` prefix is exposed
516-
as [`module.builtinModules`][].
516+
in [`module.builtinModules`][], listed without the prefix.
517517

518518
### Built-in modules with mandatory `node:` prefix
519519

@@ -527,6 +527,8 @@ taken the name. Currently the built-in modules that requires the `node:` prefix
527527
* [`node:test`][]
528528
* [`node:test/reporters`][]
529529

530+
The list of these modules is exposed in [`module.builtinModules`][], including the prefix.
531+
530532
## Cycles
531533

532534
<!--type=misc-->

lib/internal/bootstrap/realm.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -320,14 +320,17 @@ class BuiltinModule {
320320
);
321321
}
322322

323-
static getCanBeRequiredByUsersWithoutSchemeList() {
324-
return ArrayFrom(canBeRequiredByUsersWithoutSchemeList);
325-
}
326-
327323
static getSchemeOnlyModuleNames() {
328324
return ArrayFrom(schemelessBlockList);
329325
}
330326

327+
static getAllBuiltinModuleIds() {
328+
return [
329+
...canBeRequiredByUsersWithoutSchemeList,
330+
...ArrayFrom(schemelessBlockList, (x) => `node:${x}`),
331+
];
332+
}
333+
331334
// Used by user-land module loaders to compile and load builtins.
332335
compileForPublicLoader() {
333336
if (!BuiltinModule.canBeRequiredByUsers(this.id)) {

lib/internal/modules/cjs/loader.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,8 @@ Module.isBuiltin = BuiltinModule.isBuiltin;
434434
*/
435435
function initializeCJS() {
436436
// This need to be done at runtime in case --expose-internals is set.
437-
const builtinModules = BuiltinModule.getCanBeRequiredByUsersWithoutSchemeList();
438-
Module.builtinModules = ObjectFreeze(builtinModules);
437+
438+
Module.builtinModules = ObjectFreeze(BuiltinModule.getAllBuiltinModuleIds());
439439

440440
initializeCjsConditions();
441441

lib/repl.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ const { shouldColorize } = require('internal/util/colors');
131131
const CJSModule = require('internal/modules/cjs/loader').Module;
132132
let _builtinLibs = ArrayPrototypeFilter(
133133
CJSModule.builtinModules,
134-
(e) => e[0] !== '_',
134+
(e) => e[0] !== '_' && !StringPrototypeStartsWith(e, 'node:'),
135135
);
136136
const nodeSchemeBuiltinLibs = ArrayPrototypeMap(
137137
_builtinLibs, (lib) => `node:${lib}`);

test/parallel/test-internal-module-require.js

+3
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ if (process.argv[2] === 'child') {
8787
});
8888
} else {
8989
require(id);
90+
if (!id.startsWith('node:')) {
91+
require(`node:${id}`);
92+
}
9093
publicModules.add(id);
9194
}
9295
}

test/parallel/test-process-get-builtin.mjs

+9-5
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,19 @@ for (const id of publicBuiltins) {
4141
}
4242
// Check that import(id).default returns the same thing as process.getBuiltinModule(id).
4343
for (const id of publicBuiltins) {
44-
const imported = await import(`node:${id}`);
45-
assert.strictEqual(process.getBuiltinModule(id), imported.default);
44+
if (!id.startsWith('node:')) {
45+
const imported = await import(`node:${id}`);
46+
assert.strictEqual(process.getBuiltinModule(id), imported.default);
47+
}
4648
}
4749

4850
// publicBuiltins does not include 'test' which requires the node: prefix.
4951
const ids = publicBuiltins.add('test');
5052
// Check that import(id).default returns the same thing as process.getBuiltinModule(id).
5153
for (const id of ids) {
52-
const prefixed = `node:${id}`;
53-
const imported = await import(prefixed);
54-
assert.strictEqual(process.getBuiltinModule(prefixed), imported.default);
54+
if (!id.startsWith('node:')) {
55+
const prefixed = `node:${id}`;
56+
const imported = await import(prefixed);
57+
assert.strictEqual(process.getBuiltinModule(prefixed), imported.default);
58+
}
5559
}

test/parallel/test-repl-tab-complete-import.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,12 @@ testMe._domain.on('error', assert.ifError);
3232
testMe.complete('import(\'', common.mustCall((error, data) => {
3333
assert.strictEqual(error, null);
3434
publicModules.forEach((lib) => {
35-
assert(
36-
data[0].includes(lib) && data[0].includes(`node:${lib}`),
37-
`${lib} not found`,
38-
);
35+
if (!lib.startsWith('node:')) {
36+
assert(
37+
data[0].includes(lib) && data[0].includes(`node:${lib}`),
38+
`${lib} not found`,
39+
);
40+
}
3941
});
4042
const newModule = 'foobar';
4143
assert(!builtinModules.includes(newModule));
@@ -55,7 +57,7 @@ testMe.complete("import\t( 'n", common.mustCall((error, data) => {
5557
// import(...) completions include `node:` URL modules:
5658
let lastIndex = -1;
5759

58-
publicModules.forEach((lib, index) => {
60+
publicModules.filter((lib) => !lib.startsWith('node:')).forEach((lib, index) => {
5961
lastIndex = completions.indexOf(`node:${lib}`);
6062
assert.notStrictEqual(lastIndex, -1);
6163
});

test/parallel/test-repl-tab-complete.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ testMe.complete('require(\'', common.mustCall(function(error, data) {
275275
assert.strictEqual(error, null);
276276
publicModules.forEach((lib) => {
277277
assert(
278-
data[0].includes(lib) && data[0].includes(`node:${lib}`),
278+
data[0].includes(lib) && (lib.startsWith('node:') || data[0].includes(`node:${lib}`)),
279279
`${lib} not found`
280280
);
281281
});
@@ -295,7 +295,7 @@ testMe.complete("require\t( 'n", common.mustCall(function(error, data) {
295295
// require(...) completions include `node:`-prefixed modules:
296296
let lastIndex = -1;
297297

298-
publicModules.forEach((lib, index) => {
298+
publicModules.filter((lib) => !lib.startsWith('node:')).forEach((lib, index) => {
299299
lastIndex = data[0].indexOf(`node:${lib}`);
300300
assert.notStrictEqual(lastIndex, -1);
301301
});

test/parallel/test-require-resolve.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,9 @@ require(fixtures.path('resolve-paths', 'default', 'verify-paths.js'));
6161
// builtinModules.
6262
builtinModules.forEach((mod) => {
6363
assert.strictEqual(require.resolve.paths(mod), null);
64-
});
65-
66-
builtinModules.forEach((mod) => {
67-
assert.strictEqual(require.resolve.paths(`node:${mod}`), null);
64+
if (!mod.startsWith('node:')) {
65+
assert.strictEqual(require.resolve.paths(`node:${mod}`), null);
66+
}
6867
});
6968

7069
// node_modules.

0 commit comments

Comments
 (0)