diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js index 2bafb2a3ad3595..50f5001aa4b0fd 100644 --- a/lib/internal/bootstrap/node.js +++ b/lib/internal/bootstrap/node.js @@ -210,17 +210,6 @@ function startup() { 'DeprecationWarning', 'DEP0062', startup, true); } - const experimentalModules = getOptionValue('--experimental-modules'); - const experimentalVMModules = getOptionValue('--experimental-vm-modules'); - if (experimentalModules || experimentalVMModules) { - if (experimentalModules) { - process.emitWarning( - 'The ESM module loader is experimental.', - 'ExperimentalWarning', undefined); - } - NativeModule.require('internal/process/esm_loader').setup(); - } - const { deprecate } = NativeModule.require('internal/util'); { // Install legacy getters on the `util` binding for typechecking. @@ -451,6 +440,30 @@ function prepareUserCodeExecution() { delete process.env.NODE_UNIQUE_ID; } + const experimentalModules = getOptionValue('--experimental-modules'); + const experimentalVMModules = getOptionValue('--experimental-vm-modules'); + if (experimentalModules || experimentalVMModules) { + if (experimentalModules) { + process.emitWarning( + 'The ESM module loader is experimental.', + 'ExperimentalWarning', undefined); + } + + const { + setImportModuleDynamicallyCallback, + setInitializeImportMetaObjectCallback + } = internalBinding('module_wrap'); + const esm = NativeModule.require('internal/process/esm_loader'); + // Setup per-isolate callbacks that locate data or callbacks that we keep + // track of for different ESM modules. + setInitializeImportMetaObjectCallback(esm.initializeImportMetaObject); + setImportModuleDynamicallyCallback(esm.importModuleDynamicallyCallback); + const userLoader = getOptionValue('--loader'); + // If --loader is specified, create a loader with user hooks. Otherwise + // create the default loader. + esm.initializeLoader(process.cwd(), userLoader); + } + // For user code, we preload modules if `-r` is passed const preloadModules = getOptionValue('--require'); if (preloadModules) { diff --git a/lib/internal/process/esm_loader.js b/lib/internal/process/esm_loader.js index f81053a1c3c3ad..0b7f1be6ff0595 100644 --- a/lib/internal/process/esm_loader.js +++ b/lib/internal/process/esm_loader.js @@ -1,8 +1,6 @@ 'use strict'; const { - setImportModuleDynamicallyCallback, - setInitializeImportMetaObjectCallback, callbackMap, } = internalBinding('module_wrap'); @@ -15,16 +13,16 @@ const { ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING, } = require('internal/errors').codes; -function initializeImportMetaObject(wrap, meta) { +exports.initializeImportMetaObject = function(wrap, meta) { if (callbackMap.has(wrap)) { const { initializeImportMeta } = callbackMap.get(wrap); if (initializeImportMeta !== undefined) { initializeImportMeta(meta, wrapToModuleMap.get(wrap) || wrap); } } -} +}; -async function importModuleDynamicallyCallback(wrap, specifier) { +exports.importModuleDynamicallyCallback = async function(wrap, specifier) { if (callbackMap.has(wrap)) { const { importModuleDynamically } = callbackMap.get(wrap); if (importModuleDynamically !== undefined) { @@ -33,10 +31,7 @@ async function importModuleDynamicallyCallback(wrap, specifier) { } } throw new ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING(); -} - -setInitializeImportMetaObjectCallback(initializeImportMetaObject); -setImportModuleDynamicallyCallback(importModuleDynamicallyCallback); +}; let loaderResolve; exports.loaderPromise = new Promise((resolve, reject) => { @@ -45,13 +40,12 @@ exports.loaderPromise = new Promise((resolve, reject) => { exports.ESMLoader = undefined; -exports.setup = function() { +exports.initializeLoader = function(cwd, userLoader) { let ESMLoader = new Loader(); const loaderPromise = (async () => { - const userLoader = require('internal/options').getOptionValue('--loader'); if (userLoader) { const hooks = await ESMLoader.import( - userLoader, pathToFileURL(`${process.cwd()}/`).href); + userLoader, pathToFileURL(`${cwd}/`).href); ESMLoader = new Loader(); ESMLoader.hook(hooks); exports.ESMLoader = ESMLoader;