diff --git a/lib/internal/modules/esm/utils.js b/lib/internal/modules/esm/utils.js index f977bfaf57498f..4480337b52a0f5 100644 --- a/lib/internal/modules/esm/utils.js +++ b/lib/internal/modules/esm/utils.js @@ -53,7 +53,9 @@ let defaultConditions; * @returns {object} */ function getDefaultConditions() { - assert(defaultConditions !== undefined); + if (defaultConditions === undefined) { + initializeDefaultConditions(); + } return defaultConditions; } @@ -64,7 +66,9 @@ let defaultConditionsSet; * @returns {Set} */ function getDefaultConditionsSet() { - assert(defaultConditionsSet !== undefined); + if (defaultConditionsSet === undefined) { + initializeDefaultConditions(); + } return defaultConditionsSet; } @@ -74,18 +78,27 @@ function getDefaultConditionsSet() { * @returns {void} */ function initializeDefaultConditions() { + if (defaultConditions !== undefined) { + return; + } const userConditions = getOptionValue('--conditions'); const noAddons = getOptionValue('--no-addons'); - const addonConditions = noAddons ? [] : ['node-addons']; - const moduleConditions = getOptionValue('--require-module') ? ['module-sync'] : []; - defaultConditions = ObjectFreeze([ - 'node', - 'import', - ...moduleConditions, - ...addonConditions, - ...userConditions, - ]); - defaultConditionsSet = new SafeSet(defaultConditions); + const conditions = ['node', 'import']; + if (getOptionValue('--require-module')) { + conditions[conditions.length] = 'module-sync'; + } + if (!noAddons) { + conditions[conditions.length] = 'node-addons'; + } + for (let i = 0; i < userConditions.length; i++) { + conditions[conditions.length] = userConditions[i]; + } + defaultConditions = ObjectFreeze(conditions); + const set = new SafeSet(); + for (let i = 0; i < defaultConditions.length; i++) { + set.add(defaultConditions[i]); + } + defaultConditionsSet = set; } /** @@ -295,12 +308,17 @@ async function importModuleDynamicallyCallback(referrerSymbol, specifier, phase, } let _shouldSpawnLoaderHookWorker = true; +let esmInitialized = false; /** * Initializes handling of ES modules. * @param {boolean} [shouldSpawnLoaderHookWorker] Whether the custom loader worker * should be spawned later. */ function initializeESM(shouldSpawnLoaderHookWorker = true) { + if (esmInitialized) { + return; + } + esmInitialized = true; _shouldSpawnLoaderHookWorker = shouldSpawnLoaderHookWorker; initializeDefaultConditions(); // Setup per-realm callbacks that locate data or callbacks that we keep @@ -391,6 +409,8 @@ module.exports = { embedder_module_hdo, registerModule, initializeESM, + initializeImportMetaObject, + importModuleDynamicallyCallback, getDefaultConditions, getConditionsSet, shouldSpawnLoaderHookWorker, diff --git a/lib/internal/process/pre_execution.js b/lib/internal/process/pre_execution.js index 0902536708bf1d..f12b29a06ff259 100644 --- a/lib/internal/process/pre_execution.js +++ b/lib/internal/process/pre_execution.js @@ -12,6 +12,7 @@ const { NumberParseInt, ObjectDefineProperty, ObjectFreeze, + ReflectApply, String, globalThis, } = primordials; @@ -217,8 +218,36 @@ function initializeModuleLoaders(options) { // Initialize the ESM loader and a few module callbacks. // If shouldSpawnLoaderHookWorker is true, later when the ESM loader is instantiated on-demand, // it will spawn a loader worker thread to handle async custom loader hooks. - const { initializeESM } = require('internal/modules/esm/utils'); - initializeESM(shouldSpawnLoaderHookWorker); + if (!shouldSpawnLoaderHookWorker) { + const { initializeESM } = require('internal/modules/esm/utils'); + initializeESM(shouldSpawnLoaderHookWorker); + } else { + const { + setImportModuleDynamicallyCallback, + setInitializeImportMetaObjectCallback, + } = internalBinding('module_wrap'); + let esmInitialized = false; + let importModuleDynamicallyCallback; + let initializeImportMetaObject; + const ensureEsmInitialized = () => { + if (esmInitialized) return; + const esmUtils = require('internal/modules/esm/utils'); + esmUtils.initializeESM(shouldSpawnLoaderHookWorker); + importModuleDynamicallyCallback = esmUtils.importModuleDynamicallyCallback; + initializeImportMetaObject = esmUtils.initializeImportMetaObject; + esmInitialized = true; + }; + + setImportModuleDynamicallyCallback(function() { + ensureEsmInitialized(); + return ReflectApply(importModuleDynamicallyCallback, this, arguments); + }); + + setInitializeImportMetaObjectCallback(function() { + ensureEsmInitialized(); + return ReflectApply(initializeImportMetaObject, this, arguments); + }); + } const { hasStartedUserCJSExecution,