Skip to content

Commit

Permalink
esm: add --experimental-import flag
Browse files Browse the repository at this point in the history
  • Loading branch information
MoLow committed Jul 23, 2022
1 parent 7ef069e commit 5a15e7a
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 13 deletions.
13 changes: 13 additions & 0 deletions doc/api/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,17 @@ added:

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

### `--experimental-import=module`

<!-- YAML
added: REPLACEME
-->

Preload the specified module at startup.

Follows [ECMAScript modules][] resolution rules.
Use \[`--require`]\[] to load a \[CJS module]\[].

### `--experimental-import-meta-resolve`

<!-- YAML
Expand Down Expand Up @@ -1663,6 +1674,7 @@ Node.js options that are allowed are:
* `--experimental-global-customevent`
* `--experimental-global-webcrypto`
* `--experimental-import-meta-resolve`
* `--experimental-import`
* `--experimental-json-modules`
* `--experimental-loader`
* `--experimental-modules`
Expand Down Expand Up @@ -2088,6 +2100,7 @@ done
[CommonJS]: modules.md
[CustomEvent Web API]: https://dom.spec.whatwg.org/#customevent
[ECMAScript module loader]: esm.md#loaders
[ECMAScript modules]: esm.md#modules-ecmascript-modules
[Fetch API]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
[Modules loaders]: packages.md#modules-loaders
[OSSL_PROVIDER-legacy]: https://www.openssl.org/docs/man3.0/man7/OSSL_PROVIDER-legacy.html
Expand Down
7 changes: 6 additions & 1 deletion lib/internal/modules/run_main.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ function shouldUseESMLoader(mainPath) {
* (or an empty list when none have been registered).
*/
const userLoaders = getOptionValue('--experimental-loader');
if (userLoaders.length > 0)
/**
* @type {string[]} userImports A list of preloaded modules registered by the user
* (or an empty list when none have been registered).
*/
const userImports = getOptionValue('--experimental-import');
if (userLoaders.length > 0 || userImports.length > 0)
return true;
const esModuleSpecifierResolution =
getOptionValue('--experimental-specifier-resolution');
Expand Down
29 changes: 20 additions & 9 deletions lib/internal/process/esm_loader.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const {
ArrayIsArray,
ObjectCreate,
} = primordials;

Expand Down Expand Up @@ -56,8 +57,24 @@ async function initializeLoader() {

const { getOptionValue } = require('internal/options');
const customLoaders = getOptionValue('--experimental-loader');
const preloadModules = getOptionValue('--experimental-import');
const keyedExportsList = await loadInternalModules(customLoaders);

if (customLoaders.length === 0) return;
// Hooks must then be added to external/public loader
// (so they're triggered in userland)
await esmLoader.addCustomLoaders(keyedExportsList);

// Preload after loaders are added so they can be used
if (preloadModules?.length) {
await loadInternalModules(preloadModules);
}

isESMInitialized = true;
}

async function loadInternalModules(requests) {
if (!ArrayIsArray(requests) || requests.length === 0)
return;

let cwd;
try {
Expand All @@ -72,17 +89,11 @@ async function initializeLoader() {
const internalEsmLoader = new ESMLoader();

// Importation must be handled by internal loader to avoid poluting userland
const keyedExportsList = await internalEsmLoader.import(
customLoaders,
return internalEsmLoader.import(
requests,
pathToFileURL(cwd).href,
ObjectCreate(null),
);

// Hooks must then be added to external/public loader
// (so they're triggered in userland)
await esmLoader.addCustomLoaders(keyedExportsList);

isESMInitialized = true;
}

exports.loadESM = async function loadESM(callback) {
Expand Down
8 changes: 6 additions & 2 deletions src/node_options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -608,10 +608,14 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
AddAlias("-pe", { "--print", "--eval" });
AddAlias("-p", "--print");
AddOption("--require",
"module to preload (option can be repeated)",
&EnvironmentOptions::preload_modules,
"CommonJS module to preload (option can be repeated)",
&EnvironmentOptions::preload_cjs_modules,
kAllowedInEnvironment);
AddAlias("-r", "--require");
AddOption("--experimental-import",
"ES module to preload (option can be repeated)",
&EnvironmentOptions::preload_esm_modules,
kAllowedInEnvironment);
AddOption("--interactive",
"always enter the REPL even if stdin does not appear "
"to be a terminal",
Expand Down
4 changes: 3 additions & 1 deletion src/node_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,9 @@ class EnvironmentOptions : public Options {
bool tls_max_v1_3 = false;
std::string tls_keylog;

std::vector<std::string> preload_modules;
std::vector<std::string> preload_cjs_modules;

std::vector<std::string> preload_esm_modules;

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

Expand Down

0 comments on commit 5a15e7a

Please sign in to comment.