source: frontend/node_modules/webpack/lib/cache/MemoryWithGcCachePlugin.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 4.2 KB
RevLine 
[9af201e]1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const Cache = require("../Cache");
9
10/** @typedef {import("../Cache").Data} Data */
11/** @typedef {import("../Cache").Etag} Etag */
12/** @typedef {import("../Compiler")} Compiler */
13
14/**
15 * Defines the memory with gc cache plugin options type used by this module.
16 * @typedef {object} MemoryWithGcCachePluginOptions
17 * @property {number} maxGenerations max generations
18 */
19
20const PLUGIN_NAME = "MemoryWithGcCachePlugin";
21
22class MemoryWithGcCachePlugin {
23 /**
24 * Creates an instance of MemoryWithGcCachePlugin.
25 * @param {MemoryWithGcCachePluginOptions} options options
26 */
27 constructor({ maxGenerations }) {
28 this._maxGenerations = maxGenerations;
29 }
30
31 /**
32 * Applies the plugin by registering its hooks on the compiler.
33 * @param {Compiler} compiler the compiler instance
34 * @returns {void}
35 */
36 apply(compiler) {
37 const maxGenerations = this._maxGenerations;
38 /** @type {Map<string, { etag: Etag | null, data: Data } | undefined | null>} */
39 const cache = new Map();
40 /** @type {Map<string, { entry: { etag: Etag | null, data: Data } | null, until: number }>} */
41 const oldCache = new Map();
42 let generation = 0;
43 let cachePosition = 0;
44 const logger = compiler.getInfrastructureLogger(PLUGIN_NAME);
45 compiler.hooks.afterDone.tap(PLUGIN_NAME, () => {
46 generation++;
47 let clearedEntries = 0;
48 /** @type {undefined | string} */
49 let lastClearedIdentifier;
50 // Avoid coverage problems due indirect changes
51 /* istanbul ignore next */
52 for (const [identifier, entry] of oldCache) {
53 if (entry.until > generation) break;
54
55 oldCache.delete(identifier);
56 if (cache.get(identifier) === undefined) {
57 cache.delete(identifier);
58 clearedEntries++;
59 lastClearedIdentifier = identifier;
60 }
61 }
62 if (clearedEntries > 0 || oldCache.size > 0) {
63 logger.log(
64 `${cache.size - oldCache.size} active entries, ${
65 oldCache.size
66 } recently unused cached entries${
67 clearedEntries > 0
68 ? `, ${clearedEntries} old unused cache entries removed e. g. ${lastClearedIdentifier}`
69 : ""
70 }`
71 );
72 }
73 let i = (cache.size / maxGenerations) | 0;
74 let j = cachePosition >= cache.size ? 0 : cachePosition;
75 cachePosition = j + i;
76 for (const [identifier, entry] of cache) {
77 if (j !== 0) {
78 j--;
79 continue;
80 }
81 if (entry !== undefined) {
82 // We don't delete the cache entry, but set it to undefined instead
83 // This reserves the location in the data table and avoids rehashing
84 // when constantly adding and removing entries.
85 // It will be deleted when removed from oldCache.
86 cache.set(identifier, undefined);
87 oldCache.delete(identifier);
88 oldCache.set(identifier, {
89 entry,
90 until: generation + maxGenerations
91 });
92 if (i-- === 0) break;
93 }
94 }
95 });
96 compiler.cache.hooks.store.tap(
97 { name: PLUGIN_NAME, stage: Cache.STAGE_MEMORY },
98 (identifier, etag, data) => {
99 cache.set(identifier, { etag, data });
100 }
101 );
102 compiler.cache.hooks.get.tap(
103 { name: PLUGIN_NAME, stage: Cache.STAGE_MEMORY },
104 (identifier, etag, gotHandlers) => {
105 const cacheEntry = cache.get(identifier);
106 if (cacheEntry === null) {
107 return null;
108 } else if (cacheEntry !== undefined) {
109 return cacheEntry.etag === etag ? cacheEntry.data : null;
110 }
111 const oldCacheEntry = oldCache.get(identifier);
112 if (oldCacheEntry !== undefined) {
113 const cacheEntry = oldCacheEntry.entry;
114 if (cacheEntry === null) {
115 oldCache.delete(identifier);
116 cache.set(identifier, cacheEntry);
117 return null;
118 }
119 if (cacheEntry.etag !== etag) return null;
120 oldCache.delete(identifier);
121 cache.set(identifier, cacheEntry);
122 return cacheEntry.data;
123 }
124 gotHandlers.push((result, callback) => {
125 if (result === undefined) {
126 cache.set(identifier, null);
127 } else {
128 cache.set(identifier, { etag, data: result });
129 }
130 return callback();
131 });
132 }
133 );
134 compiler.cache.hooks.shutdown.tap(
135 { name: PLUGIN_NAME, stage: Cache.STAGE_MEMORY },
136 () => {
137 cache.clear();
138 oldCache.clear();
139 }
140 );
141 }
142}
143
144module.exports = MemoryWithGcCachePlugin;
Note: See TracBrowser for help on using the repository browser.