webpack 5.90.2 → 5.91.0

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.

Files changed (182) hide show
  1. package/README.md +5 -5
  2. package/bin/webpack.js +5 -1
  3. package/lib/APIPlugin.js +8 -4
  4. package/lib/AutomaticPrefetchPlugin.js +1 -1
  5. package/lib/BannerPlugin.js +3 -1
  6. package/lib/Cache.js +7 -1
  7. package/lib/CacheFacade.js +3 -3
  8. package/lib/ChunkGraph.js +32 -18
  9. package/lib/ChunkGroup.js +14 -14
  10. package/lib/CleanPlugin.js +7 -5
  11. package/lib/Compilation.js +263 -94
  12. package/lib/Compiler.js +199 -83
  13. package/lib/ConditionalInitFragment.js +4 -5
  14. package/lib/ContextModule.js +4 -1
  15. package/lib/ContextModuleFactory.js +4 -2
  16. package/lib/ContextReplacementPlugin.js +3 -2
  17. package/lib/CssModule.js +0 -3
  18. package/lib/DefinePlugin.js +4 -2
  19. package/lib/DelegatedModule.js +2 -1
  20. package/lib/Dependency.js +4 -2
  21. package/lib/DependencyTemplate.js +7 -2
  22. package/lib/DllModule.js +3 -1
  23. package/lib/DllReferencePlugin.js +6 -2
  24. package/lib/EntryOptionPlugin.js +4 -1
  25. package/lib/EntryPlugin.js +6 -1
  26. package/lib/Entrypoint.js +1 -1
  27. package/lib/ExportsInfo.js +1 -4
  28. package/lib/ExternalModule.js +120 -25
  29. package/lib/ExternalModuleFactoryPlugin.js +37 -2
  30. package/lib/FileSystemInfo.js +1 -1
  31. package/lib/Generator.js +2 -1
  32. package/lib/HookWebpackError.js +2 -2
  33. package/lib/InitFragment.js +5 -3
  34. package/lib/LibManifestPlugin.js +15 -7
  35. package/lib/Module.js +54 -5
  36. package/lib/ModuleFilenameHelpers.js +1 -1
  37. package/lib/ModuleGraph.js +56 -27
  38. package/lib/ModuleGraphConnection.js +2 -1
  39. package/lib/MultiCompiler.js +61 -17
  40. package/lib/NodeStuffPlugin.js +14 -3
  41. package/lib/NormalModule.js +239 -86
  42. package/lib/NormalModuleFactory.js +163 -32
  43. package/lib/NormalModuleReplacementPlugin.js +5 -1
  44. package/lib/ProvidePlugin.js +3 -1
  45. package/lib/RawModule.js +4 -2
  46. package/lib/ResolverFactory.js +5 -1
  47. package/lib/RuntimeModule.js +6 -5
  48. package/lib/RuntimePlugin.js +1 -0
  49. package/lib/RuntimeTemplate.js +102 -34
  50. package/lib/SourceMapDevToolPlugin.js +4 -1
  51. package/lib/Stats.js +12 -5
  52. package/lib/TemplatedPathPlugin.js +32 -6
  53. package/lib/Watching.js +67 -60
  54. package/lib/WebpackError.js +6 -6
  55. package/lib/WebpackOptionsApply.js +18 -5
  56. package/lib/asset/RawDataUrlModule.js +5 -2
  57. package/lib/async-modules/AwaitDependenciesInitFragment.js +2 -2
  58. package/lib/buildChunkGraph.js +220 -392
  59. package/lib/cache/IdleFileCachePlugin.js +8 -3
  60. package/lib/cache/MemoryCachePlugin.js +1 -1
  61. package/lib/cache/MemoryWithGcCachePlugin.js +6 -2
  62. package/lib/cache/PackFileCacheStrategy.js +49 -16
  63. package/lib/cache/ResolverCachePlugin.js +14 -6
  64. package/lib/cache/getLazyHashedEtag.js +1 -1
  65. package/lib/config/defaults.js +24 -1
  66. package/lib/config/normalization.js +3 -1
  67. package/lib/container/ContainerEntryDependency.js +2 -1
  68. package/lib/container/ContainerEntryModule.js +5 -2
  69. package/lib/container/ContainerPlugin.js +14 -10
  70. package/lib/container/FallbackModule.js +3 -2
  71. package/lib/container/RemoteModule.js +2 -1
  72. package/lib/container/RemoteRuntimeModule.js +12 -3
  73. package/lib/css/CssExportsGenerator.js +34 -17
  74. package/lib/css/CssGenerator.js +20 -2
  75. package/lib/css/CssLoadingRuntimeModule.js +212 -96
  76. package/lib/css/CssModulesPlugin.js +47 -13
  77. package/lib/debug/ProfilingPlugin.js +27 -2
  78. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +9 -5
  79. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +4 -1
  80. package/lib/dependencies/CommonJsDependencyHelpers.js +2 -1
  81. package/lib/dependencies/CommonJsExportRequireDependency.js +33 -18
  82. package/lib/dependencies/CommonJsExportsDependency.js +13 -5
  83. package/lib/dependencies/CommonJsExportsParserPlugin.js +20 -15
  84. package/lib/dependencies/CommonJsImportsParserPlugin.js +1 -2
  85. package/lib/dependencies/ContextDependencyHelpers.js +49 -29
  86. package/lib/dependencies/ContextElementDependency.js +8 -1
  87. package/lib/dependencies/CssLocalIdentifierDependency.js +63 -8
  88. package/lib/dependencies/CssUrlDependency.js +5 -3
  89. package/lib/dependencies/ExportsInfoDependency.js +4 -3
  90. package/lib/dependencies/ExternalModuleInitFragment.js +5 -3
  91. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +4 -4
  92. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +43 -23
  93. package/lib/dependencies/HarmonyExportHeaderDependency.js +1 -1
  94. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +73 -32
  95. package/lib/dependencies/HarmonyExportInitFragment.js +10 -2
  96. package/lib/dependencies/HarmonyImportDependency.js +28 -12
  97. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +44 -16
  98. package/lib/dependencies/HarmonyImportSideEffectDependency.js +7 -6
  99. package/lib/dependencies/HarmonyImportSpecifierDependency.js +21 -10
  100. package/lib/dependencies/ImportDependency.js +9 -2
  101. package/lib/dependencies/ImportEagerDependency.js +4 -2
  102. package/lib/dependencies/ImportMetaContextDependency.js +7 -0
  103. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +25 -14
  104. package/lib/dependencies/ImportParserPlugin.js +12 -4
  105. package/lib/dependencies/ImportWeakDependency.js +4 -2
  106. package/lib/dependencies/LoaderDependency.js +2 -1
  107. package/lib/dependencies/LoaderImportDependency.js +2 -1
  108. package/lib/dependencies/ModuleDependency.js +4 -5
  109. package/lib/dependencies/PureExpressionDependency.js +4 -1
  110. package/lib/dependencies/RequireContextPlugin.js +1 -1
  111. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +26 -14
  112. package/lib/dependencies/RequireEnsureDependency.js +1 -1
  113. package/lib/dependencies/URLDependency.js +7 -4
  114. package/lib/dependencies/WorkerDependency.js +1 -1
  115. package/lib/dependencies/WorkerPlugin.js +6 -5
  116. package/lib/dependencies/getFunctionExpression.js +3 -1
  117. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +2 -1
  118. package/lib/hmr/LazyCompilationPlugin.js +2 -1
  119. package/lib/javascript/BasicEvaluatedExpression.js +2 -2
  120. package/lib/javascript/ChunkHelpers.js +2 -2
  121. package/lib/javascript/JavascriptParser.js +169 -57
  122. package/lib/javascript/JavascriptParserHelpers.js +1 -1
  123. package/lib/javascript/StartupHelpers.js +22 -5
  124. package/lib/logging/Logger.js +27 -2
  125. package/lib/logging/createConsoleLogger.js +11 -7
  126. package/lib/node/NodeEnvironmentPlugin.js +13 -7
  127. package/lib/node/NodeWatchFileSystem.js +37 -26
  128. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +2 -1
  129. package/lib/node/RequireChunkLoadingRuntimeModule.js +2 -1
  130. package/lib/node/nodeConsole.js +24 -1
  131. package/lib/optimize/AggressiveSplittingPlugin.js +1 -0
  132. package/lib/optimize/ConcatenatedModule.js +140 -55
  133. package/lib/optimize/EnsureChunkConditionsPlugin.js +1 -1
  134. package/lib/optimize/InnerGraph.js +7 -2
  135. package/lib/optimize/InnerGraphPlugin.js +36 -13
  136. package/lib/optimize/ModuleConcatenationPlugin.js +12 -2
  137. package/lib/optimize/RemoveParentModulesPlugin.js +1 -0
  138. package/lib/optimize/RuntimeChunkPlugin.js +6 -1
  139. package/lib/optimize/SideEffectsFlagPlugin.js +46 -15
  140. package/lib/optimize/SplitChunksPlugin.js +2 -2
  141. package/lib/performance/SizeLimitsPlugin.js +11 -0
  142. package/lib/rules/ObjectMatcherRulePlugin.js +4 -0
  143. package/lib/runtime/EnsureChunkRuntimeModule.js +2 -1
  144. package/lib/runtime/GetTrustedTypesPolicyRuntimeModule.js +2 -1
  145. package/lib/serialization/FileMiddleware.js +1 -0
  146. package/lib/serialization/ObjectMiddleware.js +2 -0
  147. package/lib/serialization/Serializer.js +19 -0
  148. package/lib/sharing/ConsumeSharedModule.js +3 -2
  149. package/lib/sharing/ConsumeSharedPlugin.js +17 -3
  150. package/lib/sharing/ConsumeSharedRuntimeModule.js +9 -2
  151. package/lib/sharing/ProvideSharedModule.js +2 -1
  152. package/lib/sharing/ProvideSharedPlugin.js +12 -5
  153. package/lib/sharing/resolveMatchedConfigs.js +2 -2
  154. package/lib/sharing/utils.js +13 -6
  155. package/lib/util/StackedCacheMap.js +26 -0
  156. package/lib/util/WeakTupleMap.js +57 -13
  157. package/lib/util/cleverMerge.js +24 -11
  158. package/lib/util/comparators.js +34 -14
  159. package/lib/util/conventions.js +129 -0
  160. package/lib/util/fs.js +379 -65
  161. package/lib/util/hash/BatchedHash.js +3 -0
  162. package/lib/util/hash/xxhash64.js +2 -2
  163. package/lib/util/memoize.js +2 -0
  164. package/lib/util/runtime.js +1 -1
  165. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +4 -2
  166. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +15 -6
  167. package/lib/wasm-sync/WebAssemblyGenerator.js +27 -6
  168. package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +2 -1
  169. package/lib/wasm-sync/WebAssemblyParser.js +7 -4
  170. package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -1
  171. package/lib/webpack.js +11 -5
  172. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +2 -1
  173. package/package.json +25 -26
  174. package/schemas/WebpackOptions.check.js +1 -1
  175. package/schemas/WebpackOptions.json +69 -8
  176. package/schemas/plugins/BannerPlugin.check.js +1 -1
  177. package/schemas/plugins/BannerPlugin.json +5 -1
  178. package/schemas/plugins/css/CssAutoGeneratorOptions.check.js +1 -1
  179. package/schemas/plugins/css/CssGeneratorOptions.check.js +1 -1
  180. package/schemas/plugins/css/CssGlobalGeneratorOptions.check.js +1 -1
  181. package/schemas/plugins/css/CssModuleGeneratorOptions.check.js +1 -1
  182. package/types.d.ts +1772 -673
