source: frontend/node_modules/webpack/lib/util/LazySet.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: 6.9 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
8const makeSerializable = require("./makeSerializable");
9
10/**
11 * Merges every queued iterable directly into the concrete backing set.
12 * @template T
13 * @param {Set<T>} targetSet set where items should be added
14 * @param {Set<Iterable<T>>} toMerge iterables to be merged
15 * @returns {void}
16 */
17const merge = (targetSet, toMerge) => {
18 for (const set of toMerge) {
19 for (const item of set) {
20 targetSet.add(item);
21 }
22 }
23};
24
25/**
26 * Flattens nested `LazySet` instances into a single collection of iterables
27 * that can later be merged into the backing set.
28 * @template T
29 * @param {Set<Iterable<T>>} targetSet set where iterables should be added
30 * @param {LazySet<T>[]} toDeepMerge lazy sets to be flattened
31 * @returns {void}
32 */
33const flatten = (targetSet, toDeepMerge) => {
34 for (const set of toDeepMerge) {
35 if (set._set.size > 0) targetSet.add(set._set);
36 if (set._needMerge) {
37 for (const mergedSet of set._toMerge) {
38 targetSet.add(mergedSet);
39 }
40 flatten(targetSet, set._toDeepMerge);
41 }
42 }
43};
44
45/**
46 * Defines the set iterator type used by this module.
47 * @template T
48 * @typedef {import("typescript-iterable").SetIterator<T>} SetIterator
49 */
50
51/**
52 * Like Set but with an addAll method to eventually add items from another iterable.
53 * Access methods make sure that all delayed operations are executed.
54 * Iteration methods deopts to normal Set performance until clear is called again (because of the chance of modifications during iteration).
55 * @template T
56 */
57class LazySet {
58 /**
59 * Seeds the set with an optional iterable while preparing internal queues for
60 * deferred merges.
61 * @param {Iterable<T>=} iterable init iterable
62 */
63 constructor(iterable) {
64 /** @type {Set<T>} */
65 this._set = new Set(iterable);
66 /** @type {Set<Iterable<T>>} */
67 this._toMerge = new Set();
68 /** @type {LazySet<T>[]} */
69 this._toDeepMerge = [];
70 this._needMerge = false;
71 this._deopt = false;
72 }
73
74 /**
75 * Flattens any nested lazy sets that were queued for merging.
76 */
77 _flatten() {
78 flatten(this._toMerge, this._toDeepMerge);
79 this._toDeepMerge.length = 0;
80 }
81
82 /**
83 * Materializes all deferred additions into the backing set.
84 */
85 _merge() {
86 this._flatten();
87 merge(this._set, this._toMerge);
88 this._toMerge.clear();
89 this._needMerge = false;
90 }
91
92 /**
93 * Reports whether the set is empty without forcing a full merge.
94 * @returns {boolean} true when no items have been stored or queued
95 */
96 _isEmpty() {
97 return (
98 this._set.size === 0 &&
99 this._toMerge.size === 0 &&
100 this._toDeepMerge.length === 0
101 );
102 }
103
104 /**
105 * Returns the number of items after applying any deferred merges.
106 * @returns {number} number of items in the set
107 */
108 get size() {
109 if (this._needMerge) this._merge();
110 return this._set.size;
111 }
112
113 /**
114 * Adds a single item immediately to the concrete backing set.
115 * @param {T} item an item
116 * @returns {LazySet<T>} itself
117 */
118 add(item) {
119 this._set.add(item);
120 return this;
121 }
122
123 /**
124 * Queues another iterable or lazy set for later merging so large bulk adds
125 * can stay cheap until the set is read.
126 * @param {Iterable<T> | LazySet<T>} iterable a immutable iterable or another immutable LazySet which will eventually be merged into the Set
127 * @returns {LazySet<T>} itself
128 */
129 addAll(iterable) {
130 if (this._deopt) {
131 const _set = this._set;
132 for (const item of iterable) {
133 _set.add(item);
134 }
135 } else {
136 if (iterable instanceof LazySet) {
137 if (iterable._isEmpty()) return this;
138 this._toDeepMerge.push(iterable);
139 this._needMerge = true;
140 if (this._toDeepMerge.length > 100000) {
141 this._flatten();
142 }
143 } else {
144 this._toMerge.add(iterable);
145 this._needMerge = true;
146 }
147 if (this._toMerge.size > 100000) this._merge();
148 }
149 return this;
150 }
151
152 /**
153 * Removes all items and clears every deferred merge queue.
154 */
155 clear() {
156 this._set.clear();
157 this._toMerge.clear();
158 this._toDeepMerge.length = 0;
159 this._needMerge = false;
160 this._deopt = false;
161 }
162
163 /**
164 * Deletes an item after first materializing any deferred additions that may
165 * contain it.
166 * @param {T} value an item
167 * @returns {boolean} true, if the value was in the Set before
168 */
169 delete(value) {
170 if (this._needMerge) this._merge();
171 return this._set.delete(value);
172 }
173
174 /**
175 * Returns the set's entry iterator and permanently switches future
176 * operations to eager merge mode to preserve iterator correctness.
177 * @returns {SetIterator<[T, T]>} entries
178 */
179 entries() {
180 this._deopt = true;
181 if (this._needMerge) this._merge();
182 return this._set.entries();
183 }
184
185 /**
186 * Iterates over every item after forcing pending merges and switching to
187 * eager mode for correctness during iteration.
188 * @template K
189 * @param {(value: T, value2: T, set: Set<T>) => void} callbackFn function called for each entry
190 * @param {K} thisArg this argument for the callbackFn
191 * @returns {void}
192 */
193 forEach(callbackFn, thisArg) {
194 this._deopt = true;
195 if (this._needMerge) this._merge();
196 // eslint-disable-next-line unicorn/no-array-for-each, unicorn/no-array-method-this-argument
197 this._set.forEach(callbackFn, thisArg);
198 }
199
200 /**
201 * Checks whether an item is present after applying any deferred merges.
202 * @param {T} item an item
203 * @returns {boolean} true, when the item is in the Set
204 */
205 has(item) {
206 if (this._needMerge) this._merge();
207 return this._set.has(item);
208 }
209
210 /**
211 * Returns the key iterator, eagerly materializing pending merges first.
212 * @returns {SetIterator<T>} keys
213 */
214 keys() {
215 this._deopt = true;
216 if (this._needMerge) this._merge();
217 return this._set.keys();
218 }
219
220 /**
221 * Returns the value iterator, eagerly materializing pending merges first.
222 * @returns {SetIterator<T>} values
223 */
224 values() {
225 this._deopt = true;
226 if (this._needMerge) this._merge();
227 return this._set.values();
228 }
229
230 /**
231 * Returns the default iterator over values after forcing pending merges.
232 * @returns {SetIterator<T>} iterable iterator
233 */
234 [Symbol.iterator]() {
235 this._deopt = true;
236 if (this._needMerge) this._merge();
237 return this._set[Symbol.iterator]();
238 }
239
240 /* istanbul ignore next */
241 get [Symbol.toStringTag]() {
242 return "LazySet";
243 }
244
245 /**
246 * Serializes the fully materialized set contents into webpack's object
247 * serialization stream.
248 * @param {import("../serialization/ObjectMiddleware").ObjectSerializerContext} context context
249 */
250 serialize({ write }) {
251 if (this._needMerge) this._merge();
252 write(this._set.size);
253 for (const item of this._set) write(item);
254 }
255
256 /**
257 * Restores a `LazySet` from serialized item data.
258 * @template T
259 * @param {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} context context
260 * @returns {LazySet<T>} lazy set
261 */
262 static deserialize({ read }) {
263 const count = read();
264 /** @type {T[]} */
265 const items = [];
266 for (let i = 0; i < count; i++) {
267 items.push(read());
268 }
269 return new LazySet(items);
270 }
271}
272
273makeSerializable(LazySet, "webpack/lib/util/LazySet");
274
275module.exports = LazySet;
Note: See TracBrowser for help on using the repository browser.