Skip to content

Commit

Permalink
WIP: remove disentangle loader from ModuleJob
Browse files Browse the repository at this point in the history
  • Loading branch information
JakobJingleheimer committed Jun 12, 2023
1 parent 28055ff commit 9b4c85c
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 70 deletions.
63 changes: 23 additions & 40 deletions lib/internal/modules/esm/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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;
}
Expand All @@ -173,26 +159,7 @@ class DefaultModuleLoader {
* `resolve` hook
* @returns {Promise<ModuleJob>} 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')
Expand All @@ -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,
);
Expand Down
62 changes: 41 additions & 21 deletions lib/internal/modules/esm/module_job.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ const {
ObjectSetPrototypeOf,
PromiseResolve,
PromisePrototypeThen,
ReflectApply,
RegExpPrototypeExec,
RegExpPrototypeSymbolReplace,
SafePromiseAllReturnArrayLike,
Expand All @@ -20,13 +19,17 @@ const {
} = primordials;

const { ModuleWrap } = internalBinding('module_wrap');
const { setCallbackForWrap } = require('internal/modules/esm/utils');

const { decorateErrorStack } = require('internal/util');
const {
getSourceMapsEnabled,
} = 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;

Expand All @@ -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 () => {
Expand All @@ -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;
});
Expand All @@ -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;
}

Expand Down Expand Up @@ -139,16 +159,16 @@ 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;
try {
// 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.
}
Expand Down
9 changes: 0 additions & 9 deletions lib/internal/modules/esm/translators.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,22 +103,13 @@ 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');
source = stringify(source);
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;
});

Expand Down

0 comments on commit 9b4c85c

Please sign in to comment.