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.
This commit is contained in:
Tobias Koppers 2021-07-01 11:46:59 +02:00
parent 7c4bd529fc
commit b443555501
3 changed files with 27 additions and 3 deletions

View File

@ -260,6 +260,8 @@ class Compiler {
/** @type {Compilation} */
this._lastCompilation = undefined;
/** @type {NormalModuleFactory} */
this._lastNormalModuleFactory = undefined;
/** @private @type {WeakMap<Source, { sizeOnlySource: SizeOnlySource, writtenTo: Map<string, number> }>} */
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<Stats>} 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);
});
}

View File

@ -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<string, WeakMap<Object, Generator>>} */
this.generatorCache = new Map();
/** @type {WeakSet<Module>} */
this._restoredUnsafeCacheEntries = new WeakSet();
/** @type {Set<Module>} */
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

1
types.d.ts vendored
View File

@ -7198,6 +7198,7 @@ declare abstract class NormalModuleFactory extends ModuleFactory {
fs: InputFileSystem;
parserCache: Map<string, WeakMap<Object, any>>;
generatorCache: Map<string, WeakMap<Object, Generator>>;
cleanupForCache(): void;
resolveResource(
contextInfo?: any,
context?: any,