UNPKG

23 kBJavaScriptView Raw
1/*
2MIT License http://www.opensource.org/licenses/mit-license.php
3Author Tobias Koppers @sokra
4*/
5"use strict";
6
7const util = require("util");
8const SortableSet = require("./util/SortableSet");
9const intersect = require("./util/SetHelpers").intersect;
10const GraphHelpers = require("./GraphHelpers");
11const Entrypoint = require("./Entrypoint");
12let debugId = 1000;
13const ERR_CHUNK_ENTRY = "Chunk.entry was removed. Use hasRuntime()";
14const ERR_CHUNK_INITIAL =
15 "Chunk.initial was removed. Use canBeInitial/isOnlyInitial()";
16
17/** @typedef {import("./Module")} Module */
18/** @typedef {import("./ChunkGroup")} ChunkGroup */
19/** @typedef {import("./ModuleReason")} ModuleReason */
20/** @typedef {import("webpack-sources").Source} Source */
21/** @typedef {import("./util/createHash").Hash} Hash */
22
23/**
24 * @typedef {Object} WithId an object who has an id property *
25 * @property {string | number} id the id of the object
26 */
27
28/**
29 * Compare two Modules based on their ids for sorting
30 * @param {Module} a module
31 * @param {Module} b module
32 * @returns {-1|0|1} sort value
33 */
34
35// TODO use @callback
36/** @typedef {(a: Module, b: Module) => -1|0|1} ModuleSortPredicate */
37/** @typedef {(m: Module) => boolean} ModuleFilterPredicate */
38/** @typedef {(c: Chunk) => boolean} ChunkFilterPredicate */
39
40const sortModuleById = (a, b) => {
41 if (a.id < b.id) return -1;
42 if (b.id < a.id) return 1;
43 return 0;
44};
45
46/**
47 * Compare two ChunkGroups based on their ids for sorting
48 * @param {ChunkGroup} a chunk group
49 * @param {ChunkGroup} b chunk group
50 * @returns {-1|0|1} sort value
51 */
52const sortChunkGroupById = (a, b) => {
53 if (a.id < b.id) return -1;
54 if (b.id < a.id) return 1;
55 return 0;
56};
57
58/**
59 * Compare two Identifiables , based on their ids for sorting
60 * @param {Module} a first object with ident fn
61 * @param {Module} b second object with ident fn
62 * @returns {-1|0|1} The order number of the sort
63 */
64const sortByIdentifier = (a, b) => {
65 if (a.identifier() > b.identifier()) return 1;
66 if (a.identifier() < b.identifier()) return -1;
67 return 0;
68};
69
70/**
71 * @returns {string} a concatenation of module identifiers sorted
72 * @param {SortableSet} set to pull module identifiers from
73 */
74const getModulesIdent = set => {
75 set.sort();
76 let str = "";
77 for (const m of set) {
78 str += m.identifier() + "#";
79 }
80 return str;
81};
82
83/**
84 * @template T
85 * @param {SortableSet<T>} set the sortable set to convert to array
86 * @returns {Array<T>} the array returned from Array.from(set)
87 */
88const getArray = set => Array.from(set);
89
90/**
91 * @param {SortableSet<Module>} set the sortable Set to get the count/size of
92 * @returns {number} the size of the modules
93 */
94const getModulesSize = set => {
95 let size = 0;
96 for (const module of set) {
97 size += module.size();
98 }
99 return size;
100};
101
102/**
103 * A Chunk is a unit of encapsulation for Modules.
104 * Chunks are "rendered" into bundles that get emitted when the build completes.
105 */
106class Chunk {
107 /**
108 * @param {string=} name of chunk being created, is optional (for subclasses)
109 */
110 constructor(name) {
111 /** @type {number | null} */
112 this.id = null;
113 /** @type {number[] | null} */
114 this.ids = null;
115 /** @type {number} */
116 this.debugId = debugId++;
117 /** @type {string} */
118 this.name = name;
119 /** @type {boolean} */
120 this.preventIntegration = false;
121 /** @type {Module=} */
122 this.entryModule = undefined;
123 /** @private @type {SortableSet<Module>} */
124 this._modules = new SortableSet(undefined, sortByIdentifier);
125 /** @type {string?} */
126 this.filenameTemplate = undefined;
127 /** @private @type {SortableSet<ChunkGroup>} */
128 this._groups = new SortableSet(undefined, sortChunkGroupById);
129 /** @type {string[]} */
130 this.files = [];
131 /** @type {boolean} */
132 this.rendered = false;
133 /** @type {string=} */
134 this.hash = undefined;
135 /** @type {Object} */
136 this.contentHash = Object.create(null);
137 /** @type {string=} */
138 this.renderedHash = undefined;
139 /** @type {string=} */
140 this.chunkReason = undefined;
141 /** @type {boolean} */
142 this.extraAsync = false;
143 this.removedModules = undefined;
144 }
145
146 /**
147 * @deprecated Chunk.entry has been deprecated. Please use .hasRuntime() instead
148 * @returns {never} Throws an error trying to access this property
149 */
150 get entry() {
151 throw new Error(ERR_CHUNK_ENTRY);
152 }
153
154 /**
155 * @deprecated .entry has been deprecated. Please use .hasRuntime() instead
156 * @param {never} data The data that was attempting to be set
157 * @returns {never} Throws an error trying to access this property
158 */
159 set entry(data) {
160 throw new Error(ERR_CHUNK_ENTRY);
161 }
162
163 /**
164 * @deprecated Chunk.initial was removed. Use canBeInitial/isOnlyInitial()
165 * @returns {never} Throws an error trying to access this property
166 */
167 get initial() {
168 throw new Error(ERR_CHUNK_INITIAL);
169 }
170
171 /**
172 * @deprecated Chunk.initial was removed. Use canBeInitial/isOnlyInitial()
173 * @param {never} data The data attempting to be set
174 * @returns {never} Throws an error trying to access this property
175 */
176 set initial(data) {
177 throw new Error(ERR_CHUNK_INITIAL);
178 }
179
180 /**
181 * @returns {boolean} whether or not the Chunk will have a runtime
182 */
183 hasRuntime() {
184 for (const chunkGroup of this._groups) {
185 if (
186 chunkGroup.isInitial() &&
187 chunkGroup instanceof Entrypoint &&
188 chunkGroup.getRuntimeChunk() === this
189 ) {
190 return true;
191 }
192 }
193 return false;
194 }
195
196 /**
197 * @returns {boolean} whether or not this chunk can be an initial chunk
198 */
199 canBeInitial() {
200 for (const chunkGroup of this._groups) {
201 if (chunkGroup.isInitial()) return true;
202 }
203 return false;
204 }
205
206 /**
207 * @returns {boolean} whether this chunk can only be an initial chunk
208 */
209 isOnlyInitial() {
210 if (this._groups.size <= 0) return false;
211 for (const chunkGroup of this._groups) {
212 if (!chunkGroup.isInitial()) return false;
213 }
214 return true;
215 }
216
217 /**
218 * @returns {boolean} if this chunk contains the entry module
219 */
220 hasEntryModule() {
221 return !!this.entryModule;
222 }
223
224 /**
225 * @param {Module} module the module that will be added to this chunk.
226 * @returns {boolean} returns true if the chunk doesn't have the module and it was added
227 */
228 addModule(module) {
229 if (!this._modules.has(module)) {
230 this._modules.add(module);
231 return true;
232 }
233 return false;
234 }
235
236 /**
237 * @param {Module} module the module that will be removed from this chunk
238 * @returns {boolean} returns true if chunk exists and is successfully deleted
239 */
240 removeModule(module) {
241 if (this._modules.delete(module)) {
242 module.removeChunk(this);
243 return true;
244 }
245 return false;
246 }
247
248 /**
249 * @param {Module[]} modules the new modules to be set
250 * @returns {void} set new modules to this chunk and return nothing
251 */
252 setModules(modules) {
253 this._modules = new SortableSet(modules, sortByIdentifier);
254 }
255
256 /**
257 * @returns {number} the amount of modules in chunk
258 */
259 getNumberOfModules() {
260 return this._modules.size;
261 }
262
263 /**
264 * @returns {SortableSet} return the modules SortableSet for this chunk
265 */
266 get modulesIterable() {
267 return this._modules;
268 }
269
270 /**
271 * @param {ChunkGroup} chunkGroup the chunkGroup the chunk is being added
272 * @returns {boolean} returns true if chunk is not apart of chunkGroup and is added successfully
273 */
274 addGroup(chunkGroup) {
275 if (this._groups.has(chunkGroup)) return false;
276 this._groups.add(chunkGroup);
277 return true;
278 }
279
280 /**
281 * @param {ChunkGroup} chunkGroup the chunkGroup the chunk is being removed from
282 * @returns {boolean} returns true if chunk does exist in chunkGroup and is removed
283 */
284 removeGroup(chunkGroup) {
285 if (!this._groups.has(chunkGroup)) return false;
286 this._groups.delete(chunkGroup);
287 return true;
288 }
289
290 /**
291 * @param {ChunkGroup} chunkGroup the chunkGroup to check
292 * @returns {boolean} returns true if chunk has chunkGroup reference and exists in chunkGroup
293 */
294 isInGroup(chunkGroup) {
295 return this._groups.has(chunkGroup);
296 }
297
298 /**
299 * @returns {number} the amount of groups said chunk is in
300 */
301 getNumberOfGroups() {
302 return this._groups.size;
303 }
304
305 /**
306 * @returns {SortableSet<ChunkGroup>} the chunkGroups that said chunk is referenced in
307 */
308 get groupsIterable() {
309 return this._groups;
310 }
311
312 /**
313 * @param {Chunk} otherChunk the chunk to compare itself with
314 * @returns {-1|0|1} this is a comparitor function like sort and returns -1, 0, or 1 based on sort order
315 */
316 compareTo(otherChunk) {
317 if (this.name && !otherChunk.name) return -1;
318 if (!this.name && otherChunk.name) return 1;
319 if (this.name < otherChunk.name) return -1;
320 if (this.name > otherChunk.name) return 1;
321 if (this._modules.size > otherChunk._modules.size) return -1;
322 if (this._modules.size < otherChunk._modules.size) return 1;
323 this._modules.sort();
324 otherChunk._modules.sort();
325 const a = this._modules[Symbol.iterator]();
326 const b = otherChunk._modules[Symbol.iterator]();
327 // eslint-disable-next-line no-constant-condition
328 while (true) {
329 const aItem = a.next();
330 if (aItem.done) return 0;
331 const bItem = b.next();
332 const aModuleIdentifier = aItem.value.identifier();
333 const bModuleIdentifier = bItem.value.identifier();
334 if (aModuleIdentifier < bModuleIdentifier) return -1;
335 if (aModuleIdentifier > bModuleIdentifier) return 1;
336 }
337 }
338
339 /**
340 * @param {Module} module Module to check
341 * @returns {boolean} returns true if module does exist in this chunk
342 */
343 containsModule(module) {
344 return this._modules.has(module);
345 }
346
347 /**
348 * @returns {Module[]} an array of modules (do not modify)
349 */
350 getModules() {
351 return this._modules.getFromCache(getArray);
352 }
353
354 getModulesIdent() {
355 return this._modules.getFromUnorderedCache(getModulesIdent);
356 }
357
358 /**
359 * @param {string=} reason reason why chunk is removed
360 * @returns {void}
361 */
362 remove(reason) {
363 // cleanup modules
364 // Array.from is used here to create a clone, because removeChunk modifies this._modules
365 for (const module of Array.from(this._modules)) {
366 module.removeChunk(this);
367 }
368 for (const chunkGroup of this._groups) {
369 chunkGroup.removeChunk(this);
370 }
371 }
372
373 /**
374 *
375 * @param {Module} module module to move
376 * @param {Chunk} otherChunk other chunk to move it to
377 * @returns {void}
378 */
379 moveModule(module, otherChunk) {
380 GraphHelpers.disconnectChunkAndModule(this, module);
381 GraphHelpers.connectChunkAndModule(otherChunk, module);
382 module.rewriteChunkInReasons(this, [otherChunk]);
383 }
384
385 /**
386 *
387 * @param {Chunk} otherChunk the chunk to integrate with
388 * @param {ModuleReason} reason reason why the module is being integrated
389 * @returns {boolean} returns true or false if integration succeeds or fails
390 */
391 integrate(otherChunk, reason) {
392 if (!this.canBeIntegrated(otherChunk)) {
393 return false;
394 }
395
396 // Pick a new name for the integrated chunk
397 if (this.name && otherChunk.name) {
398 if (this.hasEntryModule() === otherChunk.hasEntryModule()) {
399 // When both chunks have entry modules or none have one, use
400 // shortest name
401 if (this.name.length !== otherChunk.name.length) {
402 this.name =
403 this.name.length < otherChunk.name.length
404 ? this.name
405 : otherChunk.name;
406 } else {
407 this.name = this.name < otherChunk.name ? this.name : otherChunk.name;
408 }
409 } else if (otherChunk.hasEntryModule()) {
410 // Pick the name of the chunk with the entry module
411 this.name = otherChunk.name;
412 }
413 } else if (otherChunk.name) {
414 this.name = otherChunk.name;
415 }
416
417 // Array.from is used here to create a clone, because moveModule modifies otherChunk._modules
418 for (const module of Array.from(otherChunk._modules)) {
419 otherChunk.moveModule(module, this);
420 }
421 otherChunk._modules.clear();
422
423 if (otherChunk.entryModule) {
424 this.entryModule = otherChunk.entryModule;
425 }
426
427 for (const chunkGroup of otherChunk._groups) {
428 chunkGroup.replaceChunk(otherChunk, this);
429 this.addGroup(chunkGroup);
430 }
431 otherChunk._groups.clear();
432
433 return true;
434 }
435
436 /**
437 * @param {Chunk} newChunk the new chunk that will be split out of the current chunk
438 * @returns {void}
439 */
440 split(newChunk) {
441 for (const chunkGroup of this._groups) {
442 chunkGroup.insertChunk(newChunk, this);
443 newChunk.addGroup(chunkGroup);
444 }
445 }
446
447 isEmpty() {
448 return this._modules.size === 0;
449 }
450
451 updateHash(hash) {
452 hash.update(`${this.id} `);
453 hash.update(this.ids ? this.ids.join(",") : "");
454 hash.update(`${this.name || ""} `);
455 for (const m of this._modules) {
456 hash.update(m.hash);
457 }
458 }
459
460 canBeIntegrated(otherChunk) {
461 if (this.preventIntegration || otherChunk.preventIntegration) {
462 return false;
463 }
464
465 const isAvailable = (a, b) => {
466 const queue = new Set(b.groupsIterable);
467 for (const chunkGroup of queue) {
468 if (a.isInGroup(chunkGroup)) continue;
469 if (chunkGroup.isInitial()) return false;
470 for (const parent of chunkGroup.parentsIterable) {
471 queue.add(parent);
472 }
473 }
474 return true;
475 };
476
477 const selfHasRuntime = this.hasRuntime();
478 const otherChunkHasRuntime = otherChunk.hasRuntime();
479
480 if (selfHasRuntime !== otherChunkHasRuntime) {
481 if (selfHasRuntime) {
482 return isAvailable(this, otherChunk);
483 } else if (otherChunkHasRuntime) {
484 return isAvailable(otherChunk, this);
485 } else {
486 return false;
487 }
488 }
489
490 if (this.hasEntryModule() || otherChunk.hasEntryModule()) {
491 return false;
492 }
493
494 return true;
495 }
496
497 /**
498 *
499 * @param {number} size the size
500 * @param {Object} options the options passed in
501 * @returns {number} the multiplier returned
502 */
503 addMultiplierAndOverhead(size, options) {
504 const overhead =
505 typeof options.chunkOverhead === "number" ? options.chunkOverhead : 10000;
506 const multiplicator = this.canBeInitial()
507 ? options.entryChunkMultiplicator || 10
508 : 1;
509
510 return size * multiplicator + overhead;
511 }
512
513 /**
514 * @returns {number} the size of all modules
515 */
516 modulesSize() {
517 return this._modules.getFromUnorderedCache(getModulesSize);
518 }
519
520 /**
521 * @param {Object} options the size display options
522 * @returns {number} the chunk size
523 */
524 size(options = {}) {
525 return this.addMultiplierAndOverhead(this.modulesSize(), options);
526 }
527
528 /**
529 * @param {Chunk} otherChunk the other chunk
530 * @param {TODO} options the options for this function
531 * @returns {number | false} the size, or false if it can't be integrated
532 */
533 integratedSize(otherChunk, options) {
534 // Chunk if it's possible to integrate this chunk
535 if (!this.canBeIntegrated(otherChunk)) {
536 return false;
537 }
538
539 let integratedModulesSize = this.modulesSize();
540 // only count modules that do not exist in this chunk!
541 for (const otherModule of otherChunk._modules) {
542 if (!this._modules.has(otherModule)) {
543 integratedModulesSize += otherModule.size();
544 }
545 }
546
547 return this.addMultiplierAndOverhead(integratedModulesSize, options);
548 }
549
550 /**
551 * @param {function(Module, Module): -1|0|1=} sortByFn a predicate function used to sort modules
552 * @returns {void}
553 */
554 sortModules(sortByFn) {
555 this._modules.sortWith(sortByFn || sortModuleById);
556 }
557
558 sortItems() {
559 this.sortModules();
560 }
561
562 /**
563 * @returns {Set<Chunk>} a set of all the async chunks
564 */
565 getAllAsyncChunks() {
566 const queue = new Set();
567 const chunks = new Set();
568
569 const initialChunks = intersect(
570 Array.from(this.groupsIterable, g => new Set(g.chunks))
571 );
572
573 for (const chunkGroup of this.groupsIterable) {
574 for (const child of chunkGroup.childrenIterable) {
575 queue.add(child);
576 }
577 }
578
579 for (const chunkGroup of queue) {
580 for (const chunk of chunkGroup.chunks) {
581 if (!initialChunks.has(chunk)) {
582 chunks.add(chunk);
583 }
584 }
585 for (const child of chunkGroup.childrenIterable) {
586 queue.add(child);
587 }
588 }
589
590 return chunks;
591 }
592
593 /**
594 * @typedef {Object} ChunkMaps
595 * @property {Record<string|number, string>} hash
596 * @property {Record<string|number, Record<string, string>>} contentHash
597 * @property {Record<string|number, string>} name
598 */
599
600 /**
601 * @param {boolean} realHash should the full hash or the rendered hash be used
602 * @returns {ChunkMaps} the chunk map information
603 */
604 getChunkMaps(realHash) {
605 /** @type {Record<string|number, string>} */
606 const chunkHashMap = Object.create(null);
607 /** @type {Record<string|number, Record<string, string>>} */
608 const chunkContentHashMap = Object.create(null);
609 /** @type {Record<string|number, string>} */
610 const chunkNameMap = Object.create(null);
611
612 for (const chunk of this.getAllAsyncChunks()) {
613 chunkHashMap[chunk.id] = realHash ? chunk.hash : chunk.renderedHash;
614 for (const key of Object.keys(chunk.contentHash)) {
615 if (!chunkContentHashMap[key]) {
616 chunkContentHashMap[key] = Object.create(null);
617 }
618 chunkContentHashMap[key][chunk.id] = chunk.contentHash[key];
619 }
620 if (chunk.name) {
621 chunkNameMap[chunk.id] = chunk.name;
622 }
623 }
624
625 return {
626 hash: chunkHashMap,
627 contentHash: chunkContentHashMap,
628 name: chunkNameMap
629 };
630 }
631
632 /**
633 * @returns {Record<string, Set<TODO>[]>} a record object of names to lists of child ids(?)
634 */
635 getChildIdsByOrders() {
636 const lists = new Map();
637 for (const group of this.groupsIterable) {
638 if (group.chunks[group.chunks.length - 1] === this) {
639 for (const childGroup of group.childrenIterable) {
640 // TODO webpack 5 remove this check for options
641 if (typeof childGroup.options === "object") {
642 for (const key of Object.keys(childGroup.options)) {
643 if (key.endsWith("Order")) {
644 const name = key.substr(0, key.length - "Order".length);
645 let list = lists.get(name);
646 if (list === undefined) lists.set(name, (list = []));
647 list.push({
648 order: childGroup.options[key],
649 group: childGroup
650 });
651 }
652 }
653 }
654 }
655 }
656 }
657 const result = Object.create(null);
658 for (const [name, list] of lists) {
659 list.sort((a, b) => {
660 const cmp = b.order - a.order;
661 if (cmp !== 0) return cmp;
662 // TODO webpack 5 remove this check of compareTo
663 if (a.group.compareTo) {
664 return a.group.compareTo(b.group);
665 }
666 return 0;
667 });
668 result[name] = Array.from(
669 list.reduce((set, item) => {
670 for (const chunk of item.group.chunks) {
671 set.add(chunk.id);
672 }
673 return set;
674 }, new Set())
675 );
676 }
677 return result;
678 }
679
680 getChildIdsByOrdersMap(includeDirectChildren) {
681 const chunkMaps = Object.create(null);
682
683 const addChildIdsByOrdersToMap = chunk => {
684 const data = chunk.getChildIdsByOrders();
685 for (const key of Object.keys(data)) {
686 let chunkMap = chunkMaps[key];
687 if (chunkMap === undefined) {
688 chunkMaps[key] = chunkMap = Object.create(null);
689 }
690 chunkMap[chunk.id] = data[key];
691 }
692 };
693
694 if (includeDirectChildren) {
695 const chunks = new Set();
696 for (const chunkGroup of this.groupsIterable) {
697 for (const chunk of chunkGroup.chunks) {
698 chunks.add(chunk);
699 }
700 }
701 for (const chunk of chunks) {
702 addChildIdsByOrdersToMap(chunk);
703 }
704 }
705
706 for (const chunk of this.getAllAsyncChunks()) {
707 addChildIdsByOrdersToMap(chunk);
708 }
709
710 return chunkMaps;
711 }
712
713 /**
714 * @typedef {Object} ChunkModuleMaps
715 * @property {Record<string|number, (string|number)[]>} id
716 * @property {Record<string|number, string>} hash
717 */
718
719 /**
720 * @param {ModuleFilterPredicate} filterFn function used to filter modules
721 * @returns {ChunkModuleMaps} module map information
722 */
723 getChunkModuleMaps(filterFn) {
724 /** @type {Record<string|number, (string|number)[]>} */
725 const chunkModuleIdMap = Object.create(null);
726 /** @type {Record<string|number, string>} */
727 const chunkModuleHashMap = Object.create(null);
728
729 for (const chunk of this.getAllAsyncChunks()) {
730 /** @type {(string|number)[]} */
731 let array;
732 for (const module of chunk.modulesIterable) {
733 if (filterFn(module)) {
734 if (array === undefined) {
735 array = [];
736 chunkModuleIdMap[chunk.id] = array;
737 }
738 array.push(module.id);
739 chunkModuleHashMap[module.id] = module.renderedHash;
740 }
741 }
742 if (array !== undefined) {
743 array.sort();
744 }
745 }
746
747 return {
748 id: chunkModuleIdMap,
749 hash: chunkModuleHashMap
750 };
751 }
752
753 /**
754 *
755 * @param {function(Module): boolean} filterFn predicate function used to filter modules
756 * @param {function(Chunk): boolean} filterChunkFn predicate function used to filter chunks
757 * @returns {boolean} return true if module exists in graph
758 */
759 hasModuleInGraph(filterFn, filterChunkFn) {
760 const queue = new Set(this.groupsIterable);
761 const chunksProcessed = new Set();
762
763 for (const chunkGroup of queue) {
764 for (const chunk of chunkGroup.chunks) {
765 if (!chunksProcessed.has(chunk)) {
766 chunksProcessed.add(chunk);
767 if (!filterChunkFn || filterChunkFn(chunk)) {
768 for (const module of chunk.modulesIterable) {
769 if (filterFn(module)) {
770 return true;
771 }
772 }
773 }
774 }
775 }
776 for (const child of chunkGroup.childrenIterable) {
777 queue.add(child);
778 }
779 }
780 return false;
781 }
782
783 toString() {
784 return `Chunk[${Array.from(this._modules).join()}]`;
785 }
786}
787
788// TODO remove in webpack 5
789Object.defineProperty(Chunk.prototype, "forEachModule", {
790 configurable: false,
791 value: util.deprecate(
792 /**
793 * @deprecated
794 * @this {Chunk}
795 * @typedef {function(any, any, Set<any>): void} ForEachModuleCallback
796 * @param {ForEachModuleCallback} fn Callback function
797 * @returns {void}
798 */
799 function(fn) {
800 this._modules.forEach(fn);
801 },
802 "Chunk.forEachModule: Use for(const module of chunk.modulesIterable) instead"
803 )
804});
805
806// TODO remove in webpack 5
807Object.defineProperty(Chunk.prototype, "mapModules", {
808 configurable: false,
809 value: util.deprecate(
810 /**
811 * @deprecated
812 * @this {Chunk}
813 * @typedef {function(any, number): any} MapModulesCallback
814 * @param {MapModulesCallback} fn Callback function
815 * @returns {TODO[]} result of mapped modules
816 */
817 function(fn) {
818 return Array.from(this._modules, fn);
819 },
820 "Chunk.mapModules: Use Array.from(chunk.modulesIterable, fn) instead"
821 )
822});
823
824// TODO remove in webpack 5
825Object.defineProperty(Chunk.prototype, "chunks", {
826 configurable: false,
827 get() {
828 throw new Error("Chunk.chunks: Use ChunkGroup.getChildren() instead");
829 },
830 set() {
831 throw new Error("Chunk.chunks: Use ChunkGroup.add/removeChild() instead");
832 }
833});
834
835// TODO remove in webpack 5
836Object.defineProperty(Chunk.prototype, "parents", {
837 configurable: false,
838 get() {
839 throw new Error("Chunk.parents: Use ChunkGroup.getParents() instead");
840 },
841 set() {
842 throw new Error("Chunk.parents: Use ChunkGroup.add/removeParent() instead");
843 }
844});
845
846// TODO remove in webpack 5
847Object.defineProperty(Chunk.prototype, "blocks", {
848 configurable: false,
849 get() {
850 throw new Error("Chunk.blocks: Use ChunkGroup.getBlocks() instead");
851 },
852 set() {
853 throw new Error("Chunk.blocks: Use ChunkGroup.add/removeBlock() instead");
854 }
855});
856
857// TODO remove in webpack 5
858Object.defineProperty(Chunk.prototype, "entrypoints", {
859 configurable: false,
860 get() {
861 throw new Error(
862 "Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead"
863 );
864 },
865 set() {
866 throw new Error("Chunk.entrypoints: Use Chunks.addGroup instead");
867 }
868});
869
870module.exports = Chunk;