From 9b4c85c6e9722e3eb29526f33942d7c6aafabe82 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Tue, 13 Jun 2023 00:35:57 +0200 Subject: [PATCH] WIP: remove disentangle `loader` from `ModuleJob` --- lib/internal/modules/esm/loader.js | 63 +++++++++---------------- lib/internal/modules/esm/module_job.js | 62 +++++++++++++++--------- lib/internal/modules/esm/translators.js | 9 ---- 3 files changed, 64 insertions(+), 70 deletions(-) diff --git a/lib/internal/modules/esm/loader.js b/lib/internal/modules/esm/loader.js index 5919faa56afa9c..4ed9371a09ee2d 100644 --- a/lib/internal/modules/esm/loader.js +++ b/lib/internal/modules/esm/loader.js @@ -101,22 +101,10 @@ class DefaultModuleLoader { source, url = pathToFileURL(`${process.cwd()}/[eval${++this.evalIndex}]`).href, ) { - const evalInstance = (url) => { - const { ModuleWrap } = internalBinding('module_wrap'); - const { setCallbackForWrap } = require('internal/modules/esm/utils'); - const module = new ModuleWrap(url, undefined, source, 0, 0); - setCallbackForWrap(module, { - initializeImportMeta: (meta, wrap) => this.importMetaInitialize(meta, { url }), - importModuleDynamically: (specifier, { url }, importAssertions) => { - debug('importModuleDynamically: %o', { specifier, url, Loader: this.constructor.name }); - return this.import(specifier, url, importAssertions); - }, - }); - - return module; - }; + const { ModuleWrap } = internalBinding('module_wrap'); + const moduleWrapper = new ModuleWrap(url, undefined, source, 0, 0); const ModuleJob = require('internal/modules/esm/module_job'); - const job = new ModuleJob(this, url, undefined, evalInstance, false, false); + const job = new ModuleJob(url, moduleWrapper, undefined, false, false); this.moduleMap.set(url, undefined, job); const { module } = await job.run(); @@ -155,9 +143,7 @@ class DefaultModuleLoader { this.moduleMap.set(url, undefined, job = job()); } - if (job === undefined) { - job = this.#createModuleJob(url, resolvedImportAssertions, parentURL, format); - } + job ??= this.#createModuleJob(url, resolvedImportAssertions, parentURL, format); return job; } @@ -173,26 +159,7 @@ class DefaultModuleLoader { * `resolve` hook * @returns {Promise} The (possibly pending) module job */ - #createModuleJob(url, importAssertions, parentURL, format) { - const moduleProvider = async (url, isMain) => { - const { - format: finalFormat, - responseURL, - source, - } = await this.load(url, { - format, - importAssertions, - }); - - const translator = getTranslators().get(finalFormat); - - if (!translator) { - throw new ERR_UNKNOWN_MODULE_FORMAT(finalFormat, responseURL); - } - - return FunctionPrototypeCall(translator, this, responseURL, source, isMain); - }; - + async #createModuleJob(url, importAssertions, parentURL, format) { const inspectBrk = ( parentURL === undefined && getOptionValue('--inspect-brk') @@ -202,12 +169,28 @@ class DefaultModuleLoader { process.send({ 'watch:import': [url] }); } + const { + format: finalFormat, + responseURL, + source, + } = await this.load(url, { + format, + importAssertions, + }); + + const translator = getTranslators().get(finalFormat); + + if (!translator) { + throw new ERR_UNKNOWN_MODULE_FORMAT(finalFormat, responseURL); + } + + const moduleWrapper = FunctionPrototypeCall(translator, this, responseURL, source, isMain); + const ModuleJob = require('internal/modules/esm/module_job'); const job = new ModuleJob( - this, url, + moduleWrapper, importAssertions, - moduleProvider, parentURL === undefined, inspectBrk, ); diff --git a/lib/internal/modules/esm/module_job.js b/lib/internal/modules/esm/module_job.js index 2cf2813a6dcf7f..309fc95dc2eed8 100644 --- a/lib/internal/modules/esm/module_job.js +++ b/lib/internal/modules/esm/module_job.js @@ -8,7 +8,6 @@ const { ObjectSetPrototypeOf, PromiseResolve, PromisePrototypeThen, - ReflectApply, RegExpPrototypeExec, RegExpPrototypeSymbolReplace, SafePromiseAllReturnArrayLike, @@ -20,6 +19,7 @@ const { } = primordials; const { ModuleWrap } = internalBinding('module_wrap'); +const { setCallbackForWrap } = require('internal/modules/esm/utils'); const { decorateErrorStack } = require('internal/util'); const { @@ -27,6 +27,9 @@ const { } = require('internal/source_map/source_map_cache'); const assert = require('internal/assert'); const resolvedPromise = PromiseResolve(); +let debug = require('internal/util/debuglog').debuglog('esm', (fn) => { + debug = fn; +}); const noop = FunctionPrototype; @@ -45,22 +48,43 @@ const isCommonJSGlobalLikeNotDefinedError = (errorMessage) => (globalLike) => errorMessage === `${globalLike} is not defined`, ); -/* A ModuleJob tracks the loading of a single Module, and the ModuleJobs of - * its dependencies, over time. */ +/** + * A ModuleJob tracks the loading of a single Module, and the ModuleJobs of its dependencies, over + * time. + */ class ModuleJob { - // `loader` is the Loader instance used for loading dependencies. - // `moduleProvider` is a function - constructor(loader, url, importAssertions = { __proto__: null }, - moduleProvider, isMain, inspectBrk) { - this.loader = loader; + /** + * Deep dependency jobs wrappers are instantiated, and module wrapper is instantiated. + */ + instantiated; + + module; + + constructor( + url, + moduleWrapper, + importAssertions = { __proto__: null }, + isMain, + inspectBrk, + ) { this.importAssertions = importAssertions; this.isMain = isMain; this.inspectBrk = inspectBrk; + this.modulePromise = moduleWrapper; + + debug('new ModuleJob(%o)', { url, importAssertions, isMain, inspectBrk }); - this.module = undefined; // Expose the promise to the ModuleWrap directly for linking below. // `this.module` is also filled in below. - this.modulePromise = ReflectApply(moduleProvider, loader, [url, isMain]); + + setCallbackForWrap(this.modulePromise, { + initializeImportMeta: (meta, wrap) => this.importMetaInitialize(meta, { url }), + importModuleDynamically: (specifier, { url }, importAssertions) => { + const moduleLoader = require('internal/process/esm_loader').esmLoader; + debug('importModuleDynamically: %o', { specifier, url, moduleLoader }); + return moduleLoader.import(specifier, url, importAssertions); + }, + }); // Wait for the ModuleWrap instance being linked with all dependencies. const link = async () => { @@ -73,7 +97,8 @@ class ModuleJob { // these `link` callbacks depending on each other. const dependencyJobs = []; const promises = this.module.link((specifier, assertions) => { - const job = this.loader.getModuleJob(specifier, url, assertions); + const moduleLoader = require('internal/process/esm_loader').esmLoader; + const job = moduleLoader.getModuleJob(specifier, url, assertions); ArrayPrototypePush(dependencyJobs, job); return job.modulePromise; }); @@ -88,16 +113,11 @@ class ModuleJob { // This promise is awaited later anyway, so silence // 'unhandled rejection' warnings. PromisePrototypeThen(this.linked, undefined, noop); - - // instantiated == deep dependency jobs wrappers are instantiated, - // and module wrapper is instantiated. - this.instantiated = undefined; } instantiate() { - if (this.instantiated === undefined) { - this.instantiated = this._instantiate(); - } + this.instantiated ??= this._instantiate(); + return this.instantiated; } @@ -139,7 +159,8 @@ class ModuleJob { const { 1: childSpecifier, 2: name } = RegExpPrototypeExec( /module '(.*)' does not provide an export named '(.+)'/, e.message); - const { url: childFileURL } = await this.loader.resolve( + const moduleLoader = require('internal/process/esm_loader').esmLoader; + const { url: childFileURL } = await moduleLoader.resolve( childSpecifier, parentFileUrl, ); let format; @@ -147,8 +168,7 @@ class ModuleJob { // This might throw for non-CommonJS modules because we aren't passing // in the import assertions and some formats require them; but we only // care about CommonJS for the purposes of this error message. - ({ format } = - await this.loader.load(childFileURL)); + ({ format } = await moduleLoader.load(childFileURL)); } catch { // Continue regardless of error. } diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js index 267d89f1d44730..6b87d5c5d12867 100644 --- a/lib/internal/modules/esm/translators.js +++ b/lib/internal/modules/esm/translators.js @@ -103,10 +103,6 @@ function errPath(url) { return url; } -async function importModuleDynamically(specifier, { url }, assertions) { - return asyncESM.esmLoader.import(specifier, url, assertions); -} - // Strategy for loading a standard JavaScript module. translators.set('module', async function moduleStrategy(url, source, isMain) { assertBufferSource(source, true, 'load'); @@ -114,11 +110,6 @@ translators.set('module', async function moduleStrategy(url, source, isMain) { maybeCacheSourceMap(url, source); debug(`Translating StandardModule ${url}`); const module = new ModuleWrap(url, undefined, source, 0, 0); - const { setCallbackForWrap } = require('internal/modules/esm/utils'); - setCallbackForWrap(module, { - initializeImportMeta: (meta, wrap) => this.importMetaInitialize(meta, { url }), - importModuleDynamically, - }); return module; });