UNPKG

21.5 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const ChunkGraph = require("./ChunkGraph");
9const Entrypoint = require("./Entrypoint");
10const { intersect } = require("./util/SetHelpers");
11const SortableSet = require("./util/SortableSet");
12const StringXor = require("./util/StringXor");
13const {
14 compareModulesByIdentifier,
15 compareChunkGroupsByIndex,
16 compareModulesById
17} = require("./util/comparators");
18const { createArrayToSetDeprecationSet } = require("./util/deprecation");
19const { mergeRuntime } = require("./util/runtime");
20
21/** @typedef {import("webpack-sources").Source} Source */
22/** @typedef {import("./ChunkGraph").ChunkFilterPredicate} ChunkFilterPredicate */
23/** @typedef {import("./ChunkGraph").ChunkSizeOptions} ChunkSizeOptions */
24/** @typedef {import("./ChunkGraph").ModuleFilterPredicate} ModuleFilterPredicate */
25/** @typedef {import("./ChunkGroup")} ChunkGroup */
26/** @typedef {import("./Compilation")} Compilation */
27/** @typedef {import("./Compilation").AssetInfo} AssetInfo */
28/** @typedef {import("./Compilation").PathData} PathData */
29/** @typedef {import("./Entrypoint").EntryOptions} EntryOptions */
30/** @typedef {import("./Module")} Module */
31/** @typedef {import("./ModuleGraph")} ModuleGraph */
32/** @typedef {import("./util/Hash")} Hash */
33/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
34
35const ChunkFilesSet = createArrayToSetDeprecationSet("chunk.files");
36
37/**
38 * @typedef {Object} WithId an object who has an id property *
39 * @property {string | number} id the id of the object
40 */
41
42/**
43 * @deprecated
44 * @typedef {Object} ChunkMaps
45 * @property {Record<string|number, string>} hash
46 * @property {Record<string|number, Record<string, string>>} contentHash
47 * @property {Record<string|number, string>} name
48 */
49
50/**
51 * @deprecated
52 * @typedef {Object} ChunkModuleMaps
53 * @property {Record<string|number, (string|number)[]>} id
54 * @property {Record<string|number, string>} hash
55 */
56
57let debugId = 1000;
58
59/**
60 * A Chunk is a unit of encapsulation for Modules.
61 * Chunks are "rendered" into bundles that get emitted when the build completes.
62 */
63class Chunk {
64 /**
65 * @param {string=} name of chunk being created, is optional (for subclasses)
66 */
67 constructor(name) {
68 /** @type {number | string | null} */
69 this.id = null;
70 /** @type {(number|string)[] | null} */
71 this.ids = null;
72 /** @type {number} */
73 this.debugId = debugId++;
74 /** @type {string} */
75 this.name = name;
76 /** @type {SortableSet<string>} */
77 this.idNameHints = new SortableSet();
78 /** @type {boolean} */
79 this.preventIntegration = false;
80 /** @type {(string | function(PathData, AssetInfo=): string)?} */
81 this.filenameTemplate = undefined;
82 /** @private @type {SortableSet<ChunkGroup>} */
83 this._groups = new SortableSet(undefined, compareChunkGroupsByIndex);
84 /** @type {RuntimeSpec} */
85 this.runtime = undefined;
86 /** @type {Set<string>} */
87 this.files = new ChunkFilesSet();
88 /** @type {Set<string>} */
89 this.auxiliaryFiles = new Set();
90 /** @type {boolean} */
91 this.rendered = false;
92 /** @type {string=} */
93 this.hash = undefined;
94 /** @type {Record<string, string>} */
95 this.contentHash = Object.create(null);
96 /** @type {string=} */
97 this.renderedHash = undefined;
98 /** @type {string=} */
99 this.chunkReason = undefined;
100 /** @type {boolean} */
101 this.extraAsync = false;
102 }
103
104 // TODO remove in webpack 6
105 // BACKWARD-COMPAT START
106 get entryModule() {
107 const entryModules = Array.from(
108 ChunkGraph.getChunkGraphForChunk(
109 this,
110 "Chunk.entryModule",
111 "DEP_WEBPACK_CHUNK_ENTRY_MODULE"
112 ).getChunkEntryModulesIterable(this)
113 );
114 if (entryModules.length === 0) {
115 return undefined;
116 } else if (entryModules.length === 1) {
117 return entryModules[0];
118 } else {
119 throw new Error(
120 "Module.entryModule: Multiple entry modules are not supported by the deprecated API (Use the new ChunkGroup API)"
121 );
122 }
123 }
124
125 /**
126 * @returns {boolean} true, if the chunk contains an entry module
127 */
128 hasEntryModule() {
129 return (
130 ChunkGraph.getChunkGraphForChunk(
131 this,
132 "Chunk.hasEntryModule",
133 "DEP_WEBPACK_CHUNK_HAS_ENTRY_MODULE"
134 ).getNumberOfEntryModules(this) > 0
135 );
136 }
137
138 /**
139 * @param {Module} module the module
140 * @returns {boolean} true, if the chunk could be added
141 */
142 addModule(module) {
143 const chunkGraph = ChunkGraph.getChunkGraphForChunk(
144 this,
145 "Chunk.addModule",
146 "DEP_WEBPACK_CHUNK_ADD_MODULE"
147 );
148 if (chunkGraph.isModuleInChunk(module, this)) return false;
149 chunkGraph.connectChunkAndModule(this, module);
150 return true;
151 }
152
153 /**
154 * @param {Module} module the module
155 * @returns {void}
156 */
157 removeModule(module) {
158 ChunkGraph.getChunkGraphForChunk(
159 this,
160 "Chunk.removeModule",
161 "DEP_WEBPACK_CHUNK_REMOVE_MODULE"
162 ).disconnectChunkAndModule(this, module);
163 }
164
165 /**
166 * @returns {number} the number of module which are contained in this chunk
167 */
168 getNumberOfModules() {
169 return ChunkGraph.getChunkGraphForChunk(
170 this,
171 "Chunk.getNumberOfModules",
172 "DEP_WEBPACK_CHUNK_GET_NUMBER_OF_MODULES"
173 ).getNumberOfChunkModules(this);
174 }
175
176 get modulesIterable() {
177 const chunkGraph = ChunkGraph.getChunkGraphForChunk(
178 this,
179 "Chunk.modulesIterable",
180 "DEP_WEBPACK_CHUNK_MODULES_ITERABLE"
181 );
182 return chunkGraph.getOrderedChunkModulesIterable(
183 this,
184 compareModulesByIdentifier
185 );
186 }
187
188 /**
189 * @param {Chunk} otherChunk the chunk to compare with
190 * @returns {-1|0|1} the comparison result
191 */
192 compareTo(otherChunk) {
193 const chunkGraph = ChunkGraph.getChunkGraphForChunk(
194 this,
195 "Chunk.compareTo",
196 "DEP_WEBPACK_CHUNK_COMPARE_TO"
197 );
198 return chunkGraph.compareChunks(this, otherChunk);
199 }
200
201 /**
202 * @param {Module} module the module
203 * @returns {boolean} true, if the chunk contains the module
204 */
205 containsModule(module) {
206 return ChunkGraph.getChunkGraphForChunk(
207 this,
208 "Chunk.containsModule",
209 "DEP_WEBPACK_CHUNK_CONTAINS_MODULE"
210 ).isModuleInChunk(module, this);
211 }
212
213 /**
214 * @returns {Module[]} the modules for this chunk
215 */
216 getModules() {
217 return ChunkGraph.getChunkGraphForChunk(
218 this,
219 "Chunk.getModules",
220 "DEP_WEBPACK_CHUNK_GET_MODULES"
221 ).getChunkModules(this);
222 }
223
224 /**
225 * @returns {void}
226 */
227 remove() {
228 const chunkGraph = ChunkGraph.getChunkGraphForChunk(
229 this,
230 "Chunk.remove",
231 "DEP_WEBPACK_CHUNK_REMOVE"
232 );
233 chunkGraph.disconnectChunk(this);
234 this.disconnectFromGroups();
235 }
236
237 /**
238 * @param {Module} module the module
239 * @param {Chunk} otherChunk the target chunk
240 * @returns {void}
241 */
242 moveModule(module, otherChunk) {
243 const chunkGraph = ChunkGraph.getChunkGraphForChunk(
244 this,
245 "Chunk.moveModule",
246 "DEP_WEBPACK_CHUNK_MOVE_MODULE"
247 );
248 chunkGraph.disconnectChunkAndModule(this, module);
249 chunkGraph.connectChunkAndModule(otherChunk, module);
250 }
251
252 /**
253 * @param {Chunk} otherChunk the other chunk
254 * @returns {boolean} true, if the specified chunk has been integrated
255 */
256 integrate(otherChunk) {
257 const chunkGraph = ChunkGraph.getChunkGraphForChunk(
258 this,
259 "Chunk.integrate",
260 "DEP_WEBPACK_CHUNK_INTEGRATE"
261 );
262 if (chunkGraph.canChunksBeIntegrated(this, otherChunk)) {
263 chunkGraph.integrateChunks(this, otherChunk);
264 return true;
265 } else {
266 return false;
267 }
268 }
269
270 /**
271 * @param {Chunk} otherChunk the other chunk
272 * @returns {boolean} true, if chunks could be integrated
273 */
274 canBeIntegrated(otherChunk) {
275 const chunkGraph = ChunkGraph.getChunkGraphForChunk(
276 this,
277 "Chunk.canBeIntegrated",
278 "DEP_WEBPACK_CHUNK_CAN_BE_INTEGRATED"
279 );
280 return chunkGraph.canChunksBeIntegrated(this, otherChunk);
281 }
282
283 /**
284 * @returns {boolean} true, if this chunk contains no module
285 */
286 isEmpty() {
287 const chunkGraph = ChunkGraph.getChunkGraphForChunk(
288 this,
289 "Chunk.isEmpty",
290 "DEP_WEBPACK_CHUNK_IS_EMPTY"
291 );
292 return chunkGraph.getNumberOfChunkModules(this) === 0;
293 }
294
295 /**
296 * @returns {number} total size of all modules in this chunk
297 */
298 modulesSize() {
299 const chunkGraph = ChunkGraph.getChunkGraphForChunk(
300 this,
301 "Chunk.modulesSize",
302 "DEP_WEBPACK_CHUNK_MODULES_SIZE"
303 );
304 return chunkGraph.getChunkModulesSize(this);
305 }
306
307 /**
308 * @param {ChunkSizeOptions} options options object
309 * @returns {number} total size of this chunk
310 */
311 size(options = {}) {
312 const chunkGraph = ChunkGraph.getChunkGraphForChunk(
313 this,
314 "Chunk.size",
315 "DEP_WEBPACK_CHUNK_SIZE"
316 );
317 return chunkGraph.getChunkSize(this, options);
318 }
319
320 /**
321 * @param {Chunk} otherChunk the other chunk
322 * @param {ChunkSizeOptions} options options object
323 * @returns {number} total size of the chunk or false if the chunk can't be integrated
324 */
325 integratedSize(otherChunk, options) {
326 const chunkGraph = ChunkGraph.getChunkGraphForChunk(
327 this,
328 "Chunk.integratedSize",
329 "DEP_WEBPACK_CHUNK_INTEGRATED_SIZE"
330 );
331 return chunkGraph.getIntegratedChunksSize(this, otherChunk, options);
332 }
333
334 /**
335 * @param {ModuleFilterPredicate} filterFn function used to filter modules
336 * @returns {ChunkModuleMaps} module map information
337 */
338 getChunkModuleMaps(filterFn) {
339 const chunkGraph = ChunkGraph.getChunkGraphForChunk(
340 this,
341 "Chunk.getChunkModuleMaps",
342 "DEP_WEBPACK_CHUNK_GET_CHUNK_MODULE_MAPS"
343 );
344 /** @type {Record<string|number, (string|number)[]>} */
345 const chunkModuleIdMap = Object.create(null);
346 /** @type {Record<string|number, string>} */
347 const chunkModuleHashMap = Object.create(null);
348
349 for (const asyncChunk of this.getAllAsyncChunks()) {
350 /** @type {(string|number)[]} */
351 let array;
352 for (const module of chunkGraph.getOrderedChunkModulesIterable(
353 asyncChunk,
354 compareModulesById(chunkGraph)
355 )) {
356 if (filterFn(module)) {
357 if (array === undefined) {
358 array = [];
359 chunkModuleIdMap[asyncChunk.id] = array;
360 }
361 const moduleId = chunkGraph.getModuleId(module);
362 array.push(moduleId);
363 chunkModuleHashMap[moduleId] = chunkGraph.getRenderedModuleHash(
364 module,
365 undefined
366 );
367 }
368 }
369 }
370
371 return {
372 id: chunkModuleIdMap,
373 hash: chunkModuleHashMap
374 };
375 }
376
377 /**
378 * @param {ModuleFilterPredicate} filterFn predicate function used to filter modules
379 * @param {ChunkFilterPredicate=} filterChunkFn predicate function used to filter chunks
380 * @returns {boolean} return true if module exists in graph
381 */
382 hasModuleInGraph(filterFn, filterChunkFn) {
383 const chunkGraph = ChunkGraph.getChunkGraphForChunk(
384 this,
385 "Chunk.hasModuleInGraph",
386 "DEP_WEBPACK_CHUNK_HAS_MODULE_IN_GRAPH"
387 );
388 return chunkGraph.hasModuleInGraph(this, filterFn, filterChunkFn);
389 }
390
391 /**
392 * @deprecated
393 * @param {boolean} realHash whether the full hash or the rendered hash is to be used
394 * @returns {ChunkMaps} the chunk map information
395 */
396 getChunkMaps(realHash) {
397 /** @type {Record<string|number, string>} */
398 const chunkHashMap = Object.create(null);
399 /** @type {Record<string|number, Record<string, string>>} */
400 const chunkContentHashMap = Object.create(null);
401 /** @type {Record<string|number, string>} */
402 const chunkNameMap = Object.create(null);
403
404 for (const chunk of this.getAllAsyncChunks()) {
405 chunkHashMap[chunk.id] = realHash ? chunk.hash : chunk.renderedHash;
406 for (const key of Object.keys(chunk.contentHash)) {
407 if (!chunkContentHashMap[key]) {
408 chunkContentHashMap[key] = Object.create(null);
409 }
410 chunkContentHashMap[key][chunk.id] = chunk.contentHash[key];
411 }
412 if (chunk.name) {
413 chunkNameMap[chunk.id] = chunk.name;
414 }
415 }
416
417 return {
418 hash: chunkHashMap,
419 contentHash: chunkContentHashMap,
420 name: chunkNameMap
421 };
422 }
423 // BACKWARD-COMPAT END
424
425 /**
426 * @returns {boolean} whether or not the Chunk will have a runtime
427 */
428 hasRuntime() {
429 for (const chunkGroup of this._groups) {
430 if (
431 chunkGroup instanceof Entrypoint &&
432 chunkGroup.getRuntimeChunk() === this
433 ) {
434 return true;
435 }
436 }
437 return false;
438 }
439
440 /**
441 * @returns {boolean} whether or not this chunk can be an initial chunk
442 */
443 canBeInitial() {
444 for (const chunkGroup of this._groups) {
445 if (chunkGroup.isInitial()) return true;
446 }
447 return false;
448 }
449
450 /**
451 * @returns {boolean} whether this chunk can only be an initial chunk
452 */
453 isOnlyInitial() {
454 if (this._groups.size <= 0) return false;
455 for (const chunkGroup of this._groups) {
456 if (!chunkGroup.isInitial()) return false;
457 }
458 return true;
459 }
460
461 /**
462 * @returns {EntryOptions | undefined} the entry options for this chunk
463 */
464 getEntryOptions() {
465 for (const chunkGroup of this._groups) {
466 if (chunkGroup instanceof Entrypoint) {
467 return chunkGroup.options;
468 }
469 }
470 return undefined;
471 }
472
473 /**
474 * @param {ChunkGroup} chunkGroup the chunkGroup the chunk is being added
475 * @returns {void}
476 */
477 addGroup(chunkGroup) {
478 this._groups.add(chunkGroup);
479 }
480
481 /**
482 * @param {ChunkGroup} chunkGroup the chunkGroup the chunk is being removed from
483 * @returns {void}
484 */
485 removeGroup(chunkGroup) {
486 this._groups.delete(chunkGroup);
487 }
488
489 /**
490 * @param {ChunkGroup} chunkGroup the chunkGroup to check
491 * @returns {boolean} returns true if chunk has chunkGroup reference and exists in chunkGroup
492 */
493 isInGroup(chunkGroup) {
494 return this._groups.has(chunkGroup);
495 }
496
497 /**
498 * @returns {number} the amount of groups that the said chunk is in
499 */
500 getNumberOfGroups() {
501 return this._groups.size;
502 }
503
504 /**
505 * @returns {Iterable<ChunkGroup>} the chunkGroups that the said chunk is referenced in
506 */
507 get groupsIterable() {
508 this._groups.sort();
509 return this._groups;
510 }
511
512 /**
513 * @returns {void}
514 */
515 disconnectFromGroups() {
516 for (const chunkGroup of this._groups) {
517 chunkGroup.removeChunk(this);
518 }
519 }
520
521 /**
522 * @param {Chunk} newChunk the new chunk that will be split out of
523 * @returns {void}
524 */
525 split(newChunk) {
526 for (const chunkGroup of this._groups) {
527 chunkGroup.insertChunk(newChunk, this);
528 newChunk.addGroup(chunkGroup);
529 }
530 for (const idHint of this.idNameHints) {
531 newChunk.idNameHints.add(idHint);
532 }
533 newChunk.runtime = mergeRuntime(newChunk.runtime, this.runtime);
534 }
535
536 /**
537 * @param {Hash} hash hash (will be modified)
538 * @param {ChunkGraph} chunkGraph the chunk graph
539 * @returns {void}
540 */
541 updateHash(hash, chunkGraph) {
542 hash.update(`${this.id} `);
543 hash.update(this.ids ? this.ids.join(",") : "");
544 hash.update(`${this.name || ""} `);
545 const xor = new StringXor();
546 for (const m of chunkGraph.getChunkModulesIterable(this)) {
547 xor.add(chunkGraph.getModuleHash(m, this.runtime));
548 }
549 xor.updateHash(hash);
550 const entryModules =
551 chunkGraph.getChunkEntryModulesWithChunkGroupIterable(this);
552 for (const [m, chunkGroup] of entryModules) {
553 hash.update("entry");
554 hash.update(`${chunkGraph.getModuleId(m)}`);
555 hash.update(chunkGroup.id);
556 }
557 }
558
559 /**
560 * @returns {Set<Chunk>} a set of all the async chunks
561 */
562 getAllAsyncChunks() {
563 const queue = new Set();
564 const chunks = new Set();
565
566 const initialChunks = intersect(
567 Array.from(this.groupsIterable, g => new Set(g.chunks))
568 );
569
570 const initialQueue = new Set(this.groupsIterable);
571
572 for (const chunkGroup of initialQueue) {
573 for (const child of chunkGroup.childrenIterable) {
574 if (child instanceof Entrypoint) {
575 initialQueue.add(child);
576 } else {
577 queue.add(child);
578 }
579 }
580 }
581
582 for (const chunkGroup of queue) {
583 for (const chunk of chunkGroup.chunks) {
584 if (!initialChunks.has(chunk)) {
585 chunks.add(chunk);
586 }
587 }
588 for (const child of chunkGroup.childrenIterable) {
589 queue.add(child);
590 }
591 }
592
593 return chunks;
594 }
595
596 /**
597 * @returns {Set<Chunk>} a set of all the initial chunks (including itself)
598 */
599 getAllInitialChunks() {
600 const chunks = new Set();
601 const queue = new Set(this.groupsIterable);
602 for (const group of queue) {
603 if (group.isInitial()) {
604 for (const c of group.chunks) chunks.add(c);
605 for (const g of group.childrenIterable) queue.add(g);
606 }
607 }
608 return chunks;
609 }
610
611 /**
612 * @returns {Set<Chunk>} a set of all the referenced chunks (including itself)
613 */
614 getAllReferencedChunks() {
615 const queue = new Set(this.groupsIterable);
616 const chunks = new Set();
617
618 for (const chunkGroup of queue) {
619 for (const chunk of chunkGroup.chunks) {
620 chunks.add(chunk);
621 }
622 for (const child of chunkGroup.childrenIterable) {
623 queue.add(child);
624 }
625 }
626
627 return chunks;
628 }
629
630 /**
631 * @returns {Set<Entrypoint>} a set of all the referenced entrypoints
632 */
633 getAllReferencedAsyncEntrypoints() {
634 const queue = new Set(this.groupsIterable);
635 const entrypoints = new Set();
636
637 for (const chunkGroup of queue) {
638 for (const entrypoint of chunkGroup.asyncEntrypointsIterable) {
639 entrypoints.add(entrypoint);
640 }
641 for (const child of chunkGroup.childrenIterable) {
642 queue.add(child);
643 }
644 }
645
646 return entrypoints;
647 }
648
649 /**
650 * @returns {boolean} true, if the chunk references async chunks
651 */
652 hasAsyncChunks() {
653 const queue = new Set();
654
655 const initialChunks = intersect(
656 Array.from(this.groupsIterable, g => new Set(g.chunks))
657 );
658
659 for (const chunkGroup of this.groupsIterable) {
660 for (const child of chunkGroup.childrenIterable) {
661 queue.add(child);
662 }
663 }
664
665 for (const chunkGroup of queue) {
666 for (const chunk of chunkGroup.chunks) {
667 if (!initialChunks.has(chunk)) {
668 return true;
669 }
670 }
671 for (const child of chunkGroup.childrenIterable) {
672 queue.add(child);
673 }
674 }
675
676 return false;
677 }
678
679 /**
680 * @param {ChunkGraph} chunkGraph the chunk graph
681 * @param {ChunkFilterPredicate=} filterFn function used to filter chunks
682 * @returns {Record<string, (string | number)[]>} a record object of names to lists of child ids(?)
683 */
684 getChildIdsByOrders(chunkGraph, filterFn) {
685 /** @type {Map<string, {order: number, group: ChunkGroup}[]>} */
686 const lists = new Map();
687 for (const group of this.groupsIterable) {
688 if (group.chunks[group.chunks.length - 1] === this) {
689 for (const childGroup of group.childrenIterable) {
690 for (const key of Object.keys(childGroup.options)) {
691 if (key.endsWith("Order")) {
692 const name = key.substr(0, key.length - "Order".length);
693 let list = lists.get(name);
694 if (list === undefined) {
695 list = [];
696 lists.set(name, list);
697 }
698 list.push({
699 order: childGroup.options[key],
700 group: childGroup
701 });
702 }
703 }
704 }
705 }
706 }
707 /** @type {Record<string, (string | number)[]>} */
708 const result = Object.create(null);
709 for (const [name, list] of lists) {
710 list.sort((a, b) => {
711 const cmp = b.order - a.order;
712 if (cmp !== 0) return cmp;
713 return a.group.compareTo(chunkGraph, b.group);
714 });
715 /** @type {Set<string | number>} */
716 const chunkIdSet = new Set();
717 for (const item of list) {
718 for (const chunk of item.group.chunks) {
719 if (filterFn && !filterFn(chunk, chunkGraph)) continue;
720 chunkIdSet.add(chunk.id);
721 }
722 }
723 if (chunkIdSet.size > 0) {
724 result[name] = Array.from(chunkIdSet);
725 }
726 }
727 return result;
728 }
729
730 /**
731 * @param {ChunkGraph} chunkGraph the chunk graph
732 * @param {string} type option name
733 * @returns {{ onChunks: Chunk[], chunks: Set<Chunk> }[]} referenced chunks for a specific type
734 */
735 getChildrenOfTypeInOrder(chunkGraph, type) {
736 const list = [];
737 for (const group of this.groupsIterable) {
738 for (const childGroup of group.childrenIterable) {
739 const order = childGroup.options[type];
740 if (order === undefined) continue;
741 list.push({
742 order,
743 group,
744 childGroup
745 });
746 }
747 }
748 if (list.length === 0) return undefined;
749 list.sort((a, b) => {
750 const cmp = b.order - a.order;
751 if (cmp !== 0) return cmp;
752 return a.group.compareTo(chunkGraph, b.group);
753 });
754 const result = [];
755 let lastEntry;
756 for (const { group, childGroup } of list) {
757 if (lastEntry && lastEntry.onChunks === group.chunks) {
758 for (const chunk of childGroup.chunks) {
759 lastEntry.chunks.add(chunk);
760 }
761 } else {
762 result.push(
763 (lastEntry = {
764 onChunks: group.chunks,
765 chunks: new Set(childGroup.chunks)
766 })
767 );
768 }
769 }
770 return result;
771 }
772
773 /**
774 * @param {ChunkGraph} chunkGraph the chunk graph
775 * @param {boolean=} includeDirectChildren include direct children (by default only children of async children are included)
776 * @param {ChunkFilterPredicate=} filterFn function used to filter chunks
777 * @returns {Record<string|number, Record<string, (string | number)[]>>} a record object of names to lists of child ids(?) by chunk id
778 */
779 getChildIdsByOrdersMap(chunkGraph, includeDirectChildren, filterFn) {
780 /** @type {Record<string|number, Record<string, (string | number)[]>>} */
781 const chunkMaps = Object.create(null);
782
783 /**
784 * @param {Chunk} chunk a chunk
785 * @returns {void}
786 */
787 const addChildIdsByOrdersToMap = chunk => {
788 const data = chunk.getChildIdsByOrders(chunkGraph, filterFn);
789 for (const key of Object.keys(data)) {
790 let chunkMap = chunkMaps[key];
791 if (chunkMap === undefined) {
792 chunkMaps[key] = chunkMap = Object.create(null);
793 }
794 chunkMap[chunk.id] = data[key];
795 }
796 };
797
798 if (includeDirectChildren) {
799 /** @type {Set<Chunk>} */
800 const chunks = new Set();
801 for (const chunkGroup of this.groupsIterable) {
802 for (const chunk of chunkGroup.chunks) {
803 chunks.add(chunk);
804 }
805 }
806 for (const chunk of chunks) {
807 addChildIdsByOrdersToMap(chunk);
808 }
809 }
810
811 for (const chunk of this.getAllAsyncChunks()) {
812 addChildIdsByOrdersToMap(chunk);
813 }
814
815 return chunkMaps;
816 }
817}
818
819module.exports = Chunk;