@depup/webpack 5.111.1-depup.2 → 5.112.0-depup.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 (775) hide show
  1. package/README.md +4 -8
  2. package/changes.json +3 -19
  3. package/lib/Chunk.js +3 -966
  4. package/lib/Compilation.js +224 -106
  5. package/lib/Compiler.js +19 -19
  6. package/lib/Dependency.js +3 -551
  7. package/lib/DependencyTemplate.js +3 -70
  8. package/lib/EntryPlugin.js +3 -68
  9. package/lib/Entrypoint.js +3 -121
  10. package/lib/ExternalsPlugin.js +3 -92
  11. package/lib/FileSystemInfo.js +3 -4629
  12. package/lib/InitFragment.js +3 -204
  13. package/lib/LibraryTemplatePlugin.js +3 -46
  14. package/lib/ModuleFilenameHelpers.js +3 -400
  15. package/lib/ModuleNotFoundError.js +2 -2
  16. package/lib/MultiCompiler.js +37 -8
  17. package/lib/NormalModule.js +3 -2242
  18. package/lib/NullFactory.js +3 -22
  19. package/lib/ProgressPlugin.js +3 -908
  20. package/lib/RawModule.js +3 -197
  21. package/lib/RequestShortener.js +3 -37
  22. package/lib/SingleEntryPlugin.js +1 -1
  23. package/lib/WebpackError.js +2 -2
  24. package/lib/asset/AssetBytesGenerator.js +8 -8
  25. package/lib/asset/AssetBytesParser.js +3 -3
  26. package/lib/asset/AssetGenerator.js +36 -22
  27. package/lib/asset/AssetModule.js +2 -2
  28. package/lib/asset/AssetModulesPlugin.js +6 -9
  29. package/lib/asset/AssetParser.js +3 -3
  30. package/lib/asset/AssetSourceGenerator.js +8 -8
  31. package/lib/asset/AssetSourceParser.js +3 -3
  32. package/lib/asset/RawDataUrlModule.js +17 -10
  33. package/lib/asset/WebManifestGenerator.js +7 -7
  34. package/lib/asset/WebManifestParser.js +5 -5
  35. package/lib/async-modules/AsyncModuleHelpers.js +6 -5
  36. package/lib/async-modules/AwaitDependenciesInitFragment.js +4 -4
  37. package/lib/async-modules/InferAsyncModulesPlugin.js +4 -3
  38. package/lib/async-modules/isGeneratorLowered.js +3 -3
  39. package/lib/bun/BunTargetPlugin.js +1 -1
  40. package/lib/cache/AddBuildDependenciesPlugin.js +2 -19
  41. package/lib/{Cache.js → cache/Cache.js} +1 -1
  42. package/lib/{CacheFacade.js → cache/CacheFacade.js} +5 -5
  43. package/lib/cache/IdleFileCachePlugin.js +2 -2
  44. package/lib/cache/MemoryCachePlugin.js +2 -2
  45. package/lib/cache/MemoryWithGcCachePlugin.js +2 -2
  46. package/lib/cache/PackFileCacheStrategy.js +8 -10
  47. package/lib/cache/ResolverCachePlugin.js +8 -4
  48. package/lib/cache/mergeEtags.js +1 -1
  49. package/lib/{OptionsApply.js → config/OptionsApply.js} +3 -3
  50. package/lib/{PlatformPlugin.js → config/PlatformPlugin.js} +2 -2
  51. package/lib/{WebpackOptionsApply.js → config/WebpackOptionsApply.js} +217 -200
  52. package/lib/{WebpackOptionsDefaulter.js → config/WebpackOptionsDefaulter.js} +3 -3
  53. package/lib/config/browserslistTargetHandler.js +1 -1
  54. package/lib/{cli.js → config/cli.js} +5 -158
  55. package/lib/config/defaults.js +144 -48
  56. package/lib/config/getClaimedAssetTypes.js +21 -13
  57. package/lib/config/normalization.js +18 -7
  58. package/lib/config/target.js +10 -0
  59. package/lib/container/ContainerEntryDependency.js +1 -1
  60. package/lib/container/ContainerEntryModule.js +13 -11
  61. package/lib/container/ContainerEntryModuleFactory.js +2 -2
  62. package/lib/container/ContainerExposedDependency.js +1 -1
  63. package/lib/container/ContainerPlugin.js +178 -5
  64. package/lib/container/ContainerReferencePlugin.js +75 -14
  65. package/lib/container/FallbackDependency.js +1 -1
  66. package/lib/container/FallbackItemDependency.js +1 -1
  67. package/lib/container/FallbackModule.js +12 -10
  68. package/lib/container/FallbackModuleFactory.js +2 -2
  69. package/lib/container/HoistContainerReferencesPlugin.js +10 -11
  70. package/lib/container/ModuleFederationPlugin.js +306 -7
  71. package/lib/container/RemoteModule.js +14 -10
  72. package/lib/container/RemoteRuntimeModule.js +5 -5
  73. package/lib/container/RemoteToExternalDependency.js +1 -1
  74. package/lib/container/moduleFederationHooks.js +1 -1
  75. package/lib/context/ContextModule.js +36 -25
  76. package/lib/context/ContextModuleFactory.js +13 -10
  77. package/lib/context/ContextReplacementPlugin.js +3 -3
  78. package/lib/css/CssGenerator.js +38 -31
  79. package/lib/css/CssInjectStyleRuntimeModule.js +36 -30
  80. package/lib/css/CssLoadingRuntimeModule.js +77 -44
  81. package/lib/css/CssModule.js +27 -29
  82. package/lib/css/CssModulesPlugin.js +128 -44
  83. package/lib/css/CssParser.js +682 -291
  84. package/lib/css/CssServerStylesRuntimeModule.js +3 -3
  85. package/lib/css/cssMinify.js +110 -37
  86. package/lib/css/data.js +6985 -5125
  87. package/lib/css/syntax-parser.js +19873 -0
  88. package/lib/css/syntax-printer.js +6037 -0
  89. package/lib/css/syntax.js +37 -18686
  90. package/lib/debug/ProfilingPlugin.js +52 -19
  91. package/lib/{DefinePlugin.js → define/DefinePlugin.js} +407 -41
  92. package/lib/{DotenvPlugin.js → define/DotenvPlugin.js} +9 -9
  93. package/lib/{EnvironmentPlugin.js → define/EnvironmentPlugin.js} +2 -2
  94. package/lib/deno/DenoTargetPlugin.js +1 -1
  95. package/lib/dependencies/ConstDependency.js +3 -120
  96. package/lib/dependencies/ContextElementDependency.js +5 -172
  97. package/lib/dependencies/NullDependency.js +3 -37
  98. package/lib/dependencies/{AMDDefineDependency.js → amd/AMDDefineDependency.js} +12 -11
  99. package/lib/dependencies/{AMDDefineDependencyParserPlugin.js → amd/AMDDefineDependencyParserPlugin.js} +10 -10
  100. package/lib/dependencies/{AMDPlugin.js → amd/AMDPlugin.js} +11 -11
  101. package/lib/dependencies/{AMDRequireArrayDependency.js → amd/AMDRequireArrayDependency.js} +15 -13
  102. package/lib/dependencies/{AMDRequireContextDependency.js → amd/AMDRequireContextDependency.js} +11 -10
  103. package/lib/dependencies/{AMDRequireDependenciesBlock.js → amd/AMDRequireDependenciesBlock.js} +7 -6
  104. package/lib/dependencies/{AMDRequireDependenciesBlockParserPlugin.js → amd/AMDRequireDependenciesBlockParserPlugin.js} +10 -10
  105. package/lib/dependencies/{AMDRequireDependency.js → amd/AMDRequireDependency.js} +13 -12
  106. package/lib/dependencies/{AMDRequireItemDependency.js → amd/AMDRequireItemDependency.js} +8 -7
  107. package/lib/dependencies/{AMDRuntimeModules.js → amd/AMDRuntimeModules.js} +3 -3
  108. package/lib/dependencies/{LocalModule.js → amd/LocalModule.js} +8 -4
  109. package/lib/dependencies/{LocalModuleDependency.js → amd/LocalModuleDependency.js} +17 -10
  110. package/lib/dependencies/{LocalModulesHelpers.js → amd/LocalModulesHelpers.js} +1 -1
  111. package/lib/dependencies/{RequireJsStuffPlugin.js → amd/RequireJsStuffPlugin.js} +9 -9
  112. package/lib/dependencies/{UnsupportedDependency.js → amd/UnsupportedDependency.js} +11 -10
  113. package/lib/dependencies/{CommonJsDependencyHelpers.js → commonjs/CommonJsDependencyHelpers.js} +8 -9
  114. package/lib/dependencies/{CommonJsExportRequireDependency.js → commonjs/CommonJsExportRequireDependency.js} +166 -33
  115. package/lib/dependencies/{CommonJsExportsDependency.js → commonjs/CommonJsExportsDependency.js} +15 -14
  116. package/lib/dependencies/{CommonJsExportsParserPlugin.js → commonjs/CommonJsExportsParserPlugin.js} +138 -61
  117. package/lib/dependencies/{CommonJsFullRequireDependency.js → commonjs/CommonJsFullRequireDependency.js} +32 -24
  118. package/lib/dependencies/{CommonJsImportsParserPlugin.js → commonjs/CommonJsImportsParserPlugin.js} +35 -30
  119. package/lib/dependencies/{CommonJsObjectExportDependency.js → commonjs/CommonJsObjectExportDependency.js} +13 -12
  120. package/lib/dependencies/{CommonJsPlugin.js → commonjs/CommonJsPlugin.js} +47 -35
  121. package/lib/dependencies/{CommonJsRequireContextDependency.js → commonjs/CommonJsRequireContextDependency.js} +15 -14
  122. package/lib/dependencies/{CommonJsRequireDependency.js → commonjs/CommonJsRequireDependency.js} +33 -25
  123. package/lib/dependencies/{CommonJsSelfReferenceDependency.js → commonjs/CommonJsSelfReferenceDependency.js} +17 -16
  124. package/lib/dependencies/{ModuleDecoratorDependency.js → commonjs/ModuleDecoratorDependency.js} +16 -15
  125. package/lib/dependencies/{RequireEnsureDependenciesBlock.js → commonjs/RequireEnsureDependenciesBlock.js} +8 -7
  126. package/lib/dependencies/{RequireEnsureDependenciesBlockParserPlugin.js → commonjs/RequireEnsureDependenciesBlockParserPlugin.js} +5 -5
  127. package/lib/dependencies/{RequireEnsureDependency.js → commonjs/RequireEnsureDependency.js} +13 -12
  128. package/lib/dependencies/{RequireEnsureItemDependency.js → commonjs/RequireEnsureItemDependency.js} +7 -6
  129. package/lib/dependencies/{RequireEnsurePlugin.js → commonjs/RequireEnsurePlugin.js} +8 -8
  130. package/lib/dependencies/{RequireHeaderDependency.js → commonjs/RequireHeaderDependency.js} +14 -13
  131. package/lib/dependencies/{RequireIncludeDependency.js → commonjs/RequireIncludeDependency.js} +13 -12
  132. package/lib/dependencies/{RequireIncludeDependencyParserPlugin.js → commonjs/RequireIncludeDependencyParserPlugin.js} +3 -27
  133. package/lib/dependencies/{RequireIncludePlugin.js → commonjs/RequireIncludePlugin.js} +4 -4
  134. package/lib/dependencies/{RequireResolveContextDependency.js → commonjs/RequireResolveContextDependency.js} +11 -10
  135. package/lib/dependencies/{RequireResolveDependency.js → commonjs/RequireResolveDependency.js} +12 -11
  136. package/lib/dependencies/{RequireResolveHeaderDependency.js → commonjs/RequireResolveHeaderDependency.js} +13 -12
  137. package/lib/dependencies/commonjs/TopLevelThisParserPlugin.js +59 -0
  138. package/lib/dependencies/{ContextDependency.js → context/ContextDependency.js} +15 -14
  139. package/lib/dependencies/{ContextDependencyHelpers.js → context/ContextDependencyHelpers.js} +31 -9
  140. package/lib/dependencies/{ContextDependencyTemplateAsId.js → context/ContextDependencyTemplateAsId.js} +3 -3
  141. package/lib/dependencies/{ContextDependencyTemplateAsRequireCall.js → context/ContextDependencyTemplateAsRequireCall.js} +3 -3
  142. package/lib/dependencies/context/ContextElementDependency.js +198 -0
  143. package/lib/dependencies/{ImportMetaContextDependency.js → context/ImportMetaContextDependency.js} +7 -6
  144. package/lib/dependencies/{ImportMetaContextDependencyParserPlugin.js → context/ImportMetaContextDependencyParserPlugin.js} +9 -9
  145. package/lib/dependencies/{ImportMetaContextPlugin.js → context/ImportMetaContextPlugin.js} +5 -5
  146. package/lib/dependencies/{ImportMetaGlobDependency.js → context/ImportMetaGlobDependency.js} +7 -6
  147. package/lib/dependencies/{ImportMetaGlobDependencyParserPlugin.js → context/ImportMetaGlobDependencyParserPlugin.js} +4 -4
  148. package/lib/dependencies/{ImportMetaGlobHelpers.js → context/ImportMetaGlobHelpers.js} +9 -9
  149. package/lib/dependencies/{RequireContextDependency.js → context/RequireContextDependency.js} +7 -6
  150. package/lib/dependencies/{RequireContextDependencyParserPlugin.js → context/RequireContextDependencyParserPlugin.js} +2 -2
  151. package/lib/dependencies/{RequireContextPlugin.js → context/RequireContextPlugin.js} +5 -5
  152. package/lib/dependencies/{CachedConstDependency.js → core/CachedConstDependency.js} +12 -11
  153. package/lib/dependencies/core/ConstDependency.js +131 -0
  154. package/lib/dependencies/{ImportPhase.js → core/ImportPhase.js} +5 -4
  155. package/lib/dependencies/{ModuleDependency.js → core/ModuleDependency.js} +10 -7
  156. package/lib/dependencies/{ModuleDependencyTemplateAsId.js → core/ModuleDependencyTemplateAsId.js} +3 -3
  157. package/lib/dependencies/{ModuleDependencyTemplateAsRequireId.js → core/ModuleDependencyTemplateAsRequireId.js} +2 -2
  158. package/lib/dependencies/{ModuleInitFragmentDependency.js → core/ModuleInitFragmentDependency.js} +10 -9
  159. package/lib/dependencies/core/NullDependency.js +44 -0
  160. package/lib/dependencies/{RuntimeRequirementsDependency.js → core/RuntimeRequirementsDependency.js} +10 -9
  161. package/lib/dependencies/{StaticExportsDependency.js → core/StaticExportsDependency.js} +15 -8
  162. package/lib/dependencies/{CssIcssExportDependency.js → css/CssIcssExportDependency.js} +369 -92
  163. package/lib/dependencies/{CssIcssImportDependency.js → css/CssIcssImportDependency.js} +23 -16
  164. package/lib/dependencies/{CssIcssSymbolDependency.js → css/CssIcssSymbolDependency.js} +13 -12
  165. package/lib/dependencies/{CssImportDependency.js → css/CssImportDependency.js} +15 -11
  166. package/lib/dependencies/{CssUrlDependency.js → css/CssUrlDependency.js} +23 -16
  167. package/lib/dependencies/{CreateRequireParserPlugin.js → esm/CreateRequireParserPlugin.js} +9 -9
  168. package/lib/dependencies/{HarmonyAcceptDependency.js → esm/ESMAcceptDependency.js} +41 -38
  169. package/lib/dependencies/esm/ESMAcceptImportDependency.js +39 -0
  170. package/lib/dependencies/{HarmonyCompatibilityDependency.js → esm/ESMCompatibilityDependency.js} +29 -21
  171. package/lib/dependencies/{HarmonyDetectionParserPlugin.js → esm/ESMDetectionParserPlugin.js} +19 -17
  172. package/lib/dependencies/{HarmonyEvaluatedImportSpecifierDependency.js → esm/ESMEvaluatedImportSpecifierDependency.js} +33 -30
  173. package/lib/dependencies/{HarmonyExportDependencyParserPlugin.js → esm/ESMExportDependencyParserPlugin.js} +60 -89
  174. package/lib/dependencies/{HarmonyExportExpressionDependency.js → esm/ESMExportExpressionDependency.js} +80 -45
  175. package/lib/dependencies/{HarmonyExportHeaderDependency.js → esm/ESMExportHeaderDependency.js} +17 -15
  176. package/lib/dependencies/esm/ESMExportImportedSideEffectDependency.js +37 -0
  177. package/lib/dependencies/{HarmonyExportImportedSpecifierDependency.js → esm/ESMExportImportedSpecifierDependency.js} +133 -118
  178. package/lib/dependencies/{HarmonyExportInitFragment.js → esm/ESMExportInitFragment.js} +48 -30
  179. package/lib/dependencies/{HarmonyExportSpecifierDependency.js → esm/ESMExportSpecifierDependency.js} +60 -36
  180. package/lib/dependencies/{HarmonyExports.js → esm/ESMExports.js} +4 -4
  181. package/lib/dependencies/{HarmonyImportBareSideEffectDependency.js → esm/ESMImportBareSideEffectDependency.js} +21 -13
  182. package/lib/dependencies/{HarmonyImportDependency.js → esm/ESMImportDependency.js} +74 -71
  183. package/lib/dependencies/{HarmonyImportDependencyParserPlugin.js → esm/ESMImportDependencyParserPlugin.js} +99 -84
  184. package/lib/dependencies/{HarmonyImportGuard.js → esm/ESMImportGuard.js} +26 -29
  185. package/lib/dependencies/{HarmonyImportSideEffectDependency.js → esm/ESMImportSideEffectDependency.js} +83 -39
  186. package/lib/dependencies/{HarmonyImportSpecifierDependency.js → esm/ESMImportSpecifierDependency.js} +94 -59
  187. package/lib/dependencies/esm/ESMModulesPlugin.js +207 -0
  188. package/lib/dependencies/{HarmonyTopLevelThisParserPlugin.js → esm/ESMTopLevelThisParserPlugin.js} +7 -7
  189. package/lib/dependencies/{TopLevelAwaitDependency.js → esm/TopLevelAwaitDependency.js} +12 -11
  190. package/lib/dependencies/{DynamicExports.js → helpers/DynamicExports.js} +2 -2
  191. package/lib/{util → dependencies/helpers}/chainedImports.js +5 -5
  192. package/lib/dependencies/{processExportInfo.js → helpers/processExportInfo.js} +4 -4
  193. package/lib/{util → dependencies/helpers}/traverseDestructuringAssignmentProperties.js +1 -1
  194. package/lib/dependencies/{ImportMetaHotAcceptDependency.js → hmr/ImportMetaHotAcceptDependency.js} +8 -7
  195. package/lib/dependencies/{ImportMetaHotDeclineDependency.js → hmr/ImportMetaHotDeclineDependency.js} +8 -7
  196. package/lib/dependencies/{ModuleHotAcceptDependency.js → hmr/ModuleHotAcceptDependency.js} +8 -7
  197. package/lib/dependencies/{ModuleHotDeclineDependency.js → hmr/ModuleHotDeclineDependency.js} +8 -7
  198. package/lib/dependencies/{HtmlEntryDependency.js → html/HtmlEntryDependency.js} +51 -141
  199. package/lib/dependencies/{HtmlInlineHtmlDependency.js → html/HtmlInlineHtmlDependency.js} +13 -12
  200. package/lib/dependencies/{HtmlInlineScriptDependency.js → html/HtmlInlineScriptDependency.js} +69 -19
  201. package/lib/dependencies/{HtmlInlineStyleDependency.js → html/HtmlInlineStyleDependency.js} +50 -15
  202. package/lib/dependencies/{HtmlSourceDependency.js → html/HtmlSourceDependency.js} +23 -16
  203. package/lib/dependencies/{ImportContextDependency.js → import/ImportContextDependency.js} +24 -10
  204. package/lib/dependencies/{ImportDependency.js → import/ImportDependency.js} +26 -18
  205. package/lib/dependencies/{ImportEagerDependency.js → import/ImportEagerDependency.js} +18 -10
  206. package/lib/dependencies/{ImportParserPlugin.js → import/ImportParserPlugin.js} +20 -20
  207. package/lib/dependencies/{ImportPlugin.js → import/ImportPlugin.js} +4 -4
  208. package/lib/dependencies/{ImportWeakDependency.js → import/ImportWeakDependency.js} +18 -10
  209. package/lib/dependencies/{importOptionsCheck.js → import/importOptionsCheck.js} +2 -2
  210. package/lib/dependencies/{BuildTimeConstDependency.js → import-meta/BuildTimeConstDependency.js} +12 -11
  211. package/lib/dependencies/{ImportMetaMainDependency.js → import-meta/ImportMetaMainDependency.js} +12 -11
  212. package/lib/dependencies/{ImportMetaPlugin.js → import-meta/ImportMetaPlugin.js} +119 -98
  213. package/lib/dependencies/{SystemPlugin.js → system/SystemPlugin.js} +11 -38
  214. package/lib/dependencies/{SystemRuntimeModule.js → system/SystemRuntimeModule.js} +3 -3
  215. package/lib/dependencies/{ImportMetaResolveDependency.js → url/ImportMetaResolveDependency.js} +9 -8
  216. package/lib/dependencies/{URLContextDependency.js → url/URLContextDependency.js} +11 -10
  217. package/lib/dependencies/{URLDependency.js → url/URLDependency.js} +28 -20
  218. package/lib/{url → dependencies/url}/URLParserPlugin.js +16 -18
  219. package/lib/dependencies/{URLPlugin.js → url/URLPlugin.js} +6 -7
  220. package/lib/dependencies/{WebAssemblyExportImportedDependency.js → wasm/WebAssemblyExportImportedDependency.js} +18 -11
  221. package/lib/dependencies/{WebAssemblyImportDependency.js → wasm/WebAssemblyImportDependency.js} +19 -12
  222. package/lib/dependencies/{CreateScriptUrlDependency.js → worker/CreateScriptUrlDependency.js} +12 -11
  223. package/lib/dependencies/{WorkerAndWorkletPlugin.js → worker/WorkerAndWorkletPlugin.js} +31 -33
  224. package/lib/dependencies/{WorkerDependency.js → worker/WorkerDependency.js} +22 -15
  225. package/lib/dependencies/{WorkletDependency.js → worker/WorkletDependency.js} +19 -18
  226. package/lib/{EvalDevToolModulePlugin.js → devtool/EvalDevToolModulePlugin.js} +20 -6
  227. package/lib/{EvalSourceMapDevToolPlugin.js → devtool/EvalSourceMapDevToolPlugin.js} +32 -24
  228. package/lib/devtool/ModuleFilenameHelpers.js +413 -0
  229. package/lib/{SourceMapDevToolModuleOptionsPlugin.js → devtool/SourceMapDevToolModuleOptionsPlugin.js} +10 -3
  230. package/lib/{SourceMapDevToolPlugin.js → devtool/SourceMapDevToolPlugin.js} +154 -26
  231. package/lib/{util → devtool}/generateDebugId.js +1 -1
  232. package/lib/{IgnoreWarningsPlugin.js → diagnostics/IgnoreWarningsPlugin.js} +2 -2
  233. package/lib/{NoEmitOnErrorsPlugin.js → diagnostics/NoEmitOnErrorsPlugin.js} +1 -1
  234. package/lib/diagnostics/WarnCaseSensitiveModulesPlugin.js +64 -0
  235. package/lib/{WarnDeprecatedOptionPlugin.js → diagnostics/WarnDeprecatedOptionPlugin.js} +2 -22
  236. package/lib/diagnostics/WarnNoModeSetPlugin.js +27 -0
  237. package/lib/dll/DelegatedModule.js +20 -18
  238. package/lib/dll/DelegatedModuleFactoryPlugin.js +2 -2
  239. package/lib/dll/DelegatedPlugin.js +1 -1
  240. package/lib/{dependencies → dll}/DelegatedSourceDependency.js +5 -4
  241. package/lib/{dependencies → dll}/DllEntryDependency.js +6 -5
  242. package/lib/dll/DllEntryPlugin.js +3 -3
  243. package/lib/dll/DllModule.js +11 -9
  244. package/lib/dll/DllModuleFactory.js +3 -3
  245. package/lib/dll/DllPlugin.js +18 -6
  246. package/lib/dll/DllReferencePlugin.js +102 -26
  247. package/lib/dll/LibManifestPlugin.js +9 -7
  248. package/lib/electron/ElectronTargetPlugin.js +2 -2
  249. package/lib/{DynamicEntryPlugin.js → entry/DynamicEntryPlugin.js} +3 -3
  250. package/lib/{dependencies → entry}/EntryDependency.js +11 -2
  251. package/lib/{EntryOptionPlugin.js → entry/EntryOptionPlugin.js} +6 -6
  252. package/lib/entry/EntryPlugin.js +75 -0
  253. package/lib/{performance → errors}/AssetsOverSizeLimitWarning.js +2 -2
  254. package/lib/errors/AsyncDependencyToInitialChunkError.js +2 -2
  255. package/lib/errors/BuildCycleError.js +1 -1
  256. package/lib/{WarnCaseSensitiveModulesPlugin.js → errors/CaseSensitiveModulesWarning.js} +4 -56
  257. package/lib/errors/ChunkRenderError.js +1 -1
  258. package/lib/errors/CodeGenerationError.js +1 -1
  259. package/lib/errors/CommentCompilationWarning.js +1 -1
  260. package/lib/errors/ConflictingEntryExportsWarning.js +38 -0
  261. package/lib/{dependencies → errors}/CriticalDependencyWarning.js +4 -3
  262. package/lib/errors/DeprecatedOptionWarning.js +30 -0
  263. package/lib/errors/DllManifestError.js +26 -0
  264. package/lib/{performance → errors}/DuplicatePackagesWarning.js +6 -6
  265. package/lib/{dependencies/HarmonyLinkingError.js → errors/ESMLinkingError.js} +4 -4
  266. package/lib/{performance → errors}/EntrypointsOverSizeLimitWarning.js +2 -2
  267. package/lib/errors/EnvironmentNotSupportAsyncWarning.js +2 -2
  268. package/lib/{ErrorHelpers.js → errors/ErrorHelpers.js} +7 -5
  269. package/lib/errors/ExternalStarReexportError.js +2 -2
  270. package/lib/{library → errors}/FalseIIFEUmdWarning.js +1 -1
  271. package/lib/errors/HookWebpackError.js +4 -4
  272. package/lib/errors/IgnoreErrorModuleFactory.js +3 -3
  273. package/lib/errors/InvalidDependenciesModuleWarning.js +1 -1
  274. package/lib/{optimize → errors}/MinMaxSizeWarning.js +1 -1
  275. package/lib/errors/ModuleBuildError.js +1 -1
  276. package/lib/errors/ModuleDependencyError.js +2 -2
  277. package/lib/errors/ModuleDependencyWarning.js +2 -2
  278. package/lib/errors/ModuleError.js +1 -1
  279. package/lib/errors/ModuleHashingError.js +1 -1
  280. package/lib/errors/ModuleNotFoundError.js +3 -3
  281. package/lib/errors/ModuleParseError.js +1 -1
  282. package/lib/errors/ModuleRestoreError.js +1 -1
  283. package/lib/errors/ModuleStoreError.js +1 -1
  284. package/lib/errors/ModuleWarning.js +1 -1
  285. package/lib/{performance → errors}/NoAsyncChunksWarning.js +1 -1
  286. package/lib/{WarnNoModeSetPlugin.js → errors/NoModeWarning.js} +2 -19
  287. package/lib/errors/NodeStuffInWebError.js +7 -2
  288. package/lib/errors/PathVariableError.js +31 -0
  289. package/lib/errors/RequireIncludeDeprecationWarning.js +40 -0
  290. package/lib/{performance → errors}/RuntimeInLargeChunkWarning.js +1 -1
  291. package/lib/errors/RuntimeModuleGenerationError.js +51 -0
  292. package/lib/errors/SSRManifestAutoPublicPathWarning.js +24 -0
  293. package/lib/errors/SystemImportDeprecationWarning.js +43 -0
  294. package/lib/errors/UnmergeableEntryExportsError.js +34 -0
  295. package/lib/errors/UnsupportedFeatureWarning.js +1 -1
  296. package/lib/{wasm-sync → errors}/UnsupportedWebAssemblyFeatureError.js +1 -1
  297. package/lib/{wasm-sync → errors}/WebAssemblyInInitialChunkError.js +7 -5
  298. package/lib/errors/WebpackError.js +12 -3
  299. package/lib/esm/ExportWebpackRequireRuntimeModule.js +2 -2
  300. package/lib/esm/ModuleChunkFormatPlugin.js +19 -19
  301. package/lib/esm/ModuleChunkLoadingPlugin.js +3 -3
  302. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +8 -8
  303. package/lib/{ExternalModule.js → externals/ExternalModule.js} +79 -55
  304. package/lib/{ExternalModuleFactoryPlugin.js → externals/ExternalModuleFactoryPlugin.js} +41 -39
  305. package/lib/externals/ExternalsPlugin.js +99 -0
  306. package/lib/fs/FileSystemInfo.js +4642 -0
  307. package/lib/{util → fs}/fs.js +22 -9
  308. package/lib/{AsyncDependenciesBlock.js → graph/AsyncDependenciesBlock.js} +27 -4
  309. package/lib/graph/Chunk.js +985 -0
  310. package/lib/{ChunkGraph.js → graph/ChunkGraph.js} +187 -80
  311. package/lib/{ChunkGroup.js → graph/ChunkGroup.js} +11 -3
  312. package/lib/{DependenciesBlock.js → graph/DependenciesBlock.js} +16 -4
  313. package/lib/graph/Dependency.js +628 -0
  314. package/lib/graph/Entrypoint.js +136 -0
  315. package/lib/{ExportsInfo.js → graph/ExportsInfo.js} +130 -82
  316. package/lib/{HotUpdateChunk.js → graph/HotUpdateChunk.js} +8 -0
  317. package/lib/{ModuleGraph.js → graph/ModuleGraph.js} +30 -30
  318. package/lib/{ModuleGraphConnection.js → graph/ModuleGraphConnection.js} +2 -2
  319. package/lib/{buildChunkGraph.js → graph/buildChunkGraph.js} +152 -57
  320. package/lib/{util → graph}/findGraphRoots.js +14 -8
  321. package/lib/graph/isDependencyKind.js +23 -0
  322. package/lib/hmr/HotModuleReplacement.runtime.js +2 -2
  323. package/lib/{HotModuleReplacementPlugin.js → hmr/HotModuleReplacementPlugin.js} +47 -47
  324. package/lib/hmr/HotModuleReplacementRuntimeModule.js +3 -3
  325. package/lib/hmr/JavascriptHotModuleReplacement.runtime.js +10 -8
  326. package/lib/hmr/JavascriptHotModuleReplacementHelper.js +2 -2
  327. package/lib/hmr/LazyCompilationPlugin.js +31 -21
  328. package/lib/html/HtmlGenerator.js +107 -43
  329. package/lib/html/HtmlModule.js +6 -2
  330. package/lib/html/HtmlModulesPlugin.js +172 -76
  331. package/lib/html/HtmlParser.js +503 -153
  332. package/lib/html/builtinEmbeddedRenderer.js +60 -13
  333. package/lib/html/data.js +2 -1
  334. package/lib/html/htmlMinify.js +111 -41
  335. package/lib/html/syntax-parser.js +15796 -0
  336. package/lib/html/syntax-printer.js +1034 -0
  337. package/lib/html/syntax.js +37 -13952
  338. package/lib/html/xmlMinify.js +67 -0
  339. package/lib/ids/ChunkModuleIdRangePlugin.js +2 -2
  340. package/lib/ids/DeterministicModuleIdsPlugin.js +1 -1
  341. package/lib/ids/HashedModuleIdsPlugin.js +31 -4
  342. package/lib/ids/IdHelpers.js +4 -4
  343. package/lib/ids/NaturalChunkIdsPlugin.js +1 -1
  344. package/lib/ids/OccurrenceChunkIdsPlugin.js +6 -5
  345. package/lib/ids/OccurrenceModuleIdsPlugin.js +6 -5
  346. package/lib/{RecordIdsPlugin.js → ids/RecordIdsPlugin.js} +5 -5
  347. package/lib/ids/SyncModuleIdsPlugin.js +3 -3
  348. package/lib/{util → ids}/numberHash.js +1 -1
  349. package/lib/index.js +303 -97
  350. package/lib/{APIPlugin.js → javascript/APIPlugin.js} +25 -25
  351. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +4 -5
  352. package/lib/javascript/BasicEvaluatedExpression.js +4 -4
  353. package/lib/javascript/ChunkHelpers.js +64 -4
  354. package/lib/javascript/CommonJsChunkFormatPlugin.js +4 -7
  355. package/lib/{CompatibilityPlugin.js → javascript/CompatibilityPlugin.js} +7 -7
  356. package/lib/{ConstPlugin.js → javascript/ConstPlugin.js} +74 -7
  357. package/lib/{ExportsInfoApiPlugin.js → javascript/ExportsInfoApiPlugin.js} +5 -5
  358. package/lib/{dependencies → javascript}/ExportsInfoDependency.js +10 -9
  359. package/lib/javascript/JavascriptGenerator.js +17 -17
  360. package/lib/{JavascriptMetaInfoPlugin.js → javascript/JavascriptMetaInfoPlugin.js} +7 -7
  361. package/lib/javascript/JavascriptModule.js +4 -3
  362. package/lib/javascript/JavascriptModulesPlugin.js +440 -211
  363. package/lib/javascript/JavascriptParser.js +220 -134
  364. package/lib/javascript/JavascriptParserHelpers.js +1 -1
  365. package/lib/javascript/MergedEntryExports.js +196 -0
  366. package/lib/javascript/ScopeAnalyzer.js +3840 -5
  367. package/lib/javascript/StartupHelpers.js +6 -6
  368. package/lib/{UseStrictPlugin.js → javascript/UseStrictPlugin.js} +12 -15
  369. package/lib/{dependencies → javascript}/WebpackIsIncludedDependency.js +10 -9
  370. package/lib/{WebpackIsIncludedPlugin.js → javascript/WebpackIsIncludedPlugin.js} +8 -8
  371. package/lib/javascript/data.js +533 -122
  372. package/lib/javascript/jsMinify.js +272 -0
  373. package/lib/javascript/regexp.js +67 -32
  374. package/lib/javascript/syntax-parser.js +18561 -0
  375. package/lib/javascript/syntax-printer-data.js +933 -0
  376. package/lib/javascript/syntax-printer.js +47106 -0
  377. package/lib/javascript/syntax.js +20 -11274
  378. package/lib/json/JsonData.js +1 -1
  379. package/lib/{dependencies → json}/JsonExportsDependency.js +8 -7
  380. package/lib/json/JsonGenerator.js +10 -10
  381. package/lib/json/JsonModule.js +2 -2
  382. package/lib/json/JsonModulesPlugin.js +1 -1
  383. package/lib/json/JsonParser.js +5 -5
  384. package/lib/json/jsonMinify.js +69 -0
  385. package/lib/library/AbstractLibraryPlugin.js +28 -15
  386. package/lib/library/AmdLibraryPlugin.js +4 -4
  387. package/lib/library/AssignLibraryPlugin.js +27 -11
  388. package/lib/library/EnableLibraryPlugin.js +1 -1
  389. package/lib/library/ExportPropertyLibraryPlugin.js +4 -4
  390. package/lib/library/JsonpLibraryPlugin.js +1 -1
  391. package/lib/library/LibraryTemplatePlugin.js +53 -0
  392. package/lib/library/ModuleLibraryPlugin.js +160 -166
  393. package/lib/library/SystemLibraryPlugin.js +6 -8
  394. package/lib/library/UmdLibraryPlugin.js +3 -4
  395. package/lib/{dependencies → loaders}/LoaderDependency.js +3 -3
  396. package/lib/{dependencies → loaders}/LoaderImportDependency.js +9 -3
  397. package/lib/{LoaderOptionsPlugin.js → loaders/LoaderOptionsPlugin.js} +30 -12
  398. package/lib/{dependencies → loaders}/LoaderPlugin.js +2 -2
  399. package/lib/loaders/LoaderRunner.js +31 -21
  400. package/lib/{LoaderTargetPlugin.js → loaders/LoaderTargetPlugin.js} +2 -2
  401. package/lib/logging/Logger.js +7 -9
  402. package/lib/logging/ProgressPlugin.js +957 -0
  403. package/lib/{CodeGenerationResults.js → module/CodeGenerationResults.js} +7 -7
  404. package/lib/{Generator.js → module/Generator.js} +16 -14
  405. package/lib/{Module.js → module/Module.js} +119 -51
  406. package/lib/{ModuleFactory.js → module/ModuleFactory.js} +3 -3
  407. package/lib/module/NormalModule.js +2348 -0
  408. package/lib/{NormalModuleFactory.js → module/NormalModuleFactory.js} +53 -54
  409. package/lib/module/NullFactory.js +29 -0
  410. package/lib/{Parser.js → module/Parser.js} +3 -3
  411. package/lib/module/RawModule.js +208 -0
  412. package/lib/{SelfModuleFactory.js → module/SelfModuleFactory.js} +1 -1
  413. package/lib/{util → module}/extractSourceMap.js +2 -2
  414. package/lib/{util → module}/findCaseMismatch.js +2 -2
  415. package/lib/node/CommonJsChunkLoadingPlugin.js +3 -3
  416. package/lib/{dependencies → node}/ExternalModuleDependency.js +8 -7
  417. package/lib/{dependencies → node}/ExternalModuleInitFragment.js +6 -5
  418. package/lib/{dependencies → node}/ExternalModuleInitFragmentDependency.js +14 -9
  419. package/lib/node/NodeEnvironmentPlugin.js +11 -1
  420. package/lib/{NodeStuffPlugin.js → node/NodeStuffPlugin.js} +17 -17
  421. package/lib/node/NodeTargetPlugin.js +1 -1
  422. package/lib/node/NodeWatchFileSystem.js +58 -6
  423. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +7 -7
  424. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +9 -7
  425. package/lib/node/ReadFileCompileWasmPlugin.js +7 -5
  426. package/lib/node/RequireChunkLoadingRuntimeModule.js +7 -7
  427. package/lib/node/nodeConsole.js +2 -4
  428. package/lib/optimize/AggressiveMergingPlugin.js +2 -2
  429. package/lib/optimize/AggressiveSplittingPlugin.js +12 -8
  430. package/lib/{CircularModulesPlugin.js → optimize/CircularModulesPlugin.js} +13 -13
  431. package/lib/optimize/ConcatenatedModule.js +229 -214
  432. package/lib/{ConcatenationScope.js → optimize/ConcatenationScope.js} +39 -6
  433. package/lib/optimize/ConstExportsPlugin.js +7 -7
  434. package/lib/optimize/EnsureChunkConditionsPlugin.js +3 -3
  435. package/lib/{FlagAllModulesAsUsedPlugin.js → optimize/FlagAllModulesAsUsedPlugin.js} +3 -3
  436. package/lib/{FlagDependencyExportsPlugin.js → optimize/FlagDependencyExportsPlugin.js} +17 -17
  437. package/lib/{FlagDependencyUsagePlugin.js → optimize/FlagDependencyUsagePlugin.js} +17 -17
  438. package/lib/{FlagEntryExportAsUsedPlugin.js → optimize/FlagEntryExportAsUsedPlugin.js} +2 -2
  439. package/lib/optimize/FlagIncludedChunksPlugin.js +2 -2
  440. package/lib/optimize/InlineExports.js +11 -3
  441. package/lib/optimize/InnerGraph.js +5 -13
  442. package/lib/optimize/InnerGraphPlugin.js +10 -10
  443. package/lib/optimize/LazyBarrels.js +584 -0
  444. package/lib/{util → optimize}/LazyBucketSortedSet.js +2 -2
  445. package/lib/optimize/LimitChunkCountPlugin.js +16 -7
  446. package/lib/optimize/MangleExportsPlugin.js +5 -5
  447. package/lib/optimize/MergeDuplicateChunksPlugin.js +7 -6
  448. package/lib/optimize/MinChunkSizePlugin.js +9 -6
  449. package/lib/optimize/ModuleConcatenationPlugin.js +20 -12
  450. package/lib/{dependencies → optimize}/PureExpressionDependency.js +11 -10
  451. package/lib/optimize/RealContentHashPlugin.js +16 -7
  452. package/lib/optimize/RemoveEmptyChunksPlugin.js +2 -2
  453. package/lib/optimize/RemoveParentModulesPlugin.js +4 -4
  454. package/lib/optimize/SideEffectsFlagPlugin.js +18 -18
  455. package/lib/optimize/SplitChunksPlugin.js +713 -155
  456. package/lib/{util → optimize}/TupleQueue.js +9 -9
  457. package/lib/optimize/chunkSetIntersections.js +437 -0
  458. package/lib/{util → optimize}/deterministicGrouping.js +17 -17
  459. package/lib/{BannerPlugin.js → output/BannerPlugin.js} +82 -14
  460. package/lib/{CleanPlugin.js → output/CleanPlugin.js} +66 -24
  461. package/lib/{CopyPlugin.js → output/CopyPlugin.js} +142 -67
  462. package/lib/{ManifestPlugin.js → output/ManifestPlugin.js} +91 -17
  463. package/lib/output/SSRManifestPlugin.js +349 -0
  464. package/lib/performance/AnalyzableBailoutsPlugin.js +1 -1
  465. package/lib/performance/AsyncChunkWaterfallsPlugin.js +1 -1
  466. package/lib/performance/BroadContextsPlugin.js +4 -4
  467. package/lib/performance/CacheEffectivenessPlugin.js +2 -3
  468. package/lib/performance/ConflictingResourceHintsPlugin.js +1 -1
  469. package/lib/performance/DuplicateModulesPlugin.js +3 -4
  470. package/lib/performance/DuplicatePackagesPlugin.js +3 -3
  471. package/lib/performance/DynamicExportsPlugin.js +2 -2
  472. package/lib/performance/EvalUsagePlugin.js +3 -3
  473. package/lib/performance/HotspotsPlugin.js +11 -10
  474. package/lib/performance/LargeModulesPlugin.js +2 -3
  475. package/lib/performance/LegacyJavascriptPlugin.js +1 -2
  476. package/lib/performance/MissingSideEffectsPlugin.js +2 -3
  477. package/lib/performance/MissingSourceMapsPlugin.js +5 -6
  478. package/lib/performance/PureAnnotationsPlugin.js +3 -3
  479. package/lib/performance/RedundantDynamicImportsPlugin.js +6 -8
  480. package/lib/performance/ScopeHoistingBailoutsPlugin.js +2 -2
  481. package/lib/performance/SizeLimitsPlugin.js +11 -12
  482. package/lib/performance/TopLevelThisPlugin.js +8 -7
  483. package/lib/performance/UnsplitVendorsPlugin.js +1 -2
  484. package/lib/performance/UnusedAliasesPlugin.js +6 -7
  485. package/lib/performance/UnusedAssetsPlugin.js +5 -5
  486. package/lib/performance/UnusedDefinesPlugin.js +2 -2
  487. package/lib/performance/UnusedExternalsPlugin.js +3 -4
  488. package/lib/performance/UnusedFederationPlugin.js +2 -4
  489. package/lib/performance/UnusedModulesPlugin.js +5 -4
  490. package/lib/performance/getModuleSize.js +1 -1
  491. package/lib/performance/hasOnlyUnusedExports.js +4 -4
  492. package/lib/performance/isOnlyReexported.js +7 -6
  493. package/lib/{AutomaticPrefetchPlugin.js → prefetch/AutomaticPrefetchPlugin.js} +4 -5
  494. package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +2 -2
  495. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +1 -1
  496. package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +4 -4
  497. package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +4 -4
  498. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +4 -4
  499. package/lib/{dependencies → prefetch}/PrefetchDependency.js +1 -1
  500. package/lib/{PrefetchPlugin.js → prefetch/PrefetchPlugin.js} +2 -2
  501. package/lib/prefetch/ResourceHintPlugin.js +65 -44
  502. package/lib/prefetch/ResourceHintRuntimeModule.js +3 -3
  503. package/lib/prefetch/StartupAssetHintRuntimeModule.js +3 -3
  504. package/lib/prefetch/parseResourceHintOptions.js +4 -3
  505. package/lib/{ProvidePlugin.js → provide/ProvidePlugin.js} +7 -7
  506. package/lib/{dependencies → provide}/ProvidedDependency.js +14 -13
  507. package/lib/{IgnorePlugin.js → resolve/IgnorePlugin.js} +30 -13
  508. package/lib/{NormalModuleReplacementPlugin.js → resolve/NormalModuleReplacementPlugin.js} +4 -4
  509. package/lib/{ResolverFactory.js → resolve/ResolverFactory.js} +18 -5
  510. package/lib/resolve/getResolveOptionsKey.js +59 -0
  511. package/lib/rules/RuleSetCompiler.js +27 -46
  512. package/lib/runtime/AsyncModuleGeneratorRuntimeModule.js +2 -2
  513. package/lib/runtime/AsyncModuleRuntimeModule.js +7 -4
  514. package/lib/runtime/AutoPublicPathRuntimeModule.js +5 -5
  515. package/lib/runtime/BaseUriRuntimeModule.js +3 -3
  516. package/lib/runtime/ChunkNameRuntimeModule.js +2 -2
  517. package/lib/runtime/CompatGetDefaultExportRuntimeModule.js +2 -2
  518. package/lib/runtime/CompatRuntimeModule.js +4 -4
  519. package/lib/runtime/ConcatenationWrapRuntimeModule.js +2 -2
  520. package/lib/runtime/ConstructRequireRuntimeModule.js +2 -2
  521. package/lib/runtime/CreateFakeNamespaceObjectRuntimeModule.js +2 -2
  522. package/lib/runtime/CreateScriptRuntimeModule.js +2 -2
  523. package/lib/runtime/CreateScriptUrlRuntimeModule.js +2 -2
  524. package/lib/runtime/DefinePropertyGettersRuntimeModule.js +6 -6
  525. package/lib/runtime/EnsureChunkRuntimeModule.js +4 -4
  526. package/lib/runtime/GetChunkFilenameRuntimeModule.js +6 -6
  527. package/lib/runtime/GetFullHashRuntimeModule.js +2 -2
  528. package/lib/runtime/GetMainFilenameRuntimeModule.js +4 -4
  529. package/lib/runtime/GetTrustedTypesPolicyRuntimeModule.js +3 -3
  530. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +3 -3
  531. package/lib/runtime/GlobalRuntimeModule.js +3 -3
  532. package/lib/runtime/HasOwnPropertyRuntimeModule.js +3 -3
  533. package/lib/runtime/HelperRuntimeModule.js +16 -1
  534. package/lib/runtime/LoadScriptRuntimeModule.js +3 -3
  535. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +80 -17
  536. package/lib/runtime/MakeNamespaceObjectRuntimeModule.js +2 -2
  537. package/lib/runtime/NonceRuntimeModule.js +2 -2
  538. package/lib/runtime/OnChunksLoadedRuntimeModule.js +4 -4
  539. package/lib/runtime/PublicPathRuntimeModule.js +2 -2
  540. package/lib/runtime/RelativeUrlRuntimeModule.js +2 -2
  541. package/lib/{RuntimeGlobals.js → runtime/RuntimeGlobals.js} +18 -1
  542. package/lib/runtime/RuntimeIdRuntimeModule.js +4 -4
  543. package/lib/{RuntimeModule.js → runtime/RuntimeModule.js} +36 -21
  544. package/lib/{RuntimePlugin.js → runtime/RuntimePlugin.js} +48 -50
  545. package/lib/runtime/SetAnonymousDefaultNameRuntimeModule.js +2 -2
  546. package/lib/runtime/SpecNamespaceObjectRuntimeModule.js +2 -2
  547. package/lib/runtime/StartupChunkDependenciesPlugin.js +2 -2
  548. package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +5 -5
  549. package/lib/runtime/StartupEntrypointRuntimeModule.js +3 -3
  550. package/lib/runtime/SystemContextRuntimeModule.js +2 -2
  551. package/lib/runtime/ToBinaryRuntimeModule.js +3 -3
  552. package/lib/runtime/WorkerRuntimeModule.js +1 -1
  553. package/lib/runtime/baseUri.js +1 -1
  554. package/lib/schemes/DataUriPlugin.js +1 -1
  555. package/lib/schemes/HttpUriPlugin.js +67 -11
  556. package/lib/schemes/VirtualUrlPlugin.js +50 -16
  557. package/lib/serialization/AggregateErrorSerializer.js +2 -2
  558. package/lib/serialization/FileMiddleware.js +3 -3
  559. package/lib/serialization/ObjectMiddleware.js +47 -16
  560. package/lib/serialization/SerializerMiddleware.js +2 -2
  561. package/lib/serialization/SingleItemMiddleware.js +4 -2
  562. package/lib/sharing/ConsumeSharedFallbackDependency.js +9 -1
  563. package/lib/sharing/ConsumeSharedModule.js +18 -14
  564. package/lib/sharing/ConsumeSharedPlugin.js +148 -42
  565. package/lib/sharing/ConsumeSharedRuntimeModule.js +8 -8
  566. package/lib/sharing/ProvideForSharedDependency.js +9 -1
  567. package/lib/sharing/ProvideSharedDependency.js +1 -1
  568. package/lib/sharing/ProvideSharedModule.js +11 -9
  569. package/lib/sharing/ProvideSharedModuleFactory.js +2 -2
  570. package/lib/sharing/ProvideSharedPlugin.js +111 -20
  571. package/lib/sharing/SharePlugin.js +102 -9
  572. package/lib/sharing/ShareRuntimeModule.js +6 -6
  573. package/lib/sharing/resolveMatchedConfigs.js +1 -1
  574. package/lib/{util → sharing}/semver.js +14 -16
  575. package/lib/sharing/utils.js +59 -2
  576. package/lib/stats/DefaultStatsFactoryPlugin.js +22 -19
  577. package/lib/stats/DefaultStatsPresetPlugin.js +1 -1
  578. package/lib/stats/DefaultStatsPrinterPlugin.js +3 -3
  579. package/lib/{MultiStats.js → stats/MultiStats.js} +4 -4
  580. package/lib/{Stats.js → stats/Stats.js} +4 -4
  581. package/lib/stats/StatsFactory.js +14 -13
  582. package/lib/{ChunkTemplate.js → template/ChunkTemplate.js} +7 -7
  583. package/lib/{ConditionalInitFragment.js → template/ConditionalInitFragment.js} +3 -3
  584. package/lib/template/DependencyTemplate.js +77 -0
  585. package/lib/{DependencyTemplates.js → template/DependencyTemplates.js} +9 -4
  586. package/lib/template/InitFragment.js +223 -0
  587. package/lib/{MainTemplate.js → template/MainTemplate.js} +11 -11
  588. package/lib/{ModuleInfoHeaderPlugin.js → template/ModuleInfoHeaderPlugin.js} +30 -8
  589. package/lib/{ModuleTemplate.js → template/ModuleTemplate.js} +6 -6
  590. package/lib/{RuntimeTemplate.js → template/RuntimeTemplate.js} +145 -63
  591. package/lib/{Template.js → template/Template.js} +13 -11
  592. package/lib/{TemplatedPathPlugin.js → template/TemplatedPathPlugin.js} +19 -23
  593. package/lib/typescript/TypeScriptPlugin.js +3 -3
  594. package/lib/util/RequestShortener.js +44 -0
  595. package/lib/util/SortableSet.js +87 -22
  596. package/lib/util/SourceProcessor.js +349 -44
  597. package/lib/util/TupleSet.js +27 -27
  598. package/lib/util/WeakTupleMap.js +10 -12
  599. package/lib/util/buildDiagnostics.js +2 -2
  600. package/lib/util/comparators.js +10 -10
  601. package/lib/util/concatenate.js +28 -147
  602. package/lib/util/createMappings.js +111 -0
  603. package/lib/util/dataURL.js +94 -15
  604. package/lib/util/deprecation.js +1 -1
  605. package/lib/util/extractComments.js +118 -0
  606. package/lib/util/formatLocation.js +1 -1
  607. package/lib/util/globUtils.js +197 -16
  608. package/lib/util/haltVisitors.js +51 -0
  609. package/lib/util/handlerKeys.js +2 -2
  610. package/lib/util/identifier.js +117 -1
  611. package/lib/util/implicitTypeLoaderFallback.js +6 -4
  612. package/lib/util/internalSerializables.js +294 -102
  613. package/lib/util/magicComment.js +12 -7
  614. package/lib/util/makeSerializable.js +23 -4
  615. package/lib/util/parseJson.js +1 -1
  616. package/lib/util/preloadModuleType.js +5 -2
  617. package/lib/util/registerExternalSerializer.js +2 -2
  618. package/lib/util/removeBOM.js +1 -1
  619. package/lib/util/runtime.js +1 -1
  620. package/lib/util/serialization.js +4 -1
  621. package/lib/util/source.js +2 -2
  622. package/lib/util/terminalColors.js +161 -0
  623. package/lib/{wasm-async → wasm}/AsyncWasmCompileRuntimeModule.js +5 -5
  624. package/lib/{wasm-async → wasm}/AsyncWasmLoadingRuntimeModule.js +5 -5
  625. package/lib/{wasm-async → wasm}/AsyncWasmModule.js +9 -5
  626. package/lib/{wasm-async → wasm}/AsyncWebAssemblyGenerator.js +5 -5
  627. package/lib/{wasm-async → wasm}/AsyncWebAssemblyJavascriptGenerator.js +11 -10
  628. package/lib/{wasm-async → wasm}/AsyncWebAssemblyModulesPlugin.js +26 -10
  629. package/lib/{wasm-async → wasm}/AsyncWebAssemblyParser.js +8 -8
  630. package/lib/wasm/EnableWasmLoadingPlugin.js +1 -1
  631. package/lib/{wasm-async → wasm}/UniversalCompileAsyncWasmPlugin.js +9 -7
  632. package/lib/wasm/wasmModuleFilename.js +2 -2
  633. package/lib/wasm-sync/SyncWasmModule.js +3 -3
  634. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +8 -8
  635. package/lib/wasm-sync/WasmFinalizeExportsPlugin.js +3 -3
  636. package/lib/wasm-sync/WebAssemblyGenerator.js +9 -8
  637. package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +14 -15
  638. package/lib/wasm-sync/WebAssemblyModulesPlugin.js +9 -7
  639. package/lib/wasm-sync/WebAssemblyParser.js +6 -6
  640. package/lib/wasm-sync/WebAssemblyUtils.js +6 -5
  641. package/lib/{MultiWatching.js → watch/MultiWatching.js} +3 -3
  642. package/lib/{WatchIgnorePlugin.js → watch/WatchIgnorePlugin.js} +43 -9
  643. package/lib/{Watching.js → watch/Watching.js} +8 -8
  644. package/lib/web/FetchCompileAsyncWasmPlugin.js +8 -6
  645. package/lib/web/FetchCompileWasmPlugin.js +6 -4
  646. package/lib/web/JsonpChunkLoadingPlugin.js +3 -3
  647. package/lib/web/JsonpChunkLoadingRuntimeModule.js +6 -6
  648. package/lib/web/JsonpTemplatePlugin.js +1 -1
  649. package/lib/webpack.js +27 -17
  650. package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +3 -3
  651. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +6 -6
  652. package/package.json +48 -41
  653. package/schemas/WebpackOptions.check.js +2 -1
  654. package/schemas/WebpackOptions.d.json.ts +2 -0
  655. package/schemas/WebpackOptions.json +294 -74
  656. package/schemas/plugins/BannerPlugin.check.js +2 -1
  657. package/schemas/plugins/BannerPlugin.json +29 -2
  658. package/schemas/plugins/HtmlGeneratorOptions.check.js +1 -0
  659. package/schemas/plugins/HtmlParserOptions.check.js +2 -1
  660. package/schemas/plugins/IgnorePlugin.check.js +1 -0
  661. package/schemas/plugins/IgnorePlugin.d.json.ts +2 -0
  662. package/schemas/plugins/IgnorePlugin.json +1 -1
  663. package/schemas/plugins/LoaderOptionsPlugin.check.js +1 -0
  664. package/schemas/plugins/ManifestPlugin.check.js +1 -0
  665. package/schemas/plugins/ManifestPlugin.json +3 -3
  666. package/schemas/plugins/ProgressPlugin.check.js +2 -1
  667. package/schemas/plugins/ProgressPlugin.json +2 -7
  668. package/schemas/plugins/SSRManifestPlugin.check.js +7 -0
  669. package/schemas/plugins/SSRManifestPlugin.json +20 -0
  670. package/schemas/plugins/SourceMapDevToolPlugin.check.js +2 -1
  671. package/schemas/plugins/SourceMapDevToolPlugin.json +44 -12
  672. package/schemas/plugins/WatchIgnorePlugin.check.js +2 -1
  673. package/schemas/plugins/WatchIgnorePlugin.json +12 -3
  674. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -0
  675. package/schemas/plugins/asset/AssetInlineGeneratorOptions.check.js +1 -0
  676. package/schemas/plugins/asset/AssetParserOptions.check.js +1 -0
  677. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -0
  678. package/schemas/plugins/container/ContainerPlugin.check.js +2 -1
  679. package/schemas/plugins/container/ContainerPlugin.json +8 -0
  680. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -0
  681. package/schemas/plugins/container/ExternalsType.check.js +1 -0
  682. package/schemas/plugins/container/ModuleFederationPlugin.check.js +2 -1
  683. package/schemas/plugins/container/ModuleFederationPlugin.json +40 -0
  684. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +1 -0
  685. package/schemas/plugins/css/CssGeneratorOptions.check.js +1 -0
  686. package/schemas/plugins/css/CssModuleGeneratorOptions.check.js +1 -0
  687. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -0
  688. package/schemas/plugins/css/CssParserOptions.check.js +1 -0
  689. package/schemas/plugins/debug/ProfilingPlugin.check.js +1 -0
  690. package/schemas/plugins/dll/DllPlugin.check.js +1 -0
  691. package/schemas/plugins/dll/DllReferencePlugin.check.js +2 -1
  692. package/schemas/plugins/dll/DllReferencePlugin.json +3 -18
  693. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +1 -0
  694. package/schemas/plugins/ids/OccurrenceChunkIdsPlugin.check.js +1 -0
  695. package/schemas/plugins/ids/OccurrenceModuleIdsPlugin.check.js +1 -0
  696. package/schemas/plugins/json/JsonModulesPluginGenerator.check.js +1 -0
  697. package/schemas/plugins/json/JsonModulesPluginParser.check.js +1 -0
  698. package/schemas/plugins/optimize/AggressiveSplittingPlugin.check.js +1 -0
  699. package/schemas/plugins/optimize/LimitChunkCountPlugin.check.js +1 -0
  700. package/schemas/plugins/optimize/MergeDuplicateChunksPlugin.check.js +1 -0
  701. package/schemas/plugins/optimize/MinChunkSizePlugin.check.js +1 -0
  702. package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -0
  703. package/schemas/plugins/schemes/VirtualUrlPlugin.check.js +1 -0
  704. package/schemas/plugins/sharing/ConsumeSharedPlugin.check.js +2 -1
  705. package/schemas/plugins/sharing/ConsumeSharedPlugin.json +32 -0
  706. package/schemas/plugins/sharing/ProvideSharedPlugin.check.js +2 -1
  707. package/schemas/plugins/sharing/ProvideSharedPlugin.json +32 -0
  708. package/schemas/plugins/sharing/SharePlugin.check.js +2 -1
  709. package/schemas/plugins/sharing/SharePlugin.json +32 -0
  710. package/types.d.ts +19355 -13873
  711. package/lib/LazyBarrel.js +0 -388
  712. package/lib/dependencies/HarmonyAcceptImportDependency.js +0 -39
  713. package/lib/dependencies/HarmonyModulesPlugin.js +0 -192
  714. package/lib/javascript/ChunkFormatHelpers.js +0 -72
  715. package/lib/javascript/grammar.js +0 -5546
  716. package/lib/javascript/parser.js +0 -1500
  717. package/lib/javascript/regexpData.js +0 -51
  718. package/lib/performance/getSourceModules.js +0 -22
  719. package/lib/util/Semaphore.js +0 -65
  720. package/lib/util/objectToMap.js +0 -15
  721. package/schemas/WebpackOptions.check.d.ts +0 -7
  722. package/schemas/_container.json +0 -155
  723. package/schemas/_sharing.json +0 -118
  724. package/schemas/plugins/BannerPlugin.check.d.ts +0 -7
  725. package/schemas/plugins/HtmlGeneratorOptions.check.d.ts +0 -7
  726. package/schemas/plugins/HtmlParserOptions.check.d.ts +0 -7
  727. package/schemas/plugins/IgnorePlugin.check.d.ts +0 -7
  728. package/schemas/plugins/LoaderOptionsPlugin.check.d.ts +0 -7
  729. package/schemas/plugins/ManifestPlugin.check.d.ts +0 -7
  730. package/schemas/plugins/ProgressPlugin.check.d.ts +0 -7
  731. package/schemas/plugins/SourceMapDevToolPlugin.check.d.ts +0 -7
  732. package/schemas/plugins/WatchIgnorePlugin.check.d.ts +0 -7
  733. package/schemas/plugins/asset/AssetGeneratorOptions.check.d.ts +0 -7
  734. package/schemas/plugins/asset/AssetInlineGeneratorOptions.check.d.ts +0 -7
  735. package/schemas/plugins/asset/AssetParserOptions.check.d.ts +0 -7
  736. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.d.ts +0 -7
  737. package/schemas/plugins/container/ContainerPlugin.check.d.ts +0 -7
  738. package/schemas/plugins/container/ContainerReferencePlugin.check.d.ts +0 -7
  739. package/schemas/plugins/container/ExternalsType.check.d.ts +0 -7
  740. package/schemas/plugins/container/ModuleFederationPlugin.check.d.ts +0 -7
  741. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.d.ts +0 -7
  742. package/schemas/plugins/css/CssGeneratorOptions.check.d.ts +0 -7
  743. package/schemas/plugins/css/CssModuleGeneratorOptions.check.d.ts +0 -7
  744. package/schemas/plugins/css/CssModuleParserOptions.check.d.ts +0 -7
  745. package/schemas/plugins/css/CssParserOptions.check.d.ts +0 -7
  746. package/schemas/plugins/debug/ProfilingPlugin.check.d.ts +0 -7
  747. package/schemas/plugins/dll/DllPlugin.check.d.ts +0 -7
  748. package/schemas/plugins/dll/DllReferencePlugin.check.d.ts +0 -7
  749. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.d.ts +0 -7
  750. package/schemas/plugins/ids/OccurrenceChunkIdsPlugin.check.d.ts +0 -7
  751. package/schemas/plugins/ids/OccurrenceModuleIdsPlugin.check.d.ts +0 -7
  752. package/schemas/plugins/json/JsonModulesPluginGenerator.check.d.ts +0 -7
  753. package/schemas/plugins/json/JsonModulesPluginParser.check.d.ts +0 -7
  754. package/schemas/plugins/optimize/AggressiveSplittingPlugin.check.d.ts +0 -7
  755. package/schemas/plugins/optimize/LimitChunkCountPlugin.check.d.ts +0 -7
  756. package/schemas/plugins/optimize/MergeDuplicateChunksPlugin.check.d.ts +0 -7
  757. package/schemas/plugins/optimize/MinChunkSizePlugin.check.d.ts +0 -7
  758. package/schemas/plugins/schemes/HttpUriPlugin.check.d.ts +0 -7
  759. package/schemas/plugins/schemes/VirtualUrlPlugin.check.d.ts +0 -7
  760. package/schemas/plugins/sharing/ConsumeSharedPlugin.check.d.ts +0 -7
  761. package/schemas/plugins/sharing/ProvideSharedPlugin.check.d.ts +0 -7
  762. package/schemas/plugins/sharing/SharePlugin.check.d.ts +0 -7
  763. /package/lib/{validateSchema.js → config/validateSchema.js} +0 -0
  764. /package/lib/{util → css}/conventions.js +0 -0
  765. /package/lib/{util → css}/topologicalSort.js +0 -0
  766. /package/lib/dependencies/{getFunctionExpression.js → helpers/getFunctionExpression.js} +0 -0
  767. /package/lib/{util → externals}/extractUrlAndGlobal.js +0 -0
  768. /package/lib/{util → fs}/StackedCacheMap.js +0 -0
  769. /package/lib/{util → javascript}/StackedMap.js +0 -0
  770. /package/lib/{ModuleProfile.js → module/ModuleProfile.js} +0 -0
  771. /package/lib/{ModuleSourceTypeConstants.js → module/ModuleSourceTypeConstants.js} +0 -0
  772. /package/lib/{ModuleTypeConstants.js → module/ModuleTypeConstants.js} +0 -0
  773. /package/lib/{OptimizationStages.js → optimize/OptimizationStages.js} +0 -0
  774. /package/lib/{util → optimize}/Queue.js +0 -0
  775. /package/lib/{util → stats}/smartGrouping.js +0 -0
