-
-
Notifications
You must be signed in to change notification settings - Fork 33.4k
Open
Labels
loadersIssues and PRs related to ES module loadersIssues and PRs related to ES module loaders
Description
This was an idea discussed in the loaders group a few times in the past as well as in the last collaboration summit. Opening an issue to track it properly.
The high-level idea is something like this:
module.register = function(specifier, parentURL, options) {
loader.hooksProxy.makeSyncRequest('register', specifier, parentURL, options);
module.registerHooks({
resolve(specifier, context, nextResolve) {
const result = loader.hooksProxy.makeSyncRequest('resolve', specifier, context);
return result.shortCircuit ? result : nextResolve(specifier, context);
}
load(url, context, nextLoad) {
const result = loader.hooksProxy.makeSyncRequest('load', url, context);
return result.shortCircuit ? result : nextLoad(url, context);
}
});
}
Then we will be able to:
- Eliminate the races in ESM cache handling when
require(esm)
needs the linking to be synchronous butimport esm
may populate an asynchronous linking job in the cache. There were multiple band-aids applied to work around this, like esm: link modules synchronously when no async loader hooks are used #59519 and module: handle cached linked async jobs in require(esm) #57187, but to fully eliminate the races, this would be necessary to finish Tracking Issue: Syncify the ESM Loader #55782 - Go back to using the authentic
require()
in imported CJS instead of re-inventing a separaterequire()
and eliminate its quirks, which currently includes- Invoking the hooks twice for CJS, the additional one from within the re-invented require
node/lib/internal/modules/esm/translators.js
Line 151 in af5d1c9
const job = cascadedLoader.getModuleJobForRequireInImportedCJS(specifier, url, importAttributes); - The re-invented
require
lacks a lot of properties likerequire.cache
, which is a documented caveat https://nodejs.org/api/module.html#caveat-in-the-asynchronous-load-hook - The source code for CJS ended up being loaded twice
node/lib/internal/modules/esm/load.js
Lines 97 to 99 in 0fd1ecd
// For backward compatibility reasons, we need to discard the source in // order for the CJS loader to re-fetch it. source = null; - As a side-effect of the previous quirk, when the module format is CJS, the user hook has to also deal with
source
beingnull
and usually also has to load it twice or more, like what's being done in import-in-the-middle, see ERR_INVALID_RETURN_PROPERTY_VALUE when using module.register and module.registerHooks #57327 (comment)
- Invoking the hooks twice for CJS, the additional one from within the re-invented require
- Potentially this means
module.register
can be a user-land helper that we can publish as a separate npm package and version independently.
Refs: #57327
Refs: #55808
Refs: #52697
Refs: #56241
Refs: #55782
cc @nodejs/loaders
jsumners-nr, timokoessler, mcollina, legendecas and GeoffreyParrier
Metadata
Metadata
Assignees
Labels
loadersIssues and PRs related to ES module loadersIssues and PRs related to ES module loaders