Skip to content

Commit 9a7c87d

Browse files
guybedfordBethGriggs
authored andcommitted
module: use cjsCache over esm injection
PR-URL: #34605 Reviewed-By: Bradley Farias <[email protected]> Reviewed-By: Rich Trott <[email protected]>
1 parent 093a4b0 commit 9a7c87d

File tree

3 files changed

+22
-53
lines changed

3 files changed

+22
-53
lines changed

lib/internal/modules/cjs/loader.js

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,7 @@ const {
112112
} = require('internal/util/types');
113113

114114
const asyncESM = require('internal/process/esm_loader');
115-
const ModuleJob = require('internal/modules/esm/module_job');
116-
const { ModuleWrap, kInstantiated } = internalBinding('module_wrap');
115+
const { kEvaluated } = internalBinding('module_wrap');
117116
const {
118117
encodedSepRegEx,
119118
packageInternalResolve
@@ -1101,29 +1100,13 @@ Module.prototype.load = function(filename) {
11011100
this.loaded = true;
11021101

11031102
const ESMLoader = asyncESM.ESMLoader;
1104-
const url = `${pathToFileURL(filename)}`;
1105-
const module = ESMLoader.moduleMap.get(url);
11061103
// Create module entry at load time to snapshot exports correctly
11071104
const exports = this.exports;
1108-
// Called from cjs translator
1109-
if (module !== undefined && module.module !== undefined) {
1110-
if (module.module.getStatus() >= kInstantiated)
1111-
module.module.setExport('default', exports);
1112-
} else {
1113-
// Preemptively cache
1114-
// We use a function to defer promise creation for async hooks.
1115-
ESMLoader.moduleMap.set(
1116-
url,
1117-
// Module job creation will start promises.
1118-
// We make it a function to lazily trigger those promises
1119-
// for async hooks compatibility.
1120-
() => new ModuleJob(ESMLoader, url, () =>
1121-
new ModuleWrap(url, undefined, ['default'], function() {
1122-
this.setExport('default', exports);
1123-
})
1124-
, false /* isMain */, false /* inspectBrk */)
1125-
);
1126-
}
1105+
// Preemptively cache
1106+
if ((module?.module === undefined ||
1107+
module.module.getStatus() < kEvaluated) &&
1108+
!ESMLoader.cjsCache.has(this))
1109+
ESMLoader.cjsCache.set(this, exports);
11271110
};
11281111

11291112

lib/internal/modules/esm/loader.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ require('internal/modules/cjs/loader');
66
const {
77
FunctionPrototypeBind,
88
ObjectSetPrototypeOf,
9-
SafeMap,
9+
SafeWeakMap,
1010
} = primordials;
1111

1212
const {
@@ -47,7 +47,7 @@ class Loader {
4747
this.moduleMap = new ModuleMap();
4848

4949
// Map of already-loaded CJS modules to use
50-
this.cjsCache = new SafeMap();
50+
this.cjsCache = new SafeWeakMap();
5151

5252
// This hook is called before the first root module is imported. It's a
5353
// function that returns a piece of code that runs as a sloppy-mode script.

lib/internal/modules/esm/translators.js

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ const experimentalImportMetaResolve =
4848
const translators = new SafeMap();
4949
exports.translators = translators;
5050

51+
const asyncESM = require('internal/process/esm_loader');
52+
5153
let DECODER = null;
5254
function assertBufferSource(body, allowString, hookName) {
5355
if (allowString && typeof body === 'string') {
@@ -80,21 +82,14 @@ function errPath(url) {
8082
return url;
8183
}
8284

83-
let esmLoader;
8485
async function importModuleDynamically(specifier, { url }) {
85-
if (!esmLoader) {
86-
esmLoader = require('internal/process/esm_loader').ESMLoader;
87-
}
88-
return esmLoader.import(specifier, url);
86+
return asyncESM.ESMLoader.import(specifier, url);
8987
}
9088

9189
function createImportMetaResolve(defaultParentUrl) {
9290
return async function resolve(specifier, parentUrl = defaultParentUrl) {
93-
if (!esmLoader) {
94-
esmLoader = require('internal/process/esm_loader').ESMLoader;
95-
}
9691
return PromisePrototypeCatch(
97-
esmLoader.resolve(specifier, parentUrl),
92+
asyncESM.ESMLoader.resolve(specifier, parentUrl),
9893
(error) => (
9994
error.code === 'ERR_UNSUPPORTED_DIR_IMPORT' ?
10095
error.url : PromiseReject(error))
@@ -132,27 +127,18 @@ const isWindows = process.platform === 'win32';
132127
const winSepRegEx = /\//g;
133128
translators.set('commonjs', function commonjsStrategy(url, isMain) {
134129
debug(`Translating CJSModule ${url}`);
135-
const pathname = internalURLModule.fileURLToPath(new URL(url));
136-
const cached = this.cjsCache.get(url);
137-
if (cached) {
138-
this.cjsCache.delete(url);
139-
return cached;
140-
}
141-
const module = CJSModule._cache[
142-
isWindows ? StringPrototypeReplace(pathname, winSepRegEx, '\\') : pathname
143-
];
144-
if (module && module.loaded) {
145-
const exports = module.exports;
146-
return new ModuleWrap(url, undefined, ['default'], function() {
147-
this.setExport('default', exports);
148-
});
149-
}
150130
return new ModuleWrap(url, undefined, ['default'], function() {
151131
debug(`Loading CJSModule ${url}`);
152-
// We don't care about the return val of _load here because Module#load
153-
// will handle it for us by checking the loader registry and filling the
154-
// exports like above
155-
CJSModule._load(pathname, undefined, isMain);
132+
const pathname = internalURLModule.fileURLToPath(new URL(url));
133+
let exports;
134+
const cachedModule = CJSModule._cache[pathname];
135+
if (cachedModule && asyncESM.ESMLoader.cjsCache.has(cachedModule)) {
136+
exports = asyncESM.ESMLoader.cjsCache.get(cachedModule);
137+
asyncESM.ESMLoader.cjsCache.delete(cachedModule);
138+
} else {
139+
exports = CJSModule._load(pathname, undefined, isMain);
140+
}
141+
this.setExport('default', exports);
156142
});
157143
});
158144

0 commit comments

Comments
 (0)