1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | "use strict";
|
7 |
|
8 | const util = require("util");
|
9 | const SortableSet = require("./util/SortableSet");
|
10 | const {
|
11 | compareLocations,
|
12 | compareChunks,
|
13 | compareIterables
|
14 | } = require("./util/comparators");
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 | let debugId = 5000;
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 | const getArray = set => Array.from(set);
|
43 |
|
44 | /**
|
45 | * A convenience method used to sort chunks based on their id's
|
46 | * @param {ChunkGroup} a first sorting comparator
|
47 | * @param {ChunkGroup} b second sorting comparator
|
48 | * @returns {1|0|-1} a sorting index to determine order
|
49 | */
|
50 | const sortById = (a, b) => {
|
51 | if (a.id < b.id) return -1;
|
52 | if (b.id < a.id) return 1;
|
53 | return 0;
|
54 | };
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 | const sortOrigin = (a, b) => {
|
62 | const aIdent = a.module ? a.module.identifier() : "";
|
63 | const bIdent = b.module ? b.module.identifier() : "";
|
64 | if (aIdent < bIdent) return -1;
|
65 | if (aIdent > bIdent) return 1;
|
66 | return compareLocations(a.loc, b.loc);
|
67 | };
|
68 |
|
69 | class ChunkGroup {
|
70 | |
71 |
|
72 |
|
73 |
|
74 | constructor(options) {
|
75 | if (typeof options === "string") {
|
76 | options = { name: options };
|
77 | } else if (!options) {
|
78 | options = { name: undefined };
|
79 | }
|
80 |
|
81 | this.groupDebugId = debugId++;
|
82 | this.options = options;
|
83 |
|
84 | this._children = new SortableSet(undefined, sortById);
|
85 |
|
86 | this._parents = new SortableSet(undefined, sortById);
|
87 |
|
88 | this._asyncEntrypoints = new SortableSet(undefined, sortById);
|
89 | this._blocks = new SortableSet();
|
90 |
|
91 | this.chunks = [];
|
92 |
|
93 | this.origins = [];
|
94 |
|
95 |
|
96 | this._modulePreOrderIndices = new Map();
|
97 |
|
98 |
|
99 | this._modulePostOrderIndices = new Map();
|
100 |
|
101 | this.index = undefined;
|
102 | }
|
103 |
|
104 | |
105 |
|
106 |
|
107 |
|
108 |
|
109 | addOptions(options) {
|
110 | for (const key of Object.keys(options)) {
|
111 | if (this.options[key] === undefined) {
|
112 | this.options[key] = options[key];
|
113 | } else if (this.options[key] !== options[key]) {
|
114 | if (key.endsWith("Order")) {
|
115 | this.options[key] = Math.max(this.options[key], options[key]);
|
116 | } else {
|
117 | throw new Error(
|
118 | `ChunkGroup.addOptions: No option merge strategy for ${key}`
|
119 | );
|
120 | }
|
121 | }
|
122 | }
|
123 | }
|
124 |
|
125 | |
126 |
|
127 |
|
128 |
|
129 | get name() {
|
130 | return this.options.name;
|
131 | }
|
132 |
|
133 | |
134 |
|
135 |
|
136 |
|
137 |
|
138 | set name(value) {
|
139 | this.options.name = value;
|
140 | }
|
141 |
|
142 |
|
143 | |
144 |
|
145 |
|
146 |
|
147 | get debugId() {
|
148 | return Array.from(this.chunks, x => x.debugId).join("+");
|
149 | }
|
150 |
|
151 | |
152 |
|
153 |
|
154 |
|
155 | get id() {
|
156 | return Array.from(this.chunks, x => x.id).join("+");
|
157 | }
|
158 |
|
159 | |
160 |
|
161 |
|
162 |
|
163 |
|
164 | unshiftChunk(chunk) {
|
165 | const oldIdx = this.chunks.indexOf(chunk);
|
166 | if (oldIdx > 0) {
|
167 | this.chunks.splice(oldIdx, 1);
|
168 | this.chunks.unshift(chunk);
|
169 | } else if (oldIdx < 0) {
|
170 | this.chunks.unshift(chunk);
|
171 | return true;
|
172 | }
|
173 | return false;
|
174 | }
|
175 |
|
176 | |
177 |
|
178 |
|
179 |
|
180 |
|
181 |
|
182 | insertChunk(chunk, before) {
|
183 | const oldIdx = this.chunks.indexOf(chunk);
|
184 | const idx = this.chunks.indexOf(before);
|
185 | if (idx < 0) {
|
186 | throw new Error("before chunk not found");
|
187 | }
|
188 | if (oldIdx >= 0 && oldIdx > idx) {
|
189 | this.chunks.splice(oldIdx, 1);
|
190 | this.chunks.splice(idx, 0, chunk);
|
191 | } else if (oldIdx < 0) {
|
192 | this.chunks.splice(idx, 0, chunk);
|
193 | return true;
|
194 | }
|
195 | return false;
|
196 | }
|
197 |
|
198 | |
199 |
|
200 |
|
201 |
|
202 |
|
203 | pushChunk(chunk) {
|
204 | const oldIdx = this.chunks.indexOf(chunk);
|
205 | if (oldIdx >= 0) {
|
206 | return false;
|
207 | }
|
208 | this.chunks.push(chunk);
|
209 | return true;
|
210 | }
|
211 |
|
212 | |
213 |
|
214 |
|
215 |
|
216 |
|
217 | replaceChunk(oldChunk, newChunk) {
|
218 | const oldIdx = this.chunks.indexOf(oldChunk);
|
219 | if (oldIdx < 0) return false;
|
220 | const newIdx = this.chunks.indexOf(newChunk);
|
221 | if (newIdx < 0) {
|
222 | this.chunks[oldIdx] = newChunk;
|
223 | return true;
|
224 | }
|
225 | if (newIdx < oldIdx) {
|
226 | this.chunks.splice(oldIdx, 1);
|
227 | return true;
|
228 | } else if (newIdx !== oldIdx) {
|
229 | this.chunks[oldIdx] = newChunk;
|
230 | this.chunks.splice(newIdx, 1);
|
231 | return true;
|
232 | }
|
233 | }
|
234 |
|
235 | |
236 |
|
237 |
|
238 |
|
239 | removeChunk(chunk) {
|
240 | const idx = this.chunks.indexOf(chunk);
|
241 | if (idx >= 0) {
|
242 | this.chunks.splice(idx, 1);
|
243 | return true;
|
244 | }
|
245 | return false;
|
246 | }
|
247 |
|
248 | |
249 |
|
250 |
|
251 | isInitial() {
|
252 | return false;
|
253 | }
|
254 |
|
255 | |
256 |
|
257 |
|
258 |
|
259 | addChild(group) {
|
260 | const size = this._children.size;
|
261 | this._children.add(group);
|
262 | return size !== this._children.size;
|
263 | }
|
264 |
|
265 | |
266 |
|
267 |
|
268 | getChildren() {
|
269 | return this._children.getFromCache(getArray);
|
270 | }
|
271 |
|
272 | getNumberOfChildren() {
|
273 | return this._children.size;
|
274 | }
|
275 |
|
276 | get childrenIterable() {
|
277 | return this._children;
|
278 | }
|
279 |
|
280 | |
281 |
|
282 |
|
283 |
|
284 | removeChild(group) {
|
285 | if (!this._children.has(group)) {
|
286 | return false;
|
287 | }
|
288 |
|
289 | this._children.delete(group);
|
290 | group.removeParent(this);
|
291 | return true;
|
292 | }
|
293 |
|
294 | |
295 |
|
296 |
|
297 |
|
298 | addParent(parentChunk) {
|
299 | if (!this._parents.has(parentChunk)) {
|
300 | this._parents.add(parentChunk);
|
301 | return true;
|
302 | }
|
303 | return false;
|
304 | }
|
305 |
|
306 | |
307 |
|
308 |
|
309 | getParents() {
|
310 | return this._parents.getFromCache(getArray);
|
311 | }
|
312 |
|
313 | getNumberOfParents() {
|
314 | return this._parents.size;
|
315 | }
|
316 |
|
317 | |
318 |
|
319 |
|
320 |
|
321 | hasParent(parent) {
|
322 | return this._parents.has(parent);
|
323 | }
|
324 |
|
325 | get parentsIterable() {
|
326 | return this._parents;
|
327 | }
|
328 |
|
329 | |
330 |
|
331 |
|
332 |
|
333 | removeParent(chunkGroup) {
|
334 | if (this._parents.delete(chunkGroup)) {
|
335 | chunkGroup.removeChild(this);
|
336 | return true;
|
337 | }
|
338 | return false;
|
339 | }
|
340 |
|
341 | |
342 |
|
343 |
|
344 |
|
345 | addAsyncEntrypoint(entrypoint) {
|
346 | const size = this._asyncEntrypoints.size;
|
347 | this._asyncEntrypoints.add(entrypoint);
|
348 | return size !== this._asyncEntrypoints.size;
|
349 | }
|
350 |
|
351 | get asyncEntrypointsIterable() {
|
352 | return this._asyncEntrypoints;
|
353 | }
|
354 |
|
355 | |
356 |
|
357 |
|
358 | getBlocks() {
|
359 | return this._blocks.getFromCache(getArray);
|
360 | }
|
361 |
|
362 | getNumberOfBlocks() {
|
363 | return this._blocks.size;
|
364 | }
|
365 |
|
366 | hasBlock(block) {
|
367 | return this._blocks.has(block);
|
368 | }
|
369 |
|
370 | |
371 |
|
372 |
|
373 | get blocksIterable() {
|
374 | return this._blocks;
|
375 | }
|
376 |
|
377 | |
378 |
|
379 |
|
380 |
|
381 | addBlock(block) {
|
382 | if (!this._blocks.has(block)) {
|
383 | this._blocks.add(block);
|
384 | return true;
|
385 | }
|
386 | return false;
|
387 | }
|
388 |
|
389 | |
390 |
|
391 |
|
392 |
|
393 |
|
394 |
|
395 | addOrigin(module, loc, request) {
|
396 | this.origins.push({
|
397 | module,
|
398 | loc,
|
399 | request
|
400 | });
|
401 | }
|
402 |
|
403 | |
404 |
|
405 |
|
406 | getFiles() {
|
407 | const files = new Set();
|
408 |
|
409 | for (const chunk of this.chunks) {
|
410 | for (const file of chunk.files) {
|
411 | files.add(file);
|
412 | }
|
413 | }
|
414 |
|
415 | return Array.from(files);
|
416 | }
|
417 |
|
418 | |
419 |
|
420 |
|
421 | remove() {
|
422 |
|
423 | for (const parentChunkGroup of this._parents) {
|
424 |
|
425 | parentChunkGroup._children.delete(this);
|
426 |
|
427 |
|
428 | for (const chunkGroup of this._children) {
|
429 | |
430 |
|
431 |
|
432 |
|
433 |
|
434 | chunkGroup.addParent(parentChunkGroup);
|
435 |
|
436 | parentChunkGroup.addChild(chunkGroup);
|
437 | }
|
438 | }
|
439 |
|
440 | |
441 |
|
442 |
|
443 |
|
444 |
|
445 |
|
446 | for (const chunkGroup of this._children) {
|
447 |
|
448 | chunkGroup._parents.delete(this);
|
449 | }
|
450 |
|
451 |
|
452 | for (const chunk of this.chunks) {
|
453 | chunk.removeGroup(this);
|
454 | }
|
455 | }
|
456 |
|
457 | sortItems() {
|
458 | this.origins.sort(sortOrigin);
|
459 | }
|
460 |
|
461 | |
462 |
|
463 |
|
464 |
|
465 |
|
466 |
|
467 |
|
468 |
|
469 | compareTo(chunkGraph, otherGroup) {
|
470 | if (this.chunks.length > otherGroup.chunks.length) return -1;
|
471 | if (this.chunks.length < otherGroup.chunks.length) return 1;
|
472 | return compareIterables(compareChunks(chunkGraph))(
|
473 | this.chunks,
|
474 | otherGroup.chunks
|
475 | );
|
476 | }
|
477 |
|
478 | |
479 |
|
480 |
|
481 |
|
482 |
|
483 | getChildrenByOrders(moduleGraph, chunkGraph) {
|
484 |
|
485 | const lists = new Map();
|
486 | for (const childGroup of this._children) {
|
487 | for (const key of Object.keys(childGroup.options)) {
|
488 | if (key.endsWith("Order")) {
|
489 | const name = key.substr(0, key.length - "Order".length);
|
490 | let list = lists.get(name);
|
491 | if (list === undefined) {
|
492 | lists.set(name, (list = []));
|
493 | }
|
494 | list.push({
|
495 | order: childGroup.options[key],
|
496 | group: childGroup
|
497 | });
|
498 | }
|
499 | }
|
500 | }
|
501 |
|
502 | const result = Object.create(null);
|
503 | for (const [name, list] of lists) {
|
504 | list.sort((a, b) => {
|
505 | const cmp = b.order - a.order;
|
506 | if (cmp !== 0) return cmp;
|
507 | return a.group.compareTo(chunkGraph, b.group);
|
508 | });
|
509 | result[name] = list.map(i => i.group);
|
510 | }
|
511 | return result;
|
512 | }
|
513 |
|
514 | |
515 |
|
516 |
|
517 |
|
518 |
|
519 |
|
520 | setModulePreOrderIndex(module, index) {
|
521 | this._modulePreOrderIndices.set(module, index);
|
522 | }
|
523 |
|
524 | |
525 |
|
526 |
|
527 |
|
528 |
|
529 | getModulePreOrderIndex(module) {
|
530 | return this._modulePreOrderIndices.get(module);
|
531 | }
|
532 |
|
533 | |
534 |
|
535 |
|
536 |
|
537 |
|
538 |
|
539 | setModulePostOrderIndex(module, index) {
|
540 | this._modulePostOrderIndices.set(module, index);
|
541 | }
|
542 |
|
543 | |
544 |
|
545 |
|
546 |
|
547 |
|
548 | getModulePostOrderIndex(module) {
|
549 | return this._modulePostOrderIndices.get(module);
|
550 | }
|
551 |
|
552 |
|
553 | checkConstraints() {
|
554 | const chunk = this;
|
555 | for (const child of chunk._children) {
|
556 | if (!child._parents.has(chunk)) {
|
557 | throw new Error(
|
558 | `checkConstraints: child missing parent ${chunk.debugId} -> ${child.debugId}`
|
559 | );
|
560 | }
|
561 | }
|
562 | for (const parentChunk of chunk._parents) {
|
563 | if (!parentChunk._children.has(chunk)) {
|
564 | throw new Error(
|
565 | `checkConstraints: parent missing child ${parentChunk.debugId} <- ${chunk.debugId}`
|
566 | );
|
567 | }
|
568 | }
|
569 | }
|
570 | }
|
571 |
|
572 | ChunkGroup.prototype.getModuleIndex = util.deprecate(
|
573 | ChunkGroup.prototype.getModulePreOrderIndex,
|
574 | "ChunkGroup.getModuleIndex was renamed to getModulePreOrderIndex",
|
575 | "DEP_WEBPACK_CHUNK_GROUP_GET_MODULE_INDEX"
|
576 | );
|
577 |
|
578 | ChunkGroup.prototype.getModuleIndex2 = util.deprecate(
|
579 | ChunkGroup.prototype.getModulePostOrderIndex,
|
580 | "ChunkGroup.getModuleIndex2 was renamed to getModulePostOrderIndex",
|
581 | "DEP_WEBPACK_CHUNK_GROUP_GET_MODULE_INDEX_2"
|
582 | );
|
583 |
|
584 | module.exports = ChunkGroup;
|