webpack 5.90.1 → 5.90.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of webpack might be problematic. Click here for more details.
- package/lib/Compilation.js +1 -1
- package/lib/ContextModule.js +2 -1
- package/lib/CssModule.js +0 -3
- package/lib/DelegatedModule.js +2 -1
- package/lib/DllModule.js +2 -1
- package/lib/ExternalModule.js +2 -1
- package/lib/Module.js +24 -3
- package/lib/MultiCompiler.js +36 -10
- package/lib/NormalModule.js +236 -85
- package/lib/NormalModuleFactory.js +162 -31
- package/lib/RawModule.js +2 -1
- package/lib/ResolverFactory.js +2 -0
- package/lib/RuntimeModule.js +2 -1
- package/lib/Stats.js +2 -2
- package/lib/asset/RawDataUrlModule.js +2 -1
- package/lib/buildChunkGraph.js +156 -348
- package/lib/container/ContainerEntryModule.js +2 -1
- package/lib/container/FallbackModule.js +2 -1
- package/lib/container/RemoteModule.js +2 -1
- package/lib/css/CssLoadingRuntimeModule.js +1 -1
- package/lib/dependencies/ExportsInfoDependency.js +6 -12
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +15 -5
- package/lib/dependencies/ImportParserPlugin.js +1 -0
- package/lib/dependencies/WorkerDependency.js +1 -1
- package/lib/dependencies/WorkerPlugin.js +4 -4
- package/lib/hmr/HotModuleReplacement.runtime.js +1 -1
- package/lib/hmr/LazyCompilationPlugin.js +2 -1
- package/lib/optimize/ConcatenatedModule.js +2 -1
- package/lib/runtime/AutoPublicPathRuntimeModule.js +1 -1
- package/lib/sharing/ConsumeSharedModule.js +2 -1
- package/lib/sharing/ProvideSharedModule.js +2 -1
- package/lib/util/memoize.js +2 -0
- package/lib/util/numberHash.js +4 -15
- package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +2 -1
- package/lib/webpack.js +5 -3
- package/package.json +2 -2
- package/types.d.ts +122 -78
package/lib/buildChunkGraph.js
CHANGED
@@ -34,18 +34,15 @@ const { getEntryRuntime, mergeRuntime } = require("./util/runtime");
|
|
34
34
|
* @property {ChunkGroupInfo} chunkGroupInfo
|
35
35
|
*/
|
36
36
|
|
37
|
-
/** @typedef {Set<Module> & { plus: Set<Module> }} ModuleSetPlus */
|
38
|
-
|
39
37
|
/**
|
40
38
|
* @typedef {Object} ChunkGroupInfo
|
41
39
|
* @property {ChunkGroup} chunkGroup the chunk group
|
42
40
|
* @property {RuntimeSpec} runtime the runtimes
|
43
|
-
* @property {
|
44
|
-
* @property {
|
45
|
-
* @property {ModuleSetPlus[]} availableModulesToBeMerged enqueued updates to the minimal set of available modules
|
41
|
+
* @property {bigint | undefined} minAvailableModules current minimal set of modules available at this point
|
42
|
+
* @property {bigint[]} availableModulesToBeMerged enqueued updates to the minimal set of available modules
|
46
43
|
* @property {Set<Module>=} skippedItems modules that were skipped because module is already available in parent chunks (need to reconsider when minAvailableModules is shrinking)
|
47
|
-
* @property {Set<[Module,
|
48
|
-
* @property {
|
44
|
+
* @property {Set<[Module, ModuleGraphConnection[]]>=} skippedModuleConnections referenced modules that where skipped because they were not active in this runtime
|
45
|
+
* @property {bigint | undefined} resultingAvailableModules set of modules available including modules from this chunk group
|
49
46
|
* @property {Set<ChunkGroupInfo> | undefined} children set of children chunk groups, that will be revisited when availableModules shrink
|
50
47
|
* @property {Set<ChunkGroupInfo> | undefined} availableSources set of chunk groups that are the source for minAvailableModules
|
51
48
|
* @property {Set<ChunkGroupInfo> | undefined} availableChildren set of chunk groups which depend on the this chunk group as availableSource
|
@@ -61,16 +58,34 @@ const { getEntryRuntime, mergeRuntime } = require("./util/runtime");
|
|
61
58
|
* @property {ChunkGroup} chunkGroup referenced chunk group
|
62
59
|
*/
|
63
60
|
|
64
|
-
const
|
65
|
-
|
61
|
+
const ZERO_BIGINT = BigInt(0);
|
62
|
+
const ONE_BIGINT = BigInt(1);
|
66
63
|
|
67
64
|
/**
|
68
|
-
* @param {
|
69
|
-
* @param {
|
70
|
-
* @returns {
|
65
|
+
* @param {bigint} mask The mask to test
|
66
|
+
* @param {number} ordinal The ordinal of the bit to test
|
67
|
+
* @returns {boolean} If the ordinal-th bit is set in the mask
|
71
68
|
*/
|
72
|
-
const
|
73
|
-
|
69
|
+
const isOrdinalSetInMask = (mask, ordinal) =>
|
70
|
+
BigInt.asUintN(1, mask >> BigInt(ordinal)) !== ZERO_BIGINT;
|
71
|
+
|
72
|
+
/**
|
73
|
+
* @param {ModuleGraphConnection[]} connections list of connections
|
74
|
+
* @param {RuntimeSpec} runtime for which runtime
|
75
|
+
* @returns {ConnectionState} connection state
|
76
|
+
*/
|
77
|
+
const getActiveStateOfConnections = (connections, runtime) => {
|
78
|
+
let merged = connections[0].getActiveState(runtime);
|
79
|
+
if (merged === true) return true;
|
80
|
+
for (let i = 1; i < connections.length; i++) {
|
81
|
+
const c = connections[i];
|
82
|
+
merged = ModuleGraphConnection.addConnectionStates(
|
83
|
+
merged,
|
84
|
+
c.getActiveState(runtime)
|
85
|
+
);
|
86
|
+
if (merged === true) return true;
|
87
|
+
}
|
88
|
+
return merged;
|
74
89
|
};
|
75
90
|
|
76
91
|
const extractBlockModules = (module, moduleGraph, runtime, blockModulesMap) => {
|
@@ -99,9 +114,6 @@ const extractBlockModules = (module, moduleGraph, runtime, blockModulesMap) => {
|
|
99
114
|
if (!m) continue;
|
100
115
|
// We skip weak connections
|
101
116
|
if (connection.weak) continue;
|
102
|
-
const state = connection.getActiveState(runtime);
|
103
|
-
// We skip inactive connections
|
104
|
-
if (state === false) continue;
|
105
117
|
|
106
118
|
const block = moduleGraph.getParentBlock(d);
|
107
119
|
let index = moduleGraph.getParentBlockIndex(d);
|
@@ -115,41 +127,47 @@ const extractBlockModules = (module, moduleGraph, runtime, blockModulesMap) => {
|
|
115
127
|
modules = blockModulesMap.get((blockCache = block));
|
116
128
|
}
|
117
129
|
|
118
|
-
const i = index
|
130
|
+
const i = index * 3;
|
119
131
|
modules[i] = m;
|
120
|
-
modules[i + 1] =
|
132
|
+
modules[i + 1] = connection.getActiveState(runtime);
|
133
|
+
modules[i + 2] = connection;
|
121
134
|
}
|
122
135
|
|
123
136
|
for (const modules of arrays) {
|
124
137
|
if (modules.length === 0) continue;
|
125
138
|
let indexMap;
|
126
139
|
let length = 0;
|
127
|
-
outer: for (let j = 0; j < modules.length; j +=
|
140
|
+
outer: for (let j = 0; j < modules.length; j += 3) {
|
128
141
|
const m = modules[j];
|
129
142
|
if (m === undefined) continue;
|
130
143
|
const state = modules[j + 1];
|
144
|
+
const connection = modules[j + 2];
|
131
145
|
if (indexMap === undefined) {
|
132
146
|
let i = 0;
|
133
|
-
for (; i < length; i +=
|
147
|
+
for (; i < length; i += 3) {
|
134
148
|
if (modules[i] === m) {
|
135
149
|
const merged = modules[i + 1];
|
150
|
+
modules[i + 2].push(connection);
|
136
151
|
if (merged === true) continue outer;
|
137
152
|
modules[i + 1] = ModuleGraphConnection.addConnectionStates(
|
138
153
|
merged,
|
139
154
|
state
|
140
155
|
);
|
156
|
+
continue outer;
|
141
157
|
}
|
142
158
|
}
|
143
159
|
modules[length] = m;
|
144
160
|
length++;
|
145
161
|
modules[length] = state;
|
146
162
|
length++;
|
163
|
+
modules[length] = [connection];
|
164
|
+
length++;
|
147
165
|
if (length > 30) {
|
148
166
|
// To avoid worse case performance, we will use an index map for
|
149
167
|
// linear cost access, which allows to maintain O(n) complexity
|
150
168
|
// while keeping allocations down to a minimum
|
151
169
|
indexMap = new Map();
|
152
|
-
for (let i = 0; i < length; i +=
|
170
|
+
for (let i = 0; i < length; i += 3) {
|
153
171
|
indexMap.set(modules[i], i + 1);
|
154
172
|
}
|
155
173
|
}
|
@@ -157,6 +175,7 @@ const extractBlockModules = (module, moduleGraph, runtime, blockModulesMap) => {
|
|
157
175
|
const idx = indexMap.get(m);
|
158
176
|
if (idx !== undefined) {
|
159
177
|
const merged = modules[idx];
|
178
|
+
modules[idx + 1].push(connection);
|
160
179
|
if (merged === true) continue outer;
|
161
180
|
modules[idx] = ModuleGraphConnection.addConnectionStates(
|
162
181
|
merged,
|
@@ -168,6 +187,8 @@ const extractBlockModules = (module, moduleGraph, runtime, blockModulesMap) => {
|
|
168
187
|
modules[length] = state;
|
169
188
|
indexMap.set(m, length);
|
170
189
|
length++;
|
190
|
+
modules[length] = [connection];
|
191
|
+
length++;
|
171
192
|
}
|
172
193
|
}
|
173
194
|
}
|
@@ -184,6 +205,7 @@ const extractBlockModules = (module, moduleGraph, runtime, blockModulesMap) => {
|
|
184
205
|
* @param {Map<AsyncDependenciesBlock, BlockChunkGroupConnection[]>} blockConnections connection for blocks
|
185
206
|
* @param {Set<DependenciesBlock>} blocksWithNestedBlocks flag for blocks that have nested blocks
|
186
207
|
* @param {Set<ChunkGroup>} allCreatedChunkGroups filled with all chunk groups that are created here
|
208
|
+
* @param {Map<Chunk, bigint>} maskByChunk module content mask by chunk
|
187
209
|
*/
|
188
210
|
const visitModules = (
|
189
211
|
logger,
|
@@ -192,7 +214,8 @@ const visitModules = (
|
|
192
214
|
chunkGroupInfoMap,
|
193
215
|
blockConnections,
|
194
216
|
blocksWithNestedBlocks,
|
195
|
-
allCreatedChunkGroups
|
217
|
+
allCreatedChunkGroups,
|
218
|
+
maskByChunk
|
196
219
|
) => {
|
197
220
|
const { moduleGraph, chunkGraph, moduleMemCaches } = compilation;
|
198
221
|
|
@@ -203,11 +226,35 @@ const visitModules = (
|
|
203
226
|
/** @type {Map<DependenciesBlock, (Module | ConnectionState)[]>} */
|
204
227
|
let blockModulesMap;
|
205
228
|
|
229
|
+
/** @type {Map<Module, number>} */
|
230
|
+
const ordinalByModule = new Map();
|
231
|
+
|
232
|
+
/**
|
233
|
+
* @param {Module} module The module to look up
|
234
|
+
* @returns {number} The ordinal of the module in masks
|
235
|
+
*/
|
236
|
+
const getModuleOrdinal = module => {
|
237
|
+
let ordinal = ordinalByModule.get(module);
|
238
|
+
if (ordinal === undefined) {
|
239
|
+
ordinal = ordinalByModule.size;
|
240
|
+
ordinalByModule.set(module, ordinal);
|
241
|
+
}
|
242
|
+
return ordinal;
|
243
|
+
};
|
244
|
+
|
245
|
+
for (const chunk of compilation.chunks) {
|
246
|
+
let mask = ZERO_BIGINT;
|
247
|
+
for (const m of chunkGraph.getChunkModulesIterable(chunk)) {
|
248
|
+
mask |= ONE_BIGINT << BigInt(getModuleOrdinal(m));
|
249
|
+
}
|
250
|
+
maskByChunk.set(chunk, mask);
|
251
|
+
}
|
252
|
+
|
206
253
|
/**
|
207
254
|
*
|
208
255
|
* @param {DependenciesBlock} block block
|
209
256
|
* @param {RuntimeSpec} runtime runtime
|
210
|
-
* @returns {(Module | ConnectionState)[]} block modules in flatten tuples
|
257
|
+
* @returns {(Module | ConnectionState | ModuleGraphConnection[])[]} block modules in flatten tuples
|
211
258
|
*/
|
212
259
|
const getBlockModules = (block, runtime) => {
|
213
260
|
if (blockModulesMapRuntime !== runtime) {
|
@@ -306,7 +353,6 @@ const visitModules = (
|
|
306
353
|
chunkGroup,
|
307
354
|
runtime,
|
308
355
|
minAvailableModules: undefined,
|
309
|
-
minAvailableModulesOwned: false,
|
310
356
|
availableModulesToBeMerged: [],
|
311
357
|
skippedItems: undefined,
|
312
358
|
resultingAvailableModules: undefined,
|
@@ -329,15 +375,12 @@ const visitModules = (
|
|
329
375
|
// minAvailableModules for child entrypoints are unknown yet, set to undefined.
|
330
376
|
// This means no module is added until other sets are merged into
|
331
377
|
// this minAvailableModules (by the parent entrypoints)
|
332
|
-
const skippedItems = new Set();
|
333
|
-
for (const module of modules) {
|
334
|
-
skippedItems.add(module);
|
335
|
-
}
|
378
|
+
const skippedItems = new Set(modules);
|
336
379
|
chunkGroupInfo.skippedItems = skippedItems;
|
337
380
|
chunkGroupsForCombining.add(chunkGroupInfo);
|
338
381
|
} else {
|
339
382
|
// The application may start here: We start with an empty list of available modules
|
340
|
-
chunkGroupInfo.minAvailableModules =
|
383
|
+
chunkGroupInfo.minAvailableModules = ZERO_BIGINT;
|
341
384
|
const chunk = chunkGroup.getEntrypointChunk();
|
342
385
|
for (const module of modules) {
|
343
386
|
queue.push({
|
@@ -382,7 +425,7 @@ const visitModules = (
|
|
382
425
|
/** @type {QueueItem[]} */
|
383
426
|
let queueDelayed = [];
|
384
427
|
|
385
|
-
/** @type {[Module,
|
428
|
+
/** @type {[Module, ModuleGraphConnection[]][]} */
|
386
429
|
const skipConnectionBuffer = [];
|
387
430
|
/** @type {Module[]} */
|
388
431
|
const skipBuffer = [];
|
@@ -425,12 +468,12 @@ const visitModules = (
|
|
425
468
|
b.loc,
|
426
469
|
b.request
|
427
470
|
);
|
471
|
+
maskByChunk.set(entrypoint.chunks[0], ZERO_BIGINT);
|
428
472
|
entrypoint.index = nextChunkGroupIndex++;
|
429
473
|
cgi = {
|
430
474
|
chunkGroup: entrypoint,
|
431
475
|
runtime: entrypoint.options.runtime || entrypoint.name,
|
432
|
-
minAvailableModules:
|
433
|
-
minAvailableModulesOwned: false,
|
476
|
+
minAvailableModules: ZERO_BIGINT,
|
434
477
|
availableModulesToBeMerged: [],
|
435
478
|
skippedItems: undefined,
|
436
479
|
resultingAvailableModules: undefined,
|
@@ -465,7 +508,7 @@ const visitModules = (
|
|
465
508
|
queueDelayed.push({
|
466
509
|
action: PROCESS_ENTRY_BLOCK,
|
467
510
|
block: b,
|
468
|
-
module
|
511
|
+
module,
|
469
512
|
chunk: entrypoint.chunks[0],
|
470
513
|
chunkGroup: entrypoint,
|
471
514
|
chunkGroupInfo: cgi
|
@@ -475,7 +518,7 @@ const visitModules = (
|
|
475
518
|
queue.push({
|
476
519
|
action: PROCESS_BLOCK,
|
477
520
|
block: b,
|
478
|
-
module
|
521
|
+
module,
|
479
522
|
chunk,
|
480
523
|
chunkGroup,
|
481
524
|
chunkGroupInfo
|
@@ -489,12 +532,12 @@ const visitModules = (
|
|
489
532
|
b.loc,
|
490
533
|
b.request
|
491
534
|
);
|
535
|
+
maskByChunk.set(c.chunks[0], ZERO_BIGINT);
|
492
536
|
c.index = nextChunkGroupIndex++;
|
493
537
|
cgi = {
|
494
538
|
chunkGroup: c,
|
495
539
|
runtime: chunkGroupInfo.runtime,
|
496
540
|
minAvailableModules: undefined,
|
497
|
-
minAvailableModulesOwned: undefined,
|
498
541
|
availableModulesToBeMerged: [],
|
499
542
|
skippedItems: undefined,
|
500
543
|
resultingAvailableModules: undefined,
|
@@ -559,7 +602,7 @@ const visitModules = (
|
|
559
602
|
queueDelayed.push({
|
560
603
|
action: PROCESS_BLOCK,
|
561
604
|
block: b,
|
562
|
-
module
|
605
|
+
module,
|
563
606
|
chunk: c.chunks[0],
|
564
607
|
chunkGroup: c,
|
565
608
|
chunkGroupInfo: /** @type {ChunkGroupInfo} */ (cgi)
|
@@ -582,24 +625,28 @@ const visitModules = (
|
|
582
625
|
const { minAvailableModules } = chunkGroupInfo;
|
583
626
|
// Buffer items because order need to be reversed to get indices correct
|
584
627
|
// Traverse all referenced modules
|
585
|
-
for (let i = 0
|
628
|
+
for (let i = 0, len = blockModules.length; i < len; i += 3) {
|
586
629
|
const refModule = /** @type {Module} */ (blockModules[i]);
|
587
|
-
|
630
|
+
// For single comparisons this might be cheaper
|
631
|
+
const isModuleInChunk = chunkGraph.isModuleInChunk(refModule, chunk);
|
632
|
+
|
633
|
+
if (isModuleInChunk) {
|
588
634
|
// skip early if already connected
|
589
635
|
continue;
|
590
636
|
}
|
637
|
+
|
638
|
+
const refOrdinal = /** @type {number} */ getModuleOrdinal(refModule);
|
591
639
|
const activeState = /** @type {ConnectionState} */ (
|
592
640
|
blockModules[i + 1]
|
593
641
|
);
|
594
642
|
if (activeState !== true) {
|
595
|
-
|
643
|
+
const connections = /** @type {ModuleGraphConnection[]} */ (
|
644
|
+
blockModules[i + 2]
|
645
|
+
);
|
646
|
+
skipConnectionBuffer.push([refModule, connections]);
|
647
|
+
// We skip inactive connections
|
596
648
|
if (activeState === false) continue;
|
597
|
-
}
|
598
|
-
if (
|
599
|
-
activeState === true &&
|
600
|
-
(minAvailableModules.has(refModule) ||
|
601
|
-
minAvailableModules.plus.has(refModule))
|
602
|
-
) {
|
649
|
+
} else if (isOrdinalSetInMask(minAvailableModules, refOrdinal)) {
|
603
650
|
// already in parent chunks, skip it for now
|
604
651
|
skipBuffer.push(refModule);
|
605
652
|
continue;
|
@@ -665,15 +712,15 @@ const visitModules = (
|
|
665
712
|
const blockModules = getBlockModules(block, chunkGroupInfo.runtime);
|
666
713
|
|
667
714
|
if (blockModules !== undefined) {
|
668
|
-
// Traverse all referenced modules
|
669
|
-
for (let i =
|
715
|
+
// Traverse all referenced modules in reverse order
|
716
|
+
for (let i = blockModules.length - 3; i >= 0; i -= 3) {
|
670
717
|
const refModule = /** @type {Module} */ (blockModules[i]);
|
671
718
|
const activeState = /** @type {ConnectionState} */ (
|
672
719
|
blockModules[i + 1]
|
673
720
|
);
|
674
721
|
// enqueue, then add and enter to be in the correct order
|
675
722
|
// this is relevant with circular dependencies
|
676
|
-
|
723
|
+
queue.push({
|
677
724
|
action:
|
678
725
|
activeState === true ? ADD_AND_ENTER_ENTRY_MODULE : PROCESS_BLOCK,
|
679
726
|
block: refModule,
|
@@ -683,13 +730,6 @@ const visitModules = (
|
|
683
730
|
chunkGroupInfo
|
684
731
|
});
|
685
732
|
}
|
686
|
-
// Add buffered items in reverse order
|
687
|
-
if (queueBuffer.length > 0) {
|
688
|
-
for (let i = queueBuffer.length - 1; i >= 0; i--) {
|
689
|
-
queue.push(queueBuffer[i]);
|
690
|
-
}
|
691
|
-
queueBuffer.length = 0;
|
692
|
-
}
|
693
733
|
}
|
694
734
|
|
695
735
|
// Traverse all Blocks
|
@@ -721,12 +761,18 @@ const visitModules = (
|
|
721
761
|
);
|
722
762
|
// fallthrough
|
723
763
|
case ADD_AND_ENTER_MODULE: {
|
724
|
-
|
764
|
+
const isModuleInChunk = chunkGraph.isModuleInChunk(module, chunk);
|
765
|
+
|
766
|
+
if (isModuleInChunk) {
|
725
767
|
// already connected, skip it
|
726
768
|
break;
|
727
769
|
}
|
728
770
|
// We connect Module and Chunk
|
729
771
|
chunkGraph.connectChunkAndModule(chunk, module);
|
772
|
+
const moduleOrdinal = getModuleOrdinal(module);
|
773
|
+
let chunkMask = maskByChunk.get(chunk);
|
774
|
+
chunkMask |= ONE_BIGINT << BigInt(moduleOrdinal);
|
775
|
+
maskByChunk.set(chunk, chunkMask);
|
730
776
|
}
|
731
777
|
// fallthrough
|
732
778
|
case ENTER_MODULE: {
|
@@ -783,44 +829,22 @@ const visitModules = (
|
|
783
829
|
}
|
784
830
|
};
|
785
831
|
|
832
|
+
/**
|
833
|
+
* @param {ChunkGroupInfo} chunkGroupInfo The info object for the chunk group
|
834
|
+
* @returns {bigint} The mask of available modules after the chunk group
|
835
|
+
*/
|
786
836
|
const calculateResultingAvailableModules = chunkGroupInfo => {
|
787
|
-
if (chunkGroupInfo.resultingAvailableModules)
|
837
|
+
if (chunkGroupInfo.resultingAvailableModules !== undefined)
|
788
838
|
return chunkGroupInfo.resultingAvailableModules;
|
789
839
|
|
790
|
-
|
791
|
-
|
792
|
-
// Create a new Set of available modules at this point
|
793
|
-
// We want to be as lazy as possible. There are multiple ways doing this:
|
794
|
-
// Note that resultingAvailableModules is stored as "(a) + (b)" as it's a ModuleSetPlus
|
795
|
-
// - resultingAvailableModules = (modules of chunk) + (minAvailableModules + minAvailableModules.plus)
|
796
|
-
// - resultingAvailableModules = (minAvailableModules + modules of chunk) + (minAvailableModules.plus)
|
797
|
-
// We choose one depending on the size of minAvailableModules vs minAvailableModules.plus
|
798
|
-
|
799
|
-
let resultingAvailableModules;
|
800
|
-
if (minAvailableModules.size > minAvailableModules.plus.size) {
|
801
|
-
// resultingAvailableModules = (modules of chunk) + (minAvailableModules + minAvailableModules.plus)
|
802
|
-
resultingAvailableModules =
|
803
|
-
/** @type {Set<Module> & {plus: Set<Module>}} */ (new Set());
|
804
|
-
for (const module of minAvailableModules.plus)
|
805
|
-
minAvailableModules.add(module);
|
806
|
-
minAvailableModules.plus = EMPTY_SET;
|
807
|
-
resultingAvailableModules.plus = minAvailableModules;
|
808
|
-
chunkGroupInfo.minAvailableModulesOwned = false;
|
809
|
-
} else {
|
810
|
-
// resultingAvailableModules = (minAvailableModules + modules of chunk) + (minAvailableModules.plus)
|
811
|
-
resultingAvailableModules =
|
812
|
-
/** @type {Set<Module> & {plus: Set<Module>}} */ (
|
813
|
-
new Set(minAvailableModules)
|
814
|
-
);
|
815
|
-
resultingAvailableModules.plus = minAvailableModules.plus;
|
816
|
-
}
|
840
|
+
let resultingAvailableModules = chunkGroupInfo.minAvailableModules;
|
817
841
|
|
818
842
|
// add the modules from the chunk group to the set
|
819
843
|
for (const chunk of chunkGroupInfo.chunkGroup.chunks) {
|
820
|
-
|
821
|
-
|
822
|
-
}
|
844
|
+
const mask = maskByChunk.get(chunk);
|
845
|
+
resultingAvailableModules |= mask;
|
823
846
|
}
|
847
|
+
|
824
848
|
return (chunkGroupInfo.resultingAvailableModules =
|
825
849
|
resultingAvailableModules);
|
826
850
|
};
|
@@ -867,232 +891,24 @@ const visitModules = (
|
|
867
891
|
// Execute the merge
|
868
892
|
for (const info of chunkGroupsForMerging) {
|
869
893
|
const availableModulesToBeMerged = info.availableModulesToBeMerged;
|
870
|
-
|
894
|
+
const cachedMinAvailableModules = info.minAvailableModules;
|
895
|
+
let minAvailableModules = cachedMinAvailableModules;
|
871
896
|
|
872
897
|
statMergedAvailableModuleSets += availableModulesToBeMerged.length;
|
873
898
|
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
// the list didn't shrink.
|
878
|
-
if (availableModulesToBeMerged.length > 1) {
|
879
|
-
availableModulesToBeMerged.sort(bySetSize);
|
880
|
-
}
|
881
|
-
let changed = false;
|
882
|
-
merge: for (const availableModules of availableModulesToBeMerged) {
|
883
|
-
if (cachedMinAvailableModules === undefined) {
|
884
|
-
cachedMinAvailableModules = availableModules;
|
885
|
-
info.minAvailableModules = cachedMinAvailableModules;
|
886
|
-
info.minAvailableModulesOwned = false;
|
887
|
-
changed = true;
|
899
|
+
for (const availableModules of availableModulesToBeMerged) {
|
900
|
+
if (minAvailableModules === undefined) {
|
901
|
+
minAvailableModules = availableModules;
|
888
902
|
} else {
|
889
|
-
|
890
|
-
// We own it and can modify it
|
891
|
-
if (cachedMinAvailableModules.plus === availableModules.plus) {
|
892
|
-
for (const m of cachedMinAvailableModules) {
|
893
|
-
if (!availableModules.has(m)) {
|
894
|
-
cachedMinAvailableModules.delete(m);
|
895
|
-
changed = true;
|
896
|
-
}
|
897
|
-
}
|
898
|
-
} else {
|
899
|
-
for (const m of cachedMinAvailableModules) {
|
900
|
-
if (!availableModules.has(m) && !availableModules.plus.has(m)) {
|
901
|
-
cachedMinAvailableModules.delete(m);
|
902
|
-
changed = true;
|
903
|
-
}
|
904
|
-
}
|
905
|
-
for (const m of cachedMinAvailableModules.plus) {
|
906
|
-
if (!availableModules.has(m) && !availableModules.plus.has(m)) {
|
907
|
-
// We can't remove modules from the plus part
|
908
|
-
// so we need to merge plus into the normal part to allow modifying it
|
909
|
-
const iterator =
|
910
|
-
cachedMinAvailableModules.plus[Symbol.iterator]();
|
911
|
-
// fast forward add all modules until m
|
912
|
-
/** @type {IteratorResult<Module>} */
|
913
|
-
let it;
|
914
|
-
while (!(it = iterator.next()).done) {
|
915
|
-
const module = it.value;
|
916
|
-
if (module === m) break;
|
917
|
-
cachedMinAvailableModules.add(module);
|
918
|
-
}
|
919
|
-
// check the remaining modules before adding
|
920
|
-
while (!(it = iterator.next()).done) {
|
921
|
-
const module = it.value;
|
922
|
-
if (
|
923
|
-
availableModules.has(module) ||
|
924
|
-
availableModules.plus.has(module)
|
925
|
-
) {
|
926
|
-
cachedMinAvailableModules.add(module);
|
927
|
-
}
|
928
|
-
}
|
929
|
-
cachedMinAvailableModules.plus = EMPTY_SET;
|
930
|
-
changed = true;
|
931
|
-
continue merge;
|
932
|
-
}
|
933
|
-
}
|
934
|
-
}
|
935
|
-
} else if (cachedMinAvailableModules.plus === availableModules.plus) {
|
936
|
-
// Common and fast case when the plus part is shared
|
937
|
-
// We only need to care about the normal part
|
938
|
-
if (availableModules.size < cachedMinAvailableModules.size) {
|
939
|
-
// the new availableModules is smaller so it's faster to
|
940
|
-
// fork from the new availableModules
|
941
|
-
statForkedAvailableModules++;
|
942
|
-
statForkedAvailableModulesCount += availableModules.size;
|
943
|
-
statForkedMergedModulesCount += cachedMinAvailableModules.size;
|
944
|
-
// construct a new Set as intersection of cachedMinAvailableModules and availableModules
|
945
|
-
const newSet = /** @type {ModuleSetPlus} */ (new Set());
|
946
|
-
newSet.plus = availableModules.plus;
|
947
|
-
for (const m of availableModules) {
|
948
|
-
if (cachedMinAvailableModules.has(m)) {
|
949
|
-
newSet.add(m);
|
950
|
-
}
|
951
|
-
}
|
952
|
-
statForkedResultModulesCount += newSet.size;
|
953
|
-
cachedMinAvailableModules = newSet;
|
954
|
-
info.minAvailableModulesOwned = true;
|
955
|
-
info.minAvailableModules = newSet;
|
956
|
-
changed = true;
|
957
|
-
continue merge;
|
958
|
-
}
|
959
|
-
for (const m of cachedMinAvailableModules) {
|
960
|
-
if (!availableModules.has(m)) {
|
961
|
-
// cachedMinAvailableModules need to be modified
|
962
|
-
// but we don't own it
|
963
|
-
statForkedAvailableModules++;
|
964
|
-
statForkedAvailableModulesCount +=
|
965
|
-
cachedMinAvailableModules.size;
|
966
|
-
statForkedMergedModulesCount += availableModules.size;
|
967
|
-
// construct a new Set as intersection of cachedMinAvailableModules and availableModules
|
968
|
-
// as the plus part is equal we can just take over this one
|
969
|
-
const newSet = /** @type {ModuleSetPlus} */ (new Set());
|
970
|
-
newSet.plus = availableModules.plus;
|
971
|
-
const iterator = cachedMinAvailableModules[Symbol.iterator]();
|
972
|
-
// fast forward add all modules until m
|
973
|
-
/** @type {IteratorResult<Module>} */
|
974
|
-
let it;
|
975
|
-
while (!(it = iterator.next()).done) {
|
976
|
-
const module = it.value;
|
977
|
-
if (module === m) break;
|
978
|
-
newSet.add(module);
|
979
|
-
}
|
980
|
-
// check the remaining modules before adding
|
981
|
-
while (!(it = iterator.next()).done) {
|
982
|
-
const module = it.value;
|
983
|
-
if (availableModules.has(module)) {
|
984
|
-
newSet.add(module);
|
985
|
-
}
|
986
|
-
}
|
987
|
-
statForkedResultModulesCount += newSet.size;
|
988
|
-
cachedMinAvailableModules = newSet;
|
989
|
-
info.minAvailableModulesOwned = true;
|
990
|
-
info.minAvailableModules = newSet;
|
991
|
-
changed = true;
|
992
|
-
continue merge;
|
993
|
-
}
|
994
|
-
}
|
995
|
-
} else {
|
996
|
-
for (const m of cachedMinAvailableModules) {
|
997
|
-
if (!availableModules.has(m) && !availableModules.plus.has(m)) {
|
998
|
-
// cachedMinAvailableModules need to be modified
|
999
|
-
// but we don't own it
|
1000
|
-
statForkedAvailableModules++;
|
1001
|
-
statForkedAvailableModulesCount +=
|
1002
|
-
cachedMinAvailableModules.size;
|
1003
|
-
statForkedAvailableModulesCountPlus +=
|
1004
|
-
cachedMinAvailableModules.plus.size;
|
1005
|
-
statForkedMergedModulesCount += availableModules.size;
|
1006
|
-
statForkedMergedModulesCountPlus += availableModules.plus.size;
|
1007
|
-
// construct a new Set as intersection of cachedMinAvailableModules and availableModules
|
1008
|
-
const newSet = /** @type {ModuleSetPlus} */ (new Set());
|
1009
|
-
newSet.plus = EMPTY_SET;
|
1010
|
-
const iterator = cachedMinAvailableModules[Symbol.iterator]();
|
1011
|
-
// fast forward add all modules until m
|
1012
|
-
/** @type {IteratorResult<Module>} */
|
1013
|
-
let it;
|
1014
|
-
while (!(it = iterator.next()).done) {
|
1015
|
-
const module = it.value;
|
1016
|
-
if (module === m) break;
|
1017
|
-
newSet.add(module);
|
1018
|
-
}
|
1019
|
-
// check the remaining modules before adding
|
1020
|
-
while (!(it = iterator.next()).done) {
|
1021
|
-
const module = it.value;
|
1022
|
-
if (
|
1023
|
-
availableModules.has(module) ||
|
1024
|
-
availableModules.plus.has(module)
|
1025
|
-
) {
|
1026
|
-
newSet.add(module);
|
1027
|
-
}
|
1028
|
-
}
|
1029
|
-
// also check all modules in cachedMinAvailableModules.plus
|
1030
|
-
for (const module of cachedMinAvailableModules.plus) {
|
1031
|
-
if (
|
1032
|
-
availableModules.has(module) ||
|
1033
|
-
availableModules.plus.has(module)
|
1034
|
-
) {
|
1035
|
-
newSet.add(module);
|
1036
|
-
}
|
1037
|
-
}
|
1038
|
-
statForkedResultModulesCount += newSet.size;
|
1039
|
-
cachedMinAvailableModules = newSet;
|
1040
|
-
info.minAvailableModulesOwned = true;
|
1041
|
-
info.minAvailableModules = newSet;
|
1042
|
-
changed = true;
|
1043
|
-
continue merge;
|
1044
|
-
}
|
1045
|
-
}
|
1046
|
-
for (const m of cachedMinAvailableModules.plus) {
|
1047
|
-
if (!availableModules.has(m) && !availableModules.plus.has(m)) {
|
1048
|
-
// cachedMinAvailableModules need to be modified
|
1049
|
-
// but we don't own it
|
1050
|
-
statForkedAvailableModules++;
|
1051
|
-
statForkedAvailableModulesCount +=
|
1052
|
-
cachedMinAvailableModules.size;
|
1053
|
-
statForkedAvailableModulesCountPlus +=
|
1054
|
-
cachedMinAvailableModules.plus.size;
|
1055
|
-
statForkedMergedModulesCount += availableModules.size;
|
1056
|
-
statForkedMergedModulesCountPlus += availableModules.plus.size;
|
1057
|
-
// construct a new Set as intersection of cachedMinAvailableModules and availableModules
|
1058
|
-
// we already know that all modules directly from cachedMinAvailableModules are in availableModules too
|
1059
|
-
const newSet = /** @type {ModuleSetPlus} */ (
|
1060
|
-
new Set(cachedMinAvailableModules)
|
1061
|
-
);
|
1062
|
-
newSet.plus = EMPTY_SET;
|
1063
|
-
const iterator =
|
1064
|
-
cachedMinAvailableModules.plus[Symbol.iterator]();
|
1065
|
-
// fast forward add all modules until m
|
1066
|
-
/** @type {IteratorResult<Module>} */
|
1067
|
-
let it;
|
1068
|
-
while (!(it = iterator.next()).done) {
|
1069
|
-
const module = it.value;
|
1070
|
-
if (module === m) break;
|
1071
|
-
newSet.add(module);
|
1072
|
-
}
|
1073
|
-
// check the remaining modules before adding
|
1074
|
-
while (!(it = iterator.next()).done) {
|
1075
|
-
const module = it.value;
|
1076
|
-
if (
|
1077
|
-
availableModules.has(module) ||
|
1078
|
-
availableModules.plus.has(module)
|
1079
|
-
) {
|
1080
|
-
newSet.add(module);
|
1081
|
-
}
|
1082
|
-
}
|
1083
|
-
statForkedResultModulesCount += newSet.size;
|
1084
|
-
cachedMinAvailableModules = newSet;
|
1085
|
-
info.minAvailableModulesOwned = true;
|
1086
|
-
info.minAvailableModules = newSet;
|
1087
|
-
changed = true;
|
1088
|
-
continue merge;
|
1089
|
-
}
|
1090
|
-
}
|
1091
|
-
}
|
903
|
+
minAvailableModules &= availableModules;
|
1092
904
|
}
|
1093
905
|
}
|
906
|
+
|
907
|
+
const changed = minAvailableModules !== cachedMinAvailableModules;
|
908
|
+
|
1094
909
|
availableModulesToBeMerged.length = 0;
|
1095
910
|
if (changed) {
|
911
|
+
info.minAvailableModules = minAvailableModules;
|
1096
912
|
info.resultingAvailableModules = undefined;
|
1097
913
|
outdatedChunkGroupInfo.add(info);
|
1098
914
|
}
|
@@ -1105,34 +921,24 @@ const visitModules = (
|
|
1105
921
|
for (const source of /** @type {Set<ChunkGroupInfo>} */ (
|
1106
922
|
info.availableSources
|
1107
923
|
)) {
|
1108
|
-
if (
|
924
|
+
if (source.minAvailableModules === undefined) {
|
1109
925
|
chunkGroupsForCombining.delete(info);
|
1110
926
|
break;
|
1111
927
|
}
|
1112
928
|
}
|
1113
929
|
}
|
930
|
+
|
1114
931
|
for (const info of chunkGroupsForCombining) {
|
1115
|
-
|
1116
|
-
availableModules.plus = EMPTY_SET;
|
1117
|
-
const mergeSet = set => {
|
1118
|
-
if (set.size > availableModules.plus.size) {
|
1119
|
-
for (const item of availableModules.plus) availableModules.add(item);
|
1120
|
-
availableModules.plus = set;
|
1121
|
-
} else {
|
1122
|
-
for (const item of set) availableModules.add(item);
|
1123
|
-
}
|
1124
|
-
};
|
932
|
+
let availableModules = ZERO_BIGINT;
|
1125
933
|
// combine minAvailableModules from all resultingAvailableModules
|
1126
934
|
for (const source of /** @type {Set<ChunkGroupInfo>} */ (
|
1127
935
|
info.availableSources
|
1128
936
|
)) {
|
1129
937
|
const resultingAvailableModules =
|
1130
938
|
calculateResultingAvailableModules(source);
|
1131
|
-
|
1132
|
-
mergeSet(resultingAvailableModules.plus);
|
939
|
+
availableModules |= resultingAvailableModules;
|
1133
940
|
}
|
1134
941
|
info.minAvailableModules = availableModules;
|
1135
|
-
info.minAvailableModulesOwned = false;
|
1136
942
|
info.resultingAvailableModules = undefined;
|
1137
943
|
outdatedChunkGroupInfo.add(info);
|
1138
944
|
}
|
@@ -1146,13 +952,11 @@ const visitModules = (
|
|
1146
952
|
// 1. Reconsider skipped items
|
1147
953
|
if (info.skippedItems !== undefined) {
|
1148
954
|
const minAvailableModules =
|
1149
|
-
/** @type {
|
955
|
+
/** @type {bigint} */
|
1150
956
|
(info.minAvailableModules);
|
1151
957
|
for (const module of info.skippedItems) {
|
1152
|
-
|
1153
|
-
|
1154
|
-
!minAvailableModules.plus.has(module)
|
1155
|
-
) {
|
958
|
+
const ordinal = getModuleOrdinal(module);
|
959
|
+
if (!isOrdinalSetInMask(minAvailableModules, ordinal)) {
|
1156
960
|
queue.push({
|
1157
961
|
action: ADD_AND_ENTER_MODULE,
|
1158
962
|
block: module,
|
@@ -1169,21 +973,22 @@ const visitModules = (
|
|
1169
973
|
// 2. Reconsider skipped connections
|
1170
974
|
if (info.skippedModuleConnections !== undefined) {
|
1171
975
|
const minAvailableModules =
|
1172
|
-
/** @type {
|
976
|
+
/** @type {bigint} */
|
1173
977
|
(info.minAvailableModules);
|
1174
978
|
for (const entry of info.skippedModuleConnections) {
|
1175
|
-
const [module,
|
979
|
+
const [module, connections] = entry;
|
980
|
+
const activeState = getActiveStateOfConnections(
|
981
|
+
connections,
|
982
|
+
info.runtime
|
983
|
+
);
|
1176
984
|
if (activeState === false) continue;
|
1177
985
|
if (activeState === true) {
|
986
|
+
const ordinal = getModuleOrdinal(module);
|
1178
987
|
info.skippedModuleConnections.delete(entry);
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
minAvailableModules.plus.has(module))
|
1184
|
-
) {
|
1185
|
-
info.skippedItems.add(module);
|
1186
|
-
continue;
|
988
|
+
if (isOrdinalSetInMask(minAvailableModules, ordinal)) {
|
989
|
+
info.skippedItems.add(module);
|
990
|
+
continue;
|
991
|
+
}
|
1187
992
|
}
|
1188
993
|
queue.push({
|
1189
994
|
action: activeState === true ? ADD_AND_ENTER_MODULE : PROCESS_BLOCK,
|
@@ -1274,7 +1079,7 @@ const visitModules = (
|
|
1274
1079
|
let preOrderIndex = 0;
|
1275
1080
|
let postOrderIndex = 0;
|
1276
1081
|
|
1277
|
-
const process = (current, visited
|
1082
|
+
const process = (current, visited) => {
|
1278
1083
|
if (visited.has(current)) {
|
1279
1084
|
return;
|
1280
1085
|
}
|
@@ -1286,14 +1091,14 @@ const visitModules = (
|
|
1286
1091
|
return;
|
1287
1092
|
}
|
1288
1093
|
|
1289
|
-
for (let i = 0
|
1290
|
-
const refModule = /** @type {Module} */ (blockModules[i]);
|
1094
|
+
for (let i = 0, len = blockModules.length; i < len; i += 3) {
|
1291
1095
|
const activeState = /** @type {ConnectionState} */ (
|
1292
1096
|
blockModules[i + 1]
|
1293
1097
|
);
|
1294
1098
|
if (activeState === false) {
|
1295
1099
|
continue;
|
1296
1100
|
}
|
1101
|
+
const refModule = /** @type {Module} */ (blockModules[i]);
|
1297
1102
|
|
1298
1103
|
if (refModule) {
|
1299
1104
|
chunkGroup.setModulePreOrderIndex(refModule, preOrderIndex++);
|
@@ -1303,9 +1108,10 @@ const visitModules = (
|
|
1303
1108
|
}
|
1304
1109
|
};
|
1305
1110
|
|
1306
|
-
process(block);
|
1111
|
+
process(block, new Set());
|
1307
1112
|
}
|
1308
1113
|
outdatedOrderIndexChunkGroups.clear();
|
1114
|
+
ordinalByModule.clear();
|
1309
1115
|
|
1310
1116
|
logger.log(
|
1311
1117
|
`${statProcessedQueueItems} queue items processed (${statProcessedBlocks} blocks)`
|
@@ -1324,13 +1130,13 @@ const visitModules = (
|
|
1324
1130
|
* @param {Compilation} compilation the compilation
|
1325
1131
|
* @param {Set<DependenciesBlock>} blocksWithNestedBlocks flag for blocks that have nested blocks
|
1326
1132
|
* @param {Map<AsyncDependenciesBlock, BlockChunkGroupConnection[]>} blockConnections connection for blocks
|
1327
|
-
* @param {Map<
|
1133
|
+
* @param {Map<Chunk, bigint>} maskByChunk mapping from chunk to module mask
|
1328
1134
|
*/
|
1329
1135
|
const connectChunkGroups = (
|
1330
1136
|
compilation,
|
1331
1137
|
blocksWithNestedBlocks,
|
1332
1138
|
blockConnections,
|
1333
|
-
|
1139
|
+
maskByChunk
|
1334
1140
|
) => {
|
1335
1141
|
const { chunkGraph } = compilation;
|
1336
1142
|
|
@@ -1338,15 +1144,13 @@ const connectChunkGroups = (
|
|
1338
1144
|
* Helper function to check if all modules of a chunk are available
|
1339
1145
|
*
|
1340
1146
|
* @param {ChunkGroup} chunkGroup the chunkGroup to scan
|
1341
|
-
* @param {
|
1147
|
+
* @param {bigint} availableModules the comparator set
|
1342
1148
|
* @returns {boolean} return true if all modules of a chunk are available
|
1343
1149
|
*/
|
1344
1150
|
const areModulesAvailable = (chunkGroup, availableModules) => {
|
1345
1151
|
for (const chunk of chunkGroup.chunks) {
|
1346
|
-
|
1347
|
-
|
1348
|
-
return false;
|
1349
|
-
}
|
1152
|
+
const chunkMask = maskByChunk.get(chunk);
|
1153
|
+
if ((chunkMask & availableModules) !== chunkMask) return false;
|
1350
1154
|
}
|
1351
1155
|
return true;
|
1352
1156
|
};
|
@@ -1431,6 +1235,9 @@ const buildChunkGraph = (compilation, inputEntrypointsAndModules) => {
|
|
1431
1235
|
/** @type {Set<DependenciesBlock>} */
|
1432
1236
|
const blocksWithNestedBlocks = new Set();
|
1433
1237
|
|
1238
|
+
/** @type {Map<Chunk, bigint>} */
|
1239
|
+
const maskByChunk = new Map();
|
1240
|
+
|
1434
1241
|
// PART ONE
|
1435
1242
|
|
1436
1243
|
logger.time("visitModules");
|
@@ -1441,7 +1248,8 @@ const buildChunkGraph = (compilation, inputEntrypointsAndModules) => {
|
|
1441
1248
|
chunkGroupInfoMap,
|
1442
1249
|
blockConnections,
|
1443
1250
|
blocksWithNestedBlocks,
|
1444
|
-
allCreatedChunkGroups
|
1251
|
+
allCreatedChunkGroups,
|
1252
|
+
maskByChunk
|
1445
1253
|
);
|
1446
1254
|
logger.timeEnd("visitModules");
|
1447
1255
|
|
@@ -1452,7 +1260,7 @@ const buildChunkGraph = (compilation, inputEntrypointsAndModules) => {
|
|
1452
1260
|
compilation,
|
1453
1261
|
blocksWithNestedBlocks,
|
1454
1262
|
blockConnections,
|
1455
|
-
|
1263
|
+
maskByChunk
|
1456
1264
|
);
|
1457
1265
|
logger.timeEnd("connectChunkGroups");
|
1458
1266
|
|