| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 1eb55f3 commit 374743c
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1917,6 +1917,46 @@ console.log('After:', getActiveResourcesInfo()); | |||
| 1917 | 1917 | // After: [ 'TTYWrap', 'TTYWrap', 'TTYWrap', 'Timeout' ] | |
| 1918 | 1918 | ``` | |
| 1919 | 1919 | ||
| 1920 | + ## `process.getBuiltinModule(id)` | ||
| 1921 | + | ||
| 1922 | + <!-- YAML | ||
| 1923 | + added: REPLACEME | ||
| 1924 | + --> | ||
| 1925 | + | ||
| 1926 | + * `id` {string} ID of the built-in module being requested. | ||
| 1927 | + * Returns: {Object|undefined} | ||
| 1928 | + | ||
| 1929 | + `process.getBuiltinModule(id)` provides a way to load built-in modules | ||
| 1930 | + in a globally available function. ES Modules that need to support | ||
| 1931 | + other environments can use it to conditionally load a Node.js built-in | ||
| 1932 | + when it is run in Node.js, without having to deal with the resolution | ||
| 1933 | + error that can be thrown by `import` in a non-Node.js environment or | ||
| 1934 | + having to use dynamic `import()` which either turns the module into | ||
| 1935 | + an asynchronous module, or turns a synchronous API into an asynchronous one. | ||
| 1936 | + | ||
| 1937 | + ```mjs | ||
| 1938 | + if (globalThis.process?.getBuiltinModule) { | ||
| 1939 | + // Run in Node.js, use the Node.js fs module. | ||
| 1940 | + const fs = globalThis.process.getBuiltinModule('fs'); | ||
| 1941 | + // If `require()` is needed to load user-modules, use createRequire() | ||
| 1942 | + const module = globalThis.process.getBuiltinModule('module'); | ||
| 1943 | + const require = module.createRequire(import.meta.url); | ||
| 1944 | + const foo = require('foo'); | ||
| 1945 | + } | ||
| 1946 | + ``` | ||
| 1947 | + | ||
| 1948 | + If `id` specifies a built-in module available in the current Node.js process, | ||
| 1949 | + `process.getBuiltinModule(id)` method returns the corresponding built-in | ||
| 1950 | + module. If `id` does not correspond to any built-in module, `undefined` | ||
| 1951 | + is returned. | ||
| 1952 | + | ||
| 1953 | + `process.getBuiltinModule(id)` accepts built-in module IDs that are recognized | ||
| 1954 | + by [`module.isBuiltin(id)`][]. Some built-in modules must be loaded with the | ||
| 1955 | + `node:` prefix, see [built-in modules with mandatory `node:` prefix][]. | ||
| 1956 | + The references returned by `process.getBuiltinModule(id)` always point to | ||
| 1957 | + the built-in module corresponding to `id` even if users modify | ||
| 1958 | + [`require.cache`][] so that `require(id)` returns something else. | ||
| 1959 | + | ||
| 1920 | 1960 | ## `process.getegid()` | |
| 1921 | 1961 | ||
| 1922 | 1962 | <!-- YAML | |
@@ -4020,6 +4060,7 @@ cases: | |||
| 4020 | 4060 | [`console.error()`]: console.md#consoleerrordata-args | |
| 4021 | 4061 | [`console.log()`]: console.md#consolelogdata-args | |
| 4022 | 4062 | [`domain`]: domain.md | |
| 4063 | + [`module.isBuiltin(id)`]: module.md#moduleisbuiltinmodulename | ||
| 4023 | 4064 | [`net.Server`]: net.md#class-netserver | |
| 4024 | 4065 | [`net.Socket`]: net.md#class-netsocket | |
| 4025 | 4066 | [`os.constants.dlopen`]: os.md#dlopen-constants | |
@@ -4036,9 +4077,11 @@ cases: | |||
| 4036 | 4077 | [`queueMicrotask()`]: globals.md#queuemicrotaskcallback | |
| 4037 | 4078 | [`readable.read()`]: stream.md#readablereadsize | |
| 4038 | 4079 | [`require()`]: globals.md#require | |
| 4080 | + [`require.cache`]: modules.md#requirecache | ||
| 4039 | 4081 | [`require.main`]: modules.md#accessing-the-main-module | |
| 4040 | 4082 | [`subprocess.kill()`]: child_process.md#subprocesskillsignal | |
| 4041 | 4083 | [`v8.setFlagsFromString()`]: v8.md#v8setflagsfromstringflags | |
| 4084 | + [built-in modules with mandatory `node:` prefix]: modules.md#built-in-modules-with-mandatory-node-prefix | ||
| 4042 | 4085 | [debugger]: debugger.md | |
| 4043 | 4086 | [deprecation code]: deprecations.md | |
| 4044 | 4087 | [note on process I/O]: #a-note-on-process-io | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -352,6 +352,11 @@ internalBinding('process_methods').setEmitWarningSync(emitWarningSync); | |||
| 352 | 352 | setMaybeCacheGeneratedSourceMap(maybeCacheGeneratedSourceMap); | |
| 353 | 353 | } | |
| 354 | 354 | ||
| 355 | + { | ||
| 356 | + const { getBuiltinModule } = require('internal/modules/helpers'); | ||
| 357 | + process.getBuiltinModule = getBuiltinModule; | ||
| 358 | + } | ||
| 359 | + | ||
| 355 | 360 | function setupProcessObject() { | |
| 356 | 361 | const EventEmitter = require('events'); | |
| 357 | 362 | const origProcProto = ObjectGetPrototypeOf(process); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -285,8 +285,22 @@ let _hasStartedUserCJSExecution = false; | |||
| 285 | 285 | // there is little value checking whether any user JS code is run anyway. | |
| 286 | 286 | let _hasStartedUserESMExecution = false; | |
| 287 | 287 | ||
| 288 | + /** | ||
| 289 | + * Load a public built-in module. ID may or may not be prefixed by `node:` and | ||
| 290 | + * will be normalized. | ||
| 291 | + * @param {string} id ID of the built-in to be loaded. | ||
| 292 | + * @returns {object|undefined} exports of the built-in. Undefined if the built-in | ||
| 293 | + * does not exist. | ||
| 294 | + */ | ||
| 295 | + function getBuiltinModule(id) { | ||
| 296 | + validateString(id, 'id'); | ||
| 297 | + const normalizedId = BuiltinModule.normalizeRequirableId(id); | ||
| 298 | + return normalizedId ? require(normalizedId) : undefined; | ||
| 299 | + } | ||
| 300 | + | ||
| 288 | 301 | module.exports = { | |
| 289 | 302 | addBuiltinLibsToObject, | |
| 303 | + getBuiltinModule, | ||
| 290 | 304 | getCjsConditions, | |
| 291 | 305 | initializeCjsConditions, | |
| 292 | 306 | loadBuiltinModule, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -18,6 +18,7 @@ const { | |||
| 18 | 18 | getCallSite, | |
| 19 | 19 | getTTYfd, | |
| 20 | 20 | hasCrypto, | |
| 21 | + hasIntl, | ||
| 21 | 22 | hasIPv6, | |
| 22 | 23 | hasMultiLocalhost, | |
| 23 | 24 | isAIX, | |
@@ -73,6 +74,7 @@ export { | |||
| 73 | 74 | getPort, | |
| 74 | 75 | getTTYfd, | |
| 75 | 76 | hasCrypto, | |
| 77 | + hasIntl, | ||
| 76 | 78 | hasIPv6, | |
| 77 | 79 | hasMultiLocalhost, | |
| 78 | 80 | isAIX, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,55 @@ | |||
| 1 | + import { isMainThread, hasCrypto, hasIntl } from '../common/index.mjs'; | ||
| 2 | + import assert from 'node:assert'; | ||
| 3 | + import { builtinModules } from 'node:module'; | ||
| 4 | + | ||
| 5 | + for (const invalid of [1, undefined, null, false, [], {}, () => {}, Symbol('test')]) { | ||
| 6 | + assert.throws(() => process.getBuiltinModule(invalid), { code: 'ERR_INVALID_ARG_TYPE' }); | ||
| 7 | + } | ||
| 8 | + | ||
| 9 | + for (const invalid of [ | ||
| 10 | + 'invalid', 'test', 'sea', 'test/reporter', 'internal/bootstrap/realm', | ||
| 11 | + 'internal/deps/undici/undici', 'internal/util', | ||
| 12 | + ]) { | ||
| 13 | + assert.strictEqual(process.getBuiltinModule(invalid), undefined); | ||
| 14 | + } | ||
| 15 | + | ||
| 16 | + // Check that createRequire()(id) returns the same thing as process.getBuiltinModule(id). | ||
| 17 | + const require = process.getBuiltinModule('module').createRequire(import.meta.url); | ||
| 18 | + const publicBuiltins = new Set(builtinModules); | ||
| 19 | + | ||
| 20 | + // Remove built-ins not available in the current setup. | ||
| 21 | + if (!isMainThread) { | ||
| 22 | + publicBuiltins.delete('trace_events'); | ||
| 23 | + } | ||
| 24 | + if (!hasCrypto) { | ||
| 25 | + publicBuiltins.delete('crypto'); | ||
| 26 | + publicBuiltins.delete('tls'); | ||
| 27 | + publicBuiltins.delete('_tls_common'); | ||
| 28 | + publicBuiltins.delete('_tls_wrap'); | ||
| 29 | + publicBuiltins.delete('http2'); | ||
| 30 | + publicBuiltins.delete('https'); | ||
| 31 | + publicBuiltins.delete('inspector'); | ||
| 32 | + publicBuiltins.delete('inspector/promises'); | ||
| 33 | + } | ||
| 34 | + if (!hasIntl) { | ||
| 35 | + publicBuiltins.delete('inspector'); | ||
| 36 | + publicBuiltins.delete('trace_events'); | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + for (const id of publicBuiltins) { | ||
| 40 | + assert.strictEqual(process.getBuiltinModule(id), require(id)); | ||
| 41 | + } | ||
| 42 | + // Check that import(id).default returns the same thing as process.getBuiltinModule(id). | ||
| 43 | + for (const id of publicBuiltins) { | ||
| 44 | + const imported = await import(`node:${id}`); | ||
| 45 | + assert.strictEqual(process.getBuiltinModule(id), imported.default); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + // publicBuiltins does not include 'test' which requires the node: prefix. | ||
| 49 | + const ids = publicBuiltins.add('test'); | ||
| 50 | + // Check that import(id).default returns the same thing as process.getBuiltinModule(id). | ||
| 51 | + for (const id of ids) { | ||
| 52 | + const prefixed = `node:${id}`; | ||
| 53 | + const imported = await import(prefixed); | ||
| 54 | + assert.strictEqual(process.getBuiltinModule(prefixed), imported.default); | ||
| 55 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments