PNG  IHDR;IDATxܻn0K )(pA 7LeG{ §㻢|ذaÆ 6lذaÆ 6lذaÆ 6lom$^yذag5bÆ 6lذaÆ 6lذa{ 6lذaÆ `}HFkm,mӪôô! x|'ܢ˟;E:9&ᶒ}{v]n&6 h_tڠ͵-ҫZ;Z$.Pkž)!o>}leQfJTu іچ\X=8Rن4`Vwl>nG^is"ms$ui?wbs[m6K4O.4%/bC%t Mז -lG6mrz2s%9s@-k9=)kB5\+͂Zsٲ Rn~GRC wIcIn7jJhۛNCS|j08yiHKֶۛkɈ+;SzL/F*\Ԕ#"5m2[S=gnaPeғL lذaÆ 6l^ḵaÆ 6lذaÆ 6lذa; _ذaÆ 6lذaÆ 6lذaÆ RIENDB` /* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const Cache = require("../Cache"); /** @typedef {import("webpack-sources").Source} Source */ /** @typedef {import("../Cache").Etag} Etag */ /** @typedef {import("../Compiler")} Compiler */ /** @typedef {import("../Module")} Module */ class MemoryWithGcCachePlugin { constructor({ maxGenerations }) { this._maxGenerations = maxGenerations; } /** * Apply the plugin * @param {Compiler} compiler the compiler instance * @returns {void} */ apply(compiler) { const maxGenerations = this._maxGenerations; /** @type {Map} */ const cache = new Map(); /** @type {Map} */ const oldCache = new Map(); let generation = 0; let cachePosition = 0; const logger = compiler.getInfrastructureLogger("MemoryWithGcCachePlugin"); compiler.hooks.afterDone.tap("MemoryWithGcCachePlugin", () => { generation++; let clearedEntries = 0; let lastClearedIdentifier; for (const [identifier, entry] of oldCache) { if (entry.until > generation) break; oldCache.delete(identifier); if (cache.get(identifier) === undefined) { cache.delete(identifier); clearedEntries++; lastClearedIdentifier = identifier; } } if (clearedEntries > 0 || oldCache.size > 0) { logger.log( `${cache.size - oldCache.size} active entries, ${ oldCache.size } recently unused cached entries${ clearedEntries > 0 ? `, ${clearedEntries} old unused cache entries removed e. g. ${lastClearedIdentifier}` : "" }` ); } let i = (cache.size / maxGenerations) | 0; let j = cachePosition >= cache.size ? 0 : cachePosition; cachePosition = j + i; for (const [identifier, entry] of cache) { if (j !== 0) { j--; continue; } if (entry !== undefined) { // We don't delete the cache entry, but set it to undefined instead // This reserves the location in the data table and avoids rehashing // when constantly adding and removing entries. // It will be deleted when removed from oldCache. cache.set(identifier, undefined); oldCache.delete(identifier); oldCache.set(identifier, { entry, until: generation + maxGenerations }); if (i-- === 0) break; } } }); compiler.cache.hooks.store.tap( { name: "MemoryWithGcCachePlugin", stage: Cache.STAGE_MEMORY }, (identifier, etag, data) => { cache.set(identifier, { etag, data }); } ); compiler.cache.hooks.get.tap( { name: "MemoryWithGcCachePlugin", stage: Cache.STAGE_MEMORY }, (identifier, etag, gotHandlers) => { const cacheEntry = cache.get(identifier); if (cacheEntry === null) { return null; } else if (cacheEntry !== undefined) { return cacheEntry.etag === etag ? cacheEntry.data : null; } const oldCacheEntry = oldCache.get(identifier); if (oldCacheEntry !== undefined) { const cacheEntry = oldCacheEntry.entry; if (cacheEntry === null) { oldCache.delete(identifier); cache.set(identifier, cacheEntry); return null; } else { if (cacheEntry.etag !== etag) return null; oldCache.delete(identifier); cache.set(identifier, cacheEntry); return cacheEntry.data; } } gotHandlers.push((result, callback) => { if (result === undefined) { cache.set(identifier, null); } else { cache.set(identifier, { etag, data: result }); } return callback(); }); } ); compiler.cache.hooks.shutdown.tap( { name: "MemoryWithGcCachePlugin", stage: Cache.STAGE_MEMORY }, () => { cache.clear(); oldCache.clear(); } ); } } module.exports = MemoryWithGcCachePlugin;