@@ -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 {ModuleSetPlus | undefined} minAvailableModules current minimal set of modules available at this point
44
- * @property {boolean | undefined} minAvailableModulesOwned true, if minAvailableModules is owned and can be modified
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
44
  * @property {Set<[Module, ModuleGraphConnection[]]>=} skippedModuleConnections referenced modules that where skipped because they were not active in this runtime
48
- * @property {ModuleSetPlus | undefined} resultingAvailableModules set of modules available including modules from this chunk group
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,17 +58,26 @@ const { getEntryRuntime, mergeRuntime } = require("./util/runtime");
61
58
  * @property {ChunkGroup} chunkGroup referenced chunk group
62
59
  */
63
60
 
64
- const EMPTY_SET = /** @type {ModuleSetPlus} */ (new Set());
65
- EMPTY_SET.plus = EMPTY_SET;
61
+ /** @typedef {(Module | ConnectionState | ModuleGraphConnection)[]} BlockModulesInTuples */
62
+ /** @typedef {(Module | ConnectionState | ModuleGraphConnection[])[]} BlockModulesInFlattenTuples */
63
+ /** @typedef {Map<DependenciesBlock, BlockModulesInFlattenTuples>} BlockModulesMap */
64
+ /** @typedef {Map<Chunk, bigint>} MaskByChunk */
65
+ /** @typedef {Set<DependenciesBlock>} BlocksWithNestedBlocks */
66
+ /** @typedef {Map<AsyncDependenciesBlock, BlockChunkGroupConnection[]>} BlockConnections */
67
+ /** @typedef {Map<ChunkGroup, ChunkGroupInfo>} ChunkGroupInfoMap */
68
+ /** @typedef {Set<ChunkGroup>} AllCreatedChunkGroups */
69
+ /** @typedef {Map<Entrypoint, Module[]>} InputEntrypointsAndModules */
70
+
71
+ const ZERO_BIGINT = BigInt(0);
72
+ const ONE_BIGINT = BigInt(1);
66
73
 
67
74
  /**
68
- * @param {ModuleSetPlus} a first set
69
- * @param {ModuleSetPlus} b second set
70
- * @returns {number} cmp
75
+ * @param {bigint} mask The mask to test
76
+ * @param {number} ordinal The ordinal of the bit to test
77
+ * @returns {boolean} If the ordinal-th bit is set in the mask
71
78
  */
72
- const bySetSize = (a, b) => {
73
- return b.size + b.plus.size - a.size - a.plus.size;
74
- };
79
+ const isOrdinalSetInMask = (mask, ordinal) =>
80
+ BigInt.asUintN(1, mask >> BigInt(ordinal)) !== ZERO_BIGINT;
75
81
 
