Skip to content

Commit 3ad146d

Browse files
guybedfordcodebytere
authored andcommittedOct 1, 2020
module: use cjsCache over esm injection
PR-URL: nodejs/node#34605 Backport-PR-URL: nodejs/node#35385 Reviewed-By: Bradley Farias <bradley.meck@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
1 parent 00aa935 commit 3ad146d

File tree

3 files changed

+22
-53
lines changed

3 files changed

+22
-53
lines changed
 

‎lib/internal/modules/cjs/loader.js

+6-23
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,7 @@ const {
104104
} = require('internal/constants');
105105

106106
const asyncESM = require('internal/process/esm_loader');
107-
const ModuleJob = require('internal/modules/esm/module_job');
108-
const { ModuleWrap, kInstantiated } = internalBinding('module_wrap');
107+
const { kEvaluated } = internalBinding('module_wrap');
109108
const {
110109
encodedSepRegEx,
111110
packageInternalResolve
@@ -1039,29 +1038,13 @@ Module.prototype.load = function(filename) {
10391038
this.loaded = true;
10401039

10411040
const ESMLoader = asyncESM.ESMLoader;
1042-
const url = `${pathToFileURL(filename)}`;
1043-
const module = ESMLoader.moduleMap.get(url);
10441041
// Create module entry at load time to snapshot exports correctly
10451042
const exports = this.exports;
1046-
// Called from cjs translator
1047-
if (module !== undefined && module.module !== undefined) {
1048-
if (module.module.getStatus() >= kInstantiated)
1049-
module.module.setExport('default', exports);
1050-
} else {
1051-
// Preemptively cache
1052-
// We use a function to defer promise creation for async hooks.
1053-
ESMLoader.moduleMap.set(
1054-
url,
1055-
// Module job creation will start promises.
1056-
// We make it a function to lazily trigger those promises
1057-
// for async hooks compatibility.
1058-
() => new ModuleJob(ESMLoader, url, () =>
1059-
new ModuleWrap(url, undefined, ['default'], function() {
1060-
this.setExport('default', exports);
1061-
})
1062-
, false /* isMain */, false /* inspectBrk */)
1063-
);
1064-
}
1043+
// Preemptively cache
1044+
if ((module?.module === undefined ||
1045+
module.module.getStatus() < kEvaluated) &&
1046+
!ESMLoader.cjsCache.has(this))
1047+
ESMLoader.cjsCache.set(this, exports);
10651048
};
10661049

10671050

‎lib/internal/modules/esm/loader.js

+2-2
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 {
@@ -52,7 +52,7 @@ class Loader {
5252
this.moduleMap = new ModuleMap();
5353

5454
// Map of already-loaded CJS modules to use
55-
this.cjsCache = new SafeMap();
55+
this.cjsCache = new SafeWeakMap();
5656

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

‎lib/internal/modules/esm/translators.js

+14-28
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)
Failed to load comments.