@@ -0,0 +1,4642 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Tobias Koppers @sokra
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const nodeModule = require("module");
9
+ const { isAbsolute } = require("path");
10
+ const { create: createResolver } = require("enhanced-resolve");
11
+ const { DEFAULTS } = require("../config/defaults");
12
+ const { collectCjsRequireSpecifiers } = require("../javascript/syntax-parser");
13
+ const AsyncQueue = require("../util/AsyncQueue");
14
+ const asyncLib = require("../util/async");
15
+ const createHash = require("../util/createHash");
16
+ const makeSerializable = require("../util/makeSerializable");
17
+ const memoize = require("../util/memoize");
18
+ const processAsyncTree = require("../util/processAsyncTree");
19
+ const StackedCacheMap = require("./StackedCacheMap");
20
+ const { dirname, join, lstatReadlinkAbsolute, relative } = require("./fs");
21
+
22
+ // only the mjs build-dependency walk needs it
23
+ const getEsModuleLexer = memoize(() => require("es-module-lexer"));
24
+
25
+ /** @import { ResolveRequest, ResolveFunctionAsync } from "enhanced-resolve" */
26
+ /** @import { HashFunction } from "../../declarations/WebpackOptions" */
27
+ /** @import { Logger } from "../logging/Logger" */
28
+ /** @import WebpackError from "../errors/WebpackError" */
29
+ /** @import { JsonObject, IStats, InputFileSystem } from "./fs" */
30
+ /**
31
+ * @import {
32
+ * ObjectDeserializerContext,
33
+ * ObjectSerializerContext
34
+ * } from "../serialization/ObjectMiddleware"
35
+ */
36
+ /**
37
+ * Defines the processor callback type used by this module.
38
+ * @template T
39
+ * @typedef {import("../util/AsyncQueue").Callback<T>} ProcessorCallback
40
+ */
41
+ /**
42
+ * Defines the processor type used by this module.
43
+ * @template T, R
44
+ * @typedef {import("../util/AsyncQueue").Processor<T, R>} Processor
45
+ */
46
+
47
+ const supportsEsm = Number(process.versions.modules) >= 83;
48
+
49
+ /** @type {Set<string>} */
50
+ const builtinModules = new Set(nodeModule.builtinModules);
51
+
52
+ let FS_ACCURACY = 2000;
53
+
54
+ /** @type {Set<string>} */
55
+ const EMPTY_SET = new Set();
56
+
57
+ const RBDT_RESOLVE_INITIAL = 0;
58
+ const RBDT_RESOLVE_FILE = 1;
59
+ const RBDT_RESOLVE_DIRECTORY = 2;
60
+ const RBDT_RESOLVE_CJS_FILE = 3;
61
+ const RBDT_RESOLVE_CJS_FILE_AS_CHILD = 4;
62
+ const RBDT_RESOLVE_ESM_FILE = 5;
63
+ const RBDT_DIRECTORY = 6;
64
+ const RBDT_FILE = 7;
65
+ const RBDT_DIRECTORY_DEPENDENCIES = 8;
66
+ const RBDT_FILE_DEPENDENCIES = 9;
67
+
68
+ /** @typedef {RBDT_RESOLVE_INITIAL | RBDT_RESOLVE_FILE | RBDT_RESOLVE_DIRECTORY | RBDT_RESOLVE_CJS_FILE | RBDT_RESOLVE_CJS_FILE_AS_CHILD | RBDT_RESOLVE_ESM_FILE | RBDT_DIRECTORY | RBDT_FILE | RBDT_DIRECTORY_DEPENDENCIES | RBDT_FILE_DEPENDENCIES} JobType */
69
+
70
+ const INVALID = Symbol("invalid");
71
+
72
+ // eslint-disable-next-line jsdoc/ts-no-empty-object-type
73
+ /** @typedef {{ }} ExistenceOnlyTimeEntry */
74
+
75
+ /**
76
+ * Defines the file system info entry type used by this module.
77
+ * @typedef {object} FileSystemInfoEntry
78
+ * @property {number} safeTime
79
+ * @property {number=} timestamp
80
+ */
81
+
82
+ /**
83
+ * Defines the resolved context file system info entry type used by this module.
84
+ * @typedef {object} ResolvedContextFileSystemInfoEntry
85
+ * @property {number} safeTime
86
+ * @property {string=} timestampHash
87
+ */
88
+
89
+ /** @typedef {Set<string>} Symlinks */
90
+
91
+ /**
92
+ * Defines the context file system info entry type used by this module.
93
+ * @typedef {object} ContextFileSystemInfoEntry
94
+ * @property {number} safeTime
95
+ * @property {string=} timestampHash
96
+ * @property {ResolvedContextFileSystemInfoEntry=} resolved
97
+ * @property {Symlinks=} symlinks
98
+ */
99
+
100
+ /**
101
+ * Defines the timestamp and hash type used by this module.
102
+ * @typedef {object} TimestampAndHash
103
+ * @property {number} safeTime
104
+ * @property {number=} timestamp
105
+ * @property {string} hash
106
+ */
107
+
108
+ /**
109
+ * Defines the resolved context timestamp and hash type used by this module.
110
+ * @typedef {object} ResolvedContextTimestampAndHash
111
+ * @property {number} safeTime
112
+ * @property {string=} timestampHash
113
+ * @property {string} hash
114
+ */
115
+
116
+ /**
117
+ * Defines the context timestamp and hash type used by this module.
118
+ * @typedef {object} ContextTimestampAndHash
119
+ * @property {number} safeTime
120
+ * @property {string=} timestampHash
121
+ * @property {string} hash
122
+ * @property {ResolvedContextTimestampAndHash=} resolved
123
+ * @property {Symlinks=} symlinks
124
+ */
125
+
126
+ /**
127
+ * Defines the context hash type used by this module.
128
+ * @typedef {object} ContextHash
129
+ * @property {string} hash
130
+ * @property {string=} resolved
131
+ * @property {Symlinks=} symlinks
132
+ */
133
+
134
+ /** @typedef {Set<string>} SnapshotContent */
135
+
136
+ /**
137
+ * Defines the snapshot optimization entry type used by this module.
138
+ * @typedef {object} SnapshotOptimizationEntry
139
+ * @property {Snapshot} snapshot
140
+ * @property {number} shared
141
+ * @property {SnapshotContent | undefined} snapshotContent
142
+ * @property {Set<SnapshotOptimizationEntry> | undefined} children
143
+ */
144
+
145
+ /** @typedef {Map<string, string | false | undefined>} ResolveResults */
146
+
147
+ /** @typedef {Set<string>} Files */
148
+ /** @typedef {Set<string>} Directories */
149
+ /** @typedef {Set<string>} Missing */
150
+
151
+ /**
152
+ * Defines the resolve dependencies type used by this module.
153
+ * @typedef {object} ResolveDependencies
154
+ * @property {Files} files list of files
155
+ * @property {Directories} directories list of directories
156
+ * @property {Missing} missing list of missing entries
157
+ */
158
+
159
+ /**
160
+ * Defines the resolve build dependencies result type used by this module.
161
+ * @typedef {object} ResolveBuildDependenciesResult
162
+ * @property {Files} files list of files
163
+ * @property {Directories} directories list of directories
164
+ * @property {Missing} missing list of missing entries
165
+ * @property {ResolveResults} resolveResults stored resolve results
166
+ * @property {ResolveDependencies} resolveDependencies dependencies of the resolving
167
+ */
168
+
169
+ /**
170
+ * Defines the snapshot options type used by this module.
171
+ * @typedef {object} SnapshotOptions
172
+ * @property {boolean=} hash should use hash to snapshot
173
+ * @property {boolean=} timestamp should use timestamp to snapshot
174
+ */
175
+
176
+ const DONE_ITERATOR_RESULT = new Set().keys().next();
177
+
178
+ // cspell:word tshs
179
+ // Tsh = Timestamp + Hash
180
+ // Tshs = Timestamp + Hash combinations
181
+
182
+ class SnapshotIterator {
183
+ /**
184
+ * Creates an instance of SnapshotIterator.
185
+ * @param {() => IteratorResult<string>} next next
186
+ */
187
+ constructor(next) {
188
+ this.next = next;
189
+ }
190
+ }
191
+
192
+ /**
193
+ * Defines the get maps function type used by this module.
194
+ * @template T
195
+ * @typedef {(snapshot: Snapshot) => T[]} GetMapsFunction
196
+ */
197
+
198
+ /**
199
+ * Represents SnapshotIterable.
200
+ * @template {{ keys(): IterableIterator<string> } | undefined} T
201
+ */
202
+ class SnapshotIterable {
203
+ /**
204
+ * Creates an instance of SnapshotIterable.
205
+ * @param {Snapshot} snapshot snapshot
206
+ * @param {GetMapsFunction<T>} getMaps get maps function
207
+ */
208
+ constructor(snapshot, getMaps) {
209
+ /** @type {Snapshot} */
210
+ this.snapshot = snapshot;
211
+ /** @type {GetMapsFunction<T>} */
212
+ this.getMaps = getMaps;
213
+ }
214
+
215
+ [Symbol.iterator]() {
216
+ let state = 0;
217
+ /** @type {IterableIterator<string>} */
218
+ let it;
219
+ /** @type {GetMapsFunction<T>} */
220
+ let getMaps;
221
+ /** @type {T[]} */
222
+ let maps;
223
+ /** @type {Snapshot} */
224
+ let snapshot;
225
+ /** @type {Snapshot[] | undefined} */
226
+ let queue;
227
+ return new SnapshotIterator(() => {
228
+ for (;;) {
229
+ switch (state) {
230
+ case 0:
231
+ snapshot = this.snapshot;
232
+ getMaps = this.getMaps;
233
+ maps = getMaps(snapshot);
234
+ state = 1;
235
+ /* falls through */
236
+ case 1:
237
+ if (maps.length > 0) {
238
+ const map = maps.pop();
239
+ if (map !== undefined) {
240
+ it = map.keys();
241
+ state = 2;
242
+ } else {
243
+ break;
244
+ }
245
+ } else {
246
+ state = 3;
247
+ break;
248
+ }
249
+ /* falls through */
250
+ case 2: {
251
+ const result = it.next();
252
+ if (!result.done) return result;
253
+ state = 1;
254
+ break;
255
+ }
256
+ case 3: {
257
+ const children = snapshot.children;
258
+ if (children !== undefined) {
259
+ if (children.size === 1) {
260
+ // shortcut for a single child
261
+ // avoids allocation of queue
262
+ for (const child of children) snapshot = child;
263
+ maps = getMaps(snapshot);
264
+ state = 1;
265
+ break;
266
+ }
267
+ if (queue === undefined) queue = [];
268
+ for (const child of children) {
269
+ queue.push(child);
270
+ }
271
+ }
272
+ if (queue !== undefined && queue.length > 0) {
273
+ snapshot = /** @type {Snapshot} */ (queue.pop());
274
+ maps = getMaps(snapshot);
275
+ state = 1;
276
+ break;
277
+ } else {
278
+ state = 4;
279
+ }
280
+ }
281
+ /* falls through */
282
+ case 4:
283
+ return DONE_ITERATOR_RESULT;
284
+ }
285
+ }
286
+ });
287
+ }
288
+ }
289
+
290
+ /** @typedef {Map<string, FileSystemInfoEntry | null>} FileTimestamps */
291
+ /** @typedef {Map<string, string | null>} FileHashes */
292
+ /** @typedef {Map<string, TimestampAndHash | string | null>} FileTshs */
293
+ /** @typedef {Map<string, ResolvedContextFileSystemInfoEntry | null>} ContextTimestamps */
294
+ /** @typedef {Map<string, string | null>} ContextHashes */
295
+ /** @typedef {Map<string, ResolvedContextTimestampAndHash | null>} ContextTshs */
296
+ /** @typedef {Map<string, boolean>} MissingExistence */
297
+ /** @typedef {Map<string, string>} ManagedItemInfo */
298
+ /** @typedef {Set<string>} ManagedFiles */
299
+ /** @typedef {Set<string>} ManagedContexts */
300
+ /** @typedef {Set<string>} ManagedMissing */
301
+ /** @typedef {Set<Snapshot>} Children */
302
+
303
+ // `Snapshot._flags` bit for each optional field. Serialized as a whole integer,
304
+ // so these values are a persisted-cache format contract — never renumber them.
305
+ const SNAPSHOT_FLAG_START_TIME = 1;
306
+ const SNAPSHOT_FLAG_FILE_TIMESTAMPS = 2;
307
+ const SNAPSHOT_FLAG_FILE_HASHES = 4;
308
+ const SNAPSHOT_FLAG_FILE_TSHS = 8;
309
+ const SNAPSHOT_FLAG_CONTEXT_TIMESTAMPS = 0x10;
310
+ const SNAPSHOT_FLAG_CONTEXT_HASHES = 0x20;
311
+ const SNAPSHOT_FLAG_CONTEXT_TSHS = 0x40;
312
+ const SNAPSHOT_FLAG_MISSING_EXISTENCE = 0x80;
313
+ const SNAPSHOT_FLAG_MANAGED_ITEM_INFO = 0x100;
314
+ const SNAPSHOT_FLAG_MANAGED_FILES = 0x200;
315
+ const SNAPSHOT_FLAG_MANAGED_CONTEXTS = 0x400;
316
+ const SNAPSHOT_FLAG_MANAGED_MISSING = 0x800;
317
+ const SNAPSHOT_FLAG_CHILDREN = 0x1000;
318
+
319
+ class Snapshot {
320
+ constructor() {
321
+ /** @type {number} */
322
+ this._flags = 0;
323
+ /** @type {Iterable<string> | undefined} */
324
+ this._cachedFileIterable = undefined;
325
+ /** @type {Iterable<string> | undefined} */
326
+ this._cachedContextIterable = undefined;
327
+ /** @type {Iterable<string> | undefined} */
328
+ this._cachedMissingIterable = undefined;
329
+ /** @type {number | undefined} */
330
+ this.startTime = undefined;
331
+ /** @type {FileTimestamps | undefined} */
332
+ this.fileTimestamps = undefined;
333
+ /** @type {FileHashes | undefined} */
334
+ this.fileHashes = undefined;
335
+ /** @type {FileTshs | undefined} */
336
+ this.fileTshs = undefined;
337
+ /** @type {ContextTimestamps | undefined} */
338
+ this.contextTimestamps = undefined;
339
+ /** @type {ContextHashes | undefined} */
340
+ this.contextHashes = undefined;
341
+ /** @type {ContextTshs | undefined} */
342
+ this.contextTshs = undefined;
343
+ /** @type {MissingExistence | undefined} */
344
+ this.missingExistence = undefined;
345
+ /** @type {ManagedItemInfo | undefined} */
346
+ this.managedItemInfo = undefined;
347
+ /** @type {ManagedFiles | undefined} */
348
+ this.managedFiles = undefined;
349
+ /** @type {ManagedContexts | undefined} */
350
+ this.managedContexts = undefined;
351
+ /** @type {ManagedMissing | undefined} */
352
+ this.managedMissing = undefined;
353
+ /** @type {Children | undefined} */
354
+ this.children = undefined;
355
+ }
356
+
357
+ hasStartTime() {
358
+ return (this._flags & SNAPSHOT_FLAG_START_TIME) !== 0;
359
+ }
360
+
361
+ /**
362
+ * Updates start time using the provided value.
363
+ * @param {number} value start value
364
+ */
365
+ setStartTime(value) {
366
+ this._flags |= SNAPSHOT_FLAG_START_TIME;
367
+ this.startTime = value;
368
+ }
369
+
370
+ /**
371
+ * Sets merged start time.
372
+ * @param {number | undefined} value value
373
+ * @param {Snapshot} snapshot snapshot
374
+ */
375
+ setMergedStartTime(value, snapshot) {
376
+ if (value) {
377
+ if (snapshot.hasStartTime()) {
378
+ this.setStartTime(
379
+ Math.min(
380
+ value,
381
+ /** @type {NonNullable<Snapshot["startTime"]>} */
382
+ (snapshot.startTime)
383
+ )
384
+ );
385
+ } else {
386
+ this.setStartTime(value);
387
+ }
388
+ } else if (snapshot.hasStartTime()) {
389
+ this.setStartTime(
390
+ /** @type {NonNullable<Snapshot["startTime"]>} */
391
+ (snapshot.startTime)
392
+ );
393
+ }
394
+ }
395
+
396
+ hasFileTimestamps() {
397
+ return (this._flags & SNAPSHOT_FLAG_FILE_TIMESTAMPS) !== 0;
398
+ }
399
+
400
+ /**
401
+ * Sets file timestamps.
402
+ * @param {FileTimestamps} value file timestamps
403
+ */
404
+ setFileTimestamps(value) {
405
+ this._flags |= SNAPSHOT_FLAG_FILE_TIMESTAMPS;
406
+ this.fileTimestamps = value;
407
+ }
408
+
409
+ hasFileHashes() {
410
+ return (this._flags & SNAPSHOT_FLAG_FILE_HASHES) !== 0;
411
+ }
412
+
413
+ /**
414
+ * Updates file hashes using the provided value.
415
+ * @param {FileHashes} value file hashes
416
+ */
417
+ setFileHashes(value) {
418
+ this._flags |= SNAPSHOT_FLAG_FILE_HASHES;
419
+ this.fileHashes = value;
420
+ }
421
+
422
+ hasFileTshs() {
423
+ return (this._flags & SNAPSHOT_FLAG_FILE_TSHS) !== 0;
424
+ }
425
+
426
+ /**
427
+ * Updates file tshs using the provided value.
428
+ * @param {FileTshs} value file tshs
429
+ */
430
+ setFileTshs(value) {
431
+ this._flags |= SNAPSHOT_FLAG_FILE_TSHS;
432
+ this.fileTshs = value;
433
+ }
434
+
435
+ hasContextTimestamps() {
436
+ return (this._flags & SNAPSHOT_FLAG_CONTEXT_TIMESTAMPS) !== 0;
437
+ }
438
+
439
+ /**
440
+ * Sets context timestamps.
441
+ * @param {ContextTimestamps} value context timestamps
442
+ */
443
+ setContextTimestamps(value) {
444
+ this._flags |= SNAPSHOT_FLAG_CONTEXT_TIMESTAMPS;
445
+ this.contextTimestamps = value;
446
+ }
447
+
448
+ hasContextHashes() {
449
+ return (this._flags & SNAPSHOT_FLAG_CONTEXT_HASHES) !== 0;
450
+ }
451
+
452
+ /**
453
+ * Sets context hashes.
454
+ * @param {ContextHashes} value context hashes
455
+ */
456
+ setContextHashes(value) {
457
+ this._flags |= SNAPSHOT_FLAG_CONTEXT_HASHES;
458
+ this.contextHashes = value;
459
+ }
460
+
461
+ hasContextTshs() {
462
+ return (this._flags & SNAPSHOT_FLAG_CONTEXT_TSHS) !== 0;
463
+ }
464
+
465
+ /**
466
+ * Updates context tshs using the provided value.
467
+ * @param {ContextTshs} value context tshs
468
+ */
469
+ setContextTshs(value) {
470
+ this._flags |= SNAPSHOT_FLAG_CONTEXT_TSHS;
471
+ this.contextTshs = value;
472
+ }
473
+
474
+ hasMissingExistence() {
475
+ return (this._flags & SNAPSHOT_FLAG_MISSING_EXISTENCE) !== 0;
476
+ }
477
+
478
+ /**
479
+ * Sets missing existence.
480
+ * @param {MissingExistence} value context tshs
481
+ */
482
+ setMissingExistence(value) {
483
+ this._flags |= SNAPSHOT_FLAG_MISSING_EXISTENCE;
484
+ this.missingExistence = value;
485
+ }
486
+
487
+ hasManagedItemInfo() {
488
+ return (this._flags & SNAPSHOT_FLAG_MANAGED_ITEM_INFO) !== 0;
489
+ }
490
+
491
+ /**
492
+ * Sets managed item info.
493
+ * @param {ManagedItemInfo} value managed item info
494
+ */
495
+ setManagedItemInfo(value) {
496
+ this._flags |= SNAPSHOT_FLAG_MANAGED_ITEM_INFO;
497
+ this.managedItemInfo = value;
498
+ }
499
+
500
+ hasManagedFiles() {
501
+ return (this._flags & SNAPSHOT_FLAG_MANAGED_FILES) !== 0;
502
+ }
503
+
504
+ /**
505
+ * Sets managed files.
506
+ * @param {ManagedFiles} value managed files
507
+ */
508
+ setManagedFiles(value) {
509
+ this._flags |= SNAPSHOT_FLAG_MANAGED_FILES;
510
+ this.managedFiles = value;
511
+ }
512
+
513
+ hasManagedContexts() {
514
+ return (this._flags & SNAPSHOT_FLAG_MANAGED_CONTEXTS) !== 0;
515
+ }
516
+
517
+ /**
518
+ * Sets managed contexts.
519
+ * @param {ManagedContexts} value managed contexts
520
+ */
521
+ setManagedContexts(value) {
522
+ this._flags |= SNAPSHOT_FLAG_MANAGED_CONTEXTS;
523
+ this.managedContexts = value;
524
+ }
525
+
526
+ hasManagedMissing() {
527
+ return (this._flags & SNAPSHOT_FLAG_MANAGED_MISSING) !== 0;
528
+ }
529
+
530
+ /**
531
+ * Sets managed missing.
532
+ * @param {ManagedMissing} value managed missing
533
+ */
534
+ setManagedMissing(value) {
535
+ this._flags |= SNAPSHOT_FLAG_MANAGED_MISSING;
536
+ this.managedMissing = value;
537
+ }
538
+
539
+ hasChildren() {
540
+ return (this._flags & SNAPSHOT_FLAG_CHILDREN) !== 0;
541
+ }
542
+
543
+ /**
544
+ * Updates children using the provided value.
545
+ * @param {Children} value children
546
+ */
547
+ setChildren(value) {
548
+ this._flags |= SNAPSHOT_FLAG_CHILDREN;
549
+ this.children = value;
550
+ }
551
+
552
+ /**
553
+ * Adds the provided child to the snapshot.
554
+ * @param {Snapshot} child children
555
+ */
556
+ addChild(child) {
557
+ if (!this.hasChildren()) {
558
+ this.setChildren(new Set());
559
+ }
560
+ /** @type {Children} */
561
+ (this.children).add(child);
562
+ }
563
+
564
+ /**
565
+ * Serializes this instance into the provided serializer context.
566
+ * @param {ObjectSerializerContext} context context
567
+ */
568
+ serialize({ write }) {
569
+ write(this._flags);
570
+ if (this.hasStartTime()) write(this.startTime);
571
+ if (this.hasFileTimestamps()) write(this.fileTimestamps);
572
+ if (this.hasFileHashes()) write(this.fileHashes);
573
+ if (this.hasFileTshs()) write(this.fileTshs);
574
+ if (this.hasContextTimestamps()) write(this.contextTimestamps);
575
+ if (this.hasContextHashes()) write(this.contextHashes);
576
+ if (this.hasContextTshs()) write(this.contextTshs);
577
+ if (this.hasMissingExistence()) write(this.missingExistence);
578
+ if (this.hasManagedItemInfo()) write(this.managedItemInfo);
579
+ if (this.hasManagedFiles()) write(this.managedFiles);
580
+ if (this.hasManagedContexts()) write(this.managedContexts);
581
+ if (this.hasManagedMissing()) write(this.managedMissing);
582
+ if (this.hasChildren()) write(this.children);
583
+ }
584
+
585
+ /**
586
+ * Restores this instance from the provided deserializer context.
587
+ * @param {ObjectDeserializerContext} context context
588
+ */
589
+ deserialize({ read }) {
590
+ this._flags = read();
591
+ if (this.hasStartTime()) this.startTime = read();
592
+ if (this.hasFileTimestamps()) this.fileTimestamps = read();
593
+ if (this.hasFileHashes()) this.fileHashes = read();
594
+ if (this.hasFileTshs()) this.fileTshs = read();
595
+ if (this.hasContextTimestamps()) this.contextTimestamps = read();
596
+ if (this.hasContextHashes()) this.contextHashes = read();
597
+ if (this.hasContextTshs()) this.contextTshs = read();
598
+ if (this.hasMissingExistence()) this.missingExistence = read();
599
+ if (this.hasManagedItemInfo()) this.managedItemInfo = read();
600
+ if (this.hasManagedFiles()) this.managedFiles = read();
601
+ if (this.hasManagedContexts()) this.managedContexts = read();
602
+ if (this.hasManagedMissing()) this.managedMissing = read();
603
+ if (this.hasChildren()) this.children = read();
604
+ }
605
+
606
+ /**
607
+ * Creates an iterable from the provided get map.
608
+ * @template {{ keys(): IterableIterator<string> } | undefined} T
609
+ * @param {GetMapsFunction<T>} getMaps first
610
+ * @returns {SnapshotIterable<T>} iterable
611
+ */
612
+ _createIterable(getMaps) {
613
+ return new SnapshotIterable(this, getMaps);
614
+ }
615
+
616
+ /**
617
+ * Gets file iterable.
618
+ * @returns {Iterable<string>} iterable
619
+ */
620
+ getFileIterable() {
621
+ if (this._cachedFileIterable === undefined) {
622
+ this._cachedFileIterable = this._createIterable((s) => [
623
+ s.fileTimestamps,
624
+ s.fileHashes,
625
+ s.fileTshs,
626
+ s.managedFiles
627
+ ]);
628
+ }
629
+ return this._cachedFileIterable;
630
+ }
631
+
632
+ /**
633
+ * Gets context iterable.
634
+ * @returns {Iterable<string>} iterable
635
+ */
636
+ getContextIterable() {
637
+ if (this._cachedContextIterable === undefined) {
638
+ this._cachedContextIterable = this._createIterable((s) => [
639
+ s.contextTimestamps,
640
+ s.contextHashes,
641
+ s.contextTshs,
642
+ s.managedContexts
643
+ ]);
644
+ }
645
+ return this._cachedContextIterable;
646
+ }
647
+
648
+ /**
649
+ * Gets missing iterable.
650
+ * @returns {Iterable<string>} iterable
651
+ */
652
+ getMissingIterable() {
653
+ if (this._cachedMissingIterable === undefined) {
654
+ this._cachedMissingIterable = this._createIterable((s) => [
655
+ s.missingExistence,
656
+ s.managedMissing
657
+ ]);
658
+ }
659
+ return this._cachedMissingIterable;
660
+ }
661
+ }
662
+
663
+ makeSerializable(
664
+ Snapshot,
665
+ [
666
+ "webpack/lib/fs/FileSystemInfo",
667
+ // TODO in the next major release: remove, they restore pre-move cache packs
668
+ "webpack/lib/FileSystemInfo"
669
+ ],
670
+ "Snapshot"
671
+ );
672
+
673
+ const MIN_COMMON_SNAPSHOT_SIZE = 3;
674
+
675
+ /**
676
+ * Defines the snapshot optimization value type used by this module.
677
+ * @template U, T
678
+ * @typedef {U extends true ? Set<string> : Map<string, T>} SnapshotOptimizationValue
679
+ */
680
+
681
+ /**
682
+ * Represents SnapshotOptimization.
683
+ * @template T
684
+ * @template {boolean} [U=false]
685
+ */
686
+ class SnapshotOptimization {
687
+ /**
688
+ * Creates an instance of SnapshotOptimization.
689
+ * @param {(snapshot: Snapshot) => boolean} has has value
690
+ * @param {(snapshot: Snapshot) => SnapshotOptimizationValue<U, T> | undefined} get get value
691
+ * @param {(snapshot: Snapshot, value: SnapshotOptimizationValue<U, T>) => void} set set value
692
+ * @param {boolean=} useStartTime use the start time of snapshots
693
+ * @param {U=} isSet value is an Set instead of a Map
694
+ */
695
+ constructor(
696
+ has,
697
+ get,
698
+ set,
699
+ useStartTime = true,
700
+ isSet = /** @type {U} */ (false)
701
+ ) {
702
+ this._has = has;
703
+ this._get = get;
704
+ this._set = set;
705
+ /** @type {boolean} */
706
+ this._useStartTime = useStartTime;
707
+ /** @type {U} */
708
+ this._isSet = isSet;
709
+ /** @type {Map<string, SnapshotOptimizationEntry>} */
710
+ this._map = new Map();
711
+ /** @type {number} */
712
+ this._statItemsShared = 0;
713
+ /** @type {number} */
714
+ this._statItemsUnshared = 0;
715
+ /** @type {number} */
716
+ this._statSharedSnapshots = 0;
717
+ /** @type {number} */
718
+ this._statReusedSharedSnapshots = 0;
719
+ }
720
+
721
+ getStatisticMessage() {
722
+ const total = this._statItemsShared + this._statItemsUnshared;
723
+ if (total === 0) return;
724
+ return `${
725
+ this._statItemsShared && Math.round((this._statItemsShared * 100) / total)
726
+ }% (${this._statItemsShared}/${total}) entries shared via ${
727
+ this._statSharedSnapshots
728
+ } shared snapshots (${
729
+ this._statReusedSharedSnapshots + this._statSharedSnapshots
730
+ } times referenced)`;
731
+ }
732
+
733
+ clear() {
734
+ this._map.clear();
735
+ this._statItemsShared = 0;
736
+ this._statItemsUnshared = 0;
737
+ this._statSharedSnapshots = 0;
738
+ this._statReusedSharedSnapshots = 0;
739
+ }
740
+
741
+ /**
742
+ * Processes the provided new snapshot.
743
+ * @param {Snapshot} newSnapshot snapshot
744
+ * @param {Set<string>} capturedFiles files to snapshot/share
745
+ * @returns {void}
746
+ */
747
+ optimize(newSnapshot, capturedFiles) {
748
+ if (capturedFiles.size === 0) {
749
+ return;
750
+ }
751
+ /**
752
+ * Increase shared and store optimization entry.
753
+ * @param {SnapshotOptimizationEntry} entry optimization entry
754
+ * @returns {void}
755
+ */
756
+ const increaseSharedAndStoreOptimizationEntry = (entry) => {
757
+ if (entry.children !== undefined) {
758
+ for (const child of entry.children) {
759
+ increaseSharedAndStoreOptimizationEntry(child);
760
+ }
761
+ }
762
+ entry.shared++;
763
+ storeOptimizationEntry(entry);
764
+ };
765
+ /**
766
+ * Stores optimization entry.
767
+ * @param {SnapshotOptimizationEntry} entry optimization entry
768
+ * @returns {void}
769
+ */
770
+ const storeOptimizationEntry = (entry) => {
771
+ for (const path of /** @type {SnapshotContent} */ (
772
+ entry.snapshotContent
773
+ )) {
774
+ const old =
775
+ /** @type {SnapshotOptimizationEntry} */
776
+ (this._map.get(path));
777
+ if (old.shared < entry.shared) {
778
+ this._map.set(path, entry);
779
+ }
780
+ capturedFiles.delete(path);
781
+ }
782
+ };
783
+
784
+ /** @type {SnapshotOptimizationEntry | undefined} */
785
+ let newOptimizationEntry;
786
+
787
+ const capturedFilesSize = capturedFiles.size;
788
+
789
+ /** @type {Set<SnapshotOptimizationEntry> | undefined} */
790
+ const optimizationEntries = new Set();
791
+
792
+ for (const path of capturedFiles) {
793
+ const optimizationEntry = this._map.get(path);
794
+ if (optimizationEntry === undefined) {
795
+ if (newOptimizationEntry === undefined) {
796
+ newOptimizationEntry = {
797
+ snapshot: newSnapshot,
798
+ shared: 0,
799
+ snapshotContent: undefined,
800
+ children: undefined
801
+ };
802
+ }
803
+ this._map.set(path, newOptimizationEntry);
804
+ } else {
805
+ optimizationEntries.add(optimizationEntry);
806
+ }
807
+ }
808
+
809
+ optimizationEntriesLabel: for (const optimizationEntry of optimizationEntries) {
810
+ const snapshot = optimizationEntry.snapshot;
811
+ if (optimizationEntry.shared > 0) {
812
+ // It's a shared snapshot
813
+ // We can't change it, so we can only use it when all files match
814
+ // and startTime is compatible
815
+ if (
816
+ this._useStartTime &&
817
+ newSnapshot.startTime &&
818
+ (!snapshot.startTime || snapshot.startTime > newSnapshot.startTime)
819
+ ) {
820
+ continue;
821
+ }
822
+ /** @type {Set<string>} */
823
+ const nonSharedFiles = new Set();
824
+ const snapshotContent =
825
+ /** @type {NonNullable<SnapshotOptimizationEntry["snapshotContent"]>} */
826
+ (optimizationEntry.snapshotContent);
827
+ const snapshotEntries =
828
+ /** @type {SnapshotOptimizationValue<U, T>} */
829
+ (this._get(snapshot));
830
+ for (const path of snapshotContent) {
831
+ if (!capturedFiles.has(path)) {
832
+ if (!snapshotEntries.has(path)) {
833
+ // File is not shared and can't be removed from the snapshot
834
+ // because it's in a child of the snapshot
835
+ continue optimizationEntriesLabel;
836
+ }
837
+ nonSharedFiles.add(path);
838
+ }
839
+ }
840
+ if (nonSharedFiles.size === 0) {
841
+ // The complete snapshot is shared
842
+ // add it as child
843
+ newSnapshot.addChild(snapshot);
844
+ increaseSharedAndStoreOptimizationEntry(optimizationEntry);
845
+ this._statReusedSharedSnapshots++;
846
+ } else {
847
+ // Only a part of the snapshot is shared
848
+ const sharedCount = snapshotContent.size - nonSharedFiles.size;
849
+ if (sharedCount < MIN_COMMON_SNAPSHOT_SIZE) {
850
+ // Common part it too small
851
+ continue;
852
+ }
853
+ // Extract common timestamps from both snapshots
854
+ /** @type {Set<string> | Map<string, T>} */
855
+ let commonMap;
856
+ if (this._isSet) {
857
+ commonMap = new Set();
858
+ for (const path of /** @type {Set<string>} */ (snapshotEntries)) {
859
+ if (nonSharedFiles.has(path)) continue;
860
+ commonMap.add(path);
861
+ snapshotEntries.delete(path);
862
+ }
863
+ } else {
864
+ commonMap = new Map();
865
+ const map = /** @type {Map<string, T>} */ (snapshotEntries);
866
+ for (const [path, value] of map) {
867
+ if (nonSharedFiles.has(path)) continue;
868
+ commonMap.set(path, value);
869
+ snapshotEntries.delete(path);
870
+ }
871
+ }
872
+ // Create and attach snapshot
873
+ const commonSnapshot = new Snapshot();
874
+ if (this._useStartTime) {
875
+ commonSnapshot.setMergedStartTime(newSnapshot.startTime, snapshot);
876
+ }
877
+ this._set(
878
+ commonSnapshot,
879
+ /** @type {SnapshotOptimizationValue<U, T>} */ (commonMap)
880
+ );
881
+ newSnapshot.addChild(commonSnapshot);
882
+ snapshot.addChild(commonSnapshot);
883
+ // Create optimization entry
884
+ const newEntry = {
885
+ snapshot: commonSnapshot,
886
+ shared: optimizationEntry.shared + 1,
887
+ snapshotContent: new Set(commonMap.keys()),
888
+ children: undefined
889
+ };
890
+ if (optimizationEntry.children === undefined) {
891
+ optimizationEntry.children = new Set();
892
+ }
893
+ optimizationEntry.children.add(newEntry);
894
+ storeOptimizationEntry(newEntry);
895
+ this._statSharedSnapshots++;
896
+ }
897
+ } else {
898
+ // It's a unshared snapshot
899
+ // We can extract a common shared snapshot
900
+ // with all common files
901
+ const snapshotEntries = this._get(snapshot);
902
+ if (snapshotEntries === undefined) {
903
+ // Incomplete snapshot, that can't be used
904
+ continue;
905
+ }
906
+ /** @type {Set<string> | Map<string, T>} */
907
+ let commonMap;
908
+ if (this._isSet) {
909
+ commonMap = new Set();
910
+ const set = /** @type {Set<string>} */ (snapshotEntries);
911
+ if (capturedFiles.size < set.size) {
912
+ for (const path of capturedFiles) {
913
+ if (set.has(path)) commonMap.add(path);
914
+ }
915
+ } else {
916
+ for (const path of set) {
917
+ if (capturedFiles.has(path)) commonMap.add(path);
918
+ }
919
+ }
920
+ } else {
921
+ commonMap = new Map();
922
+ const map = /** @type {Map<string, T>} */ (snapshotEntries);
923
+ for (const path of capturedFiles) {
924
+ const ts = map.get(path);
925
+ if (ts === undefined) continue;
926
+ commonMap.set(path, ts);
927
+ }
928
+ }
929
+
930
+ if (commonMap.size < MIN_COMMON_SNAPSHOT_SIZE) {
931
+ // Common part it too small
932
+ continue;
933
+ }
934
+ // Create and attach snapshot
935
+ const commonSnapshot = new Snapshot();
936
+ if (this._useStartTime) {
937
+ commonSnapshot.setMergedStartTime(newSnapshot.startTime, snapshot);
938
+ }
939
+ this._set(
940
+ commonSnapshot,
941
+ /** @type {SnapshotOptimizationValue<U, T>} */
942
+ (commonMap)
943
+ );
944
+ newSnapshot.addChild(commonSnapshot);
945
+ snapshot.addChild(commonSnapshot);
946
+ // Remove files from snapshot
947
+ for (const path of commonMap.keys()) snapshotEntries.delete(path);
948
+ const sharedCount = commonMap.size;
949
+ this._statItemsUnshared -= sharedCount;
950
+ this._statItemsShared += sharedCount;
951
+ // Create optimization entry
952
+ storeOptimizationEntry({
953
+ snapshot: commonSnapshot,
954
+ shared: 2,
955
+ snapshotContent: new Set(commonMap.keys()),
956
+ children: undefined
957
+ });
958
+ this._statSharedSnapshots++;
959
+ }
960
+ }
961
+ const unshared = capturedFiles.size;
962
+ this._statItemsUnshared += unshared;
963
+ this._statItemsShared += capturedFilesSize - unshared;
964
+ }
965
+ }
966
+
967
+ /** @type {Record<string, string>} */
968
+ const ESCAPES = {
969
+ n: "\n",
970
+ r: "\r",
971
+ t: "\t",
972
+ b: "\b",
973
+ f: "\f",
974
+ v: "\v"
975
+ };
976
+
977
+ /**
978
+ * Cooks a JS string/template literal specifier into its evaluated value,
979
+ * matching ECMAScript escape semantics (sloppy-mode for string literals).
980
+ * @param {string} str input including the surrounding quotes
981
+ * @returns {string | null} result, or null when not a quoted literal
982
+ * @throws {Error} on a malformed escape sequence, like the JS parser would
983
+ */
984
+ const parseString = (str) => {
985
+ const q = str[0];
986
+
987
+ if (q !== '"' && q !== "'" && q !== "`") {
988
+ return null;
989
+ }
990
+
991
+ const template = q === "`";
992
+ const inner = str.slice(1, -1);
993
+ const len = inner.length;
994
+ let result = "";
995
+ let i = 0;
996
+
997
+ while (i < len) {
998
+ const ch = inner[i];
999
+ if (ch !== "\\") {
1000
+ // Template value normalizes raw <CR> and <CRLF> to <LF>
1001
+ if (template && ch === "\r") {
1002
+ result += "\n";
1003
+ i += inner[i + 1] === "\n" ? 2 : 1;
1004
+ } else {
1005
+ result += ch;
1006
+ i++;
1007
+ }
1008
+ continue;
1009
+ }
1010
+
1011
+ i++;
1012
+ if (i >= len) throw new Error("Unterminated escape sequence");
1013
+ const esc = inner[i];
1014
+
1015
+ if (esc === "x") {
1016
+ const hex = inner.slice(i + 1, i + 3);
1017
+ if (!/^[0-9a-fA-F]{2}$/.test(hex)) {
1018
+ throw new Error("Invalid hexadecimal escape sequence");
1019
+ }
1020
+ result += String.fromCharCode(Number.parseInt(hex, 16));
1021
+ i += 3;
1022
+ } else if (esc === "u") {
1023
+ if (inner[i + 1] === "{") {
1024
+ // \u{N...}
1025
+ const closeIdx = inner.indexOf("}", i + 2);
1026
+ const codeStr = closeIdx === -1 ? "" : inner.slice(i + 2, closeIdx);
1027
+ const code = Number.parseInt(codeStr, 16);
1028
+ if (!/^[0-9a-fA-F]+$/.test(codeStr) || code > 0x10ffff) {
1029
+ throw new Error("Invalid Unicode escape sequence");
1030
+ }
1031
+ result += String.fromCodePoint(code);
1032
+ i = closeIdx + 1;
1033
+ } else {
1034
+ // \uNNNN
1035
+ const hex = inner.slice(i + 1, i + 5);
1036
+ if (!/^[0-9a-fA-F]{4}$/.test(hex)) {
1037
+ throw new Error("Invalid Unicode escape sequence");
1038
+ }
1039
+ result += String.fromCharCode(Number.parseInt(hex, 16));
1040
+ i += 5;
1041
+ }
1042
+ } else if (esc === "\r") {
1043
+ // Line continuation: \<CR> or \<CRLF>
1044
+ i += inner[i + 1] === "\n" ? 2 : 1;
1045
+ } else if (esc === "\n" || esc === "\u2028" || esc === "\u2029") {
1046
+ // Line continuation: \<LF>, \<LS>, \<PS>
1047
+ i++;
1048
+ } else if (ESCAPES[esc] !== undefined) {
1049
+ result += ESCAPES[esc];
1050
+ i++;
1051
+ } else if (esc >= "0" && esc <= "7") {
1052
+ // \0 not followed by a digit is NUL, otherwise a legacy octal escape
1053
+ const next = inner[i + 1];
1054
+ if (esc === "0" && !(next >= "0" && next <= "9")) {
1055
+ result += "\0";
1056
+ i++;
1057
+ continue;
1058
+ }
1059
+ if (template) throw new Error("Octal escape not allowed in template");
1060
+ // Up to 3 octal digits, value capped at \377
1061
+ let oct = esc;
1062
+ i++;
1063
+ const max = esc <= "3" ? 3 : 2;
1064
+ while (oct.length < max && inner[i] >= "0" && inner[i] <= "7") {
1065
+ oct += inner[i];
1066
+ i++;
1067
+ }
1068
+ result += String.fromCharCode(Number.parseInt(oct, 8));
1069
+ } else if (esc === "8" || esc === "9") {
1070
+ if (template) throw new Error("\\8 and \\9 not allowed in template");
1071
+ result += esc;
1072
+ i++;
1073
+ } else {
1074
+ // \', \", \\, \`, and any other NonEscapeCharacter — the char itself
1075
+ result += esc;
1076
+ i++;
1077
+ }
1078
+ }
1079
+
1080
+ return result;
1081
+ };
1082
+
1083
+ /* istanbul ignore next */
1084
+ /**
1085
+ * Processes the provided mtime.
1086
+ * @param {number} mtime mtime
1087
+ */
1088
+ const applyMtime = (mtime) => {
1089
+ if (FS_ACCURACY > 1 && mtime % 2 !== 0) FS_ACCURACY = 1;
1090
+ else if (FS_ACCURACY > 10 && mtime % 20 !== 0) FS_ACCURACY = 10;
1091
+ else if (FS_ACCURACY > 100 && mtime % 200 !== 0) FS_ACCURACY = 100;
1092
+ else if (FS_ACCURACY > 1000 && mtime % 2000 !== 0) FS_ACCURACY = 1000;
1093
+ };
1094
+
1095
+ /**
1096
+ * Merges the provided values into a single result.
1097
+ * @template T
1098
+ * @template K
1099
+ * @param {Map<T, K> | undefined} a source map
1100
+ * @param {Map<T, K> | undefined} b joining map
1101
+ * @returns {Map<T, K>} joined map
1102
+ */
1103
+ const mergeMaps = (a, b) => {
1104
+ if (!b || b.size === 0) return /** @type {Map<T, K>} */ (a);
1105
+ if (!a || a.size === 0) return /** @type {Map<T, K>} */ (b);
1106
+ /** @type {Map<T, K>} */
1107
+ const map = new Map(a);
1108
+ for (const [key, value] of b) {
1109
+ map.set(key, value);
1110
+ }
1111
+ return map;
1112
+ };
1113
+
1114
+ /**
1115
+ * Merges the provided values into a single result.
1116
+ * @template T
1117
+ * @param {Set<T> | undefined} a source map
1118
+ * @param {Set<T> | undefined} b joining map
1119
+ * @returns {Set<T>} joined map
1120
+ */
1121
+ const mergeSets = (a, b) => {
1122
+ if (!b || b.size === 0) return /** @type {Set<T>} */ (a);
1123
+ if (!a || a.size === 0) return /** @type {Set<T>} */ (b);
1124
+ /** @type {Set<T>} */
1125
+ const map = new Set(a);
1126
+ for (const item of b) {
1127
+ map.add(item);
1128
+ }
1129
+ return map;
1130
+ };
1131
+
1132
+ /**
1133
+ * Finding file or directory to manage
1134
+ * @param {string} managedPath path that is managing by {@link FileSystemInfo}
1135
+ * @param {string} path path to file or directory
1136
+ * @returns {string | null} managed item
1137
+ * @example
1138
+ * getManagedItem(
1139
+ * '/Users/user/my-project/node_modules/',
1140
+ * '/Users/user/my-project/node_modules/package/index.js'
1141
+ * ) === '/Users/user/my-project/node_modules/package'
1142
+ * getManagedItem(
1143
+ * '/Users/user/my-project/node_modules/',
1144
+ * '/Users/user/my-project/node_modules/package1/node_modules/package2'
1145
+ * ) === '/Users/user/my-project/node_modules/package1/node_modules/package2'
1146
+ * getManagedItem(
1147
+ * '/Users/user/my-project/node_modules/',
1148
+ * '/Users/user/my-project/node_modules/.bin/script.js'
1149
+ * ) === null // hidden files are disallowed as managed items
1150
+ * getManagedItem(
1151
+ * '/Users/user/my-project/node_modules/',
1152
+ * '/Users/user/my-project/node_modules/package'
1153
+ * ) === '/Users/user/my-project/node_modules/package'
1154
+ */
1155
+ const getManagedItem = (managedPath, path) => {
1156
+ let i = managedPath.length;
1157
+ let slashes = 1;
1158
+ let startingPosition = true;
1159
+ loop: while (i < path.length) {
1160
+ switch (path.charCodeAt(i)) {
1161
+ case 47: // slash
1162
+ case 92: // backslash
1163
+ if (--slashes === 0) break loop;
1164
+ startingPosition = true;
1165
+ break;
1166
+ case 46: // .
1167
+ // hidden files are disallowed as managed items
1168
+ // it's probably .yarn-integrity or .cache
1169
+ if (startingPosition) return null;
1170
+ break;
1171
+ case 64: // @
1172
+ if (!startingPosition) return null;
1173
+ slashes++;
1174
+ break;
1175
+ default:
1176
+ startingPosition = false;
1177
+ break;
1178
+ }
1179
+ i++;
1180
+ }
1181
+ if (i === path.length) slashes--;
1182
+ // return null when path is incomplete
1183
+ if (slashes !== 0) return null;
1184
+ // if (path.slice(i + 1, i + 13) === "node_modules")
1185
+ if (
1186
+ path.length >= i + 13 &&
1187
+ path.charCodeAt(i + 1) === 110 &&
1188
+ path.charCodeAt(i + 2) === 111 &&
1189
+ path.charCodeAt(i + 3) === 100 &&
1190
+ path.charCodeAt(i + 4) === 101 &&
1191
+ path.charCodeAt(i + 5) === 95 &&
1192
+ path.charCodeAt(i + 6) === 109 &&
1193
+ path.charCodeAt(i + 7) === 111 &&
1194
+ path.charCodeAt(i + 8) === 100 &&
1195
+ path.charCodeAt(i + 9) === 117 &&
1196
+ path.charCodeAt(i + 10) === 108 &&
1197
+ path.charCodeAt(i + 11) === 101 &&
1198
+ path.charCodeAt(i + 12) === 115
1199
+ ) {
1200
+ // if this is the end of the path
1201
+ if (path.length === i + 13) {
1202
+ // return the node_modules directory
1203
+ // it's special
1204
+ return path;
1205
+ }
1206
+ const c = path.charCodeAt(i + 13);
1207
+ // if next symbol is slash or backslash
1208
+ if (c === 47 || c === 92) {
1209
+ // Managed subpath
1210
+ return getManagedItem(path.slice(0, i + 14), path);
1211
+ }
1212
+ }
1213
+ return path.slice(0, i);
1214
+ };
1215
+
1216
+ /**
1217
+ * The managed directory a `snapshot.managedPaths` RegExp matched. The schema
1218
+ * documents it as matching that directory, so a capture-less pattern is it.
1219
+ * @param {RegExpExecArray} match a match of a managed path RegExp
1220
+ * @returns {string} the managed directory
1221
+ */
1222
+ const getManagedPathFromMatch = (match) =>
1223
+ match[1] === undefined ? match[0] : match[1];
1224
+
1225
+ /**
1226
+ * Gets resolved timestamp.
1227
+ * @template {ContextFileSystemInfoEntry | ContextTimestampAndHash} T
1228
+ * @param {T | null} entry entry
1229
+ * @returns {T["resolved"] | null | undefined} the resolved entry
1230
+ */
1231
+ const getResolvedTimestamp = (entry) => {
1232
+ if (entry === null) return null;
1233
+ if (entry.resolved !== undefined) return entry.resolved;
1234
+ return entry.symlinks === undefined ? entry : undefined;
1235
+ };
1236
+
1237
+ /**
1238
+ * Gets resolved hash.
1239
+ * @param {ContextHash | null} entry entry
1240
+ * @returns {string | null | undefined} the resolved entry
1241
+ */
1242
+ const getResolvedHash = (entry) => {
1243
+ if (entry === null) return null;
1244
+ if (entry.resolved !== undefined) return entry.resolved;
1245
+ return entry.symlinks === undefined ? entry.hash : undefined;
1246
+ };
1247
+
1248
+ /**
1249
+ * Adds the provided source to the snapshot optimization.
1250
+ * @template T
1251
+ * @param {Set<T>} source source
1252
+ * @param {Set<T>} target target
1253
+ */
1254
+ const addAll = (source, target) => {
1255
+ for (const key of source) target.add(key);
1256
+ };
1257
+
1258
+ // Bun doesn't populate `require.cache` `module.children`, so the CJS build-dependency
1259
+ // walk needs a source-parsing fallback there. Node/Deno populate it — never pay for it.
1260
+ const IS_BUN = Boolean(process.versions.bun);
1261
+
1262
+ /** @typedef {Set<string>} LoggedPaths */
1263
+
1264
+ /** @typedef {FileSystemInfoEntry | ExistenceOnlyTimeEntry | "ignore" | null} FileTimestamp */
1265
+ /** @typedef {ContextFileSystemInfoEntry | ExistenceOnlyTimeEntry | "ignore" | null} ContextTimestamp */
1266
+ /** @typedef {ResolvedContextFileSystemInfoEntry | "ignore" | null} ResolvedContextTimestamp */
1267
+
1268
+ /**
1269
+ * `watchpack` may report `{}` (existence-only) for files and directories it
1270
+ * is watching but has no time information for. Such entries cannot be used
1271
+ * for snapshot comparison, so cache lookups treat them as "no cached value"
1272
+ * and fall back to a fresh on-disk read.
1273
+ * @param {FileTimestamp | ContextTimestamp | undefined} entry cache entry
1274
+ * @returns {entry is ExistenceOnlyTimeEntry} true if the entry exists but carries no time info
1275
+ */
1276
+ const isExistenceOnly = (entry) => {
1277
+ if (entry === undefined || entry === null || entry === "ignore") return false;
1278
+ return (
1279
+ /** @type {Partial<FileSystemInfoEntry> & Partial<ContextFileSystemInfoEntry>} */
1280
+ (entry).safeTime === undefined
1281
+ );
1282
+ };
1283
+
1284
+ /**
1285
+ * Watchpack directory entries may carry `safeTime` / `timestamp` but never
1286
+ * `timestampHash`; such object caches cannot back snapshot checks or symlink walks.
1287
+ * @param {ContextFileSystemInfoEntry | null | "ignore" | undefined} entry cache entry
1288
+ * @returns {boolean} true when a non-null object entry lacks `timestampHash`
1289
+ */
1290
+ const contextCacheEntryLacksTimestampHash = (entry) =>
1291
+ entry !== null &&
1292
+ typeof entry === "object" &&
1293
+ /** @type {ContextFileSystemInfoEntry} */ (entry).timestampHash === undefined;
1294
+
1295
+ /** @typedef {(err?: WebpackError | null, result?: boolean) => void} CheckSnapshotValidCallback */
1296
+
1297
+ /**
1298
+ * Used to access information about the filesystem in a cached way
1299
+ */
1300
+ class FileSystemInfo {
1301
+ /**
1302
+ * Creates an instance of FileSystemInfo.
1303
+ * @param {InputFileSystem} fs file system
1304
+ * @param {object} options options
1305
+ * @param {Iterable<string | RegExp>=} options.unmanagedPaths paths that are not managed by a package manager and the contents are subject to change
1306
+ * @param {Iterable<string | RegExp>=} options.managedPaths paths that are only managed by a package manager
1307
+ * @param {Iterable<string | RegExp>=} options.immutablePaths paths that are immutable
1308
+ * @param {Logger=} options.logger logger used to log invalid snapshots
1309
+ * @param {HashFunction=} options.hashFunction the hash function to use
1310
+ */
1311
+ constructor(
1312
+ fs,
1313
+ {
1314
+ unmanagedPaths = [],
1315
+ managedPaths = [],
1316
+ immutablePaths = [],
1317
+ logger,
1318
+ hashFunction = DEFAULTS.HASH_FUNCTION
1319
+ } = {}
1320
+ ) {
1321
+ /** @type {InputFileSystem} */
1322
+ this.fs = fs;
1323
+ this.logger = logger;
1324
+ /** @type {number} */
1325
+ this._remainingLogs = logger ? 40 : 0;
1326
+ /** @type {LoggedPaths | undefined} */
1327
+ this._loggedPaths = logger ? new Set() : undefined;
1328
+ /** @type {HashFunction} */
1329
+ this._hashFunction = hashFunction;
1330
+ /** @type {WeakMap<Snapshot, boolean | CheckSnapshotValidCallback[]>} */
1331
+ this._snapshotCache = new WeakMap();
1332
+ /** @type {SnapshotOptimization<FileSystemInfoEntry | null, false>} */
1333
+ this._fileTimestampsOptimization = new SnapshotOptimization(
1334
+ (s) => s.hasFileTimestamps(),
1335
+ (s) => s.fileTimestamps,
1336
+ (s, v) => s.setFileTimestamps(v)
1337
+ );
1338
+ /** @type {SnapshotOptimization<string | null, false>} */
1339
+ this._fileHashesOptimization = new SnapshotOptimization(
1340
+ (s) => s.hasFileHashes(),
1341
+ (s) => s.fileHashes,
1342
+ (s, v) => s.setFileHashes(v),
1343
+ false
1344
+ );
1345
+ /** @type {SnapshotOptimization<string | TimestampAndHash | null, false>} */
1346
+ this._fileTshsOptimization = new SnapshotOptimization(
1347
+ (s) => s.hasFileTshs(),
1348
+ (s) => s.fileTshs,
1349
+ (s, v) => s.setFileTshs(v)
1350
+ );
1351
+ /** @type {SnapshotOptimization<ResolvedContextFileSystemInfoEntry | null, false>} */
1352
+ this._contextTimestampsOptimization = new SnapshotOptimization(
1353
+ (s) => s.hasContextTimestamps(),
1354
+ (s) => s.contextTimestamps,
1355
+ (s, v) => s.setContextTimestamps(v)
1356
+ );
1357
+ /** @type {SnapshotOptimization<string | null, false>} */
1358
+ this._contextHashesOptimization = new SnapshotOptimization(
1359
+ (s) => s.hasContextHashes(),
1360
+ (s) => s.contextHashes,
1361
+ (s, v) => s.setContextHashes(v),
1362
+ false
1363
+ );
1364
+ /** @type {SnapshotOptimization<ResolvedContextTimestampAndHash | null, false>} */
1365
+ this._contextTshsOptimization = new SnapshotOptimization(
1366
+ (s) => s.hasContextTshs(),
1367
+ (s) => s.contextTshs,
1368
+ (s, v) => s.setContextTshs(v)
1369
+ );
1370
+ /** @type {SnapshotOptimization<boolean, false>} */
1371
+ this._missingExistenceOptimization = new SnapshotOptimization(
1372
+ (s) => s.hasMissingExistence(),
1373
+ (s) => s.missingExistence,
1374
+ (s, v) => s.setMissingExistence(v),
1375
+ false
1376
+ );
1377
+ /** @type {SnapshotOptimization<string, false>} */
1378
+ this._managedItemInfoOptimization = new SnapshotOptimization(
1379
+ (s) => s.hasManagedItemInfo(),
1380
+ (s) => s.managedItemInfo,
1381
+ (s, v) => s.setManagedItemInfo(v),
1382
+ false
1383
+ );
1384
+ this._managedFilesOptimization = new SnapshotOptimization(
1385
+ (s) => s.hasManagedFiles(),
1386
+ (s) => s.managedFiles,
1387
+ (s, v) => s.setManagedFiles(v),
1388
+ false,
1389
+ true
1390
+ );
1391
+ this._managedContextsOptimization = new SnapshotOptimization(
1392
+ (s) => s.hasManagedContexts(),
1393
+ (s) => s.managedContexts,
1394
+ (s, v) => s.setManagedContexts(v),
1395
+ false,
1396
+ true
1397
+ );
1398
+ this._managedMissingOptimization = new SnapshotOptimization(
1399
+ (s) => s.hasManagedMissing(),
1400
+ (s) => s.managedMissing,
1401
+ (s, v) => s.setManagedMissing(v),
1402
+ false,
1403
+ true
1404
+ );
1405
+ /** @type {StackedCacheMap<string, FileTimestamp>} */
1406
+ this._fileTimestamps = new StackedCacheMap();
1407
+ /** @type {Map<string, string | null>} */
1408
+ this._fileHashes = new Map();
1409
+ /** @type {Map<string, TimestampAndHash | string>} */
1410
+ this._fileTshs = new Map();
1411
+ /** @type {StackedCacheMap<string, ContextTimestamp>} */
1412
+ this._contextTimestamps = new StackedCacheMap();
1413
+ /** @type {Map<string, ContextHash>} */
1414
+ this._contextHashes = new Map();
1415
+ /** @type {Map<string, ContextTimestampAndHash>} */
1416
+ this._contextTshs = new Map();
1417
+ /** @type {Map<string, string>} */
1418
+ this._managedItems = new Map();
1419
+ // memoized checkManaged results: 0 = not managed, 1 = immutable, string = managed item
1420
+ /** @type {Map<string, 0 | 1 | string>} */
1421
+ this._pathClassificationCache = new Map();
1422
+ /** @type {AsyncQueue<string, string, FileSystemInfoEntry>} */
1423
+ this.fileTimestampQueue = new AsyncQueue({
1424
+ name: "file timestamp",
1425
+ parallelism: 30,
1426
+ processor: this._readFileTimestamp.bind(this)
1427
+ });
1428
+ /** @type {AsyncQueue<string, string, string>} */
1429
+ this.fileHashQueue = new AsyncQueue({
1430
+ name: "file hash",
1431
+ parallelism: 10,
1432
+ processor: this._readFileHash.bind(this)
1433
+ });
1434
+ /** @type {AsyncQueue<string, string, ContextFileSystemInfoEntry>} */
1435
+ this.contextTimestampQueue = new AsyncQueue({
1436
+ name: "context timestamp",
1437
+ parallelism: 2,
1438
+ processor: this._readContextTimestamp.bind(this)
1439
+ });
1440
+ /** @type {AsyncQueue<string, string, ContextHash>} */
1441
+ this.contextHashQueue = new AsyncQueue({
1442
+ name: "context hash",
1443
+ parallelism: 2,
1444
+ processor: this._readContextHash.bind(this)
1445
+ });
1446
+ /** @type {AsyncQueue<string, string, ContextTimestampAndHash>} */
1447
+ this.contextTshQueue = new AsyncQueue({
1448
+ name: "context hash and timestamp",
1449
+ parallelism: 2,
1450
+ processor: this._readContextTimestampAndHash.bind(this)
1451
+ });
1452
+ /** @type {AsyncQueue<string, string, string>} */
1453
+ this.managedItemQueue = new AsyncQueue({
1454
+ name: "managed item info",
1455
+ parallelism: 10,
1456
+ processor: this._getManagedItemInfo.bind(this)
1457
+ });
1458
+ /** @type {AsyncQueue<string, string, Set<string>>} */
1459
+ this.managedItemDirectoryQueue = new AsyncQueue({
1460
+ name: "managed item directory info",
1461
+ parallelism: 10,
1462
+ processor: this._getManagedItemDirectoryInfo.bind(this)
1463
+ });
1464
+ const _unmanagedPaths = [...unmanagedPaths];
1465
+ /** @type {string[]} */
1466
+ this.unmanagedPathsWithSlash = _unmanagedPaths
1467
+ .filter((p) => typeof p === "string")
1468
+ .map((p) => join(fs, p, "_").slice(0, -1));
1469
+ /** @type {RegExp[]} */
1470
+ this.unmanagedPathsRegExps = _unmanagedPaths.filter(
1471
+ (p) => typeof p !== "string"
1472
+ );
1473
+
1474
+ this.managedPaths = [...managedPaths];
1475
+ /** @type {string[]} */
1476
+ this.managedPathsWithSlash = this.managedPaths
1477
+ .filter((p) => typeof p === "string")
1478
+ .map((p) => join(fs, p, "_").slice(0, -1));
1479
+ /** @type {RegExp[]} */
1480
+ this.managedPathsRegExps = this.managedPaths.filter(
1481
+ (p) => typeof p !== "string"
1482
+ );
1483
+
1484
+ this.immutablePaths = [...immutablePaths];
1485
+ /** @type {string[]} */
1486
+ this.immutablePathsWithSlash = this.immutablePaths
1487
+ .filter((p) => typeof p === "string")
1488
+ .map((p) => join(fs, p, "_").slice(0, -1));
1489
+ /** @type {RegExp[]} */
1490
+ this.immutablePathsRegExps = this.immutablePaths.filter(
1491
+ (p) => typeof p !== "string"
1492
+ );
1493
+
1494
+ /** @type {Map<string, number | null> | undefined} */
1495
+ this._cachedDeprecatedFileTimestamps = undefined;
1496
+ /** @type {Map<string, number | null> | undefined} */
1497
+ this._cachedDeprecatedContextTimestamps = undefined;
1498
+
1499
+ /** @type {boolean} */
1500
+ this._warnAboutExperimentalEsmTracking = false;
1501
+
1502
+ /** @type {number} */
1503
+ this._statCreatedSnapshots = 0;
1504
+ /** @type {number} */
1505
+ this._statTestedSnapshotsCached = 0;
1506
+ /** @type {number} */
1507
+ this._statTestedSnapshotsNotCached = 0;
1508
+ /** @type {number} */
1509
+ this._statTestedChildrenCached = 0;
1510
+ /** @type {number} */
1511
+ this._statTestedChildrenNotCached = 0;
1512
+ /** @type {number} */
1513
+ this._statTestedEntries = 0;
1514
+ }
1515
+
1516
+ logStatistics() {
1517
+ const logger = /** @type {Logger} */ (this.logger);
1518
+ /**
1519
+ * Processes the provided header.
1520
+ * @param {string} header header
1521
+ * @param {string | undefined} message message
1522
+ */
1523
+ const logWhenMessage = (header, message) => {
1524
+ if (message) {
1525
+ logger.log(`${header}: ${message}`);
1526
+ }
1527
+ };
1528
+ logger.log(`${this._statCreatedSnapshots} new snapshots created`);
1529
+ logger.log(
1530
+ `${
1531
+ this._statTestedSnapshotsNotCached &&
1532
+ Math.round(
1533
+ (this._statTestedSnapshotsNotCached * 100) /
1534
+ (this._statTestedSnapshotsCached +
1535
+ this._statTestedSnapshotsNotCached)
1536
+ )
1537
+ }% root snapshot uncached (${this._statTestedSnapshotsNotCached} / ${
1538
+ this._statTestedSnapshotsCached + this._statTestedSnapshotsNotCached
1539
+ })`
1540
+ );
1541
+ logger.log(
1542
+ `${
1543
+ this._statTestedChildrenNotCached &&
1544
+ Math.round(
1545
+ (this._statTestedChildrenNotCached * 100) /
1546
+ (this._statTestedChildrenCached + this._statTestedChildrenNotCached)
1547
+ )
1548
+ }% children snapshot uncached (${this._statTestedChildrenNotCached} / ${
1549
+ this._statTestedChildrenCached + this._statTestedChildrenNotCached
1550
+ })`
1551
+ );
1552
+ logger.log(`${this._statTestedEntries} entries tested`);
1553
+ logger.log(
1554
+ `File info in cache: ${this._fileTimestamps.size} timestamps ${this._fileHashes.size} hashes ${this._fileTshs.size} timestamp hash combinations`
1555
+ );
1556
+ logWhenMessage(
1557
+ "File timestamp snapshot optimization",
1558
+ this._fileTimestampsOptimization.getStatisticMessage()
1559
+ );
1560
+ logWhenMessage(
1561
+ "File hash snapshot optimization",
1562
+ this._fileHashesOptimization.getStatisticMessage()
1563
+ );
1564
+ logWhenMessage(
1565
+ "File timestamp hash combination snapshot optimization",
1566
+ this._fileTshsOptimization.getStatisticMessage()
1567
+ );
1568
+ logger.log(
1569
+ `Directory info in cache: ${this._contextTimestamps.size} timestamps ${this._contextHashes.size} hashes ${this._contextTshs.size} timestamp hash combinations`
1570
+ );
1571
+ logWhenMessage(
1572
+ "Directory timestamp snapshot optimization",
1573
+ this._contextTimestampsOptimization.getStatisticMessage()
1574
+ );
1575
+ logWhenMessage(
1576
+ "Directory hash snapshot optimization",
1577
+ this._contextHashesOptimization.getStatisticMessage()
1578
+ );
1579
+ logWhenMessage(
1580
+ "Directory timestamp hash combination snapshot optimization",
1581
+ this._contextTshsOptimization.getStatisticMessage()
1582
+ );
1583
+ logWhenMessage(
1584
+ "Missing items snapshot optimization",
1585
+ this._missingExistenceOptimization.getStatisticMessage()
1586
+ );
1587
+ logger.log(`Managed items info in cache: ${this._managedItems.size} items`);
1588
+ logWhenMessage(
1589
+ "Managed items snapshot optimization",
1590
+ this._managedItemInfoOptimization.getStatisticMessage()
1591
+ );
1592
+ logWhenMessage(
1593
+ "Managed files snapshot optimization",
1594
+ this._managedFilesOptimization.getStatisticMessage()
1595
+ );
1596
+ logWhenMessage(
1597
+ "Managed contexts snapshot optimization",
1598
+ this._managedContextsOptimization.getStatisticMessage()
1599
+ );
1600
+ logWhenMessage(
1601
+ "Managed missing snapshot optimization",
1602
+ this._managedMissingOptimization.getStatisticMessage()
1603
+ );
1604
+ }
1605
+
1606
+ /**
1607
+ * Processes the provided path.
1608
+ * @private
1609
+ * @param {string} path path
1610
+ * @param {string} reason reason
1611
+ * @param {EXPECTED_ANY[]} args arguments
1612
+ */
1613
+ _log(path, reason, ...args) {
1614
+ const key = path + reason;
1615
+ const loggedPaths = /** @type {LoggedPaths} */ (this._loggedPaths);
1616
+ if (loggedPaths.has(key)) return;
1617
+ loggedPaths.add(key);
1618
+ /** @type {Logger} */
1619
+ (this.logger).debug(`${path} invalidated because ${reason}`, ...args);
1620
+ if (--this._remainingLogs === 0) {
1621
+ /** @type {Logger} */
1622
+ (this.logger).debug(
1623
+ "Logging limit has been reached and no further logging will be emitted by FileSystemInfo"
1624
+ );
1625
+ }
1626
+ }
1627
+
1628
+ clear() {
1629
+ this._remainingLogs = this.logger ? 40 : 0;
1630
+ if (this._loggedPaths !== undefined) this._loggedPaths.clear();
1631
+
1632
+ this._snapshotCache = new WeakMap();
1633
+ this._fileTimestampsOptimization.clear();
1634
+ this._fileHashesOptimization.clear();
1635
+ this._fileTshsOptimization.clear();
1636
+ this._contextTimestampsOptimization.clear();
1637
+ this._contextHashesOptimization.clear();
1638
+ this._contextTshsOptimization.clear();
1639
+ this._missingExistenceOptimization.clear();
1640
+ this._managedItemInfoOptimization.clear();
1641
+ this._managedFilesOptimization.clear();
1642
+ this._managedContextsOptimization.clear();
1643
+ this._managedMissingOptimization.clear();
1644
+ this._fileTimestamps.clear();
1645
+ this._fileHashes.clear();
1646
+ this._fileTshs.clear();
1647
+ this._contextTimestamps.clear();
1648
+ this._contextHashes.clear();
1649
+ this._contextTshs.clear();
1650
+ this._managedItems.clear();
1651
+ this._pathClassificationCache.clear();
1652
+
1653
+ this._cachedDeprecatedFileTimestamps = undefined;
1654
+ this._cachedDeprecatedContextTimestamps = undefined;
1655
+
1656
+ this._statCreatedSnapshots = 0;
1657
+ this._statTestedSnapshotsCached = 0;
1658
+ this._statTestedSnapshotsNotCached = 0;
1659
+ this._statTestedChildrenCached = 0;
1660
+ this._statTestedChildrenNotCached = 0;
1661
+ this._statTestedEntries = 0;
1662
+ }
1663
+
1664
+ /**
1665
+ * Adds file timestamps.
1666
+ * @param {ReadonlyMap<string, FileTimestamp>} map timestamps
1667
+ * @param {boolean=} immutable if 'map' is immutable and FileSystemInfo can keep referencing it
1668
+ * @returns {void}
1669
+ */
1670
+ addFileTimestamps(map, immutable) {
1671
+ this._fileTimestamps.addAll(map, immutable);
1672
+ this._cachedDeprecatedFileTimestamps = undefined;
1673
+ }
1674
+
1675
+ /**
1676
+ * Adds context timestamps.
1677
+ * @param {ReadonlyMap<string, ContextTimestamp>} map timestamps
1678
+ * @param {boolean=} immutable if 'map' is immutable and FileSystemInfo can keep referencing it
1679
+ * @returns {void}
1680
+ */
1681
+ addContextTimestamps(map, immutable) {
1682
+ this._contextTimestamps.addAll(map, immutable);
1683
+ this._cachedDeprecatedContextTimestamps = undefined;
1684
+ }
1685
+
1686
+ /**
1687
+ * Gets file timestamp.
1688
+ * @param {string} path file path
1689
+ * @param {(err?: WebpackError | null, fileTimestamp?: FileSystemInfoEntry | "ignore" | null) => void} callback callback function
1690
+ * @returns {void}
1691
+ */
1692
+ getFileTimestamp(path, callback) {
1693
+ const cache = this._fileTimestamps.get(path);
1694
+ if (cache !== undefined && !isExistenceOnly(cache)) {
1695
+ return callback(
1696
+ null,
1697
+ /** @type {FileSystemInfoEntry | "ignore" | null} */ (cache)
1698
+ );
1699
+ }
1700
+ this.fileTimestampQueue.add(path, callback);
1701
+ }
1702
+
1703
+ /**
1704
+ * Gets context timestamp.
1705
+ * @param {string} path context path
1706
+ * @param {(err?: WebpackError | null, resolvedContextTimestamp?: ResolvedContextTimestamp) => void} callback callback function
1707
+ * @returns {void}
1708
+ */
1709
+ getContextTimestamp(path, callback) {
1710
+ const cache = this._contextTimestamps.get(path);
1711
+ if (cache !== undefined && !isExistenceOnly(cache)) {
1712
+ if (cache === "ignore") return callback(null, "ignore");
1713
+ const fullEntry =
1714
+ /** @type {ContextFileSystemInfoEntry | null} */
1715
+ (cache);
1716
+ const resolved = getResolvedTimestamp(fullEntry);
1717
+ if (resolved !== undefined) return callback(null, resolved);
1718
+ return this._resolveContextTimestamp(
1719
+ /** @type {ContextFileSystemInfoEntry} */
1720
+ (fullEntry),
1721
+ callback
1722
+ );
1723
+ }
1724
+ this._readFreshContextTimestamp(path, callback);
1725
+ }
1726
+
1727
+ /**
1728
+ * Reads a context timestamp directly from disk, bypassing any cached
1729
+ * entry. Used by `getContextTimestamp` and the snapshot validity
1730
+ * checks when the cached entry is missing or is an `ExistenceOnlyTimeEntry`
1731
+ * (`{}`) supplied by watchpack — both cases require a fresh read to
1732
+ * obtain the `timestampHash`.
1733
+ * @private
1734
+ * @param {string} path context path
1735
+ * @param {(err?: WebpackError | null, resolvedContextTimestamp?: ResolvedContextTimestamp) => void} callback callback function
1736
+ * @returns {void}
1737
+ */
1738
+ _readFreshContextTimestamp(path, callback) {
1739
+ this.contextTimestampQueue.add(path, (err, _entry) => {
1740
+ if (err) return callback(err);
1741
+ const entry = /** @type {ContextFileSystemInfoEntry | null} */ (_entry);
1742
+ if (entry === null) return callback(null, null);
1743
+ const resolved = getResolvedTimestamp(entry);
1744
+ if (resolved !== undefined) return callback(null, resolved);
1745
+ this._resolveContextTimestamp(entry, callback);
1746
+ });
1747
+ }
1748
+
1749
+ /**
1750
+ * Get unresolved context timestamp. Existence-only cache entries (`{}`)
1751
+ * are bypassed so the callback always receives a complete entry, "ignore"
1752
+ * or null.
1753
+ * @private
1754
+ * @param {string} path context path
1755
+ * @param {(err?: WebpackError | null, contextTimestamp?: ContextFileSystemInfoEntry | "ignore" | null) => void} callback callback function
1756
+ * @returns {void}
1757
+ */
1758
+ _getUnresolvedContextTimestamp(path, callback) {
1759
+ const cache = this._contextTimestamps.get(path);
1760
+ if (
1761
+ cache !== undefined &&
1762
+ !isExistenceOnly(cache) &&
1763
+ !contextCacheEntryLacksTimestampHash(
1764
+ /** @type {ContextFileSystemInfoEntry | null | "ignore"} */ (cache)
1765
+ )
1766
+ ) {
1767
+ return callback(
1768
+ null,
1769
+ /** @type {ContextFileSystemInfoEntry | "ignore" | null} */ (cache)
1770
+ );
1771
+ }
1772
+ this.contextTimestampQueue.add(path, callback);
1773
+ }
1774
+
1775
+ /**
1776
+ * Returns file hash.
1777
+ * @param {string} path file path
1778
+ * @param {(err?: WebpackError | null, hash?: string | null) => void} callback callback function
1779
+ * @returns {void}
1780
+ */
1781
+ getFileHash(path, callback) {
1782
+ const cache = this._fileHashes.get(path);
1783
+ if (cache !== undefined) return callback(null, cache);
1784
+ this.fileHashQueue.add(path, callback);
1785
+ }
1786
+
1787
+ /**
1788
+ * Returns context hash.
1789
+ * @param {string} path context path
1790
+ * @param {(err?: WebpackError | null, contextHash?: string) => void} callback callback function
1791
+ * @returns {void}
1792
+ */
1793
+ getContextHash(path, callback) {
1794
+ const cache = this._contextHashes.get(path);
1795
+ if (cache !== undefined) {
1796
+ const resolved = getResolvedHash(cache);
1797
+ if (resolved !== undefined) {
1798
+ return callback(null, /** @type {string} */ (resolved));
1799
+ }
1800
+ return this._resolveContextHash(cache, callback);
1801
+ }
1802
+ this.contextHashQueue.add(path, (err, _entry) => {
1803
+ if (err) return callback(err);
1804
+ const entry = /** @type {ContextHash} */ (_entry);
1805
+ const resolved = getResolvedHash(entry);
1806
+ if (resolved !== undefined) {
1807
+ return callback(null, /** @type {string} */ (resolved));
1808
+ }
1809
+ this._resolveContextHash(entry, callback);
1810
+ });
1811
+ }
1812
+
1813
+ /**
1814
+ * Get unresolved context hash.
1815
+ * @private
1816
+ * @param {string} path context path
1817
+ * @param {(err?: WebpackError | null, contextHash?: ContextHash | null) => void} callback callback function
1818
+ * @returns {void}
1819
+ */
1820
+ _getUnresolvedContextHash(path, callback) {
1821
+ const cache = this._contextHashes.get(path);
1822
+ if (cache !== undefined) return callback(null, cache);
1823
+ this.contextHashQueue.add(path, callback);
1824
+ }
1825
+
1826
+ /**
1827
+ * Returns context tsh.
1828
+ * @param {string} path context path
1829
+ * @param {(err?: WebpackError | null, resolvedContextTimestampAndHash?: ResolvedContextTimestampAndHash | null) => void} callback callback function
1830
+ * @returns {void}
1831
+ */
1832
+ getContextTsh(path, callback) {
1833
+ const cache = this._contextTshs.get(path);
1834
+ if (cache !== undefined) {
1835
+ const resolved = getResolvedTimestamp(cache);
1836
+ if (resolved !== undefined) return callback(null, resolved);
1837
+ return this._resolveContextTsh(cache, callback);
1838
+ }
1839
+ this.contextTshQueue.add(path, (err, _entry) => {
1840
+ if (err) return callback(err);
1841
+ const entry = /** @type {ContextTimestampAndHash} */ (_entry);
1842
+ const resolved = getResolvedTimestamp(entry);
1843
+ if (resolved !== undefined) return callback(null, resolved);
1844
+ this._resolveContextTsh(entry, callback);
1845
+ });
1846
+ }
1847
+
1848
+ /**
1849
+ * Get unresolved context tsh.
1850
+ * @private
1851
+ * @param {string} path context path
1852
+ * @param {(err?: WebpackError | null, contextTimestampAndHash?: ContextTimestampAndHash | null) => void} callback callback function
1853
+ * @returns {void}
1854
+ */
1855
+ _getUnresolvedContextTsh(path, callback) {
1856
+ const cache = this._contextTshs.get(path);
1857
+ if (cache !== undefined) return callback(null, cache);
1858
+ this.contextTshQueue.add(path, callback);
1859
+ }
1860
+
1861
+ _createBuildDependenciesResolvers() {
1862
+ const resolveContext = createResolver({
1863
+ resolveToContext: true,
1864
+ exportsFields: [],
1865
+ fileSystem: this.fs
1866
+ });
1867
+ const resolveCjs = createResolver({
1868
+ extensions: [".js", ".json", ".node"],
1869
+ conditionNames: ["require", "module-sync", "node"],
1870
+ exportsFields: ["exports"],
1871
+ fileSystem: this.fs
1872
+ });
1873
+ const resolveCjsAsChild = createResolver({
1874
+ extensions: [".js", ".json", ".node"],
1875
+ conditionNames: ["require", "module-sync", "node"],
1876
+ exportsFields: [],
1877
+ fileSystem: this.fs
1878
+ });
1879
+ const resolveEsm = createResolver({
1880
+ extensions: [".js", ".json", ".node"],
1881
+ fullySpecified: true,
1882
+ conditionNames: ["import", "module-sync", "node"],
1883
+ exportsFields: ["exports"],
1884
+ fileSystem: this.fs
1885
+ });
1886
+ return { resolveContext, resolveEsm, resolveCjs, resolveCjsAsChild };
1887
+ }
1888
+
1889
+ /**
1890
+ * Resolves build dependencies.
1891
+ * @param {string} context context directory
1892
+ * @param {Iterable<string>} deps dependencies
1893
+ * @param {Iterable<string> | undefined} optionalDeps optional dependencies that may be missing
1894
+ * @param {(err?: Error | null, resolveBuildDependenciesResult?: ResolveBuildDependenciesResult) => void} callback callback function
1895
+ * @returns {void}
1896
+ */
1897
+ resolveBuildDependencies(context, deps, optionalDeps, callback) {
1898
+ /** @type {Set<string>} */
1899
+ const optional = new Set(optionalDeps);
1900
+ const { resolveContext, resolveEsm, resolveCjs, resolveCjsAsChild } =
1901
+ this._createBuildDependenciesResolvers();
1902
+
1903
+ /** @type {Files} */
1904
+ const files = new Set();
1905
+ /** @type {Symlinks} */
1906
+ const fileSymlinks = new Set();
1907
+ /** @type {Directories} */
1908
+ const directories = new Set();
1909
+ /** @type {Symlinks} */
1910
+ const directorySymlinks = new Set();
1911
+ /** @type {Missing} */
1912
+ const missing = new Set();
1913
+ /** @type {ResolveDependencies["files"]} */
1914
+ const resolveFiles = new Set();
1915
+ /** @type {ResolveDependencies["directories"]} */
1916
+ const resolveDirectories = new Set();
1917
+ /** @type {ResolveDependencies["missing"]} */
1918
+ const resolveMissing = new Set();
1919
+ /** @type {ResolveResults} */
1920
+ const resolveResults = new Map();
1921
+ /** @type {Set<string>} */
1922
+ const invalidResolveResults = new Set();
1923
+ const resolverContext = {
1924
+ fileDependencies: resolveFiles,
1925
+ contextDependencies: resolveDirectories,
1926
+ missingDependencies: resolveMissing
1927
+ };
1928
+ /**
1929
+ * Expected to string.
1930
+ * @param {undefined | boolean | string} expected expected result
1931
+ * @returns {string} expected result
1932
+ */
1933
+ const expectedToString = (expected) =>
1934
+ expected ? ` (expected ${expected})` : "";
1935
+ /** @typedef {{ type: JobType, context: string | undefined, path: string, issuer: Job | undefined, expected: undefined | boolean | string }} Job */
1936
+
1937
+ /**
1938
+ * Returns result.
1939
+ * @param {Job} job job
1940
+ * @returns {string} result
1941
+ */
1942
+ const jobToString = (job) => {
1943
+ switch (job.type) {
1944
+ case RBDT_RESOLVE_FILE:
1945
+ return `resolve file ${job.path}${expectedToString(job.expected)}`;
1946
+ case RBDT_RESOLVE_DIRECTORY:
1947
+ return `resolve directory ${job.path}`;
1948
+ case RBDT_RESOLVE_CJS_FILE:
1949
+ return `resolve commonjs file ${job.path}${expectedToString(
1950
+ job.expected
1951
+ )}`;
1952
+ case RBDT_RESOLVE_ESM_FILE:
1953
+ return `resolve esm file ${job.path}${expectedToString(
1954
+ job.expected
1955
+ )}`;
1956
+ case RBDT_DIRECTORY:
1957
+ return `directory ${job.path}`;
1958
+ case RBDT_FILE:
1959
+ return `file ${job.path}`;
1960
+ case RBDT_DIRECTORY_DEPENDENCIES:
1961
+ return `directory dependencies ${job.path}`;
1962
+ case RBDT_FILE_DEPENDENCIES:
1963
+ return `file dependencies ${job.path}`;
1964
+ }
1965
+ return `unknown ${job.type} ${job.path}`;
1966
+ };
1967
+ /**
1968
+ * Returns string value.
1969
+ * @param {Job} job job
1970
+ * @returns {string} string value
1971
+ */
1972
+ const pathToString = (job) => {
1973
+ let result = ` at ${jobToString(job)}`;
1974
+ /** @type {Job | undefined} */
1975
+ (job) = job.issuer;
1976
+ while (job !== undefined) {
1977
+ result += `\n at ${jobToString(job)}`;
1978
+ job = /** @type {Job} */ (job.issuer);
1979
+ }
1980
+ return result;
1981
+ };
1982
+ const logger = /** @type {Logger} */ (this.logger);
1983
+ processAsyncTree(
1984
+ Array.from(
1985
+ deps,
1986
+ (dep) =>
1987
+ /** @type {Job} */ ({
1988
+ type: RBDT_RESOLVE_INITIAL,
1989
+ context,
1990
+ path: dep,
1991
+ expected: optional.has(dep) ? false : undefined,
1992
+ issuer: undefined
1993
+ })
1994
+ ),
1995
+ 20,
1996
+ (job, push, callback) => {
1997
+ const { type, context, path, expected } = job;
1998
+ /**
1999
+ * Resolves directory.
2000
+ * @param {string} path path
2001
+ * @returns {void}
2002
+ */
2003
+ const resolveDirectory = (path) => {
2004
+ const key = `d\n${context}\n${path}`;
2005
+ if (resolveResults.has(key)) {
2006
+ return callback();
2007
+ }
2008
+ resolveResults.set(key, undefined);
2009
+ resolveContext(
2010
+ /** @type {string} */ (context),
2011
+ path,
2012
+ resolverContext,
2013
+ (err, _, result) => {
2014
+ if (err) {
2015
+ if (expected === false) {
2016
+ resolveResults.set(key, false);
2017
+ resolveMissing.add(path);
2018
+ return callback();
2019
+ }
2020
+ invalidResolveResults.add(key);
2021
+ err.message += `\nwhile resolving '${path}' in ${context} to a directory`;
2022
+ return callback(err);
2023
+ }
2024
+ const resultPath = /** @type {ResolveRequest} */ (result).path;
2025
+ resolveResults.set(key, resultPath);
2026
+ push({
2027
+ type: RBDT_DIRECTORY,
2028
+ context: undefined,
2029
+ path: /** @type {string} */ (resultPath),
2030
+ expected: undefined,
2031
+ issuer: job
2032
+ });
2033
+ callback();
2034
+ }
2035
+ );
2036
+ };
2037
+ /**
2038
+ * Processes the provided path.
2039
+ * @param {string} path path
2040
+ * @param {("f" | "c" | "e")=} symbol symbol
2041
+ * @param {(ResolveFunctionAsync)=} resolve resolve fn
2042
+ * @returns {void}
2043
+ */
2044
+ const resolveFile = (path, symbol, resolve) => {
2045
+ const key = `${symbol}\n${context}\n${path}`;
2046
+ if (resolveResults.has(key)) {
2047
+ return callback();
2048
+ }
2049
+ resolveResults.set(key, undefined);
2050
+ /** @type {ResolveFunctionAsync} */
2051
+ (resolve)(
2052
+ /** @type {string} */ (context),
2053
+ path,
2054
+ resolverContext,
2055
+ (err, _, result) => {
2056
+ if (typeof expected === "string") {
2057
+ if (!err && result && result.path === expected) {
2058
+ resolveResults.set(key, result.path);
2059
+ } else {
2060
+ invalidResolveResults.add(key);
2061
+ logger.warn(
2062
+ `Resolving '${path}' in ${context} for build dependencies doesn't lead to expected result '${expected}', but to '${
2063
+ err || (result && result.path)
2064
+ }' instead. Resolving dependencies are ignored for this path.\n${pathToString(
2065
+ job
2066
+ )}`
2067
+ );
2068
+ }
2069
+ } else {
2070
+ if (err) {
2071
+ if (expected === false) {
2072
+ resolveResults.set(key, false);
2073
+ resolveMissing.add(path);
2074
+ return callback();
2075
+ }
2076
+ invalidResolveResults.add(key);
2077
+ err.message += `\nwhile resolving '${path}' in ${context} as file\n${pathToString(
2078
+ job
2079
+ )}`;
2080
+ return callback(err);
2081
+ }
2082
+ const resultPath = /** @type {ResolveRequest} */ (result).path;
2083
+ resolveResults.set(key, resultPath);
2084
+ push({
2085
+ type: RBDT_FILE,
2086
+ context: undefined,
2087
+ path: /** @type {string} */ (resultPath),
2088
+ expected: undefined,
2089
+ issuer: job
2090
+ });
2091
+ }
2092
+ callback();
2093
+ }
2094
+ );
2095
+ };
2096
+ const resolvedType =
2097
+ type === RBDT_RESOLVE_INITIAL
2098
+ ? /[\\/]$/.test(path)
2099
+ ? RBDT_RESOLVE_DIRECTORY
2100
+ : RBDT_RESOLVE_FILE
2101
+ : type;
2102
+ switch (resolvedType) {
2103
+ case RBDT_RESOLVE_FILE: {
2104
+ resolveFile(
2105
+ path,
2106
+ "f",
2107
+ /\.mjs$/.test(path) ? resolveEsm : resolveCjs
2108
+ );
2109
+ break;
2110
+ }
2111
+ case RBDT_RESOLVE_DIRECTORY: {
2112
+ resolveDirectory(
2113
+ type === RBDT_RESOLVE_INITIAL ? path.slice(0, -1) : path
2114
+ );
2115
+ break;
2116
+ }
2117
+ case RBDT_RESOLVE_CJS_FILE: {
2118
+ resolveFile(path, "f", resolveCjs);
2119
+ break;
2120
+ }
2121
+ case RBDT_RESOLVE_CJS_FILE_AS_CHILD: {
2122
+ resolveFile(path, "c", resolveCjsAsChild);
2123
+ break;
2124
+ }
2125
+ case RBDT_RESOLVE_ESM_FILE: {
2126
+ resolveFile(path, "e", resolveEsm);
2127
+ break;
2128
+ }
2129
+ case RBDT_FILE: {
2130
+ if (files.has(path)) {
2131
+ callback();
2132
+ break;
2133
+ }
2134
+ files.add(path);
2135
+ /** @type {NonNullable<InputFileSystem["realpath"]>} */
2136
+ (this.fs.realpath)(path, (err, _realPath) => {
2137
+ if (err) return callback(err);
2138
+ const realPath = /** @type {string} */ (_realPath);
2139
+ if (realPath !== path) {
2140
+ fileSymlinks.add(path);
2141
+ resolveFiles.add(path);
2142
+ if (files.has(realPath)) return callback();
2143
+ files.add(realPath);
2144
+ }
2145
+ push({
2146
+ type: RBDT_FILE_DEPENDENCIES,
2147
+ context: undefined,
2148
+ path: realPath,
2149
+ expected: undefined,
2150
+ issuer: job
2151
+ });
2152
+ callback();
2153
+ });
2154
+ break;
2155
+ }
2156
+ case RBDT_DIRECTORY: {
2157
+ if (directories.has(path)) {
2158
+ callback();
2159
+ break;
2160
+ }
2161
+ directories.add(path);
2162
+ /** @type {NonNullable<InputFileSystem["realpath"]>} */
2163
+ (this.fs.realpath)(path, (err, _realPath) => {
2164
+ if (err) return callback(err);
2165
+ const realPath = /** @type {string} */ (_realPath);
2166
+ if (realPath !== path) {
2167
+ directorySymlinks.add(path);
2168
+ resolveFiles.add(path);
2169
+ if (directories.has(realPath)) return callback();
2170
+ directories.add(realPath);
2171
+ }
2172
+ push({
2173
+ type: RBDT_DIRECTORY_DEPENDENCIES,
2174
+ context: undefined,
2175
+ path: realPath,
2176
+ expected: undefined,
2177
+ issuer: job
2178
+ });
2179
+ callback();
2180
+ });
2181
+ break;
2182
+ }
2183
+ case RBDT_FILE_DEPENDENCIES: {
2184
+ // Check for known files without dependencies
2185
+ if (/\.json5?$|\.yarn-integrity$|yarn\.lock$|\.ya?ml/.test(path)) {
2186
+ process.nextTick(callback);
2187
+ break;
2188
+ }
2189
+ // Check commonjs cache for the module
2190
+ /** @type {NodeModule | undefined} */
2191
+ const module = require.cache[path];
2192
+ if (
2193
+ module &&
2194
+ Array.isArray(module.children) &&
2195
+ // https://github.com/nodejs/node/issues/59868
2196
+ // Force use `es-module-lexer` for mjs
2197
+ !/\.mjs$/.test(path)
2198
+ ) {
2199
+ children: for (const child of module.children) {
2200
+ const childPath = child.filename;
2201
+ if (childPath) {
2202
+ push({
2203
+ type: RBDT_FILE,
2204
+ context: undefined,
2205
+ path: childPath,
2206
+ expected: undefined,
2207
+ issuer: job
2208
+ });
2209
+ const context = dirname(this.fs, path);
2210
+ for (const modulePath of module.paths) {
2211
+ if (childPath.startsWith(modulePath)) {
2212
+ const subPath = childPath.slice(modulePath.length + 1);
2213
+ const packageMatch = /^@[^\\/]+[\\/][^\\/]+/.exec(
2214
+ subPath
2215
+ );
2216
+ if (packageMatch) {
2217
+ push({
2218
+ type: RBDT_FILE,
2219
+ context: undefined,
2220
+ path: `${
2221
+ modulePath +
2222
+ childPath[modulePath.length] +
2223
+ packageMatch[0] +
2224
+ childPath[modulePath.length]
2225
+ }package.json`,
2226
+ expected: false,
2227
+ issuer: job
2228
+ });
2229
+ }
2230
+ let request = subPath.replace(/\\/g, "/");
2231
+ if (request.endsWith(".js")) {
2232
+ request = request.slice(0, -3);
2233
+ }
2234
+ push({
2235
+ type: RBDT_RESOLVE_CJS_FILE_AS_CHILD,
2236
+ context,
2237
+ path: request,
2238
+ expected: child.filename,
2239
+ issuer: job
2240
+ });
2241
+ continue children;
2242
+ }
2243
+ }
2244
+ let request = relative(this.fs, context, childPath);
2245
+ if (request.endsWith(".js")) request = request.slice(0, -3);
2246
+ request = request.replace(/\\/g, "/");
2247
+ if (!request.startsWith("../") && !isAbsolute(request)) {
2248
+ request = `./${request}`;
2249
+ }
2250
+ push({
2251
+ type: RBDT_RESOLVE_CJS_FILE,
2252
+ context,
2253
+ path: request,
2254
+ expected: child.filename,
2255
+ issuer: job
2256
+ });
2257
+ }
2258
+ }
2259
+ // On Bun the children array is empty (unpopulated), so recover the
2260
+ // static require() specifiers by parsing the source; Node/Deno don't.
2261
+ /* istanbul ignore next */
2262
+ if (IS_BUN && module.children.length === 0) {
2263
+ this.fs.readFile(path, (err, content) => {
2264
+ if (err) return callback(err);
2265
+ try {
2266
+ const context = dirname(this.fs, path);
2267
+ const source = /** @type {Buffer} */ (content).toString();
2268
+ for (const dependency of collectCjsRequireSpecifiers(
2269
+ source
2270
+ )) {
2271
+ if (dependency.startsWith("node:")) continue;
2272
+ if (builtinModules.has(dependency)) continue;
2273
+ push({
2274
+ type: RBDT_RESOLVE_CJS_FILE,
2275
+ context,
2276
+ path: dependency,
2277
+ // Best effort: tolerate specifiers that don't resolve.
2278
+ expected: false,
2279
+ issuer: job
2280
+ });
2281
+ }
2282
+ } catch (_err) {
2283
+ // Source we can't parse as CommonJS — ignore its dependencies.
2284
+ }
2285
+ process.nextTick(callback);
2286
+ });
2287
+ break;
2288
+ }
2289
+ } else if (supportsEsm && /\.m?js$/.test(path)) {
2290
+ if (!this._warnAboutExperimentalEsmTracking) {
2291
+ logger.log(
2292
+ "Node.js doesn't offer a (nice) way to introspect the ESM dependency graph yet.\n" +
2293
+ "Until a full solution is available webpack uses an experimental ESM tracking based on parsing.\n" +
2294
+ "As best effort webpack parses the ESM files to guess dependencies. But this can lead to expensive and incorrect tracking."
2295
+ );
2296
+ this._warnAboutExperimentalEsmTracking = true;
2297
+ }
2298
+
2299
+ const lexer = getEsModuleLexer();
2300
+
2301
+ lexer.init.then(() => {
2302
+ this.fs.readFile(path, (err, content) => {
2303
+ if (err) return callback(err);
2304
+ try {
2305
+ const context = dirname(this.fs, path);
2306
+ const source = /** @type {Buffer} */ (content).toString();
2307
+ const [imports] = lexer.parse(source);
2308
+ /** @type {Set<string>} */
2309
+ const added = new Set();
2310
+ for (const imp of imports) {
2311
+ try {
2312
+ // import.meta
2313
+ if (imp.d === -2) {
2314
+ continue;
2315
+ }
2316
+
2317
+ /** @type {string | null} */
2318
+ const dependency =
2319
+ imp.n ||
2320
+ parseString(source.slice(imp.s, imp.e).trim());
2321
+
2322
+ if (!dependency) {
2323
+ continue;
2324
+ }
2325
+
2326
+ // We should not track Node.js build dependencies
2327
+ if (dependency.startsWith("node:")) continue;
2328
+ if (builtinModules.has(dependency)) continue;
2329
+ // Avoid extra jobs for identical imports
2330
+ if (added.has(dependency)) continue;
2331
+
2332
+ push({
2333
+ type: RBDT_RESOLVE_ESM_FILE,
2334
+ context,
2335
+ path: dependency,
2336
+ expected: imp.d > -1 ? false : undefined,
2337
+ issuer: job
2338
+ });
2339
+ added.add(dependency);
2340
+ } catch (err1) {
2341
+ logger.warn(
2342
+ `Parsing of ${path} for build dependencies failed at 'import(${source.slice(
2343
+ imp.s,
2344
+ imp.e
2345
+ )})'.\n` +
2346
+ "Build dependencies behind this expression are ignored and might cause incorrect cache invalidation."
2347
+ );
2348
+ logger.debug(pathToString(job));
2349
+ logger.debug(/** @type {Error} */ (err1).stack);
2350
+ }
2351
+ }
2352
+ } catch (err2) {
2353
+ logger.warn(
2354
+ `Parsing of ${path} for build dependencies failed and all dependencies of this file are ignored, which might cause incorrect cache invalidation..`
2355
+ );
2356
+ logger.debug(pathToString(job));
2357
+ logger.debug(/** @type {Error} */ (err2).stack);
2358
+ }
2359
+ process.nextTick(callback);
2360
+ });
2361
+ }, callback);
2362
+ break;
2363
+ } else {
2364
+ logger.log(
2365
+ `Assuming ${path} has no dependencies as we were unable to assign it to any module system.`
2366
+ );
2367
+ logger.debug(pathToString(job));
2368
+ }
2369
+ process.nextTick(callback);
2370
+ break;
2371
+ }
2372
+ case RBDT_DIRECTORY_DEPENDENCIES: {
2373
+ const match =
2374
+ /(^.+[\\/]node_modules[\\/](?:@[^\\/]+[\\/])?[^\\/]+)/.exec(path);
2375
+ const packagePath = match ? match[1] : path;
2376
+ const packageJson = join(this.fs, packagePath, "package.json");
2377
+ this.fs.readFile(packageJson, (err, content) => {
2378
+ if (err) {
2379
+ if (err.code === "ENOENT") {
2380
+ resolveMissing.add(packageJson);
2381
+ const parent = dirname(this.fs, packagePath);
2382
+ if (parent !== packagePath) {
2383
+ push({
2384
+ type: RBDT_DIRECTORY_DEPENDENCIES,
2385
+ context: undefined,
2386
+ path: parent,
2387
+ expected: undefined,
2388
+ issuer: job
2389
+ });
2390
+ }
2391
+ callback();
2392
+ return;
2393
+ }
2394
+ return callback(err);
2395
+ }
2396
+ resolveFiles.add(packageJson);
2397
+ /** @type {JsonObject} */
2398
+ let packageData;
2399
+ try {
2400
+ packageData = JSON.parse(
2401
+ /** @type {Buffer} */
2402
+ (content).toString("utf8")
2403
+ );
2404
+ } catch (parseErr) {
2405
+ return callback(/** @type {Error} */ (parseErr));
2406
+ }
2407
+ const depsObject = packageData.dependencies;
2408
+ const optionalDepsObject = packageData.optionalDependencies;
2409
+ /** @type {Set<string>} */
2410
+ const allDeps = new Set();
2411
+ /** @type {Set<string>} */
2412
+ const optionalDeps = new Set();
2413
+ if (typeof depsObject === "object" && depsObject) {
2414
+ for (const dep of Object.keys(depsObject)) {
2415
+ allDeps.add(dep);
2416
+ }
2417
+ }
2418
+ if (
2419
+ typeof optionalDepsObject === "object" &&
2420
+ optionalDepsObject
2421
+ ) {
2422
+ for (const dep of Object.keys(optionalDepsObject)) {
2423
+ allDeps.add(dep);
2424
+ optionalDeps.add(dep);
2425
+ }
2426
+ }
2427
+ for (const dep of allDeps) {
2428
+ push({
2429
+ type: RBDT_RESOLVE_DIRECTORY,
2430
+ context: packagePath,
2431
+ path: dep,
2432
+ expected: !optionalDeps.has(dep),
2433
+ issuer: job
2434
+ });
2435
+ }
2436
+ callback();
2437
+ });
2438
+ break;
2439
+ }
2440
+ }
2441
+ },
2442
+ (err) => {
2443
+ if (err) return callback(err);
2444
+ for (const l of fileSymlinks) files.delete(l);
2445
+ for (const l of directorySymlinks) directories.delete(l);
2446
+ for (const k of invalidResolveResults) resolveResults.delete(k);
2447
+ callback(null, {
2448
+ files,
2449
+ directories,
2450
+ missing,
2451
+ resolveResults,
2452
+ resolveDependencies: {
2453
+ files: resolveFiles,
2454
+ directories: resolveDirectories,
2455
+ missing: resolveMissing
2456
+ }
2457
+ });
2458
+ }
2459
+ );
2460
+ }
2461
+
2462
+ /**
2463
+ * Checks resolve results valid.
2464
+ * @param {ResolveResults} resolveResults results from resolving
2465
+ * @param {(err?: Error | null, result?: boolean) => void} callback callback with true when resolveResults resolve the same way
2466
+ * @returns {void}
2467
+ */
2468
+ checkResolveResultsValid(resolveResults, callback) {
2469
+ const { resolveCjs, resolveCjsAsChild, resolveEsm, resolveContext } =
2470
+ this._createBuildDependenciesResolvers();
2471
+ asyncLib.eachLimit(
2472
+ resolveResults,
2473
+ 20,
2474
+ ([key, expectedResult], callback) => {
2475
+ const [type, context, path] = key.split("\n");
2476
+ switch (type) {
2477
+ case "d":
2478
+ resolveContext(context, path, {}, (err, _, result) => {
2479
+ if (expectedResult === false) {
2480
+ return callback(err ? undefined : INVALID);
2481
+ }
2482
+ if (err) return callback(err);
2483
+ const resultPath = /** @type {ResolveRequest} */ (result).path;
2484
+ if (resultPath !== expectedResult) return callback(INVALID);
2485
+ callback();
2486
+ });
2487
+ break;
2488
+ case "f":
2489
+ resolveCjs(context, path, {}, (err, _, result) => {
2490
+ if (expectedResult === false) {
2491
+ return callback(err ? undefined : INVALID);
2492
+ }
2493
+ if (err) return callback(err);
2494
+ const resultPath = /** @type {ResolveRequest} */ (result).path;
2495
+ if (resultPath !== expectedResult) return callback(INVALID);
2496
+ callback();
2497
+ });
2498
+ break;
2499
+ case "c":
2500
+ resolveCjsAsChild(context, path, {}, (err, _, result) => {
2501
+ if (expectedResult === false) {
2502
+ return callback(err ? undefined : INVALID);
2503
+ }
2504
+ if (err) return callback(err);
2505
+ const resultPath = /** @type {ResolveRequest} */ (result).path;
2506
+ if (resultPath !== expectedResult) return callback(INVALID);
2507
+ callback();
2508
+ });
2509
+ break;
2510
+ case "e":
2511
+ resolveEsm(context, path, {}, (err, _, result) => {
2512
+ if (expectedResult === false) {
2513
+ return callback(err ? undefined : INVALID);
2514
+ }
2515
+ if (err) return callback(err);
2516
+ const resultPath = /** @type {ResolveRequest} */ (result).path;
2517
+ if (resultPath !== expectedResult) return callback(INVALID);
2518
+ callback();
2519
+ });
2520
+ break;
2521
+ default:
2522
+ callback(new Error("Unexpected type in resolve result key"));
2523
+ break;
2524
+ }
2525
+ },
2526
+ /**
2527
+ * Processes the provided err.
2528
+ * @param {(Error | typeof INVALID | null)=} err error or invalid flag
2529
+ * @returns {void}
2530
+ */
2531
+ (err) => {
2532
+ if (err === INVALID) {
2533
+ return callback(null, false);
2534
+ }
2535
+ if (err) {
2536
+ return callback(err);
2537
+ }
2538
+ return callback(null, true);
2539
+ }
2540
+ );
2541
+ }
2542
+
2543
+ /**
2544
+ * Creates a snapshot.
2545
+ * @param {number | null | undefined} startTime when processing the files has started
2546
+ * @param {Iterable<string> | null | undefined} files all files
2547
+ * @param {Iterable<string> | null | undefined} directories all directories
2548
+ * @param {Iterable<string> | null | undefined} missing all missing files or directories
2549
+ * @param {SnapshotOptions | null | undefined} options options object (for future extensions)
2550
+ * @param {(err: WebpackError | null, snapshot: Snapshot | null) => void} callback callback function
2551
+ * @returns {void}
2552
+ */
2553
+ createSnapshot(startTime, files, directories, missing, options, callback) {
2554
+ // collections are allocated lazily to avoid per-snapshot garbage for unused modes
2555
+ /** @type {FileTimestamps | undefined} */
2556
+ let fileTimestamps;
2557
+ /** @type {FileHashes | undefined} */
2558
+ let fileHashes;
2559
+ /** @type {FileTshs | undefined} */
2560
+ let fileTshs;
2561
+ /** @type {ContextTimestamps | undefined} */
2562
+ let contextTimestamps;
2563
+ /** @type {ContextHashes | undefined} */
2564
+ let contextHashes;
2565
+ /** @type {ContextTshs | undefined} */
2566
+ let contextTshs;
2567
+ /** @type {MissingExistence | undefined} */
2568
+ let missingExistence;
2569
+ /** @type {ManagedItemInfo | undefined} */
2570
+ let managedItemInfo;
2571
+ /** @type {ManagedFiles} */
2572
+ const managedFiles = new Set();
2573
+ /** @type {ManagedContexts} */
2574
+ const managedContexts = new Set();
2575
+ /** @type {ManagedMissing} */
2576
+ const managedMissing = new Set();
2577
+
2578
+ const snapshot = new Snapshot();
2579
+ if (startTime) snapshot.setStartTime(startTime);
2580
+
2581
+ /** @type {Set<string>} */
2582
+ const managedItems = new Set();
2583
+
2584
+ /** 1 = timestamp, 2 = hash, 3 = timestamp + hash */
2585
+ const mode = options && options.hash ? (options.timestamp ? 3 : 2) : 1;
2586
+
2587
+ let jobs = 1;
2588
+ const jobDone = () => {
2589
+ if (--jobs === 0) {
2590
+ if (fileTimestamps !== undefined && fileTimestamps.size !== 0) {
2591
+ snapshot.setFileTimestamps(fileTimestamps);
2592
+ }
2593
+ if (fileHashes !== undefined && fileHashes.size !== 0) {
2594
+ snapshot.setFileHashes(fileHashes);
2595
+ }
2596
+ if (fileTshs !== undefined && fileTshs.size !== 0) {
2597
+ snapshot.setFileTshs(fileTshs);
2598
+ }
2599
+ if (contextTimestamps !== undefined && contextTimestamps.size !== 0) {
2600
+ snapshot.setContextTimestamps(contextTimestamps);
2601
+ }
2602
+ if (contextHashes !== undefined && contextHashes.size !== 0) {
2603
+ snapshot.setContextHashes(contextHashes);
2604
+ }
2605
+ if (contextTshs !== undefined && contextTshs.size !== 0) {
2606
+ snapshot.setContextTshs(contextTshs);
2607
+ }
2608
+ if (missingExistence !== undefined && missingExistence.size !== 0) {
2609
+ snapshot.setMissingExistence(missingExistence);
2610
+ }
2611
+ if (managedItemInfo !== undefined && managedItemInfo.size !== 0) {
2612
+ snapshot.setManagedItemInfo(managedItemInfo);
2613
+ }
2614
+ this._managedFilesOptimization.optimize(snapshot, managedFiles);
2615
+ if (managedFiles.size !== 0) {
2616
+ snapshot.setManagedFiles(managedFiles);
2617
+ }
2618
+ this._managedContextsOptimization.optimize(snapshot, managedContexts);
2619
+ if (managedContexts.size !== 0) {
2620
+ snapshot.setManagedContexts(managedContexts);
2621
+ }
2622
+ this._managedMissingOptimization.optimize(snapshot, managedMissing);
2623
+ if (managedMissing.size !== 0) {
2624
+ snapshot.setManagedMissing(managedMissing);
2625
+ }
2626
+ this._snapshotCache.set(snapshot, true);
2627
+ this._statCreatedSnapshots++;
2628
+
2629
+ callback(null, snapshot);
2630
+ }
2631
+ };
2632
+ const jobError = () => {
2633
+ if (jobs > 0) {
2634
+ // large negative number instead of NaN or something else to keep jobs to stay a SMI (v8)
2635
+ jobs = -100000000;
2636
+ callback(null, null);
2637
+ }
2638
+ };
2639
+ const classificationCache = this._pathClassificationCache;
2640
+ /**
2641
+ * Checks true when managed.
2642
+ * @param {string} path path
2643
+ * @param {ManagedFiles} managedSet managed set
2644
+ * @returns {boolean} true when managed
2645
+ */
2646
+ const checkManaged = (path, managedSet) => {
2647
+ // classification is a pure function of the path, so it's shared across snapshots
2648
+ const cached = classificationCache.get(path);
2649
+ if (cached !== undefined) {
2650
+ if (cached === 0) return false;
2651
+ if (cached !== 1) managedItems.add(cached);
2652
+ managedSet.add(path);
2653
+ return true;
2654
+ }
2655
+ for (const unmanagedPath of this.unmanagedPathsRegExps) {
2656
+ if (unmanagedPath.test(path)) {
2657
+ classificationCache.set(path, 0);
2658
+ return false;
2659
+ }
2660
+ }
2661
+ for (const unmanagedPath of this.unmanagedPathsWithSlash) {
2662
+ if (path.startsWith(unmanagedPath)) {
2663
+ classificationCache.set(path, 0);
2664
+ return false;
2665
+ }
2666
+ }
2667
+ for (const immutablePath of this.immutablePathsRegExps) {
2668
+ if (immutablePath.test(path)) {
2669
+ classificationCache.set(path, 1);
2670
+ managedSet.add(path);
2671
+ return true;
2672
+ }
2673
+ }
2674
+ for (const immutablePath of this.immutablePathsWithSlash) {
2675
+ if (path.startsWith(immutablePath)) {
2676
+ classificationCache.set(path, 1);
2677
+ managedSet.add(path);
2678
+ return true;
2679
+ }
2680
+ }
2681
+ for (const managedPath of this.managedPathsRegExps) {
2682
+ const match = managedPath.exec(path);
2683
+ if (match) {
2684
+ const managedItem = getManagedItem(
2685
+ getManagedPathFromMatch(match),
2686
+ path
2687
+ );
2688
+ if (managedItem) {
2689
+ classificationCache.set(path, managedItem);
2690
+ managedItems.add(managedItem);
2691
+ managedSet.add(path);
2692
+ return true;
2693
+ }
2694
+ }
2695
+ }
2696
+ for (const managedPath of this.managedPathsWithSlash) {
2697
+ if (path.startsWith(managedPath)) {
2698
+ const managedItem = getManagedItem(managedPath, path);
2699
+ if (managedItem) {
2700
+ classificationCache.set(path, managedItem);
2701
+ managedItems.add(managedItem);
2702
+ managedSet.add(path);
2703
+ return true;
2704
+ }
2705
+ }
2706
+ }
2707
+ classificationCache.set(path, 0);
2708
+ return false;
2709
+ };
2710
+ /**
2711
+ * Capture non managed.
2712
+ * @param {Iterable<string>} items items
2713
+ * @param {Set<string>} managedSet managed set
2714
+ * @returns {Set<string>} result
2715
+ */
2716
+ const captureNonManaged = (items, managedSet) => {
2717
+ /** @type {Set<string>} */
2718
+ const capturedItems = new Set();
2719
+ for (const path of items) {
2720
+ if (!checkManaged(path, managedSet)) capturedItems.add(path);
2721
+ }
2722
+ return capturedItems;
2723
+ };
2724
+ /**
2725
+ * Process captured files.
2726
+ * @param {ManagedFiles} capturedFiles captured files
2727
+ */
2728
+ const processCapturedFiles = (capturedFiles) => {
2729
+ if (capturedFiles.size === 0) {
2730
+ return;
2731
+ }
2732
+ switch (mode) {
2733
+ case 3: {
2734
+ this._fileTshsOptimization.optimize(snapshot, capturedFiles);
2735
+ if (fileTshs === undefined) fileTshs = new Map();
2736
+ const fileTshsMap = fileTshs;
2737
+ for (const path of capturedFiles) {
2738
+ const cache = this._fileTshs.get(path);
2739
+ if (cache !== undefined) {
2740
+ fileTshsMap.set(path, cache);
2741
+ } else {
2742
+ jobs++;
2743
+ this._getFileTimestampAndHash(path, (err, entry) => {
2744
+ if (err) {
2745
+ if (this.logger) {
2746
+ this.logger.debug(
2747
+ `Error snapshotting file timestamp hash combination of ${path}: ${err.stack}`
2748
+ );
2749
+ }
2750
+ jobError();
2751
+ } else {
2752
+ fileTshsMap.set(
2753
+ path,
2754
+ /** @type {TimestampAndHash} */ (entry)
2755
+ );
2756
+ jobDone();
2757
+ }
2758
+ });
2759
+ }
2760
+ }
2761
+ break;
2762
+ }
2763
+ case 2: {
2764
+ this._fileHashesOptimization.optimize(snapshot, capturedFiles);
2765
+ if (fileHashes === undefined) fileHashes = new Map();
2766
+ const fileHashesMap = fileHashes;
2767
+ for (const path of capturedFiles) {
2768
+ const cache = this._fileHashes.get(path);
2769
+ if (cache !== undefined) {
2770
+ fileHashesMap.set(path, cache);
2771
+ } else {
2772
+ jobs++;
2773
+ this.fileHashQueue.add(path, (err, entry) => {
2774
+ if (err) {
2775
+ if (this.logger) {
2776
+ this.logger.debug(
2777
+ `Error snapshotting file hash of ${path}: ${err.stack}`
2778
+ );
2779
+ }
2780
+ jobError();
2781
+ } else {
2782
+ fileHashesMap.set(path, /** @type {string} */ (entry));
2783
+ jobDone();
2784
+ }
2785
+ });
2786
+ }
2787
+ }
2788
+ break;
2789
+ }
2790
+ case 1: {
2791
+ this._fileTimestampsOptimization.optimize(snapshot, capturedFiles);
2792
+ if (fileTimestamps === undefined) fileTimestamps = new Map();
2793
+ const fileTimestampsMap = fileTimestamps;
2794
+ for (const path of capturedFiles) {
2795
+ const cache = this._fileTimestamps.get(path);
2796
+ if (cache !== undefined && !isExistenceOnly(cache)) {
2797
+ if (cache !== "ignore") {
2798
+ fileTimestampsMap.set(
2799
+ path,
2800
+ /** @type {FileSystemInfoEntry | null} */ (cache)
2801
+ );
2802
+ }
2803
+ } else {
2804
+ jobs++;
2805
+ this.fileTimestampQueue.add(path, (err, entry) => {
2806
+ if (err) {
2807
+ if (this.logger) {
2808
+ this.logger.debug(
2809
+ `Error snapshotting file timestamp of ${path}: ${err.stack}`
2810
+ );
2811
+ }
2812
+ jobError();
2813
+ } else {
2814
+ fileTimestampsMap.set(
2815
+ path,
2816
+ /** @type {FileSystemInfoEntry} */
2817
+ (entry)
2818
+ );
2819
+ jobDone();
2820
+ }
2821
+ });
2822
+ }
2823
+ }
2824
+ break;
2825
+ }
2826
+ }
2827
+ };
2828
+ if (files) {
2829
+ processCapturedFiles(captureNonManaged(files, managedFiles));
2830
+ }
2831
+ /**
2832
+ * Process captured directories.
2833
+ * @param {ManagedContexts} capturedDirectories captured directories
2834
+ */
2835
+ const processCapturedDirectories = (capturedDirectories) => {
2836
+ if (capturedDirectories.size === 0) {
2837
+ return;
2838
+ }
2839
+ switch (mode) {
2840
+ case 3: {
2841
+ this._contextTshsOptimization.optimize(snapshot, capturedDirectories);
2842
+ if (contextTshs === undefined) contextTshs = new Map();
2843
+ const contextTshsMap = contextTshs;
2844
+ for (const path of capturedDirectories) {
2845
+ const cache = this._contextTshs.get(path);
2846
+ /** @type {ResolvedContextTimestampAndHash | null | undefined} */
2847
+ let resolved;
2848
+ if (
2849
+ cache !== undefined &&
2850
+ (resolved = getResolvedTimestamp(cache)) !== undefined
2851
+ ) {
2852
+ contextTshsMap.set(path, resolved);
2853
+ } else {
2854
+ jobs++;
2855
+ /**
2856
+ * Processes the provided err.
2857
+ * @param {(WebpackError | null)=} err error
2858
+ * @param {(ResolvedContextTimestampAndHash | null)=} entry entry
2859
+ * @returns {void}
2860
+ */
2861
+ const callback = (err, entry) => {
2862
+ if (err) {
2863
+ if (this.logger) {
2864
+ this.logger.debug(
2865
+ `Error snapshotting context timestamp hash combination of ${path}: ${err.stack}`
2866
+ );
2867
+ }
2868
+ jobError();
2869
+ } else {
2870
+ contextTshsMap.set(
2871
+ path,
2872
+ /** @type {ResolvedContextTimestampAndHash | null} */
2873
+ (entry)
2874
+ );
2875
+ jobDone();
2876
+ }
2877
+ };
2878
+ if (cache !== undefined) {
2879
+ this._resolveContextTsh(cache, callback);
2880
+ } else {
2881
+ this.getContextTsh(path, callback);
2882
+ }
2883
+ }
2884
+ }
2885
+ break;
2886
+ }
2887
+ case 2: {
2888
+ this._contextHashesOptimization.optimize(
2889
+ snapshot,
2890
+ capturedDirectories
2891
+ );
2892
+ if (contextHashes === undefined) contextHashes = new Map();
2893
+ const contextHashesMap = contextHashes;
2894
+ for (const path of capturedDirectories) {
2895
+ const cache = this._contextHashes.get(path);
2896
+ /** @type {undefined | null | string} */
2897
+ let resolved;
2898
+ if (
2899
+ cache !== undefined &&
2900
+ (resolved = getResolvedHash(cache)) !== undefined
2901
+ ) {
2902
+ contextHashesMap.set(path, resolved);
2903
+ } else {
2904
+ jobs++;
2905
+ /**
2906
+ * Processes the provided err.
2907
+ * @param {(WebpackError | null)=} err err
2908
+ * @param {string=} entry entry
2909
+ */
2910
+ const callback = (err, entry) => {
2911
+ if (err) {
2912
+ if (this.logger) {
2913
+ this.logger.debug(
2914
+ `Error snapshotting context hash of ${path}: ${err.stack}`
2915
+ );
2916
+ }
2917
+ jobError();
2918
+ } else {
2919
+ contextHashesMap.set(path, /** @type {string} */ (entry));
2920
+ jobDone();
2921
+ }
2922
+ };
2923
+ if (cache !== undefined) {
2924
+ this._resolveContextHash(cache, callback);
2925
+ } else {
2926
+ this.getContextHash(path, callback);
2927
+ }
2928
+ }
2929
+ }
2930
+ break;
2931
+ }
2932
+ case 1: {
2933
+ this._contextTimestampsOptimization.optimize(
2934
+ snapshot,
2935
+ capturedDirectories
2936
+ );
2937
+ if (contextTimestamps === undefined) contextTimestamps = new Map();
2938
+ const contextTimestampsMap = contextTimestamps;
2939
+ for (const path of capturedDirectories) {
2940
+ const cache = this._contextTimestamps.get(path);
2941
+ if (cache === "ignore") continue;
2942
+ /** @type {ContextFileSystemInfoEntry | null | undefined} */
2943
+ const usableCache =
2944
+ cache === undefined || isExistenceOnly(cache)
2945
+ ? undefined
2946
+ : /** @type {ContextFileSystemInfoEntry | null} */ (cache);
2947
+ const cacheLacksHash =
2948
+ contextCacheEntryLacksTimestampHash(usableCache);
2949
+ /** @type {undefined | null | ResolvedContextFileSystemInfoEntry} */
2950
+ let resolved;
2951
+ if (
2952
+ usableCache !== undefined &&
2953
+ !cacheLacksHash &&
2954
+ (resolved = getResolvedTimestamp(usableCache)) !== undefined
2955
+ ) {
2956
+ contextTimestampsMap.set(path, resolved);
2957
+ } else {
2958
+ jobs++;
2959
+ /**
2960
+ * Processes the provided err.
2961
+ * @param {(WebpackError | null)=} err error
2962
+ * @param {ResolvedContextTimestamp=} entry entry
2963
+ * @returns {void}
2964
+ */
2965
+ const callback = (err, entry) => {
2966
+ if (err) {
2967
+ if (this.logger) {
2968
+ this.logger.debug(
2969
+ `Error snapshotting context timestamp of ${path}: ${err.stack}`
2970
+ );
2971
+ }
2972
+ jobError();
2973
+ } else {
2974
+ contextTimestampsMap.set(
2975
+ path,
2976
+ /** @type {ResolvedContextFileSystemInfoEntry | null} */
2977
+ (entry)
2978
+ );
2979
+ jobDone();
2980
+ }
2981
+ };
2982
+ if (cacheLacksHash) {
2983
+ this._readFreshContextTimestamp(path, callback);
2984
+ } else if (usableCache !== undefined && usableCache !== null) {
2985
+ this._resolveContextTimestamp(usableCache, callback);
2986
+ } else {
2987
+ // Force a fresh on-disk read so the snapshot stores a
2988
+ // complete entry (with `timestampHash`).
2989
+ this._readFreshContextTimestamp(path, callback);
2990
+ }
2991
+ }
2992
+ }
2993
+ break;
2994
+ }
2995
+ }
2996
+ };
2997
+ if (directories) {
2998
+ processCapturedDirectories(
2999
+ captureNonManaged(directories, managedContexts)
3000
+ );
3001
+ }
3002
+ /**
3003
+ * Process captured missing.
3004
+ * @param {ManagedMissing} capturedMissing captured missing
3005
+ */
3006
+ const processCapturedMissing = (capturedMissing) => {
3007
+ if (capturedMissing.size === 0) {
3008
+ return;
3009
+ }
3010
+ this._missingExistenceOptimization.optimize(snapshot, capturedMissing);
3011
+ if (missingExistence === undefined) missingExistence = new Map();
3012
+ const missingExistenceMap = missingExistence;
3013
+ for (const path of capturedMissing) {
3014
+ const cache = this._fileTimestamps.get(path);
3015
+ if (cache !== undefined && !isExistenceOnly(cache)) {
3016
+ if (cache !== "ignore") {
3017
+ missingExistenceMap.set(path, Boolean(cache));
3018
+ }
3019
+ } else {
3020
+ jobs++;
3021
+ this.fileTimestampQueue.add(path, (err, entry) => {
3022
+ if (err) {
3023
+ if (this.logger) {
3024
+ this.logger.debug(
3025
+ `Error snapshotting missing timestamp of ${path}: ${err.stack}`
3026
+ );
3027
+ }
3028
+ jobError();
3029
+ } else {
3030
+ missingExistenceMap.set(path, Boolean(entry));
3031
+ jobDone();
3032
+ }
3033
+ });
3034
+ }
3035
+ }
3036
+ };
3037
+ if (missing) {
3038
+ processCapturedMissing(captureNonManaged(missing, managedMissing));
3039
+ }
3040
+ this._managedItemInfoOptimization.optimize(snapshot, managedItems);
3041
+ if (managedItems.size !== 0 && managedItemInfo === undefined) {
3042
+ managedItemInfo = new Map();
3043
+ }
3044
+ const managedItemInfoMap = managedItemInfo;
3045
+ for (const path of managedItems) {
3046
+ const cache = this._managedItems.get(path);
3047
+ if (cache !== undefined) {
3048
+ if (!cache.startsWith("*")) {
3049
+ managedFiles.add(join(this.fs, path, "package.json"));
3050
+ } else if (cache === "*nested") {
3051
+ managedMissing.add(join(this.fs, path, "package.json"));
3052
+ }
3053
+ /** @type {ManagedItemInfo} */ (managedItemInfoMap).set(path, cache);
3054
+ } else {
3055
+ jobs++;
3056
+ this.managedItemQueue.add(path, (err, entry) => {
3057
+ if (err) {
3058
+ if (this.logger) {
3059
+ this.logger.debug(
3060
+ `Error snapshotting managed item ${path}: ${err.stack}`
3061
+ );
3062
+ }
3063
+ jobError();
3064
+ } else if (entry) {
3065
+ if (!entry.startsWith("*")) {
3066
+ managedFiles.add(join(this.fs, path, "package.json"));
3067
+ } else if (cache === "*nested") {
3068
+ managedMissing.add(join(this.fs, path, "package.json"));
3069
+ }
3070
+ /** @type {ManagedItemInfo} */ (managedItemInfoMap).set(
3071
+ path,
3072
+ entry
3073
+ );
3074
+ jobDone();
3075
+ } else {
3076
+ // Fallback to normal snapshotting
3077
+ /**
3078
+ * Processes the provided set.
3079
+ * @param {Set<string>} set set
3080
+ * @param {(set: Set<string>) => void} fn fn
3081
+ */
3082
+ const process = (set, fn) => {
3083
+ if (set.size === 0) return;
3084
+ /** @type {Set<string>} */
3085
+ const captured = new Set();
3086
+ for (const file of set) {
3087
+ if (file.startsWith(path)) captured.add(file);
3088
+ }
3089
+ if (captured.size > 0) fn(captured);
3090
+ };
3091
+ process(managedFiles, processCapturedFiles);
3092
+ process(managedContexts, processCapturedDirectories);
3093
+ process(managedMissing, processCapturedMissing);
3094
+ jobDone();
3095
+ }
3096
+ });
3097
+ }
3098
+ }
3099
+ jobDone();
3100
+ }
3101
+
3102
+ /**
3103
+ * Merges the provided values into a single result.
3104
+ * @param {Snapshot} snapshot1 a snapshot
3105
+ * @param {Snapshot} snapshot2 a snapshot
3106
+ * @returns {Snapshot} merged snapshot
3107
+ */
3108
+ mergeSnapshots(snapshot1, snapshot2) {
3109
+ const snapshot = new Snapshot();
3110
+ if (snapshot1.hasStartTime() && snapshot2.hasStartTime()) {
3111
+ snapshot.setStartTime(
3112
+ Math.min(
3113
+ /** @type {NonNullable<Snapshot["startTime"]>} */
3114
+ (snapshot1.startTime),
3115
+ /** @type {NonNullable<Snapshot["startTime"]>} */
3116
+ (snapshot2.startTime)
3117
+ )
3118
+ );
3119
+ } else if (snapshot2.hasStartTime()) {
3120
+ snapshot.startTime = snapshot2.startTime;
3121
+ } else if (snapshot1.hasStartTime()) {
3122
+ snapshot.startTime = snapshot1.startTime;
3123
+ }
3124
+ if (snapshot1.hasFileTimestamps() || snapshot2.hasFileTimestamps()) {
3125
+ snapshot.setFileTimestamps(
3126
+ mergeMaps(snapshot1.fileTimestamps, snapshot2.fileTimestamps)
3127
+ );
3128
+ }
3129
+ if (snapshot1.hasFileHashes() || snapshot2.hasFileHashes()) {
3130
+ snapshot.setFileHashes(
3131
+ mergeMaps(snapshot1.fileHashes, snapshot2.fileHashes)
3132
+ );
3133
+ }
3134
+ if (snapshot1.hasFileTshs() || snapshot2.hasFileTshs()) {
3135
+ snapshot.setFileTshs(mergeMaps(snapshot1.fileTshs, snapshot2.fileTshs));
3136
+ }
3137
+ if (snapshot1.hasContextTimestamps() || snapshot2.hasContextTimestamps()) {
3138
+ snapshot.setContextTimestamps(
3139
+ mergeMaps(snapshot1.contextTimestamps, snapshot2.contextTimestamps)
3140
+ );
3141
+ }
3142
+ if (snapshot1.hasContextHashes() || snapshot2.hasContextHashes()) {
3143
+ snapshot.setContextHashes(
3144
+ mergeMaps(snapshot1.contextHashes, snapshot2.contextHashes)
3145
+ );
3146
+ }
3147
+ if (snapshot1.hasContextTshs() || snapshot2.hasContextTshs()) {
3148
+ snapshot.setContextTshs(
3149
+ mergeMaps(snapshot1.contextTshs, snapshot2.contextTshs)
3150
+ );
3151
+ }
3152
+ if (snapshot1.hasMissingExistence() || snapshot2.hasMissingExistence()) {
3153
+ snapshot.setMissingExistence(
3154
+ mergeMaps(snapshot1.missingExistence, snapshot2.missingExistence)
3155
+ );
3156
+ }
3157
+ if (snapshot1.hasManagedItemInfo() || snapshot2.hasManagedItemInfo()) {
3158
+ snapshot.setManagedItemInfo(
3159
+ mergeMaps(snapshot1.managedItemInfo, snapshot2.managedItemInfo)
3160
+ );
3161
+ }
3162
+ if (snapshot1.hasManagedFiles() || snapshot2.hasManagedFiles()) {
3163
+ snapshot.setManagedFiles(
3164
+ mergeSets(snapshot1.managedFiles, snapshot2.managedFiles)
3165
+ );
3166
+ }
3167
+ if (snapshot1.hasManagedContexts() || snapshot2.hasManagedContexts()) {
3168
+ snapshot.setManagedContexts(
3169
+ mergeSets(snapshot1.managedContexts, snapshot2.managedContexts)
3170
+ );
3171
+ }
3172
+ if (snapshot1.hasManagedMissing() || snapshot2.hasManagedMissing()) {
3173
+ snapshot.setManagedMissing(
3174
+ mergeSets(snapshot1.managedMissing, snapshot2.managedMissing)
3175
+ );
3176
+ }
3177
+ if (snapshot1.hasChildren() || snapshot2.hasChildren()) {
3178
+ snapshot.setChildren(mergeSets(snapshot1.children, snapshot2.children));
3179
+ }
3180
+ if (
3181
+ this._snapshotCache.get(snapshot1) === true &&
3182
+ this._snapshotCache.get(snapshot2) === true
3183
+ ) {
3184
+ this._snapshotCache.set(snapshot, true);
3185
+ }
3186
+ return snapshot;
3187
+ }
3188
+
3189
+ /**
3190
+ * Checks snapshot valid.
3191
+ * @param {Snapshot} snapshot the snapshot made
3192
+ * @param {CheckSnapshotValidCallback} callback callback function
3193
+ * @returns {void}
3194
+ */
3195
+ checkSnapshotValid(snapshot, callback) {
3196
+ const cachedResult = this._snapshotCache.get(snapshot);
3197
+ if (cachedResult !== undefined) {
3198
+ this._statTestedSnapshotsCached++;
3199
+ if (typeof cachedResult === "boolean") {
3200
+ callback(null, cachedResult);
3201
+ } else {
3202
+ cachedResult.push(callback);
3203
+ }
3204
+ return;
3205
+ }
3206
+ this._statTestedSnapshotsNotCached++;
3207
+ this._checkSnapshotValidNoCache(snapshot, callback);
3208
+ }
3209
+
3210
+ /**
3211
+ * Check snapshot valid no cache.
3212
+ * @private
3213
+ * @param {Snapshot} snapshot the snapshot made
3214
+ * @param {CheckSnapshotValidCallback} callback callback function
3215
+ * @returns {void}
3216
+ */
3217
+ _checkSnapshotValidNoCache(snapshot, callback) {
3218
+ /** @type {number | undefined} */
3219
+ let startTime;
3220
+ if (snapshot.hasStartTime()) {
3221
+ startTime = snapshot.startTime;
3222
+ }
3223
+ let jobs = 1;
3224
+ const jobDone = () => {
3225
+ if (--jobs === 0) {
3226
+ this._snapshotCache.set(snapshot, true);
3227
+ callback(null, true);
3228
+ }
3229
+ };
3230
+ const invalid = () => {
3231
+ if (jobs > 0) {
3232
+ // large negative number instead of NaN or something else to keep jobs to stay a SMI (v8)
3233
+ jobs = -100000000;
3234
+ this._snapshotCache.set(snapshot, false);
3235
+ callback(null, false);
3236
+ }
3237
+ };
3238
+ /**
3239
+ * Invalid with error.
3240
+ * @param {string} path path
3241
+ * @param {WebpackError} err err
3242
+ */
3243
+ const invalidWithError = (path, err) => {
3244
+ if (this._remainingLogs > 0) {
3245
+ this._log(path, "error occurred: %s", err);
3246
+ }
3247
+ invalid();
3248
+ };
3249
+ /**
3250
+ * Checks true, if ok.
3251
+ * @param {string} path file path
3252
+ * @param {string | null} current current hash
3253
+ * @param {string | null} snap snapshot hash
3254
+ * @returns {boolean} true, if ok
3255
+ */
3256
+ const checkHash = (path, current, snap) => {
3257
+ if (current !== snap) {
3258
+ // If hash differ it's invalid
3259
+ if (this._remainingLogs > 0) {
3260
+ this._log(path, "hashes differ (%s != %s)", current, snap);
3261
+ }
3262
+ return false;
3263
+ }
3264
+ return true;
3265
+ };
3266
+ /**
3267
+ * Checks true, if ok.
3268
+ * @param {string} path file path
3269
+ * @param {boolean} current current entry
3270
+ * @param {boolean} snap entry from snapshot
3271
+ * @returns {boolean} true, if ok
3272
+ */
3273
+ const checkExistence = (path, current, snap) => {
3274
+ if (!current !== !snap) {
3275
+ // If existence of item differs
3276
+ // it's invalid
3277
+ if (this._remainingLogs > 0) {
3278
+ this._log(
3279
+ path,
3280
+ current ? "it didn't exist before" : "it does no longer exist"
3281
+ );
3282
+ }
3283
+ return false;
3284
+ }
3285
+ return true;
3286
+ };
3287
+ /**
3288
+ * Checks true, if ok.
3289
+ * @param {string} path file path
3290
+ * @param {FileSystemInfoEntry | null} c current entry
3291
+ * @param {FileSystemInfoEntry | null} s entry from snapshot
3292
+ * @param {boolean} log log reason
3293
+ * @returns {boolean} true, if ok
3294
+ */
3295
+ const checkFile = (path, c, s, log = true) => {
3296
+ if (c === s) return true;
3297
+ if (!checkExistence(path, Boolean(c), Boolean(s))) return false;
3298
+ if (c) {
3299
+ // For existing items only
3300
+ if (typeof startTime === "number" && c.safeTime > startTime) {
3301
+ // If a change happened after starting reading the item
3302
+ // this may no longer be valid
3303
+ if (log && this._remainingLogs > 0) {
3304
+ this._log(
3305
+ path,
3306
+ "it may have changed (%d) after the start time of the snapshot (%d)",
3307
+ c.safeTime,
3308
+ startTime
3309
+ );
3310
+ }
3311
+ return false;
3312
+ }
3313
+ const snap = /** @type {FileSystemInfoEntry} */ (s);
3314
+ if (snap.timestamp !== undefined && c.timestamp !== snap.timestamp) {
3315
+ // If we have a timestamp (it was a file or symlink) and it differs from current timestamp
3316
+ // it's invalid
3317
+ if (log && this._remainingLogs > 0) {
3318
+ this._log(
3319
+ path,
3320
+ "timestamps differ (%d != %d)",
3321
+ c.timestamp,
3322
+ snap.timestamp
3323
+ );
3324
+ }
3325
+ return false;
3326
+ }
3327
+ }
3328
+ return true;
3329
+ };
3330
+ /**
3331
+ * Checks true, if ok.
3332
+ * @param {string} path file path
3333
+ * @param {ResolvedContextFileSystemInfoEntry | null} c current entry
3334
+ * @param {ResolvedContextFileSystemInfoEntry | null} s entry from snapshot
3335
+ * @param {boolean} log log reason
3336
+ * @returns {boolean} true, if ok
3337
+ */
3338
+ const checkContext = (path, c, s, log = true) => {
3339
+ if (c === s) return true;
3340
+ if (!checkExistence(path, Boolean(c), Boolean(s))) return false;
3341
+ if (c) {
3342
+ // For existing items only
3343
+ if (typeof startTime === "number" && c.safeTime > startTime) {
3344
+ // If a change happened after starting reading the item
3345
+ // this may no longer be valid
3346
+ if (log && this._remainingLogs > 0) {
3347
+ this._log(
3348
+ path,
3349
+ "it may have changed (%d) after the start time of the snapshot (%d)",
3350
+ c.safeTime,
3351
+ startTime
3352
+ );
3353
+ }
3354
+ return false;
3355
+ }
3356
+ const snap = /** @type {ResolvedContextFileSystemInfoEntry} */ (s);
3357
+ if (
3358
+ snap.timestampHash !== undefined &&
3359
+ c.timestampHash !== snap.timestampHash
3360
+ ) {
3361
+ // If we have a timestampHash (it was a directory) and it differs from current timestampHash
3362
+ // it's invalid
3363
+ if (log && this._remainingLogs > 0) {
3364
+ this._log(
3365
+ path,
3366
+ "timestamps hashes differ (%s != %s)",
3367
+ c.timestampHash,
3368
+ snap.timestampHash
3369
+ );
3370
+ }
3371
+ return false;
3372
+ }
3373
+ }
3374
+ return true;
3375
+ };
3376
+ if (snapshot.hasChildren()) {
3377
+ /**
3378
+ * Processes the provided err.
3379
+ * @param {(WebpackError | null)=} err err
3380
+ * @param {boolean=} result result
3381
+ * @returns {void}
3382
+ */
3383
+ const childCallback = (err, result) => {
3384
+ if (err || !result) return invalid();
3385
+ jobDone();
3386
+ };
3387
+ for (const child of /** @type {Children} */ (snapshot.children)) {
3388
+ const cache = this._snapshotCache.get(child);
3389
+ if (cache !== undefined) {
3390
+ this._statTestedChildrenCached++;
3391
+ /* istanbul ignore else */
3392
+ if (typeof cache === "boolean") {
3393
+ if (cache === false) {
3394
+ invalid();
3395
+ return;
3396
+ }
3397
+ } else {
3398
+ jobs++;
3399
+ cache.push(childCallback);
3400
+ }
3401
+ } else {
3402
+ this._statTestedChildrenNotCached++;
3403
+ jobs++;
3404
+ this._checkSnapshotValidNoCache(child, childCallback);
3405
+ }
3406
+ }
3407
+ }
3408
+ if (snapshot.hasFileTimestamps()) {
3409
+ const fileTimestamps =
3410
+ /** @type {FileTimestamps} */
3411
+ (snapshot.fileTimestamps);
3412
+ this._statTestedEntries += fileTimestamps.size;
3413
+ for (const [path, ts] of fileTimestamps) {
3414
+ const cache = this._fileTimestamps.get(path);
3415
+ if (cache !== undefined && !isExistenceOnly(cache)) {
3416
+ if (
3417
+ cache !== "ignore" &&
3418
+ !checkFile(
3419
+ path,
3420
+ /** @type {FileSystemInfoEntry | null} */ (cache),
3421
+ ts
3422
+ )
3423
+ ) {
3424
+ invalid();
3425
+ return;
3426
+ }
3427
+ } else {
3428
+ jobs++;
3429
+ this.fileTimestampQueue.add(path, (err, entry) => {
3430
+ if (err) return invalidWithError(path, err);
3431
+ if (
3432
+ !checkFile(
3433
+ path,
3434
+ /** @type {FileSystemInfoEntry | null} */ (entry),
3435
+ ts
3436
+ )
3437
+ ) {
3438
+ invalid();
3439
+ } else {
3440
+ jobDone();
3441
+ }
3442
+ });
3443
+ }
3444
+ }
3445
+ }
3446
+ /**
3447
+ * Process file hash snapshot.
3448
+ * @param {string} path file path
3449
+ * @param {string | null} hash hash
3450
+ */
3451
+ const processFileHashSnapshot = (path, hash) => {
3452
+ const cache = this._fileHashes.get(path);
3453
+ if (cache !== undefined) {
3454
+ if (cache !== "ignore" && !checkHash(path, cache, hash)) {
3455
+ invalid();
3456
+ }
3457
+ } else {
3458
+ jobs++;
3459
+ this.fileHashQueue.add(path, (err, entry) => {
3460
+ if (err) return invalidWithError(path, err);
3461
+ if (!checkHash(path, /** @type {string} */ (entry), hash)) {
3462
+ invalid();
3463
+ } else {
3464
+ jobDone();
3465
+ }
3466
+ });
3467
+ }
3468
+ };
3469
+ if (snapshot.hasFileHashes()) {
3470
+ const fileHashes = /** @type {FileHashes} */ (snapshot.fileHashes);
3471
+ this._statTestedEntries += fileHashes.size;
3472
+ for (const [path, hash] of fileHashes) {
3473
+ processFileHashSnapshot(path, hash);
3474
+ }
3475
+ }
3476
+ if (snapshot.hasFileTshs()) {
3477
+ const fileTshs = /** @type {FileTshs} */ (snapshot.fileTshs);
3478
+ this._statTestedEntries += fileTshs.size;
3479
+ for (const [path, tsh] of fileTshs) {
3480
+ if (typeof tsh === "string") {
3481
+ processFileHashSnapshot(path, tsh);
3482
+ } else {
3483
+ const cache = this._fileTimestamps.get(path);
3484
+ if (cache !== undefined && !isExistenceOnly(cache)) {
3485
+ if (
3486
+ cache === "ignore" ||
3487
+ !checkFile(
3488
+ path,
3489
+ /** @type {FileSystemInfoEntry | null} */ (cache),
3490
+ tsh,
3491
+ false
3492
+ )
3493
+ ) {
3494
+ processFileHashSnapshot(path, tsh && tsh.hash);
3495
+ }
3496
+ } else {
3497
+ jobs++;
3498
+ this.fileTimestampQueue.add(path, (err, entry) => {
3499
+ if (err) return invalidWithError(path, err);
3500
+ if (
3501
+ !checkFile(
3502
+ path,
3503
+ /** @type {FileSystemInfoEntry | null} */
3504
+ (entry),
3505
+ tsh,
3506
+ false
3507
+ )
3508
+ ) {
3509
+ processFileHashSnapshot(path, tsh && tsh.hash);
3510
+ }
3511
+ jobDone();
3512
+ });
3513
+ }
3514
+ }
3515
+ }
3516
+ }
3517
+ if (snapshot.hasContextTimestamps()) {
3518
+ const contextTimestamps =
3519
+ /** @type {ContextTimestamps} */
3520
+ (snapshot.contextTimestamps);
3521
+ this._statTestedEntries += contextTimestamps.size;
3522
+ for (const [path, ts] of contextTimestamps) {
3523
+ const cache = this._contextTimestamps.get(path);
3524
+ if (cache === "ignore") continue;
3525
+ // Treat existence-only entries (`{}` from watchpack) as a cache
3526
+ // miss — they carry no time info, so we cannot compare them to
3527
+ // the snapshot.
3528
+ /** @type {ContextFileSystemInfoEntry | null | undefined} */
3529
+ const usableCache =
3530
+ cache === undefined || isExistenceOnly(cache)
3531
+ ? undefined
3532
+ : /** @type {ContextFileSystemInfoEntry | null} */ (cache);
3533
+ const cacheLacksHash =
3534
+ contextCacheEntryLacksTimestampHash(usableCache) &&
3535
+ ts !== null &&
3536
+ ts.timestampHash !== undefined;
3537
+ /** @type {undefined | null | ResolvedContextFileSystemInfoEntry} */
3538
+ let resolved;
3539
+ if (
3540
+ usableCache !== undefined &&
3541
+ !cacheLacksHash &&
3542
+ (resolved = getResolvedTimestamp(usableCache)) !== undefined
3543
+ ) {
3544
+ if (!checkContext(path, resolved, ts)) {
3545
+ invalid();
3546
+ return;
3547
+ }
3548
+ } else {
3549
+ jobs++;
3550
+ /**
3551
+ * Processes the provided err.
3552
+ * @param {(WebpackError | null)=} err error
3553
+ * @param {ResolvedContextTimestamp=} entry entry
3554
+ * @returns {void}
3555
+ */
3556
+ const callback = (err, entry) => {
3557
+ if (err) return invalidWithError(path, err);
3558
+ if (
3559
+ !checkContext(
3560
+ path,
3561
+ /** @type {ResolvedContextFileSystemInfoEntry | null} */
3562
+ (entry),
3563
+ ts
3564
+ )
3565
+ ) {
3566
+ invalid();
3567
+ } else {
3568
+ jobDone();
3569
+ }
3570
+ };
3571
+ if (cacheLacksHash) {
3572
+ this._readFreshContextTimestamp(path, callback);
3573
+ } else if (usableCache !== undefined && usableCache !== null) {
3574
+ this._resolveContextTimestamp(usableCache, callback);
3575
+ } else {
3576
+ this.getContextTimestamp(path, callback);
3577
+ }
3578
+ }
3579
+ }
3580
+ }
3581
+ /**
3582
+ * Process context hash snapshot.
3583
+ * @param {string} path path
3584
+ * @param {string | null} hash hash
3585
+ */
3586
+ const processContextHashSnapshot = (path, hash) => {
3587
+ const cache = this._contextHashes.get(path);
3588
+ /** @type {undefined | null | string} */
3589
+ let resolved;
3590
+ if (
3591
+ cache !== undefined &&
3592
+ (resolved = getResolvedHash(cache)) !== undefined
3593
+ ) {
3594
+ if (!checkHash(path, resolved, hash)) {
3595
+ invalid();
3596
+ }
3597
+ } else {
3598
+ jobs++;
3599
+ /**
3600
+ * Processes the provided err.
3601
+ * @param {(WebpackError | null)=} err err
3602
+ * @param {string=} entry entry
3603
+ * @returns {void}
3604
+ */
3605
+ const callback = (err, entry) => {
3606
+ if (err) return invalidWithError(path, err);
3607
+ if (!checkHash(path, /** @type {string} */ (entry), hash)) {
3608
+ invalid();
3609
+ } else {
3610
+ jobDone();
3611
+ }
3612
+ };
3613
+ if (cache !== undefined) {
3614
+ this._resolveContextHash(cache, callback);
3615
+ } else {
3616
+ this.getContextHash(path, callback);
3617
+ }
3618
+ }
3619
+ };
3620
+ if (snapshot.hasContextHashes()) {
3621
+ const contextHashes =
3622
+ /** @type {ContextHashes} */
3623
+ (snapshot.contextHashes);
3624
+ this._statTestedEntries += contextHashes.size;
3625
+ for (const [path, hash] of contextHashes) {
3626
+ processContextHashSnapshot(path, hash);
3627
+ }
3628
+ }
3629
+ if (snapshot.hasContextTshs()) {
3630
+ const contextTshs = /** @type {ContextTshs} */ (snapshot.contextTshs);
3631
+ this._statTestedEntries += contextTshs.size;
3632
+ for (const [path, tsh] of contextTshs) {
3633
+ if (typeof tsh === "string") {
3634
+ processContextHashSnapshot(path, tsh);
3635
+ } else {
3636
+ const cache = this._contextTimestamps.get(path);
3637
+ if (cache === "ignore") continue;
3638
+ // See the matching block in `hasContextTimestamps` above.
3639
+ /** @type {ContextFileSystemInfoEntry | null | undefined} */
3640
+ const usableCache =
3641
+ cache === undefined || isExistenceOnly(cache)
3642
+ ? undefined
3643
+ : /** @type {ContextFileSystemInfoEntry | null} */ (cache);
3644
+ const cacheLacksHash =
3645
+ contextCacheEntryLacksTimestampHash(usableCache) &&
3646
+ tsh !== null &&
3647
+ tsh.timestampHash !== undefined;
3648
+ /** @type {undefined | null | ResolvedContextFileSystemInfoEntry} */
3649
+ let resolved;
3650
+ if (
3651
+ usableCache !== undefined &&
3652
+ !cacheLacksHash &&
3653
+ (resolved = getResolvedTimestamp(usableCache)) !== undefined
3654
+ ) {
3655
+ if (!checkContext(path, resolved, tsh, false)) {
3656
+ processContextHashSnapshot(path, tsh && tsh.hash);
3657
+ }
3658
+ } else {
3659
+ jobs++;
3660
+ /**
3661
+ * Processes the provided err.
3662
+ * @param {(WebpackError | null)=} err error
3663
+ * @param {ResolvedContextTimestamp=} entry entry
3664
+ * @returns {void}
3665
+ */
3666
+ const callback = (err, entry) => {
3667
+ if (err) return invalidWithError(path, err);
3668
+ if (
3669
+ !checkContext(
3670
+ path,
3671
+ /** @type {ResolvedContextFileSystemInfoEntry | null} */
3672
+ (entry),
3673
+ tsh,
3674
+ false
3675
+ )
3676
+ ) {
3677
+ processContextHashSnapshot(path, tsh && tsh.hash);
3678
+ }
3679
+ jobDone();
3680
+ };
3681
+ if (cacheLacksHash) {
3682
+ this._readFreshContextTimestamp(path, callback);
3683
+ } else if (usableCache !== undefined && usableCache !== null) {
3684
+ this._resolveContextTimestamp(usableCache, callback);
3685
+ } else {
3686
+ this.getContextTimestamp(path, callback);
3687
+ }
3688
+ }
3689
+ }
3690
+ }
3691
+ }
3692
+ if (snapshot.hasMissingExistence()) {
3693
+ const missingExistence =
3694
+ /** @type {MissingExistence} */
3695
+ (snapshot.missingExistence);
3696
+ this._statTestedEntries += missingExistence.size;
3697
+ for (const [path, existence] of missingExistence) {
3698
+ const cache = this._fileTimestamps.get(path);
3699
+ if (cache !== undefined && !isExistenceOnly(cache)) {
3700
+ if (
3701
+ cache !== "ignore" &&
3702
+ !checkExistence(path, Boolean(cache), Boolean(existence))
3703
+ ) {
3704
+ invalid();
3705
+ return;
3706
+ }
3707
+ } else {
3708
+ jobs++;
3709
+ this.fileTimestampQueue.add(path, (err, entry) => {
3710
+ if (err) return invalidWithError(path, err);
3711
+ if (!checkExistence(path, Boolean(entry), Boolean(existence))) {
3712
+ invalid();
3713
+ } else {
3714
+ jobDone();
3715
+ }
3716
+ });
3717
+ }
3718
+ }
3719
+ }
3720
+ if (snapshot.hasManagedItemInfo()) {
3721
+ const managedItemInfo =
3722
+ /** @type {ManagedItemInfo} */
3723
+ (snapshot.managedItemInfo);
3724
+ this._statTestedEntries += managedItemInfo.size;
3725
+ for (const [path, info] of managedItemInfo) {
3726
+ const cache = this._managedItems.get(path);
3727
+ if (cache !== undefined) {
3728
+ if (!checkHash(path, cache, info)) {
3729
+ invalid();
3730
+ return;
3731
+ }
3732
+ } else {
3733
+ jobs++;
3734
+ this.managedItemQueue.add(path, (err, entry) => {
3735
+ if (err) return invalidWithError(path, err);
3736
+ if (!checkHash(path, /** @type {string} */ (entry), info)) {
3737
+ invalid();
3738
+ } else {
3739
+ jobDone();
3740
+ }
3741
+ });
3742
+ }
3743
+ }
3744
+ }
3745
+ jobDone();
3746
+
3747
+ // if there was an async action
3748
+ // try to join multiple concurrent request for this snapshot
3749
+ if (jobs > 0) {
3750
+ const callbacks = [callback];
3751
+ callback = (err, result) => {
3752
+ for (const callback of callbacks) callback(err, result);
3753
+ };
3754
+ this._snapshotCache.set(snapshot, callbacks);
3755
+ }
3756
+ }
3757
+
3758
+ /**
3759
+ * @private
3760
+ * @type {Processor<string, FileSystemInfoEntry>}
3761
+ */
3762
+ _readFileTimestamp(path, callback) {
3763
+ this.fs.stat(path, (err, _stat) => {
3764
+ if (err) {
3765
+ if (err.code === "ENOENT") {
3766
+ this._fileTimestamps.set(path, null);
3767
+ this._cachedDeprecatedFileTimestamps = undefined;
3768
+ return callback(null, null);
3769
+ }
3770
+ return callback(/** @type {WebpackError} */ (err));
3771
+ }
3772
+ const stat = /** @type {IStats} */ (_stat);
3773
+ /** @type {FileSystemInfoEntry} */
3774
+ let ts;
3775
+ if (stat.isDirectory()) {
3776
+ ts = {
3777
+ safeTime: 0,
3778
+ timestamp: undefined
3779
+ };
3780
+ } else {
3781
+ const mtime = Number(stat.mtime);
3782
+
3783
+ if (mtime) applyMtime(mtime);
3784
+
3785
+ ts = {
3786
+ safeTime: mtime ? mtime + FS_ACCURACY : Infinity,
3787
+ timestamp: mtime
3788
+ };
3789
+ }
3790
+
3791
+ this._fileTimestamps.set(path, ts);
3792
+ this._cachedDeprecatedFileTimestamps = undefined;
3793
+
3794
+ callback(null, ts);
3795
+ });
3796
+ }
3797
+
3798
+ /**
3799
+ * @private
3800
+ * @type {Processor<string, string>}
3801
+ */
3802
+ _readFileHash(path, callback) {
3803
+ this.fs.readFile(path, (err, content) => {
3804
+ if (err) {
3805
+ if (err.code === "EISDIR") {
3806
+ this._fileHashes.set(path, "directory");
3807
+ return callback(null, "directory");
3808
+ }
3809
+ if (err.code === "ENOENT") {
3810
+ this._fileHashes.set(path, null);
3811
+ return callback(null, null);
3812
+ }
3813
+ if (err.code === "ERR_FS_FILE_TOO_LARGE") {
3814
+ /** @type {Logger} */
3815
+ (this.logger).warn(`Ignoring ${path} for hashing as it's very large`);
3816
+ this._fileHashes.set(path, "too large");
3817
+ return callback(null, "too large");
3818
+ }
3819
+ return callback(/** @type {WebpackError} */ (err));
3820
+ }
3821
+
3822
+ const hash = createHash(this._hashFunction);
3823
+
3824
+ hash.update(/** @type {string | Buffer} */ (content));
3825
+
3826
+ const digest = hash.digest("hex");
3827
+
3828
+ this._fileHashes.set(path, digest);
3829
+
3830
+ callback(null, digest);
3831
+ });
3832
+ }
3833
+
3834
+ /**
3835
+ * Get file timestamp and hash.
3836
+ * @private
3837
+ * @param {string} path path
3838
+ * @param {(err: WebpackError | null, timestampAndHash?: TimestampAndHash | string) => void} callback callback
3839
+ */
3840
+ _getFileTimestampAndHash(path, callback) {
3841
+ /**
3842
+ * Continue with hash.
3843
+ * @param {string} hash hash
3844
+ * @returns {void}
3845
+ */
3846
+ const continueWithHash = (hash) => {
3847
+ const cache = this._fileTimestamps.get(path);
3848
+ if (cache !== undefined) {
3849
+ if (cache !== "ignore") {
3850
+ /** @type {TimestampAndHash} */
3851
+ const result = {
3852
+ .../** @type {FileSystemInfoEntry} */ (cache),
3853
+ hash
3854
+ };
3855
+ this._fileTshs.set(path, result);
3856
+ return callback(null, result);
3857
+ }
3858
+ this._fileTshs.set(path, hash);
3859
+ return callback(null, hash);
3860
+ }
3861
+ this.fileTimestampQueue.add(path, (err, entry) => {
3862
+ if (err) {
3863
+ return callback(err);
3864
+ }
3865
+ /** @type {TimestampAndHash} */
3866
+ const result = {
3867
+ .../** @type {FileSystemInfoEntry} */ (entry),
3868
+ hash
3869
+ };
3870
+ this._fileTshs.set(path, result);
3871
+ return callback(null, result);
3872
+ });
3873
+ };
3874
+
3875
+ const cache = this._fileHashes.get(path);
3876
+ if (cache !== undefined) {
3877
+ continueWithHash(/** @type {string} */ (cache));
3878
+ } else {
3879
+ this.fileHashQueue.add(path, (err, entry) => {
3880
+ if (err) {
3881
+ return callback(err);
3882
+ }
3883
+ continueWithHash(/** @type {string} */ (entry));
3884
+ });
3885
+ }
3886
+ }
3887
+
3888
+ /**
3889
+ * Processes the provided object.
3890
+ * @private
3891
+ * @template T
3892
+ * @template ItemType
3893
+ * @param {object} options options
3894
+ * @param {string} options.path path
3895
+ * @param {(value: string) => ItemType} options.fromImmutablePath called when context item is an immutable path
3896
+ * @param {(value: string) => ItemType} options.fromManagedItem called when context item is a managed path
3897
+ * @param {(value: string, result: string, callback: (err?: WebpackError | null, itemType?: ItemType) => void) => void} options.fromSymlink called when context item is a symlink
3898
+ * @param {(value: string, stats: IStats, callback: (err?: WebpackError | null, itemType?: ItemType | null) => void) => void} options.fromFile called when context item is a file
3899
+ * @param {(value: string, stats: IStats, callback: (err?: WebpackError | null, itemType?: ItemType) => void) => void} options.fromDirectory called when context item is a directory
3900
+ * @param {(arr: string[], arr1: ItemType[]) => T} options.reduce called from all context items
3901
+ * @param {(err?: Error | null, result?: T | null) => void} callback callback
3902
+ */
3903
+ _readContext(
3904
+ {
3905
+ path,
3906
+ fromImmutablePath,
3907
+ fromManagedItem,
3908
+ fromSymlink,
3909
+ fromFile,
3910
+ fromDirectory,
3911
+ reduce
3912
+ },
3913
+ callback
3914
+ ) {
3915
+ this.fs.readdir(path, (err, _files) => {
3916
+ if (err) {
3917
+ if (err.code === "ENOENT") {
3918
+ return callback(null, null);
3919
+ }
3920
+ return callback(err);
3921
+ }
3922
+ const files = /** @type {string[]} */ (_files)
3923
+ .map((file) => file.normalize("NFC"))
3924
+ .filter((file) => !/^\./.test(file))
3925
+ .sort();
3926
+ asyncLib.map(
3927
+ files,
3928
+ (file, callback) => {
3929
+ const child = join(this.fs, path, file);
3930
+ for (const immutablePath of this.immutablePathsRegExps) {
3931
+ if (immutablePath.test(path)) {
3932
+ // ignore any immutable path for timestamping
3933
+ return callback(null, fromImmutablePath(path));
3934
+ }
3935
+ }
3936
+ for (const immutablePath of this.immutablePathsWithSlash) {
3937
+ if (path.startsWith(immutablePath)) {
3938
+ // ignore any immutable path for timestamping
3939
+ return callback(null, fromImmutablePath(path));
3940
+ }
3941
+ }
3942
+ for (const managedPath of this.managedPathsRegExps) {
3943
+ const match = managedPath.exec(path);
3944
+ if (match) {
3945
+ const managedItem = getManagedItem(
3946
+ getManagedPathFromMatch(match),
3947
+ path
3948
+ );
3949
+ if (managedItem) {
3950
+ // construct timestampHash from managed info
3951
+ return this.managedItemQueue.add(managedItem, (err, info) => {
3952
+ if (err) return callback(err);
3953
+ return callback(
3954
+ null,
3955
+ fromManagedItem(/** @type {string} */ (info))
3956
+ );
3957
+ });
3958
+ }
3959
+ }
3960
+ }
3961
+ for (const managedPath of this.managedPathsWithSlash) {
3962
+ if (path.startsWith(managedPath)) {
3963
+ const managedItem = getManagedItem(managedPath, child);
3964
+ if (managedItem) {
3965
+ // construct timestampHash from managed info
3966
+ return this.managedItemQueue.add(managedItem, (err, info) => {
3967
+ if (err) return callback(err);
3968
+ return callback(
3969
+ null,
3970
+ fromManagedItem(/** @type {string} */ (info))
3971
+ );
3972
+ });
3973
+ }
3974
+ }
3975
+ }
3976
+
3977
+ lstatReadlinkAbsolute(this.fs, child, (err, _stat) => {
3978
+ if (err) return callback(err);
3979
+
3980
+ const stat = /** @type {IStats | string} */ (_stat);
3981
+
3982
+ if (typeof stat === "string") {
3983
+ return fromSymlink(child, stat, callback);
3984
+ }
3985
+
3986
+ if (stat.isFile()) {
3987
+ return fromFile(child, stat, callback);
3988
+ }
3989
+ if (stat.isDirectory()) {
3990
+ return fromDirectory(child, stat, callback);
3991
+ }
3992
+ callback(null, null);
3993
+ });
3994
+ },
3995
+ (err, results) => {
3996
+ if (err) return callback(err);
3997
+ const result = reduce(files, /** @type {ItemType[]} */ (results));
3998
+ callback(null, result);
3999
+ }
4000
+ );
4001
+ });
4002
+ }
4003
+
4004
+ /**
4005
+ * @private
4006
+ * @type {Processor<string, ContextFileSystemInfoEntry>}
4007
+ */
4008
+ _readContextTimestamp(path, callback) {
4009
+ this._readContext(
4010
+ {
4011
+ path,
4012
+ fromImmutablePath: () =>
4013
+ /** @type {ContextFileSystemInfoEntry | FileSystemInfoEntry | "ignore" | null} */
4014
+ (null),
4015
+ fromManagedItem: (info) => ({
4016
+ safeTime: 0,
4017
+ timestampHash: info
4018
+ }),
4019
+ fromSymlink: (file, target, callback) => {
4020
+ callback(
4021
+ null,
4022
+ /** @type {ContextFileSystemInfoEntry} */
4023
+ ({
4024
+ timestampHash: target,
4025
+ symlinks: new Set([target])
4026
+ })
4027
+ );
4028
+ },
4029
+ fromFile: (file, stat, callback) => {
4030
+ // Prefer the cached value over our new stat to report consistent results
4031
+ const cache = this._fileTimestamps.get(file);
4032
+ if (cache !== undefined && !isExistenceOnly(cache)) {
4033
+ return callback(
4034
+ null,
4035
+ cache === "ignore"
4036
+ ? null
4037
+ : /** @type {FileSystemInfoEntry | null} */ (cache)
4038
+ );
4039
+ }
4040
+
4041
+ const mtime = Number(stat.mtime);
4042
+
4043
+ if (mtime) applyMtime(mtime);
4044
+
4045
+ /** @type {FileSystemInfoEntry} */
4046
+ const ts = {
4047
+ safeTime: mtime ? mtime + FS_ACCURACY : Infinity,
4048
+ timestamp: mtime
4049
+ };
4050
+
4051
+ this._fileTimestamps.set(file, ts);
4052
+ this._cachedDeprecatedFileTimestamps = undefined;
4053
+ callback(null, ts);
4054
+ },
4055
+ fromDirectory: (directory, stat, callback) => {
4056
+ this.contextTimestampQueue.increaseParallelism();
4057
+ this._getUnresolvedContextTimestamp(directory, (err, tsEntry) => {
4058
+ this.contextTimestampQueue.decreaseParallelism();
4059
+ callback(err, tsEntry);
4060
+ });
4061
+ },
4062
+ reduce: (files, tsEntries) => {
4063
+ /** @type {undefined | Symlinks} */
4064
+ let symlinks;
4065
+
4066
+ const hash = createHash(this._hashFunction);
4067
+
4068
+ for (const file of files) hash.update(file);
4069
+ let safeTime = 0;
4070
+ for (const _e of tsEntries) {
4071
+ if (!_e) {
4072
+ hash.update("n");
4073
+ continue;
4074
+ }
4075
+ const entry =
4076
+ /** @type {FileSystemInfoEntry | ContextFileSystemInfoEntry} */
4077
+ (_e);
4078
+ if (/** @type {FileSystemInfoEntry} */ (entry).timestamp) {
4079
+ hash.update("f");
4080
+ hash.update(
4081
+ `${/** @type {FileSystemInfoEntry} */ (entry).timestamp}`
4082
+ );
4083
+ } else if (
4084
+ /** @type {ContextFileSystemInfoEntry} */ (entry).timestampHash
4085
+ ) {
4086
+ hash.update("d");
4087
+ hash.update(
4088
+ `${/** @type {ContextFileSystemInfoEntry} */ (entry).timestampHash}`
4089
+ );
4090
+ }
4091
+ if (
4092
+ /** @type {ContextFileSystemInfoEntry} */
4093
+ (entry).symlinks !== undefined
4094
+ ) {
4095
+ if (symlinks === undefined) symlinks = new Set();
4096
+ addAll(
4097
+ /** @type {ContextFileSystemInfoEntry} */ (entry).symlinks,
4098
+ symlinks
4099
+ );
4100
+ }
4101
+ if (entry.safeTime) {
4102
+ safeTime = Math.max(safeTime, entry.safeTime);
4103
+ }
4104
+ }
4105
+
4106
+ const digest = hash.digest("hex");
4107
+ /** @type {ContextFileSystemInfoEntry} */
4108
+ const result = {
4109
+ safeTime,
4110
+ timestampHash: digest
4111
+ };
4112
+ if (symlinks) result.symlinks = symlinks;
4113
+ return result;
4114
+ }
4115
+ },
4116
+ (err, result) => {
4117
+ if (err) return callback(/** @type {WebpackError} */ (err));
4118
+ this._contextTimestamps.set(path, result);
4119
+ this._cachedDeprecatedContextTimestamps = undefined;
4120
+
4121
+ callback(null, result);
4122
+ }
4123
+ );
4124
+ }
4125
+
4126
+ /**
4127
+ * Resolve context timestamp.
4128
+ * @private
4129
+ * @param {ContextFileSystemInfoEntry} entry entry
4130
+ * @param {(err?: WebpackError | null, resolvedContextTimestamp?: ResolvedContextTimestamp) => void} callback callback
4131
+ * @returns {void}
4132
+ */
4133
+ _resolveContextTimestamp(entry, callback) {
4134
+ /** @type {string[]} */
4135
+ const hashes = [];
4136
+ let safeTime = 0;
4137
+ // Skip already-visited symlink targets so cyclic pnpm/peer-variant graphs terminate (#21084).
4138
+ const seen = new Set(entry.symlinks);
4139
+ processAsyncTree(
4140
+ /** @type {NonNullable<ContextHash["symlinks"]>} */ (entry.symlinks),
4141
+ 10,
4142
+ (target, push, callback) => {
4143
+ this._getUnresolvedContextTimestamp(target, (err, entry) => {
4144
+ if (err) return callback(err);
4145
+ if (entry && entry !== "ignore") {
4146
+ hashes.push(/** @type {string} */ (entry.timestampHash));
4147
+ if (entry.safeTime) {
4148
+ safeTime = Math.max(safeTime, entry.safeTime);
4149
+ }
4150
+ if (entry.symlinks !== undefined) {
4151
+ for (const target of entry.symlinks) {
4152
+ if (!seen.has(target)) {
4153
+ seen.add(target);
4154
+ push(target);
4155
+ }
4156
+ }
4157
+ }
4158
+ }
4159
+ callback();
4160
+ });
4161
+ },
4162
+ (err) => {
4163
+ if (err) return callback(/** @type {WebpackError} */ (err));
4164
+ const hash = createHash(this._hashFunction);
4165
+ hash.update(/** @type {string} */ (entry.timestampHash));
4166
+ if (entry.safeTime) {
4167
+ safeTime = Math.max(safeTime, entry.safeTime);
4168
+ }
4169
+ hashes.sort();
4170
+ for (const h of hashes) {
4171
+ hash.update(h);
4172
+ }
4173
+ callback(
4174
+ null,
4175
+ (entry.resolved = {
4176
+ safeTime,
4177
+ timestampHash: hash.digest("hex")
4178
+ })
4179
+ );
4180
+ }
4181
+ );
4182
+ }
4183
+
4184
+ /**
4185
+ * @private
4186
+ * @type {Processor<string, ContextHash>}
4187
+ */
4188
+ _readContextHash(path, callback) {
4189
+ this._readContext(
4190
+ {
4191
+ path,
4192
+ fromImmutablePath: () => /** @type {ContextHash | ""} */ (""),
4193
+ fromManagedItem: (info) => info || "",
4194
+ fromSymlink: (file, target, callback) => {
4195
+ callback(
4196
+ null,
4197
+ /** @type {ContextHash} */
4198
+ ({
4199
+ hash: target,
4200
+ symlinks: new Set([target])
4201
+ })
4202
+ );
4203
+ },
4204
+ fromFile: (file, stat, callback) =>
4205
+ this.getFileHash(file, (err, hash) => {
4206
+ callback(err, hash || "");
4207
+ }),
4208
+ fromDirectory: (directory, stat, callback) => {
4209
+ this.contextHashQueue.increaseParallelism();
4210
+ this._getUnresolvedContextHash(directory, (err, hash) => {
4211
+ this.contextHashQueue.decreaseParallelism();
4212
+ callback(err, hash || "");
4213
+ });
4214
+ },
4215
+ /**
4216
+ * Returns reduced hash.
4217
+ * @param {string[]} files files
4218
+ * @param {(string | ContextHash | null)[]} fileHashes hashes
4219
+ * @returns {ContextHash} reduced hash
4220
+ */
4221
+ reduce: (files, fileHashes) => {
4222
+ /** @type {undefined | Symlinks} */
4223
+ let symlinks;
4224
+ const hash = createHash(this._hashFunction);
4225
+
4226
+ for (const file of files) hash.update(file);
4227
+ for (const entry of fileHashes) {
4228
+ // null for unsupported entry kinds (FIFO, socket); skip like the tsh reduce
4229
+ if (!entry) {
4230
+ continue;
4231
+ } else if (typeof entry === "string") {
4232
+ hash.update(entry);
4233
+ } else {
4234
+ if (entry.hash) hash.update(entry.hash);
4235
+ if (entry.symlinks) {
4236
+ if (symlinks === undefined) symlinks = new Set();
4237
+ addAll(entry.symlinks, symlinks);
4238
+ }
4239
+ }
4240
+ }
4241
+
4242
+ /** @type {ContextHash} */
4243
+ const result = {
4244
+ hash: hash.digest("hex")
4245
+ };
4246
+ if (symlinks) result.symlinks = symlinks;
4247
+ return result;
4248
+ }
4249
+ },
4250
+ (err, _result) => {
4251
+ if (err) return callback(/** @type {WebpackError} */ (err));
4252
+ const result = /** @type {ContextHash} */ (_result);
4253
+ this._contextHashes.set(path, result);
4254
+ return callback(null, result);
4255
+ }
4256
+ );
4257
+ }
4258
+
4259
+ /**
4260
+ * Resolve context hash.
4261
+ * @private
4262
+ * @param {ContextHash} entry context hash
4263
+ * @param {(err: WebpackError | null, contextHash?: string) => void} callback callback
4264
+ * @returns {void}
4265
+ */
4266
+ _resolveContextHash(entry, callback) {
4267
+ /** @type {string[]} */
4268
+ const hashes = [];
4269
+ // Skip already-visited symlink targets so cyclic pnpm/peer-variant graphs terminate (#21084).
4270
+ const seen = new Set(entry.symlinks);
4271
+ processAsyncTree(
4272
+ /** @type {NonNullable<ContextHash["symlinks"]>} */ (entry.symlinks),
4273
+ 10,
4274
+ (target, push, callback) => {
4275
+ this._getUnresolvedContextHash(target, (err, hash) => {
4276
+ if (err) return callback(err);
4277
+ if (hash) {
4278
+ hashes.push(hash.hash);
4279
+ if (hash.symlinks !== undefined) {
4280
+ for (const target of hash.symlinks) {
4281
+ if (!seen.has(target)) {
4282
+ seen.add(target);
4283
+ push(target);
4284
+ }
4285
+ }
4286
+ }
4287
+ }
4288
+ callback();
4289
+ });
4290
+ },
4291
+ (err) => {
4292
+ if (err) return callback(/** @type {WebpackError} */ (err));
4293
+ const hash = createHash(this._hashFunction);
4294
+ hash.update(entry.hash);
4295
+ hashes.sort();
4296
+ for (const h of hashes) {
4297
+ hash.update(h);
4298
+ }
4299
+ callback(null, (entry.resolved = hash.digest("hex")));
4300
+ }
4301
+ );
4302
+ }
4303
+
4304
+ /**
4305
+ * @private
4306
+ * @type {Processor<string, ContextTimestampAndHash>}
4307
+ */
4308
+ _readContextTimestampAndHash(path, callback) {
4309
+ /**
4310
+ * Processes the provided timestamp.
4311
+ * @param {ContextTimestamp} timestamp timestamp
4312
+ * @param {ContextHash | null} hash hash
4313
+ */
4314
+ const finalize = (timestamp, hash) => {
4315
+ // Merging two `null` reads yields `{}`, which reads as "exists, no hash" (#21636)
4316
+ const result =
4317
+ /** @type {ContextTimestampAndHash} */
4318
+ (
4319
+ hash === null || timestamp === "ignore"
4320
+ ? hash
4321
+ : { ...timestamp, ...hash }
4322
+ );
4323
+ this._contextTshs.set(path, result);
4324
+ callback(null, result);
4325
+ };
4326
+ const cachedHash = this._contextHashes.get(path);
4327
+ const cachedTimestamp = this._contextTimestamps.get(path);
4328
+ if (cachedHash !== undefined) {
4329
+ if (cachedTimestamp !== undefined) {
4330
+ finalize(cachedTimestamp, cachedHash);
4331
+ } else {
4332
+ this.contextTimestampQueue.add(path, (err, entry) => {
4333
+ if (err) return callback(err);
4334
+ finalize(
4335
+ /** @type {ContextFileSystemInfoEntry} */
4336
+ (entry),
4337
+ cachedHash
4338
+ );
4339
+ });
4340
+ }
4341
+ } else if (cachedTimestamp !== undefined) {
4342
+ this.contextHashQueue.add(path, (err, entry) => {
4343
+ if (err) return callback(err);
4344
+ finalize(cachedTimestamp, /** @type {ContextHash} */ (entry));
4345
+ });
4346
+ } else {
4347
+ this._readContext(
4348
+ {
4349
+ path,
4350
+ fromImmutablePath: () =>
4351
+ /** @type {ContextTimestampAndHash | Omit<ContextTimestampAndHash, "safeTime"> | string | null} */ (
4352
+ null
4353
+ ),
4354
+ fromManagedItem: (info) => ({
4355
+ safeTime: 0,
4356
+ timestampHash: info,
4357
+ hash: info || ""
4358
+ }),
4359
+ fromSymlink: (file, target, callback) => {
4360
+ callback(null, {
4361
+ timestampHash: target,
4362
+ hash: target,
4363
+ symlinks: new Set([target])
4364
+ });
4365
+ },
4366
+ fromFile: (file, stat, callback) => {
4367
+ this._getFileTimestampAndHash(file, callback);
4368
+ },
4369
+ fromDirectory: (directory, stat, callback) => {
4370
+ this.contextTshQueue.increaseParallelism();
4371
+ this.contextTshQueue.add(directory, (err, result) => {
4372
+ this.contextTshQueue.decreaseParallelism();
4373
+ callback(err, result);
4374
+ });
4375
+ },
4376
+ /**
4377
+ * Returns tsh.
4378
+ * @param {string[]} files files
4379
+ * @param {(Partial<TimestampAndHash> & Partial<ContextTimestampAndHash> | string | null)[]} results results
4380
+ * @returns {ContextTimestampAndHash} tsh
4381
+ */
4382
+ reduce: (files, results) => {
4383
+ /** @type {undefined | Symlinks} */
4384
+ let symlinks;
4385
+
4386
+ const tsHash = createHash(this._hashFunction);
4387
+ const hash = createHash(this._hashFunction);
4388
+
4389
+ for (const file of files) {
4390
+ tsHash.update(file);
4391
+ hash.update(file);
4392
+ }
4393
+ let safeTime = 0;
4394
+ for (const entry of results) {
4395
+ if (!entry) {
4396
+ tsHash.update("n");
4397
+ continue;
4398
+ }
4399
+ if (typeof entry === "string") {
4400
+ tsHash.update("n");
4401
+ hash.update(entry);
4402
+ continue;
4403
+ }
4404
+ if (entry.timestamp) {
4405
+ tsHash.update("f");
4406
+ tsHash.update(`${entry.timestamp}`);
4407
+ } else if (entry.timestampHash) {
4408
+ tsHash.update("d");
4409
+ tsHash.update(`${entry.timestampHash}`);
4410
+ }
4411
+ if (entry.symlinks !== undefined) {
4412
+ if (symlinks === undefined) symlinks = new Set();
4413
+ addAll(entry.symlinks, symlinks);
4414
+ }
4415
+ if (entry.safeTime) {
4416
+ safeTime = Math.max(safeTime, entry.safeTime);
4417
+ }
4418
+ hash.update(/** @type {string} */ (entry.hash));
4419
+ }
4420
+
4421
+ /** @type {ContextTimestampAndHash} */
4422
+ const result = {
4423
+ safeTime,
4424
+ timestampHash: tsHash.digest("hex"),
4425
+ hash: hash.digest("hex")
4426
+ };
4427
+ if (symlinks) result.symlinks = symlinks;
4428
+ return result;
4429
+ }
4430
+ },
4431
+ (err, _result) => {
4432
+ if (err) return callback(/** @type {WebpackError} */ (err));
4433
+ const result = /** @type {ContextTimestampAndHash} */ (_result);
4434
+ this._contextTshs.set(path, result);
4435
+ return callback(null, result);
4436
+ }
4437
+ );
4438
+ }
4439
+ }
4440
+
4441
+ /**
4442
+ * Resolve context tsh.
4443
+ * @private
4444
+ * @param {ContextTimestampAndHash} entry entry
4445
+ * @param {ProcessorCallback<ResolvedContextTimestampAndHash>} callback callback
4446
+ * @returns {void}
4447
+ */
4448
+ _resolveContextTsh(entry, callback) {
4449
+ /** @type {string[]} */
4450
+ const hashes = [];
4451
+ /** @type {string[]} */
4452
+ const tsHashes = [];
4453
+ let safeTime = 0;
4454
+ // Skip already-visited symlink targets so cyclic pnpm/peer-variant graphs terminate (#21084).
4455
+ const seen = new Set(entry.symlinks);
4456
+ processAsyncTree(
4457
+ /** @type {NonNullable<ContextHash["symlinks"]>} */ (entry.symlinks),
4458
+ 10,
4459
+ (target, push, callback) => {
4460
+ this._getUnresolvedContextTsh(target, (err, entry) => {
4461
+ if (err) return callback(err);
4462
+ if (entry) {
4463
+ hashes.push(entry.hash);
4464
+ if (entry.timestampHash) tsHashes.push(entry.timestampHash);
4465
+ if (entry.safeTime) {
4466
+ safeTime = Math.max(safeTime, entry.safeTime);
4467
+ }
4468
+ if (entry.symlinks !== undefined) {
4469
+ for (const target of entry.symlinks) {
4470
+ if (!seen.has(target)) {
4471
+ seen.add(target);
4472
+ push(target);
4473
+ }
4474
+ }
4475
+ }
4476
+ }
4477
+ callback();
4478
+ });
4479
+ },
4480
+ (err) => {
4481
+ if (err) return callback(/** @type {WebpackError} */ (err));
4482
+ const hash = createHash(this._hashFunction);
4483
+ const tsHash = createHash(this._hashFunction);
4484
+ hash.update(entry.hash);
4485
+ if (entry.timestampHash) tsHash.update(entry.timestampHash);
4486
+ if (entry.safeTime) {
4487
+ safeTime = Math.max(safeTime, entry.safeTime);
4488
+ }
4489
+ hashes.sort();
4490
+ for (const h of hashes) {
4491
+ hash.update(h);
4492
+ }
4493
+ tsHashes.sort();
4494
+ for (const h of tsHashes) {
4495
+ tsHash.update(h);
4496
+ }
4497
+ callback(
4498
+ null,
4499
+ (entry.resolved = {
4500
+ safeTime,
4501
+ timestampHash: tsHash.digest("hex"),
4502
+ hash: hash.digest("hex")
4503
+ })
4504
+ );
4505
+ }
4506
+ );
4507
+ }
4508
+
4509
+ /**
4510
+ * @private
4511
+ * @type {Processor<string, Set<string>>}
4512
+ */
4513
+ _getManagedItemDirectoryInfo(path, callback) {
4514
+ this.fs.readdir(path, (err, elements) => {
4515
+ if (err) {
4516
+ if (err.code === "ENOENT" || err.code === "ENOTDIR") {
4517
+ return callback(null, EMPTY_SET);
4518
+ }
4519
+ return callback(/** @type {WebpackError} */ (err));
4520
+ }
4521
+ const set = new Set(
4522
+ /** @type {string[]} */
4523
+ (elements).map((element) => join(this.fs, path, element))
4524
+ );
4525
+ callback(null, set);
4526
+ });
4527
+ }
4528
+
4529
+ /**
4530
+ * @private
4531
+ * @type {Processor<string, string>}
4532
+ */
4533
+ _getManagedItemInfo(path, callback) {
4534
+ const dir = dirname(this.fs, path);
4535
+ this.managedItemDirectoryQueue.add(dir, (err, elements) => {
4536
+ if (err) {
4537
+ return callback(err);
4538
+ }
4539
+ if (!(/** @type {Set<string>} */ (elements).has(path))) {
4540
+ // file or directory doesn't exist
4541
+ this._managedItems.set(path, "*missing");
4542
+ return callback(null, "*missing");
4543
+ }
4544
+ // something exists
4545
+ // it may be a file or directory
4546
+ if (
4547
+ path.endsWith("node_modules") &&
4548
+ (path.endsWith("/node_modules") || path.endsWith("\\node_modules"))
4549
+ ) {
4550
+ // we are only interested in existence of this special directory
4551
+ this._managedItems.set(path, "*node_modules");
4552
+ return callback(null, "*node_modules");
4553
+ }
4554
+
4555
+ // we assume it's a directory, as files shouldn't occur in managed paths
4556
+ const packageJsonPath = join(this.fs, path, "package.json");
4557
+ this.fs.readFile(packageJsonPath, (err, content) => {
4558
+ if (err) {
4559
+ if (err.code === "ENOENT" || err.code === "ENOTDIR") {
4560
+ // no package.json or path is not a directory
4561
+ this.fs.readdir(path, (err, elements) => {
4562
+ if (
4563
+ !err &&
4564
+ /** @type {string[]} */ (elements).length === 1 &&
4565
+ /** @type {string[]} */ (elements)[0] === "node_modules"
4566
+ ) {
4567
+ // This is only a grouping folder e.g. used by yarn
4568
+ // we are only interested in existence of this special directory
4569
+ this._managedItems.set(path, "*nested");
4570
+ return callback(null, "*nested");
4571
+ }
4572
+ /** @type {Logger} */
4573
+ (this.logger).warn(
4574
+ `Managed item ${path} isn't a directory or doesn't contain a package.json (see snapshot.managedPaths option)`
4575
+ );
4576
+ return callback();
4577
+ });
4578
+ return;
4579
+ }
4580
+ return callback(/** @type {WebpackError} */ (err));
4581
+ }
4582
+ /** @type {JsonObject} */
4583
+ let data;
4584
+ try {
4585
+ data = JSON.parse(/** @type {Buffer} */ (content).toString("utf8"));
4586
+ } catch (parseErr) {
4587
+ return callback(/** @type {WebpackError} */ (parseErr));
4588
+ }
4589
+ if (!data.name) {
4590
+ /** @type {Logger} */
4591
+ (this.logger).warn(
4592
+ `${packageJsonPath} doesn't contain a "name" property (see snapshot.managedPaths option)`
4593
+ );
4594
+ return callback();
4595
+ }
4596
+ const info = `${data.name || ""}@${data.version || ""}`;
4597
+ this._managedItems.set(path, info);
4598
+ callback(null, info);
4599
+ });
4600
+ });
4601
+ }
4602
+
4603
+ getDeprecatedFileTimestamps() {
4604
+ if (this._cachedDeprecatedFileTimestamps !== undefined) {
4605
+ return this._cachedDeprecatedFileTimestamps;
4606
+ }
4607
+ /** @type {Map<string, number | null>} */
4608
+ const map = new Map();
4609
+ for (const [path, info] of this._fileTimestamps) {
4610
+ if (info) {
4611
+ const safeTime =
4612
+ typeof info === "object"
4613
+ ? /** @type {Partial<FileSystemInfoEntry>} */ (info).safeTime
4614
+ : undefined;
4615
+ map.set(path, safeTime === undefined ? null : safeTime);
4616
+ }
4617
+ }
4618
+ return (this._cachedDeprecatedFileTimestamps = map);
4619
+ }
4620
+
4621
+ getDeprecatedContextTimestamps() {
4622
+ if (this._cachedDeprecatedContextTimestamps !== undefined) {
4623
+ return this._cachedDeprecatedContextTimestamps;
4624
+ }
4625
+ /** @type {Map<string, number | null>} */
4626
+ const map = new Map();
4627
+ for (const [path, info] of this._contextTimestamps) {
4628
+ if (info) {
4629
+ const safeTime =
4630
+ typeof info === "object"
4631
+ ? /** @type {Partial<ContextFileSystemInfoEntry>} */ (info).safeTime
4632
+ : undefined;
4633
+ map.set(path, safeTime === undefined ? null : safeTime);
4634
+ }
4635
+ }
4636
+ return (this._cachedDeprecatedContextTimestamps = map);
4637
+ }
4638
+ }
4639
+
4640
+ FileSystemInfo.Snapshot = Snapshot;
4641
+
4642
+ module.exports = FileSystemInfo;