Skip to content

Commit 198f88f

Browse files
committed
esm: add --experimental-import flag
1 parent 0484022 commit 198f88f

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
@@ -290,6 +290,17 @@ added:
290290

291291
Expose the [Web Crypto API][] on the global scope.
292292

293+
### `--experimental-import module`
294+
295+
<!-- YAML
296+
added: REPLACEME
297+
-->
298+
299+
Preload the specified module at startup.
300+
301+
Follows [ECMAScript modules][] resolution
302+
rules.
303+
293304
### `--experimental-import-meta-resolve`
294305

295306
<!-- YAML
@@ -1653,6 +1664,7 @@ Node.js options that are allowed are:
16531664
* `--enable-source-maps`
16541665
* `--experimental-abortcontroller`
16551666
* `--experimental-global-webcrypto`
1667+
* `--experimental-import`
16561668
* `--experimental-import-meta-resolve`
16571669
* `--experimental-json-modules`
16581670
* `--experimental-loader`
@@ -2078,6 +2090,7 @@ done
20782090
[Chrome DevTools Protocol]: https://chromedevtools.github.io/devtools-protocol/
20792091
[CommonJS]: modules.md
20802092
[ECMAScript module loader]: esm.md#loaders
2093+
[ECMAScript modules]: esm.md#modules-ecmascript-modules
20812094
[Fetch API]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
20822095
[Modules loaders]: packages.md#modules-loaders
20832096
[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 && preloadModules.length > 0) {
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
@@ -604,10 +604,14 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
604604
AddAlias("-pe", { "--print", "--eval" });
605605
AddAlias("-p", "--print");
606606
AddOption("--require",
607-
"module to preload (option can be repeated)",
608-
&EnvironmentOptions::preload_modules,
607+
"cjs module to preload (option can be repeated)",
608+
&EnvironmentOptions::preload_cjs_modules,
609609
kAllowedInEnvironment);
610610
AddAlias("-r", "--require");
611+
AddOption("--experimental-import",
612+
"esm module to preload (option can be repeated)",
613+
&EnvironmentOptions::preload_esm_modules,
614+
kAllowedInEnvironment);
611615
AddOption("--interactive",
612616
"always enter the REPL even if stdin does not appear "
613617
"to be a terminal",

src/node_options.h

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

190-
std::vector<std::string> preload_modules;
190+
std::vector<std::string> preload_cjs_modules;
191+
192+
std::vector<std::string> preload_esm_modules;
191193

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

0 commit comments

Comments
 (0)