UNPKG

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