From b443555501b1002fc63a4af0bedd3297cdc1f562 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Thu, 1 Jul 2021 11:46:59 +0200 Subject: [PATCH] this is a workaround to remove compilation-specific references from modules in the unsafe cache I'm not proud of this solution, but it fixes it for now Long term we might move these kind of references out of the module into some kind of compilation/module graph specific store. But that's not yet possible for backward-compat reasons. --- lib/Compiler.js | 15 ++++++++++++++- lib/NormalModuleFactory.js | 14 ++++++++++++-- types.d.ts | 1 + 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/Compiler.js b/lib/Compiler.js index 84d7d0208..d32c009e2 100644 --- a/lib/Compiler.js +++ b/lib/Compiler.js @@ -260,6 +260,8 @@ class Compiler { /** @type {Compilation} */ this._lastCompilation = undefined; + /** @type {NormalModuleFactory} */ + this._lastNormalModuleFactory = undefined; /** @private @type {WeakMap }>} */ this._assetEmittingSourceCache = new WeakMap(); @@ -375,6 +377,14 @@ class Compiler { } } + // TODO webpack 6: solve this in a better way + _cleanupLastNormalModuleFactory() { + if (this._lastNormalModuleFactory !== undefined) { + this._lastNormalModuleFactory.cleanupForCache(); + this._lastNormalModuleFactory = undefined; + } + } + /** * @param {WatchOptions} watchOptions the watcher's options * @param {Callback} handler signals when the call finishes @@ -1036,6 +1046,7 @@ ${other}`); } createNormalModuleFactory() { + this._cleanupLastNormalModuleFactory(); const normalModuleFactory = new NormalModuleFactory({ context: this.options.context, fs: this.inputFileSystem, @@ -1044,6 +1055,7 @@ ${other}`); associatedObjectForCache: this.root, layers: this.options.experiments.layers }); + this._lastNormalModuleFactory = normalModuleFactory; this.hooks.normalModuleFactory.call(normalModuleFactory); return normalModuleFactory; } @@ -1122,8 +1134,9 @@ ${other}`); if (err) return callback(err); // Get rid of reference to last compilation to avoid leaking memory // We can't run this._cleanupLastCompilation() as the Stats to this compilation - // might be still in use. We try to get rid for the reference to the cache instead. + // might be still in use. We try to get rid of the reference to the cache instead. this._lastCompilation = undefined; + this._lastNormalModuleFactory = undefined; this.cache.shutdown(callback); }); } diff --git a/lib/NormalModuleFactory.js b/lib/NormalModuleFactory.js index 4f1eaf6f6..402156fb6 100644 --- a/lib/NormalModuleFactory.js +++ b/lib/NormalModuleFactory.js @@ -13,8 +13,10 @@ const { SyncHook, HookMap } = require("tapable"); +const ChunkGraph = require("./ChunkGraph"); const Module = require("./Module"); const ModuleFactory = require("./ModuleFactory"); +const ModuleGraph = require("./ModuleGraph"); const NormalModule = require("./NormalModule"); const BasicEffectRulePlugin = require("./rules/BasicEffectRulePlugin"); const BasicMatcherRulePlugin = require("./rules/BasicMatcherRulePlugin"); @@ -257,8 +259,8 @@ class NormalModuleFactory extends ModuleFactory { this.parserCache = new Map(); /** @type {Map>} */ this.generatorCache = new Map(); - /** @type {WeakSet} */ - this._restoredUnsafeCacheEntries = new WeakSet(); + /** @type {Set} */ + this._restoredUnsafeCacheEntries = new Set(); const cacheParseResource = parseResource.bindCache( associatedObjectForCache @@ -661,6 +663,14 @@ class NormalModuleFactory extends ModuleFactory { ); } + cleanupForCache() { + for (const module of this._restoredUnsafeCacheEntries) { + ChunkGraph.clearChunkGraphForModule(module); + ModuleGraph.clearModuleGraphForModule(module); + module.cleanupForCache(); + } + } + /** * @param {ModuleFactoryCreateData} data data object * @param {function(Error=, ModuleFactoryResult=): void} callback callback diff --git a/types.d.ts b/types.d.ts index 52533f058..16eaab94a 100644 --- a/types.d.ts +++ b/types.d.ts @@ -7198,6 +7198,7 @@ declare abstract class NormalModuleFactory extends ModuleFactory { fs: InputFileSystem; parserCache: Map>; generatorCache: Map>; + cleanupForCache(): void; resolveResource( contextInfo?: any, context?: any,