diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index 537258450f5333..8c5cf89de341b5 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -79,6 +79,8 @@ const { const isWindows = process.platform === 'win32'; +const relativeResolveCache = Object.create(null); + let requireDepth = 0; let statCache = null; function stat(filename) { @@ -568,14 +570,28 @@ Module._resolveLookupPaths = function(request, parent, newReturn) { // Then have it load the file contents before returning its exports // object. Module._load = function(request, parent, isMain) { + let relResolveCacheIdentifier; 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]; + if (filename !== undefined) { + const cachedModule = Module._cache[filename]; + if (cachedModule !== undefined) { + updateChildren(parent, cachedModule, true); + return cachedModule.exports; + } + delete relativeResolveCache[relResolveCacheIdentifier]; + } } const filename = Module._resolveFilename(request, parent, isMain); const cachedModule = Module._cache[filename]; - if (cachedModule) { + if (cachedModule !== undefined) { updateChildren(parent, cachedModule, true); return cachedModule.exports; } @@ -595,6 +611,9 @@ Module._load = function(request, parent, isMain) { } Module._cache[filename] = module; + if (parent !== undefined) { + relativeResolveCache[relResolveCacheIdentifier] = filename; + } let threw = true; try { @@ -603,6 +622,9 @@ Module._load = function(request, parent, isMain) { } finally { if (threw) { delete Module._cache[filename]; + if (parent !== undefined) { + delete relativeResolveCache[relResolveCacheIdentifier]; + } } }