| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent c224e1b commit c39b7c2
16 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -530,7 +530,8 @@ Only the root context is supported. There is no guarantee that | |||
| 530 | 530 | `globalThis.Array` is indeed the default intrinsic reference. Code may break | |
| 531 | 531 | under this flag. | |
| 532 | 532 | ||
| 533 | - To allow polyfills to be added, `--require` runs before freezing intrinsics. | ||
| 533 | + To allow polyfills to be added, | ||
| 534 | + [`--require`][] and [`--import`][] both run before freezing intrinsics. | ||
| 534 | 535 | ||
| 535 | 536 | ### `--force-node-api-uncaught-exceptions-policy` | |
| 536 | 537 | ||
@@ -679,6 +680,18 @@ added: v0.11.15 | |||
| 679 | 680 | ||
| 680 | 681 | Specify ICU data load path. (Overrides `NODE_ICU_DATA`.) | |
| 681 | 682 | ||
| 683 | + ### `--import=module` | ||
| 684 | + | ||
| 685 | + <!-- YAML | ||
| 686 | + added: REPLACEME | ||
| 687 | + --> | ||
| 688 | + | ||
| 689 | + Preload the specified module at startup. | ||
| 690 | + | ||
| 691 | + Follows [ECMAScript module][] resolution rules. | ||
| 692 | + Use [`--require`][] to load a [CommonJS module][]. | ||
| 693 | + Modules preloaded with `--require` will run before modules preloaded with `--import`. | ||
| 694 | + | ||
| 682 | 695 | ### `--input-type=type` | |
| 683 | 696 | ||
| 684 | 697 | <!-- YAML | |
@@ -1739,8 +1752,9 @@ Preload the specified module at startup. | |||
| 1739 | 1752 | Follows `require()`'s module resolution | |
| 1740 | 1753 | rules. `module` may be either a path to a file, or a node module name. | |
| 1741 | 1754 | ||
| 1742 | - Only CommonJS modules are supported. Attempting to preload a | ||
| 1743 | - ES6 Module using `--require` will fail with an error. | ||
| 1755 | + Only CommonJS modules are supported. | ||
| 1756 | + Use [`--import`][] to preload an [ECMAScript module][]. | ||
| 1757 | + Modules preloaded with `--require` will run before modules preloaded with `--import`. | ||
| 1744 | 1758 | ||
| 1745 | 1759 | ### `-v`, `--version` | |
| 1746 | 1760 | ||
@@ -1895,6 +1909,7 @@ Node.js options that are allowed are: | |||
| 1895 | 1909 | * `--heapsnapshot-signal` | |
| 1896 | 1910 | * `--http-parser` | |
| 1897 | 1911 | * `--icu-data-dir` | |
| 1912 | + * `--import` | ||
| 1898 | 1913 | * `--input-type` | |
| 1899 | 1914 | * `--insecure-http-parser` | |
| 1900 | 1915 | * `--inspect-brk` | |
@@ -2315,7 +2330,9 @@ done | |||
| 2315 | 2330 | [#42511]: https://github.com/nodejs/node/issues/42511 | |
| 2316 | 2331 | [Chrome DevTools Protocol]: https://chromedevtools.github.io/devtools-protocol/ | |
| 2317 | 2332 | [CommonJS]: modules.md | |
| 2333 | + [CommonJS module]: modules.md | ||
| 2318 | 2334 | [CustomEvent Web API]: https://dom.spec.whatwg.org/#customevent | |
| 2335 | + [ECMAScript module]: esm.md#modules-ecmascript-modules | ||
| 2319 | 2336 | [ECMAScript module loader]: esm.md#loaders | |
| 2320 | 2337 | [Fetch API]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API | |
| 2321 | 2338 | [Modules loaders]: packages.md#modules-loaders | |
@@ -2333,9 +2350,11 @@ done | |||
| 2333 | 2350 | [`--diagnostic-dir`]: #--diagnostic-dirdirectory | |
| 2334 | 2351 | [`--experimental-wasm-modules`]: #--experimental-wasm-modules | |
| 2335 | 2352 | [`--heap-prof-dir`]: #--heap-prof-dir | |
| 2353 | + [`--import`]: #--importmodule | ||
| 2336 | 2354 | [`--openssl-config`]: #--openssl-configfile | |
| 2337 | 2355 | [`--preserve-symlinks`]: #--preserve-symlinks | |
| 2338 | 2356 | [`--redirect-warnings`]: #--redirect-warningsfile | |
| 2357 | + [`--require`]: #-r---require-module | ||
| 2339 | 2358 | [`Atomics.wait()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/wait | |
| 2340 | 2359 | [`Buffer`]: buffer.md#class-buffer | |
| 2341 | 2360 | [`CRYPTO_secure_malloc_init`]: https://www.openssl.org/docs/man3.0/man3/CRYPTO_secure_malloc_init.html | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4,6 +4,7 @@ | |||
| 4 | 4 | // instead of actually running the file. | |
| 5 | 5 | ||
| 6 | 6 | const { URL } = require('internal/url'); | |
| 7 | + const { getOptionValue } = require('internal/options'); | ||
| 7 | 8 | const { | |
| 8 | 9 | prepareMainThreadExecution, | |
| 9 | 10 | markBootstrapComplete, | |
@@ -38,18 +39,29 @@ if (process.argv[1] && process.argv[1] !== '-') { | |||
| 38 | 39 | ||
| 39 | 40 | markBootstrapComplete(); | |
| 40 | 41 | ||
| 41 | - checkSyntax(source, filename); | ||
| 42 | + loadESMIfNeeded(() => checkSyntax(source, filename)); | ||
| 42 | 43 | } else { | |
| 43 | 44 | markBootstrapComplete(); | |
| 44 | 45 | ||
| 45 | - readStdin((code) => { | ||
| 46 | + loadESMIfNeeded(() => readStdin((code) => { | ||
| 46 | 47 | checkSyntax(code, '[stdin]'); | |
| 47 | - }); | ||
| 48 | + })); | ||
| 48 | 49 | } | |
| 49 | 50 | ||
| 50 | - async function checkSyntax(source, filename) { | ||
| 51 | + function loadESMIfNeeded(cb) { | ||
| 51 | 52 | const { getOptionValue } = require('internal/options'); | |
| 52 | - let isModule = false; | ||
| 53 | + const hasModulePreImport = getOptionValue('--import').length > 0; | ||
| 54 | + | ||
| 55 | + if (hasModulePreImport) { | ||
| 56 | + const { loadESM } = require('internal/process/esm_loader'); | ||
| 57 | + loadESM(cb); | ||
| 58 | + return; | ||
| 59 | + } | ||
| 60 | + cb(); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + async function checkSyntax(source, filename) { | ||
| 64 | + let isModule = true; | ||
| 53 | 65 | if (filename === '[stdin]' || filename === '[eval]') { | |
| 54 | 66 | isModule = getOptionValue('--input-type') === 'module'; | |
| 55 | 67 | } else { | |
@@ -59,11 +71,14 @@ async function checkSyntax(source, filename) { | |||
| 59 | 71 | const format = await defaultGetFormat(new URL(url)); | |
| 60 | 72 | isModule = format === 'module'; | |
| 61 | 73 | } | |
| 74 | + | ||
| 62 | 75 | if (isModule) { | |
| 63 | 76 | const { ModuleWrap } = internalBinding('module_wrap'); | |
| 64 | 77 | new ModuleWrap(filename, undefined, source, 0, 0); | |
| 65 | 78 | return; | |
| 66 | 79 | } | |
| 67 | 80 | ||
| 68 | - wrapSafe(filename, source); | ||
| 81 | + const { loadESM } = require('internal/process/esm_loader'); | ||
| 82 | + const { handleMainPromise } = require('internal/modules/run_main'); | ||
| 83 | + handleMainPromise(loadESM((loader) => wrapSafe(filename, source))); | ||
| 69 | 84 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -24,11 +24,13 @@ readStdin((code) => { | |||
| 24 | 24 | process._eval = code; | |
| 25 | 25 | ||
| 26 | 26 | const print = getOptionValue('--print'); | |
| 27 | + const loadESM = getOptionValue('--import').length > 0; | ||
| 27 | 28 | if (getOptionValue('--input-type') === 'module') | |
| 28 | 29 | evalModule(code, print); | |
| 29 | 30 | else | |
| 30 | 31 | evalScript('[stdin]', | |
| 31 | 32 | code, | |
| 32 | 33 | getOptionValue('--inspect-brk'), | |
| 33 | - print); | ||
| 34 | + print, | ||
| 35 | + loadESM); | ||
| 34 | 36 | }); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -22,10 +22,12 @@ markBootstrapComplete(); | |||
| 22 | 22 | ||
| 23 | 23 | const source = getOptionValue('--eval'); | |
| 24 | 24 | const print = getOptionValue('--print'); | |
| 25 | + const loadESM = getOptionValue('--import').length > 0; | ||
| 25 | 26 | if (getOptionValue('--input-type') === 'module') | |
| 26 | 27 | evalModule(source, print); | |
| 27 | 28 | else | |
| 28 | 29 | evalScript('[eval]', | |
| 29 | 30 | source, | |
| 30 | 31 | getOptionValue('--inspect-brk'), | |
| 31 | - print); | ||
| 32 | + print, | ||
| 33 | + loadESM); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -33,7 +33,12 @@ function shouldUseESMLoader(mainPath) { | |||
| 33 | 33 | * (or an empty list when none have been registered). | |
| 34 | 34 | */ | |
| 35 | 35 | const userLoaders = getOptionValue('--experimental-loader'); | |
| 36 | - if (userLoaders.length > 0) | ||
| 36 | + /** | ||
| 37 | + * @type {string[]} userImports A list of preloaded modules registered by the user | ||
| 38 | + * (or an empty list when none have been registered). | ||
| 39 | + */ | ||
| 40 | + const userImports = getOptionValue('--import'); | ||
| 41 | + if (userLoaders.length > 0 || userImports.length > 0) | ||
| 37 | 42 | return true; | |
| 38 | 43 | const esModuleSpecifierResolution = | |
| 39 | 44 | getOptionValue('--experimental-specifier-resolution'); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,6 +1,7 @@ | |||
| 1 | 1 | 'use strict'; | |
| 2 | 2 | ||
| 3 | 3 | const { | |
| 4 | + ArrayIsArray, | ||
| 4 | 5 | ObjectCreate, | |
| 5 | 6 | } = primordials; | |
| 6 | 7 | ||
@@ -56,8 +57,23 @@ async function initializeLoader() { | |||
| 56 | 57 | ||
| 57 | 58 | const { getOptionValue } = require('internal/options'); | |
| 58 | 59 | const customLoaders = getOptionValue('--experimental-loader'); | |
| 60 | + const preloadModules = getOptionValue('--import'); | ||
| 61 | + const loaders = await loadModulesInIsolation(customLoaders); | ||
| 59 | 62 | ||
| 60 | - if (customLoaders.length === 0) return; | ||
| 63 | + // Hooks must then be added to external/public loader | ||
| 64 | + // (so they're triggered in userland) | ||
| 65 | + esmLoader.addCustomLoaders(loaders); | ||
| 66 | + | ||
| 67 | + // Preload after loaders are added so they can be used | ||
| 68 | + if (preloadModules?.length) { | ||
| 69 | + await loadModulesInIsolation(preloadModules, loaders); | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + isESMInitialized = true; | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + function loadModulesInIsolation(specifiers, loaders = []) { | ||
| 76 | + if (!ArrayIsArray(specifiers) || specifiers.length === 0) { return; } | ||
| 61 | 77 | ||
| 62 | 78 | let cwd; | |
| 63 | 79 | try { | |
@@ -70,19 +86,14 @@ async function initializeLoader() { | |||
| 70 | 86 | // between internal Node.js and userland. For example, a module with internal | |
| 71 | 87 | // state (such as a counter) should be independent. | |
| 72 | 88 | const internalEsmLoader = new ESMLoader(); | |
| 89 | + internalEsmLoader.addCustomLoaders(loaders); | ||
| 73 | 90 | ||
| 74 | 91 | // Importation must be handled by internal loader to avoid poluting userland | |
| 75 | - const keyedExportsList = await internalEsmLoader.import( | ||
| 76 | - customLoaders, | ||
| 92 | + return internalEsmLoader.import( | ||
| 93 | + specifiers, | ||
| 77 | 94 | pathToFileURL(cwd).href, | |
| 78 | 95 | ObjectCreate(null), | |
| 79 | 96 | ); | |
| 80 | - | ||
| 81 | - // Hooks must then be added to external/public loader | ||
| 82 | - // (so they're triggered in userland) | ||
| 83 | - await esmLoader.addCustomLoaders(keyedExportsList); | ||
| 84 | - | ||
| 85 | - isESMInitialized = true; | ||
| 86 | 97 | } | |
| 87 | 98 | ||
| 88 | 99 | exports.loadESM = async function loadESM(callback) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -50,7 +50,7 @@ function evalModule(source, print) { | |||
| 50 | 50 | return handleMainPromise(loadESM((loader) => loader.eval(source))); | |
| 51 | 51 | } | |
| 52 | 52 | ||
| 53 | - function evalScript(name, body, breakFirstLine, print) { | ||
| 53 | + function evalScript(name, body, breakFirstLine, print, shouldLoadESM = false) { | ||
| 54 | 54 | const CJSModule = require('internal/modules/cjs/loader').Module; | |
| 55 | 55 | const { kVmBreakFirstLineSymbol } = require('internal/util'); | |
| 56 | 56 | const { pathToFileURL } = require('url'); | |
@@ -62,36 +62,45 @@ function evalScript(name, body, breakFirstLine, print) { | |||
| 62 | 62 | module.filename = path.join(cwd, name); | |
| 63 | 63 | module.paths = CJSModule._nodeModulePaths(cwd); | |
| 64 | 64 | ||
| 65 | + const { handleMainPromise } = require('internal/modules/run_main'); | ||
| 65 | 66 | const asyncESM = require('internal/process/esm_loader'); | |
| 66 | 67 | const baseUrl = pathToFileURL(module.filename).href; | |
| 68 | + const { loadESM } = asyncESM; | ||
| 69 | + | ||
| 70 | + const runScript = () => { | ||
| 71 | + // Create wrapper for cache entry | ||
| 72 | + const script = ` | ||
| 73 | + globalThis.module = module; | ||
| 74 | + globalThis.exports = exports; | ||
| 75 | + globalThis.__dirname = __dirname; | ||
| 76 | + globalThis.require = require; | ||
| 77 | + return (main) => main(); | ||
| 78 | + `; | ||
| 79 | + globalThis.__filename = name; | ||
| 80 | + RegExpPrototypeExec(/^/, ''); // Necessary to reset RegExp statics before user code runs. | ||
| 81 | + const result = module._compile(script, `${name}-wrapper`)(() => | ||
| 82 | + require('vm').runInThisContext(body, { | ||
| 83 | + filename: name, | ||
| 84 | + displayErrors: true, | ||
| 85 | + [kVmBreakFirstLineSymbol]: !!breakFirstLine, | ||
| 86 | + importModuleDynamically(specifier, _, importAssertions) { | ||
| 87 | + const loader = asyncESM.esmLoader; | ||
| 88 | + return loader.import(specifier, baseUrl, importAssertions); | ||
| 89 | + }, | ||
| 90 | + })); | ||
| 91 | + if (print) { | ||
| 92 | + const { log } = require('internal/console/global'); | ||
| 93 | + log(result); | ||
| 94 | + } | ||
| 67 | 95 | ||
| 68 | - // Create wrapper for cache entry | ||
| 69 | - const script = ` | ||
| 70 | - globalThis.module = module; | ||
| 71 | - globalThis.exports = exports; | ||
| 72 | - globalThis.__dirname = __dirname; | ||
| 73 | - globalThis.require = require; | ||
| 74 | - return (main) => main(); | ||
| 75 | - `; | ||
| 76 | - globalThis.__filename = name; | ||
| 77 | - RegExpPrototypeExec(/^/, ''); // Necessary to reset RegExp statics before user code runs. | ||
| 78 | - const result = module._compile(script, `${name}-wrapper`)(() => | ||
| 79 | - require('vm').runInThisContext(body, { | ||
| 80 | - filename: name, | ||
| 81 | - displayErrors: true, | ||
| 82 | - [kVmBreakFirstLineSymbol]: !!breakFirstLine, | ||
| 83 | - importModuleDynamically(specifier, _, importAssertions) { | ||
| 84 | - const loader = asyncESM.esmLoader; | ||
| 85 | - return loader.import(specifier, baseUrl, importAssertions); | ||
| 86 | - }, | ||
| 87 | - })); | ||
| 88 | - if (print) { | ||
| 89 | - const { log } = require('internal/console/global'); | ||
| 90 | - log(result); | ||
| 91 | - } | ||
| 96 | + if (origModule !== undefined) | ||
| 97 | + globalThis.module = origModule; | ||
| 98 | + }; | ||
| 92 | 99 | ||
| 93 | - if (origModule !== undefined) | ||
| 94 | - globalThis.module = origModule; | ||
| 100 | + if (shouldLoadESM) { | ||
| 101 | + return handleMainPromise(loadESM(runScript)); | ||
| 102 | + } | ||
| 103 | + return runScript(); | ||
| 95 | 104 | } | |
| 96 | 105 | ||
| 97 | 106 | const exceptionHandlerState = { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -666,10 +666,14 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { | |||
| 666 | 666 | AddAlias("-pe", { "--print", "--eval" }); | |
| 667 | 667 | AddAlias("-p", "--print"); | |
| 668 | 668 | AddOption("--require", | |
| 669 | - "module to preload (option can be repeated)", | ||
| 670 | - &EnvironmentOptions::preload_modules, | ||
| 669 | + "CommonJS module to preload (option can be repeated)", | ||
| 670 | + &EnvironmentOptions::preload_cjs_modules, | ||
| 671 | 671 | kAllowedInEnvvar); | |
| 672 | 672 | AddAlias("-r", "--require"); | |
| 673 | + AddOption("--import", | ||
| 674 | + "ES module to preload (option can be repeated)", | ||
| 675 | + &EnvironmentOptions::preload_esm_modules, | ||
| 676 | + kAllowedInEnvironment); | ||
| 673 | 677 | AddOption("--interactive", | |
| 674 | 678 | "always enter the REPL even if stdin does not appear " | |
| 675 | 679 | "to be a terminal", | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -200,7 +200,9 @@ class EnvironmentOptions : public Options { | |||
| 200 | 200 | bool tls_max_v1_3 = false; | |
| 201 | 201 | std::string tls_keylog; | |
| 202 | 202 | ||
| 203 | - std::vector<std::string> preload_modules; | ||
| 203 | + std::vector<std::string> preload_cjs_modules; | ||
| 204 | + | ||
| 205 | + std::vector<std::string> preload_esm_modules; | ||
| 204 | 206 | ||
| 205 | 207 | std::vector<std::string> user_argv; | |
| 206 | 208 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments