webpack 5.108.3 → 5.109.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.
Files changed (191) hide show
  1. package/lib/APIPlugin.js +48 -29
  2. package/lib/CacheFacade.js +8 -0
  3. package/lib/ChunkGroup.js +1 -0
  4. package/lib/CompatibilityPlugin.js +31 -29
  5. package/lib/Compilation.js +50 -8
  6. package/lib/ConstPlugin.js +11 -11
  7. package/lib/ContextModule.js +239 -6
  8. package/lib/ContextModuleFactory.js +139 -14
  9. package/lib/DefinePlugin.js +396 -101
  10. package/lib/Entrypoint.js +1 -1
  11. package/lib/ExportsInfoApiPlugin.js +2 -2
  12. package/lib/ExternalModule.js +107 -5
  13. package/lib/ExternalModuleFactoryPlugin.js +20 -1
  14. package/lib/FileSystemInfo.js +130 -74
  15. package/lib/FlagDependencyExportsPlugin.js +55 -8
  16. package/lib/HotModuleReplacementPlugin.js +18 -15
  17. package/lib/LazyBarrel.js +30 -3
  18. package/lib/Module.js +3 -0
  19. package/lib/ModuleFilenameHelpers.js +2 -2
  20. package/lib/ModuleTypeConstants.js +8 -1
  21. package/lib/MultiCompiler.js +13 -2
  22. package/lib/MultiWatching.js +1 -0
  23. package/lib/NodeStuffPlugin.js +51 -33
  24. package/lib/NormalModule.js +169 -405
  25. package/lib/NormalModuleFactory.js +76 -2
  26. package/lib/ProgressPlugin.js +211 -119
  27. package/lib/ProvidePlugin.js +2 -2
  28. package/lib/RuntimeGlobals.js +47 -0
  29. package/lib/RuntimePlugin.js +33 -0
  30. package/lib/RuntimeTemplate.js +304 -16
  31. package/lib/UseStrictPlugin.js +1 -1
  32. package/lib/WebpackIsIncludedPlugin.js +1 -1
  33. package/lib/WebpackOptionsApply.js +24 -19
  34. package/lib/asset/AssetGenerator.js +110 -28
  35. package/lib/asset/AssetModulesPlugin.js +92 -2
  36. package/lib/asset/WebManifestGenerator.js +164 -0
  37. package/lib/asset/WebManifestParser.js +130 -0
  38. package/lib/async-modules/AwaitDependenciesInitFragment.js +14 -4
  39. package/lib/async-modules/isGeneratorLowered.js +26 -0
  40. package/lib/cache/PackFileCacheStrategy.js +9 -3
  41. package/lib/config/browserslistTargetHandler.js +40 -0
  42. package/lib/config/defaults.js +222 -32
  43. package/lib/config/normalization.js +26 -0
  44. package/lib/config/target.js +9 -1
  45. package/lib/css/CssGenerator.js +73 -73
  46. package/lib/css/CssLoadingRuntimeModule.js +5 -1
  47. package/lib/css/CssModulesPlugin.js +92 -53
  48. package/lib/css/CssParser.js +843 -302
  49. package/lib/css/syntax.js +1219 -483
  50. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -6
  51. package/lib/dependencies/AMDPlugin.js +2 -2
  52. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +13 -13
  53. package/lib/dependencies/CommonJsDependencyHelpers.js +39 -0
  54. package/lib/dependencies/CommonJsExportsDependency.js +47 -2
  55. package/lib/dependencies/CommonJsExportsParserPlugin.js +10 -10
  56. package/lib/dependencies/CommonJsImportsParserPlugin.js +18 -18
  57. package/lib/dependencies/CommonJsPlugin.js +2 -2
  58. package/lib/dependencies/CommonJsRequireDependency.js +26 -1
  59. package/lib/dependencies/CommonJsSelfReferenceDependency.js +32 -1
  60. package/lib/dependencies/ContextDependencyHelpers.js +3 -3
  61. package/lib/dependencies/CreateRequireParserPlugin.js +6 -6
  62. package/lib/dependencies/CssIcssExportDependency.js +190 -87
  63. package/lib/dependencies/CssUrlDependency.js +35 -4
  64. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +2 -2
  65. package/lib/dependencies/HarmonyCompatibilityDependency.js +32 -14
  66. package/lib/dependencies/HarmonyDetectionParserPlugin.js +43 -13
  67. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +7 -19
  68. package/lib/dependencies/HarmonyImportDependency.js +12 -1
  69. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +34 -107
  70. package/lib/dependencies/HarmonyImportGuard.js +192 -20
  71. package/lib/dependencies/HarmonyModulesPlugin.js +6 -0
  72. package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +1 -1
  73. package/lib/dependencies/HtmlEntryDependency.js +797 -172
  74. package/lib/dependencies/HtmlSourceDependency.js +26 -0
  75. package/lib/dependencies/ImportDependency.js +43 -1
  76. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +31 -18
  77. package/lib/dependencies/ImportMetaContextPlugin.js +38 -7
  78. package/lib/dependencies/ImportMetaGlobDependency.js +81 -0
  79. package/lib/dependencies/ImportMetaGlobDependencyParserPlugin.js +78 -0
  80. package/lib/dependencies/ImportMetaGlobHelpers.js +660 -0
  81. package/lib/dependencies/ImportMetaPlugin.js +532 -180
  82. package/lib/dependencies/ImportMetaResolveDependency.js +90 -0
  83. package/lib/dependencies/ImportParserPlugin.js +87 -26
  84. package/lib/dependencies/ImportPhase.js +10 -8
  85. package/lib/dependencies/LoaderPlugin.js +5 -1
  86. package/lib/dependencies/RequireContextDependencyParserPlugin.js +1 -1
  87. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +3 -6
  88. package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +4 -11
  89. package/lib/dependencies/SystemPlugin.js +2 -4
  90. package/lib/dependencies/TopLevelAwaitDependency.js +93 -0
  91. package/lib/dependencies/URLDependency.js +141 -21
  92. package/lib/dependencies/{WorkerPlugin.js → WorkerAndWorkletPlugin.js} +324 -112
  93. package/lib/dependencies/WorkerDependency.js +86 -18
  94. package/lib/dependencies/WorkletDependency.js +278 -0
  95. package/lib/dll/DelegatedModuleFactoryPlugin.js +19 -0
  96. package/lib/errors/EnvironmentNotSupportAsyncWarning.js +1 -1
  97. package/lib/errors/LoaderLoadingError.js +20 -0
  98. package/lib/errors/ModuleParseError.js +39 -22
  99. package/lib/errors/NodeStuffInWebError.js +1 -1
  100. package/lib/esm/ModuleChunkFormatPlugin.js +47 -14
  101. package/lib/esm/ModuleChunkLoadingPlugin.js +8 -1
  102. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +29 -1
  103. package/lib/hmr/lazyCompilationBackend.js +32 -8
  104. package/lib/html/HtmlGenerator.js +940 -91
  105. package/lib/html/HtmlModule.js +3 -2
  106. package/lib/html/HtmlModulesPlugin.js +625 -170
  107. package/lib/html/HtmlParser.js +812 -340
  108. package/lib/html/favicon.svg +1 -0
  109. package/lib/html/syntax.js +2116 -834
  110. package/lib/ids/IdHelpers.js +1 -1
  111. package/lib/index.js +6 -0
  112. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +4 -5
  113. package/lib/javascript/BasicEvaluatedExpression.js +366 -48
  114. package/lib/javascript/JavascriptGenerator.js +197 -49
  115. package/lib/javascript/JavascriptModulesPlugin.js +178 -24
  116. package/lib/javascript/JavascriptParser.js +711 -355
  117. package/lib/javascript/JavascriptParserHelpers.js +3 -6
  118. package/lib/javascript/syntax.js +4380 -0
  119. package/lib/library/ModuleLibraryPlugin.js +38 -1
  120. package/lib/loaders/LoaderRunner.js +714 -0
  121. package/lib/loaders/loadLoader.js +100 -0
  122. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +19 -0
  123. package/lib/node/ReadFileCompileWasmPlugin.js +14 -0
  124. package/lib/optimize/ConcatenatedModule.js +120 -16
  125. package/lib/optimize/FlagIncludedChunksPlugin.js +13 -3
  126. package/lib/optimize/InnerGraphPlugin.js +50 -30
  127. package/lib/optimize/ModuleConcatenationPlugin.js +69 -3
  128. package/lib/optimize/SideEffectsFlagPlugin.js +86 -43
  129. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +15 -0
  130. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +24 -13
  131. package/lib/prefetch/ResourceHintPlugin.js +663 -0
  132. package/lib/prefetch/ResourceHintRuntimeModule.js +149 -0
  133. package/lib/prefetch/StartupAssetHintRuntimeModule.js +210 -0
  134. package/lib/prefetch/parseResourceHintOptions.js +103 -0
  135. package/lib/rules/RuleSetCompiler.js +114 -0
  136. package/lib/runtime/AsyncModuleGeneratorRuntimeModule.js +56 -0
  137. package/lib/runtime/AsyncModuleRuntimeModule.js +24 -8
  138. package/lib/runtime/AutoPublicPathRuntimeModule.js +7 -1
  139. package/lib/runtime/CommonJsWrapRuntimeModule.js +37 -0
  140. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +59 -0
  141. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +204 -8
  142. package/lib/runtime/SetAnonymousDefaultNameRuntimeModule.js +4 -1
  143. package/lib/schemes/HttpUriPlugin.js +40 -1
  144. package/lib/schemes/VirtualUrlPlugin.js +1 -2
  145. package/lib/serialization/FileMiddleware.js +29 -3
  146. package/lib/stats/DefaultStatsFactoryPlugin.js +32 -3
  147. package/lib/stats/DefaultStatsPresetPlugin.js +2 -0
  148. package/lib/stats/DefaultStatsPrinterPlugin.js +12 -2
  149. package/lib/stats/StatsFactory.js +15 -8
  150. package/lib/url/URLParserPlugin.js +98 -19
  151. package/lib/util/AsyncQueue.js +122 -72
  152. package/lib/util/LocConverter.js +9 -8
  153. package/lib/util/SetHelpers.js +1 -1
  154. package/lib/util/SourceProcessor.js +41 -28
  155. package/lib/util/StackedMap.js +122 -48
  156. package/lib/util/binarySearchBounds.js +2 -2
  157. package/lib/util/concatenate.js +40 -14
  158. package/lib/util/createHooksRegistry.js +13 -5
  159. package/lib/util/dataURL.js +2 -2
  160. package/lib/util/deterministicGrouping.js +7 -5
  161. package/lib/util/formatSize.js +6 -2
  162. package/lib/util/globUtils.js +710 -0
  163. package/lib/util/identifier.js +23 -6
  164. package/lib/util/implicitTypeLoaderFallback.js +62 -0
  165. package/lib/util/internalSerializables.js +88 -71
  166. package/lib/util/magicComment.js +121 -25
  167. package/lib/util/numberHash.js +2 -2
  168. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +24 -18
  169. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +33 -22
  170. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +79 -16
  171. package/lib/web/FetchCompileAsyncWasmPlugin.js +19 -0
  172. package/lib/web/FetchCompileWasmPlugin.js +14 -0
  173. package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -0
  174. package/lib/webpack.js +65 -0
  175. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +3 -0
  176. package/module.d.ts +21 -0
  177. package/package.json +14 -13
  178. package/schemas/WebpackOptions.check.js +1 -1
  179. package/schemas/WebpackOptions.json +759 -36
  180. package/schemas/plugins/HtmlParserOptions.check.js +1 -1
  181. package/schemas/plugins/ProgressPlugin.check.js +1 -1
  182. package/schemas/plugins/ProgressPlugin.json +17 -1
  183. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  184. package/schemas/plugins/container/ContainerReferencePlugin.json +1 -0
  185. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  186. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  187. package/schemas/plugins/container/ModuleFederationPlugin.json +1 -0
  188. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +1 -1
  189. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  190. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  191. package/types.d.ts +1300 -325
@@ -1243,6 +1243,17 @@ const isExistenceOnly = (entry) => {
1243
1243
  );
1244
1244
  };
1245
1245
 
1246
+ /**
1247
+ * Watchpack directory entries may carry `safeTime` / `timestamp` but never
1248
+ * `timestampHash`; such object caches cannot back snapshot checks or symlink walks.
1249
+ * @param {ContextFileSystemInfoEntry | null | "ignore" | undefined} entry cache entry
1250
+ * @returns {boolean} true when a non-null object entry lacks `timestampHash`
1251
+ */
1252
+ const contextCacheEntryLacksTimestampHash = (entry) =>
1253
+ entry !== null &&
1254
+ typeof entry === "object" &&
1255
+ /** @type {ContextFileSystemInfoEntry} */ (entry).timestampHash === undefined;
1256
+
1246
1257
  /** @typedef {(err?: WebpackError | null, result?: boolean) => void} CheckSnapshotValidCallback */
1247
1258
 
1248
1259
  /**
@@ -1367,6 +1378,9 @@ class FileSystemInfo {
1367
1378
  this._contextTshs = new Map();
1368
1379
  /** @type {Map<string, string>} */
1369
1380
  this._managedItems = new Map();
1381
+ // memoized checkManaged results: 0 = not managed, 1 = immutable, string = managed item
1382
+ /** @type {Map<string, 0 | 1 | string>} */
1383
+ this._pathClassificationCache = new Map();
1370
1384
  /** @type {AsyncQueue<string, string, FileSystemInfoEntry>} */
1371
1385
  this.fileTimestampQueue = new AsyncQueue({
1372
1386
  name: "file timestamp",
@@ -1596,7 +1610,7 @@ class FileSystemInfo {
1596
1610
  this._contextHashes.clear();
1597
1611
  this._contextTshs.clear();
1598
1612
  this._managedItems.clear();
1599
- this._managedItems.clear();
1613
+ this._pathClassificationCache.clear();
1600
1614
 
1601
1615
  this._cachedDeprecatedFileTimestamps = undefined;
1602
1616
  this._cachedDeprecatedContextTimestamps = undefined;
@@ -1705,7 +1719,13 @@ class FileSystemInfo {
1705
1719
  */
1706
1720
  _getUnresolvedContextTimestamp(path, callback) {
1707
1721
  const cache = this._contextTimestamps.get(path);
1708
- if (cache !== undefined && !isExistenceOnly(cache)) {
1722
+ if (
1723
+ cache !== undefined &&
1724
+ !isExistenceOnly(cache) &&
1725
+ !contextCacheEntryLacksTimestampHash(
1726
+ /** @type {ContextFileSystemInfoEntry | null | "ignore"} */ (cache)
1727
+ )
1728
+ ) {
1709
1729
  return callback(
1710
1730
  null,
1711
1731
  /** @type {ContextFileSystemInfoEntry | "ignore" | null} */ (cache)
@@ -2460,30 +2480,29 @@ class FileSystemInfo {
2460
2480
  * @returns {void}
2461
2481
  */
2462
2482
  createSnapshot(startTime, files, directories, missing, options, callback) {
2463
- /** @type {FileTimestamps} */
2464
- const fileTimestamps = new Map();
2465
- /** @type {FileHashes} */
2466
- const fileHashes = new Map();
2467
- /** @type {FileTshs} */
2468
- const fileTshs = new Map();
2469
- /** @type {ContextTimestamps} */
2470
- const contextTimestamps = new Map();
2471
- /** @type {ContextHashes} */
2472
- const contextHashes = new Map();
2473
- /** @type {ContextTshs} */
2474
- const contextTshs = new Map();
2475
- /** @type {MissingExistence} */
2476
- const missingExistence = new Map();
2477
- /** @type {ManagedItemInfo} */
2478
- const managedItemInfo = new Map();
2483
+ // collections are allocated lazily to avoid per-snapshot garbage for unused modes
2484
+ /** @type {FileTimestamps | undefined} */
2485
+ let fileTimestamps;
2486
+ /** @type {FileHashes | undefined} */
2487
+ let fileHashes;
2488
+ /** @type {FileTshs | undefined} */
2489
+ let fileTshs;
2490
+ /** @type {ContextTimestamps | undefined} */
2491
+ let contextTimestamps;
2492
+ /** @type {ContextHashes | undefined} */
2493
+ let contextHashes;
2494
+ /** @type {ContextTshs | undefined} */
2495
+ let contextTshs;
2496
+ /** @type {MissingExistence | undefined} */
2497
+ let missingExistence;
2498
+ /** @type {ManagedItemInfo | undefined} */
2499
+ let managedItemInfo;
2479
2500
  /** @type {ManagedFiles} */
2480
2501
  const managedFiles = new Set();
2481
2502
  /** @type {ManagedContexts} */
2482
2503
  const managedContexts = new Set();
2483
2504
  /** @type {ManagedMissing} */
2484
2505
  const managedMissing = new Set();
2485
- /** @type {Children} */
2486
- const children = new Set();
2487
2506
 
2488
2507
  const snapshot = new Snapshot();
2489
2508
  if (startTime) snapshot.setStartTime(startTime);
@@ -2497,28 +2516,28 @@ class FileSystemInfo {
2497
2516
  let jobs = 1;
2498
2517
  const jobDone = () => {
2499
2518
  if (--jobs === 0) {
2500
- if (fileTimestamps.size !== 0) {
2519
+ if (fileTimestamps !== undefined && fileTimestamps.size !== 0) {
2501
2520
  snapshot.setFileTimestamps(fileTimestamps);
2502
2521
  }
2503
- if (fileHashes.size !== 0) {
2522
+ if (fileHashes !== undefined && fileHashes.size !== 0) {
2504
2523
  snapshot.setFileHashes(fileHashes);
2505
2524
  }
2506
- if (fileTshs.size !== 0) {
2525
+ if (fileTshs !== undefined && fileTshs.size !== 0) {
2507
2526
  snapshot.setFileTshs(fileTshs);
2508
2527
  }
2509
- if (contextTimestamps.size !== 0) {
2528
+ if (contextTimestamps !== undefined && contextTimestamps.size !== 0) {
2510
2529
  snapshot.setContextTimestamps(contextTimestamps);
2511
2530
  }
2512
- if (contextHashes.size !== 0) {
2531
+ if (contextHashes !== undefined && contextHashes.size !== 0) {
2513
2532
  snapshot.setContextHashes(contextHashes);
2514
2533
  }
2515
- if (contextTshs.size !== 0) {
2534
+ if (contextTshs !== undefined && contextTshs.size !== 0) {
2516
2535
  snapshot.setContextTshs(contextTshs);
2517
2536
  }
2518
- if (missingExistence.size !== 0) {
2537
+ if (missingExistence !== undefined && missingExistence.size !== 0) {
2519
2538
  snapshot.setMissingExistence(missingExistence);
2520
2539
  }
2521
- if (managedItemInfo.size !== 0) {
2540
+ if (managedItemInfo !== undefined && managedItemInfo.size !== 0) {
2522
2541
  snapshot.setManagedItemInfo(managedItemInfo);
2523
2542
  }
2524
2543
  this._managedFilesOptimization.optimize(snapshot, managedFiles);
@@ -2533,9 +2552,6 @@ class FileSystemInfo {
2533
2552
  if (managedMissing.size !== 0) {
2534
2553
  snapshot.setManagedMissing(managedMissing);
2535
2554
  }
2536
- if (children.size !== 0) {
2537
- snapshot.setChildren(children);
2538
- }
2539
2555
  this._snapshotCache.set(snapshot, true);
2540
2556
  this._statCreatedSnapshots++;
2541
2557
 
@@ -2549,6 +2565,7 @@ class FileSystemInfo {
2549
2565
  callback(null, null);
2550
2566
  }
2551
2567
  };
2568
+ const classificationCache = this._pathClassificationCache;
2552
2569
  /**
2553
2570
  * Checks true when managed.
2554
2571
  * @param {string} path path
@@ -2556,20 +2573,36 @@ class FileSystemInfo {
2556
2573
  * @returns {boolean} true when managed
2557
2574
  */
2558
2575
  const checkManaged = (path, managedSet) => {
2576
+ // classification is a pure function of the path, so it's shared across snapshots
2577
+ const cached = classificationCache.get(path);
2578
+ if (cached !== undefined) {
2579
+ if (cached === 0) return false;
2580
+ if (cached !== 1) managedItems.add(cached);
2581
+ managedSet.add(path);
2582
+ return true;
2583
+ }
2559
2584
  for (const unmanagedPath of this.unmanagedPathsRegExps) {
2560
- if (unmanagedPath.test(path)) return false;
2585
+ if (unmanagedPath.test(path)) {
2586
+ classificationCache.set(path, 0);
2587
+ return false;
2588
+ }
2561
2589
  }
2562
2590
  for (const unmanagedPath of this.unmanagedPathsWithSlash) {
2563
- if (path.startsWith(unmanagedPath)) return false;
2591
+ if (path.startsWith(unmanagedPath)) {
2592
+ classificationCache.set(path, 0);
2593
+ return false;
2594
+ }
2564
2595
  }
2565
2596
  for (const immutablePath of this.immutablePathsRegExps) {
2566
2597
  if (immutablePath.test(path)) {
2598
+ classificationCache.set(path, 1);
2567
2599
  managedSet.add(path);
2568
2600
  return true;
2569
2601
  }
2570
2602
  }
2571
2603
  for (const immutablePath of this.immutablePathsWithSlash) {
2572
2604
  if (path.startsWith(immutablePath)) {
2605
+ classificationCache.set(path, 1);
2573
2606
  managedSet.add(path);
2574
2607
  return true;
2575
2608
  }
@@ -2579,6 +2612,7 @@ class FileSystemInfo {
2579
2612
  if (match) {
2580
2613
  const managedItem = getManagedItem(match[1], path);
2581
2614
  if (managedItem) {
2615
+ classificationCache.set(path, managedItem);
2582
2616
  managedItems.add(managedItem);
2583
2617
  managedSet.add(path);
2584
2618
  return true;
@@ -2589,12 +2623,14 @@ class FileSystemInfo {
2589
2623
  if (path.startsWith(managedPath)) {
2590
2624
  const managedItem = getManagedItem(managedPath, path);
2591
2625
  if (managedItem) {
2626
+ classificationCache.set(path, managedItem);
2592
2627
  managedItems.add(managedItem);
2593
2628
  managedSet.add(path);
2594
2629
  return true;
2595
2630
  }
2596
2631
  }
2597
2632
  }
2633
+ classificationCache.set(path, 0);
2598
2634
  return false;
2599
2635
  };
2600
2636
  /**
@@ -2620,12 +2656,14 @@ class FileSystemInfo {
2620
2656
  return;
2621
2657
  }
2622
2658
  switch (mode) {
2623
- case 3:
2659
+ case 3: {
2624
2660
  this._fileTshsOptimization.optimize(snapshot, capturedFiles);
2661
+ if (fileTshs === undefined) fileTshs = new Map();
2662
+ const fileTshsMap = fileTshs;
2625
2663
  for (const path of capturedFiles) {
2626
2664
  const cache = this._fileTshs.get(path);
2627
2665
  if (cache !== undefined) {
2628
- fileTshs.set(path, cache);
2666
+ fileTshsMap.set(path, cache);
2629
2667
  } else {
2630
2668
  jobs++;
2631
2669
  this._getFileTimestampAndHash(path, (err, entry) => {
@@ -2637,19 +2675,25 @@ class FileSystemInfo {
2637
2675
  }
2638
2676
  jobError();
2639
2677
  } else {
2640
- fileTshs.set(path, /** @type {TimestampAndHash} */ (entry));
2678
+ fileTshsMap.set(
2679
+ path,
2680
+ /** @type {TimestampAndHash} */ (entry)
2681
+ );
2641
2682
  jobDone();
2642
2683
  }
2643
2684
  });
2644
2685
  }
2645
2686
  }
2646
2687
  break;
2647
- case 2:
2688
+ }
2689
+ case 2: {
2648
2690
  this._fileHashesOptimization.optimize(snapshot, capturedFiles);
2691
+ if (fileHashes === undefined) fileHashes = new Map();
2692
+ const fileHashesMap = fileHashes;
2649
2693
  for (const path of capturedFiles) {
2650
2694
  const cache = this._fileHashes.get(path);
2651
2695
  if (cache !== undefined) {
2652
- fileHashes.set(path, cache);
2696
+ fileHashesMap.set(path, cache);
2653
2697
  } else {
2654
2698
  jobs++;
2655
2699
  this.fileHashQueue.add(path, (err, entry) => {
@@ -2661,20 +2705,23 @@ class FileSystemInfo {
2661
2705
  }
2662
2706
  jobError();
2663
2707
  } else {
2664
- fileHashes.set(path, /** @type {string} */ (entry));
2708
+ fileHashesMap.set(path, /** @type {string} */ (entry));
2665
2709
  jobDone();
2666
2710
  }
2667
2711
  });
2668
2712
  }
2669
2713
  }
2670
2714
  break;
2671
- case 1:
2715
+ }
2716
+ case 1: {
2672
2717
  this._fileTimestampsOptimization.optimize(snapshot, capturedFiles);
2718
+ if (fileTimestamps === undefined) fileTimestamps = new Map();
2719
+ const fileTimestampsMap = fileTimestamps;
2673
2720
  for (const path of capturedFiles) {
2674
2721
  const cache = this._fileTimestamps.get(path);
2675
2722
  if (cache !== undefined && !isExistenceOnly(cache)) {
2676
2723
  if (cache !== "ignore") {
2677
- fileTimestamps.set(
2724
+ fileTimestampsMap.set(
2678
2725
  path,
2679
2726
  /** @type {FileSystemInfoEntry | null} */ (cache)
2680
2727
  );
@@ -2690,7 +2737,7 @@ class FileSystemInfo {
2690
2737
  }
2691
2738
  jobError();
2692
2739
  } else {
2693
- fileTimestamps.set(
2740
+ fileTimestampsMap.set(
2694
2741
  path,
2695
2742
  /** @type {FileSystemInfoEntry} */
2696
2743
  (entry)
@@ -2701,6 +2748,7 @@ class FileSystemInfo {
2701
2748
  }
2702
2749
  }
2703
2750
  break;
2751
+ }
2704
2752
  }
2705
2753
  };
2706
2754
  if (files) {
@@ -2715,8 +2763,10 @@ class FileSystemInfo {
2715
2763
  return;
2716
2764
  }
2717
2765
  switch (mode) {
2718
- case 3:
2766
+ case 3: {
2719
2767
  this._contextTshsOptimization.optimize(snapshot, capturedDirectories);
2768
+ if (contextTshs === undefined) contextTshs = new Map();
2769
+ const contextTshsMap = contextTshs;
2720
2770
  for (const path of capturedDirectories) {
2721
2771
  const cache = this._contextTshs.get(path);
2722
2772
  /** @type {ResolvedContextTimestampAndHash | null | undefined} */
@@ -2725,7 +2775,7 @@ class FileSystemInfo {
2725
2775
  cache !== undefined &&
2726
2776
  (resolved = getResolvedTimestamp(cache)) !== undefined
2727
2777
  ) {
2728
- contextTshs.set(path, resolved);
2778
+ contextTshsMap.set(path, resolved);
2729
2779
  } else {
2730
2780
  jobs++;
2731
2781
  /**
@@ -2743,7 +2793,7 @@ class FileSystemInfo {
2743
2793
  }
2744
2794
  jobError();
2745
2795
  } else {
2746
- contextTshs.set(
2796
+ contextTshsMap.set(
2747
2797
  path,
2748
2798
  /** @type {ResolvedContextTimestampAndHash | null} */
2749
2799
  (entry)
@@ -2759,11 +2809,14 @@ class FileSystemInfo {
2759
2809
  }
2760
2810
  }
2761
2811
  break;
2762
- case 2:
2812
+ }
2813
+ case 2: {
2763
2814
  this._contextHashesOptimization.optimize(
2764
2815
  snapshot,
2765
2816
  capturedDirectories
2766
2817
  );
2818
+ if (contextHashes === undefined) contextHashes = new Map();
2819
+ const contextHashesMap = contextHashes;
2767
2820
  for (const path of capturedDirectories) {
2768
2821
  const cache = this._contextHashes.get(path);
2769
2822
  /** @type {undefined | null | string} */
@@ -2772,7 +2825,7 @@ class FileSystemInfo {
2772
2825
  cache !== undefined &&
2773
2826
  (resolved = getResolvedHash(cache)) !== undefined
2774
2827
  ) {
2775
- contextHashes.set(path, resolved);
2828
+ contextHashesMap.set(path, resolved);
2776
2829
  } else {
2777
2830
  jobs++;
2778
2831
  /**
@@ -2789,7 +2842,7 @@ class FileSystemInfo {
2789
2842
  }
2790
2843
  jobError();
2791
2844
  } else {
2792
- contextHashes.set(path, /** @type {string} */ (entry));
2845
+ contextHashesMap.set(path, /** @type {string} */ (entry));
2793
2846
  jobDone();
2794
2847
  }
2795
2848
  };
@@ -2801,11 +2854,14 @@ class FileSystemInfo {
2801
2854
  }
2802
2855
  }
2803
2856
  break;
2804
- case 1:
2857
+ }
2858
+ case 1: {
2805
2859
  this._contextTimestampsOptimization.optimize(
2806
2860
  snapshot,
2807
2861
  capturedDirectories
2808
2862
  );
2863
+ if (contextTimestamps === undefined) contextTimestamps = new Map();
2864
+ const contextTimestampsMap = contextTimestamps;
2809
2865
  for (const path of capturedDirectories) {
2810
2866
  const cache = this._contextTimestamps.get(path);
2811
2867
  if (cache === "ignore") continue;
@@ -2814,14 +2870,8 @@ class FileSystemInfo {
2814
2870
  cache === undefined || isExistenceOnly(cache)
2815
2871
  ? undefined
2816
2872
  : /** @type {ContextFileSystemInfoEntry | null} */ (cache);
2817
- // A non-null cache entry without `timestampHash` cannot be
2818
- // used to populate the snapshot — the snapshot would then
2819
- // miss directory-change detection, since validity relies on
2820
- // `timestampHash`. Re-read the directory in that case.
2821
2873
  const cacheLacksHash =
2822
- usableCache !== undefined &&
2823
- usableCache !== null &&
2824
- usableCache.timestampHash === undefined;
2874
+ contextCacheEntryLacksTimestampHash(usableCache);
2825
2875
  /** @type {undefined | null | ResolvedContextFileSystemInfoEntry} */
2826
2876
  let resolved;
2827
2877
  if (
@@ -2829,7 +2879,7 @@ class FileSystemInfo {
2829
2879
  !cacheLacksHash &&
2830
2880
  (resolved = getResolvedTimestamp(usableCache)) !== undefined
2831
2881
  ) {
2832
- contextTimestamps.set(path, resolved);
2882
+ contextTimestampsMap.set(path, resolved);
2833
2883
  } else {
2834
2884
  jobs++;
2835
2885
  /**
@@ -2847,7 +2897,7 @@ class FileSystemInfo {
2847
2897
  }
2848
2898
  jobError();
2849
2899
  } else {
2850
- contextTimestamps.set(
2900
+ contextTimestampsMap.set(
2851
2901
  path,
2852
2902
  /** @type {ResolvedContextFileSystemInfoEntry | null} */
2853
2903
  (entry)
@@ -2867,6 +2917,7 @@ class FileSystemInfo {
2867
2917
  }
2868
2918
  }
2869
2919
  break;
2920
+ }
2870
2921
  }
2871
2922
  };
2872
2923
  if (directories) {
@@ -2883,11 +2934,13 @@ class FileSystemInfo {
2883
2934
  return;
2884
2935
  }
2885
2936
  this._missingExistenceOptimization.optimize(snapshot, capturedMissing);
2937
+ if (missingExistence === undefined) missingExistence = new Map();
2938
+ const missingExistenceMap = missingExistence;
2886
2939
  for (const path of capturedMissing) {
2887
2940
  const cache = this._fileTimestamps.get(path);
2888
2941
  if (cache !== undefined && !isExistenceOnly(cache)) {
2889
2942
  if (cache !== "ignore") {
2890
- missingExistence.set(path, Boolean(cache));
2943
+ missingExistenceMap.set(path, Boolean(cache));
2891
2944
  }
2892
2945
  } else {
2893
2946
  jobs++;
@@ -2900,7 +2953,7 @@ class FileSystemInfo {
2900
2953
  }
2901
2954
  jobError();
2902
2955
  } else {
2903
- missingExistence.set(path, Boolean(entry));
2956
+ missingExistenceMap.set(path, Boolean(entry));
2904
2957
  jobDone();
2905
2958
  }
2906
2959
  });
@@ -2911,6 +2964,10 @@ class FileSystemInfo {
2911
2964
  processCapturedMissing(captureNonManaged(missing, managedMissing));
2912
2965
  }
2913
2966
  this._managedItemInfoOptimization.optimize(snapshot, managedItems);
2967
+ if (managedItems.size !== 0 && managedItemInfo === undefined) {
2968
+ managedItemInfo = new Map();
2969
+ }
2970
+ const managedItemInfoMap = managedItemInfo;
2914
2971
  for (const path of managedItems) {
2915
2972
  const cache = this._managedItems.get(path);
2916
2973
  if (cache !== undefined) {
@@ -2919,7 +2976,7 @@ class FileSystemInfo {
2919
2976
  } else if (cache === "*nested") {
2920
2977
  managedMissing.add(join(this.fs, path, "package.json"));
2921
2978
  }
2922
- managedItemInfo.set(path, cache);
2979
+ /** @type {ManagedItemInfo} */ (managedItemInfoMap).set(path, cache);
2923
2980
  } else {
2924
2981
  jobs++;
2925
2982
  this.managedItemQueue.add(path, (err, entry) => {
@@ -2936,7 +2993,10 @@ class FileSystemInfo {
2936
2993
  } else if (cache === "*nested") {
2937
2994
  managedMissing.add(join(this.fs, path, "package.json"));
2938
2995
  }
2939
- managedItemInfo.set(path, entry);
2996
+ /** @type {ManagedItemInfo} */ (managedItemInfoMap).set(
2997
+ path,
2998
+ entry
2999
+ );
2940
3000
  jobDone();
2941
3001
  } else {
2942
3002
  // Fallback to normal snapshotting
@@ -3396,13 +3456,8 @@ class FileSystemInfo {
3396
3456
  cache === undefined || isExistenceOnly(cache)
3397
3457
  ? undefined
3398
3458
  : /** @type {ContextFileSystemInfoEntry | null} */ (cache);
3399
- // A non-null cache entry that lacks `timestampHash` while the
3400
- // snapshot has one cannot be used either; we re-read the
3401
- // directory through the disk-backed queue instead.
3402
3459
  const cacheLacksHash =
3403
- usableCache !== undefined &&
3404
- usableCache !== null &&
3405
- usableCache.timestampHash === undefined &&
3460
+ contextCacheEntryLacksTimestampHash(usableCache) &&
3406
3461
  ts !== null &&
3407
3462
  ts.timestampHash !== undefined;
3408
3463
  /** @type {undefined | null | ResolvedContextFileSystemInfoEntry} */
@@ -3513,9 +3568,7 @@ class FileSystemInfo {
3513
3568
  ? undefined
3514
3569
  : /** @type {ContextFileSystemInfoEntry | null} */ (cache);
3515
3570
  const cacheLacksHash =
3516
- usableCache !== undefined &&
3517
- usableCache !== null &&
3518
- usableCache.timestampHash === undefined &&
3571
+ contextCacheEntryLacksTimestampHash(usableCache) &&
3519
3572
  tsh !== null &&
3520
3573
  tsh.timestampHash !== undefined;
3521
3574
  /** @type {undefined | null | ResolvedContextFileSystemInfoEntry} */
@@ -4085,7 +4138,7 @@ class FileSystemInfo {
4085
4138
  /**
4086
4139
  * Returns reduced hash.
4087
4140
  * @param {string[]} files files
4088
- * @param {(string | ContextHash)[]} fileHashes hashes
4141
+ * @param {(string | ContextHash | null)[]} fileHashes hashes
4089
4142
  * @returns {ContextHash} reduced hash
4090
4143
  */
4091
4144
  reduce: (files, fileHashes) => {
@@ -4095,10 +4148,13 @@ class FileSystemInfo {
4095
4148
 
4096
4149
  for (const file of files) hash.update(file);
4097
4150
  for (const entry of fileHashes) {
4098
- if (typeof entry === "string") {
4151
+ // null for unsupported entry kinds (FIFO, socket); skip like the tsh reduce
4152
+ if (!entry) {
4153
+ continue;
4154
+ } else if (typeof entry === "string") {
4099
4155
  hash.update(entry);
4100
4156
  } else {
4101
- hash.update(entry.hash);
4157
+ if (entry.hash) hash.update(entry.hash);
4102
4158
  if (entry.symlinks) {
4103
4159
  if (symlinks === undefined) symlinks = new Set();
4104
4160
  addAll(entry.symlinks, symlinks);
@@ -7,6 +7,7 @@
7
7
 
8
8
  const asyncLib = require("neo-async");
9
9
  const Queue = require("./util/Queue");
10
+ const createHash = require("./util/createHash");
10
11
 
11
12
  /** @typedef {import("./Compiler")} Compiler */
12
13
  /** @typedef {import("./DependenciesBlock")} DependenciesBlock */
@@ -16,12 +17,32 @@ const Queue = require("./util/Queue");
16
17
  /** @typedef {import("./ExportsInfo")} ExportsInfo */
17
18
  /** @typedef {import("./ExportsInfo").ExportInfoName} ExportInfoName */
18
19
  /** @typedef {import("./ExportsInfo").RestoreProvidedData} RestoreProvidedData */
20
+ /** @typedef {import("../declarations/WebpackOptions").HashFunction} HashFunction */
21
+ /** @typedef {import("./LazyBarrel")} LazyBarrelController */
19
22
  /** @typedef {import("./Module")} Module */
20
23
  /** @typedef {import("./Module").BuildInfo} BuildInfo */
21
24
 
22
25
  const PLUGIN_NAME = "FlagDependencyExportsPlugin";
23
26
  const PLUGIN_LOGGER_NAME = `webpack.${PLUGIN_NAME}`;
24
27
 
28
+ /** @typedef {{ etag: string, data: RestoreProvidedData }} MemCacheEntry */
29
+
30
+ /**
31
+ * @param {Module} module the module
32
+ * @param {LazyBarrelController} lazyBarrelController the compilation's lazy barrel controller
33
+ * @param {HashFunction} hashFunction hash function for long keys
34
+ * @returns {string} the hash
35
+ */
36
+ const getLazyRequestsHash = (module, lazyBarrelController, hashFunction) => {
37
+ const lazyKeys = lazyBarrelController.getLazyRequests(module);
38
+ if (!lazyKeys) return "";
39
+ const joined = [...lazyKeys].join("|");
40
+ if (joined.length < 100) return joined;
41
+ const hash = createHash(hashFunction);
42
+ hash.update(joined);
43
+ return /** @type {string} */ (hash.digest("hex"));
44
+ };
45
+
25
46
  class FlagDependencyExportsPlugin {
26
47
  /**
27
48
  * Applies the plugin by registering its hooks on the compiler.
@@ -32,6 +53,8 @@ class FlagDependencyExportsPlugin {
32
53
  compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
33
54
  const moduleGraph = compilation.moduleGraph;
34
55
  const cache = compilation.getCache(PLUGIN_NAME);
56
+ const lazyBarrelController = compilation._lazyBarrelController;
57
+ const hashFunction = compilation.outputOptions.hashFunction;
35
58
  compilation.hooks.finishModules.tapAsync(
36
59
  PLUGIN_NAME,
37
60
  (modules, callback) => {
@@ -80,16 +103,28 @@ class FlagDependencyExportsPlugin {
80
103
  return callback();
81
104
  }
82
105
  const memCache = moduleMemCaches && moduleMemCaches.get(module);
83
- const memCacheValue = memCache && memCache.get(this);
84
- if (memCacheValue !== undefined) {
106
+ /** @type {MemCacheEntry | undefined} */
107
+ const memCacheEntry = memCache && memCache.get(this);
108
+ const hash = getLazyRequestsHash(
109
+ module,
110
+ lazyBarrelController,
111
+ hashFunction
112
+ );
113
+ // validated by the still-lazy request keys: reference-change
114
+ // detection cannot invalidate the mem cache when the un-lazied
115
+ // connections are unsafe-cached (they are skipped when comparing
116
+ // references)
117
+ if (memCacheEntry !== undefined && memCacheEntry.etag === hash) {
85
118
  statRestoredFromMemCache++;
86
- exportsInfo.restoreProvided(memCacheValue);
119
+ exportsInfo.restoreProvided(memCacheEntry.data);
87
120
  return callback();
88
121
  }
122
+ const buildHash = /** @type {string} */ (
123
+ /** @type {BuildInfo} */ (module.buildInfo).hash
124
+ );
89
125
  cache.get(
90
126
  module.identifier(),
91
- /** @type {BuildInfo} */
92
- (module.buildInfo).hash,
127
+ hash ? `${buildHash}|${hash}` : buildHash,
93
128
  (err, result) => {
94
129
  if (err) return callback(err);
95
130
 
@@ -421,13 +456,25 @@ class FlagDependencyExportsPlugin {
421
456
  .getRestoreProvidedData();
422
457
  const memCache =
423
458
  moduleMemCaches && moduleMemCaches.get(module);
459
+ const hash = getLazyRequestsHash(
460
+ module,
461
+ lazyBarrelController,
462
+ hashFunction
463
+ );
424
464
  if (memCache) {
425
- memCache.set(this, cachedData);
465
+ /** @type {MemCacheEntry} */
466
+ const entry = {
467
+ etag: hash,
468
+ data: cachedData
469
+ };
470
+ memCache.set(this, entry);
426
471
  }
472
+ const buildHash = /** @type {string} */ (
473
+ /** @type {BuildInfo} */ (module.buildInfo).hash
474
+ );
427
475
  cache.store(
428
476
  module.identifier(),
429
- /** @type {BuildInfo} */
430
- (module.buildInfo).hash,
477
+ hash ? `${buildHash}|${hash}` : buildHash,
431
478
  cachedData,
432
479
  callback
433
480
  );