'use strict'; const { ArrayIsArray, SafeSet, SafeWeakMap, ObjectFreeze, } = primordials; const { ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING, ERR_INVALID_ARG_VALUE, } = require('internal/errors').codes; const { getOptionValue } = require('internal/options'); const { loadPreloadModules, initializeFrozenIntrinsics, } = require('internal/process/pre_execution'); const { pathToFileURL } = require('internal/url'); const { setImportModuleDynamicallyCallback, setInitializeImportMetaObjectCallback, } = internalBinding('module_wrap'); const { getModuleFromWrap, } = require('internal/vm/module'); const assert = require('internal/assert'); const callbackMap = new SafeWeakMap(); function setCallbackForWrap(wrap, data) { callbackMap.set(wrap, data); } let defaultConditions; function getDefaultConditions() { assert(defaultConditions !== undefined); return defaultConditions; } let defaultConditionsSet; function getDefaultConditionsSet() { assert(defaultConditionsSet !== undefined); return defaultConditionsSet; } // This function is called during pre-execution, before any user code is run. function initializeDefaultConditions() { const userConditions = getOptionValue('--conditions'); const noAddons = getOptionValue('--no-addons'); const addonConditions = noAddons ? [] : ['node-addons']; defaultConditions = ObjectFreeze([ 'node', 'import', ...addonConditions, ...userConditions, ]); defaultConditionsSet = new SafeSet(defaultConditions); } /** * @param {string[]} [conditions] * @returns {Set} */ function getConditionsSet(conditions) { if (conditions !== undefined && conditions !== getDefaultConditions()) { if (!ArrayIsArray(conditions)) { throw new ERR_INVALID_ARG_VALUE('conditions', conditions, 'expected an array'); } return new SafeSet(conditions); } return getDefaultConditionsSet(); } function initializeImportMetaObject(wrap, meta) { if (callbackMap.has(wrap)) { const { initializeImportMeta } = callbackMap.get(wrap); if (initializeImportMeta !== undefined) { meta = initializeImportMeta(meta, getModuleFromWrap(wrap) || wrap); } } } async function importModuleDynamicallyCallback(wrap, specifier, assertions) { if (callbackMap.has(wrap)) { const { importModuleDynamically } = callbackMap.get(wrap); if (importModuleDynamically !== undefined) { return importModuleDynamically( specifier, getModuleFromWrap(wrap) || wrap, assertions); } } throw new ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING(); } // This is configured during pre-execution. Specifically it's set to true for // the loader worker in internal/main/worker_thread.js. let _isLoaderWorker = false; function initializeESM(isLoaderWorker = false) { _isLoaderWorker = isLoaderWorker; initializeDefaultConditions(); // Setup per-isolate callbacks that locate data or callbacks that we keep // track of for different ESM modules. setInitializeImportMetaObjectCallback(initializeImportMetaObject); setImportModuleDynamicallyCallback(importModuleDynamicallyCallback); } function isLoaderWorker() { return _isLoaderWorker; } async function initializeHooks() { const customLoaderURLs = getOptionValue('--experimental-loader'); let cwd; try { // `process.cwd()` can fail if the parent directory is deleted while the process runs. cwd = process.cwd() + '/'; } catch { cwd = '/'; } const { Hooks } = require('internal/modules/esm/hooks'); const esmLoader = require('internal/process/esm_loader').esmLoader; const hooks = new Hooks(); esmLoader.setCustomizations(hooks); // We need the loader customizations to be set _before_ we start invoking // `--require`, otherwise loops can happen because a `--require` script // might call `register(...)` before we've installed ourselves. These // global values are magically set in `setupUserModules` just for us and // we call them in the correct order. // N.B. This block appears here specifically in order to ensure that // `--require` calls occur before `--loader` ones do. loadPreloadModules(); initializeFrozenIntrinsics(); const parentURL = pathToFileURL(cwd).href; for (let i = 0; i < customLoaderURLs.length; i++) { await hooks.register( customLoaderURLs[i], parentURL, ); } return hooks; } module.exports = { setCallbackForWrap, initializeESM, initializeHooks, getDefaultConditions, getConditionsSet, loaderWorkerId: 'internal/modules/esm/worker', isLoaderWorker, };