source: frontend/node_modules/webpack/lib/ChunkGraph.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 60.7 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 util = require("util");
9const Entrypoint = require("./Entrypoint");
10const ModuleGraphConnection = require("./ModuleGraphConnection");
11const { DEFAULTS } = require("./config/defaults");
12const { first } = require("./util/SetHelpers");
13const SortableSet = require("./util/SortableSet");
14const {
15 compareIds,
16 compareIterables,
17 compareModulesById,
18 compareModulesByIdentifier,
19 compareSelect,
20 concatComparators
21} = require("./util/comparators");
22const createHash = require("./util/createHash");
23const findGraphRoots = require("./util/findGraphRoots");
24const {
25 RuntimeSpecMap,
26 RuntimeSpecSet,
27 forEachRuntime,
28 mergeRuntime,
29 runtimeToString
30} = require("./util/runtime");
31
32/** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
33/** @typedef {import("./Chunk")} Chunk */
34/** @typedef {import("./Chunk").Chunks} Chunks */
35/** @typedef {import("./Chunk").Entrypoints} Entrypoints */
36/** @typedef {import("./Chunk").ChunkId} ChunkId */
37/** @typedef {import("./ChunkGroup")} ChunkGroup */
38/** @typedef {import("./Module")} Module */
39/** @typedef {import("./Module").SourceType} SourceType */
40/** @typedef {import("./Module").SourceTypes} SourceTypes */
41/** @typedef {import("./Module").ReadOnlyRuntimeRequirements} ReadOnlyRuntimeRequirements */
42/** @typedef {import("./Module").RuntimeRequirements} RuntimeRequirements */
43/** @typedef {import("./ModuleGraph")} ModuleGraph */
44/** @typedef {import("./ModuleGraphConnection").ConnectionState} ConnectionState */
45/** @typedef {import("./RuntimeModule")} RuntimeModule */
46/** @typedef {import("./util/Hash").HashFunction} HashFunction */
47/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
48
49/** @type {ReadonlySet<string>} */
50const EMPTY_SET = new Set();
51
52const ZERO_BIG_INT = BigInt(0);
53
54const compareModuleIterables = compareIterables(compareModulesByIdentifier);
55
56/** @typedef {(c: Chunk, chunkGraph: ChunkGraph) => boolean} ChunkFilterPredicate */
57/** @typedef {(m: Module) => boolean} ModuleFilterPredicate */
58/** @typedef {[Module, Entrypoint | undefined]} EntryModuleWithChunkGroup */
59
60/**
61 * Represents the module hash info runtime component.
62 * @typedef {object} ChunkSizeOptions
63 * @property {number=} chunkOverhead constant overhead for a chunk
64 * @property {number=} entryChunkMultiplicator multiplicator for initial chunks
65 */
66
67class ModuleHashInfo {
68 /**
69 * Creates an instance of ModuleHashInfo.
70 * @param {string} hash hash
71 * @param {string} renderedHash rendered hash
72 */
73 constructor(hash, renderedHash) {
74 /** @type {string} */
75 this.hash = hash;
76 /** @type {string} */
77 this.renderedHash = renderedHash;
78 }
79}
80
81/**
82 * Returns set as array.
83 * @template T
84 * @param {SortableSet<T>} set the set
85 * @returns {T[]} set as array
86 */
87const getArray = (set) => [...set];
88
89/**
90 * Gets module runtimes.
91 * @param {SortableChunks} chunks the chunks
92 * @returns {RuntimeSpecSet} runtimes
93 */
94const getModuleRuntimes = (chunks) => {
95 const runtimes = new RuntimeSpecSet();
96 for (const chunk of chunks) {
97 runtimes.add(chunk.runtime);
98 }
99 return runtimes;
100};
101
102/**
103 * Modules by source type.
104 * @param {SourceTypesByModule | undefined} sourceTypesByModule sourceTypesByModule
105 * @returns {ModulesBySourceType} modules by source type
106 */
107const modulesBySourceType = (sourceTypesByModule) => (set) => {
108 /** @typedef {SortableSet<Module>} ModuleSortableSet */
109 /** @type {Map<SourceType, ModuleSortableSet>} */
110 const map = new Map();
111 for (const module of set) {
112 const sourceTypes =
113 (sourceTypesByModule && sourceTypesByModule.get(module)) ||
114 module.getSourceTypes();
115 for (const sourceType of sourceTypes) {
116 let innerSet = map.get(sourceType);
117 if (innerSet === undefined) {
118 /** @type {ModuleSortableSet} */
119 innerSet = new SortableSet();
120 map.set(sourceType, innerSet);
121 }
122 innerSet.add(module);
123 }
124 }
125 for (const [key, innerSet] of map) {
126 // When all modules have the source type, we reuse the original SortableSet
127 // to benefit from the shared cache (especially for sorting)
128 if (innerSet.size === set.size) {
129 map.set(key, set);
130 }
131 }
132 return map;
133};
134
135/** @typedef {(set: SortableSet<Module>) => Map<string, SortableSet<Module>>} ModulesBySourceType */
136
137/** @type {ModulesBySourceType} */
138const defaultModulesBySourceType = modulesBySourceType(undefined);
139
140/**
141 * Defines the module set to array function type used by this module.
142 * @typedef {(set: SortableSet<Module>) => Module[]} ModuleSetToArrayFunction
143 */
144
145/**
146 * @template T
147 * @type {WeakMap<ModuleComparator, ModuleSetToArrayFunction>}
148 */
149const createOrderedArrayFunctionMap = new WeakMap();
150
151/**
152 * Creates an ordered array function.
153 * @template T
154 * @param {ModuleComparator} comparator comparator function
155 * @returns {ModuleSetToArrayFunction} set as ordered array
156 */
157const createOrderedArrayFunction = (comparator) => {
158 let fn = createOrderedArrayFunctionMap.get(comparator);
159 if (fn !== undefined) return fn;
160 fn = (set) => {
161 set.sortWith(comparator);
162 return [...set];
163 };
164 createOrderedArrayFunctionMap.set(comparator, fn);
165 return fn;
166};
167
168/**
169 * Returns the size of the modules.
170 * @param {Iterable<Module>} modules the modules to get the count/size of
171 * @returns {number} the size of the modules
172 */
173const getModulesSize = (modules) => {
174 let size = 0;
175 for (const module of modules) {
176 for (const type of module.getSourceTypes()) {
177 size += module.size(type);
178 }
179 }
180 return size;
181};
182
183/** @typedef {Record<string, number>} SizesOfModules */
184
185/**
186 * Gets modules sizes.
187 * @param {Iterable<Module>} modules the sortable Set to get the size of
188 * @returns {SizesOfModules} the sizes of the modules
189 */
190const getModulesSizes = (modules) => {
191 /** @type {SizesOfModules} */
192 const sizes = Object.create(null);
193 for (const module of modules) {
194 for (const type of module.getSourceTypes()) {
195 sizes[type] = (sizes[type] || 0) + module.size(type);
196 }
197 }
198 return sizes;
199};
200
201/**
202 * Checks whether this module hash info is available chunk.
203 * @param {Chunk} a chunk
204 * @param {Chunk} b chunk
205 * @returns {boolean} true, if a is always a parent of b
206 */
207const isAvailableChunk = (a, b) => {
208 const queue = new Set(b.groupsIterable);
209 for (const chunkGroup of queue) {
210 if (a.isInGroup(chunkGroup)) continue;
211 if (chunkGroup.isInitial()) return false;
212 for (const parent of chunkGroup.parentsIterable) {
213 queue.add(parent);
214 }
215 }
216 return true;
217};
218
219/** @typedef {SortableSet<Chunk>} SortableChunks */
220/** @typedef {Set<Chunk>} EntryInChunks */
221/** @typedef {Set<Chunk>} RuntimeInChunks */
222/** @typedef {string | number} ModuleId */
223/** @typedef {RuntimeSpecMap<Set<string>, RuntimeRequirements>} ChunkGraphRuntimeRequirements */
224
225class ChunkGraphModule {
226 constructor() {
227 /** @type {SortableChunks} */
228 this.chunks = new SortableSet();
229 /** @type {EntryInChunks | undefined} */
230 this.entryInChunks = undefined;
231 /** @type {RuntimeInChunks | undefined} */
232 this.runtimeInChunks = undefined;
233 /** @type {RuntimeSpecMap<ModuleHashInfo> | undefined} */
234 this.hashes = undefined;
235 /** @type {ModuleId | null} */
236 this.id = null;
237 /** @type {ChunkGraphRuntimeRequirements | undefined} */
238 this.runtimeRequirements = undefined;
239 /** @type {RuntimeSpecMap<string, bigint> | undefined} */
240 this.graphHashes = undefined;
241 /** @type {RuntimeSpecMap<string, string> | undefined} */
242 this.graphHashesWithConnections = undefined;
243 }
244}
245
246/** @typedef {WeakMap<Module, SourceTypes>} SourceTypesByModule */
247/** @typedef {Map<Module, Entrypoint>} EntryModules */
248
249class ChunkGraphChunk {
250 constructor() {
251 /** @type {SortableSet<Module>} */
252 this.modules = new SortableSet();
253 /** @type {SourceTypesByModule | undefined} */
254 this.sourceTypesByModule = undefined;
255 /** @type {EntryModules} */
256 this.entryModules = new Map();
257 /** @type {SortableSet<RuntimeModule>} */
258 this.runtimeModules = new SortableSet();
259 /** @type {Set<RuntimeModule> | undefined} */
260 this.fullHashModules = undefined;
261 /** @type {Set<RuntimeModule> | undefined} */
262 this.dependentHashModules = undefined;
263 /** @type {RuntimeRequirements | undefined} */
264 this.runtimeRequirements = undefined;
265 /** @type {Set<string>} */
266 this.runtimeRequirementsInTree = new Set();
267 /** @type {ModulesBySourceType} */
268 this._modulesBySourceType = defaultModulesBySourceType;
269 }
270}
271
272/** @typedef {string | number} RuntimeId */
273/** @typedef {Record<ModuleId, string>} IdToHashMap */
274/** @typedef {Record<ChunkId, IdToHashMap>} ChunkModuleHashMap */
275/** @typedef {Record<ChunkId, ModuleId[]>} ChunkModuleIdMap */
276/** @typedef {Record<ChunkId, boolean>} ChunkConditionMap */
277
278/** @typedef {(a: Module, b: Module) => -1 | 0 | 1} ModuleComparator */
279
280class ChunkGraph {
281 /**
282 * Creates an instance of ChunkGraph.
283 * @param {ModuleGraph} moduleGraph the module graph
284 * @param {HashFunction} hashFunction the hash function to use
285 */
286 constructor(moduleGraph, hashFunction = DEFAULTS.HASH_FUNCTION) {
287 /**
288 * @private
289 * @type {WeakMap<Module, ChunkGraphModule>}
290 */
291 this._modules = new WeakMap();
292 /**
293 * @private
294 * @type {WeakMap<Chunk, ChunkGraphChunk>}
295 */
296 this._chunks = new WeakMap();
297 /**
298 * @private
299 * @type {WeakMap<AsyncDependenciesBlock, ChunkGroup>}
300 */
301 this._blockChunkGroups = new WeakMap();
302 /**
303 * @private
304 * @type {Map<string, RuntimeId>}
305 */
306 this._runtimeIds = new Map();
307 /** @type {ModuleGraph} */
308 this.moduleGraph = moduleGraph;
309
310 this._hashFunction = hashFunction;
311
312 this._getGraphRoots = this._getGraphRoots.bind(this);
313 }
314
315 /**
316 * Get chunk graph module.
317 * @private
318 * @param {Module} module the module
319 * @returns {ChunkGraphModule} internal module
320 */
321 _getChunkGraphModule(module) {
322 let cgm = this._modules.get(module);
323 if (cgm === undefined) {
324 cgm = new ChunkGraphModule();
325 this._modules.set(module, cgm);
326 }
327 return cgm;
328 }
329
330 /**
331 * Get chunk graph chunk.
332 * @private
333 * @param {Chunk} chunk the chunk
334 * @returns {ChunkGraphChunk} internal chunk
335 */
336 _getChunkGraphChunk(chunk) {
337 let cgc = this._chunks.get(chunk);
338 if (cgc === undefined) {
339 cgc = new ChunkGraphChunk();
340 this._chunks.set(chunk, cgc);
341 }
342 return cgc;
343 }
344
345 /**
346 * Returns the graph roots.
347 * @param {SortableSet<Module>} set the sortable Set to get the roots of
348 * @returns {Module[]} the graph roots
349 */
350 _getGraphRoots(set) {
351 const { moduleGraph } = this;
352 return [
353 ...findGraphRoots(set, (module) => {
354 /** @type {Set<Module>} */
355 const set = new Set();
356 /**
357 * Adds the provided module to the chunk graph.
358 * @param {Module} module module
359 */
360 const addDependencies = (module) => {
361 for (const connection of moduleGraph.getOutgoingConnections(module)) {
362 if (!connection.module) continue;
363 const activeState = connection.getActiveState(undefined);
364 if (activeState === false) continue;
365 if (activeState === ModuleGraphConnection.TRANSITIVE_ONLY) {
366 addDependencies(connection.module);
367 continue;
368 }
369 set.add(connection.module);
370 }
371 };
372 addDependencies(module);
373 return set;
374 })
375 ].sort(compareModulesByIdentifier);
376 }
377
378 /**
379 * Connects chunk and module.
380 * @param {Chunk} chunk the new chunk
381 * @param {Module} module the module
382 * @returns {void}
383 */
384 connectChunkAndModule(chunk, module) {
385 const cgm = this._getChunkGraphModule(module);
386 const cgc = this._getChunkGraphChunk(chunk);
387 cgm.chunks.add(chunk);
388 cgc.modules.add(module);
389 }
390
391 /**
392 * Disconnects chunk and module.
393 * @param {Chunk} chunk the chunk
394 * @param {Module} module the module
395 * @returns {void}
396 */
397 disconnectChunkAndModule(chunk, module) {
398 const cgm = this._getChunkGraphModule(module);
399 const cgc = this._getChunkGraphChunk(chunk);
400 cgc.modules.delete(module);
401 // No need to invalidate cgc._modulesBySourceType because we modified cgc.modules anyway
402 if (cgc.sourceTypesByModule) cgc.sourceTypesByModule.delete(module);
403 cgm.chunks.delete(chunk);
404 }
405
406 /**
407 * Processes the provided chunk.
408 * @param {Chunk} chunk the chunk which will be disconnected
409 * @returns {void}
410 */
411 disconnectChunk(chunk) {
412 const cgc = this._getChunkGraphChunk(chunk);
413 for (const module of cgc.modules) {
414 const cgm = this._getChunkGraphModule(module);
415 cgm.chunks.delete(chunk);
416 }
417 cgc.modules.clear();
418 chunk.disconnectFromGroups();
419 ChunkGraph.clearChunkGraphForChunk(chunk);
420 }
421
422 /**
423 * Processes the provided chunk.
424 * @param {Chunk} chunk the chunk
425 * @param {Iterable<Module>} modules the modules
426 * @returns {void}
427 */
428 attachModules(chunk, modules) {
429 const cgc = this._getChunkGraphChunk(chunk);
430 for (const module of modules) {
431 cgc.modules.add(module);
432 }
433 }
434
435 /**
436 * Attach runtime modules.
437 * @param {Chunk} chunk the chunk
438 * @param {Iterable<RuntimeModule>} modules the runtime modules
439 * @returns {void}
440 */
441 attachRuntimeModules(chunk, modules) {
442 const cgc = this._getChunkGraphChunk(chunk);
443 for (const module of modules) {
444 cgc.runtimeModules.add(module);
445 }
446 }
447
448 /**
449 * Attach full hash modules.
450 * @param {Chunk} chunk the chunk
451 * @param {Iterable<RuntimeModule>} modules the modules that require a full hash
452 * @returns {void}
453 */
454 attachFullHashModules(chunk, modules) {
455 const cgc = this._getChunkGraphChunk(chunk);
456 if (cgc.fullHashModules === undefined) cgc.fullHashModules = new Set();
457 for (const module of modules) {
458 cgc.fullHashModules.add(module);
459 }
460 }
461
462 /**
463 * Attach dependent hash modules.
464 * @param {Chunk} chunk the chunk
465 * @param {Iterable<RuntimeModule>} modules the modules that require a full hash
466 * @returns {void}
467 */
468 attachDependentHashModules(chunk, modules) {
469 const cgc = this._getChunkGraphChunk(chunk);
470 if (cgc.dependentHashModules === undefined) {
471 cgc.dependentHashModules = new Set();
472 }
473 for (const module of modules) {
474 cgc.dependentHashModules.add(module);
475 }
476 }
477
478 /**
479 * Processes the provided old module.
480 * @param {Module} oldModule the replaced module
481 * @param {Module} newModule the replacing module
482 * @returns {void}
483 */
484 replaceModule(oldModule, newModule) {
485 const oldCgm = this._getChunkGraphModule(oldModule);
486 const newCgm = this._getChunkGraphModule(newModule);
487
488 for (const chunk of oldCgm.chunks) {
489 const cgc = this._getChunkGraphChunk(chunk);
490 cgc.modules.delete(oldModule);
491 cgc.modules.add(newModule);
492 newCgm.chunks.add(chunk);
493 }
494 oldCgm.chunks.clear();
495
496 if (oldCgm.entryInChunks !== undefined) {
497 if (newCgm.entryInChunks === undefined) {
498 newCgm.entryInChunks = new Set();
499 }
500 for (const chunk of oldCgm.entryInChunks) {
501 const cgc = this._getChunkGraphChunk(chunk);
502 const old = /** @type {Entrypoint} */ (cgc.entryModules.get(oldModule));
503 /** @type {EntryModules} */
504 const newEntryModules = new Map();
505 for (const [m, cg] of cgc.entryModules) {
506 if (m === oldModule) {
507 newEntryModules.set(newModule, old);
508 } else {
509 newEntryModules.set(m, cg);
510 }
511 }
512 cgc.entryModules = newEntryModules;
513 newCgm.entryInChunks.add(chunk);
514 }
515 oldCgm.entryInChunks = undefined;
516 }
517
518 if (oldCgm.runtimeInChunks !== undefined) {
519 if (newCgm.runtimeInChunks === undefined) {
520 newCgm.runtimeInChunks = new Set();
521 }
522 for (const chunk of oldCgm.runtimeInChunks) {
523 const cgc = this._getChunkGraphChunk(chunk);
524 cgc.runtimeModules.delete(/** @type {RuntimeModule} */ (oldModule));
525 cgc.runtimeModules.add(/** @type {RuntimeModule} */ (newModule));
526 newCgm.runtimeInChunks.add(chunk);
527 if (
528 cgc.fullHashModules !== undefined &&
529 cgc.fullHashModules.has(/** @type {RuntimeModule} */ (oldModule))
530 ) {
531 cgc.fullHashModules.delete(/** @type {RuntimeModule} */ (oldModule));
532 cgc.fullHashModules.add(/** @type {RuntimeModule} */ (newModule));
533 }
534 if (
535 cgc.dependentHashModules !== undefined &&
536 cgc.dependentHashModules.has(/** @type {RuntimeModule} */ (oldModule))
537 ) {
538 cgc.dependentHashModules.delete(
539 /** @type {RuntimeModule} */ (oldModule)
540 );
541 cgc.dependentHashModules.add(
542 /** @type {RuntimeModule} */ (newModule)
543 );
544 }
545 }
546 oldCgm.runtimeInChunks = undefined;
547 }
548 }
549
550 /**
551 * Checks whether this chunk graph is module in chunk.
552 * @param {Module} module the checked module
553 * @param {Chunk} chunk the checked chunk
554 * @returns {boolean} true, if the chunk contains the module
555 */
556 isModuleInChunk(module, chunk) {
557 const cgc = this._getChunkGraphChunk(chunk);
558 return cgc.modules.has(module);
559 }
560
561 /**
562 * Checks whether this chunk graph is module in chunk group.
563 * @param {Module} module the checked module
564 * @param {ChunkGroup} chunkGroup the checked chunk group
565 * @returns {boolean} true, if the chunk contains the module
566 */
567 isModuleInChunkGroup(module, chunkGroup) {
568 for (const chunk of chunkGroup.chunks) {
569 if (this.isModuleInChunk(module, chunk)) return true;
570 }
571 return false;
572 }
573
574 /**
575 * Checks whether this chunk graph is entry module.
576 * @param {Module} module the checked module
577 * @returns {boolean} true, if the module is entry of any chunk
578 */
579 isEntryModule(module) {
580 const cgm = this._getChunkGraphModule(module);
581 return cgm.entryInChunks !== undefined;
582 }
583
584 /**
585 * Gets module chunks iterable.
586 * @param {Module} module the module
587 * @returns {Iterable<Chunk>} iterable of chunks (do not modify)
588 */
589 getModuleChunksIterable(module) {
590 const cgm = this._getChunkGraphModule(module);
591 return cgm.chunks;
592 }
593
594 /**
595 * Gets ordered module chunks iterable.
596 * @param {Module} module the module
597 * @param {(a: Chunk, b: Chunk) => -1 | 0 | 1} sortFn sort function
598 * @returns {Iterable<Chunk>} iterable of chunks (do not modify)
599 */
600 getOrderedModuleChunksIterable(module, sortFn) {
601 const cgm = this._getChunkGraphModule(module);
602 cgm.chunks.sortWith(sortFn);
603 return cgm.chunks;
604 }
605
606 /**
607 * Gets module chunks.
608 * @param {Module} module the module
609 * @returns {Chunk[]} array of chunks (cached, do not modify)
610 */
611 getModuleChunks(module) {
612 const cgm = this._getChunkGraphModule(module);
613 return cgm.chunks.getFromCache(getArray);
614 }
615
616 /**
617 * Gets number of module chunks.
618 * @param {Module} module the module
619 * @returns {number} the number of chunk which contain the module
620 */
621 getNumberOfModuleChunks(module) {
622 const cgm = this._getChunkGraphModule(module);
623 return cgm.chunks.size;
624 }
625
626 /**
627 * Gets module runtimes.
628 * @param {Module} module the module
629 * @returns {RuntimeSpecSet} runtimes
630 */
631 getModuleRuntimes(module) {
632 const cgm = this._getChunkGraphModule(module);
633 return cgm.chunks.getFromUnorderedCache(getModuleRuntimes);
634 }
635
636 /**
637 * Gets number of chunk modules.
638 * @param {Chunk} chunk the chunk
639 * @returns {number} the number of modules which are contained in this chunk
640 */
641 getNumberOfChunkModules(chunk) {
642 const cgc = this._getChunkGraphChunk(chunk);
643 return cgc.modules.size;
644 }
645
646 /**
647 * Gets number of chunk full hash modules.
648 * @param {Chunk} chunk the chunk
649 * @returns {number} the number of full hash modules which are contained in this chunk
650 */
651 getNumberOfChunkFullHashModules(chunk) {
652 const cgc = this._getChunkGraphChunk(chunk);
653 return cgc.fullHashModules === undefined ? 0 : cgc.fullHashModules.size;
654 }
655
656 /**
657 * Gets chunk modules iterable.
658 * @param {Chunk} chunk the chunk
659 * @returns {Iterable<Module>} return the modules for this chunk
660 */
661 getChunkModulesIterable(chunk) {
662 const cgc = this._getChunkGraphChunk(chunk);
663 return cgc.modules;
664 }
665
666 /**
667 * Gets chunk modules iterable by source type.
668 * @param {Chunk} chunk the chunk
669 * @param {string} sourceType source type
670 * @returns {Iterable<Module> | undefined} return the modules for this chunk
671 */
672 getChunkModulesIterableBySourceType(chunk, sourceType) {
673 const cgc = this._getChunkGraphChunk(chunk);
674 const modulesWithSourceType = cgc.modules
675 .getFromUnorderedCache(cgc._modulesBySourceType)
676 .get(sourceType);
677 return modulesWithSourceType;
678 }
679
680 /**
681 * Sets chunk module source types.
682 * @param {Chunk} chunk chunk
683 * @param {Module} module chunk module
684 * @param {SourceTypes} sourceTypes source types
685 */
686 setChunkModuleSourceTypes(chunk, module, sourceTypes) {
687 const cgc = this._getChunkGraphChunk(chunk);
688 if (cgc.sourceTypesByModule === undefined) {
689 cgc.sourceTypesByModule = new WeakMap();
690 }
691 cgc.sourceTypesByModule.set(module, sourceTypes);
692 // Update cgc._modulesBySourceType to invalidate the cache
693 cgc._modulesBySourceType = modulesBySourceType(cgc.sourceTypesByModule);
694 }
695
696 /**
697 * Gets chunk module source types.
698 * @param {Chunk} chunk chunk
699 * @param {Module} module chunk module
700 * @returns {SourceTypes} source types
701 */
702 getChunkModuleSourceTypes(chunk, module) {
703 const cgc = this._getChunkGraphChunk(chunk);
704 if (cgc.sourceTypesByModule === undefined) {
705 return module.getSourceTypes();
706 }
707 return cgc.sourceTypesByModule.get(module) || module.getSourceTypes();
708 }
709
710 /**
711 * Gets module source types.
712 * @param {Module} module module
713 * @returns {SourceTypes} source types
714 */
715 getModuleSourceTypes(module) {
716 return (
717 this._getOverwrittenModuleSourceTypes(module) || module.getSourceTypes()
718 );
719 }
720
721 /**
722 * Get overwritten module source types.
723 * @param {Module} module module
724 * @returns {SourceTypes | undefined} source types
725 */
726 _getOverwrittenModuleSourceTypes(module) {
727 let newSet = false;
728 /** @type {Set<SourceType> | undefined} */
729 let sourceTypes;
730 for (const chunk of this.getModuleChunksIterable(module)) {
731 const cgc = this._getChunkGraphChunk(chunk);
732 if (cgc.sourceTypesByModule === undefined) return;
733 const st = cgc.sourceTypesByModule.get(module);
734 if (st === undefined) return;
735 if (!sourceTypes) {
736 sourceTypes = /** @type {Set<SourceType>} */ (st);
737 } else if (!newSet) {
738 for (const type of st) {
739 if (!newSet) {
740 if (!sourceTypes.has(type)) {
741 newSet = true;
742 sourceTypes = new Set(sourceTypes);
743 sourceTypes.add(type);
744 }
745 } else {
746 sourceTypes.add(type);
747 }
748 }
749 } else {
750 for (const type of st) sourceTypes.add(type);
751 }
752 }
753
754 return sourceTypes;
755 }
756
757 /**
758 * Gets ordered chunk modules iterable.
759 * @param {Chunk} chunk the chunk
760 * @param {ModuleComparator} comparator comparator function
761 * @returns {Iterable<Module>} return the modules for this chunk
762 */
763 getOrderedChunkModulesIterable(chunk, comparator) {
764 const cgc = this._getChunkGraphChunk(chunk);
765 cgc.modules.sortWith(comparator);
766 return cgc.modules;
767 }
768
769 /**
770 * Gets ordered chunk modules iterable by source type.
771 * @param {Chunk} chunk the chunk
772 * @param {string} sourceType source type
773 * @param {ModuleComparator} comparator comparator function
774 * @returns {Iterable<Module> | undefined} return the modules for this chunk
775 */
776 getOrderedChunkModulesIterableBySourceType(chunk, sourceType, comparator) {
777 const cgc = this._getChunkGraphChunk(chunk);
778 const modulesWithSourceType = cgc.modules
779 .getFromUnorderedCache(cgc._modulesBySourceType)
780 .get(sourceType);
781 if (modulesWithSourceType === undefined) return;
782 modulesWithSourceType.sortWith(comparator);
783 return modulesWithSourceType;
784 }
785
786 /**
787 * Gets chunk modules.
788 * @param {Chunk} chunk the chunk
789 * @returns {Module[]} return the modules for this chunk (cached, do not modify)
790 */
791 getChunkModules(chunk) {
792 const cgc = this._getChunkGraphChunk(chunk);
793 return cgc.modules.getFromUnorderedCache(getArray);
794 }
795
796 /**
797 * Gets ordered chunk modules.
798 * @param {Chunk} chunk the chunk
799 * @param {ModuleComparator} comparator comparator function
800 * @returns {Module[]} return the modules for this chunk (cached, do not modify)
801 */
802 getOrderedChunkModules(chunk, comparator) {
803 const cgc = this._getChunkGraphChunk(chunk);
804 const arrayFunction = createOrderedArrayFunction(comparator);
805 return cgc.modules.getFromUnorderedCache(arrayFunction);
806 }
807
808 /**
809 * Gets chunk module id map.
810 * @param {Chunk} chunk the chunk
811 * @param {ModuleFilterPredicate} filterFn function used to filter modules
812 * @param {boolean} includeAllChunks all chunks or only async chunks
813 * @returns {ChunkModuleIdMap} chunk to module ids object
814 */
815 getChunkModuleIdMap(chunk, filterFn, includeAllChunks = false) {
816 /** @type {ChunkModuleIdMap} */
817 const chunkModuleIdMap = Object.create(null);
818
819 for (const asyncChunk of includeAllChunks
820 ? chunk.getAllReferencedChunks()
821 : chunk.getAllAsyncChunks()) {
822 /** @type {ModuleId[] | undefined} */
823 let array;
824 for (const module of this.getOrderedChunkModulesIterable(
825 asyncChunk,
826 compareModulesById(this)
827 )) {
828 if (filterFn(module)) {
829 if (array === undefined) {
830 array = [];
831 chunkModuleIdMap[/** @type {ChunkId} */ (asyncChunk.id)] = array;
832 }
833 const moduleId = /** @type {ModuleId} */ (this.getModuleId(module));
834 array.push(moduleId);
835 }
836 }
837 }
838
839 return chunkModuleIdMap;
840 }
841
842 /**
843 * Gets chunk module rendered hash map.
844 * @param {Chunk} chunk the chunk
845 * @param {ModuleFilterPredicate} filterFn function used to filter modules
846 * @param {number} hashLength length of the hash
847 * @param {boolean} includeAllChunks all chunks or only async chunks
848 * @returns {ChunkModuleHashMap} chunk to module id to module hash object
849 */
850 getChunkModuleRenderedHashMap(
851 chunk,
852 filterFn,
853 hashLength = 0,
854 includeAllChunks = false
855 ) {
856 /** @type {ChunkModuleHashMap} */
857 const chunkModuleHashMap = Object.create(null);
858
859 for (const asyncChunk of includeAllChunks
860 ? chunk.getAllReferencedChunks()
861 : chunk.getAllAsyncChunks()) {
862 /** @type {IdToHashMap | undefined} */
863 let idToHashMap;
864 for (const module of this.getOrderedChunkModulesIterable(
865 asyncChunk,
866 compareModulesById(this)
867 )) {
868 if (filterFn(module)) {
869 if (idToHashMap === undefined) {
870 /** @type {IdToHashMap} */
871 idToHashMap = Object.create(null);
872 chunkModuleHashMap[/** @type {ChunkId} */ (asyncChunk.id)] =
873 /** @type {IdToHashMap} */
874 (idToHashMap);
875 }
876 const moduleId = this.getModuleId(module);
877 const hash = this.getRenderedModuleHash(module, asyncChunk.runtime);
878 /** @type {IdToHashMap} */
879 (idToHashMap)[/** @type {ModuleId} */ (moduleId)] = hashLength
880 ? hash.slice(0, hashLength)
881 : hash;
882 }
883 }
884 }
885
886 return chunkModuleHashMap;
887 }
888
889 /**
890 * Gets chunk condition map.
891 * @param {Chunk} chunk the chunk
892 * @param {ChunkFilterPredicate} filterFn function used to filter chunks
893 * @returns {ChunkConditionMap} chunk condition map
894 */
895 getChunkConditionMap(chunk, filterFn) {
896 /** @type {ChunkConditionMap} */
897 const map = Object.create(null);
898 for (const c of chunk.getAllReferencedChunks()) {
899 map[/** @type {ChunkId} */ (c.id)] = filterFn(c, this);
900 }
901 return map;
902 }
903
904 /**
905 * Checks whether this chunk graph contains the chunk.
906 * @param {Chunk} chunk the chunk
907 * @param {ModuleFilterPredicate} filterFn predicate function used to filter modules
908 * @param {ChunkFilterPredicate=} filterChunkFn predicate function used to filter chunks
909 * @returns {boolean} return true if module exists in graph
910 */
911 hasModuleInGraph(chunk, filterFn, filterChunkFn) {
912 const queue = new Set(chunk.groupsIterable);
913 /** @type {Set<Chunk>} */
914 const chunksProcessed = new Set();
915
916 for (const chunkGroup of queue) {
917 for (const innerChunk of chunkGroup.chunks) {
918 if (!chunksProcessed.has(innerChunk)) {
919 chunksProcessed.add(innerChunk);
920 if (!filterChunkFn || filterChunkFn(innerChunk, this)) {
921 for (const module of this.getChunkModulesIterable(innerChunk)) {
922 if (filterFn(module)) {
923 return true;
924 }
925 }
926 }
927 }
928 }
929 for (const child of chunkGroup.childrenIterable) {
930 queue.add(child);
931 }
932 }
933 return false;
934 }
935
936 /**
937 * Compares the provided values and returns their ordering.
938 * @param {Chunk} chunkA first chunk
939 * @param {Chunk} chunkB second chunk
940 * @returns {-1 | 0 | 1} this is a comparator function like sort and returns -1, 0, or 1 based on sort order
941 */
942 compareChunks(chunkA, chunkB) {
943 const cgcA = this._getChunkGraphChunk(chunkA);
944 const cgcB = this._getChunkGraphChunk(chunkB);
945 if (cgcA.modules.size > cgcB.modules.size) return -1;
946 if (cgcA.modules.size < cgcB.modules.size) return 1;
947 cgcA.modules.sortWith(compareModulesByIdentifier);
948 cgcB.modules.sortWith(compareModulesByIdentifier);
949 return compareModuleIterables(cgcA.modules, cgcB.modules);
950 }
951
952 /**
953 * Gets chunk modules size.
954 * @param {Chunk} chunk the chunk
955 * @returns {number} total size of all modules in the chunk
956 */
957 getChunkModulesSize(chunk) {
958 const cgc = this._getChunkGraphChunk(chunk);
959 return cgc.modules.getFromUnorderedCache(getModulesSize);
960 }
961
962 /**
963 * Gets chunk modules sizes.
964 * @param {Chunk} chunk the chunk
965 * @returns {Record<string, number>} total sizes of all modules in the chunk by source type
966 */
967 getChunkModulesSizes(chunk) {
968 const cgc = this._getChunkGraphChunk(chunk);
969 return cgc.modules.getFromUnorderedCache(getModulesSizes);
970 }
971
972 /**
973 * Gets chunk root modules.
974 * @param {Chunk} chunk the chunk
975 * @returns {Module[]} root modules of the chunks (ordered by identifier)
976 */
977 getChunkRootModules(chunk) {
978 const cgc = this._getChunkGraphChunk(chunk);
979 return cgc.modules.getFromUnorderedCache(this._getGraphRoots);
980 }
981
982 /**
983 * Returns total size of the chunk.
984 * @param {Chunk} chunk the chunk
985 * @param {ChunkSizeOptions} options options object
986 * @returns {number} total size of the chunk
987 */
988 getChunkSize(chunk, options = {}) {
989 const cgc = this._getChunkGraphChunk(chunk);
990 const modulesSize = cgc.modules.getFromUnorderedCache(getModulesSize);
991 const chunkOverhead =
992 typeof options.chunkOverhead === "number" ? options.chunkOverhead : 10000;
993 const entryChunkMultiplicator =
994 typeof options.entryChunkMultiplicator === "number"
995 ? options.entryChunkMultiplicator
996 : 10;
997 return (
998 chunkOverhead +
999 modulesSize * (chunk.canBeInitial() ? entryChunkMultiplicator : 1)
1000 );
1001 }
1002
1003 /**
1004 * Gets integrated chunks size.
1005 * @param {Chunk} chunkA chunk
1006 * @param {Chunk} chunkB chunk
1007 * @param {ChunkSizeOptions} options options object
1008 * @returns {number} total size of the chunk or false if chunks can't be integrated
1009 */
1010 getIntegratedChunksSize(chunkA, chunkB, options = {}) {
1011 const cgcA = this._getChunkGraphChunk(chunkA);
1012 const cgcB = this._getChunkGraphChunk(chunkB);
1013 const allModules = new Set(cgcA.modules);
1014 for (const m of cgcB.modules) allModules.add(m);
1015 const modulesSize = getModulesSize(allModules);
1016 const chunkOverhead =
1017 typeof options.chunkOverhead === "number" ? options.chunkOverhead : 10000;
1018 const entryChunkMultiplicator =
1019 typeof options.entryChunkMultiplicator === "number"
1020 ? options.entryChunkMultiplicator
1021 : 10;
1022 return (
1023 chunkOverhead +
1024 modulesSize *
1025 (chunkA.canBeInitial() || chunkB.canBeInitial()
1026 ? entryChunkMultiplicator
1027 : 1)
1028 );
1029 }
1030
1031 /**
1032 * Checks whether it can chunks be integrated.
1033 * @param {Chunk} chunkA chunk
1034 * @param {Chunk} chunkB chunk
1035 * @returns {boolean} true, if chunks could be integrated
1036 */
1037 canChunksBeIntegrated(chunkA, chunkB) {
1038 if (chunkA.preventIntegration || chunkB.preventIntegration) {
1039 return false;
1040 }
1041
1042 const hasRuntimeA = chunkA.hasRuntime();
1043 const hasRuntimeB = chunkB.hasRuntime();
1044
1045 if (hasRuntimeA !== hasRuntimeB) {
1046 if (hasRuntimeA) {
1047 return isAvailableChunk(chunkA, chunkB);
1048 } else if (hasRuntimeB) {
1049 return isAvailableChunk(chunkB, chunkA);
1050 }
1051
1052 return false;
1053 }
1054
1055 if (
1056 this.getNumberOfEntryModules(chunkA) > 0 ||
1057 this.getNumberOfEntryModules(chunkB) > 0
1058 ) {
1059 return false;
1060 }
1061
1062 return true;
1063 }
1064
1065 /**
1066 * Processes the provided chunk a.
1067 * @param {Chunk} chunkA the target chunk
1068 * @param {Chunk} chunkB the chunk to integrate
1069 * @returns {void}
1070 */
1071 integrateChunks(chunkA, chunkB) {
1072 // Decide for one name (deterministic)
1073 if (chunkA.name && chunkB.name) {
1074 if (
1075 this.getNumberOfEntryModules(chunkA) > 0 ===
1076 this.getNumberOfEntryModules(chunkB) > 0
1077 ) {
1078 // When both chunks have entry modules or none have one, use
1079 // shortest name
1080 if (chunkA.name.length !== chunkB.name.length) {
1081 chunkA.name =
1082 chunkA.name.length < chunkB.name.length ? chunkA.name : chunkB.name;
1083 } else {
1084 chunkA.name = chunkA.name < chunkB.name ? chunkA.name : chunkB.name;
1085 }
1086 } else if (this.getNumberOfEntryModules(chunkB) > 0) {
1087 // Pick the name of the chunk with the entry module
1088 chunkA.name = chunkB.name;
1089 }
1090 } else if (chunkB.name) {
1091 chunkA.name = chunkB.name;
1092 }
1093
1094 // Merge id name hints
1095 for (const hint of chunkB.idNameHints) {
1096 chunkA.idNameHints.add(hint);
1097 }
1098
1099 // Merge runtime
1100 chunkA.runtime = mergeRuntime(chunkA.runtime, chunkB.runtime);
1101
1102 // getChunkModules is used here to create a clone, because disconnectChunkAndModule modifies
1103 for (const module of this.getChunkModules(chunkB)) {
1104 this.disconnectChunkAndModule(chunkB, module);
1105 this.connectChunkAndModule(chunkA, module);
1106 }
1107
1108 for (const [
1109 module,
1110 chunkGroup
1111 ] of this.getChunkEntryModulesWithChunkGroupIterable(chunkB)) {
1112 this.disconnectChunkAndEntryModule(chunkB, module);
1113 this.connectChunkAndEntryModule(
1114 chunkA,
1115 module,
1116 /** @type {Entrypoint} */
1117 (chunkGroup)
1118 );
1119 }
1120
1121 for (const chunkGroup of chunkB.groupsIterable) {
1122 chunkGroup.replaceChunk(chunkB, chunkA);
1123 chunkA.addGroup(chunkGroup);
1124 chunkB.removeGroup(chunkGroup);
1125 }
1126 ChunkGraph.clearChunkGraphForChunk(chunkB);
1127 }
1128
1129 /**
1130 * Upgrade dependent to full hash modules.
1131 * @param {Chunk} chunk the chunk to upgrade
1132 * @returns {void}
1133 */
1134 upgradeDependentToFullHashModules(chunk) {
1135 const cgc = this._getChunkGraphChunk(chunk);
1136 if (cgc.dependentHashModules === undefined) return;
1137 if (cgc.fullHashModules === undefined) {
1138 cgc.fullHashModules = cgc.dependentHashModules;
1139 } else {
1140 for (const m of cgc.dependentHashModules) {
1141 cgc.fullHashModules.add(m);
1142 }
1143 cgc.dependentHashModules = undefined;
1144 }
1145 }
1146
1147 /**
1148 * Checks whether this chunk graph is entry module in chunk.
1149 * @param {Module} module the checked module
1150 * @param {Chunk} chunk the checked chunk
1151 * @returns {boolean} true, if the chunk contains the module as entry
1152 */
1153 isEntryModuleInChunk(module, chunk) {
1154 const cgc = this._getChunkGraphChunk(chunk);
1155 return cgc.entryModules.has(module);
1156 }
1157
1158 /**
1159 * Connects chunk and entry module.
1160 * @param {Chunk} chunk the new chunk
1161 * @param {Module} module the entry module
1162 * @param {Entrypoint} entrypoint the chunk group which must be loaded before the module is executed
1163 * @returns {void}
1164 */
1165 connectChunkAndEntryModule(chunk, module, entrypoint) {
1166 const cgm = this._getChunkGraphModule(module);
1167 const cgc = this._getChunkGraphChunk(chunk);
1168 if (cgm.entryInChunks === undefined) {
1169 cgm.entryInChunks = new Set();
1170 }
1171 cgm.entryInChunks.add(chunk);
1172 cgc.entryModules.set(module, entrypoint);
1173 }
1174
1175 /**
1176 * Connects chunk and runtime module.
1177 * @param {Chunk} chunk the new chunk
1178 * @param {RuntimeModule} module the runtime module
1179 * @returns {void}
1180 */
1181 connectChunkAndRuntimeModule(chunk, module) {
1182 const cgm = this._getChunkGraphModule(module);
1183 const cgc = this._getChunkGraphChunk(chunk);
1184 if (cgm.runtimeInChunks === undefined) {
1185 cgm.runtimeInChunks = new Set();
1186 }
1187 cgm.runtimeInChunks.add(chunk);
1188 cgc.runtimeModules.add(module);
1189 }
1190
1191 /**
1192 * Adds full hash module to chunk.
1193 * @param {Chunk} chunk the new chunk
1194 * @param {RuntimeModule} module the module that require a full hash
1195 * @returns {void}
1196 */
1197 addFullHashModuleToChunk(chunk, module) {
1198 const cgc = this._getChunkGraphChunk(chunk);
1199 if (cgc.fullHashModules === undefined) cgc.fullHashModules = new Set();
1200 cgc.fullHashModules.add(module);
1201 }
1202
1203 /**
1204 * Adds dependent hash module to chunk.
1205 * @param {Chunk} chunk the new chunk
1206 * @param {RuntimeModule} module the module that require a full hash
1207 * @returns {void}
1208 */
1209 addDependentHashModuleToChunk(chunk, module) {
1210 const cgc = this._getChunkGraphChunk(chunk);
1211 if (cgc.dependentHashModules === undefined) {
1212 cgc.dependentHashModules = new Set();
1213 }
1214 cgc.dependentHashModules.add(module);
1215 }
1216
1217 /**
1218 * Disconnects chunk and entry module.
1219 * @param {Chunk} chunk the new chunk
1220 * @param {Module} module the entry module
1221 * @returns {void}
1222 */
1223 disconnectChunkAndEntryModule(chunk, module) {
1224 const cgm = this._getChunkGraphModule(module);
1225 const cgc = this._getChunkGraphChunk(chunk);
1226 /** @type {EntryInChunks} */
1227 (cgm.entryInChunks).delete(chunk);
1228 if (/** @type {EntryInChunks} */ (cgm.entryInChunks).size === 0) {
1229 cgm.entryInChunks = undefined;
1230 }
1231 cgc.entryModules.delete(module);
1232 }
1233
1234 /**
1235 * Disconnects chunk and runtime module.
1236 * @param {Chunk} chunk the new chunk
1237 * @param {RuntimeModule} module the runtime module
1238 * @returns {void}
1239 */
1240 disconnectChunkAndRuntimeModule(chunk, module) {
1241 const cgm = this._getChunkGraphModule(module);
1242 const cgc = this._getChunkGraphChunk(chunk);
1243 /** @type {RuntimeInChunks} */
1244 (cgm.runtimeInChunks).delete(chunk);
1245 if (/** @type {RuntimeInChunks} */ (cgm.runtimeInChunks).size === 0) {
1246 cgm.runtimeInChunks = undefined;
1247 }
1248 cgc.runtimeModules.delete(module);
1249 }
1250
1251 /**
1252 * Disconnects entry module.
1253 * @param {Module} module the entry module, it will no longer be entry
1254 * @returns {void}
1255 */
1256 disconnectEntryModule(module) {
1257 const cgm = this._getChunkGraphModule(module);
1258 for (const chunk of /** @type {EntryInChunks} */ (cgm.entryInChunks)) {
1259 const cgc = this._getChunkGraphChunk(chunk);
1260 cgc.entryModules.delete(module);
1261 }
1262 cgm.entryInChunks = undefined;
1263 }
1264
1265 /**
1266 * Disconnects entries.
1267 * @param {Chunk} chunk the chunk, for which all entries will be removed
1268 * @returns {void}
1269 */
1270 disconnectEntries(chunk) {
1271 const cgc = this._getChunkGraphChunk(chunk);
1272 for (const module of cgc.entryModules.keys()) {
1273 const cgm = this._getChunkGraphModule(module);
1274 /** @type {EntryInChunks} */
1275 (cgm.entryInChunks).delete(chunk);
1276 if (/** @type {EntryInChunks} */ (cgm.entryInChunks).size === 0) {
1277 cgm.entryInChunks = undefined;
1278 }
1279 }
1280 cgc.entryModules.clear();
1281 }
1282
1283 /**
1284 * Gets number of entry modules.
1285 * @param {Chunk} chunk the chunk
1286 * @returns {number} the amount of entry modules in chunk
1287 */
1288 getNumberOfEntryModules(chunk) {
1289 const cgc = this._getChunkGraphChunk(chunk);
1290 return cgc.entryModules.size;
1291 }
1292
1293 /**
1294 * Gets number of runtime modules.
1295 * @param {Chunk} chunk the chunk
1296 * @returns {number} the amount of entry modules in chunk
1297 */
1298 getNumberOfRuntimeModules(chunk) {
1299 const cgc = this._getChunkGraphChunk(chunk);
1300 return cgc.runtimeModules.size;
1301 }
1302
1303 /**
1304 * Gets chunk entry modules iterable.
1305 * @param {Chunk} chunk the chunk
1306 * @returns {Iterable<Module>} iterable of modules (do not modify)
1307 */
1308 getChunkEntryModulesIterable(chunk) {
1309 const cgc = this._getChunkGraphChunk(chunk);
1310 return cgc.entryModules.keys();
1311 }
1312
1313 /**
1314 * Gets chunk entry dependent chunks iterable.
1315 * @param {Chunk} chunk the chunk
1316 * @returns {Iterable<Chunk>} iterable of chunks
1317 */
1318 getChunkEntryDependentChunksIterable(chunk) {
1319 /** @type {Chunks} */
1320 const set = new Set();
1321 for (const chunkGroup of chunk.groupsIterable) {
1322 if (chunkGroup instanceof Entrypoint) {
1323 const entrypointChunk = chunkGroup.getEntrypointChunk();
1324 const cgc = this._getChunkGraphChunk(entrypointChunk);
1325 for (const chunkGroup of cgc.entryModules.values()) {
1326 for (const c of chunkGroup.chunks) {
1327 if (c !== chunk && c !== entrypointChunk && !c.hasRuntime()) {
1328 set.add(c);
1329 }
1330 }
1331 }
1332 }
1333 }
1334
1335 return set;
1336 }
1337
1338 /**
1339 * Gets runtime chunk dependent chunks iterable.
1340 * @param {Chunk} chunk the chunk
1341 * @returns {Iterable<Chunk>} iterable of chunks and include chunks from children entrypoints
1342 */
1343 getRuntimeChunkDependentChunksIterable(chunk) {
1344 /** @type {Chunks} */
1345 const set = new Set();
1346
1347 /** @type {Entrypoints} */
1348 const entrypoints = new Set();
1349
1350 for (const chunkGroup of chunk.groupsIterable) {
1351 if (chunkGroup instanceof Entrypoint) {
1352 const queue = [chunkGroup];
1353 while (queue.length > 0) {
1354 const current = queue.shift();
1355 if (current) {
1356 entrypoints.add(current);
1357
1358 let hasChildrenEntrypoint = false;
1359 for (const child of current.childrenIterable) {
1360 if (child instanceof Entrypoint && child.dependOn(current)) {
1361 hasChildrenEntrypoint = true;
1362 queue.push(/** @type {Entrypoint} */ (child));
1363 }
1364 }
1365 // entryChunkB: hasChildrenEntrypoint = true
1366 // entryChunkA: dependOn = entryChunkB
1367 if (hasChildrenEntrypoint) {
1368 const entrypointChunk = current.getEntrypointChunk();
1369 if (entrypointChunk !== chunk && !entrypointChunk.hasRuntime()) {
1370 // add entryChunkB to set
1371 set.add(entrypointChunk);
1372 }
1373 }
1374 }
1375 }
1376 }
1377 }
1378
1379 for (const entrypoint of entrypoints) {
1380 const entrypointChunk = entrypoint.getEntrypointChunk();
1381 const cgc = this._getChunkGraphChunk(entrypointChunk);
1382 for (const chunkGroup of cgc.entryModules.values()) {
1383 for (const c of chunkGroup.chunks) {
1384 if (c !== chunk && c !== entrypointChunk && !c.hasRuntime()) {
1385 set.add(c);
1386 }
1387 }
1388 }
1389 }
1390 return set;
1391 }
1392
1393 /**
1394 * Checks whether this chunk graph contains the chunk.
1395 * @param {Chunk} chunk the chunk
1396 * @returns {boolean} true, when it has dependent chunks
1397 */
1398 hasChunkEntryDependentChunks(chunk) {
1399 const cgc = this._getChunkGraphChunk(chunk);
1400 for (const chunkGroup of cgc.entryModules.values()) {
1401 for (const c of chunkGroup.chunks) {
1402 if (c !== chunk) {
1403 return true;
1404 }
1405 }
1406 }
1407 return false;
1408 }
1409
1410 /**
1411 * Gets chunk runtime modules iterable.
1412 * @param {Chunk} chunk the chunk
1413 * @returns {Iterable<RuntimeModule>} iterable of modules (do not modify)
1414 */
1415 getChunkRuntimeModulesIterable(chunk) {
1416 const cgc = this._getChunkGraphChunk(chunk);
1417 return cgc.runtimeModules;
1418 }
1419
1420 /**
1421 * Gets chunk runtime modules in order.
1422 * @param {Chunk} chunk the chunk
1423 * @returns {RuntimeModule[]} array of modules in order of execution
1424 */
1425 getChunkRuntimeModulesInOrder(chunk) {
1426 const cgc = this._getChunkGraphChunk(chunk);
1427 const array = [...cgc.runtimeModules];
1428 array.sort(
1429 concatComparators(
1430 compareSelect(
1431 (r) => /** @type {RuntimeModule} */ (r).stage,
1432 compareIds
1433 ),
1434 compareModulesByIdentifier
1435 )
1436 );
1437 return array;
1438 }
1439
1440 /**
1441 * Gets chunk full hash modules iterable.
1442 * @param {Chunk} chunk the chunk
1443 * @returns {Iterable<RuntimeModule> | undefined} iterable of modules (do not modify)
1444 */
1445 getChunkFullHashModulesIterable(chunk) {
1446 const cgc = this._getChunkGraphChunk(chunk);
1447 return cgc.fullHashModules;
1448 }
1449
1450 /**
1451 * Gets chunk full hash modules set.
1452 * @param {Chunk} chunk the chunk
1453 * @returns {ReadonlySet<RuntimeModule> | undefined} set of modules (do not modify)
1454 */
1455 getChunkFullHashModulesSet(chunk) {
1456 const cgc = this._getChunkGraphChunk(chunk);
1457 return cgc.fullHashModules;
1458 }
1459
1460 /**
1461 * Gets chunk dependent hash modules iterable.
1462 * @param {Chunk} chunk the chunk
1463 * @returns {Iterable<RuntimeModule> | undefined} iterable of modules (do not modify)
1464 */
1465 getChunkDependentHashModulesIterable(chunk) {
1466 const cgc = this._getChunkGraphChunk(chunk);
1467 return cgc.dependentHashModules;
1468 }
1469
1470 /**
1471 * Gets chunk entry modules with chunk group iterable.
1472 * @param {Chunk} chunk the chunk
1473 * @returns {Iterable<EntryModuleWithChunkGroup>} iterable of modules (do not modify)
1474 */
1475 getChunkEntryModulesWithChunkGroupIterable(chunk) {
1476 const cgc = this._getChunkGraphChunk(chunk);
1477 return cgc.entryModules;
1478 }
1479
1480 /**
1481 * Gets block chunk group.
1482 * @param {AsyncDependenciesBlock} depBlock the async block
1483 * @returns {ChunkGroup | undefined} the chunk group
1484 */
1485 getBlockChunkGroup(depBlock) {
1486 return this._blockChunkGroups.get(depBlock);
1487 }
1488
1489 /**
1490 * Connects block and chunk group.
1491 * @param {AsyncDependenciesBlock} depBlock the async block
1492 * @param {ChunkGroup} chunkGroup the chunk group
1493 * @returns {void}
1494 */
1495 connectBlockAndChunkGroup(depBlock, chunkGroup) {
1496 this._blockChunkGroups.set(depBlock, chunkGroup);
1497 chunkGroup.addBlock(depBlock);
1498 }
1499
1500 /**
1501 * Disconnects chunk group.
1502 * @param {ChunkGroup} chunkGroup the chunk group
1503 * @returns {void}
1504 */
1505 disconnectChunkGroup(chunkGroup) {
1506 for (const block of chunkGroup.blocksIterable) {
1507 this._blockChunkGroups.delete(block);
1508 }
1509 // TODO refactor by moving blocks list into ChunkGraph
1510 chunkGroup._blocks.clear();
1511 }
1512
1513 /**
1514 * Returns the id of the module.
1515 * @param {Module} module the module
1516 * @returns {ModuleId | null} the id of the module
1517 */
1518 getModuleId(module) {
1519 const cgm = this._getChunkGraphModule(module);
1520 return cgm.id;
1521 }
1522
1523 /**
1524 * Updates module id using the provided module.
1525 * @param {Module} module the module
1526 * @param {ModuleId} id the id of the module
1527 * @returns {void}
1528 */
1529 setModuleId(module, id) {
1530 const cgm = this._getChunkGraphModule(module);
1531 cgm.id = id;
1532 }
1533
1534 /**
1535 * Returns the id of the runtime.
1536 * @param {string} runtime runtime
1537 * @returns {RuntimeId} the id of the runtime
1538 */
1539 getRuntimeId(runtime) {
1540 return /** @type {RuntimeId} */ (this._runtimeIds.get(runtime));
1541 }
1542
1543 /**
1544 * Updates runtime id using the provided runtime.
1545 * @param {string} runtime runtime
1546 * @param {RuntimeId} id the id of the runtime
1547 * @returns {void}
1548 */
1549 setRuntimeId(runtime, id) {
1550 this._runtimeIds.set(runtime, id);
1551 }
1552
1553 /**
1554 * Get module hash info.
1555 * @template T
1556 * @param {Module} module the module
1557 * @param {RuntimeSpecMap<T>} hashes hashes data
1558 * @param {RuntimeSpec} runtime the runtime
1559 * @returns {T} hash
1560 */
1561 _getModuleHashInfo(module, hashes, runtime) {
1562 if (!hashes) {
1563 throw new Error(
1564 `Module ${module.identifier()} has no hash info for runtime ${runtimeToString(
1565 runtime
1566 )} (hashes not set at all)`
1567 );
1568 } else if (runtime === undefined) {
1569 const hashInfoItems = new Set(hashes.values());
1570 if (hashInfoItems.size !== 1) {
1571 throw new Error(
1572 `No unique hash info entry for unspecified runtime for ${module.identifier()} (existing runtimes: ${Array.from(
1573 hashes.keys(),
1574 (r) => runtimeToString(r)
1575 ).join(", ")}).
1576Caller might not support runtime-dependent code generation (opt-out via optimization.usedExports: "global").`
1577 );
1578 }
1579 return /** @type {T} */ (first(hashInfoItems));
1580 } else {
1581 const hashInfo = hashes.get(runtime);
1582 if (!hashInfo) {
1583 throw new Error(
1584 `Module ${module.identifier()} has no hash info for runtime ${runtimeToString(
1585 runtime
1586 )} (available runtimes ${Array.from(
1587 hashes.keys(),
1588 runtimeToString
1589 ).join(", ")})`
1590 );
1591 }
1592 return hashInfo;
1593 }
1594 }
1595
1596 /**
1597 * Checks whether this chunk graph contains the module.
1598 * @param {Module} module the module
1599 * @param {RuntimeSpec} runtime the runtime
1600 * @returns {boolean} true, if the module has hashes for this runtime
1601 */
1602 hasModuleHashes(module, runtime) {
1603 const cgm = this._getChunkGraphModule(module);
1604 const hashes = /** @type {RuntimeSpecMap<ModuleHashInfo>} */ (cgm.hashes);
1605 return hashes && hashes.has(runtime);
1606 }
1607
1608 /**
1609 * Returns hash.
1610 * @param {Module} module the module
1611 * @param {RuntimeSpec} runtime the runtime
1612 * @returns {string} hash
1613 */
1614 getModuleHash(module, runtime) {
1615 const cgm = this._getChunkGraphModule(module);
1616 const hashes = /** @type {RuntimeSpecMap<ModuleHashInfo>} */ (cgm.hashes);
1617 return this._getModuleHashInfo(module, hashes, runtime).hash;
1618 }
1619
1620 /**
1621 * Gets rendered module hash.
1622 * @param {Module} module the module
1623 * @param {RuntimeSpec} runtime the runtime
1624 * @returns {string} hash
1625 */
1626 getRenderedModuleHash(module, runtime) {
1627 const cgm = this._getChunkGraphModule(module);
1628 const hashes = /** @type {RuntimeSpecMap<ModuleHashInfo>} */ (cgm.hashes);
1629 return this._getModuleHashInfo(module, hashes, runtime).renderedHash;
1630 }
1631
1632 /**
1633 * Sets module hashes.
1634 * @param {Module} module the module
1635 * @param {RuntimeSpec} runtime the runtime
1636 * @param {string} hash the full hash
1637 * @param {string} renderedHash the shortened hash for rendering
1638 * @returns {void}
1639 */
1640 setModuleHashes(module, runtime, hash, renderedHash) {
1641 const cgm = this._getChunkGraphModule(module);
1642 if (cgm.hashes === undefined) {
1643 cgm.hashes = new RuntimeSpecMap();
1644 }
1645 cgm.hashes.set(runtime, new ModuleHashInfo(hash, renderedHash));
1646 }
1647
1648 /**
1649 * Adds module runtime requirements.
1650 * @param {Module} module the module
1651 * @param {RuntimeSpec} runtime the runtime
1652 * @param {RuntimeRequirements} items runtime requirements to be added (ownership of this Set is given to ChunkGraph when transferOwnership not false)
1653 * @param {boolean} transferOwnership true: transfer ownership of the items object, false: items is immutable and shared and won't be modified
1654 * @returns {void}
1655 */
1656 addModuleRuntimeRequirements(
1657 module,
1658 runtime,
1659 items,
1660 transferOwnership = true
1661 ) {
1662 const cgm = this._getChunkGraphModule(module);
1663 const runtimeRequirementsMap = cgm.runtimeRequirements;
1664 if (runtimeRequirementsMap === undefined) {
1665 /** @type {ChunkGraphRuntimeRequirements} */
1666 const map = new RuntimeSpecMap();
1667 // TODO avoid cloning item and track ownership instead
1668 map.set(runtime, transferOwnership ? items : new Set(items));
1669 cgm.runtimeRequirements = map;
1670 return;
1671 }
1672 runtimeRequirementsMap.update(runtime, (runtimeRequirements) => {
1673 if (runtimeRequirements === undefined) {
1674 return transferOwnership ? items : new Set(items);
1675 } else if (!transferOwnership || runtimeRequirements.size >= items.size) {
1676 for (const item of items) runtimeRequirements.add(item);
1677 return runtimeRequirements;
1678 }
1679
1680 for (const item of runtimeRequirements) items.add(item);
1681 return items;
1682 });
1683 }
1684
1685 /**
1686 * Adds chunk runtime requirements.
1687 * @param {Chunk} chunk the chunk
1688 * @param {RuntimeRequirements} items runtime requirements to be added (ownership of this Set is given to ChunkGraph)
1689 * @returns {void}
1690 */
1691 addChunkRuntimeRequirements(chunk, items) {
1692 const cgc = this._getChunkGraphChunk(chunk);
1693 const runtimeRequirements = cgc.runtimeRequirements;
1694 if (runtimeRequirements === undefined) {
1695 cgc.runtimeRequirements = items;
1696 } else if (runtimeRequirements.size >= items.size) {
1697 for (const item of items) runtimeRequirements.add(item);
1698 } else {
1699 for (const item of runtimeRequirements) items.add(item);
1700 cgc.runtimeRequirements = items;
1701 }
1702 }
1703
1704 /**
1705 * Adds tree runtime requirements.
1706 * @param {Chunk} chunk the chunk
1707 * @param {Iterable<string>} items runtime requirements to be added
1708 * @returns {void}
1709 */
1710 addTreeRuntimeRequirements(chunk, items) {
1711 const cgc = this._getChunkGraphChunk(chunk);
1712 const runtimeRequirements = cgc.runtimeRequirementsInTree;
1713 for (const item of items) runtimeRequirements.add(item);
1714 }
1715
1716 /**
1717 * Gets module runtime requirements.
1718 * @param {Module} module the module
1719 * @param {RuntimeSpec} runtime the runtime
1720 * @returns {ReadOnlyRuntimeRequirements} runtime requirements
1721 */
1722 getModuleRuntimeRequirements(module, runtime) {
1723 const cgm = this._getChunkGraphModule(module);
1724 const runtimeRequirements =
1725 cgm.runtimeRequirements && cgm.runtimeRequirements.get(runtime);
1726 return runtimeRequirements === undefined ? EMPTY_SET : runtimeRequirements;
1727 }
1728
1729 /**
1730 * Gets chunk runtime requirements.
1731 * @param {Chunk} chunk the chunk
1732 * @returns {ReadOnlyRuntimeRequirements} runtime requirements
1733 */
1734 getChunkRuntimeRequirements(chunk) {
1735 const cgc = this._getChunkGraphChunk(chunk);
1736 const runtimeRequirements = cgc.runtimeRequirements;
1737 return runtimeRequirements === undefined ? EMPTY_SET : runtimeRequirements;
1738 }
1739
1740 /**
1741 * Gets module graph hash.
1742 * @param {Module} module the module
1743 * @param {RuntimeSpec} runtime the runtime
1744 * @param {boolean} withConnections include connections
1745 * @returns {string} hash
1746 */
1747 getModuleGraphHash(module, runtime, withConnections = true) {
1748 const cgm = this._getChunkGraphModule(module);
1749 return withConnections
1750 ? this._getModuleGraphHashWithConnections(cgm, module, runtime)
1751 : this._getModuleGraphHashBigInt(cgm, module, runtime).toString(16);
1752 }
1753
1754 /**
1755 * Gets module graph hash big int.
1756 * @param {Module} module the module
1757 * @param {RuntimeSpec} runtime the runtime
1758 * @param {boolean} withConnections include connections
1759 * @returns {bigint} hash
1760 */
1761 getModuleGraphHashBigInt(module, runtime, withConnections = true) {
1762 const cgm = this._getChunkGraphModule(module);
1763 return withConnections
1764 ? BigInt(
1765 `0x${this._getModuleGraphHashWithConnections(cgm, module, runtime)}`
1766 )
1767 : this._getModuleGraphHashBigInt(cgm, module, runtime);
1768 }
1769
1770 /**
1771 * Get module graph hash big int.
1772 * @param {ChunkGraphModule} cgm the ChunkGraphModule
1773 * @param {Module} module the module
1774 * @param {RuntimeSpec} runtime the runtime
1775 * @returns {bigint} hash as big int
1776 */
1777 _getModuleGraphHashBigInt(cgm, module, runtime) {
1778 if (cgm.graphHashes === undefined) {
1779 cgm.graphHashes = new RuntimeSpecMap();
1780 }
1781 const graphHash = cgm.graphHashes.provide(runtime, () => {
1782 const hash = createHash(this._hashFunction);
1783 hash.update(`${cgm.id}${this.moduleGraph.isAsync(module)}`);
1784 const sourceTypes = this._getOverwrittenModuleSourceTypes(module);
1785 if (sourceTypes !== undefined) {
1786 for (const type of sourceTypes) hash.update(type);
1787 }
1788 this.moduleGraph.getExportsInfo(module).updateHash(hash, runtime);
1789 return BigInt(`0x${hash.digest("hex")}`);
1790 });
1791 return graphHash;
1792 }
1793
1794 /**
1795 * Get module graph hash with connections.
1796 * @param {ChunkGraphModule} cgm the ChunkGraphModule
1797 * @param {Module} module the module
1798 * @param {RuntimeSpec} runtime the runtime
1799 * @returns {string} hash
1800 */
1801 _getModuleGraphHashWithConnections(cgm, module, runtime) {
1802 if (cgm.graphHashesWithConnections === undefined) {
1803 cgm.graphHashesWithConnections = new RuntimeSpecMap();
1804 }
1805
1806 /**
1807 * Active state to string.
1808 * @param {ConnectionState} state state
1809 * @returns {"F" | "T" | "O"} result
1810 */
1811 const activeStateToString = (state) => {
1812 if (state === false) return "F";
1813 if (state === true) return "T";
1814 if (state === ModuleGraphConnection.TRANSITIVE_ONLY) return "O";
1815 throw new Error("Not implemented active state");
1816 };
1817 const strict = module.buildMeta && module.buildMeta.strictHarmonyModule;
1818 return cgm.graphHashesWithConnections.provide(runtime, () => {
1819 const graphHash = this._getModuleGraphHashBigInt(
1820 cgm,
1821 module,
1822 runtime
1823 ).toString(16);
1824 const connections = this.moduleGraph.getOutgoingConnections(module);
1825 /** @type {Set<Module>} */
1826 const activeNamespaceModules = new Set();
1827 /** @type {Map<string, Module | Set<Module>>} */
1828 const connectedModules = new Map();
1829 /**
1830 * Process connection.
1831 * @param {ModuleGraphConnection} connection connection
1832 * @param {string} stateInfo state info
1833 */
1834 const processConnection = (connection, stateInfo) => {
1835 const module = connection.module;
1836 stateInfo += module.getExportsType(this.moduleGraph, strict);
1837 // cspell:word Tnamespace
1838 if (stateInfo === "Tnamespace") {
1839 activeNamespaceModules.add(module);
1840 } else {
1841 const oldModule = connectedModules.get(stateInfo);
1842 if (oldModule === undefined) {
1843 connectedModules.set(stateInfo, module);
1844 } else if (oldModule instanceof Set) {
1845 oldModule.add(module);
1846 } else if (oldModule !== module) {
1847 connectedModules.set(stateInfo, new Set([oldModule, module]));
1848 }
1849 }
1850 };
1851 if (runtime === undefined || typeof runtime === "string") {
1852 for (const connection of connections) {
1853 const state = connection.getActiveState(runtime);
1854 if (state === false) continue;
1855 processConnection(connection, state === true ? "T" : "O");
1856 }
1857 } else {
1858 // cspell:word Tnamespace
1859 for (const connection of connections) {
1860 /** @type {Set<ConnectionState>} */
1861 const states = new Set();
1862 let stateInfo = "";
1863 forEachRuntime(
1864 runtime,
1865 (runtime) => {
1866 const state = connection.getActiveState(runtime);
1867 states.add(state);
1868 stateInfo += activeStateToString(state) + runtime;
1869 },
1870 true
1871 );
1872 if (states.size === 1) {
1873 const state = first(states);
1874 if (state === false) continue;
1875 stateInfo = activeStateToString(
1876 /** @type {ConnectionState} */
1877 (state)
1878 );
1879 }
1880 processConnection(connection, stateInfo);
1881 }
1882 }
1883 // cspell:word Tnamespace
1884 if (activeNamespaceModules.size === 0 && connectedModules.size === 0) {
1885 return graphHash;
1886 }
1887 const connectedModulesInOrder =
1888 connectedModules.size > 1
1889 ? [...connectedModules].sort(([a], [b]) => (a < b ? -1 : 1))
1890 : connectedModules;
1891 const hash = createHash(this._hashFunction);
1892 /**
1893 * Adds module to hash.
1894 * @param {Module} module module
1895 */
1896 const addModuleToHash = (module) => {
1897 hash.update(
1898 this._getModuleGraphHashBigInt(
1899 this._getChunkGraphModule(module),
1900 module,
1901 runtime
1902 ).toString(16)
1903 );
1904 };
1905 /**
1906 * Adds modules to hash.
1907 * @param {Set<Module>} modules modules
1908 */
1909 const addModulesToHash = (modules) => {
1910 let xor = ZERO_BIG_INT;
1911 for (const m of modules) {
1912 xor ^= this._getModuleGraphHashBigInt(
1913 this._getChunkGraphModule(m),
1914 m,
1915 runtime
1916 );
1917 }
1918 hash.update(xor.toString(16));
1919 };
1920 if (activeNamespaceModules.size === 1) {
1921 addModuleToHash(
1922 /** @type {Module} */ (activeNamespaceModules.values().next().value)
1923 );
1924 } else if (activeNamespaceModules.size > 1) {
1925 addModulesToHash(activeNamespaceModules);
1926 }
1927 for (const [stateInfo, modules] of connectedModulesInOrder) {
1928 hash.update(stateInfo);
1929 if (modules instanceof Set) {
1930 addModulesToHash(modules);
1931 } else {
1932 addModuleToHash(modules);
1933 }
1934 }
1935 hash.update(graphHash);
1936 return hash.digest("hex");
1937 });
1938 }
1939
1940 /**
1941 * Gets tree runtime requirements.
1942 * @param {Chunk} chunk the chunk
1943 * @returns {ReadOnlyRuntimeRequirements} runtime requirements
1944 */
1945 getTreeRuntimeRequirements(chunk) {
1946 const cgc = this._getChunkGraphChunk(chunk);
1947 return cgc.runtimeRequirementsInTree;
1948 }
1949
1950 // TODO remove in webpack 6
1951 /**
1952 * Gets chunk graph for module.
1953 * @deprecated
1954 * @param {Module} module the module
1955 * @param {string} deprecateMessage message for the deprecation message
1956 * @param {string} deprecationCode code for the deprecation
1957 * @returns {ChunkGraph} the chunk graph
1958 */
1959 static getChunkGraphForModule(module, deprecateMessage, deprecationCode) {
1960 const fn = deprecateGetChunkGraphForModuleMap.get(deprecateMessage);
1961 if (fn) return fn(module);
1962 const newFn = util.deprecate(
1963 /**
1964 * Handles the callback logic for this hook.
1965 * @param {Module} module the module
1966 * @returns {ChunkGraph} the chunk graph
1967 */
1968 (module) => {
1969 const chunkGraph = chunkGraphForModuleMap.get(module);
1970 if (!chunkGraph) {
1971 throw new Error(
1972 `${
1973 deprecateMessage
1974 }: There was no ChunkGraph assigned to the Module for backward-compat (Use the new API)`
1975 );
1976 }
1977 return chunkGraph;
1978 },
1979 `${deprecateMessage}: Use new ChunkGraph API`,
1980 deprecationCode
1981 );
1982 deprecateGetChunkGraphForModuleMap.set(deprecateMessage, newFn);
1983 return newFn(module);
1984 }
1985
1986 // TODO remove in webpack 6
1987 // BACKWARD-COMPAT START
1988 /**
1989 * Sets chunk graph for module.
1990 * @deprecated
1991 * @param {Module} module the module
1992 * @param {ChunkGraph} chunkGraph the chunk graph
1993 * @returns {void}
1994 */
1995 static setChunkGraphForModule(module, chunkGraph) {
1996 chunkGraphForModuleMap.set(module, chunkGraph);
1997 }
1998
1999 /**
2000 * Clear chunk graph for module.
2001 * @deprecated
2002 * @param {Module} module the module
2003 * @returns {void}
2004 */
2005 static clearChunkGraphForModule(module) {
2006 chunkGraphForModuleMap.delete(module);
2007 }
2008
2009 /**
2010 * Gets chunk graph for chunk.
2011 * @deprecated
2012 * @param {Chunk} chunk the chunk
2013 * @param {string} deprecateMessage message for the deprecation message
2014 * @param {string} deprecationCode code for the deprecation
2015 * @returns {ChunkGraph} the chunk graph
2016 */
2017 static getChunkGraphForChunk(chunk, deprecateMessage, deprecationCode) {
2018 const fn = deprecateGetChunkGraphForChunkMap.get(deprecateMessage);
2019 if (fn) return fn(chunk);
2020 const newFn = util.deprecate(
2021 /**
2022 * Handles the callback logic for this hook.
2023 * @param {Chunk} chunk the chunk
2024 * @returns {ChunkGraph} the chunk graph
2025 */
2026 (chunk) => {
2027 const chunkGraph = chunkGraphForChunkMap.get(chunk);
2028 if (!chunkGraph) {
2029 throw new Error(
2030 `${
2031 deprecateMessage
2032 }There was no ChunkGraph assigned to the Chunk for backward-compat (Use the new API)`
2033 );
2034 }
2035 return chunkGraph;
2036 },
2037 `${deprecateMessage}: Use new ChunkGraph API`,
2038 deprecationCode
2039 );
2040 deprecateGetChunkGraphForChunkMap.set(deprecateMessage, newFn);
2041 return newFn(chunk);
2042 }
2043
2044 /**
2045 * Sets chunk graph for chunk.
2046 * @deprecated
2047 * @param {Chunk} chunk the chunk
2048 * @param {ChunkGraph} chunkGraph the chunk graph
2049 * @returns {void}
2050 */
2051 static setChunkGraphForChunk(chunk, chunkGraph) {
2052 chunkGraphForChunkMap.set(chunk, chunkGraph);
2053 }
2054
2055 /**
2056 * Clear chunk graph for chunk.
2057 * @deprecated
2058 * @param {Chunk} chunk the chunk
2059 * @returns {void}
2060 */
2061 static clearChunkGraphForChunk(chunk) {
2062 chunkGraphForChunkMap.delete(chunk);
2063 }
2064 // BACKWARD-COMPAT END
2065}
2066
2067// TODO remove in webpack 6
2068/** @type {WeakMap<Module, ChunkGraph>} */
2069const chunkGraphForModuleMap = new WeakMap();
2070
2071// TODO remove in webpack 6
2072/** @type {WeakMap<Chunk, ChunkGraph>} */
2073const chunkGraphForChunkMap = new WeakMap();
2074
2075// TODO remove in webpack 6
2076/** @type {Map<string, (module: Module) => ChunkGraph>} */
2077const deprecateGetChunkGraphForModuleMap = new Map();
2078
2079// TODO remove in webpack 6
2080/** @type {Map<string, (chunk: Chunk) => ChunkGraph>} */
2081const deprecateGetChunkGraphForChunkMap = new Map();
2082
2083module.exports = ChunkGraph;
Note: See TracBrowser for help on using the repository browser.