From 96e3f3be22a88e059a92768efd29dc564d9cf818 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Sat, 2 Mar 2024 03:23:22 +0100 Subject: [PATCH] module: refactor ESM loader initialization and entry point handling Split the `internal/process/esm_loader` file which contains the singleton cascaded loader: - The the singleton cascaded loader now directly resides in `internal/modules/esm/loader`, where the constructor also lives. This file is the root of most circular dependency of ESM code, (because components of the loader need the singleton itself), so this makes the dependency more obvious. Added comments about loading it lazily to avoid circular dependency. - The getter to the cascaded loader is also turned into a method to make the side effect explicit. - The sequence of `loadESM()` and `handleMainPromise` is now merged together into `runEntryPointWithESMLoader()` in `internal/modules/run_main` because this is intended to run entry points with the ESM loader and not just any module. - Documents how top-level await is handled. PR-URL: https://github.com/nodejs/node/pull/51999 Fixes: https://github.com/nodejs/node/issues/42868 Reviewed-By: Moshe Atlow Reviewed-By: Benjamin Gruenbaum Reviewed-By: Geoffrey Booth --- .github/CODEOWNERS | 1 - lib/internal/main/check_syntax.js | 7 +- lib/internal/main/eval_stdin.js | 8 +- lib/internal/main/eval_string.js | 8 +- lib/internal/main/repl.js | 5 +- lib/internal/main/worker_thread.js | 4 +- .../modules/esm/handle_process_exit.js | 16 ---- lib/internal/modules/esm/hooks.js | 4 +- lib/internal/modules/esm/loader.js | 34 +++++--- lib/internal/modules/esm/translators.js | 9 ++- lib/internal/modules/esm/utils.js | 11 +-- lib/internal/modules/run_main.js | 78 ++++++++++++++----- lib/internal/process/esm_loader.js | 40 ---------- lib/internal/process/execution.js | 38 +++++---- lib/internal/process/per_thread.js | 4 +- lib/internal/test_runner/utils.js | 4 +- lib/repl.js | 5 +- 17 files changed, 136 insertions(+), 140 deletions(-) delete mode 100644 lib/internal/modules/esm/handle_process_exit.js delete mode 100644 lib/internal/process/esm_loader.js diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e4241de7d42e75..e1fe4d0add3daf 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -96,7 +96,6 @@ /doc/api/packages.md @nodejs/loaders /lib/internal/bootstrap/realm.js @nodejs/loaders /lib/internal/modules/* @nodejs/loaders -/lib/internal/process/esm_loader.js @nodejs/loaders /lib/internal/process/execution.js @nodejs/loaders /lib/module.js @nodejs/loaders /src/module_wrap* @nodejs/loaders @nodejs/vm diff --git a/lib/internal/main/check_syntax.js b/lib/internal/main/check_syntax.js index 9a19c1809fe102..5a7ab5dc19e4e7 100644 --- a/lib/internal/main/check_syntax.js +++ b/lib/internal/main/check_syntax.js @@ -50,8 +50,7 @@ function loadESMIfNeeded(cb) { const hasModulePreImport = getOptionValue('--import').length > 0; if (hasModulePreImport) { - const { loadESM } = require('internal/process/esm_loader'); - loadESM(cb); + require('internal/modules/run_main').runEntryPointWithESMLoader(cb); return; } cb(); @@ -76,7 +75,5 @@ async function checkSyntax(source, filename) { return; } - const { loadESM } = require('internal/process/esm_loader'); - const { handleMainPromise } = require('internal/modules/run_main'); - handleMainPromise(loadESM((loader) => wrapSafe(filename, source))); + wrapSafe(filename, source); } diff --git a/lib/internal/main/eval_stdin.js b/lib/internal/main/eval_stdin.js index d71751e781b9b5..3ee4bcdb1d853b 100644 --- a/lib/internal/main/eval_stdin.js +++ b/lib/internal/main/eval_stdin.js @@ -10,7 +10,7 @@ const { const { getOptionValue } = require('internal/options'); const { - evalModule, + evalModuleEntryPoint, evalScript, readStdin, } = require('internal/process/execution'); @@ -24,15 +24,15 @@ readStdin((code) => { process._eval = code; const print = getOptionValue('--print'); - const loadESM = getOptionValue('--import').length > 0; + const shouldLoadESM = getOptionValue('--import').length > 0; if (getOptionValue('--input-type') === 'module' || (getOptionValue('--experimental-default-type') === 'module' && getOptionValue('--input-type') !== 'commonjs')) { - evalModule(code, print); + evalModuleEntryPoint(code, print); } else { evalScript('[stdin]', code, getOptionValue('--inspect-brk'), print, - loadESM); + shouldLoadESM); } }); diff --git a/lib/internal/main/eval_string.js b/lib/internal/main/eval_string.js index 908532b0b1865a..1125aa8d98e5aa 100644 --- a/lib/internal/main/eval_string.js +++ b/lib/internal/main/eval_string.js @@ -13,7 +13,7 @@ const { prepareMainThreadExecution, markBootstrapComplete, } = require('internal/process/pre_execution'); -const { evalModule, evalScript } = require('internal/process/execution'); +const { evalModuleEntryPoint, evalScript } = require('internal/process/execution'); const { addBuiltinLibsToObject } = require('internal/modules/helpers'); const { getOptionValue } = require('internal/options'); @@ -24,10 +24,10 @@ markBootstrapComplete(); const source = getOptionValue('--eval'); const print = getOptionValue('--print'); -const loadESM = getOptionValue('--import').length > 0 || getOptionValue('--experimental-loader').length > 0; +const shouldLoadESM = getOptionValue('--import').length > 0 || getOptionValue('--experimental-loader').length > 0; if (getOptionValue('--input-type') === 'module' || (getOptionValue('--experimental-default-type') === 'module' && getOptionValue('--input-type') !== 'commonjs')) { - evalModule(source, print); + evalModuleEntryPoint(source, print); } else { // For backward compatibility, we want the identifier crypto to be the // `node:crypto` module rather than WebCrypto. @@ -54,5 +54,5 @@ if (getOptionValue('--input-type') === 'module' || ) : source, getOptionValue('--inspect-brk'), print, - loadESM); + shouldLoadESM); } diff --git a/lib/internal/main/repl.js b/lib/internal/main/repl.js index da1764a9c80d95..f7aa3a3e2602fa 100644 --- a/lib/internal/main/repl.js +++ b/lib/internal/main/repl.js @@ -35,8 +35,7 @@ if (process.env.NODE_REPL_EXTERNAL_MODULE) { process.exit(kInvalidCommandLineArgument); } - const esmLoader = require('internal/process/esm_loader'); - esmLoader.loadESM(() => { + require('internal/modules/run_main').runEntryPointWithESMLoader(() => { console.log(`Welcome to Node.js ${process.version}.\n` + 'Type ".help" for more information.'); @@ -64,5 +63,7 @@ if (process.env.NODE_REPL_EXTERNAL_MODULE) { getOptionValue('--inspect-brk'), getOptionValue('--print')); } + // The TLAs in the REPL are still run as scripts, just transformed as async + // IIFEs for the REPL code itself to await on. }); } diff --git a/lib/internal/main/worker_thread.js b/lib/internal/main/worker_thread.js index c14091ffe09ca7..c0b151a1eac9de 100644 --- a/lib/internal/main/worker_thread.js +++ b/lib/internal/main/worker_thread.js @@ -170,8 +170,8 @@ port.on('message', (message) => { } case 'module': { - const { evalModule } = require('internal/process/execution'); - PromisePrototypeThen(evalModule(filename), undefined, (e) => { + const { evalModuleEntryPoint } = require('internal/process/execution'); + PromisePrototypeThen(evalModuleEntryPoint(filename), undefined, (e) => { workerOnGlobalUncaughtException(e, true); }); break; diff --git a/lib/internal/modules/esm/handle_process_exit.js b/lib/internal/modules/esm/handle_process_exit.js deleted file mode 100644 index 4689ef6bb204c0..00000000000000 --- a/lib/internal/modules/esm/handle_process_exit.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; - -const { exitCodes: { kUnfinishedTopLevelAwait } } = internalBinding('errors'); - -/** - * Handle a Promise from running code that potentially does Top-Level Await. - * In that case, it makes sense to set the exit code to a specific non-zero value - * if the main code never finishes running. - */ -function handleProcessExit() { - process.exitCode ??= kUnfinishedTopLevelAwait; -} - -module.exports = { - handleProcessExit, -}; diff --git a/lib/internal/modules/esm/hooks.js b/lib/internal/modules/esm/hooks.js index 314c49a95a4ea1..60942130dd48b9 100644 --- a/lib/internal/modules/esm/hooks.js +++ b/lib/internal/modules/esm/hooks.js @@ -146,8 +146,8 @@ class Hooks { * loader (user-land) to the worker. */ async register(urlOrSpecifier, parentURL, data) { - const moduleLoader = require('internal/process/esm_loader').esmLoader; - const keyedExports = await moduleLoader.import( + const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader(); + const keyedExports = await cascadedLoader.import( urlOrSpecifier, parentURL, kEmptyObject, diff --git a/lib/internal/modules/esm/loader.js b/lib/internal/modules/esm/loader.js index c0e3cdb36e1c02..fd4faa3bd4af62 100644 --- a/lib/internal/modules/esm/loader.js +++ b/lib/internal/modules/esm/loader.js @@ -20,7 +20,7 @@ const { ERR_UNKNOWN_MODULE_FORMAT, } = require('internal/errors').codes; const { getOptionValue } = require('internal/options'); -const { pathToFileURL, isURL } = require('internal/url'); +const { isURL } = require('internal/url'); const { emitExperimentalWarning } = require('internal/util'); const { getDefaultConditions, @@ -85,11 +85,6 @@ class ModuleLoader { */ #defaultConditions = getDefaultConditions(); - /** - * The index for assigning unique URLs to anonymous module evaluation - */ - evalIndex = 0; - /** * Registry of resolved specifiers */ @@ -187,10 +182,7 @@ class ModuleLoader { } } - async eval( - source, - url = pathToFileURL(`${process.cwd()}/[eval${++this.evalIndex}]`).href, - ) { + async eval(source, url) { const evalInstance = (url) => { const { ModuleWrap } = internalBinding('module_wrap'); const { registerModule } = require('internal/modules/esm/utils'); @@ -214,6 +206,7 @@ class ModuleLoader { return { __proto__: null, namespace: module.getNamespace(), + module, }; } @@ -568,6 +561,23 @@ function getHooksProxy() { return hooksProxy; } +let cascadedLoader; + +/** + * This is a singleton ESM loader that integrates the loader hooks, if any. + * It it used by other internal built-ins when they need to load ESM code + * while also respecting hooks. + * When built-ins need access to this loader, they should do + * require('internal/module/esm/loader').getOrInitializeCascadedLoader() + * lazily only right before the loader is actually needed, and don't do it + * in the top-level, to avoid circular dependencies. + * @returns {ModuleLoader} + */ +function getOrInitializeCascadedLoader() { + cascadedLoader ??= createModuleLoader(); + return cascadedLoader; +} + /** * Register a single loader programmatically. * @param {string|import('url').URL} specifier @@ -598,12 +608,11 @@ function getHooksProxy() { * ``` */ function register(specifier, parentURL = undefined, options) { - const moduleLoader = require('internal/process/esm_loader').esmLoader; if (parentURL != null && typeof parentURL === 'object' && !isURL(parentURL)) { options = parentURL; parentURL = options.parentURL; } - moduleLoader.register( + getOrInitializeCascadedLoader().register( specifier, parentURL ?? 'data:', options?.data, @@ -614,5 +623,6 @@ function register(specifier, parentURL = undefined, options) { module.exports = { createModuleLoader, getHooksProxy, + getOrInitializeCascadedLoader, register, }; diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js index ca547699d00ed1..61e489a6cedd7a 100644 --- a/lib/internal/modules/esm/translators.js +++ b/lib/internal/modules/esm/translators.js @@ -55,7 +55,6 @@ const { const { maybeCacheSourceMap } = require('internal/source_map/source_map_cache'); const moduleWrap = internalBinding('module_wrap'); const { ModuleWrap } = moduleWrap; -const asyncESM = require('internal/process/esm_loader'); const { emitWarningSync } = require('internal/process/warning'); const { internalCompileFunction } = require('internal/vm'); const { @@ -157,7 +156,8 @@ function errPath(url) { * @returns {Promise} The imported module. */ async function importModuleDynamically(specifier, { url }, attributes) { - return asyncESM.esmLoader.import(specifier, url, attributes); + const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader(); + return cascadedLoader.import(specifier, url, attributes); } // Strategy for loading a standard JavaScript module. @@ -243,6 +243,7 @@ function loadCJSModule(module, source, url, filename) { const compiledWrapper = compileResult.function; + const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader(); const __dirname = dirname(filename); // eslint-disable-next-line func-name-matching,func-style const requireFn = function require(specifier) { @@ -261,7 +262,7 @@ function loadCJSModule(module, source, url, filename) { } specifier = `${pathToFileURL(path)}`; } - const job = asyncESM.esmLoader.getModuleJobSync(specifier, url, importAttributes); + const job = cascadedLoader.getModuleJobSync(specifier, url, importAttributes); job.runSync(); return cjsCache.get(job.url).exports; }; @@ -272,7 +273,7 @@ function loadCJSModule(module, source, url, filename) { specifier = `${pathToFileURL(path)}`; } } - const { url: resolvedURL } = asyncESM.esmLoader.resolveSync(specifier, url, kEmptyObject); + const { url: resolvedURL } = cascadedLoader.resolveSync(specifier, url, kEmptyObject); return StringPrototypeStartsWith(resolvedURL, 'file://') ? fileURLToPath(resolvedURL) : resolvedURL; }); setOwnProperty(requireFn, 'main', process.mainModule); diff --git a/lib/internal/modules/esm/utils.js b/lib/internal/modules/esm/utils.js index 202159498edd47..7c1fb2a5745b5b 100644 --- a/lib/internal/modules/esm/utils.js +++ b/lib/internal/modules/esm/utils.js @@ -32,7 +32,6 @@ const { const { emitExperimentalWarning, getCWDURL, - getLazy, } = require('internal/util'); const { setImportModuleDynamicallyCallback, @@ -181,9 +180,6 @@ function initializeImportMetaObject(symbol, meta) { } } } -const getCascadedLoader = getLazy( - () => require('internal/process/esm_loader').esmLoader, -); /** * Proxy the dynamic import to the default loader. @@ -194,7 +190,8 @@ const getCascadedLoader = getLazy( */ function defaultImportModuleDynamically(specifier, attributes, referrerName) { const parentURL = normalizeReferrerURL(referrerName); - return getCascadedLoader().import(specifier, parentURL, attributes); + const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader(); + return cascadedLoader.import(specifier, parentURL, attributes); } /** @@ -263,10 +260,10 @@ async function initializeHooks() { const customLoaderURLs = getOptionValue('--experimental-loader'); const { Hooks } = require('internal/modules/esm/hooks'); - const esmLoader = require('internal/process/esm_loader').esmLoader; + const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader(); const hooks = new Hooks(); - esmLoader.setCustomizations(hooks); + cascadedLoader.setCustomizations(hooks); // We need the loader customizations to be set _before_ we start invoking // `--require`, otherwise loops can happen because a `--require` script diff --git a/lib/internal/modules/run_main.js b/lib/internal/modules/run_main.js index 23268637e4fd58..6488bedb21cf6c 100644 --- a/lib/internal/modules/run_main.js +++ b/lib/internal/modules/run_main.js @@ -9,6 +9,15 @@ const { getNearestParentPackageJSONType } = internalBinding('modules'); const { getOptionValue } = require('internal/options'); const { checkPackageJSONIntegrity } = require('internal/modules/package_json_reader'); const path = require('path'); +const { pathToFileURL } = require('internal/url'); +const { kEmptyObject, getCWDURL } = require('internal/util'); +const { + hasUncaughtExceptionCaptureCallback, +} = require('internal/process/execution'); +const { + triggerUncaughtException, + exitCodes: { kUnfinishedTopLevelAwait }, +} = internalBinding('errors'); /** * Get the absolute path to the main entry point. @@ -94,35 +103,58 @@ function shouldUseESMLoader(mainPath) { } /** - * Run the main entry point through the ESM Loader. - * @param {string} mainPath - Absolute path for the main entry point + * Handle a Promise from running code that potentially does Top-Level Await. + * In that case, it makes sense to set the exit code to a specific non-zero value + * if the main code never finishes running. */ -function runMainESM(mainPath) { - const { loadESM } = require('internal/process/esm_loader'); - const { pathToFileURL } = require('internal/url'); - const main = pathToFileURL(mainPath).href; - - handleMainPromise(loadESM((esmLoader) => { - return esmLoader.import(main, undefined, { __proto__: null }); - })); +function handleProcessExit() { + process.exitCode ??= kUnfinishedTopLevelAwait; } /** - * Handle process exit events around the main entry point promise. - * @param {Promise} promise - Main entry point promise + * @param {function(ModuleLoader):ModuleWrap|undefined} callback */ -async function handleMainPromise(promise) { - const { - handleProcessExit, - } = require('internal/modules/esm/handle_process_exit'); +async function asyncRunEntryPointWithESMLoader(callback) { process.on('exit', handleProcessExit); + const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader(); try { - return await promise; + const userImports = getOptionValue('--import'); + if (userImports.length > 0) { + const parentURL = getCWDURL().href; + for (let i = 0; i < userImports.length; i++) { + await cascadedLoader.import(userImports[i], parentURL, kEmptyObject); + } + } else { + cascadedLoader.forceLoadHooks(); + } + await callback(cascadedLoader); + } catch (err) { + if (hasUncaughtExceptionCaptureCallback()) { + process._fatalException(err); + return; + } + triggerUncaughtException( + err, + true, /* fromPromise */ + ); } finally { process.off('exit', handleProcessExit); } } +/** + * This initializes the ESM loader and runs --import (if any) before executing the + * callback to run the entry point. + * If the callback intends to evaluate a ESM module as entry point, it should return + * the corresponding ModuleWrap so that stalled TLA can be checked a process exit. + * @param {function(ModuleLoader):ModuleWrap|undefined} callback + * @returns {Promise} + */ +function runEntryPointWithESMLoader(callback) { + const promise = asyncRunEntryPointWithESMLoader(callback); + return promise; +} + /** * Parse the CLI main entry point string and run it. * For backwards compatibility, we have to run a bunch of monkey-patchable code that belongs to the CJS loader (exposed @@ -135,7 +167,14 @@ function executeUserEntryPoint(main = process.argv[1]) { const resolvedMain = resolveMainPath(main); const useESMLoader = shouldUseESMLoader(resolvedMain); if (useESMLoader) { - runMainESM(resolvedMain || main); + const mainPath = resolvedMain || main; + const mainURL = pathToFileURL(mainPath).href; + + runEntryPointWithESMLoader((cascadedLoader) => { + // Note that if the graph contains unfinished TLA, this may never resolve + // even after the event loop stops running. + return cascadedLoader.import(mainURL, undefined, { __proto__: null }, true); + }); } else { // Module._load is the monkey-patchable CJS module loader. const { Module } = require('internal/modules/cjs/loader'); @@ -145,5 +184,6 @@ function executeUserEntryPoint(main = process.argv[1]) { module.exports = { executeUserEntryPoint, - handleMainPromise, + runEntryPointWithESMLoader, + handleProcessExit, }; diff --git a/lib/internal/process/esm_loader.js b/lib/internal/process/esm_loader.js deleted file mode 100644 index 0865d7ceef66b7..00000000000000 --- a/lib/internal/process/esm_loader.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; - -const { createModuleLoader } = require('internal/modules/esm/loader'); -const { getOptionValue } = require('internal/options'); -const { - hasUncaughtExceptionCaptureCallback, -} = require('internal/process/execution'); -const { kEmptyObject, getCWDURL } = require('internal/util'); - -let esmLoader; - -module.exports = { - get esmLoader() { - return esmLoader ??= createModuleLoader(); - }, - async loadESM(callback) { - esmLoader ??= createModuleLoader(); - try { - const userImports = getOptionValue('--import'); - if (userImports.length > 0) { - const parentURL = getCWDURL().href; - for (let i = 0; i < userImports.length; i++) { - await esmLoader.import(userImports[i], parentURL, kEmptyObject); - } - } else { - esmLoader.forceLoadHooks(); - } - await callback(esmLoader); - } catch (err) { - if (hasUncaughtExceptionCaptureCallback()) { - process._fatalException(err); - return; - } - internalBinding('errors').triggerUncaughtException( - err, - true, /* fromPromise */ - ); - } - }, -}; diff --git a/lib/internal/process/execution.js b/lib/internal/process/execution.js index 5de5edfb2d5524..e69add7394e60f 100644 --- a/lib/internal/process/execution.js +++ b/lib/internal/process/execution.js @@ -15,6 +15,7 @@ const { ERR_EVAL_ESM_CANNOT_PRINT, }, } = require('internal/errors'); +const { pathToFileURL } = require('internal/url'); const { exitCodes: { kGenericUserError } } = internalBinding('errors'); const { @@ -46,19 +47,30 @@ function tryGetCwd() { } } -function evalModule(source, print) { +let evalIndex = 0; +function getEvalModuleUrl() { + return pathToFileURL(`${process.cwd()}/[eval${++evalIndex}]`).href; +} + +/** + * Evaluate an ESM entry point and return the promise that gets fulfilled after + * it finishes evaluation. + * @param {string} source Source code the ESM + * @param {boolean} print Whether the result should be printed. + * @returns {Promise} + */ +function evalModuleEntryPoint(source, print) { if (print) { throw new ERR_EVAL_ESM_CANNOT_PRINT(); } - const { loadESM } = require('internal/process/esm_loader'); - const { handleMainPromise } = require('internal/modules/run_main'); RegExpPrototypeExec(/^/, ''); // Necessary to reset RegExp statics before user code runs. - return handleMainPromise(loadESM((loader) => loader.eval(source))); + return require('internal/modules/run_main').runEntryPointWithESMLoader( + (loader) => loader.eval(source, getEvalModuleUrl(), true), + ); } function evalScript(name, body, breakFirstLine, print, shouldLoadESM = false) { const CJSModule = require('internal/modules/cjs/loader').Module; - const { pathToFileURL } = require('internal/url'); const cwd = tryGetCwd(); const origModule = globalThis.module; // Set e.g. when called from the REPL. @@ -67,15 +79,12 @@ function evalScript(name, body, breakFirstLine, print, shouldLoadESM = false) { module.filename = path.join(cwd, name); module.paths = CJSModule._nodeModulePaths(cwd); - const { handleMainPromise } = require('internal/modules/run_main'); - const asyncESM = require('internal/process/esm_loader'); const baseUrl = pathToFileURL(module.filename).href; - const { loadESM } = asyncESM; if (getOptionValue('--experimental-detect-module') && getOptionValue('--input-type') === '' && getOptionValue('--experimental-default-type') === '' && containsModuleSyntax(body, name)) { - return evalModule(body, print); + return evalModuleEntryPoint(body, print); } const runScript = () => { @@ -92,8 +101,8 @@ function evalScript(name, body, breakFirstLine, print, shouldLoadESM = false) { const result = module._compile(script, `${name}-wrapper`)(() => { const hostDefinedOptionId = Symbol(name); async function importModuleDynamically(specifier, _, importAttributes) { - const loader = asyncESM.esmLoader; - return loader.import(specifier, baseUrl, importAttributes); + const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader(); + return cascadedLoader.import(specifier, baseUrl, importAttributes); } const script = makeContextifyScript( body, // code @@ -118,9 +127,10 @@ function evalScript(name, body, breakFirstLine, print, shouldLoadESM = false) { }; if (shouldLoadESM) { - return handleMainPromise(loadESM(runScript)); + require('internal/modules/run_main').runEntryPointWithESMLoader(runScript); + return; } - return runScript(); + runScript(); } const exceptionHandlerState = { @@ -228,7 +238,7 @@ function readStdin(callback) { module.exports = { readStdin, tryGetCwd, - evalModule, + evalModuleEntryPoint, evalScript, onGlobalUncaughtException: createOnGlobalUncaughtException(), setUncaughtExceptionCaptureCallback, diff --git a/lib/internal/process/per_thread.js b/lib/internal/process/per_thread.js index b45f2a61e0ddaf..85777c9e4a3ed5 100644 --- a/lib/internal/process/per_thread.js +++ b/lib/internal/process/per_thread.js @@ -173,9 +173,7 @@ function wrapProcessMethods(binding) { memoryUsage.rss = rss; function exit(code) { - const { - handleProcessExit, - } = require('internal/modules/esm/handle_process_exit'); + const { handleProcessExit } = require('internal/modules/run_main'); process.off('exit', handleProcessExit); if (arguments.length !== 0) { diff --git a/lib/internal/test_runner/utils.js b/lib/internal/test_runner/utils.js index 184d44dce6c162..0a3fd9cad83edd 100644 --- a/lib/internal/test_runner/utils.js +++ b/lib/internal/test_runner/utils.js @@ -154,8 +154,8 @@ async function getReportersMap(reporters, destinations) { parentURL = 'file:///'; } - const { esmLoader } = require('internal/process/esm_loader'); - reporter = await esmLoader.import(name, parentURL, { __proto__: null }); + const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader(); + reporter = await cascadedLoader.import(name, parentURL, { __proto__: null }); } if (reporter?.default) { diff --git a/lib/repl.js b/lib/repl.js index 1fbce42888c9a2..d16f8882211a42 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -462,9 +462,8 @@ function REPLServer(prompt, // Continue regardless of error. } async function importModuleDynamically(specifier, _, importAttributes) { - const asyncESM = require('internal/process/esm_loader'); - return asyncESM.esmLoader.import(specifier, parentURL, - importAttributes); + const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader(); + return cascadedLoader.import(specifier, parentURL, importAttributes); } // `experimentalREPLAwait` is set to true by default. // Shall be false in case `--no-experimental-repl-await` flag is used.