76
82
  /**
77
83
  * @param {ModuleGraphConnection[]} connections list of connections
@@ -92,15 +98,26 @@ const getActiveStateOfConnections = (connections, runtime) => {
92
98
  return merged;
93
99
  };
94
100
 
101
+ /**
102
+ * @param {Module} module module
103
+ * @param {ModuleGraph} moduleGraph module graph
104
+ * @param {RuntimeSpec} runtime runtime
105
+ * @param {BlockModulesMap} blockModulesMap block modules map
106
+ */
95
107
  const extractBlockModules = (module, moduleGraph, runtime, blockModulesMap) => {
108
+ /** @type {DependenciesBlock | undefined} */
96
109
  let blockCache;
110
+ /** @type {BlockModulesInTuples | undefined} */
97
111
  let modules;
98
112
 
113
+ /** @type {BlockModulesInTuples[]} */
99
114
  const arrays = [];
100
115
 
116
+ /** @type {DependenciesBlock[]} */
101
117
  const queue = [module];
102
118
  while (queue.length > 0) {
103
- const block = queue.pop();
119
+ const block = /** @type {DependenciesBlock} */ (queue.pop());
120
+ /** @type {Module[]} */
104
121
  const arr = [];
105
122
  arrays.push(arr);
106
123
  blockModulesMap.set(block, arr);
@@ -124,17 +141,26 @@ const extractBlockModules = (module, moduleGraph, runtime, blockModulesMap) => {
124
141
 
125
142
  // deprecated fallback
126
143
  if (index < 0) {
127
- index = block.dependencies.indexOf(d);
144
+ index = /** @type {DependenciesBlock} */ (block).dependencies.indexOf(d);
128
145
  }
129
146
 
130
147
  if (blockCache !== block) {
131
- modules = blockModulesMap.get((blockCache = block));
148
+ modules =
149
+ /** @type {BlockModulesInTuples} */
150
+ (
151
+ blockModulesMap.get(
152
+ (blockCache = /** @type {DependenciesBlock} */ (block))
153
+ )
154
+ );
132
155
  }
133
156
 
134
157
  const i = index * 3;
135
- modules[i] = m;
136
- modules[i + 1] = connection.getActiveState(runtime);
137
- modules[i + 2] = connection;
158
+ /** @type {BlockModulesInTuples} */
159
+ (modules)[i] = m;
160
+ /** @type {BlockModulesInTuples} */
161
+ (modules)[i + 1] = connection.getActiveState(runtime);
162
+ /** @type {BlockModulesInTuples} */
163
+ (modules)[i + 2] = connection;
138
164
  }
139
165
 
140
166
  for (const modules of arrays) {
@@ -144,14 +170,15 @@ const extractBlockModules = (module, moduleGraph, runtime, blockModulesMap) => {
144
170
  outer: for (let j = 0; j < modules.length; j += 3) {
145
171
  const m = modules[j];
146
172
  if (m === undefined) continue;
147
- const state = modules[j + 1];
148
- const connection = modules[j + 2];
173
+ const state = /** @type {ConnectionState} */ (modules[j + 1]);
174
+ const connection = /** @type {ModuleGraphConnection} */ (modules[j + 2]);
149
175
  if (indexMap === undefined) {
150
176
  let i = 0;
151
177
  for (; i < length; i += 3) {
152
178
  if (modules[i] === m) {
153
- const merged = modules[i + 1];
154
- modules[i + 2].push(connection);
179
+ const merged = /** @type {ConnectionState} */ (modules[i + 1]);
180
+ /** @type {ModuleGraphConnection[]} */
181
+ (/** @type {unknown} */ (modules[i + 2])).push(connection);
155
182
  if (merged === true) continue outer;
156
183
  modules[i + 1] = ModuleGraphConnection.addConnectionStates(
157
184
  merged,
@@ -164,7 +191,8 @@ const extractBlockModules = (module, moduleGraph, runtime, blockModulesMap) => {
164
191
  length++;
165
192
  modules[length] = state;
166
193
  length++;
167
- modules[length] = [connection];
194
+ /** @type {ModuleGraphConnection[]} */
195
+ (/** @type {unknown} */ (modules[length])) = [connection];
168
196
  length++;
169
197
  if (length > 30) {
170
198
  // To avoid worse case performance, we will use an index map for
@@ -178,8 +206,9 @@ const extractBlockModules = (module, moduleGraph, runtime, blockModulesMap) => {
178
206
  } else {
179
207
  const idx = indexMap.get(m);
180
208
  if (idx !== undefined) {
181
- const merged = modules[idx];
182
- modules[idx + 1].push(connection);
209
+ const merged = /** @type {ConnectionState} */ (modules[idx]);
210
+ /** @type {ModuleGraphConnection[]} */
211
+ (/** @type {unknown} */ (modules[idx + 1])).push(connection);
183
212
  if (merged === true) continue outer;
184
213
  modules[idx] = ModuleGraphConnection.addConnectionStates(
185
214
  merged,
@@ -191,7 +220,11 @@ const extractBlockModules = (module, moduleGraph, runtime, blockModulesMap) => {
191
220
  modules[length] = state;
192
221
  indexMap.set(m, length);
193
222
  length++;
194
- modules[length] = [connection];
223
+ /** @type {ModuleGraphConnection[]} */
224
+ (
225
+ /** @type {unknown} */
226
+ (modules[length])
227
+ ) = [connection];
195
228
  length++;
196
229
  }
197
230
  }
@@ -204,11 +237,12 @@ const extractBlockModules = (module, moduleGraph, runtime, blockModulesMap) => {
204
237
  *
205
238
  * @param {Logger} logger a logger
206
239
  * @param {Compilation} compilation the compilation
207
- * @param {Map<Entrypoint, Module[]>} inputEntrypointsAndModules chunk groups which are processed with the modules
208
- * @param {Map<ChunkGroup, ChunkGroupInfo>} chunkGroupInfoMap mapping from chunk group to available modules
209
- * @param {Map<AsyncDependenciesBlock, BlockChunkGroupConnection[]>} blockConnections connection for blocks
210
- * @param {Set<DependenciesBlock>} blocksWithNestedBlocks flag for blocks that have nested blocks
211
- * @param {Set<ChunkGroup>} allCreatedChunkGroups filled with all chunk groups that are created here
240
+ * @param {InputEntrypointsAndModules} inputEntrypointsAndModules chunk groups which are processed with the modules
241
+ * @param {ChunkGroupInfoMap} chunkGroupInfoMap mapping from chunk group to available modules
242
+ * @param {BlockConnections} blockConnections connection for blocks
243
+ * @param {BlocksWithNestedBlocks} blocksWithNestedBlocks flag for blocks that have nested blocks
244
+ * @param {AllCreatedChunkGroups} allCreatedChunkGroups filled with all chunk groups that are created here
245
+ * @param {MaskByChunk} maskByChunk module content mask by chunk
212
246
  */
213
247
  const visitModules = (
214
248
  logger,
@@ -217,30 +251,51 @@ const visitModules = (
217
251
  chunkGroupInfoMap,
218
252
  blockConnections,
219
253
  blocksWithNestedBlocks,
220
- allCreatedChunkGroups
254
+ allCreatedChunkGroups,
255
+ maskByChunk
221
256
  ) => {
222
257
  const { moduleGraph, chunkGraph, moduleMemCaches } = compilation;
223
258
 
224
259
  const blockModulesRuntimeMap = new Map();
225
260
 
226
- /** @type {RuntimeSpec | false} */
227
- let blockModulesMapRuntime = false;
228
- /** @type {Map<DependenciesBlock, (Module | ConnectionState)[]>} */
261
+ /** @type {BlockModulesMap | undefined} */
229
262
  let blockModulesMap;
230
263
 
264
+ /** @type {Map<Module, number>} */
265
+ const ordinalByModule = new Map();
266
+
267
+ /**
268
+ * @param {Module} module The module to look up
269
+ * @returns {number} The ordinal of the module in masks
270
+ */
271
+ const getModuleOrdinal = module => {
272
+ let ordinal = ordinalByModule.get(module);
273
+ if (ordinal === undefined) {
274
+ ordinal = ordinalByModule.size;
275
+ ordinalByModule.set(module, ordinal);
276
+ }
277
+ return ordinal;
278
+ };
279
+
280
+ for (const chunk of compilation.chunks) {
281
+ let mask = ZERO_BIGINT;
282
+ for (const m of chunkGraph.getChunkModulesIterable(chunk)) {
283
+ mask |= ONE_BIGINT << BigInt(getModuleOrdinal(m));
284
+ }
285
+ maskByChunk.set(chunk, mask);
286
+ }
287
+
231
288
  /**
232
289
  *
233
290
  * @param {DependenciesBlock} block block
234
291
  * @param {RuntimeSpec} runtime runtime
235
- * @returns {(Module | ConnectionState | ModuleGraphConnection[])[]} block modules in flatten tuples
292
+ * @returns {BlockModulesInFlattenTuples} block modules in flatten tuples
236
293
  */
237
294
  const getBlockModules = (block, runtime) => {
238
- if (blockModulesMapRuntime !== runtime) {
239
- blockModulesMap = blockModulesRuntimeMap.get(runtime);
240
- if (blockModulesMap === undefined) {
241
- blockModulesMap = new Map();
242
- blockModulesRuntimeMap.set(runtime, blockModulesMap);
243
- }
295
+ blockModulesMap = blockModulesRuntimeMap.get(runtime);
296
+ if (blockModulesMap === undefined) {
297
+ blockModulesMap = new Map();
298
+ blockModulesRuntimeMap.set(runtime, blockModulesMap);
244
299
  }
245
300
  let blockModules = blockModulesMap.get(block);
246
301
  if (blockModules !== undefined) return blockModules;
@@ -264,9 +319,11 @@ const visitModules = (
264
319
  } else {
265
320
  logger.time("visitModules: prepare");
266
321
  extractBlockModules(module, moduleGraph, runtime, blockModulesMap);
267
- blockModules = blockModulesMap.get(block);
322
+ blockModules =
323
+ /** @type {BlockModulesInFlattenTuples} */
324
+ (blockModulesMap.get(block));
268
325
  logger.timeAggregate("visitModules: prepare");
269
- return /** @type {(Module | ConnectionState)[]} */ (blockModules);
326
+ return blockModules;
270
327
  }
271
328
  };
272
329
 
@@ -331,7 +388,6 @@ const visitModules = (
331
388
  chunkGroup,
332
389
  runtime,
333
390
  minAvailableModules: undefined,
334
- minAvailableModulesOwned: false,
335
391
  availableModulesToBeMerged: [],
336
392
  skippedItems: undefined,
337
393
  resultingAvailableModules: undefined,
@@ -354,15 +410,12 @@ const visitModules = (
354
410
  // minAvailableModules for child entrypoints are unknown yet, set to undefined.
355
411
  // This means no module is added until other sets are merged into
356
412
  // this minAvailableModules (by the parent entrypoints)
357
- const skippedItems = new Set();
358
- for (const module of modules) {
359
- skippedItems.add(module);
360
- }
413
+ const skippedItems = new Set(modules);
361
414
  chunkGroupInfo.skippedItems = skippedItems;
362
415
  chunkGroupsForCombining.add(chunkGroupInfo);
363
416
  } else {
364
417
  // The application may start here: We start with an empty list of available modules
365
- chunkGroupInfo.minAvailableModules = EMPTY_SET;
418
+ chunkGroupInfo.minAvailableModules = ZERO_BIGINT;
366
419
  const chunk = chunkGroup.getEntrypointChunk();
367
420
  for (const module of modules) {
368
421
  queue.push({
@@ -433,6 +486,7 @@ const visitModules = (
433
486
  const iteratorBlock = b => {
434
487
  // 1. We create a chunk group with single chunk in it for this Block
435
488
  // but only once (blockChunkGroups map)
489
+ /** @type {ChunkGroupInfo | undefined} */
436
490
  let cgi = blockChunkGroups.get(b);
437
491
  /** @type {ChunkGroup | undefined} */
438
492
  let c;
@@ -447,15 +501,15 @@ const visitModules = (
447
501
  entrypoint = compilation.addAsyncEntrypoint(
448
502
  entryOptions,
449
503
  module,
450
- b.loc,
451
- b.request
504
+ /** @type {DependencyLocation} */ (b.loc),
505
+ /** @type {string} */ (b.request)
452
506
  );
507
+ maskByChunk.set(entrypoint.chunks[0], ZERO_BIGINT);
453
508
  entrypoint.index = nextChunkGroupIndex++;
454
509
  cgi = {
455
510
  chunkGroup: entrypoint,
456
511
  runtime: entrypoint.options.runtime || entrypoint.name,
457
- minAvailableModules: EMPTY_SET,
458
- minAvailableModulesOwned: false,
512
+ minAvailableModules: ZERO_BIGINT,
459
513
  availableModulesToBeMerged: [],
460
514
  skippedItems: undefined,
461
515
  resultingAvailableModules: undefined,
@@ -482,7 +536,11 @@ const visitModules = (
482
536
  } else {
483
537
  entrypoint = /** @type {Entrypoint} */ (cgi.chunkGroup);
484
538
  // TODO merge entryOptions
485
- entrypoint.addOrigin(module, b.loc, b.request);
539
+ entrypoint.addOrigin(
540
+ module,
541
+ /** @type {DependencyLocation} */ (b.loc),
542
+ /** @type {string} */ (b.request)
543
+ );
486
544
  chunkGraph.connectBlockAndChunkGroup(b, entrypoint);
487
545
  }
488
546
 
@@ -490,7 +548,7 @@ const visitModules = (
490
548
  queueDelayed.push({
491
549
  action: PROCESS_ENTRY_BLOCK,
492
550
  block: b,
493
- module: module,
551
+ module,
494
552
  chunk: entrypoint.chunks[0],
495
553
  chunkGroup: entrypoint,
496
554
  chunkGroupInfo: cgi
@@ -500,26 +558,26 @@ const visitModules = (
500
558
  queue.push({
501
559
  action: PROCESS_BLOCK,
502
560
  block: b,
503
- module: module,
561
+ module,
504
562
  chunk,
505
563
  chunkGroup,
506
564
  chunkGroupInfo
507
565
  });
508
566
  } else {
509
- cgi = chunkName && namedChunkGroups.get(chunkName);
567
+ cgi = chunkName ? namedChunkGroups.get(chunkName) : undefined;
510
568
  if (!cgi) {
511
569
  c = compilation.addChunkInGroup(
512
570
  b.groupOptions || b.chunkName,
513
571
  module,
514
- b.loc,
515
- b.request
572
+ /** @type {DependencyLocation} */ (b.loc),
573
+ /** @type {string} */ (b.request)
516
574
  );
575
+ maskByChunk.set(c.chunks[0], ZERO_BIGINT);
517
576
  c.index = nextChunkGroupIndex++;
518
577
  cgi = {
519
578
  chunkGroup: c,
520
579
  runtime: chunkGroupInfo.runtime,
521
580
  minAvailableModules: undefined,
522
- minAvailableModulesOwned: undefined,
523
581
  availableModulesToBeMerged: [],
524
582
  skippedItems: undefined,
525
583
  resultingAvailableModules: undefined,
@@ -543,19 +601,23 @@ const visitModules = (
543
601
  new AsyncDependencyToInitialChunkError(
544
602
  /** @type {string} */ (chunkName),
545
603
  module,
546
- b.loc
604
+ /** @type {DependencyLocation} */ (b.loc)
547
605
  )
548
606
  );
549
607
  c = chunkGroup;
550
608
  } else {
551
609
  c.addOptions(b.groupOptions);
552
610
  }
553
- c.addOrigin(module, b.loc, b.request);
611
+ c.addOrigin(
612
+ module,
613
+ /** @type {DependencyLocation} */ (b.loc),
614
+ /** @type {string} */ (b.request)
615
+ );
554
616
  }
555
617
  blockConnections.set(b, []);
556
618
  }
557
619
  blockChunkGroups.set(b, /** @type {ChunkGroupInfo} */ (cgi));
558
- blockByChunkGroups.set(cgi, b);
620
+ blockByChunkGroups.set(/** @type {ChunkGroupInfo} */ (cgi), b);
559
621
  } else if (entryOptions) {
560
622
  entrypoint = /** @type {Entrypoint} */ (cgi.chunkGroup);
561
623
  } else {
@@ -565,7 +627,8 @@ const visitModules = (
565
627
  if (c !== undefined) {
566
628
  // 2. We store the connection for the block
567
629
  // to connect it later if needed
568
- blockConnections.get(b).push({
630
+ /** @type {BlockChunkGroupConnection[]} */
631
+ (blockConnections.get(b)).push({
569
632
  originChunkGroupInfo: chunkGroupInfo,
570
633
  chunkGroup: c
571
634
  });
@@ -584,7 +647,7 @@ const visitModules = (
584
647
  queueDelayed.push({
585
648
  action: PROCESS_BLOCK,
586
649
  block: b,
587
- module: module,
650
+ module,
588
651
  chunk: c.chunks[0],
589
652
  chunkGroup: c,
590
653
  chunkGroupInfo: /** @type {ChunkGroupInfo} */ (cgi)
@@ -604,15 +667,22 @@ const visitModules = (
604
667
  const blockModules = getBlockModules(block, chunkGroupInfo.runtime);
605
668
 
606
669
  if (blockModules !== undefined) {
607
- const { minAvailableModules } = chunkGroupInfo;
670
+ const minAvailableModules =
671
+ /** @type {bigint} */
672
+ (chunkGroupInfo.minAvailableModules);
608
673
  // Buffer items because order need to be reversed to get indices correct
609
674
  // Traverse all referenced modules
610
- for (let i = 0; i < blockModules.length; i += 3) {
675
+ for (let i = 0, len = blockModules.length; i < len; i += 3) {
611
676
  const refModule = /** @type {Module} */ (blockModules[i]);
612
- if (chunkGraph.isModuleInChunk(refModule, chunk)) {
677
+ // For single comparisons this might be cheaper
678
+ const isModuleInChunk = chunkGraph.isModuleInChunk(refModule, chunk);
679
+
680
+ if (isModuleInChunk) {
613
681
  // skip early if already connected
614
682
  continue;
615
683
  }
684
+
685
+ const refOrdinal = /** @type {number} */ getModuleOrdinal(refModule);
616
686
  const activeState = /** @type {ConnectionState} */ (
617
687
  blockModules[i + 1]
618
688
  );
@@ -623,12 +693,7 @@ const visitModules = (
623
693
  skipConnectionBuffer.push([refModule, connections]);
624
694
  // We skip inactive connections
625
695
  if (activeState === false) continue;
626
- }
627
- if (
628
- activeState === true &&
629
- (minAvailableModules.has(refModule) ||
630
- minAvailableModules.plus.has(refModule))
631
- ) {
696
+ } else if (isOrdinalSetInMask(minAvailableModules, refOrdinal)) {
632
697
  // already in parent chunks, skip it for now
633
698
  skipBuffer.push(refModule);
634
699
  continue;
@@ -694,15 +759,15 @@ const visitModules = (
694
759
  const blockModules = getBlockModules(block, chunkGroupInfo.runtime);
695
760
 
696
761
  if (blockModules !== undefined) {
697
- // Traverse all referenced modules
698
- for (let i = 0; i < blockModules.length; i += 3) {
762
+ // Traverse all referenced modules in reverse order
763
+ for (let i = blockModules.length - 3; i >= 0; i -= 3) {
699
764
  const refModule = /** @type {Module} */ (blockModules[i]);
700
765
  const activeState = /** @type {ConnectionState} */ (
701
766
  blockModules[i + 1]
702
767
  );
703
768
  // enqueue, then add and enter to be in the correct order
704
769
  // this is relevant with circular dependencies
705
- queueBuffer.push({
770
+ queue.push({
706
771
  action:
707
772
  activeState === true ? ADD_AND_ENTER_ENTRY_MODULE : PROCESS_BLOCK,
708
773
  block: refModule,
@@ -712,13 +777,6 @@ const visitModules = (
712
777
  chunkGroupInfo
713
778
  });
714
779
  }
715
- // Add buffered items in reverse order
716
- if (queueBuffer.length > 0) {
717
- for (let i = queueBuffer.length - 1; i >= 0; i--) {
718
- queue.push(queueBuffer[i]);
719
- }
720
- queueBuffer.length = 0;
721
- }
722
780
  }
723
781
 
724
782
  // Traverse all Blocks
@@ -750,12 +808,18 @@ const visitModules = (
750
808
  );
751
809
  // fallthrough
752
810
  case ADD_AND_ENTER_MODULE: {
753
- if (chunkGraph.isModuleInChunk(module, chunk)) {
811
+ const isModuleInChunk = chunkGraph.isModuleInChunk(module, chunk);
812
+
813
+ if (isModuleInChunk) {
754
814
  // already connected, skip it
755
815
  break;
756
816
  }
757
817
  // We connect Module and Chunk
758
818
  chunkGraph.connectChunkAndModule(chunk, module);
819
+ const moduleOrdinal = getModuleOrdinal(module);
820
+ let chunkMask = /** @type {bigint} */ (maskByChunk.get(chunk));
821
+ chunkMask |= ONE_BIGINT << BigInt(moduleOrdinal);
822
+ maskByChunk.set(chunk, chunkMask);
759
823
  }
760
824
  // fallthrough
761
825
  case ENTER_MODULE: {
@@ -812,44 +876,24 @@ const visitModules = (
812
876
  }
813
877
  };
814
878
 
879
+ /**
880
+ * @param {ChunkGroupInfo} chunkGroupInfo The info object for the chunk group
881
+ * @returns {bigint} The mask of available modules after the chunk group
882
+ */
815
883
  const calculateResultingAvailableModules = chunkGroupInfo => {
816
- if (chunkGroupInfo.resultingAvailableModules)
884
+ if (chunkGroupInfo.resultingAvailableModules !== undefined)
817
885
  return chunkGroupInfo.resultingAvailableModules;
818
886
 
819
- const minAvailableModules = chunkGroupInfo.minAvailableModules;
820
-
821
- // Create a new Set of available modules at this point
822
- // We want to be as lazy as possible. There are multiple ways doing this:
823
- // Note that resultingAvailableModules is stored as "(a) + (b)" as it's a ModuleSetPlus
824
- // - resultingAvailableModules = (modules of chunk) + (minAvailableModules + minAvailableModules.plus)
825
- // - resultingAvailableModules = (minAvailableModules + modules of chunk) + (minAvailableModules.plus)
826
- // We choose one depending on the size of minAvailableModules vs minAvailableModules.plus
827
-
828
- let resultingAvailableModules;
829
- if (minAvailableModules.size > minAvailableModules.plus.size) {
830
- // resultingAvailableModules = (modules of chunk) + (minAvailableModules + minAvailableModules.plus)
831
- resultingAvailableModules =
832
- /** @type {Set<Module> & {plus: Set<Module>}} */ (new Set());
833
- for (const module of minAvailableModules.plus)
834
- minAvailableModules.add(module);
835
- minAvailableModules.plus = EMPTY_SET;
836
- resultingAvailableModules.plus = minAvailableModules;
837
- chunkGroupInfo.minAvailableModulesOwned = false;
838
- } else {
839
- // resultingAvailableModules = (minAvailableModules + modules of chunk) + (minAvailableModules.plus)
840
- resultingAvailableModules =
841
- /** @type {Set<Module> & {plus: Set<Module>}} */ (
842
- new Set(minAvailableModules)
843
- );
844
- resultingAvailableModules.plus = minAvailableModules.plus;
845
- }
887
+ let resultingAvailableModules = /** @type {bigint} */ (
888
+ chunkGroupInfo.minAvailableModules
889
+ );
846
890
 
847
891
  // add the modules from the chunk group to the set
848
892
  for (const chunk of chunkGroupInfo.chunkGroup.chunks) {
849
- for (const m of chunkGraph.getChunkModulesIterable(chunk)) {
850
- resultingAvailableModules.add(m);
851
- }
893
+ const mask = /** @type {bigint} */ (maskByChunk.get(chunk));
894
+ resultingAvailableModules |= mask;
852
895
  }
896
+
853
897
  return (chunkGroupInfo.resultingAvailableModules =
854
898
  resultingAvailableModules);
855
899
  };
@@ -896,232 +940,24 @@ const visitModules = (
896
940
  // Execute the merge
897
941
  for (const info of chunkGroupsForMerging) {
898
942
  const availableModulesToBeMerged = info.availableModulesToBeMerged;
899
- let cachedMinAvailableModules = info.minAvailableModules;
943
+ const cachedMinAvailableModules = info.minAvailableModules;
944
+ let minAvailableModules = cachedMinAvailableModules;
900
945
 
901
946
  statMergedAvailableModuleSets += availableModulesToBeMerged.length;
902
947
 
903
- // 1. Get minimal available modules
904
- // It doesn't make sense to traverse a chunk again with more available modules.
905
- // This step calculates the minimal available modules and skips traversal when
906
- // the list didn't shrink.
907
- if (availableModulesToBeMerged.length > 1) {
908
- availableModulesToBeMerged.sort(bySetSize);
909
- }
910
- let changed = false;
911
- merge: for (const availableModules of availableModulesToBeMerged) {
912
- if (cachedMinAvailableModules === undefined) {
913
- cachedMinAvailableModules = availableModules;
914
- info.minAvailableModules = cachedMinAvailableModules;
915
- info.minAvailableModulesOwned = false;
916
- changed = true;
948
+ for (const availableModules of availableModulesToBeMerged) {
949
+ if (minAvailableModules === undefined) {
950
+ minAvailableModules = availableModules;
917
951
  } else {
918
- if (info.minAvailableModulesOwned) {
919
- // We own it and can modify it
920
- if (cachedMinAvailableModules.plus === availableModules.plus) {
921
- for (const m of cachedMinAvailableModules) {
922
- if (!availableModules.has(m)) {
923
- cachedMinAvailableModules.delete(m);
924
- changed = true;
925
- }
926
- }
927
- } else {
928
- for (const m of cachedMinAvailableModules) {
929
- if (!availableModules.has(m) && !availableModules.plus.has(m)) {
930
- cachedMinAvailableModules.delete(m);
931
- changed = true;
932
- }
933
- }
934
- for (const m of cachedMinAvailableModules.plus) {
935
- if (!availableModules.has(m) && !availableModules.plus.has(m)) {
936
- // We can't remove modules from the plus part
937
- // so we need to merge plus into the normal part to allow modifying it
938
- const iterator =
939
- cachedMinAvailableModules.plus[Symbol.iterator]();
940
- // fast forward add all modules until m
941
- /** @type {IteratorResult<Module>} */
942
- let it;
943
- while (!(it = iterator.next()).done) {
944
- const module = it.value;
945
- if (module === m) break;
946
- cachedMinAvailableModules.add(module);
947
- }
948
- // check the remaining modules before adding
949
- while (!(it = iterator.next()).done) {
950
- const module = it.value;
951
- if (
952
- availableModules.has(module) ||
953
- availableModules.plus.has(module)
954
- ) {
955
- cachedMinAvailableModules.add(module);
956
- }
957
- }
958
- cachedMinAvailableModules.plus = EMPTY_SET;
959
- changed = true;
960
- continue merge;
961
- }
962
- }
963
- }
964
- } else if (cachedMinAvailableModules.plus === availableModules.plus) {
965
- // Common and fast case when the plus part is shared
966
- // We only need to care about the normal part
967
- if (availableModules.size < cachedMinAvailableModules.size) {
968
- // the new availableModules is smaller so it's faster to
969
- // fork from the new availableModules
970
- statForkedAvailableModules++;
971
- statForkedAvailableModulesCount += availableModules.size;
972
- statForkedMergedModulesCount += cachedMinAvailableModules.size;
973
- // construct a new Set as intersection of cachedMinAvailableModules and availableModules
974
- const newSet = /** @type {ModuleSetPlus} */ (new Set());
975
- newSet.plus = availableModules.plus;
976
- for (const m of availableModules) {
977
- if (cachedMinAvailableModules.has(m)) {
978
- newSet.add(m);
979
- }
980
- }
981
- statForkedResultModulesCount += newSet.size;
982
- cachedMinAvailableModules = newSet;
983
- info.minAvailableModulesOwned = true;
984
- info.minAvailableModules = newSet;
985
- changed = true;
986
- continue merge;
987
- }
988
- for (const m of cachedMinAvailableModules) {
989
- if (!availableModules.has(m)) {
990
- // cachedMinAvailableModules need to be modified
991
- // but we don't own it
992
- statForkedAvailableModules++;
993
- statForkedAvailableModulesCount +=
994
- cachedMinAvailableModules.size;
995
- statForkedMergedModulesCount += availableModules.size;
996
- // construct a new Set as intersection of cachedMinAvailableModules and availableModules
997
- // as the plus part is equal we can just take over this one
998
- const newSet = /** @type {ModuleSetPlus} */ (new Set());
999
- newSet.plus = availableModules.plus;
1000
- const iterator = cachedMinAvailableModules[Symbol.iterator]();
1001
- // fast forward add all modules until m
1002
- /** @type {IteratorResult<Module>} */
1003
- let it;
1004
- while (!(it = iterator.next()).done) {
1005
- const module = it.value;
1006
- if (module === m) break;
1007
- newSet.add(module);
1008
- }
1009
- // check the remaining modules before adding
1010
- while (!(it = iterator.next()).done) {
1011
- const module = it.value;
1012
- if (availableModules.has(module)) {
1013
- newSet.add(module);
1014
- }
1015
- }
1016
- statForkedResultModulesCount += newSet.size;
1017
- cachedMinAvailableModules = newSet;
1018
- info.minAvailableModulesOwned = true;
1019
- info.minAvailableModules = newSet;
1020
- changed = true;
1021
- continue merge;
1022
- }
1023
- }
1024
- } else {
1025
- for (const m of cachedMinAvailableModules) {
1026
- if (!availableModules.has(m) && !availableModules.plus.has(m)) {
1027
- // cachedMinAvailableModules need to be modified
1028
- // but we don't own it
1029
- statForkedAvailableModules++;
1030
- statForkedAvailableModulesCount +=
1031
- cachedMinAvailableModules.size;
1032
- statForkedAvailableModulesCountPlus +=
1033
- cachedMinAvailableModules.plus.size;
1034
- statForkedMergedModulesCount += availableModules.size;
1035
- statForkedMergedModulesCountPlus += availableModules.plus.size;
1036
- // construct a new Set as intersection of cachedMinAvailableModules and availableModules
1037
- const newSet = /** @type {ModuleSetPlus} */ (new Set());
1038
- newSet.plus = EMPTY_SET;
1039
- const iterator = cachedMinAvailableModules[Symbol.iterator]();
1040
- // fast forward add all modules until m
1041
- /** @type {IteratorResult<Module>} */
1042
- let it;
1043
- while (!(it = iterator.next()).done) {
1044
- const module = it.value;
1045
- if (module === m) break;
1046
- newSet.add(module);
1047
- }
1048
- // check the remaining modules before adding
1049
- while (!(it = iterator.next()).done) {
1050
- const module = it.value;
1051
- if (
1052
- availableModules.has(module) ||
1053
- availableModules.plus.has(module)
1054
- ) {
1055
- newSet.add(module);
1056
- }
1057
- }
1058
- // also check all modules in cachedMinAvailableModules.plus
1059
- for (const module of cachedMinAvailableModules.plus) {
1060
- if (
1061
- availableModules.has(module) ||
1062
- availableModules.plus.has(module)
1063
- ) {
1064
- newSet.add(module);
1065
- }
1066
- }
1067
- statForkedResultModulesCount += newSet.size;
1068
- cachedMinAvailableModules = newSet;
1069
- info.minAvailableModulesOwned = true;
1070
- info.minAvailableModules = newSet;
1071
- changed = true;
1072
- continue merge;
1073
- }
1074
- }
1075
- for (const m of cachedMinAvailableModules.plus) {
1076
- if (!availableModules.has(m) && !availableModules.plus.has(m)) {
1077
- // cachedMinAvailableModules need to be modified
1078
- // but we don't own it
1079
- statForkedAvailableModules++;
1080
- statForkedAvailableModulesCount +=
1081
- cachedMinAvailableModules.size;
1082
- statForkedAvailableModulesCountPlus +=
1083
- cachedMinAvailableModules.plus.size;
1084
- statForkedMergedModulesCount += availableModules.size;
1085
- statForkedMergedModulesCountPlus += availableModules.plus.size;
1086
- // construct a new Set as intersection of cachedMinAvailableModules and availableModules
1087
- // we already know that all modules directly from cachedMinAvailableModules are in availableModules too
1088
- const newSet = /** @type {ModuleSetPlus} */ (
1089
- new Set(cachedMinAvailableModules)
1090
- );
1091
- newSet.plus = EMPTY_SET;
1092
- const iterator =
1093
- cachedMinAvailableModules.plus[Symbol.iterator]();
1094
- // fast forward add all modules until m
1095
- /** @type {IteratorResult<Module>} */
1096
- let it;
1097
- while (!(it = iterator.next()).done) {
1098
- const module = it.value;
1099
- if (module === m) break;
1100
- newSet.add(module);
1101
- }
1102
- // check the remaining modules before adding
1103
- while (!(it = iterator.next()).done) {
1104
- const module = it.value;
1105
- if (
1106
- availableModules.has(module) ||
1107
- availableModules.plus.has(module)
1108
- ) {
1109
- newSet.add(module);
1110
- }
1111
- }
1112
- statForkedResultModulesCount += newSet.size;
1113
- cachedMinAvailableModules = newSet;
1114
- info.minAvailableModulesOwned = true;
1115
- info.minAvailableModules = newSet;
1116
- changed = true;
1117
- continue merge;
1118
- }
1119
- }
1120
- }
952
+ minAvailableModules &= availableModules;
1121
953
  }
1122
954
  }
955
+
956
+ const changed = minAvailableModules !== cachedMinAvailableModules;
957
+
1123
958
  availableModulesToBeMerged.length = 0;
1124
959
  if (changed) {
960
+ info.minAvailableModules = minAvailableModules;
1125
961
  info.resultingAvailableModules = undefined;
1126
962
  outdatedChunkGroupInfo.add(info);
1127
963
  }
@@ -1134,34 +970,24 @@ const visitModules = (
1134
970
  for (const source of /** @type {Set<ChunkGroupInfo>} */ (
1135
971
  info.availableSources
1136
972
  )) {
1137
- if (!source.minAvailableModules) {
973
+ if (source.minAvailableModules === undefined) {
1138
974
  chunkGroupsForCombining.delete(info);
1139
975
  break;
1140
976
  }
1141
977
  }
1142
978
  }
979
+
1143
980
  for (const info of chunkGroupsForCombining) {
1144
- const availableModules = /** @type {ModuleSetPlus} */ (new Set());
1145
- availableModules.plus = EMPTY_SET;
1146
- const mergeSet = set => {
1147
- if (set.size > availableModules.plus.size) {
1148
- for (const item of availableModules.plus) availableModules.add(item);
1149
- availableModules.plus = set;
1150
- } else {
1151
- for (const item of set) availableModules.add(item);
1152
- }
1153
- };
981
+ let availableModules = ZERO_BIGINT;
1154
982
  // combine minAvailableModules from all resultingAvailableModules
1155
983
  for (const source of /** @type {Set<ChunkGroupInfo>} */ (
1156
984
  info.availableSources
1157
985
  )) {
1158
986
  const resultingAvailableModules =
1159
987
  calculateResultingAvailableModules(source);
1160
- mergeSet(resultingAvailableModules);
1161
- mergeSet(resultingAvailableModules.plus);
988
+ availableModules |= resultingAvailableModules;
1162
989
  }
1163
990
  info.minAvailableModules = availableModules;
1164
- info.minAvailableModulesOwned = false;
1165
991
  info.resultingAvailableModules = undefined;
1166
992
  outdatedChunkGroupInfo.add(info);
1167
993
  }
@@ -1175,13 +1001,11 @@ const visitModules = (
1175
1001
  // 1. Reconsider skipped items
1176
1002
  if (info.skippedItems !== undefined) {
1177
1003
  const minAvailableModules =
1178
- /** @type {ModuleSetPlus} */
1004
+ /** @type {bigint} */
1179
1005
  (info.minAvailableModules);
1180
1006
  for (const module of info.skippedItems) {
1181
- if (
1182
- !minAvailableModules.has(module) &&
1183
- !minAvailableModules.plus.has(module)
1184
- ) {
1007
+ const ordinal = getModuleOrdinal(module);
1008
+ if (!isOrdinalSetInMask(minAvailableModules, ordinal)) {
1185
1009
  queue.push({
1186
1010
  action: ADD_AND_ENTER_MODULE,
1187
1011
  block: module,
@@ -1198,7 +1022,7 @@ const visitModules = (
1198
1022
  // 2. Reconsider skipped connections
1199
1023
  if (info.skippedModuleConnections !== undefined) {
1200
1024
  const minAvailableModules =
1201
- /** @type {ModuleSetPlus} */
1025
+ /** @type {bigint} */
1202
1026
  (info.minAvailableModules);
1203
1027
  for (const entry of info.skippedModuleConnections) {
1204
1028
  const [module, connections] = entry;
@@ -1208,15 +1032,13 @@ const visitModules = (
1208
1032
  );
1209
1033
  if (activeState === false) continue;
1210
1034
  if (activeState === true) {
1035
+ const ordinal = getModuleOrdinal(module);
1211
1036
  info.skippedModuleConnections.delete(entry);
1212
- }
1213
- if (
1214
- activeState === true &&
1215
- (minAvailableModules.has(module) ||
1216
- minAvailableModules.plus.has(module))
1217
- ) {
1218
- info.skippedItems.add(module);
1219
- continue;
1037
+ if (isOrdinalSetInMask(minAvailableModules, ordinal)) {
1038
+ /** @type {NonNullable<ChunkGroupInfo["skippedItems"]>} */
1039
+ (info.skippedItems).add(module);
1040
+ continue;
1041
+ }
1220
1042
  }
1221
1043
  queue.push({
1222
1044
  action: activeState === true ? ADD_AND_ENTER_MODULE : PROCESS_BLOCK,
@@ -1307,26 +1129,29 @@ const visitModules = (
1307
1129
  let preOrderIndex = 0;
1308
1130
  let postOrderIndex = 0;
1309
1131
 
1310
- const process = (current, visited = new Set()) => {
1311
- if (visited.has(current)) {
1312
- return;
1313
- }
1314
-
1315
- visited.add(current);
1316
-
1132
+ /**
1133
+ * @param {DependenciesBlock} current current
1134
+ * @param {BlocksWithNestedBlocks} visited visited dependencies blocks
1135
+ */
1136
+ const process = (current, visited) => {
1317
1137
  const blockModules = getBlockModules(current, runtime);
1318
1138
  if (blockModules === undefined) {
1319
1139
  return;
1320
1140
  }
1321
1141
 
1322
- for (let i = 0; i < blockModules.length; i += 3) {
1323
- const refModule = /** @type {Module} */ (blockModules[i]);
1142
+ for (let i = 0, len = blockModules.length; i < len; i += 3) {
1324
1143
  const activeState = /** @type {ConnectionState} */ (
1325
1144
  blockModules[i + 1]
1326
1145
  );
1327
1146
  if (activeState === false) {
1328
1147
  continue;
1329
1148
  }
1149
+ const refModule = /** @type {Module} */ (blockModules[i]);
1150
+ if (visited.has(refModule)) {
1151
+ continue;
1152
+ }
1153
+
1154
+ visited.add(refModule);
1330
1155
 
1331
1156
  if (refModule) {
1332
1157
  chunkGroup.setModulePreOrderIndex(refModule, preOrderIndex++);
@@ -1336,9 +1161,10 @@ const visitModules = (
1336
1161
  }
1337
1162
  };
1338
1163
 
1339
- process(block);
1164
+ process(block, new Set());
1340
1165
  }
1341
1166
  outdatedOrderIndexChunkGroups.clear();
1167
+ ordinalByModule.clear();
1342
1168
 
1343
1169
  logger.log(
1344
1170
  `${statProcessedQueueItems} queue items processed (${statProcessedBlocks} blocks)`
@@ -1355,15 +1181,15 @@ const visitModules = (
1355
1181
  /**
1356
1182
  *
1357
1183
  * @param {Compilation} compilation the compilation
1358
- * @param {Set<DependenciesBlock>} blocksWithNestedBlocks flag for blocks that have nested blocks
1359
- * @param {Map<AsyncDependenciesBlock, BlockChunkGroupConnection[]>} blockConnections connection for blocks
1360
- * @param {Map<ChunkGroup, ChunkGroupInfo>} chunkGroupInfoMap mapping from chunk group to available modules
1184
+ * @param {BlocksWithNestedBlocks} blocksWithNestedBlocks flag for blocks that have nested blocks
1185
+ * @param {BlockConnections} blockConnections connection for blocks
1186
+ * @param {MaskByChunk} maskByChunk mapping from chunk to module mask
1361
1187
  */
1362
1188
  const connectChunkGroups = (
1363
1189
  compilation,
1364
1190
  blocksWithNestedBlocks,
1365
1191
  blockConnections,
1366
- chunkGroupInfoMap
1192
+ maskByChunk
1367
1193
  ) => {
1368
1194
  const { chunkGraph } = compilation;
1369
1195
 
@@ -1371,15 +1197,13 @@ const connectChunkGroups = (
1371
1197
  * Helper function to check if all modules of a chunk are available
1372
1198
  *
1373
1199
  * @param {ChunkGroup} chunkGroup the chunkGroup to scan
1374
- * @param {ModuleSetPlus} availableModules the comparator set
1200
+ * @param {bigint} availableModules the comparator set
1375
1201
  * @returns {boolean} return true if all modules of a chunk are available
1376
1202
  */
1377
1203
  const areModulesAvailable = (chunkGroup, availableModules) => {
1378
1204
  for (const chunk of chunkGroup.chunks) {
1379
- for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
1380
- if (!availableModules.has(module) && !availableModules.plus.has(module))
1381
- return false;
1382
- }
1205
+ const chunkMask = /** @type {bigint} */ (maskByChunk.get(chunk));
1206
+ if ((chunkMask & availableModules) !== chunkMask) return false;
1383
1207
  }
1384
1208
  return true;
1385
1209
  };
@@ -1398,7 +1222,7 @@ const connectChunkGroups = (
1398
1222
  connections.every(({ chunkGroup, originChunkGroupInfo }) =>
1399
1223
  areModulesAvailable(
1400
1224
  chunkGroup,
1401
- originChunkGroupInfo.resultingAvailableModules
1225
+ /** @type {bigint} */ (originChunkGroupInfo.resultingAvailableModules)
1402
1226
  )
1403
1227
  )
1404
1228
  ) {
@@ -1444,7 +1268,7 @@ const cleanupUnconnectedGroups = (compilation, allCreatedChunkGroups) => {
1444
1268
  /**
1445
1269
  * This method creates the Chunk graph from the Module graph
1446
1270
  * @param {Compilation} compilation the compilation
1447
- * @param {Map<Entrypoint, Module[]>} inputEntrypointsAndModules chunk groups which are processed with the modules
1271
+ * @param {InputEntrypointsAndModules} inputEntrypointsAndModules chunk groups which are processed with the modules
1448
1272
  * @returns {void}
1449
1273
  */
1450
1274
  const buildChunkGraph = (compilation, inputEntrypointsAndModules) => {
@@ -1452,18 +1276,21 @@ const buildChunkGraph = (compilation, inputEntrypointsAndModules) => {
1452
1276
 
1453
1277
  // SHARED STATE
1454
1278
 
1455
- /** @type {Map<AsyncDependenciesBlock, BlockChunkGroupConnection[]>} */
1279
+ /** @type {BlockConnections} */
1456
1280
  const blockConnections = new Map();
1457
1281
 
1458
- /** @type {Set<ChunkGroup>} */
1282
+ /** @type {AllCreatedChunkGroups} */
1459
1283
  const allCreatedChunkGroups = new Set();
1460
1284
 
1461
- /** @type {Map<ChunkGroup, ChunkGroupInfo>} */
1285
+ /** @type {ChunkGroupInfoMap} */
1462
1286
  const chunkGroupInfoMap = new Map();
1463
1287
 
1464
- /** @type {Set<DependenciesBlock>} */
1288
+ /** @type {BlocksWithNestedBlocks} */
1465
1289
  const blocksWithNestedBlocks = new Set();
1466
1290
 
1291
+ /** @type {MaskByChunk} */
1292
+ const maskByChunk = new Map();
1293
+
1467
1294
  // PART ONE
1468
1295
 
1469
1296
  logger.time("visitModules");
@@ -1474,7 +1301,8 @@ const buildChunkGraph = (compilation, inputEntrypointsAndModules) => {
1474
1301
  chunkGroupInfoMap,
1475
1302
  blockConnections,
1476
1303
  blocksWithNestedBlocks,
1477
- allCreatedChunkGroups
1304
+ allCreatedChunkGroups,
1305
+ maskByChunk
1478
1306
  );
1479
1307
  logger.timeEnd("visitModules");
1480
1308
 
@@ -1485,7 +1313,7 @@ const buildChunkGraph = (compilation, inputEntrypointsAndModules) => {
1485
1313
  compilation,
1486
1314
  blocksWithNestedBlocks,
1487
1315
  blockConnections,
1488
- chunkGroupInfoMap
1316
+ maskByChunk
1489
1317
  );
1490
1318
  logger.timeEnd("connectChunkGroups");
1491
1319