source: frontend/node_modules/webpack/lib/util/StackedCacheMap.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.0 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8/**
9 * The StackedCacheMap is a data structure designed as an alternative to a Map
10 * in situations where you need to handle multiple item additions and
11 * frequently access the largest map.
12 *
13 * It is particularly optimized for efficiently adding multiple items
14 * at once, which can be achieved using the `addAll` method.
15 *
16 * It has a fallback Map that is used when the map to be added is mutable.
17 *
18 * Note: `delete` and `has` are not supported for performance reasons.
19 * @example
20 * ```js
21 * const map = new StackedCacheMap();
22 * map.addAll(new Map([["a", 1], ["b", 2]]), true);
23 * map.addAll(new Map([["c", 3], ["d", 4]]), true);
24 * map.get("a"); // 1
25 * map.get("d"); // 4
26 * for (const [key, value] of map) {
27 * console.log(key, value);
28 * }
29 * ```
30 * @template K
31 * @template V
32 */
33class StackedCacheMap {
34 /**
35 * Initializes the mutable fallback map and the stack of immutable cache
36 * layers.
37 */
38 constructor() {
39 /** @type {Map<K, V>} */
40 this.map = new Map();
41 /** @type {ReadonlyMap<K, V>[]} */
42 this.stack = [];
43 }
44
45 /**
46 * Adds another cache layer. Immutable maps are retained by reference and
47 * reordered so larger layers are checked first, while mutable maps are
48 * copied into the fallback map.
49 * @param {ReadonlyMap<K, V>} map map to add
50 * @param {boolean=} immutable if 'map' is immutable and StackedCacheMap can keep referencing it
51 */
52 addAll(map, immutable) {
53 if (immutable) {
54 this.stack.push(map);
55
56 // largest map should go first
57 for (let i = this.stack.length - 1; i > 0; i--) {
58 const beforeLast = this.stack[i - 1];
59 if (beforeLast.size >= map.size) break;
60 this.stack[i] = beforeLast;
61 this.stack[i - 1] = map;
62 }
63 } else {
64 for (const [key, value] of map) {
65 this.map.set(key, value);
66 }
67 }
68 }
69
70 /**
71 * Stores or overrides a value in the mutable fallback map.
72 * @param {K} item the key of the element to add
73 * @param {V} value the value of the element to add
74 * @returns {void}
75 */
76 set(item, value) {
77 this.map.set(item, value);
78 }
79
80 /**
81 * Rejects deletions because this data structure is optimized for append-only
82 * cache layers.
83 * @param {K} item the item to delete
84 * @returns {void}
85 */
86 delete(item) {
87 throw new Error("Items can't be deleted from a StackedCacheMap");
88 }
89
90 /**
91 * Rejects `has` checks because they would force the same layered lookup work
92 * as `get` without returning the cached value.
93 * @param {K} item the item to test
94 * @returns {boolean} true if the item exists in this set
95 */
96 has(item) {
97 throw new Error(
98 "Checking StackedCacheMap.has before reading is inefficient, use StackedCacheMap.get and check for undefined"
99 );
100 }
101
102 /**
103 * Looks up a key by scanning immutable cache layers first and then the
104 * mutable fallback map.
105 * @param {K} item the key of the element to return
106 * @returns {V | undefined} the value of the element
107 */
108 get(item) {
109 for (const map of this.stack) {
110 const value = map.get(item);
111 if (value !== undefined) return value;
112 }
113 return this.map.get(item);
114 }
115
116 /**
117 * Removes every cache layer and clears the mutable fallback map.
118 */
119 clear() {
120 this.stack.length = 0;
121 this.map.clear();
122 }
123
124 /**
125 * Returns the total number of entries across the fallback map and all stacked
126 * cache layers.
127 * @returns {number} size of the map
128 */
129 get size() {
130 let size = this.map.size;
131 for (const map of this.stack) {
132 size += map.size;
133 }
134 return size;
135 }
136
137 /**
138 * Iterates over the fallback map first and then each stacked cache layer.
139 * @returns {Iterator<[K, V]>} iterator
140 */
141 [Symbol.iterator]() {
142 const iterators = this.stack.map((map) => map[Symbol.iterator]());
143 let current = this.map[Symbol.iterator]();
144 return {
145 next() {
146 let result = current.next();
147 while (result.done && iterators.length > 0) {
148 current = /** @type {MapIterator<[K, V]>} */ (iterators.pop());
149 result = current.next();
150 }
151 return result;
152 }
153 };
154 }
155}
156
157module.exports = StackedCacheMap;
Note: See TracBrowser for help on using the repository browser.