Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 21 additions & 13 deletions lib/internal/modules/cjs/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ let { startTimer, endTimer } = debugWithTimer('module_timer', (start, end) => {
const { tracingChannel } = require('diagnostics_channel');
const onRequire = getLazy(() => tracingChannel('module.require'));

const relativeResolveCache = { __proto__: null };
const relativeResolveCache = new SafeMap();

let requireDepth = 0;
let isPreloading = false;
Expand Down Expand Up @@ -1273,17 +1273,23 @@ function loadBuiltinWithHooks(id, url, format) {
* @returns {object}
*/
Module._load = function(request, parent, isMain, internalOptions = kEmptyObject) {
let relResolveCacheIdentifier;
let relResolveCacheByDir;
if (parent) {
debug('Module._load REQUEST %s parent: %s', request, parent.id);
// Fast path for (lazy loaded) modules in the same directory. The indirect
// caching is required to allow cache invalidation without changing the old
// cache key names.
relResolveCacheIdentifier = `${parent.path}\x00${request}`;
const filename = relativeResolveCache[relResolveCacheIdentifier];
reportModuleToWatchMode(filename);
reportModuleToWatchModeFromWorker(filename);
// Fast path for (lazy loaded) modules in the same directory. Keyed by
// parent directory and then request, so no concatenated cache key
// string is allocated per require() call.
relResolveCacheByDir = relativeResolveCache.get(parent.path);
if (relResolveCacheByDir === undefined) {
// A plain object handles dynamically built specifier strings
// better than a Map here.
relResolveCacheByDir = { __proto__: null };
relativeResolveCache.set(parent.path, relResolveCacheByDir);
}
const filename = relResolveCacheByDir[request];
if (filename !== undefined) {
reportModuleToWatchMode(filename);
reportModuleToWatchModeFromWorker(filename);
const cachedModule = Module._cache[filename];
if (cachedModule !== undefined) {
updateChildren(parent, cachedModule, true);
Expand All @@ -1292,7 +1298,7 @@ Module._load = function(request, parent, isMain, internalOptions = kEmptyObject)
}
return cachedModule.exports;
}
delete relativeResolveCache[relResolveCacheIdentifier];
delete relResolveCacheByDir[request];
}
}

Expand Down Expand Up @@ -1395,8 +1401,8 @@ Module._load = function(request, parent, isMain, internalOptions = kEmptyObject)
module[kFormat] ??= format;
}

if (parent !== undefined) {
relativeResolveCache[relResolveCacheIdentifier] = filename;
if (relResolveCacheByDir !== undefined) {
relResolveCacheByDir[request] = filename;
}

let threw = true;
Expand All @@ -1407,7 +1413,9 @@ Module._load = function(request, parent, isMain, internalOptions = kEmptyObject)
if (threw) {
delete Module._cache[filename];
if (parent !== undefined) {
delete relativeResolveCache[relResolveCacheIdentifier];
if (relResolveCacheByDir !== undefined) {
delete relResolveCacheByDir[request];
}
const children = parent?.children;
if (ArrayIsArray(children)) {
const index = ArrayPrototypeIndexOf(children, module);
Expand Down
Loading