mirror of
https://github.com/nodejs/node.git
synced 2025-05-05 11:29:34 +00:00

PR-URL: https://github.com/nodejs/node/pull/46826 Reviewed-By: Jacob Smith <jacob@frende.me> Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
179 lines
5.2 KiB
JavaScript
179 lines
5.2 KiB
JavaScript
'use strict';
|
|
|
|
const {
|
|
ArrayIsArray,
|
|
PromisePrototypeThen,
|
|
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 { pathToFileURL } = require('internal/url');
|
|
const { kEmptyObject } = require('internal/util');
|
|
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<string>}
|
|
*/
|
|
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 hooks = new Hooks();
|
|
|
|
const { DefaultModuleLoader } = require('internal/modules/esm/loader');
|
|
class ModuleLoader extends DefaultModuleLoader {
|
|
loaderType = 'internal';
|
|
async #getModuleJob(specifier, parentURL, importAssertions) {
|
|
const resolveResult = await hooks.resolve(specifier, parentURL, importAssertions);
|
|
return this.getJobFromResolveResult(resolveResult, parentURL, importAssertions);
|
|
}
|
|
getModuleJob(specifier, parentURL, importAssertions) {
|
|
const jobPromise = this.#getModuleJob(specifier, parentURL, importAssertions);
|
|
return {
|
|
run() {
|
|
return PromisePrototypeThen(jobPromise, (job) => job.run());
|
|
},
|
|
get modulePromise() {
|
|
return PromisePrototypeThen(jobPromise, (job) => job.modulePromise);
|
|
},
|
|
get linked() {
|
|
return PromisePrototypeThen(jobPromise, (job) => job.linked);
|
|
},
|
|
};
|
|
}
|
|
load(url, context) { return hooks.load(url, context); }
|
|
}
|
|
const privateModuleLoader = new ModuleLoader();
|
|
const parentURL = pathToFileURL(cwd).href;
|
|
|
|
// TODO(jlenon7): reuse the `Hooks.register()` method for registering loaders.
|
|
for (let i = 0; i < customLoaderURLs.length; i++) {
|
|
const customLoaderURL = customLoaderURLs[i];
|
|
|
|
// Importation must be handled by internal loader to avoid polluting user-land
|
|
const keyedExports = await privateModuleLoader.import(
|
|
customLoaderURL,
|
|
parentURL,
|
|
kEmptyObject,
|
|
);
|
|
|
|
hooks.addCustomLoader(customLoaderURL, keyedExports);
|
|
}
|
|
|
|
const preloadScripts = hooks.initializeGlobalPreload();
|
|
|
|
return { __proto__: null, hooks, preloadScripts };
|
|
}
|
|
|
|
module.exports = {
|
|
setCallbackForWrap,
|
|
initializeESM,
|
|
initializeHooks,
|
|
getDefaultConditions,
|
|
getConditionsSet,
|
|
loaderWorkerId: 'internal/modules/esm/worker',
|
|
isLoaderWorker,
|
|
};
|