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