source: frontend/node_modules/webpack/lib/util/runtime.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: 18.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
8const SortableSet = require("./SortableSet");
9
10/** @typedef {import("../Compilation")} Compilation */
11/** @typedef {import("../Entrypoint").EntryOptions} EntryOptions */
12
13/** @typedef {SortableSet<string>} RuntimeSpecSortableSet */
14/** @typedef {string | RuntimeSpecSortableSet | undefined} RuntimeSpec */
15/** @typedef {RuntimeSpec | boolean} RuntimeCondition */
16
17/**
18 * Gets entry runtime.
19 * @param {Compilation} compilation the compilation
20 * @param {string} name name of the entry
21 * @param {EntryOptions=} options optionally already received entry options
22 * @returns {RuntimeSpec} runtime
23 */
24const getEntryRuntime = (compilation, name, options) => {
25 /** @type {EntryOptions["dependOn"]} */
26 let dependOn;
27 /** @type {EntryOptions["runtime"]} */
28 let runtime;
29 if (options) {
30 ({ dependOn, runtime } = options);
31 } else {
32 const entry = compilation.entries.get(name);
33 if (!entry) return name;
34 ({ dependOn, runtime } = entry.options);
35 }
36 if (dependOn) {
37 /** @type {RuntimeSpec} */
38 let result;
39 const queue = new Set(dependOn);
40 for (const name of queue) {
41 const dep = compilation.entries.get(name);
42 if (!dep) continue;
43 const { dependOn, runtime } = dep.options;
44 if (dependOn) {
45 for (const name of dependOn) {
46 queue.add(name);
47 }
48 } else {
49 result = mergeRuntimeOwned(result, runtime || name);
50 }
51 }
52 return result || name;
53 }
54 return runtime || name;
55};
56
57/**
58 * Processes the provided runtime.
59 * @param {RuntimeSpec} runtime runtime
60 * @param {(runtime: string | undefined) => void} fn functor
61 * @param {boolean} deterministicOrder enforce a deterministic order
62 * @returns {void}
63 */
64const forEachRuntime = (runtime, fn, deterministicOrder = false) => {
65 if (runtime === undefined) {
66 fn(undefined);
67 } else if (typeof runtime === "string") {
68 fn(runtime);
69 } else {
70 if (deterministicOrder) runtime.sort();
71 for (const r of runtime) {
72 fn(r);
73 }
74 }
75};
76
77/**
78 * Returns runtime key.
79 * @template T
80 * @param {Exclude<RuntimeSpec, undefined | string>} set set
81 * @returns {string} runtime key
82 */
83const getRuntimesKey = (set) => {
84 set.sort();
85 return [...set].join("\n");
86};
87
88/**
89 * Returns key of runtimes.
90 * @param {RuntimeSpec} runtime runtime(s)
91 * @returns {string} key of runtimes
92 */
93const getRuntimeKey = (runtime) => {
94 if (runtime === undefined) return "*";
95 if (typeof runtime === "string") return runtime;
96 return runtime.getFromUnorderedCache(getRuntimesKey);
97};
98
99/**
100 * Returns runtime(s).
101 * @param {string} key key of runtimes
102 * @returns {RuntimeSpec} runtime(s)
103 */
104const keyToRuntime = (key) => {
105 if (key === "*") return;
106 const items = key.split("\n");
107 if (items.length === 1) return items[0];
108 return new SortableSet(items);
109};
110
111/**
112 * Gets runtimes string.
113 * @template T
114 * @param {Exclude<RuntimeSpec, undefined | string>} set set
115 * @returns {string} runtime string
116 */
117const getRuntimesString = (set) => {
118 set.sort();
119 return [...set].join("+");
120};
121
122/**
123 * Returns readable version.
124 * @param {RuntimeSpec} runtime runtime(s)
125 * @returns {string} readable version
126 */
127const runtimeToString = (runtime) => {
128 if (runtime === undefined) return "*";
129 if (typeof runtime === "string") return runtime;
130 return runtime.getFromUnorderedCache(getRuntimesString);
131};
132
133/**
134 * Runtime condition to string.
135 * @param {RuntimeCondition} runtimeCondition runtime condition
136 * @returns {string} readable version
137 */
138const runtimeConditionToString = (runtimeCondition) => {
139 if (runtimeCondition === true) return "true";
140 if (runtimeCondition === false) return "false";
141 return runtimeToString(runtimeCondition);
142};
143
144/**
145 * Returns true, when they are equal.
146 * @param {RuntimeSpec} a first
147 * @param {RuntimeSpec} b second
148 * @returns {boolean} true, when they are equal
149 */
150const runtimeEqual = (a, b) => {
151 if (a === b) {
152 return true;
153 } else if (
154 a === undefined ||
155 b === undefined ||
156 typeof a === "string" ||
157 typeof b === "string"
158 ) {
159 return false;
160 } else if (a.size !== b.size) {
161 return false;
162 }
163 a.sort();
164 b.sort();
165 const aIt = a[Symbol.iterator]();
166 const bIt = b[Symbol.iterator]();
167 for (;;) {
168 const aV = aIt.next();
169 if (aV.done) return true;
170 const bV = bIt.next();
171 if (aV.value !== bV.value) return false;
172 }
173};
174
175/**
176 * Compares the provided values and returns their ordering.
177 * @param {RuntimeSpec} a first
178 * @param {RuntimeSpec} b second
179 * @returns {-1 | 0 | 1} compare
180 */
181const compareRuntime = (a, b) => {
182 if (a === b) {
183 return 0;
184 } else if (a === undefined) {
185 return -1;
186 } else if (b === undefined) {
187 return 1;
188 }
189 const aKey = getRuntimeKey(a);
190 const bKey = getRuntimeKey(b);
191 if (aKey < bKey) return -1;
192 if (aKey > bKey) return 1;
193 return 0;
194};
195
196/**
197 * Merges the provided values into a single result.
198 * @param {RuntimeSpec} a first
199 * @param {RuntimeSpec} b second
200 * @returns {RuntimeSpec} merged
201 */
202const mergeRuntime = (a, b) => {
203 if (a === undefined) {
204 return b;
205 } else if (b === undefined) {
206 return a;
207 } else if (a === b) {
208 return a;
209 } else if (typeof a === "string") {
210 if (typeof b === "string") {
211 /** @type {RuntimeSpecSortableSet} */
212 const set = new SortableSet();
213 set.add(a);
214 set.add(b);
215 return set;
216 } else if (b.has(a)) {
217 return b;
218 }
219 /** @type {RuntimeSpecSortableSet} */
220 const set = new SortableSet(b);
221 set.add(a);
222 return set;
223 }
224 if (typeof b === "string") {
225 if (a.has(b)) return a;
226 /** @type {RuntimeSpecSortableSet} */
227 const set = new SortableSet(a);
228 set.add(b);
229 return set;
230 }
231 /** @type {RuntimeSpecSortableSet} */
232 const set = new SortableSet(a);
233 for (const item of b) set.add(item);
234 if (set.size === a.size) return a;
235 return set;
236};
237
238/**
239 * Merges runtime condition.
240 * @param {RuntimeCondition} a first
241 * @param {RuntimeCondition} b second
242 * @param {RuntimeSpec} runtime full runtime
243 * @returns {RuntimeCondition} result
244 */
245const mergeRuntimeCondition = (a, b, runtime) => {
246 if (a === false) return b;
247 if (b === false) return a;
248 if (a === true || b === true) return true;
249 const merged = mergeRuntime(a, b);
250 if (merged === undefined) return;
251 if (typeof merged === "string") {
252 if (typeof runtime === "string" && merged === runtime) return true;
253 return merged;
254 }
255 if (typeof runtime === "string" || runtime === undefined) return merged;
256 if (merged.size === runtime.size) return true;
257 return merged;
258};
259
260/**
261 * Merges runtime condition non false.
262 * @param {RuntimeSpec | true} a first
263 * @param {RuntimeSpec | true} b second
264 * @param {RuntimeSpec} runtime full runtime
265 * @returns {RuntimeSpec | true} result
266 */
267const mergeRuntimeConditionNonFalse = (a, b, runtime) => {
268 if (a === true || b === true) return true;
269 const merged = mergeRuntime(a, b);
270 if (merged === undefined) return;
271 if (typeof merged === "string") {
272 if (typeof runtime === "string" && merged === runtime) return true;
273 return merged;
274 }
275 if (typeof runtime === "string" || runtime === undefined) return merged;
276 if (merged.size === runtime.size) return true;
277 return merged;
278};
279
280/**
281 * Merges runtime owned.
282 * @param {RuntimeSpec} a first (may be modified)
283 * @param {RuntimeSpec} b second
284 * @returns {RuntimeSpec} merged
285 */
286const mergeRuntimeOwned = (a, b) => {
287 if (b === undefined) {
288 return a;
289 } else if (a === b) {
290 return a;
291 } else if (a === undefined) {
292 if (typeof b === "string") {
293 return b;
294 }
295 /** @type {RuntimeSpecSortableSet} */
296 return new SortableSet(b);
297 } else if (typeof a === "string") {
298 if (typeof b === "string") {
299 /** @type {RuntimeSpecSortableSet} */
300 const set = new SortableSet();
301 set.add(a);
302 set.add(b);
303 return set;
304 }
305 /** @type {RuntimeSpecSortableSet} */
306 const set = new SortableSet(b);
307 set.add(a);
308 return set;
309 }
310 if (typeof b === "string") {
311 a.add(b);
312 return a;
313 }
314 for (const item of b) a.add(item);
315 return a;
316};
317
318/**
319 * Returns merged.
320 * @param {RuntimeSpec} a first
321 * @param {RuntimeSpec} b second
322 * @returns {RuntimeSpec} merged
323 */
324const intersectRuntime = (a, b) => {
325 if (a === undefined) {
326 return b;
327 } else if (b === undefined) {
328 return a;
329 } else if (a === b) {
330 return a;
331 } else if (typeof a === "string") {
332 if (typeof b === "string") {
333 return;
334 } else if (b.has(a)) {
335 return a;
336 }
337 return;
338 }
339 if (typeof b === "string") {
340 if (a.has(b)) return b;
341 return;
342 }
343 /** @type {RuntimeSpecSortableSet} */
344 const set = new SortableSet();
345 for (const item of b) {
346 if (a.has(item)) set.add(item);
347 }
348 if (set.size === 0) return;
349 if (set.size === 1) {
350 const [item] = set;
351 return item;
352 }
353 return set;
354};
355
356/**
357 * Returns result.
358 * @param {RuntimeSpec} a first
359 * @param {RuntimeSpec} b second
360 * @returns {RuntimeSpec} result
361 */
362const subtractRuntime = (a, b) => {
363 if (a === undefined) {
364 return;
365 } else if (b === undefined) {
366 return a;
367 } else if (a === b) {
368 return;
369 } else if (typeof a === "string") {
370 if (typeof b === "string") {
371 return a;
372 } else if (b.has(a)) {
373 return;
374 }
375 return a;
376 }
377 if (typeof b === "string") {
378 if (!a.has(b)) return a;
379 if (a.size === 2) {
380 for (const item of a) {
381 if (item !== b) return item;
382 }
383 }
384 /** @type {RuntimeSpecSortableSet} */
385 const set = new SortableSet(a);
386 set.delete(b);
387 return set;
388 }
389 /** @type {RuntimeSpecSortableSet} */
390 const set = new SortableSet();
391 for (const item of a) {
392 if (!b.has(item)) set.add(item);
393 }
394 if (set.size === 0) return;
395 if (set.size === 1) {
396 const [item] = set;
397 return item;
398 }
399 return set;
400};
401
402/**
403 * Subtract runtime condition.
404 * @param {RuntimeCondition} a first
405 * @param {RuntimeCondition} b second
406 * @param {RuntimeSpec} runtime runtime
407 * @returns {RuntimeCondition} result
408 */
409const subtractRuntimeCondition = (a, b, runtime) => {
410 if (b === true) return false;
411 if (b === false) return a;
412 if (a === false) return false;
413 const result = subtractRuntime(a === true ? runtime : a, b);
414 return result === undefined ? false : result;
415};
416
417/**
418 * Returns true/false if filter is constant for all runtimes, otherwise runtimes that are active.
419 * @param {RuntimeSpec} runtime runtime
420 * @param {(runtime?: RuntimeSpec) => boolean} filter filter function
421 * @returns {boolean | RuntimeSpec} true/false if filter is constant for all runtimes, otherwise runtimes that are active
422 */
423const filterRuntime = (runtime, filter) => {
424 if (runtime === undefined) return filter();
425 if (typeof runtime === "string") return filter(runtime);
426 let some = false;
427 let every = true;
428 /** @type {RuntimeSpec} */
429 let result;
430 for (const r of runtime) {
431 const v = filter(r);
432 if (v) {
433 some = true;
434 result = mergeRuntimeOwned(result, r);
435 } else {
436 every = false;
437 }
438 }
439 if (!some) return false;
440 if (every) return true;
441 return result;
442};
443
444/**
445 * Defines the runtime spec map inner map type used by this module.
446 * @template T
447 * @typedef {Map<string, T>} RuntimeSpecMapInnerMap
448 */
449
450/**
451 * Represents RuntimeSpecMap.
452 * @template T
453 * @template [R=T]
454 */
455class RuntimeSpecMap {
456 /**
457 * Creates an instance of RuntimeSpecMap.
458 * @param {RuntimeSpecMap<T, R>=} clone copy form this
459 */
460 constructor(clone) {
461 /** @type {0 | 1 | 2} */
462 this._mode = clone ? clone._mode : 0; // 0 = empty, 1 = single entry, 2 = map
463 /** @type {RuntimeSpec} */
464 this._singleRuntime = clone ? clone._singleRuntime : undefined;
465 /** @type {R | undefined} */
466 this._singleValue = clone ? clone._singleValue : undefined;
467 /** @type {RuntimeSpecMapInnerMap<R> | undefined} */
468 this._map = clone && clone._map ? new Map(clone._map) : undefined;
469 }
470
471 /**
472 * Returns value.
473 * @param {RuntimeSpec} runtime the runtimes
474 * @returns {R | undefined} value
475 */
476 get(runtime) {
477 switch (this._mode) {
478 case 0:
479 return;
480 case 1:
481 return runtimeEqual(this._singleRuntime, runtime)
482 ? this._singleValue
483 : undefined;
484 default:
485 return /** @type {RuntimeSpecMapInnerMap<R>} */ (this._map).get(
486 getRuntimeKey(runtime)
487 );
488 }
489 }
490
491 /**
492 * Returns true, when the runtime is stored.
493 * @param {RuntimeSpec} runtime the runtimes
494 * @returns {boolean} true, when the runtime is stored
495 */
496 has(runtime) {
497 switch (this._mode) {
498 case 0:
499 return false;
500 case 1:
501 return runtimeEqual(this._singleRuntime, runtime);
502 default:
503 return /** @type {RuntimeSpecMapInnerMap<R>} */ (this._map).has(
504 getRuntimeKey(runtime)
505 );
506 }
507 }
508
509 /**
510 * Updates default using the provided runtime.
511 * @param {RuntimeSpec} runtime the runtimes
512 * @param {R} value the value
513 */
514 set(runtime, value) {
515 switch (this._mode) {
516 case 0:
517 this._mode = 1;
518 this._singleRuntime = runtime;
519 this._singleValue = value;
520 break;
521 case 1:
522 if (runtimeEqual(this._singleRuntime, runtime)) {
523 this._singleValue = value;
524 break;
525 }
526 this._mode = 2;
527 this._map = new Map();
528 this._map.set(
529 getRuntimeKey(this._singleRuntime),
530 /** @type {R} */ (this._singleValue)
531 );
532 this._singleRuntime = undefined;
533 this._singleValue = undefined;
534 /* falls through */
535 default:
536 /** @type {RuntimeSpecMapInnerMap<R>} */
537 (this._map).set(getRuntimeKey(runtime), value);
538 }
539 }
540
541 /**
542 * Returns the new value.
543 * @param {RuntimeSpec} runtime the runtimes
544 * @param {() => R} computer function to compute the value
545 * @returns {R} the new value
546 */
547 provide(runtime, computer) {
548 switch (this._mode) {
549 case 0:
550 this._mode = 1;
551 this._singleRuntime = runtime;
552 return (this._singleValue = computer());
553 case 1: {
554 if (runtimeEqual(this._singleRuntime, runtime)) {
555 return /** @type {R} */ (this._singleValue);
556 }
557 this._mode = 2;
558 this._map = new Map();
559 this._map.set(
560 getRuntimeKey(this._singleRuntime),
561 /** @type {R} */
562 (this._singleValue)
563 );
564 this._singleRuntime = undefined;
565 this._singleValue = undefined;
566 const newValue = computer();
567 this._map.set(getRuntimeKey(runtime), newValue);
568 return newValue;
569 }
570 default: {
571 const key = getRuntimeKey(runtime);
572 const value =
573 /** @type {RuntimeSpecMapInnerMap<R>} */
574 (this._map).get(key);
575 if (value !== undefined) return value;
576 const newValue = computer();
577 /** @type {RuntimeSpecMapInnerMap<R>} */
578 (this._map).set(key, newValue);
579 return newValue;
580 }
581 }
582 }
583
584 /**
585 * Processes the provided runtime.
586 * @param {RuntimeSpec} runtime the runtimes
587 */
588 delete(runtime) {
589 switch (this._mode) {
590 case 0:
591 return;
592 case 1:
593 if (runtimeEqual(this._singleRuntime, runtime)) {
594 this._mode = 0;
595 this._singleRuntime = undefined;
596 this._singleValue = undefined;
597 }
598 return;
599 default:
600 /** @type {RuntimeSpecMapInnerMap<R>} */
601 (this._map).delete(getRuntimeKey(runtime));
602 }
603 }
604
605 /**
606 * Processes the provided runtime.
607 * @param {RuntimeSpec} runtime the runtimes
608 * @param {(value: R | undefined) => R} fn function to update the value
609 */
610 update(runtime, fn) {
611 switch (this._mode) {
612 case 0:
613 throw new Error("runtime passed to update must exist");
614 case 1: {
615 if (runtimeEqual(this._singleRuntime, runtime)) {
616 this._singleValue = fn(this._singleValue);
617 break;
618 }
619 const newValue = fn(undefined);
620 if (newValue !== undefined) {
621 this._mode = 2;
622 this._map = new Map();
623 this._map.set(
624 getRuntimeKey(this._singleRuntime),
625 /** @type {R} */
626 (this._singleValue)
627 );
628 this._singleRuntime = undefined;
629 this._singleValue = undefined;
630 this._map.set(getRuntimeKey(runtime), newValue);
631 }
632 break;
633 }
634 default: {
635 const key = getRuntimeKey(runtime);
636 const oldValue =
637 /** @type {RuntimeSpecMapInnerMap<R>} */
638 (this._map).get(key);
639 const newValue = fn(oldValue);
640 if (newValue !== oldValue) {
641 /** @type {RuntimeSpecMapInnerMap<R>} */
642 (this._map).set(key, newValue);
643 }
644 }
645 }
646 }
647
648 keys() {
649 switch (this._mode) {
650 case 0:
651 return [];
652 case 1:
653 return [this._singleRuntime];
654 default:
655 return Array.from(
656 /** @type {RuntimeSpecMapInnerMap<R>} */
657 (this._map).keys(),
658 keyToRuntime
659 );
660 }
661 }
662
663 /**
664 * Returns values.
665 * @returns {IterableIterator<R>} values
666 */
667 values() {
668 switch (this._mode) {
669 case 0:
670 return [][Symbol.iterator]();
671 case 1:
672 return [/** @type {R} */ (this._singleValue)][Symbol.iterator]();
673 default:
674 return /** @type {RuntimeSpecMapInnerMap<R>} */ (this._map).values();
675 }
676 }
677
678 get size() {
679 if (/** @type {number} */ (this._mode) <= 1) {
680 return /** @type {number} */ (this._mode);
681 }
682
683 return /** @type {RuntimeSpecMapInnerMap<R>} */ (this._map).size;
684 }
685}
686
687class RuntimeSpecSet {
688 /**
689 * Creates an instance of RuntimeSpecSet.
690 * @param {Iterable<RuntimeSpec>=} iterable iterable
691 */
692 constructor(iterable) {
693 /** @type {Map<string, RuntimeSpec>} */
694 this._map = new Map();
695 if (iterable) {
696 for (const item of iterable) {
697 this.add(item);
698 }
699 }
700 }
701
702 /**
703 * Processes the provided runtime.
704 * @param {RuntimeSpec} runtime runtime
705 */
706 add(runtime) {
707 this._map.set(getRuntimeKey(runtime), runtime);
708 }
709
710 /**
711 * Returns true, when the runtime exists.
712 * @param {RuntimeSpec} runtime runtime
713 * @returns {boolean} true, when the runtime exists
714 */
715 has(runtime) {
716 return this._map.has(getRuntimeKey(runtime));
717 }
718
719 /**
720 * Returns iterable iterator.
721 * @returns {IterableIterator<RuntimeSpec>} iterable iterator
722 */
723 [Symbol.iterator]() {
724 return this._map.values();
725 }
726
727 get size() {
728 return this._map.size;
729 }
730}
731
732module.exports.RuntimeSpecMap = RuntimeSpecMap;
733module.exports.RuntimeSpecSet = RuntimeSpecSet;
734module.exports.compareRuntime = compareRuntime;
735module.exports.filterRuntime = filterRuntime;
736module.exports.forEachRuntime = forEachRuntime;
737module.exports.getEntryRuntime = getEntryRuntime;
738module.exports.getRuntimeKey = getRuntimeKey;
739module.exports.intersectRuntime = intersectRuntime;
740module.exports.keyToRuntime = keyToRuntime;
741module.exports.mergeRuntime = mergeRuntime;
742module.exports.mergeRuntimeCondition = mergeRuntimeCondition;
743module.exports.mergeRuntimeConditionNonFalse = mergeRuntimeConditionNonFalse;
744module.exports.mergeRuntimeOwned = mergeRuntimeOwned;
745module.exports.runtimeConditionToString = runtimeConditionToString;
746module.exports.runtimeEqual = runtimeEqual;
747module.exports.runtimeToString = runtimeToString;
748module.exports.subtractRuntime = subtractRuntime;
749module.exports.subtractRuntimeCondition = subtractRuntimeCondition;
Note: See TracBrowser for help on using the repository browser.