Skip to content

Commit 5a15e7a

Browse files
committed
esm: add --experimental-import flag
1 parent 7ef069e commit 5a15e7a

File tree

5 files changed

+48
-13
lines changed

5 files changed

+48
-13
lines changed

doc/api/cli.md

+13
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,17 @@ added:
298298

299299
Expose the [Web Crypto API][] on the global scope.
300300

301+
### `--experimental-import=module`
302+
303+
<!-- YAML
304+
added: REPLACEME
305+
-->
306+
307+
Preload the specified module at startup.
308+
309+
Follows [ECMAScript modules][] resolution rules.
310+
Use \[`--require`]\[] to load a \[CJS module]\[].
311+
301312
### `--experimental-import-meta-resolve`
302313

303314
<!-- YAML
@@ -1663,6 +1674,7 @@ Node.js options that are allowed are:
16631674
* `--experimental-global-customevent`
16641675
* `--experimental-global-webcrypto`
16651676
* `--experimental-import-meta-resolve`
1677+
* `--experimental-import`
16661678
* `--experimental-json-modules`
16671679
* `--experimental-loader`
16681680
* `--experimental-modules`
@@ -2088,6 +2100,7 @@ done
20882100
[CommonJS]: modules.md
20892101
[CustomEvent Web API]: https://dom.spec.whatwg.org/#customevent
20902102
[ECMAScript module loader]: esm.md#loaders
2103+
[ECMAScript modules]: esm.md#modules-ecmascript-modules
20912104
[Fetch API]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
20922105
[Modules loaders]: packages.md#modules-loaders
20932106
[OSSL_PROVIDER-legacy]: https://www.openssl.org/docs/man3.0/man7/OSSL_PROVIDER-legacy.html

lib/internal/modules/run_main.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,12 @@ function shouldUseESMLoader(mainPath) {
3333
* (or an empty list when none have been registered).
3434
*/
3535
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('--experimental-import');
41+
if (userLoaders.length > 0 || userImports.length > 0)
3742
return true;
3843
const esModuleSpecifierResolution =
3944
getOptionValue('--experimental-specifier-resolution');

lib/internal/process/esm_loader.js

+20-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
const {
4+
ArrayIsArray,
45
ObjectCreate,
56
} = primordials;
67

@@ -56,8 +57,24 @@ async function initializeLoader() {
5657

5758
const { getOptionValue } = require('internal/options');
5859
const customLoaders = getOptionValue('--experimental-loader');
60+
const preloadModules = getOptionValue('--experimental-import');
61+
const keyedExportsList = await loadInternalModules(customLoaders);
5962

60-
if (customLoaders.length === 0) return;
63+
// Hooks must then be added to external/public loader
64+
// (so they're triggered in userland)
65+
await esmLoader.addCustomLoaders(keyedExportsList);
66+
67+
// Preload after loaders are added so they can be used
68+
if (preloadModules?.length) {
69+
await loadInternalModules(preloadModules);
70+
}
71+
72+
isESMInitialized = true;
73+
}
74+
75+
async function loadInternalModules(requests) {
76+
if (!ArrayIsArray(requests) || requests.length === 0)
77+
return;
6178

6279
let cwd;
6380
try {
@@ -72,17 +89,11 @@ async function initializeLoader() {
7289
const internalEsmLoader = new ESMLoader();
7390

7491
// Importation must be handled by internal loader to avoid poluting userland
75-
const keyedExportsList = await internalEsmLoader.import(
76-
customLoaders,
92+
return internalEsmLoader.import(
93+
requests,
7794
pathToFileURL(cwd).href,
7895
ObjectCreate(null),
7996
);
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;
8697
}
8798

8899
exports.loadESM = async function loadESM(callback) {

src/node_options.cc

+6-2
Original file line numberDiff line numberDiff line change
@@ -608,10 +608,14 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
608608
AddAlias("-pe", { "--print", "--eval" });
609609
AddAlias("-p", "--print");
610610
AddOption("--require",
611-
"module to preload (option can be repeated)",
612-
&EnvironmentOptions::preload_modules,
611+
"CommonJS module to preload (option can be repeated)",
612+
&EnvironmentOptions::preload_cjs_modules,
613613
kAllowedInEnvironment);
614614
AddAlias("-r", "--require");
615+
AddOption("--experimental-import",
616+
"ES module to preload (option can be repeated)",
617+
&EnvironmentOptions::preload_esm_modules,
618+
kAllowedInEnvironment);
615619
AddOption("--interactive",
616620
"always enter the REPL even if stdin does not appear "
617621
"to be a terminal",

src/node_options.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,9 @@ class EnvironmentOptions : public Options {
188188
bool tls_max_v1_3 = false;
189189
std::string tls_keylog;
190190

191-
std::vector<std::string> preload_modules;
191+
std::vector<std::string> preload_cjs_modules;
192+
193+
std::vector<std::string> preload_esm_modules;
192194

193195
std::vector<std::string> user_argv;
194196

0 commit comments

Comments
 (0)