11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst { 41cb0ef41Sopenharmony_ci ArrayIsArray, 51cb0ef41Sopenharmony_ci SafeSet, 61cb0ef41Sopenharmony_ci SafeWeakMap, 71cb0ef41Sopenharmony_ci ObjectFreeze, 81cb0ef41Sopenharmony_ci} = primordials; 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ciconst { 111cb0ef41Sopenharmony_ci privateSymbols: { 121cb0ef41Sopenharmony_ci host_defined_option_symbol, 131cb0ef41Sopenharmony_ci }, 141cb0ef41Sopenharmony_ci} = internalBinding('util'); 151cb0ef41Sopenharmony_ciconst { 161cb0ef41Sopenharmony_ci default_host_defined_options, 171cb0ef41Sopenharmony_ci vm_dynamic_import_missing_flag, 181cb0ef41Sopenharmony_ci} = internalBinding('symbols'); 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_ciconst { 211cb0ef41Sopenharmony_ci ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING_FLAG, 221cb0ef41Sopenharmony_ci ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING, 231cb0ef41Sopenharmony_ci ERR_INVALID_ARG_VALUE, 241cb0ef41Sopenharmony_ci} = require('internal/errors').codes; 251cb0ef41Sopenharmony_ciconst { getOptionValue } = require('internal/options'); 261cb0ef41Sopenharmony_ciconst { 271cb0ef41Sopenharmony_ci loadPreloadModules, 281cb0ef41Sopenharmony_ci initializeFrozenIntrinsics, 291cb0ef41Sopenharmony_ci} = require('internal/process/pre_execution'); 301cb0ef41Sopenharmony_ciconst { getCWDURL } = require('internal/util'); 311cb0ef41Sopenharmony_ciconst { 321cb0ef41Sopenharmony_ci setImportModuleDynamicallyCallback, 331cb0ef41Sopenharmony_ci setInitializeImportMetaObjectCallback, 341cb0ef41Sopenharmony_ci} = internalBinding('module_wrap'); 351cb0ef41Sopenharmony_ciconst assert = require('internal/assert'); 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_cilet defaultConditions; 381cb0ef41Sopenharmony_ci/** 391cb0ef41Sopenharmony_ci * Returns the default conditions for ES module loading. 401cb0ef41Sopenharmony_ci */ 411cb0ef41Sopenharmony_cifunction getDefaultConditions() { 421cb0ef41Sopenharmony_ci assert(defaultConditions !== undefined); 431cb0ef41Sopenharmony_ci return defaultConditions; 441cb0ef41Sopenharmony_ci} 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci/** @type {Set<string>} */ 471cb0ef41Sopenharmony_cilet defaultConditionsSet; 481cb0ef41Sopenharmony_ci/** 491cb0ef41Sopenharmony_ci * Returns the default conditions for ES module loading, as a Set. 501cb0ef41Sopenharmony_ci */ 511cb0ef41Sopenharmony_cifunction getDefaultConditionsSet() { 521cb0ef41Sopenharmony_ci assert(defaultConditionsSet !== undefined); 531cb0ef41Sopenharmony_ci return defaultConditionsSet; 541cb0ef41Sopenharmony_ci} 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci/** 571cb0ef41Sopenharmony_ci * Initializes the default conditions for ESM module loading. 581cb0ef41Sopenharmony_ci * This function is called during pre-execution, before any user code is run. 591cb0ef41Sopenharmony_ci */ 601cb0ef41Sopenharmony_cifunction initializeDefaultConditions() { 611cb0ef41Sopenharmony_ci const userConditions = getOptionValue('--conditions'); 621cb0ef41Sopenharmony_ci const noAddons = getOptionValue('--no-addons'); 631cb0ef41Sopenharmony_ci const addonConditions = noAddons ? [] : ['node-addons']; 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci defaultConditions = ObjectFreeze([ 661cb0ef41Sopenharmony_ci 'node', 671cb0ef41Sopenharmony_ci 'import', 681cb0ef41Sopenharmony_ci ...addonConditions, 691cb0ef41Sopenharmony_ci ...userConditions, 701cb0ef41Sopenharmony_ci ]); 711cb0ef41Sopenharmony_ci defaultConditionsSet = new SafeSet(defaultConditions); 721cb0ef41Sopenharmony_ci} 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci/** 751cb0ef41Sopenharmony_ci * @param {string[]} [conditions] 761cb0ef41Sopenharmony_ci * @returns {Set<string>} 771cb0ef41Sopenharmony_ci */ 781cb0ef41Sopenharmony_cifunction getConditionsSet(conditions) { 791cb0ef41Sopenharmony_ci if (conditions !== undefined && conditions !== getDefaultConditions()) { 801cb0ef41Sopenharmony_ci if (!ArrayIsArray(conditions)) { 811cb0ef41Sopenharmony_ci throw new ERR_INVALID_ARG_VALUE('conditions', conditions, 821cb0ef41Sopenharmony_ci 'expected an array'); 831cb0ef41Sopenharmony_ci } 841cb0ef41Sopenharmony_ci return new SafeSet(conditions); 851cb0ef41Sopenharmony_ci } 861cb0ef41Sopenharmony_ci return getDefaultConditionsSet(); 871cb0ef41Sopenharmony_ci} 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci/** 901cb0ef41Sopenharmony_ci * @callback ImportModuleDynamicallyCallback 911cb0ef41Sopenharmony_ci * @param {string} specifier 921cb0ef41Sopenharmony_ci * @param {ModuleWrap|ContextifyScript|Function|vm.Module} callbackReferrer 931cb0ef41Sopenharmony_ci * @param {object} attributes 941cb0ef41Sopenharmony_ci * @returns { Promise<void> } 951cb0ef41Sopenharmony_ci */ 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci/** 981cb0ef41Sopenharmony_ci * @callback InitializeImportMetaCallback 991cb0ef41Sopenharmony_ci * @param {object} meta 1001cb0ef41Sopenharmony_ci * @param {ModuleWrap|ContextifyScript|Function|vm.Module} callbackReferrer 1011cb0ef41Sopenharmony_ci */ 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci/** 1041cb0ef41Sopenharmony_ci * @typedef {{ 1051cb0ef41Sopenharmony_ci * callbackReferrer: ModuleWrap|ContextifyScript|Function|vm.Module 1061cb0ef41Sopenharmony_ci * initializeImportMeta? : InitializeImportMetaCallback, 1071cb0ef41Sopenharmony_ci * importModuleDynamically? : ImportModuleDynamicallyCallback 1081cb0ef41Sopenharmony_ci * }} ModuleRegistry 1091cb0ef41Sopenharmony_ci */ 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci/** 1121cb0ef41Sopenharmony_ci * @type {WeakMap<symbol, ModuleRegistry>} 1131cb0ef41Sopenharmony_ci */ 1141cb0ef41Sopenharmony_ciconst moduleRegistries = new SafeWeakMap(); 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ci/** 1171cb0ef41Sopenharmony_ci * V8 would make sure that as long as import() can still be initiated from 1181cb0ef41Sopenharmony_ci * the referrer, the symbol referenced by |host_defined_option_symbol| should 1191cb0ef41Sopenharmony_ci * be alive, which in term would keep the settings object alive through the 1201cb0ef41Sopenharmony_ci * WeakMap, and in turn that keeps the referrer object alive, which would be 1211cb0ef41Sopenharmony_ci * passed into the callbacks. 1221cb0ef41Sopenharmony_ci * The reference goes like this: 1231cb0ef41Sopenharmony_ci * [v8::internal::Script] (via host defined options) ----1--> [idSymbol] 1241cb0ef41Sopenharmony_ci * [callbackReferrer] (via host_defined_option_symbol) ------2------^ | 1251cb0ef41Sopenharmony_ci * ^----------3---- (via WeakMap)------ 1261cb0ef41Sopenharmony_ci * 1+3 makes sure that as long as import() can still be initiated, the 1271cb0ef41Sopenharmony_ci * referrer wrap is still around and can be passed into the callbacks. 1281cb0ef41Sopenharmony_ci * 2 is only there so that we can get the id symbol to configure the 1291cb0ef41Sopenharmony_ci * weak map. 1301cb0ef41Sopenharmony_ci * @param {ModuleWrap|ContextifyScript|Function} referrer The referrer to 1311cb0ef41Sopenharmony_ci * get the id symbol from. This is different from callbackReferrer which 1321cb0ef41Sopenharmony_ci * could be set by the caller. 1331cb0ef41Sopenharmony_ci * @param {ModuleRegistry} registry 1341cb0ef41Sopenharmony_ci */ 1351cb0ef41Sopenharmony_cifunction registerModule(referrer, registry) { 1361cb0ef41Sopenharmony_ci const idSymbol = referrer[host_defined_option_symbol]; 1371cb0ef41Sopenharmony_ci if (idSymbol === default_host_defined_options || 1381cb0ef41Sopenharmony_ci idSymbol === vm_dynamic_import_missing_flag) { 1391cb0ef41Sopenharmony_ci // The referrer is compiled without custom callbacks, so there is 1401cb0ef41Sopenharmony_ci // no registry to hold on to. We'll throw 1411cb0ef41Sopenharmony_ci // ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING when a callback is 1421cb0ef41Sopenharmony_ci // needed. 1431cb0ef41Sopenharmony_ci return; 1441cb0ef41Sopenharmony_ci } 1451cb0ef41Sopenharmony_ci // To prevent it from being GC'ed. 1461cb0ef41Sopenharmony_ci registry.callbackReferrer ??= referrer; 1471cb0ef41Sopenharmony_ci moduleRegistries.set(idSymbol, registry); 1481cb0ef41Sopenharmony_ci} 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci/** 1511cb0ef41Sopenharmony_ci * Defines the `import.meta` object for a given module. 1521cb0ef41Sopenharmony_ci * @param {symbol} symbol - Reference to the module. 1531cb0ef41Sopenharmony_ci * @param {Record<string, string | Function>} meta - The import.meta object to initialize. 1541cb0ef41Sopenharmony_ci */ 1551cb0ef41Sopenharmony_cifunction initializeImportMetaObject(symbol, meta) { 1561cb0ef41Sopenharmony_ci if (moduleRegistries.has(symbol)) { 1571cb0ef41Sopenharmony_ci const { initializeImportMeta, callbackReferrer } = moduleRegistries.get(symbol); 1581cb0ef41Sopenharmony_ci if (initializeImportMeta !== undefined) { 1591cb0ef41Sopenharmony_ci meta = initializeImportMeta(meta, callbackReferrer); 1601cb0ef41Sopenharmony_ci } 1611cb0ef41Sopenharmony_ci } 1621cb0ef41Sopenharmony_ci} 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci/** 1651cb0ef41Sopenharmony_ci * Asynchronously imports a module dynamically using a callback function. The native callback. 1661cb0ef41Sopenharmony_ci * @param {symbol} symbol - Reference to the module. 1671cb0ef41Sopenharmony_ci * @param {string} specifier - The module specifier string. 1681cb0ef41Sopenharmony_ci * @param {Record<string, string>} attributes - The import attributes object. 1691cb0ef41Sopenharmony_ci * @returns {Promise<import('internal/modules/esm/loader.js').ModuleExports>} - The imported module object. 1701cb0ef41Sopenharmony_ci * @throws {ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING} - If the callback function is missing. 1711cb0ef41Sopenharmony_ci */ 1721cb0ef41Sopenharmony_ciasync function importModuleDynamicallyCallback(symbol, specifier, attributes) { 1731cb0ef41Sopenharmony_ci if (moduleRegistries.has(symbol)) { 1741cb0ef41Sopenharmony_ci const { importModuleDynamically, callbackReferrer } = moduleRegistries.get(symbol); 1751cb0ef41Sopenharmony_ci if (importModuleDynamically !== undefined) { 1761cb0ef41Sopenharmony_ci return importModuleDynamically(specifier, callbackReferrer, attributes); 1771cb0ef41Sopenharmony_ci } 1781cb0ef41Sopenharmony_ci } 1791cb0ef41Sopenharmony_ci if (symbol === vm_dynamic_import_missing_flag) { 1801cb0ef41Sopenharmony_ci throw new ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING_FLAG(); 1811cb0ef41Sopenharmony_ci } 1821cb0ef41Sopenharmony_ci throw new ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING(); 1831cb0ef41Sopenharmony_ci} 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_cilet _isLoaderWorker = false; 1861cb0ef41Sopenharmony_ci/** 1871cb0ef41Sopenharmony_ci * Initializes handling of ES modules. 1881cb0ef41Sopenharmony_ci * This is configured during pre-execution. Specifically it's set to true for 1891cb0ef41Sopenharmony_ci * the loader worker in internal/main/worker_thread.js. 1901cb0ef41Sopenharmony_ci * @param {boolean} [isLoaderWorker=false] - A boolean indicating whether the loader is a worker or not. 1911cb0ef41Sopenharmony_ci */ 1921cb0ef41Sopenharmony_cifunction initializeESM(isLoaderWorker = false) { 1931cb0ef41Sopenharmony_ci _isLoaderWorker = isLoaderWorker; 1941cb0ef41Sopenharmony_ci initializeDefaultConditions(); 1951cb0ef41Sopenharmony_ci // Setup per-isolate callbacks that locate data or callbacks that we keep 1961cb0ef41Sopenharmony_ci // track of for different ESM modules. 1971cb0ef41Sopenharmony_ci setInitializeImportMetaObjectCallback(initializeImportMetaObject); 1981cb0ef41Sopenharmony_ci setImportModuleDynamicallyCallback(importModuleDynamicallyCallback); 1991cb0ef41Sopenharmony_ci} 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ci/** 2021cb0ef41Sopenharmony_ci * Determine whether the current process is a loader worker. 2031cb0ef41Sopenharmony_ci * @returns {boolean} Whether the current process is a loader worker. 2041cb0ef41Sopenharmony_ci */ 2051cb0ef41Sopenharmony_cifunction isLoaderWorker() { 2061cb0ef41Sopenharmony_ci return _isLoaderWorker; 2071cb0ef41Sopenharmony_ci} 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ci/** 2101cb0ef41Sopenharmony_ci * Register module customization hooks. 2111cb0ef41Sopenharmony_ci */ 2121cb0ef41Sopenharmony_ciasync function initializeHooks() { 2131cb0ef41Sopenharmony_ci const customLoaderURLs = getOptionValue('--experimental-loader'); 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ci const { Hooks } = require('internal/modules/esm/hooks'); 2161cb0ef41Sopenharmony_ci const esmLoader = require('internal/process/esm_loader').esmLoader; 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_ci const hooks = new Hooks(); 2191cb0ef41Sopenharmony_ci esmLoader.setCustomizations(hooks); 2201cb0ef41Sopenharmony_ci 2211cb0ef41Sopenharmony_ci // We need the loader customizations to be set _before_ we start invoking 2221cb0ef41Sopenharmony_ci // `--require`, otherwise loops can happen because a `--require` script 2231cb0ef41Sopenharmony_ci // might call `register(...)` before we've installed ourselves. These 2241cb0ef41Sopenharmony_ci // global values are magically set in `setupUserModules` just for us and 2251cb0ef41Sopenharmony_ci // we call them in the correct order. 2261cb0ef41Sopenharmony_ci // N.B. This block appears here specifically in order to ensure that 2271cb0ef41Sopenharmony_ci // `--require` calls occur before `--loader` ones do. 2281cb0ef41Sopenharmony_ci loadPreloadModules(); 2291cb0ef41Sopenharmony_ci initializeFrozenIntrinsics(); 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ci const parentURL = getCWDURL().href; 2321cb0ef41Sopenharmony_ci for (let i = 0; i < customLoaderURLs.length; i++) { 2331cb0ef41Sopenharmony_ci await hooks.register( 2341cb0ef41Sopenharmony_ci customLoaderURLs[i], 2351cb0ef41Sopenharmony_ci parentURL, 2361cb0ef41Sopenharmony_ci ); 2371cb0ef41Sopenharmony_ci } 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ci const preloadScripts = hooks.initializeGlobalPreload(); 2401cb0ef41Sopenharmony_ci 2411cb0ef41Sopenharmony_ci return { __proto__: null, hooks, preloadScripts }; 2421cb0ef41Sopenharmony_ci} 2431cb0ef41Sopenharmony_ci 2441cb0ef41Sopenharmony_cimodule.exports = { 2451cb0ef41Sopenharmony_ci registerModule, 2461cb0ef41Sopenharmony_ci initializeESM, 2471cb0ef41Sopenharmony_ci initializeHooks, 2481cb0ef41Sopenharmony_ci getDefaultConditions, 2491cb0ef41Sopenharmony_ci getConditionsSet, 2501cb0ef41Sopenharmony_ci loaderWorkerId: 'internal/modules/esm/worker', 2511cb0ef41Sopenharmony_ci isLoaderWorker, 2521cb0ef41Sopenharmony_ci}; 253