From 31ed23cfa5fda409db4f8ab5f75bffe7ab60984f Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sun, 8 Dec 2024 14:55:29 -0800 Subject: [PATCH] module: add `module.builtinPrefixOnlyModules` Fixes https://github.com/nodejs/node/issues/42785 --- doc/api/module.md | 26 +++++++++++++++++++ doc/api/modules.md | 3 +++ lib/internal/modules/cjs/loader.js | 3 +++ test/parallel/test-internal-module-require.js | 14 +++++++--- 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/doc/api/module.md b/doc/api/module.md index ffb07d6b5a32b8..89f80e9d2a8a30 100644 --- a/doc/api/module.md +++ b/doc/api/module.md @@ -45,6 +45,32 @@ import { builtinModules as builtin } from 'node:module'; const builtin = require('node:module').builtinModules; ``` +### `module.builtinPrefixOnlyModules` + + + +* {string\[]} + +A list of the names of all modules provided by Node.js that require a `node:` prefix. +Can be used to verify if a module is maintained by a third party or not. + +`module` in this context isn't the same object that's provided +by the [module wrapper][]. To access it, require the `Module` module: + +```mjs +// module.mjs +// In an ECMAScript module +import { builtinPrefoxOnlyModules as builtinPrefixOnly } from 'node:module'; +``` + +```cjs +// module.cjs +// In a CommonJS module +const builtinPrefixOnly = require('node:module').builtinPrefoxOnlyModules; +``` + ### `module.createRequire(filename)` @@ -1278,6 +1280,7 @@ This section was moved to [`__filename`]: #__filename [`import()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import [`module.builtinModules`]: module.md#modulebuiltinmodules +[`module.builtinPrefixOnlyModules`]: module.md#modulebuiltinprefixonlymodules [`module.children`]: #modulechildren [`module.id`]: #moduleid [`module` core module]: module.md diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index f99d0fc2a7a0eb..e556eed5191db9 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -423,6 +423,9 @@ function initializeCJS() { const builtinModules = BuiltinModule.getCanBeRequiredByUsersWithoutSchemeList(); Module.builtinModules = ObjectFreeze(builtinModules); + const builtinPrefixOnlyModules = ArrayPrototypeMap(BuiltinModule.getSchemeOnlyModuleNames(), x => `node:${x}`); + Module.builtinPrefixOnlyModules = ObjectFreeze(builtinPrefixOnlyModules); + initializeCjsConditions(); if (!getEmbedderOptions().noGlobalSearchPaths) { diff --git a/test/parallel/test-internal-module-require.js b/test/parallel/test-internal-module-require.js index c6e2057d3da1ee..e93074929b87ba 100644 --- a/test/parallel/test-internal-module-require.js +++ b/test/parallel/test-internal-module-require.js @@ -75,7 +75,7 @@ const expectedPublicModules = new Set([ if (process.argv[2] === 'child') { assert(!process.execArgv.includes('--expose-internals')); - process.once('message', ({ allBuiltins }) => { + process.once('message', ({ allBuiltins, builtinPrefixOnlyModules }) => { const publicModules = new Set(); for (const id of allBuiltins) { if (id.startsWith('internal/')) { @@ -87,6 +87,7 @@ if (process.argv[2] === 'child') { }); } else { require(id); + require(`node:${id}`); publicModules.add(id); } } @@ -98,15 +99,22 @@ if (process.argv[2] === 'child') { new Set(require('module').builtinModules) ); assert.deepStrictEqual(publicModules, expectedPublicModules); + + const prefixOnlyModules = new Set(); + for (const id of builtinPrefixOnlyModules) { + require(id); + prefixOnlyModules.add(id); + } + assert.deepStrictEqual(prefixOnlyModules, new Set(require('module').builtinPrefixOnlyModules)); }); } else { assert(process.execArgv.includes('--expose-internals')); const child = fork(__filename, ['child'], { execArgv: [] }); - const { builtinModules } = require('module'); + const { builtinModules, builtinPrefixOnlyModules } = require('module'); // When --expose-internals is on, require('module').builtinModules // contains internal modules. - const message = { allBuiltins: builtinModules }; + const message = { allBuiltins: builtinModules, builtinPrefixOnlyModules }; child.send(message); }