mirror of
https://github.com/nodejs/node.git
synced 2025-08-15 13:48:44 +02:00
module: refator ESM loader for adding future synchronous hooks
This lays the foundation for supporting synchronous hooks proposed in https://github.com/nodejs/loaders/pull/198 for ESM. - Corrects and adds several JSDoc comments for internal functions of the ESM loader, as well as explaining how require() for import CJS work in the special resolve/load paths. This doesn't consolidate it with import in require(esm) yet due to caching differences, which is left as a TODO. - The moduleProvider passed into ModuleJob is replaced as moduleOrModulePromise, we call the translators directly in the ESM loader and verify it right after loading for clarity. - Reuse a few refactored out helpers for require(esm) in getModuleJobForRequire(). PR-URL: https://github.com/nodejs/node/pull/54769 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
7014e50ca3
commit
3ac5b49d85
3 changed files with 266 additions and 158 deletions
|
@ -8,7 +8,6 @@ const {
|
|||
ObjectSetPrototypeOf,
|
||||
PromisePrototypeThen,
|
||||
PromiseResolve,
|
||||
ReflectApply,
|
||||
RegExpPrototypeExec,
|
||||
RegExpPrototypeSymbolReplace,
|
||||
SafePromiseAllReturnArrayLike,
|
||||
|
@ -56,13 +55,12 @@ const isCommonJSGlobalLikeNotDefinedError = (errorMessage) =>
|
|||
);
|
||||
|
||||
class ModuleJobBase {
|
||||
constructor(url, importAttributes, moduleWrapMaybePromise, isMain, inspectBrk) {
|
||||
constructor(url, importAttributes, isMain, inspectBrk) {
|
||||
this.importAttributes = importAttributes;
|
||||
this.isMain = isMain;
|
||||
this.inspectBrk = inspectBrk;
|
||||
|
||||
this.url = url;
|
||||
this.module = moduleWrapMaybePromise;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,21 +68,29 @@ class ModuleJobBase {
|
|||
* its dependencies, over time. */
|
||||
class ModuleJob extends ModuleJobBase {
|
||||
#loader = null;
|
||||
// `loader` is the Loader instance used for loading dependencies.
|
||||
constructor(loader, url, importAttributes = { __proto__: null },
|
||||
moduleProvider, isMain, inspectBrk, sync = false) {
|
||||
const modulePromise = ReflectApply(moduleProvider, loader, [url, isMain]);
|
||||
super(url, importAttributes, modulePromise, isMain, inspectBrk);
|
||||
this.#loader = loader;
|
||||
// Expose the promise to the ModuleWrap directly for linking below.
|
||||
// `this.module` is also filled in below.
|
||||
this.modulePromise = modulePromise;
|
||||
|
||||
if (sync) {
|
||||
this.module = this.modulePromise;
|
||||
/**
|
||||
* @param {ModuleLoader} loader The ESM loader.
|
||||
* @param {string} url URL of the module to be wrapped in ModuleJob.
|
||||
* @param {ImportAttributes} importAttributes Import attributes from the import statement.
|
||||
* @param {ModuleWrap|Promise<ModuleWrap>} moduleOrModulePromise Translated ModuleWrap for the module.
|
||||
* @param {boolean} isMain Whether the module is the entry point.
|
||||
* @param {boolean} inspectBrk Whether this module should be evaluated with the
|
||||
* first line paused in the debugger (because --inspect-brk is passed).
|
||||
* @param {boolean} isForRequireInImportedCJS Whether this is created for require() in imported CJS.
|
||||
*/
|
||||
constructor(loader, url, importAttributes = { __proto__: null },
|
||||
moduleOrModulePromise, isMain, inspectBrk, isForRequireInImportedCJS = false) {
|
||||
super(url, importAttributes, isMain, inspectBrk);
|
||||
this.#loader = loader;
|
||||
|
||||
// Expose the promise to the ModuleWrap directly for linking below.
|
||||
if (isForRequireInImportedCJS) {
|
||||
this.module = moduleOrModulePromise;
|
||||
assert(this.module instanceof ModuleWrap);
|
||||
this.modulePromise = PromiseResolve(this.module);
|
||||
} else {
|
||||
this.modulePromise = PromiseResolve(this.modulePromise);
|
||||
this.modulePromise = moduleOrModulePromise;
|
||||
}
|
||||
|
||||
// Promise for the list of all dependencyJobs.
|
||||
|
@ -123,7 +129,7 @@ class ModuleJob extends ModuleJobBase {
|
|||
for (let idx = 0; idx < moduleRequests.length; idx++) {
|
||||
const { specifier, attributes } = moduleRequests[idx];
|
||||
|
||||
const dependencyJobPromise = this.#loader.getModuleJob(
|
||||
const dependencyJobPromise = this.#loader.getModuleJobForImport(
|
||||
specifier, this.url, attributes,
|
||||
);
|
||||
const modulePromise = PromisePrototypeThen(dependencyJobPromise, (job) => {
|
||||
|
@ -288,14 +294,33 @@ class ModuleJob extends ModuleJobBase {
|
|||
}
|
||||
}
|
||||
|
||||
// This is a fully synchronous job and does not spawn additional threads in any way.
|
||||
// All the steps are ensured to be synchronous and it throws on instantiating
|
||||
// an asynchronous graph.
|
||||
/**
|
||||
* This is a fully synchronous job and does not spawn additional threads in any way.
|
||||
* All the steps are ensured to be synchronous and it throws on instantiating
|
||||
* an asynchronous graph. It also disallows CJS <-> ESM cycles.
|
||||
*
|
||||
* This is used for ES modules loaded via require(esm). Modules loaded by require() in
|
||||
* imported CJS are handled by ModuleJob with the isForRequireInImportedCJS set to true instead.
|
||||
* The two currently have different caching behaviors.
|
||||
* TODO(joyeecheung): consolidate this with the isForRequireInImportedCJS variant of ModuleJob.
|
||||
*/
|
||||
class ModuleJobSync extends ModuleJobBase {
|
||||
#loader = null;
|
||||
|
||||
/**
|
||||
* @param {ModuleLoader} loader The ESM loader.
|
||||
* @param {string} url URL of the module to be wrapped in ModuleJob.
|
||||
* @param {ImportAttributes} importAttributes Import attributes from the import statement.
|
||||
* @param {ModuleWrap} moduleWrap Translated ModuleWrap for the module.
|
||||
* @param {boolean} isMain Whether the module is the entry point.
|
||||
* @param {boolean} inspectBrk Whether this module should be evaluated with the
|
||||
* first line paused in the debugger (because --inspect-brk is passed).
|
||||
*/
|
||||
constructor(loader, url, importAttributes, moduleWrap, isMain, inspectBrk) {
|
||||
super(url, importAttributes, moduleWrap, isMain, inspectBrk, true);
|
||||
super(url, importAttributes, isMain, inspectBrk, true);
|
||||
|
||||
this.#loader = loader;
|
||||
this.module = moduleWrap;
|
||||
|
||||
assert(this.module instanceof ModuleWrap);
|
||||
// Store itself into the cache first before linking in case there are circular
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue