webpack 4.8.2 → 4.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +95 -52
  2. package/bin/webpack.js +128 -43
  3. package/lib/AmdMainTemplatePlugin.js +10 -0
  4. package/lib/AsyncDependencyToInitialChunkError.js +12 -2
  5. package/lib/BannerPlugin.js +115 -101
  6. package/lib/CaseSensitiveModulesWarning.js +20 -2
  7. package/lib/Chunk.js +1 -0
  8. package/lib/ChunkGroup.js +465 -465
  9. package/lib/ChunkRenderError.js +8 -0
  10. package/lib/ChunkTemplate.js +71 -71
  11. package/lib/Compilation.js +1 -1
  12. package/lib/Compiler.js +2 -1
  13. package/lib/ContextModule.js +8 -8
  14. package/lib/DllPlugin.js +3 -1
  15. package/lib/DllReferencePlugin.js +2 -1
  16. package/lib/Entrypoint.js +54 -54
  17. package/lib/EvalSourceMapDevToolModuleTemplatePlugin.js +115 -115
  18. package/lib/ExportPropertyMainTemplatePlugin.js +13 -0
  19. package/lib/Generator.js +52 -52
  20. package/lib/HotModuleReplacement.runtime.js +633 -633
  21. package/lib/JsonParser.js +2 -1
  22. package/lib/LibManifestPlugin.js +9 -0
  23. package/lib/LibraryTemplatePlugin.js +66 -33
  24. package/lib/MainTemplate.js +468 -468
  25. package/lib/Module.js +3 -3
  26. package/lib/ModuleDependencyError.js +12 -2
  27. package/lib/NormalModuleFactory.js +5 -3
  28. package/lib/Parser.js +27 -23
  29. package/lib/ProgressPlugin.js +1 -1
  30. package/lib/RecordIdsPlugin.js +3 -1
  31. package/lib/RuntimeTemplate.js +1 -1
  32. package/lib/SetVarMainTemplatePlugin.js +12 -0
  33. package/lib/SourceMapDevToolPlugin.js +11 -13
  34. package/lib/Template.js +289 -290
  35. package/lib/UmdMainTemplatePlugin.js +67 -32
  36. package/lib/WebpackError.js +8 -2
  37. package/lib/compareLocations.js +20 -0
  38. package/lib/debug/ProfilingPlugin.js +416 -416
  39. package/lib/dependencies/ContextDependencyHelpers.js +142 -142
  40. package/lib/dependencies/WebpackMissingModule.js +2 -2
  41. package/lib/optimize/RemoveEmptyChunksPlugin.js +42 -40
  42. package/lib/optimize/RuntimeChunkPlugin.js +9 -5
  43. package/lib/optimize/SplitChunksPlugin.js +195 -124
  44. package/lib/util/Queue.js +46 -46
  45. package/lib/util/SetHelpers.js +48 -48
  46. package/lib/util/SortableSet.js +106 -106
  47. package/lib/util/StackedSetMap.js +128 -128
  48. package/lib/util/cachedMerge.js +13 -0
  49. package/lib/util/identifier.js +5 -0
  50. package/lib/util/objectToMap.js +16 -16
  51. package/lib/wasm/WebAssemblyGenerator.js +280 -280
  52. package/lib/wasm/WebAssemblyParser.js +79 -79
  53. package/lib/web/JsonpMainTemplatePlugin.js +2 -2
  54. package/package.json +21 -17
  55. package/schemas/WebpackOptions.json +12 -1
  56. package/schemas/plugins/BannerPlugin.json +96 -85
  57. package/schemas/plugins/DllPlugin.json +4 -0
@@ -10,6 +10,7 @@ const GraphHelpers = require("../GraphHelpers");
10
10
  const { isSubset } = require("../util/SetHelpers");
11
11
 
12
12
  /** @typedef {import("../Chunk")} Chunk */
13
+ /** @typedef {import("../Module")} Module */
13
14
 
14
15
  const hashFilename = name => {
15
16
  return crypto
@@ -310,7 +311,6 @@ module.exports = class SplitChunksPlugin {
310
311
 
311
312
  // Create a list of possible combinations
312
313
  const combinationsCache = new Map(); // Map<string, Set<Chunk>[]>
313
- const selectedChunksCacheByChunksSet = new WeakMap(); // WeakMap<Set<Chunk>, WeakMap<Function, {chunks: Chunk[], key: string}>>
314
314
 
315
315
  const getCombinations = key => {
316
316
  const chunksSet = chunkSetsInGraph.get(key);
@@ -330,14 +330,36 @@ module.exports = class SplitChunksPlugin {
330
330
  return array;
331
331
  };
332
332
 
333
+ /**
334
+ * @typedef {Object} SelectedChunksResult
335
+ * @property {Chunk[]} chunks the list of chunks
336
+ * @property {string} key a key of the list
337
+ */
338
+
339
+ /**
340
+ * @typedef {function(Chunk): boolean} ChunkFilterFunction
341
+ */
342
+
343
+ /** @type {WeakMap<Set<Chunk>, WeakMap<ChunkFilterFunction, SelectedChunksResult>>} */
344
+ const selectedChunksCacheByChunksSet = new WeakMap();
345
+
346
+ /**
347
+ * get list and key by applying the filter function to the list
348
+ * It is cached for performance reasons
349
+ * @param {Set<Chunk>} chunks list of chunks
350
+ * @param {ChunkFilterFunction} chunkFilter filter function for chunks
351
+ * @returns {SelectedChunksResult} list and key
352
+ */
333
353
  const getSelectedChunks = (chunks, chunkFilter) => {
334
354
  let entry = selectedChunksCacheByChunksSet.get(chunks);
335
355
  if (entry === undefined) {
336
- entry = new Map();
356
+ entry = new WeakMap();
337
357
  selectedChunksCacheByChunksSet.set(chunks, entry);
338
358
  }
359
+ /** @type {SelectedChunksResult} */
339
360
  let entry2 = entry.get(chunkFilter);
340
361
  if (entry2 === undefined) {
362
+ /** @type {Chunk[]} */
341
363
  const selectedChunks = [];
342
364
  for (const chunk of chunks) {
343
365
  if (chunkFilter(chunk)) selectedChunks.push(chunk);
@@ -351,10 +373,76 @@ module.exports = class SplitChunksPlugin {
351
373
  return entry2;
352
374
  };
353
375
 
376
+ /**
377
+ * @typedef {Object} ChunksInfoItem
378
+ * @property {SortableSet} modules
379
+ * @property {TODO} cacheGroup
380
+ * @property {string} name
381
+ * @property {number} size
382
+ * @property {Map<Chunk, number>} chunks
383
+ * @property {Set<Chunk>} reuseableChunks
384
+ * @property {Set<string>} chunksKeys
385
+ */
386
+
354
387
  // Map a list of chunks to a list of modules
355
388
  // For the key the chunk "index" is used, the value is a SortableSet of modules
389
+ /** @type {Map<string, ChunksInfoItem>} */
356
390
  const chunksInfoMap = new Map();
357
391
 
392
+ /**
393
+ * @param {TODO} cacheGroup the current cache group
394
+ * @param {Chunk[]} selectedChunks chunks selected for this module
395
+ * @param {string} selectedChunksKey a key of selectedChunks
396
+ * @param {Module} module the current module
397
+ * @returns {void}
398
+ */
399
+ const addModuleToChunksInfoMap = (
400
+ cacheGroup,
401
+ selectedChunks,
402
+ selectedChunksKey,
403
+ module
404
+ ) => {
405
+ // Break if minimum number of chunks is not reached
406
+ if (selectedChunks.length < cacheGroup.minChunks) return;
407
+ // Determine name for split chunk
408
+ const name = cacheGroup.getName(
409
+ module,
410
+ selectedChunks,
411
+ cacheGroup.key
412
+ );
413
+ // Create key for maps
414
+ // When it has a name we use the name as key
415
+ // Elsewise we create the key from chunks and cache group key
416
+ // This automatically merges equal names
417
+ const key =
418
+ (name && `name:${name}`) ||
419
+ `chunks:${selectedChunksKey} key:${cacheGroup.key}`;
420
+ // Add module to maps
421
+ let info = chunksInfoMap.get(key);
422
+ if (info === undefined) {
423
+ chunksInfoMap.set(
424
+ key,
425
+ (info = {
426
+ modules: new SortableSet(undefined, sortByIdentifier),
427
+ cacheGroup,
428
+ name,
429
+ size: 0,
430
+ chunks: new Map(),
431
+ reuseableChunks: new Set(),
432
+ chunksKeys: new Set()
433
+ })
434
+ );
435
+ }
436
+ info.modules.add(module);
437
+ info.size += module.size();
438
+ if (!info.chunksKeys.has(selectedChunksKey)) {
439
+ info.chunksKeys.add(selectedChunksKey);
440
+ for (const chunk of selectedChunks) {
441
+ info.chunks.set(chunk, chunk.getNumberOfModules());
442
+ }
443
+ }
444
+ };
445
+
358
446
  // Walk through all modules
359
447
  for (const module of compilation.modules) {
360
448
  // Get cache group
@@ -422,55 +510,17 @@ module.exports = class SplitChunksPlugin {
422
510
  chunkCombination,
423
511
  cacheGroup.chunksFilter
424
512
  );
425
- // Break if minimum number of chunks is not reached
426
- if (selectedChunks.length < cacheGroup.minChunks) continue;
427
- // Determine name for split chunk
428
- const name = cacheGroup.getName(
429
- module,
513
+
514
+ addModuleToChunksInfoMap(
515
+ cacheGroup,
430
516
  selectedChunks,
431
- cacheGroup.key
517
+ selectedChunksKey,
518
+ module
432
519
  );
433
- // Create key for maps
434
- // When it has a name we use the name as key
435
- // Elsewise we create the key from chunks and cache group key
436
- // This automatically merges equal names
437
- const key =
438
- (name && `name:${name}`) ||
439
- `chunks:${selectedChunksKey} key:${cacheGroup.key}`;
440
- // Add module to maps
441
- let info = chunksInfoMap.get(key);
442
- if (info === undefined) {
443
- chunksInfoMap.set(
444
- key,
445
- (info = {
446
- modules: new SortableSet(undefined, sortByIdentifier),
447
- cacheGroup,
448
- name,
449
- size: 0,
450
- chunks: new Map(),
451
- reusedableChunks: new Set(),
452
- chunksKeys: new Set()
453
- })
454
- );
455
- }
456
- info.modules.add(module);
457
- info.size += module.size();
458
- if (!info.chunksKeys.has(selectedChunksKey)) {
459
- info.chunksKeys.add(selectedChunksKey);
460
- for (const chunk of selectedChunks) {
461
- info.chunks.set(chunk, chunk.getNumberOfModules());
462
- }
463
- }
464
520
  }
465
521
  }
466
522
  }
467
523
 
468
- for (const [key, info] of chunksInfoMap) {
469
- // Get size of module lists
470
- if (info.size < info.cacheGroup.minSize) {
471
- chunksInfoMap.delete(key);
472
- }
473
- }
474
524
  while (chunksInfoMap.size > 0) {
475
525
  // Find best matching entry
476
526
  let bestEntryKey;
@@ -478,15 +528,20 @@ module.exports = class SplitChunksPlugin {
478
528
  for (const pair of chunksInfoMap) {
479
529
  const key = pair[0];
480
530
  const info = pair[1];
481
- if (bestEntry === undefined) {
482
- bestEntry = info;
483
- bestEntryKey = key;
484
- } else if (compareEntries(bestEntry, info) < 0) {
485
- bestEntry = info;
486
- bestEntryKey = key;
531
+ if (info.size >= info.cacheGroup.minSize) {
532
+ if (bestEntry === undefined) {
533
+ bestEntry = info;
534
+ bestEntryKey = key;
535
+ } else if (compareEntries(bestEntry, info) < 0) {
536
+ bestEntry = info;
537
+ bestEntryKey = key;
538
+ }
487
539
  }
488
540
  }
489
541
 
542
+ // No suitable item left
543
+ if (bestEntry === undefined) break;
544
+
490
545
  const item = bestEntry;
491
546
  chunksInfoMap.delete(bestEntryKey);
492
547
 
@@ -517,12 +572,19 @@ module.exports = class SplitChunksPlugin {
517
572
  }
518
573
  }
519
574
  }
520
- const usedChunks = [];
521
- // Walk through all chunks
522
- for (const chunk of item.chunks.keys()) {
575
+ // Check if maxRequests condition can be fullfilled
576
+
577
+ const usedChunks = Array.from(item.chunks.keys()).filter(chunk => {
523
578
  // skip if we address ourself
524
- if ((chunkName && chunk.name === chunkName) || chunk === newChunk)
525
- continue;
579
+ return (
580
+ (!chunkName || chunk.name !== chunkName) && chunk !== newChunk
581
+ );
582
+ });
583
+
584
+ // Skip when no chunk selected
585
+ if (usedChunks.length === 0) continue;
586
+
587
+ const chunkInLimit = usedChunks.filter(chunk => {
526
588
  // respect max requests when not enforced
527
589
  const maxRequests = chunk.isOnlyInitial()
528
590
  ? item.cacheGroup.maxInitialRequests
@@ -532,88 +594,97 @@ module.exports = class SplitChunksPlugin {
532
594
  item.cacheGroup.maxAsyncRequests
533
595
  )
534
596
  : item.cacheGroup.maxAsyncRequests;
535
- if (isFinite(maxRequests) && getRequests(chunk) >= maxRequests)
536
- continue;
537
- if (newChunk === undefined) {
538
- // Create the new chunk
539
- newChunk = compilation.addChunk(chunkName);
597
+ return !isFinite(maxRequests) || getRequests(chunk) < maxRequests;
598
+ });
599
+
600
+ if (chunkInLimit.length < usedChunks.length) {
601
+ for (const module of item.modules) {
602
+ addModuleToChunksInfoMap(
603
+ item.cacheGroup,
604
+ chunkInLimit,
605
+ getKey(chunkInLimit),
606
+ module
607
+ );
540
608
  }
609
+ continue;
610
+ }
611
+
612
+ // Create the new chunk if not reusing one
613
+ if (!isReused) {
614
+ newChunk = compilation.addChunk(chunkName);
615
+ }
616
+ // Walk through all chunks
617
+ for (const chunk of usedChunks) {
541
618
  // Add graph connections for splitted chunk
542
619
  chunk.split(newChunk);
543
- usedChunks.push(chunk);
544
620
  }
545
621
 
546
- // If we successfully created a new chunk or reused one
547
- if (newChunk) {
548
- // Add a note to the chunk
549
- newChunk.chunkReason = isReused
550
- ? "reused as split chunk"
551
- : "split chunk";
552
- if (item.cacheGroup.key) {
553
- newChunk.chunkReason += ` (cache group: ${
554
- item.cacheGroup.key
555
- })`;
622
+ // Add a note to the chunk
623
+ newChunk.chunkReason = isReused
624
+ ? "reused as split chunk"
625
+ : "split chunk";
626
+ if (item.cacheGroup.key) {
627
+ newChunk.chunkReason += ` (cache group: ${item.cacheGroup.key})`;
628
+ }
629
+ if (chunkName) {
630
+ newChunk.chunkReason += ` (name: ${chunkName})`;
631
+ // If the chosen name is already an entry point we remove the entry point
632
+ const entrypoint = compilation.entrypoints.get(chunkName);
633
+ if (entrypoint) {
634
+ compilation.entrypoints.delete(chunkName);
635
+ entrypoint.remove();
636
+ newChunk.entryModule = undefined;
637
+ }
638
+ }
639
+ if (item.cacheGroup.filename) {
640
+ if (!newChunk.isOnlyInitial()) {
641
+ throw new Error(
642
+ "SplitChunksPlugin: You are trying to set a filename for a chunk which is (also) loaded on demand. " +
643
+ "The runtime can only handle loading of chunks which match the chunkFilename schema. " +
644
+ "Using a custom filename would fail at runtime. " +
645
+ `(cache group: ${item.cacheGroup.key})`
646
+ );
556
647
  }
557
- if (chunkName) {
558
- newChunk.chunkReason += ` (name: ${chunkName})`;
559
- // If the chosen name is already an entry point we remove the entry point
560
- const entrypoint = compilation.entrypoints.get(chunkName);
561
- if (entrypoint) {
562
- compilation.entrypoints.delete(chunkName);
563
- entrypoint.remove();
564
- newChunk.entryModule = undefined;
648
+ newChunk.filenameTemplate = item.cacheGroup.filename;
649
+ }
650
+ if (!isReused) {
651
+ // Add all modules to the new chunk
652
+ for (const module of item.modules) {
653
+ if (typeof module.chunkCondition === "function") {
654
+ if (!module.chunkCondition(newChunk)) continue;
655
+ }
656
+ // Add module to new chunk
657
+ GraphHelpers.connectChunkAndModule(newChunk, module);
658
+ // Remove module from used chunks
659
+ for (const chunk of usedChunks) {
660
+ chunk.removeModule(module);
661
+ module.rewriteChunkInReasons(chunk, [newChunk]);
565
662
  }
566
663
  }
567
- if (item.cacheGroup.filename) {
568
- if (!newChunk.isOnlyInitial()) {
569
- throw new Error(
570
- "SplitChunksPlugin: You are trying to set a filename for a chunk which is (also) loaded on demand. " +
571
- "The runtime can only handle loading of chunks which match the chunkFilename schema. " +
572
- "Using a custom filename would fail at runtime. " +
573
- `(cache group: ${item.cacheGroup.key})`
574
- );
664
+ } else {
665
+ // Remove all modules from used chunks
666
+ for (const module of item.modules) {
667
+ for (const chunk of usedChunks) {
668
+ chunk.removeModule(module);
669
+ module.rewriteChunkInReasons(chunk, [newChunk]);
575
670
  }
576
- newChunk.filenameTemplate = item.cacheGroup.filename;
577
671
  }
578
- if (!isReused) {
579
- // Add all modules to the new chunk
672
+ }
673
+ // remove all modules from other entries and update size
674
+ for (const [key, info] of chunksInfoMap) {
675
+ if (isOverlap(info.chunks, item.chunks)) {
676
+ const oldSize = info.modules.size;
580
677
  for (const module of item.modules) {
581
- if (typeof module.chunkCondition === "function") {
582
- if (!module.chunkCondition(newChunk)) continue;
583
- }
584
- // Add module to new chunk
585
- GraphHelpers.connectChunkAndModule(newChunk, module);
586
- // Remove module from used chunks
587
- for (const chunk of usedChunks) {
588
- chunk.removeModule(module);
589
- module.rewriteChunkInReasons(chunk, [newChunk]);
590
- }
678
+ info.modules.delete(module);
591
679
  }
592
- } else {
593
- // Remove all modules from used chunks
594
- for (const module of item.modules) {
595
- for (const chunk of usedChunks) {
596
- chunk.removeModule(module);
597
- module.rewriteChunkInReasons(chunk, [newChunk]);
598
- }
680
+ if (info.modules.size === 0) {
681
+ chunksInfoMap.delete(key);
682
+ continue;
599
683
  }
600
- }
601
- // remove all modules from other entries and update size
602
- for (const [key, info] of chunksInfoMap) {
603
- if (isOverlap(info.chunks, item.chunks)) {
604
- const oldSize = info.modules.size;
605
- for (const module of item.modules) {
606
- info.modules.delete(module);
607
- }
608
- if (info.modules.size === 0) {
684
+ if (info.modules.size !== oldSize) {
685
+ info.size = getModulesSize(info.modules);
686
+ if (info.size < info.cacheGroup.minSize)
609
687
  chunksInfoMap.delete(key);
610
- continue;
611
- }
612
- if (info.modules.size !== oldSize) {
613
- info.size = getModulesSize(info.modules);
614
- if (info.size < info.cacheGroup.minSize)
615
- chunksInfoMap.delete(key);
616
- }
617
688
  }
618
689
  }
619
690
  }
package/lib/util/Queue.js CHANGED
@@ -1,46 +1,46 @@
1
- "use strict";
2
-
3
- /**
4
- * @template T
5
- */
6
- class Queue {
7
- /**
8
- * @param {IterableIterator<T>=} items The initial elements.
9
- */
10
- constructor(items) {
11
- /** @private @type {Set<T>} */
12
- this.set = new Set(items);
13
- /** @private @type {Iterator<T>} */
14
- this.iterator = this.set[Symbol.iterator]();
15
- }
16
-
17
- /**
18
- * Returns the number of elements in this queue.
19
- * @returns {number} The number of elements in this queue.
20
- */
21
- get length() {
22
- return this.set.size;
23
- }
24
-
25
- /**
26
- * Appends the specified element to this queue.
27
- * @param {T} item The element to add.
28
- * @returns {void}
29
- */
30
- enqueue(item) {
31
- this.set.add(item);
32
- }
33
-
34
- /**
35
- * Retrieves and removes the head of this queue.
36
- * @returns {T | undefined} The head of the queue of `undefined` if this queue is empty.
37
- */
38
- dequeue() {
39
- const result = this.iterator.next();
40
- if (result.done) return undefined;
41
- this.set.delete(result.value);
42
- return result.value;
43
- }
44
- }
45
-
46
- module.exports = Queue;
1
+ "use strict";
2
+
3
+ /**
4
+ * @template T
5
+ */
6
+ class Queue {
7
+ /**
8
+ * @param {IterableIterator<T>=} items The initial elements.
9
+ */
10
+ constructor(items) {
11
+ /** @private @type {Set<T>} */
12
+ this.set = new Set(items);
13
+ /** @private @type {Iterator<T>} */
14
+ this.iterator = this.set[Symbol.iterator]();
15
+ }
16
+
17
+ /**
18
+ * Returns the number of elements in this queue.
19
+ * @returns {number} The number of elements in this queue.
20
+ */
21
+ get length() {
22
+ return this.set.size;
23
+ }
24
+
25
+ /**
26
+ * Appends the specified element to this queue.
27
+ * @param {T} item The element to add.
28
+ * @returns {void}
29
+ */
30
+ enqueue(item) {
31
+ this.set.add(item);
32
+ }
33
+
34
+ /**
35
+ * Retrieves and removes the head of this queue.
36
+ * @returns {T | undefined} The head of the queue of `undefined` if this queue is empty.
37
+ */
38
+ dequeue() {
39
+ const result = this.iterator.next();
40
+ if (result.done) return undefined;
41
+ this.set.delete(result.value);
42
+ return result.value;
43
+ }
44
+ }
45
+
46
+ module.exports = Queue;
@@ -1,48 +1,48 @@
1
- "use strict";
2
-
3
- /**
4
- * intersect creates Set containing the intersection of elements between all sets
5
- * @param {Set[]} sets an array of sets being checked for shared elements
6
- * @returns {Set<TODO>} returns a new Set containing the intersecting items
7
- */
8
- function intersect(sets) {
9
- if (sets.length === 0) return new Set();
10
- if (sets.length === 1) return new Set(sets[0]);
11
- let minSize = Infinity;
12
- let minIndex = -1;
13
- for (let i = 0; i < sets.length; i++) {
14
- const size = sets[i].size;
15
- if (size < minSize) {
16
- minIndex = i;
17
- minSize = size;
18
- }
19
- }
20
- const current = new Set(sets[minIndex]);
21
- for (let i = 0; i < sets.length; i++) {
22
- if (i === minIndex) continue;
23
- const set = sets[i];
24
- for (const item of current) {
25
- if (!set.has(item)) {
26
- current.delete(item);
27
- }
28
- }
29
- }
30
- return current;
31
- }
32
-
33
- /**
34
- * Checks if a set is the subset of another set
35
- * @param {Set<TODO>} bigSet a Set which contains the original elements to compare against
36
- * @param {Set<TODO>} smallSet the set whos elements might be contained inside of bigSet
37
- * @returns {boolean} returns true if smallSet contains all elements inside of the bigSet
38
- */
39
- function isSubset(bigSet, smallSet) {
40
- if (bigSet.size < smallSet.size) return false;
41
- for (const item of smallSet) {
42
- if (!bigSet.has(item)) return false;
43
- }
44
- return true;
45
- }
46
-
47
- exports.intersect = intersect;
48
- exports.isSubset = isSubset;
1
+ "use strict";
2
+
3
+ /**
4
+ * intersect creates Set containing the intersection of elements between all sets
5
+ * @param {Set[]} sets an array of sets being checked for shared elements
6
+ * @returns {Set<TODO>} returns a new Set containing the intersecting items
7
+ */
8
+ function intersect(sets) {
9
+ if (sets.length === 0) return new Set();
10
+ if (sets.length === 1) return new Set(sets[0]);
11
+ let minSize = Infinity;
12
+ let minIndex = -1;
13
+ for (let i = 0; i < sets.length; i++) {
14
+ const size = sets[i].size;
15
+ if (size < minSize) {
16
+ minIndex = i;
17
+ minSize = size;
18
+ }
19
+ }
20
+ const current = new Set(sets[minIndex]);
21
+ for (let i = 0; i < sets.length; i++) {
22
+ if (i === minIndex) continue;
23
+ const set = sets[i];
24
+ for (const item of current) {
25
+ if (!set.has(item)) {
26
+ current.delete(item);
27
+ }
28
+ }
29
+ }
30
+ return current;
31
+ }
32
+
33
+ /**
34
+ * Checks if a set is the subset of another set
35
+ * @param {Set<TODO>} bigSet a Set which contains the original elements to compare against
36
+ * @param {Set<TODO>} smallSet the set whos elements might be contained inside of bigSet
37
+ * @returns {boolean} returns true if smallSet contains all elements inside of the bigSet
38
+ */
39
+ function isSubset(bigSet, smallSet) {
40
+ if (bigSet.size < smallSet.size) return false;
41
+ for (const item of smallSet) {
42
+ if (!bigSet.has(item)) return false;
43
+ }
44
+ return true;
45
+ }
46
+
47
+ exports.intersect = intersect;
48
+ exports.isSubset = isSubset;