From 9964a8283f86b7429e16aac8b044df6aed1ce7ad Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Mon, 22 Oct 2018 09:02:39 +0200 Subject: [PATCH] fix resolver cache --- lib/ResolverFactory.js | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/lib/ResolverFactory.js b/lib/ResolverFactory.js index 3fb3a6c7a..4c70555e7 100644 --- a/lib/ResolverFactory.js +++ b/lib/ResolverFactory.js @@ -8,6 +8,8 @@ const Factory = require("enhanced-resolve").ResolverFactory; const { HookMap, SyncHook, SyncWaterfallHook } = require("tapable"); +/** @typedef {import("enhanced-resolve/lib/Resolver")} Resolver */ + module.exports = class ResolverFactory { constructor() { this.hooks = Object.freeze({ @@ -16,21 +18,43 @@ module.exports = class ResolverFactory { ), resolver: new HookMap(() => new SyncHook(["resolver", "resolveOptions"])) }); - this.cache1 = new WeakMap(); - this.cache2 = new Map(); + /** @type {Map, stringified: Map }>} */ + this.cache = new Map(); } + /** + * @param {string} type type of resolver + * @param {Object} resolveOptions options + * @returns {Resolver} the resolver + */ get(type, resolveOptions) { - const cachedResolver = this.cache1.get(resolveOptions); - if (cachedResolver) return cachedResolver(); - const ident = `${type}|${JSON.stringify(resolveOptions)}`; - const resolver = this.cache2.get(ident); - if (resolver) return resolver; + let typedCaches = this.cache.get(type); + if (!typedCaches) { + typedCaches = { + direct: new WeakMap(), + stringified: new Map() + }; + this.cache.set(type, typedCaches); + } + const cachedResolver = typedCaches.direct.get(resolveOptions); + if (cachedResolver) return cachedResolver; + const ident = JSON.stringify(resolveOptions); + const resolver = typedCaches.stringified.get(ident); + if (resolver) { + typedCaches.direct.set(resolveOptions, resolver); + return resolver; + } const newResolver = this._create(type, resolveOptions); - this.cache2.set(ident, newResolver); + typedCaches.direct.set(resolveOptions, newResolver); + typedCaches.stringified.set(ident, newResolver); return newResolver; } + /** + * @param {string} type type of resolver + * @param {Object} resolveOptions options + * @returns {Resolver} the resolver + */ _create(type, resolveOptions) { resolveOptions = this.hooks.resolveOptions.for(type).call(resolveOptions); const resolver = Factory.createResolver(resolveOptions);