Apply module bundling
[platform/framework/web/wrtjs.git] / node_modules / webpack / lib / util / LazySet.js
1 /*
2         MIT License http://www.opensource.org/licenses/mit-license.php
3         Author Tobias Koppers @sokra
4 */
5
6 "use strict";
7
8 const makeSerializable = require("./makeSerializable.js");
9
10 /**
11  * @template T
12  * @param {Set<T>} targetSet set where items should be added
13  * @param {Set<Iterable<T>>} toMerge iterables to be merged
14  * @returns {void}
15  */
16 const merge = (targetSet, toMerge) => {
17         for (const set of toMerge) {
18                 for (const item of set) {
19                         targetSet.add(item);
20                 }
21         }
22 };
23
24 /**
25  * @template T
26  * @param {Set<Iterable<T>>} targetSet set where iterables should be added
27  * @param {Array<LazySet<T>>} toDeepMerge lazy sets to be flattened
28  * @returns {void}
29  */
30 const flatten = (targetSet, toDeepMerge) => {
31         for (const set of toDeepMerge) {
32                 if (set._set.size > 0) targetSet.add(set._set);
33                 if (set._needMerge) {
34                         for (const mergedSet of set._toMerge) {
35                                 targetSet.add(mergedSet);
36                         }
37                         flatten(targetSet, set._toDeepMerge);
38                 }
39         }
40 };
41
42 /**
43  * Like Set but with an addAll method to eventually add items from another iterable.
44  * Access methods make sure that all delayed operations are executed.
45  * Iteration methods deopts to normal Set performance until clear is called again (because of the chance of modifications during iteration).
46  * @template T
47  */
48 class LazySet {
49         /**
50          * @param {Iterable<T>=} iterable init iterable
51          */
52         constructor(iterable) {
53                 /** @type {Set<T>} */
54                 this._set = new Set(iterable);
55                 /** @type {Set<Iterable<T>>} */
56                 this._toMerge = new Set();
57                 /** @type {Array<LazySet<T>>} */
58                 this._toDeepMerge = [];
59                 this._needMerge = false;
60                 this._deopt = false;
61         }
62
63         _flatten() {
64                 flatten(this._toMerge, this._toDeepMerge);
65                 this._toDeepMerge.length = 0;
66         }
67
68         _merge() {
69                 this._flatten();
70                 merge(this._set, this._toMerge);
71                 this._toMerge.clear();
72                 this._needMerge = false;
73         }
74
75         _isEmpty() {
76                 return (
77                         this._set.size === 0 &&
78                         this._toMerge.size === 0 &&
79                         this._toDeepMerge.length === 0
80                 );
81         }
82
83         get size() {
84                 if (this._needMerge) this._merge();
85                 return this._set.size;
86         }
87
88         /**
89          * @param {T} item an item
90          * @returns {this} itself
91          */
92         add(item) {
93                 this._set.add(item);
94                 return this;
95         }
96
97         /**
98          * @param {Iterable<T> | LazySet<T>} iterable a immutable iterable or another immutable LazySet which will eventually be merged into the Set
99          * @returns {this} itself
100          */
101         addAll(iterable) {
102                 if (this._deopt) {
103                         const _set = this._set;
104                         for (const item of iterable) {
105                                 _set.add(item);
106                         }
107                 } else {
108                         if (iterable instanceof LazySet) {
109                                 if (iterable._isEmpty()) return this;
110                                 this._toDeepMerge.push(iterable);
111                                 this._needMerge = true;
112                                 if (this._toDeepMerge.length > 100000) {
113                                         this._flatten();
114                                 }
115                         } else {
116                                 this._toMerge.add(iterable);
117                                 this._needMerge = true;
118                         }
119                         if (this._toMerge.size > 100000) this._merge();
120                 }
121                 return this;
122         }
123
124         clear() {
125                 this._set.clear();
126                 this._toMerge.clear();
127                 this._toDeepMerge.length = 0;
128                 this._needMerge = false;
129                 this._deopt = false;
130         }
131
132         /**
133          * @param {T} value an item
134          * @returns {boolean} true, if the value was in the Set before
135          */
136         delete(value) {
137                 if (this._needMerge) this._merge();
138                 return this._set.delete(value);
139         }
140
141         entries() {
142                 this._deopt = true;
143                 if (this._needMerge) this._merge();
144                 return this._set.entries();
145         }
146
147         /**
148          * @param {function(T, T, Set<T>): void} callbackFn function called for each entry
149          * @param {any} thisArg this argument for the callbackFn
150          * @returns {void}
151          */
152         forEach(callbackFn, thisArg) {
153                 this._deopt = true;
154                 if (this._needMerge) this._merge();
155                 this._set.forEach(callbackFn, thisArg);
156         }
157
158         /**
159          * @param {T} item an item
160          * @returns {boolean} true, when the item is in the Set
161          */
162         has(item) {
163                 if (this._needMerge) this._merge();
164                 return this._set.has(item);
165         }
166
167         keys() {
168                 this._deopt = true;
169                 if (this._needMerge) this._merge();
170                 return this._set.keys();
171         }
172
173         values() {
174                 this._deopt = true;
175                 if (this._needMerge) this._merge();
176                 return this._set.values();
177         }
178
179         [Symbol.iterator]() {
180                 this._deopt = true;
181                 if (this._needMerge) this._merge();
182                 return this._set[Symbol.iterator]();
183         }
184
185         /* istanbul ignore next */
186         get [Symbol.toStringTag]() {
187                 return "LazySet";
188         }
189
190         serialize({ write }) {
191                 if (this._needMerge) this._merge();
192                 write(this._set.size);
193                 for (const item of this._set) write(item);
194         }
195
196         static deserialize({ read }) {
197                 const count = read();
198                 const items = [];
199                 for (let i = 0; i < count; i++) {
200                         items.push(read());
201                 }
202                 return new LazySet(items);
203         }
204 }
205
206 makeSerializable(LazySet, "webpack/lib/util/LazySet");
207
208 module.exports = LazySet;