webpack 5.56.1 → 5.58.1

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.

@@ -33,8 +33,6 @@ class AsyncDependenciesBlock extends DependenciesBlock {
33
33
  this.groupOptions = groupOptions;
34
34
  this.loc = loc;
35
35
  this.request = request;
36
- /** @type {DependenciesBlock} */
37
- this.parent = undefined;
38
36
  this._stringifiedGroupOptions = undefined;
39
37
  }
40
38
 
@@ -66,9 +64,10 @@ class AsyncDependenciesBlock extends DependenciesBlock {
66
64
  if (this._stringifiedGroupOptions === undefined) {
67
65
  this._stringifiedGroupOptions = JSON.stringify(this.groupOptions);
68
66
  }
69
- hash.update(this._stringifiedGroupOptions);
70
67
  const chunkGroup = chunkGraph.getBlockChunkGroup(this);
71
- hash.update(chunkGroup ? chunkGroup.id : "");
68
+ hash.update(
69
+ `${this._stringifiedGroupOptions}${chunkGroup ? chunkGroup.id : ""}`
70
+ );
72
71
  super.updateHash(hash, context);
73
72
  }
74
73
 
package/lib/Chunk.js CHANGED
@@ -539,9 +539,9 @@ class Chunk {
539
539
  * @returns {void}
540
540
  */
541
541
  updateHash(hash, chunkGraph) {
542
- hash.update(`${this.id} `);
543
- hash.update(this.ids ? this.ids.join(",") : "");
544
- hash.update(`${this.name || ""} `);
542
+ hash.update(
543
+ `${this.id} ${this.ids ? this.ids.join() : ""} ${this.name || ""} `
544
+ );
545
545
  const xor = new StringXor();
546
546
  for (const m of chunkGraph.getChunkModulesIterable(this)) {
547
547
  xor.add(chunkGraph.getModuleHash(m, this.runtime));
@@ -550,9 +550,7 @@ class Chunk {
550
550
  const entryModules =
551
551
  chunkGraph.getChunkEntryModulesWithChunkGroupIterable(this);
552
552
  for (const [m, chunkGroup] of entryModules) {
553
- hash.update("entry");
554
- hash.update(`${chunkGraph.getModuleId(m)}`);
555
- hash.update(chunkGroup.id);
553
+ hash.update(`entry${chunkGraph.getModuleId(m)}${chunkGroup.id}`);
556
554
  }
557
555
  }
558
556
 
package/lib/ChunkGraph.js CHANGED
@@ -235,16 +235,6 @@ class ChunkGraph {
235
235
  this._hashFunction = hashFunction;
236
236
 
237
237
  this._getGraphRoots = this._getGraphRoots.bind(this);
238
-
239
- // Caching
240
- this._cacheChunkGraphModuleKey1 = undefined;
241
- this._cacheChunkGraphModuleValue1 = undefined;
242
- this._cacheChunkGraphModuleKey2 = undefined;
243
- this._cacheChunkGraphModuleValue2 = undefined;
244
- this._cacheChunkGraphChunkKey1 = undefined;
245
- this._cacheChunkGraphChunkValue1 = undefined;
246
- this._cacheChunkGraphChunkKey2 = undefined;
247
- this._cacheChunkGraphChunkValue2 = undefined;
248
238
  }
249
239
 
250
240
  /**
@@ -253,19 +243,11 @@ class ChunkGraph {
253
243
  * @returns {ChunkGraphModule} internal module
254
244
  */
255
245
  _getChunkGraphModule(module) {
256
- if (this._cacheChunkGraphModuleKey1 === module)
257
- return this._cacheChunkGraphModuleValue1;
258
- if (this._cacheChunkGraphModuleKey2 === module)
259
- return this._cacheChunkGraphModuleValue2;
260
246
  let cgm = this._modules.get(module);
261
247
  if (cgm === undefined) {
262
248
  cgm = new ChunkGraphModule();
263
249
  this._modules.set(module, cgm);
264
250
  }
265
- this._cacheChunkGraphModuleKey2 = this._cacheChunkGraphModuleKey1;
266
- this._cacheChunkGraphModuleValue2 = this._cacheChunkGraphModuleValue1;
267
- this._cacheChunkGraphModuleKey1 = module;
268
- this._cacheChunkGraphModuleValue1 = cgm;
269
251
  return cgm;
270
252
  }
271
253
 
@@ -275,19 +257,11 @@ class ChunkGraph {
275
257
  * @returns {ChunkGraphChunk} internal chunk
276
258
  */
277
259
  _getChunkGraphChunk(chunk) {
278
- if (this._cacheChunkGraphChunkKey1 === chunk)
279
- return this._cacheChunkGraphChunkValue1;
280
- if (this._cacheChunkGraphChunkKey2 === chunk)
281
- return this._cacheChunkGraphChunkValue2;
282
260
  let cgc = this._chunks.get(chunk);
283
261
  if (cgc === undefined) {
284
262
  cgc = new ChunkGraphChunk();
285
263
  this._chunks.set(chunk, cgc);
286
264
  }
287
- this._cacheChunkGraphChunkKey2 = this._cacheChunkGraphChunkKey1;
288
- this._cacheChunkGraphChunkValue2 = this._cacheChunkGraphChunkValue1;
289
- this._cacheChunkGraphChunkKey1 = chunk;
290
- this._cacheChunkGraphChunkValue1 = cgc;
291
265
  return cgc;
292
266
  }
293
267
 
@@ -1499,8 +1473,7 @@ Caller might not support runtime-dependent code generation (opt-out via optimiza
1499
1473
  }
1500
1474
  const graphHash = cgm.graphHashes.provide(runtime, () => {
1501
1475
  const hash = createHash(this._hashFunction);
1502
- hash.update(`${cgm.id}`);
1503
- hash.update(`${this.moduleGraph.isAsync(module)}`);
1476
+ hash.update(`${cgm.id}${this.moduleGraph.isAsync(module)}`);
1504
1477
  this.moduleGraph.getExportsInfo(module).updateHash(hash, runtime);
1505
1478
  return BigInt(`0x${/** @type {string} */ (hash.digest("hex"))}`);
1506
1479
  });
@@ -917,8 +917,10 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
917
917
  };
918
918
  defineRemovedModuleTemplates(this.moduleTemplates);
919
919
 
920
- /** @type {WeakMap<Module, WeakTupleMap<any, any>> | undefined} */
920
+ /** @type {Map<Module, WeakTupleMap<any, any>> | undefined} */
921
921
  this.moduleMemCaches = undefined;
922
+ /** @type {Map<Module, WeakTupleMap<any, any>> | undefined} */
923
+ this.moduleMemCaches2 = undefined;
922
924
  this.moduleGraph = new ModuleGraph();
923
925
  /** @type {ChunkGraph} */
924
926
  this.chunkGraph = undefined;
@@ -1403,8 +1405,9 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
1403
1405
  processModuleDependenciesNonRecursive(module) {
1404
1406
  const processDependenciesBlock = block => {
1405
1407
  if (block.dependencies) {
1408
+ let i = 0;
1406
1409
  for (const dep of block.dependencies) {
1407
- this.moduleGraph.setParents(dep, block, module);
1410
+ this.moduleGraph.setParents(dep, block, module, i++);
1408
1411
  }
1409
1412
  }
1410
1413
  if (block.blocks) {
@@ -1448,10 +1451,11 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
1448
1451
 
1449
1452
  /**
1450
1453
  * @param {Dependency} dep dependency
1454
+ * @param {number} index index in block
1451
1455
  * @returns {void}
1452
1456
  */
1453
- const processDependency = dep => {
1454
- this.moduleGraph.setParents(dep, currentBlock, module);
1457
+ const processDependency = (dep, index) => {
1458
+ this.moduleGraph.setParents(dep, currentBlock, module, index);
1455
1459
  if (this._unsafeCache) {
1456
1460
  try {
1457
1461
  const cachedModule = unsafeCacheDependencies.get(dep);
@@ -1555,7 +1559,8 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
1555
1559
  const block = queue.pop();
1556
1560
  if (block.dependencies) {
1557
1561
  currentBlock = block;
1558
- for (const dep of block.dependencies) processDependency(dep);
1562
+ let i = 0;
1563
+ for (const dep of block.dependencies) processDependency(dep, i++);
1559
1564
  }
1560
1565
  if (block.blocks) {
1561
1566
  for (const b of block.blocks) queue.push(b);
@@ -2169,7 +2174,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
2169
2174
  const moduleMemCacheCache = this.compiler.moduleMemCaches;
2170
2175
  if (!moduleMemCacheCache) return;
2171
2176
  if (!this.moduleMemCaches) {
2172
- this.moduleMemCaches = new WeakMap();
2177
+ this.moduleMemCaches = new Map();
2173
2178
  this.moduleGraph.setModuleMemCaches(this.moduleMemCaches);
2174
2179
  }
2175
2180
  const { moduleGraph, moduleMemCaches } = this;
@@ -2179,7 +2184,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
2179
2184
  let statChanged = 0;
2180
2185
  let statUnchanged = 0;
2181
2186
  let statReferencesChanged = 0;
2182
- let statWithoutHash = 0;
2187
+ let statWithoutBuild = 0;
2183
2188
 
2184
2189
  const computeReferences = module => {
2185
2190
  /** @type {WeakMap<Dependency, Module>} */
@@ -2211,48 +2216,63 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
2211
2216
  return true;
2212
2217
  };
2213
2218
 
2214
- for (const module of modules) {
2215
- const hash = module.buildInfo && module.buildInfo.hash;
2216
- if (typeof hash === "string") {
2217
- const cachedMemCache = moduleMemCacheCache.get(module);
2218
- if (cachedMemCache === undefined) {
2219
- // create a new entry
2220
- const memCache = new WeakTupleMap();
2221
- moduleMemCacheCache.set(module, {
2222
- hash: hash,
2223
- references: computeReferences(module),
2224
- memCache
2225
- });
2226
- moduleMemCaches.set(module, memCache);
2227
- affectedModules.add(module);
2228
- statNew++;
2229
- } else if (cachedMemCache.hash !== hash) {
2230
- // use a new one
2231
- const memCache = new WeakTupleMap();
2232
- moduleMemCaches.set(module, memCache);
2233
- affectedModules.add(module);
2234
- cachedMemCache.hash = hash;
2235
- cachedMemCache.references = computeReferences(module);
2236
- cachedMemCache.memCache = memCache;
2237
- statChanged++;
2238
- } else if (!compareReferences(module, cachedMemCache.references)) {
2239
- // use a new one
2240
- const memCache = new WeakTupleMap();
2241
- moduleMemCaches.set(module, memCache);
2242
- affectedModules.add(module);
2243
- cachedMemCache.references = computeReferences(module);
2244
- cachedMemCache.memCache = memCache;
2245
- statReferencesChanged++;
2219
+ const modulesWithoutCache = new Set(modules);
2220
+ for (const [module, cachedMemCache] of moduleMemCacheCache) {
2221
+ if (modulesWithoutCache.has(module)) {
2222
+ const buildInfo = module.buildInfo;
2223
+ if (buildInfo) {
2224
+ if (cachedMemCache.buildInfo !== buildInfo) {
2225
+ // use a new one
2226
+ const memCache = new WeakTupleMap();
2227
+ moduleMemCaches.set(module, memCache);
2228
+ affectedModules.add(module);
2229
+ cachedMemCache.buildInfo = buildInfo;
2230
+ cachedMemCache.references = computeReferences(module);
2231
+ cachedMemCache.memCache = memCache;
2232
+ statChanged++;
2233
+ } else if (!compareReferences(module, cachedMemCache.references)) {
2234
+ // use a new one
2235
+ const memCache = new WeakTupleMap();
2236
+ moduleMemCaches.set(module, memCache);
2237
+ affectedModules.add(module);
2238
+ cachedMemCache.references = computeReferences(module);
2239
+ cachedMemCache.memCache = memCache;
2240
+ statReferencesChanged++;
2241
+ } else {
2242
+ // keep the old mem cache
2243
+ moduleMemCaches.set(module, cachedMemCache.memCache);
2244
+ statUnchanged++;
2245
+ }
2246
2246
  } else {
2247
- // keep the old mem cache
2248
- moduleMemCaches.set(module, cachedMemCache.memCache);
2249
- statUnchanged++;
2247
+ infectedModules.add(module);
2248
+ moduleMemCacheCache.delete(module);
2249
+ statWithoutBuild++;
2250
2250
  }
2251
+ modulesWithoutCache.delete(module);
2252
+ } else {
2253
+ moduleMemCacheCache.delete(module);
2254
+ }
2255
+ }
2256
+
2257
+ for (const module of modulesWithoutCache) {
2258
+ const buildInfo = module.buildInfo;
2259
+ if (buildInfo) {
2260
+ // create a new entry
2261
+ const memCache = new WeakTupleMap();
2262
+ moduleMemCacheCache.set(module, {
2263
+ buildInfo,
2264
+ references: computeReferences(module),
2265
+ memCache
2266
+ });
2267
+ moduleMemCaches.set(module, memCache);
2268
+ affectedModules.add(module);
2269
+ statNew++;
2251
2270
  } else {
2252
2271
  infectedModules.add(module);
2253
- statWithoutHash++;
2272
+ statWithoutBuild++;
2254
2273
  }
2255
2274
  }
2275
+
2256
2276
  const reduceAffectType = connections => {
2257
2277
  let affected = false;
2258
2278
  for (const { dependency } of connections) {
@@ -2313,7 +2333,112 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
2313
2333
  infectedModules.size
2314
2334
  } infected of ${
2315
2335
  this.modules.size
2316
- }) modules flagged as affected (${statNew} new modules, ${statChanged} changed, ${statReferencesChanged} references changed, ${statUnchanged} unchanged, ${statWithoutHash} without hash)`
2336
+ }) modules flagged as affected (${statNew} new modules, ${statChanged} changed, ${statReferencesChanged} references changed, ${statUnchanged} unchanged, ${statWithoutBuild} were not built)`
2337
+ );
2338
+ }
2339
+
2340
+ _computeAffectedModulesWithChunkGraph() {
2341
+ const { moduleMemCaches } = this;
2342
+ if (!moduleMemCaches) return;
2343
+ const moduleMemCaches2 = (this.moduleMemCaches2 = new Map());
2344
+ const { moduleGraph, chunkGraph } = this;
2345
+ const key = "memCache2";
2346
+ let statUnchanged = 0;
2347
+ let statChanged = 0;
2348
+ let statNew = 0;
2349
+ /**
2350
+ * @param {Module} module module
2351
+ * @returns {{ modules?: Map<Module, string | number | undefined>, blocks?: (string | number)[] }} references
2352
+ */
2353
+ const computeReferences = module => {
2354
+ /** @type {Map<Module, string | number | undefined>} */
2355
+ let modules = undefined;
2356
+ /** @type {(string | number)[] | undefined} */
2357
+ let blocks = undefined;
2358
+ const outgoing = moduleGraph.getOutgoingConnectionsByModule(module);
2359
+ if (outgoing !== undefined) {
2360
+ for (const m of outgoing.keys()) {
2361
+ if (!m) continue;
2362
+ if (modules === undefined) modules = new Map();
2363
+ modules.set(m, chunkGraph.getModuleId(m));
2364
+ }
2365
+ }
2366
+ if (module.blocks.length > 0) {
2367
+ blocks = [];
2368
+ const queue = Array.from(module.blocks);
2369
+ for (const block of queue) {
2370
+ const chunkGroup = chunkGraph.getBlockChunkGroup(block);
2371
+ if (chunkGroup) {
2372
+ for (const chunk of chunkGroup.chunks) {
2373
+ blocks.push(chunk.id);
2374
+ }
2375
+ } else {
2376
+ blocks.push(null);
2377
+ }
2378
+ queue.push.apply(queue, block.blocks);
2379
+ }
2380
+ }
2381
+ return { modules, blocks };
2382
+ };
2383
+ /**
2384
+ * @param {Module} module module
2385
+ * @param {Object} references references
2386
+ * @param {Map<Module, string | number>=} references.modules modules
2387
+ * @param {(string | number)[]=} references.blocks blocks
2388
+ * @returns {boolean} ok?
2389
+ */
2390
+ const compareReferences = (module, { modules, blocks }) => {
2391
+ if (modules !== undefined) {
2392
+ for (const [module, id] of modules) {
2393
+ if (chunkGraph.getModuleId(module) !== id) return false;
2394
+ }
2395
+ }
2396
+ if (blocks !== undefined) {
2397
+ const queue = Array.from(module.blocks);
2398
+ let i = 0;
2399
+ for (const block of queue) {
2400
+ const chunkGroup = chunkGraph.getBlockChunkGroup(block);
2401
+ if (chunkGroup) {
2402
+ for (const chunk of chunkGroup.chunks) {
2403
+ if (i >= blocks.length || blocks[i++] !== chunk.id) return false;
2404
+ }
2405
+ } else {
2406
+ if (i >= blocks.length || blocks[i++] !== null) return false;
2407
+ }
2408
+ queue.push.apply(queue, block.blocks);
2409
+ }
2410
+ if (i !== blocks.length) return false;
2411
+ }
2412
+ return true;
2413
+ };
2414
+
2415
+ for (const [module, memCache] of moduleMemCaches) {
2416
+ /** @type {{ references: { modules?: Map<Module, string | number | undefined>, blocks?: (string | number)[]}, memCache: WeakTupleMap<any[], any> }} */
2417
+ const cache = memCache.get(key);
2418
+ if (cache === undefined) {
2419
+ const memCache2 = new WeakTupleMap();
2420
+ memCache.set(key, {
2421
+ references: computeReferences(module),
2422
+ memCache: memCache2
2423
+ });
2424
+ moduleMemCaches2.set(module, memCache2);
2425
+ statNew++;
2426
+ } else if (!compareReferences(module, cache.references)) {
2427
+ const memCache = new WeakTupleMap();
2428
+ cache.references = computeReferences(module);
2429
+ cache.memCache = memCache;
2430
+ moduleMemCaches2.set(module, memCache);
2431
+ statChanged++;
2432
+ } else {
2433
+ moduleMemCaches2.set(module, cache.memCache);
2434
+ statUnchanged++;
2435
+ }
2436
+ }
2437
+
2438
+ this.logger.log(
2439
+ `${Math.round(
2440
+ (100 * statChanged) / (statNew + statChanged + statUnchanged)
2441
+ )}% modules flagged as affected by chunk graph (${statNew} new modules, ${statChanged} changed, ${statUnchanged} unchanged)`
2317
2442
  );
2318
2443
  }
2319
2444
 
@@ -2561,6 +2686,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
2561
2686
  this.assetsInfo.clear();
2562
2687
  this.moduleGraph.removeAllModuleAttributes();
2563
2688
  this.moduleGraph.unfreeze();
2689
+ this.moduleMemCaches2 = undefined;
2564
2690
  }
2565
2691
 
2566
2692
  /**
@@ -2616,13 +2742,14 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
2616
2742
  this.chunkGroups.push(entrypoint);
2617
2743
  connectChunkGroupAndChunk(entrypoint, chunk);
2618
2744
 
2745
+ const entryModules = new Set();
2619
2746
  for (const dep of [...this.globalEntry.dependencies, ...dependencies]) {
2620
2747
  entrypoint.addOrigin(null, { name }, /** @type {any} */ (dep).request);
2621
2748
 
2622
2749
  const module = this.moduleGraph.getModule(dep);
2623
2750
  if (module) {
2624
2751
  chunkGraph.connectChunkAndEntryModule(chunk, module, entrypoint);
2625
- this.assignDepth(module);
2752
+ entryModules.add(module);
2626
2753
  const modulesList = chunkGraphInit.get(entrypoint);
2627
2754
  if (modulesList === undefined) {
2628
2755
  chunkGraphInit.set(entrypoint, [module]);
@@ -2632,6 +2759,8 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
2632
2759
  }
2633
2760
  }
2634
2761
 
2762
+ this.assignDepths(entryModules);
2763
+
2635
2764
  const mapAndSort = deps =>
2636
2765
  deps
2637
2766
  .map(dep => this.moduleGraph.getModule(dep))
@@ -2778,6 +2907,10 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
2778
2907
 
2779
2908
  this.assignRuntimeIds();
2780
2909
 
2910
+ this.logger.time("compute affected modules with chunk graph");
2911
+ this._computeAffectedModulesWithChunkGraph();
2912
+ this.logger.timeEnd("compute affected modules with chunk graph");
2913
+
2781
2914
  this.sortItemsWithChunkIds();
2782
2915
 
2783
2916
  if (shouldRecord) {
@@ -3121,18 +3254,14 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
3121
3254
  chunkGraphEntries = this._getChunkGraphEntries()
3122
3255
  } = {}) {
3123
3256
  const context = { chunkGraph, codeGenerationResults };
3124
- const { moduleMemCaches } = this;
3257
+ const { moduleMemCaches2 } = this;
3125
3258
  this.logger.time("runtime requirements.modules");
3126
3259
  const additionalModuleRuntimeRequirements =
3127
3260
  this.hooks.additionalModuleRuntimeRequirements;
3128
3261
  const runtimeRequirementInModule = this.hooks.runtimeRequirementInModule;
3129
3262
  for (const module of modules) {
3130
3263
  if (chunkGraph.getNumberOfModuleChunks(module) > 0) {
3131
- const memCache =
3132
- moduleMemCaches &&
3133
- // modules with async blocks depend on the chunk graph and can't be cached that way
3134
- module.blocks.length === 0 &&
3135
- moduleMemCaches.get(module);
3264
+ const memCache = moduleMemCaches2 && moduleMemCaches2.get(module);
3136
3265
  for (const runtime of chunkGraph.getModuleRuntimes(module)) {
3137
3266
  if (memCache) {
3138
3267
  const cached = memCache.get(
@@ -3401,6 +3530,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
3401
3530
  }
3402
3531
 
3403
3532
  /**
3533
+ * @deprecated
3404
3534
  * @param {Module} module module to assign depth
3405
3535
  * @returns {void}
3406
3536
  */
@@ -3434,6 +3564,38 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
3434
3564
  }
3435
3565
  }
3436
3566
 
3567
+ /**
3568
+ * @param {Set<Module>} modules module to assign depth
3569
+ * @returns {void}
3570
+ */
3571
+ assignDepths(modules) {
3572
+ const moduleGraph = this.moduleGraph;
3573
+
3574
+ /** @type {Set<Module | number>} */
3575
+ const queue = new Set(modules);
3576
+ queue.add(1);
3577
+ let depth = 0;
3578
+
3579
+ let i = 0;
3580
+ for (const module of queue) {
3581
+ i++;
3582
+ if (typeof module === "number") {
3583
+ depth = module;
3584
+ if (queue.size === i) return;
3585
+ queue.add(depth + 1);
3586
+ } else {
3587
+ moduleGraph.setDepth(module, depth);
3588
+ for (const { module: refModule } of moduleGraph.getOutgoingConnections(
3589
+ module
3590
+ )) {
3591
+ if (refModule) {
3592
+ queue.add(refModule);
3593
+ }
3594
+ }
3595
+ }
3596
+ }
3597
+ }
3598
+
3437
3599
  /**
3438
3600
  * @param {Dependency} dependency the dependency
3439
3601
  * @param {RuntimeSpec} runtime the runtime
@@ -3589,14 +3751,10 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
3589
3751
  createModuleHashes() {
3590
3752
  let statModulesHashed = 0;
3591
3753
  let statModulesFromCache = 0;
3592
- const { chunkGraph, runtimeTemplate, moduleMemCaches } = this;
3754
+ const { chunkGraph, runtimeTemplate, moduleMemCaches2 } = this;
3593
3755
  const { hashFunction, hashDigest, hashDigestLength } = this.outputOptions;
3594
3756
  for (const module of this.modules) {
3595
- const memCache =
3596
- moduleMemCaches &&
3597
- // modules with async blocks depend on the chunk graph and can't be cached that way
3598
- module.blocks.length === 0 &&
3599
- moduleMemCaches.get(module);
3757
+ const memCache = moduleMemCaches2 && moduleMemCaches2.get(module);
3600
3758
  for (const runtime of chunkGraph.getModuleRuntimes(module)) {
3601
3759
  if (memCache) {
3602
3760
  const digest = memCache.get(`moduleHash-${getRuntimeKey(runtime)}`);
package/lib/Compiler.js CHANGED
@@ -249,7 +249,7 @@ class Compiler {
249
249
 
250
250
  this.cache = new Cache();
251
251
 
252
- /** @type {WeakMap<Module, { hash: string, references: WeakMap<Dependency, Module>, memCache: WeakTupleMap }> | undefined} */
252
+ /** @type {Map<Module, { buildInfo: object, references: WeakMap<Dependency, Module>, memCache: WeakTupleMap }> | undefined} */
253
253
  this.moduleMemCaches = undefined;
254
254
 
255
255
  this.compilerPath = "";
@@ -22,6 +22,15 @@ class DependenciesBlock {
22
22
  this.dependencies = [];
23
23
  /** @type {AsyncDependenciesBlock[]} */
24
24
  this.blocks = [];
25
+ /** @type {DependenciesBlock} */
26
+ this.parent = undefined;
27
+ }
28
+
29
+ getRootBlock() {
30
+ /** @type {DependenciesBlock} */
31
+ let current = this;
32
+ while (current.parent) current = current.parent;
33
+ return current;
25
34
  }
26
35
 
27
36
  /**
package/lib/Dependency.js CHANGED
@@ -91,6 +91,8 @@ class Dependency {
91
91
  this._parentModule = undefined;
92
92
  /** @type {DependenciesBlock} */
93
93
  this._parentDependenciesBlock = undefined;
94
+ /** @type {number} */
95
+ this._parentDependenciesBlockIndex = -1;
94
96
  // TODO check if this can be moved into ModuleDependency
95
97
  /** @type {boolean} */
96
98
  this.weak = false;
@@ -48,8 +48,7 @@ class DependencyTemplates {
48
48
  */
49
49
  updateHash(part) {
50
50
  const hash = createHash(this._hashFunction);
51
- hash.update(this._hash);
52
- hash.update(part);
51
+ hash.update(`${this._hash}${part}`);
53
52
  this._hash = /** @type {string} */ (hash.digest("hex"));
54
53
  }
55
54
 
package/lib/DllModule.js CHANGED
@@ -117,8 +117,7 @@ class DllModule extends Module {
117
117
  * @returns {void}
118
118
  */
119
119
  updateHash(hash, context) {
120
- hash.update("dll module");
121
- hash.update(this.name || "");
120
+ hash.update(`dll module${this.name || ""}`);
122
121
  super.updateHash(hash, context);
123
122
  }
124
123
 
@@ -1412,10 +1412,11 @@ class ExportInfo {
1412
1412
  }
1413
1413
 
1414
1414
  _updateHash(hash, runtime, alreadyVisitedExportsInfo) {
1415
- hash.update(`${this._usedName || this.name}`);
1416
- hash.update(`${this.getUsed(runtime)}`);
1417
- hash.update(`${this.provided}`);
1418
- hash.update(`${this.terminalBinding}`);
1415
+ hash.update(
1416
+ `${this._usedName || this.name}${this.getUsed(runtime)}${this.provided}${
1417
+ this.terminalBinding
1418
+ }`
1419
+ );
1419
1420
  if (this.exportsInfo && !alreadyVisitedExportsInfo.has(this.exportsInfo)) {
1420
1421
  this.exportsInfo._updateHash(hash, runtime, alreadyVisitedExportsInfo);
1421
1422
  }
@@ -32,6 +32,7 @@ const { register } = require("./util/serialization");
32
32
  /** @typedef {import("./Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */
33
33
  /** @typedef {import("./Module").LibIdentOptions} LibIdentOptions */
34
34
  /** @typedef {import("./Module").NeedBuildContext} NeedBuildContext */
35
+ /** @typedef {import("./NormalModuleFactory")} NormalModuleFactory */
35
36
  /** @typedef {import("./RequestShortener")} RequestShortener */
36
37
  /** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
37
38
  /** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
@@ -497,6 +498,10 @@ class ExternalModule extends Module {
497
498
  callback();
498
499
  }
499
500
 
501
+ restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) {
502
+ this._restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory);
503
+ }
504
+
500
505
  /**
501
506
  * @param {ConcatenationBailoutReasonContext} context context
502
507
  * @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated
@@ -679,10 +684,10 @@ class ExternalModule extends Module {
679
684
  */
680
685
  updateHash(hash, context) {
681
686
  const { chunkGraph } = context;
682
- hash.update(this.externalType);
683
- hash.update(JSON.stringify(this.request));
684
687
  hash.update(
685
- JSON.stringify(Boolean(this.isOptional(chunkGraph.moduleGraph)))
688
+ `${this.externalType}${JSON.stringify(this.request)}${this.isOptional(
689
+ chunkGraph.moduleGraph
690
+ )}`
686
691
  );
687
692
  super.updateHash(hash, context);
688
693
  }
@@ -46,10 +46,15 @@ class FlagDependencyUsagePlugin {
46
46
  stage: STAGE_DEFAULT
47
47
  },
48
48
  modules => {
49
+ if (compilation.moduleMemCaches) {
50
+ throw new Error(
51
+ "optimization.usedExports can't be used with cacheUnaffected as export usage is a global effect"
52
+ );
53
+ }
54
+
49
55
  const logger = compilation.getLogger(
50
56
  "webpack.FlagDependencyUsagePlugin"
51
57
  );
52
-
53
58
  /** @type {Map<ExportsInfo, Module>} */
54
59
  const exportInfoToModuleMap = new Map();
55
60
 
package/lib/Module.js CHANGED
@@ -885,6 +885,10 @@ class Module extends DependenciesBlock {
885
885
  return true;
886
886
  }
887
887
 
888
+ hasChunkCondition() {
889
+ return this.chunkCondition !== Module.prototype.chunkCondition;
890
+ }
891
+
888
892
  /**
889
893
  * Assuming this module is in the cache. Update the (cached) module with
890
894
  * the fresh module from the factory. Usually updates internal references