webpack 5.107.2 → 5.108.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 (357) hide show
  1. package/hot/dev-server.js +2 -0
  2. package/lib/APIPlugin.js +8 -4
  3. package/lib/CacheFacade.js +7 -0
  4. package/lib/Chunk.js +4 -0
  5. package/lib/ChunkGraph.js +30 -9
  6. package/lib/CircularModulesPlugin.js +190 -0
  7. package/lib/CleanPlugin.js +2 -1
  8. package/lib/Compilation.js +396 -65
  9. package/lib/Compiler.js +25 -11
  10. package/lib/ConcatenationScope.js +10 -3
  11. package/lib/ContextExclusionPlugin.js +1 -0
  12. package/lib/ContextModule.js +92 -47
  13. package/lib/ContextReplacementPlugin.js +4 -0
  14. package/lib/DefinePlugin.js +89 -15
  15. package/lib/Dependency.js +111 -7
  16. package/lib/EntryOptionPlugin.js +39 -2
  17. package/lib/EntryPlugin.js +2 -0
  18. package/lib/ExportsInfo.js +314 -73
  19. package/lib/ExternalModule.js +82 -34
  20. package/lib/ExternalModuleFactoryPlugin.js +1 -0
  21. package/lib/ExternalsPlugin.js +1 -0
  22. package/lib/FileSystemInfo.js +173 -23
  23. package/lib/FlagAllModulesAsUsedPlugin.js +1 -5
  24. package/lib/FlagDependencyExportsPlugin.js +23 -0
  25. package/lib/FlagDependencyUsagePlugin.js +87 -5
  26. package/lib/FlagEntryExportAsUsedPlugin.js +2 -0
  27. package/lib/Generator.js +8 -0
  28. package/lib/HotModuleReplacementPlugin.js +65 -28
  29. package/lib/IgnorePlugin.js +1 -0
  30. package/lib/InitFragment.js +5 -0
  31. package/lib/JavascriptMetaInfoPlugin.js +7 -5
  32. package/lib/LazyBarrel.js +361 -0
  33. package/lib/LoaderTargetPlugin.js +1 -0
  34. package/lib/Module.js +21 -42
  35. package/lib/ModuleGraph.js +3 -2
  36. package/lib/ModuleProfile.js +27 -1
  37. package/lib/ModuleTemplate.js +2 -0
  38. package/lib/MultiCompiler.js +2 -0
  39. package/lib/MultiStats.js +1 -0
  40. package/lib/MultiWatching.js +2 -0
  41. package/lib/NodeStuffPlugin.js +22 -17
  42. package/lib/NormalModule.js +142 -80
  43. package/lib/NormalModuleReplacementPlugin.js +2 -0
  44. package/lib/PrefetchPlugin.js +2 -0
  45. package/lib/ProgressPlugin.js +8 -0
  46. package/lib/ProvidePlugin.js +1 -0
  47. package/lib/RawModule.js +20 -16
  48. package/lib/RecordIdsPlugin.js +1 -0
  49. package/lib/RuntimeGlobals.js +5 -0
  50. package/lib/RuntimePlugin.js +58 -26
  51. package/lib/RuntimeTemplate.js +278 -21
  52. package/lib/SelfModuleFactory.js +1 -0
  53. package/lib/SourceMapDevToolPlugin.js +3 -5
  54. package/lib/Stats.js +1 -0
  55. package/lib/Template.js +8 -2
  56. package/lib/TemplatedPathPlugin.js +473 -131
  57. package/lib/WarnCaseSensitiveModulesPlugin.js +1 -0
  58. package/lib/WarnDeprecatedOptionPlugin.js +4 -0
  59. package/lib/WarnNoModeSetPlugin.js +1 -0
  60. package/lib/WatchIgnorePlugin.js +1 -0
  61. package/lib/Watching.js +9 -0
  62. package/lib/WebpackOptionsApply.js +50 -5
  63. package/lib/asset/AssetBytesGenerator.js +11 -3
  64. package/lib/asset/AssetGenerator.js +47 -22
  65. package/lib/asset/AssetModule.js +47 -0
  66. package/lib/asset/AssetModulesPlugin.js +14 -14
  67. package/lib/asset/AssetParser.js +2 -2
  68. package/lib/asset/AssetSourceGenerator.js +8 -0
  69. package/lib/asset/RawDataUrlModule.js +12 -13
  70. package/lib/buildChunkGraph.js +64 -7
  71. package/lib/bun/BunTargetPlugin.js +48 -0
  72. package/lib/cache/AddBuildDependenciesPlugin.js +1 -0
  73. package/lib/cache/AddManagedPathsPlugin.js +3 -0
  74. package/lib/cache/IdleFileCachePlugin.js +4 -0
  75. package/lib/cache/MemoryWithGcCachePlugin.js +1 -0
  76. package/lib/cache/PackFileCacheStrategy.js +1 -0
  77. package/lib/cache/ResolverCachePlugin.js +2 -0
  78. package/lib/cache/mergeEtags.js +2 -0
  79. package/lib/cli.js +109 -19
  80. package/lib/config/browserslistTargetHandler.js +99 -0
  81. package/lib/config/defaults.js +147 -7
  82. package/lib/config/defineConfig.js +31 -0
  83. package/lib/config/normalization.js +5 -0
  84. package/lib/config/target.js +181 -2
  85. package/lib/container/ContainerEntryModule.js +15 -14
  86. package/lib/container/ContainerExposedDependency.js +2 -2
  87. package/lib/container/ContainerReferencePlugin.js +1 -1
  88. package/lib/container/FallbackDependency.js +5 -7
  89. package/lib/container/FallbackModule.js +10 -9
  90. package/lib/container/RemoteModule.js +20 -10
  91. package/lib/container/RemoteRuntimeModule.js +14 -12
  92. package/lib/css/CssGenerator.js +353 -327
  93. package/lib/css/CssInjectStyleRuntimeModule.js +36 -8
  94. package/lib/css/CssLoadingRuntimeModule.js +118 -47
  95. package/lib/css/CssModule.js +52 -23
  96. package/lib/css/CssModulesPlugin.js +107 -124
  97. package/lib/css/CssParser.js +2759 -2205
  98. package/lib/css/syntax.js +2859 -0
  99. package/lib/debug/ProfilingPlugin.js +2 -0
  100. package/lib/deno/DenoTargetPlugin.js +47 -0
  101. package/lib/dependencies/AMDDefineDependency.js +22 -17
  102. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +1 -0
  103. package/lib/dependencies/AMDRequireArrayDependency.js +7 -11
  104. package/lib/dependencies/AMDRequireContextDependency.js +7 -11
  105. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +1 -0
  106. package/lib/dependencies/AMDRequireDependency.js +24 -20
  107. package/lib/dependencies/CachedConstDependency.js +3 -0
  108. package/lib/dependencies/CommonJsDependencyHelpers.js +1 -0
  109. package/lib/dependencies/CommonJsExportRequireDependency.js +79 -31
  110. package/lib/dependencies/CommonJsExportsDependency.js +21 -16
  111. package/lib/dependencies/CommonJsExportsParserPlugin.js +230 -7
  112. package/lib/dependencies/CommonJsFullRequireDependency.js +27 -19
  113. package/lib/dependencies/CommonJsImportsParserPlugin.js +51 -16
  114. package/lib/dependencies/CommonJsPlugin.js +1 -1
  115. package/lib/dependencies/CommonJsRequireContextDependency.js +10 -13
  116. package/lib/dependencies/CommonJsRequireDependency.js +42 -11
  117. package/lib/dependencies/CommonJsSelfReferenceDependency.js +22 -14
  118. package/lib/dependencies/ConstDependency.js +16 -11
  119. package/lib/dependencies/ContextDependency.js +4 -0
  120. package/lib/dependencies/ContextDependencyTemplateAsId.js +1 -1
  121. package/lib/dependencies/ContextElementDependency.js +23 -14
  122. package/lib/dependencies/CreateRequireParserPlugin.js +1 -0
  123. package/lib/dependencies/CreateScriptUrlDependency.js +5 -7
  124. package/lib/dependencies/CriticalDependencyWarning.js +1 -0
  125. package/lib/dependencies/CssIcssExportDependency.js +512 -574
  126. package/lib/dependencies/CssIcssImportDependency.js +9 -9
  127. package/lib/dependencies/CssIcssSymbolDependency.js +22 -15
  128. package/lib/dependencies/CssImportDependency.js +25 -1
  129. package/lib/dependencies/CssUrlDependency.js +23 -14
  130. package/lib/dependencies/DllEntryDependency.js +9 -13
  131. package/lib/dependencies/ExportBindingInitFragment.js +164 -0
  132. package/lib/dependencies/ExportsInfoDependency.js +12 -12
  133. package/lib/dependencies/ExternalModuleDependency.js +8 -5
  134. package/lib/dependencies/ExternalModuleInitFragment.js +7 -5
  135. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +13 -10
  136. package/lib/dependencies/HarmonyAcceptDependency.js +11 -11
  137. package/lib/dependencies/HarmonyAcceptImportDependency.js +1 -0
  138. package/lib/dependencies/HarmonyDetectionParserPlugin.js +47 -22
  139. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +28 -2
  140. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +46 -22
  141. package/lib/dependencies/HarmonyExportExpressionDependency.js +107 -30
  142. package/lib/dependencies/HarmonyExportHeaderDependency.js +7 -9
  143. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +109 -31
  144. package/lib/dependencies/HarmonyExportInitFragment.js +18 -15
  145. package/lib/dependencies/HarmonyExportSpecifierDependency.js +83 -18
  146. package/lib/dependencies/HarmonyExports.js +4 -1
  147. package/lib/dependencies/HarmonyImportDependency.js +24 -0
  148. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +110 -74
  149. package/lib/dependencies/HarmonyImportGuard.js +254 -0
  150. package/lib/dependencies/HarmonyImportSideEffectDependency.js +18 -1
  151. package/lib/dependencies/HarmonyImportSpecifierDependency.js +118 -14
  152. package/lib/dependencies/HarmonyLinkingError.js +1 -0
  153. package/lib/dependencies/HarmonyModulesPlugin.js +1 -0
  154. package/lib/dependencies/{HtmlScriptSrcDependency.js → HtmlEntryDependency.js} +261 -109
  155. package/lib/dependencies/HtmlInlineHtmlDependency.js +107 -0
  156. package/lib/dependencies/HtmlInlineScriptDependency.js +17 -13
  157. package/lib/dependencies/HtmlInlineStyleDependency.js +45 -11
  158. package/lib/dependencies/ImportContextDependency.js +5 -9
  159. package/lib/dependencies/ImportDependency.js +44 -2
  160. package/lib/dependencies/ImportMetaHotAcceptDependency.js +1 -0
  161. package/lib/dependencies/ImportMetaHotDeclineDependency.js +1 -0
  162. package/lib/dependencies/ImportMetaPlugin.js +74 -30
  163. package/lib/dependencies/ImportParserPlugin.js +19 -0
  164. package/lib/dependencies/ImportWeakDependency.js +1 -0
  165. package/lib/dependencies/JsonExportsDependency.js +9 -9
  166. package/lib/dependencies/LoaderImportDependency.js +1 -0
  167. package/lib/dependencies/LocalModule.js +11 -12
  168. package/lib/dependencies/LocalModuleDependency.js +11 -13
  169. package/lib/dependencies/ModuleDecoratorDependency.js +9 -9
  170. package/lib/dependencies/ModuleDependency.js +7 -0
  171. package/lib/dependencies/ModuleHotAcceptDependency.js +1 -0
  172. package/lib/dependencies/ModuleHotDeclineDependency.js +1 -0
  173. package/lib/dependencies/ModuleInitFragmentDependency.js +15 -11
  174. package/lib/dependencies/ProvidedDependency.js +31 -27
  175. package/lib/dependencies/PureExpressionDependency.js +7 -9
  176. package/lib/dependencies/RequireEnsureDependency.js +12 -13
  177. package/lib/dependencies/RequireHeaderDependency.js +3 -4
  178. package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +3 -0
  179. package/lib/dependencies/RequireResolveContextDependency.js +7 -11
  180. package/lib/dependencies/RequireResolveDependency.js +1 -0
  181. package/lib/dependencies/RequireResolveHeaderDependency.js +3 -5
  182. package/lib/dependencies/RuntimeRequirementsDependency.js +6 -7
  183. package/lib/dependencies/StaticExportsDependency.js +10 -10
  184. package/lib/dependencies/SystemPlugin.js +2 -0
  185. package/lib/dependencies/URLContextDependency.js +5 -7
  186. package/lib/dependencies/URLDependency.js +14 -16
  187. package/lib/dependencies/UnsupportedDependency.js +8 -13
  188. package/lib/dependencies/WebAssemblyExportImportedDependency.js +11 -16
  189. package/lib/dependencies/WebAssemblyImportDependency.js +14 -16
  190. package/lib/dependencies/WebpackIsIncludedDependency.js +1 -0
  191. package/lib/dependencies/WorkerDependency.js +19 -8
  192. package/lib/dependencies/WorkerPlugin.js +22 -6
  193. package/lib/dependencies/processExportInfo.js +13 -11
  194. package/lib/dll/DelegatedModule.js +29 -15
  195. package/lib/dll/DelegatedModuleFactoryPlugin.js +1 -0
  196. package/lib/dll/DelegatedPlugin.js +1 -0
  197. package/lib/dll/DllEntryPlugin.js +3 -0
  198. package/lib/dll/DllModule.js +3 -2
  199. package/lib/dll/DllPlugin.js +16 -0
  200. package/lib/dll/DllReferencePlugin.js +3 -0
  201. package/lib/dll/LibManifestPlugin.js +1 -0
  202. package/lib/electron/ElectronTargetPlugin.js +22 -4
  203. package/lib/errors/ConcurrentCompilationError.js +1 -0
  204. package/lib/errors/HookWebpackError.js +11 -13
  205. package/lib/errors/IgnoreErrorModuleFactory.js +1 -0
  206. package/lib/errors/InvalidDependenciesModuleWarning.js +2 -0
  207. package/lib/errors/JSONParseError.js +9 -8
  208. package/lib/errors/ModuleBuildError.js +16 -13
  209. package/lib/errors/ModuleDependencyError.js +8 -1
  210. package/lib/errors/ModuleDependencyWarning.js +8 -1
  211. package/lib/errors/ModuleError.js +5 -11
  212. package/lib/errors/ModuleHashingError.js +4 -0
  213. package/lib/errors/ModuleNotFoundError.js +3 -0
  214. package/lib/errors/ModuleParseError.js +5 -11
  215. package/lib/errors/ModuleRestoreError.js +2 -0
  216. package/lib/errors/ModuleStoreError.js +3 -0
  217. package/lib/errors/ModuleWarning.js +7 -11
  218. package/lib/errors/NodeStuffInWebError.js +1 -0
  219. package/lib/errors/NonErrorEmittedError.js +2 -0
  220. package/lib/errors/UnhandledSchemeError.js +1 -0
  221. package/lib/esm/ModuleChunkLoadingPlugin.js +0 -1
  222. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +28 -23
  223. package/lib/hmr/HotModuleReplacement.runtime.js +175 -30
  224. package/lib/hmr/HotModuleReplacementRuntimeModule.js +7 -0
  225. package/lib/hmr/JavascriptHotModuleReplacement.runtime.js +173 -26
  226. package/lib/hmr/LazyCompilationPlugin.js +30 -6
  227. package/lib/html/HtmlGenerator.js +217 -23
  228. package/lib/html/HtmlModule.js +40 -0
  229. package/lib/html/HtmlModulesPlugin.js +219 -55
  230. package/lib/html/HtmlParser.js +1108 -1099
  231. package/lib/html/{walkHtmlTokens.js → syntax.js} +4701 -212
  232. package/lib/ids/IdHelpers.js +4 -2
  233. package/lib/index.js +19 -0
  234. package/lib/javascript/BasicEvaluatedExpression.js +1 -0
  235. package/lib/javascript/EnableChunkLoadingPlugin.js +1 -0
  236. package/lib/javascript/JavascriptGenerator.js +6 -2
  237. package/lib/javascript/JavascriptModule.js +54 -0
  238. package/lib/javascript/JavascriptModulesPlugin.js +257 -102
  239. package/lib/javascript/JavascriptParser.js +285 -158
  240. package/lib/json/JsonModule.js +40 -0
  241. package/lib/json/JsonModulesPlugin.js +7 -0
  242. package/lib/json/JsonParser.js +4 -2
  243. package/lib/library/AssignLibraryPlugin.js +5 -3
  244. package/lib/library/ExportPropertyLibraryPlugin.js +1 -0
  245. package/lib/library/FalseIIFEUmdWarning.js +1 -0
  246. package/lib/library/ModuleLibraryPlugin.js +24 -5
  247. package/lib/library/SystemLibraryPlugin.js +3 -3
  248. package/lib/node/NodeTargetPlugin.js +1 -0
  249. package/lib/node/NodeWatchFileSystem.js +1 -0
  250. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +10 -9
  251. package/lib/node/RequireChunkLoadingRuntimeModule.js +18 -16
  252. package/lib/optimize/ConcatenatedModule.js +395 -77
  253. package/lib/optimize/ConstExportsPlugin.js +211 -0
  254. package/lib/optimize/InlineExports.js +178 -0
  255. package/lib/optimize/InnerGraph.js +372 -275
  256. package/lib/optimize/InnerGraphPlugin.js +196 -99
  257. package/lib/optimize/ModuleConcatenationPlugin.js +56 -25
  258. package/lib/optimize/RealContentHashPlugin.js +14 -1
  259. package/lib/optimize/SideEffectsFlagPlugin.js +234 -64
  260. package/lib/runtime/AsyncModuleRuntimeModule.js +32 -30
  261. package/lib/runtime/AutoPublicPathRuntimeModule.js +11 -5
  262. package/lib/runtime/CompatGetDefaultExportRuntimeModule.js +1 -1
  263. package/lib/runtime/CreateFakeNamespaceObjectRuntimeModule.js +6 -4
  264. package/lib/runtime/DefinePropertyGettersRuntimeModule.js +33 -4
  265. package/lib/runtime/GetChunkFilenameRuntimeModule.js +82 -3
  266. package/lib/runtime/GetTrustedTypesPolicyRuntimeModule.js +1 -1
  267. package/lib/runtime/HasOwnPropertyRuntimeModule.js +1 -1
  268. package/lib/runtime/LoadScriptRuntimeModule.js +18 -13
  269. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +39 -26
  270. package/lib/runtime/MakeNamespaceObjectRuntimeModule.js +1 -1
  271. package/lib/runtime/OnChunksLoadedRuntimeModule.js +4 -4
  272. package/lib/runtime/RelativeUrlRuntimeModule.js +3 -2
  273. package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +1 -1
  274. package/lib/runtime/StartupEntrypointRuntimeModule.js +4 -3
  275. package/lib/runtime/WorkerRuntimeModule.js +33 -0
  276. package/lib/schemes/HttpUriPlugin.js +3 -2
  277. package/lib/serialization/AggregateErrorSerializer.js +7 -6
  278. package/lib/serialization/ArraySerializer.js +4 -8
  279. package/lib/serialization/BinaryMiddleware.js +538 -468
  280. package/lib/serialization/DateObjectSerializer.js +2 -2
  281. package/lib/serialization/ErrorObjectSerializer.js +7 -6
  282. package/lib/serialization/MapObjectSerializer.js +5 -9
  283. package/lib/serialization/NullPrototypeObjectSerializer.js +7 -9
  284. package/lib/serialization/ObjectMiddleware.js +50 -13
  285. package/lib/serialization/PlainObjectSerializer.js +9 -8
  286. package/lib/serialization/RegExpObjectSerializer.js +2 -2
  287. package/lib/serialization/Serializer.js +1 -0
  288. package/lib/serialization/SetObjectSerializer.js +4 -8
  289. package/lib/sharing/ConsumeSharedModule.js +6 -7
  290. package/lib/sharing/ConsumeSharedPlugin.js +1 -0
  291. package/lib/sharing/ConsumeSharedRuntimeModule.js +46 -41
  292. package/lib/sharing/ProvideSharedDependency.js +30 -15
  293. package/lib/sharing/ProvideSharedModule.js +30 -11
  294. package/lib/sharing/ProvideSharedPlugin.js +4 -2
  295. package/lib/sharing/SharePlugin.js +3 -0
  296. package/lib/sharing/ShareRuntimeModule.js +18 -16
  297. package/lib/sharing/resolveMatchedConfigs.js +2 -1
  298. package/lib/sharing/utils.js +1 -1
  299. package/lib/stats/DefaultStatsFactoryPlugin.js +4 -6
  300. package/lib/stats/DefaultStatsPrinterPlugin.js +14 -14
  301. package/lib/stats/StatsFactory.js +11 -9
  302. package/lib/stats/StatsPrinter.js +9 -2
  303. package/lib/url/URLParserPlugin.js +5 -2
  304. package/lib/util/AsyncQueue.js +10 -0
  305. package/lib/util/LazyBucketSortedSet.js +5 -0
  306. package/lib/util/LazySet.js +6 -4
  307. package/lib/util/LocConverter.js +11 -1
  308. package/lib/util/Semaphore.js +1 -0
  309. package/lib/util/SourceProcessor.js +106 -0
  310. package/lib/util/TupleSet.js +1 -0
  311. package/lib/util/WeakTupleMap.js +27 -1
  312. package/lib/util/chainedImports.js +3 -3
  313. package/lib/util/comparators.js +2 -2
  314. package/lib/util/concatenate.js +31 -7
  315. package/lib/util/createHash.js +0 -1
  316. package/lib/util/deterministicGrouping.js +19 -12
  317. package/lib/util/extractSourceMap.js +1 -1
  318. package/lib/util/findGraphRoots.js +2 -0
  319. package/lib/util/fs.js +10 -5
  320. package/lib/util/hash/DebugHash.js +1 -0
  321. package/lib/util/hash/hash-digest.js +24 -15
  322. package/lib/util/identifier.js +7 -0
  323. package/lib/util/internalSerializables.js +11 -2
  324. package/lib/util/magicComment.js +42 -0
  325. package/lib/util/makeSerializable.js +1 -0
  326. package/lib/util/nonNumericOnlyHash.js +30 -1
  327. package/lib/util/property.js +7 -1
  328. package/lib/util/publicPathPlaceholder.js +64 -0
  329. package/lib/util/registerExternalSerializer.js +4 -4
  330. package/lib/wasm-async/AsyncWasmModule.js +77 -0
  331. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +1 -1
  332. package/lib/wasm-async/AsyncWebAssemblyModulesPlugin.js +1 -96
  333. package/lib/wasm-async/AsyncWebAssemblyParser.js +1 -1
  334. package/lib/wasm-async/UniversalCompileAsyncWasmPlugin.js +1 -1
  335. package/lib/wasm-sync/SyncWasmModule.js +39 -0
  336. package/lib/wasm-sync/UnsupportedWebAssemblyFeatureError.js +1 -0
  337. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +6 -3
  338. package/lib/wasm-sync/WasmFinalizeExportsPlugin.js +2 -1
  339. package/lib/wasm-sync/WebAssemblyGenerator.js +1 -0
  340. package/lib/wasm-sync/WebAssemblyInInitialChunkError.js +2 -0
  341. package/lib/wasm-sync/WebAssemblyModulesPlugin.js +10 -0
  342. package/lib/wasm-sync/WebAssemblyParser.js +7 -3
  343. package/lib/web/JsonpChunkLoadingRuntimeModule.js +45 -39
  344. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +11 -10
  345. package/package.json +35 -27
  346. package/schemas/WebpackOptions.check.js +1 -1
  347. package/schemas/WebpackOptions.json +212 -3
  348. package/schemas/plugins/HtmlGeneratorOptions.check.js +1 -1
  349. package/schemas/plugins/HtmlParserOptions.check.d.ts +7 -0
  350. package/schemas/plugins/HtmlParserOptions.check.js +6 -0
  351. package/schemas/plugins/HtmlParserOptions.json +3 -0
  352. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +1 -1
  353. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  354. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  355. package/types.d.ts +1456 -290
  356. package/lib/css/walkCssTokens.js +0 -2020
  357. package/lib/util/AppendOnlyStackedSet.js +0 -93
@@ -9,6 +9,10 @@ const { basename, extname } = require("path");
9
9
  const util = require("util");
10
10
  const Chunk = require("./Chunk");
11
11
  const Module = require("./Module");
12
+ const {
13
+ decode: decodeBase,
14
+ encode: encodeBase
15
+ } = require("./util/hash/hash-digest");
12
16
  const { parseResource } = require("./util/identifier");
13
17
  const memoize = require("./util/memoize");
14
18
 
@@ -17,6 +21,7 @@ const getMimeTypes = memoize(() => require("./util/mimeTypes"));
17
21
  /** @typedef {import("./ChunkGraph")} ChunkGraph */
18
22
  /** @typedef {import("./ChunkGraph").ModuleId} ModuleId */
19
23
  /** @typedef {import("./Compilation").AssetInfo} AssetInfo */
24
+ /** @typedef {import("./Compilation").HashWithDigestFunction} HashWithDigestFunction */
20
25
  /** @typedef {import("./Compilation").PathData} PathData */
21
26
  /** @typedef {import("./Compilation").PathDataChunk} PathDataChunk */
22
27
  /** @typedef {import("./Compilation").PathDataModule} PathDataModule */
@@ -24,6 +29,46 @@ const getMimeTypes = memoize(() => require("./util/mimeTypes"));
24
29
 
25
30
  const REGEXP = /\[\\*([\w:]+)\\*\]/g;
26
31
 
32
+ /**
33
+ * Placeholder kinds present in a template string, cached so the scan is not
34
+ * repeated for reused templates (e.g. `output.filename`, `localIdentName`).
35
+ * Bounded so dynamic (function-built) paths can't grow it without limit.
36
+ * @type {Map<string, Set<string>>}
37
+ */
38
+ const presentKindsCache = new Map();
39
+ const PRESENT_KINDS_CACHE_MAX = 1000;
40
+
41
+ /**
42
+ * Returns the placeholder kinds (`[kind]` / `[kind:arg]`) a template references,
43
+ * matching the replace pass below so guarding replacer construction by it stays
44
+ * output-identical.
45
+ * @param {string} path template string (already known to contain `[`)
46
+ * @returns {Set<string>} placeholder kinds present
47
+ */
48
+ const getPresentKinds = (path) => {
49
+ const cached = presentKindsCache.get(path);
50
+ if (cached !== undefined) return cached;
51
+ /** @type {Set<string>} */
52
+ const kinds = new Set();
53
+ // `RegExp.exec` loop rather than `String.matchAll` (Node.js 12+) so this
54
+ // stays compatible with the supported Node.js 10 range.
55
+ REGEXP.lastIndex = 0;
56
+ /** @type {RegExpExecArray | null} */
57
+ let m;
58
+ while ((m = REGEXP.exec(path)) !== null) {
59
+ const content = /** @type {string} */ (m[1]);
60
+ if (content.length + 2 === m[0].length) {
61
+ const cm = /^(\w+)(?::\w+)?(?::\w+)?$/.exec(content);
62
+ if (cm) kinds.add(cm[1]);
63
+ }
64
+ }
65
+ if (presentKindsCache.size >= PRESENT_KINDS_CACHE_MAX) {
66
+ presentKindsCache.clear();
67
+ }
68
+ presentKindsCache.set(path, kinds);
69
+ return kinds;
70
+ };
71
+
27
72
  /** @type {PathData["prepareId"]} */
28
73
  const prepareId = (id) => {
29
74
  if (typeof id !== "string") return id;
@@ -47,22 +92,143 @@ const prepareId = (id) => {
47
92
  * @param {string} input
48
93
  */
49
94
 
95
+ /** @typedef {"26" | "32" | "36" | "49" | "52" | "58" | "62"} Base */
96
+
97
+ // `[<digest>]` placeholders may request a digest webpack does not store the
98
+ // hash in; loader-utils calls the URL-safe base64 `base64safe`.
99
+ const BASE_DIGEST = /^base(\d+)$/;
100
+ const SUPPORTED_BASES = new Set(["26", "32", "36", "49", "52", "58", "62"]);
101
+
102
+ // Node < 14.18 lacks the `base64url` Buffer encoding; fall back to base64 + swap.
103
+ let isBase64UrlSupported = false;
104
+ try {
105
+ isBase64UrlSupported = Boolean(Buffer.from("", "base64url"));
106
+ } catch (_err) {
107
+ // Nothing
108
+ }
109
+
110
+ /**
111
+ * @param {string} digest digest name from a `[<hash>:<digest>]` placeholder
112
+ * @returns {boolean} whether a hash can be re-encoded into this digest
113
+ */
114
+ const isSupportedDigest = (digest) => {
115
+ if (digest === "base64url" || digest === "base64safe") return true;
116
+ const base = BASE_DIGEST.exec(digest);
117
+ if (base) return base[1] === "64" || SUPPORTED_BASES.has(base[1]);
118
+ return Buffer.isEncoding(digest);
119
+ };
120
+
121
+ /**
122
+ * Decodes an already-digested hash string back into its raw bytes.
123
+ * @param {string} value digested hash
124
+ * @param {string} digest digest the value is encoded in
125
+ * @returns {Buffer} raw bytes
126
+ */
127
+ const digestToBuffer = (value, digest) => {
128
+ const base = BASE_DIGEST.exec(digest);
129
+ if (base && Number(base[1]) !== 64) {
130
+ return decodeBase(value, /** @type {Base} */ (base[1]));
131
+ }
132
+ if (
133
+ (digest === "base64url" || digest === "base64safe") &&
134
+ !isBase64UrlSupported
135
+ ) {
136
+ return Buffer.from(value.replace(/-/g, "+").replace(/_/g, "/"), "base64");
137
+ }
138
+ return Buffer.from(
139
+ value,
140
+ /** @type {BufferEncoding} */ (
141
+ digest === "base64safe" ? "base64url" : digest
142
+ )
143
+ );
144
+ };
145
+
146
+ /**
147
+ * Encodes raw bytes into the requested digest.
148
+ * @param {Buffer} buffer raw bytes
149
+ * @param {string} digest target digest
150
+ * @returns {string} encoded hash
151
+ */
152
+ const bufferToDigest = (buffer, digest) => {
153
+ const base = BASE_DIGEST.exec(digest);
154
+ if (base && Number(base[1]) !== 64) {
155
+ return encodeBase(buffer, /** @type {Base} */ (base[1]));
156
+ }
157
+ if (
158
+ (digest === "base64url" || digest === "base64safe") &&
159
+ !isBase64UrlSupported
160
+ ) {
161
+ return buffer
162
+ .toString("base64")
163
+ .replace(/\+/g, "-")
164
+ .replace(/\//g, "_")
165
+ .replace(/[=]+$/, "");
166
+ }
167
+ return buffer.toString(
168
+ /** @type {BufferEncoding} */ (
169
+ digest === "base64safe" ? "base64url" : digest
170
+ )
171
+ );
172
+ };
173
+
174
+ /**
175
+ * Re-encodes a digested hash into another digest (e.g. `[contenthash:base64]`).
176
+ * The source is already truncated to `output.hashDigestLength`, so the result is
177
+ * derived from those bytes, not the full content. Throws on an unknown digest so
178
+ * a typo fails loudly rather than silently keeping the original encoding.
179
+ * @param {string} value digested hash
180
+ * @param {string} fromDigest digest the value is encoded in
181
+ * @param {string} toDigest requested digest
182
+ * @returns {string} re-encoded hash
183
+ */
184
+ const reEncodeDigest = (value, fromDigest, toDigest) => {
185
+ if (toDigest === fromDigest) return value;
186
+ if (!isSupportedDigest(toDigest)) {
187
+ throw new Error(
188
+ `Unsupported hash digest "${toDigest}" in path template (use hex, base64, base64url, or base26/32/36/49/52/58/62)`
189
+ );
190
+ }
191
+ return bufferToDigest(digestToBuffer(value, fromDigest), toDigest);
192
+ };
193
+
50
194
  /**
51
195
  * Returns hash replacer function.
52
196
  * @param {ReplacerFunction} replacer replacer
53
197
  * @param {((arg0: number) => string) | undefined} handler handler
54
198
  * @param {AssetInfo | undefined} assetInfo asset info
55
199
  * @param {string} hashName hash name
200
+ * @param {string} sourceDigest digest the stored hash is encoded in
201
+ * @param {string=} fullValue untruncated hash, re-encoded for `[<hash>:<digest>]` so the result carries full entropy instead of the `hashDigestLength`-truncated value
202
+ * @param {boolean=} recordDigest record the inline digest on `assetInfo.contenthashDigest` so `RealContentHashPlugin` re-encodes the recomputed hash in it
203
+ * @param {HashWithDigestFunction=} digestHandler builds the value for `[<hash>:<digest>]` in a per-chunk runtime context (the runtime chunk-filename map), where a single re-encode of the whole expression is impossible
56
204
  * @returns {Replacer} hash replacer function
57
205
  */
58
- const hashLength = (replacer, handler, assetInfo, hashName) => {
206
+ const hashLength = (
207
+ replacer,
208
+ handler,
209
+ assetInfo,
210
+ hashName,
211
+ sourceDigest,
212
+ fullValue,
213
+ recordDigest,
214
+ digestHandler
215
+ ) => {
59
216
  /** @type {Replacer} */
60
- const fn = (match, arg, input) => {
217
+ const fn = (match, arg, input, digest) => {
61
218
  /** @type {string} */
62
219
  let result;
63
220
  const length = arg && Number.parseInt(arg, 10);
64
221
 
65
- if (length && handler) {
222
+ if (digest && digestHandler) {
223
+ result = digestHandler(digest, length || undefined);
224
+ } else if (digest) {
225
+ const hash = reEncodeDigest(
226
+ fullValue !== undefined ? fullValue : replacer(match, arg, input),
227
+ sourceDigest,
228
+ digest
229
+ );
230
+ result = length ? hash.slice(0, length) : hash;
231
+ } else if (length && handler) {
66
232
  result = handler(length);
67
233
  } else {
68
234
  const hash = replacer(match, arg, input);
@@ -71,6 +237,12 @@ const hashLength = (replacer, handler, assetInfo, hashName) => {
71
237
  }
72
238
  if (assetInfo) {
73
239
  assetInfo.immutable = true;
240
+ if (digest && recordDigest) {
241
+ // `base64safe` is encoded as `base64url`; record what the value is in.
242
+ (assetInfo.contenthashDigest || (assetInfo.contenthashDigest = {}))[
243
+ result
244
+ ] = digest === "base64safe" ? "base64url" : digest;
245
+ }
74
246
  if (Array.isArray(assetInfo[hashName])) {
75
247
  assetInfo[hashName] = [...assetInfo[hashName], result];
76
248
  } else if (assetInfo[hashName]) {
@@ -85,7 +257,7 @@ const hashLength = (replacer, handler, assetInfo, hashName) => {
85
257
  return fn;
86
258
  };
87
259
 
88
- /** @typedef {(match: string, arg: string | undefined, input: string) => string} Replacer */
260
+ /** @typedef {(match: string, arg: string | undefined, input: string, digest?: string) => string} Replacer */
89
261
 
90
262
  /**
91
263
  * Returns replacer.
@@ -167,7 +339,27 @@ const deprecated = (fn, message, code) => {
167
339
  * @returns {string} the interpolated path
168
340
  */
169
341
  const interpolate = (path, data, assetInfo) => {
342
+ if (typeof path === "function") {
343
+ path = path(data, assetInfo);
344
+ }
345
+
346
+ // Literal paths carry no `[placeholder]`, so the whole replacement table
347
+ // and regex pass are pure overhead — building replacers has no side effects
348
+ // (those only fire when a replacer is invoked), so the output is identical.
349
+ if (!path.includes("[")) {
350
+ return path;
351
+ }
352
+
353
+ // Only build replacers for placeholders the template actually uses — most
354
+ // templates reference a handful, so building the whole table per call is
355
+ // wasted work. Replacer construction has no side effects (those fire only
356
+ // when a replacer is invoked, which happens for present kinds), so this is
357
+ // output-identical.
358
+ const presentKinds = getPresentKinds(path);
359
+
170
360
  const chunkGraph = data.chunkGraph;
361
+ // Digest the stored hashes are encoded in, so `[hash:<digest>]` can re-encode.
362
+ const sourceDigest = data.hashDigest || "hex";
171
363
 
172
364
  /** @type {Map<string, Replacer>} */
173
365
  const replacements = new Map();
@@ -184,7 +376,17 @@ const interpolate = (path, data, assetInfo) => {
184
376
  // [path] - /some/path/
185
377
  // [name] - file
186
378
  // [ext] - .js
187
- if (typeof data.filename === "string") {
379
+ if (
380
+ typeof data.filename === "string" &&
381
+ (presentKinds.has("file") ||
382
+ presentKinds.has("query") ||
383
+ presentKinds.has("fragment") ||
384
+ presentKinds.has("path") ||
385
+ presentKinds.has("base") ||
386
+ presentKinds.has("name") ||
387
+ presentKinds.has("ext") ||
388
+ presentKinds.has("filebase"))
389
+ ) {
188
390
  // check that filename is data uri
189
391
  const match = data.filename.match(/^data:([^;,]+)/);
190
392
  if (match) {
@@ -197,22 +399,28 @@ const interpolate = (path, data, assetInfo) => {
197
399
  : false;
198
400
  const baseReplacer = contentHash ? replacer(contentHash) : emptyReplacer;
199
401
 
200
- replacements.set("file", emptyReplacer);
201
- replacements.set("query", emptyReplacer);
202
- replacements.set("fragment", emptyReplacer);
203
- replacements.set("path", emptyReplacer);
204
- replacements.set("base", baseReplacer);
205
- replacements.set("name", baseReplacer);
206
- replacements.set("ext", replacer(ext ? `.${ext}` : "", true));
402
+ if (presentKinds.has("file")) replacements.set("file", emptyReplacer);
403
+ if (presentKinds.has("query")) replacements.set("query", emptyReplacer);
404
+ if (presentKinds.has("fragment")) {
405
+ replacements.set("fragment", emptyReplacer);
406
+ }
407
+ if (presentKinds.has("path")) replacements.set("path", emptyReplacer);
408
+ if (presentKinds.has("base")) replacements.set("base", baseReplacer);
409
+ if (presentKinds.has("name")) replacements.set("name", baseReplacer);
410
+ if (presentKinds.has("ext")) {
411
+ replacements.set("ext", replacer(ext ? `.${ext}` : "", true));
412
+ }
207
413
  // Legacy
208
- replacements.set(
209
- "filebase",
210
- deprecated(
211
- baseReplacer,
212
- "[filebase] is now [base]",
213
- "DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_FILENAME"
214
- )
215
- );
414
+ if (presentKinds.has("filebase")) {
415
+ replacements.set(
416
+ "filebase",
417
+ deprecated(
418
+ baseReplacer,
419
+ "[filebase] is now [base]",
420
+ "DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_FILENAME"
421
+ )
422
+ );
423
+ }
216
424
  } else {
217
425
  const { path: file, query, fragment } = parseResource(data.filename);
218
426
 
@@ -221,22 +429,30 @@ const interpolate = (path, data, assetInfo) => {
221
429
  const name = base.slice(0, base.length - ext.length);
222
430
  const path = file.slice(0, file.length - base.length);
223
431
 
224
- replacements.set("file", replacer(file));
225
- replacements.set("query", replacer(query, true));
226
- replacements.set("fragment", replacer(fragment, true));
227
- replacements.set("path", replacer(path, true));
228
- replacements.set("base", replacer(base));
229
- replacements.set("name", replacer(name));
230
- replacements.set("ext", replacer(ext, true));
432
+ if (presentKinds.has("file")) replacements.set("file", replacer(file));
433
+ if (presentKinds.has("query")) {
434
+ replacements.set("query", replacer(query, true));
435
+ }
436
+ if (presentKinds.has("fragment")) {
437
+ replacements.set("fragment", replacer(fragment, true));
438
+ }
439
+ if (presentKinds.has("path")) {
440
+ replacements.set("path", replacer(path, true));
441
+ }
442
+ if (presentKinds.has("base")) replacements.set("base", replacer(base));
443
+ if (presentKinds.has("name")) replacements.set("name", replacer(name));
444
+ if (presentKinds.has("ext")) replacements.set("ext", replacer(ext, true));
231
445
  // Legacy
232
- replacements.set(
233
- "filebase",
234
- deprecated(
235
- replacer(base),
236
- "[filebase] is now [base]",
237
- "DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_FILENAME"
238
- )
239
- );
446
+ if (presentKinds.has("filebase")) {
447
+ replacements.set(
448
+ "filebase",
449
+ deprecated(
450
+ replacer(base),
451
+ "[filebase] is now [base]",
452
+ "DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_FILENAME"
453
+ )
454
+ );
455
+ }
240
456
  }
241
457
  }
242
458
 
@@ -249,25 +465,35 @@ const interpolate = (path, data, assetInfo) => {
249
465
  // Legacy Placeholders
250
466
  //
251
467
  // [hash] - data.hash (3a4b5c6e7f)
252
- if (data.hash) {
468
+ if (data.hash && (presentKinds.has("fullhash") || presentKinds.has("hash"))) {
253
469
  const hashReplacer = hashLength(
254
470
  replacer(data.hash),
255
471
  data.hashWithLength,
256
472
  assetInfo,
257
- "fullhash"
473
+ "fullhash",
474
+ data.fullHashDigest || sourceDigest,
475
+ data.fullHash,
476
+ undefined,
477
+ data.hashWithDigest
258
478
  );
259
479
 
260
- replacements.set("fullhash", hashReplacer);
480
+ if (presentKinds.has("fullhash")) {
481
+ replacements.set("fullhash", hashReplacer);
482
+ }
261
483
 
262
- // Legacy
263
- replacements.set(
264
- "hash",
265
- deprecated(
266
- hashReplacer,
267
- "[hash] is now [fullhash] (also consider using [chunkhash] or [contenthash], see documentation for details)",
268
- "DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_HASH"
269
- )
270
- );
484
+ // Legacy — but a css-loader-style `[hash]` local ident is not deprecated
485
+ if (presentKinds.has("hash")) {
486
+ replacements.set(
487
+ "hash",
488
+ data.hashAsFullHash
489
+ ? hashReplacer
490
+ : deprecated(
491
+ hashReplacer,
492
+ "[hash] is now [fullhash] (also consider using [chunkhash] or [contenthash], see documentation for details)",
493
+ "DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_HASH"
494
+ )
495
+ );
496
+ }
271
497
  }
272
498
 
273
499
  // Chunk Context
@@ -283,33 +509,55 @@ const interpolate = (path, data, assetInfo) => {
283
509
 
284
510
  const contentHashType = data.contentHashType;
285
511
 
286
- const idReplacer = replacer(chunk.id);
287
- const nameReplacer = replacer(chunk.name || chunk.id);
288
- const chunkhashReplacer = hashLength(
289
- replacer(chunk instanceof Chunk ? chunk.renderedHash : chunk.hash),
290
- "hashWithLength" in chunk ? chunk.hashWithLength : undefined,
291
- assetInfo,
292
- "chunkhash"
293
- );
294
- const contenthashReplacer = hashLength(
295
- replacer(
296
- data.contentHash ||
297
- (contentHashType &&
298
- chunk.contentHash &&
299
- chunk.contentHash[contentHashType])
300
- ),
301
- data.contentHashWithLength ||
302
- ("contentHashWithLength" in chunk && chunk.contentHashWithLength
303
- ? chunk.contentHashWithLength[/** @type {string} */ (contentHashType)]
304
- : undefined),
305
- assetInfo,
306
- "contenthash"
307
- );
308
-
309
- replacements.set("id", idReplacer);
310
- replacements.set("name", nameReplacer);
311
- replacements.set("chunkhash", chunkhashReplacer);
312
- replacements.set("contenthash", contenthashReplacer);
512
+ if (presentKinds.has("id")) replacements.set("id", replacer(chunk.id));
513
+ if (presentKinds.has("name")) {
514
+ replacements.set("name", replacer(chunk.name || chunk.id));
515
+ }
516
+ if (presentKinds.has("chunkhash")) {
517
+ replacements.set(
518
+ "chunkhash",
519
+ hashLength(
520
+ replacer(chunk instanceof Chunk ? chunk.renderedHash : chunk.hash),
521
+ "hashWithLength" in chunk ? chunk.hashWithLength : undefined,
522
+ assetInfo,
523
+ "chunkhash",
524
+ sourceDigest,
525
+ chunk.hash,
526
+ undefined,
527
+ "hashWithDigest" in chunk ? chunk.hashWithDigest : undefined
528
+ )
529
+ );
530
+ }
531
+ if (presentKinds.has("contenthash")) {
532
+ const ct = /** @type {string} */ (contentHashType);
533
+ replacements.set(
534
+ "contenthash",
535
+ hashLength(
536
+ replacer(
537
+ data.contentHash ||
538
+ (contentHashType &&
539
+ chunk.contentHash &&
540
+ chunk.contentHash[contentHashType])
541
+ ),
542
+ data.contentHashWithLength ||
543
+ ("contentHashWithLength" in chunk && chunk.contentHashWithLength
544
+ ? chunk.contentHashWithLength[ct]
545
+ : undefined),
546
+ assetInfo,
547
+ "contenthash",
548
+ sourceDigest,
549
+ // full content digest, so a static `[contenthash:<digest>]` re-encodes
550
+ // from full entropy (the runtime path uses `contentHashWithDigest`)
551
+ "contentHashFull" in chunk && chunk.contentHashFull
552
+ ? chunk.contentHashFull[ct]
553
+ : undefined,
554
+ data.realContentHash,
555
+ "contentHashWithDigest" in chunk && chunk.contentHashWithDigest
556
+ ? chunk.contentHashWithDigest[ct]
557
+ : undefined
558
+ )
559
+ );
560
+ }
313
561
  }
314
562
 
315
563
  // Module Context
@@ -325,78 +573,149 @@ const interpolate = (path, data, assetInfo) => {
325
573
  // [modulehash] - module.hash (6237543873.png)
326
574
  if (data.module) {
327
575
  const module = data.module;
576
+ const needId = presentKinds.has("id");
577
+ const needModuleId = presentKinds.has("moduleid");
578
+ // `data.hashAsFullHash` keeps `[hash]` as the `[fullhash]` alias (CSS local
579
+ // idents) instead of repurposing it to the module hash; `[modulehash]` stays.
580
+ const needHash = presentKinds.has("hash") && !data.hashAsFullHash;
581
+
582
+ if (needId || needModuleId) {
583
+ const idReplacer = replacer(() =>
584
+ (data.prepareId || prepareId)(
585
+ module instanceof Module
586
+ ? /** @type {ModuleId} */
587
+ (/** @type {ChunkGraph} */ (chunkGraph).getModuleId(module))
588
+ : module.id
589
+ )
590
+ );
591
+ if (needId) replacements.set("id", idReplacer);
592
+ // Legacy
593
+ if (needModuleId) {
594
+ replacements.set(
595
+ "moduleid",
596
+ deprecated(
597
+ idReplacer,
598
+ "[moduleid] is now [id]",
599
+ "DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_MODULE_ID"
600
+ )
601
+ );
602
+ }
603
+ }
328
604
 
329
- const idReplacer = replacer(() =>
330
- (data.prepareId || prepareId)(
605
+ // `[hash]` aliases module content hash when present, else module hash.
606
+ const wantModuleHash =
607
+ presentKinds.has("modulehash") || (needHash && !data.contentHash);
608
+ const wantContentHash =
609
+ presentKinds.has("contenthash") || (needHash && data.contentHash);
610
+ /** @type {Replacer | undefined} */
611
+ let moduleHashReplacer;
612
+ /** @type {Replacer | undefined} */
613
+ let contentHashReplacer;
614
+ if (wantModuleHash) {
615
+ moduleHashReplacer = hashLength(
616
+ replacer(() =>
617
+ module instanceof Module
618
+ ? /** @type {ChunkGraph} */
619
+ (chunkGraph).getRenderedModuleHash(module, data.runtime)
620
+ : module.hash
621
+ ),
622
+ "hashWithLength" in module ? module.hashWithLength : undefined,
623
+ assetInfo,
624
+ "modulehash",
625
+ sourceDigest,
626
+ // `getModuleHash` is the untruncated digest (`getRenderedModuleHash` is
627
+ // the truncated one), so `[modulehash:<digest>]` re-encodes full entropy
331
628
  module instanceof Module
332
- ? /** @type {ModuleId} */
333
- (/** @type {ChunkGraph} */ (chunkGraph).getModuleId(module))
334
- : module.id
335
- )
336
- );
337
- const moduleHashReplacer = hashLength(
338
- replacer(() =>
339
- module instanceof Module
340
- ? /** @type {ChunkGraph} */
341
- (chunkGraph).getRenderedModuleHash(module, data.runtime)
629
+ ? /** @type {ChunkGraph} */ (chunkGraph).getModuleHash(
630
+ module,
631
+ data.runtime
632
+ )
342
633
  : module.hash
343
- ),
344
- "hashWithLength" in module ? module.hashWithLength : undefined,
345
- assetInfo,
346
- "modulehash"
347
- );
348
- const contentHashReplacer = hashLength(
349
- replacer(/** @type {string} */ (data.contentHash)),
350
- undefined,
351
- assetInfo,
352
- "contenthash"
353
- );
354
-
355
- replacements.set("id", idReplacer);
356
- replacements.set("modulehash", moduleHashReplacer);
357
- replacements.set("contenthash", contentHashReplacer);
358
- replacements.set(
359
- "hash",
360
- data.contentHash ? contentHashReplacer : moduleHashReplacer
361
- );
362
- // Legacy
363
- replacements.set(
364
- "moduleid",
365
- deprecated(
366
- idReplacer,
367
- "[moduleid] is now [id]",
368
- "DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_MODULE_ID"
369
- )
370
- );
634
+ );
635
+ if (presentKinds.has("modulehash")) {
636
+ replacements.set("modulehash", moduleHashReplacer);
637
+ }
638
+ }
639
+ if (wantContentHash) {
640
+ contentHashReplacer = hashLength(
641
+ replacer(/** @type {string} */ (data.contentHash)),
642
+ undefined,
643
+ assetInfo,
644
+ "contenthash",
645
+ sourceDigest,
646
+ // full content digest, so a static `[contenthash:<digest>]` re-encodes
647
+ // from full entropy (asset modules supply it via `contentHashFull`)
648
+ data.contentHashFull,
649
+ data.realContentHash
650
+ );
651
+ if (presentKinds.has("contenthash")) {
652
+ replacements.set("contenthash", contentHashReplacer);
653
+ }
654
+ }
655
+ if (needHash) {
656
+ replacements.set(
657
+ "hash",
658
+ /** @type {Replacer} */
659
+ (data.contentHash ? contentHashReplacer : moduleHashReplacer)
660
+ );
661
+ }
371
662
  }
372
663
 
373
664
  // Other things
374
- if (data.url) {
665
+ //
666
+ // Placeholders
667
+ //
668
+ // [url] - data.url
669
+ // [uniqueName] - data.uniqueName (output.uniqueName)
670
+ // [uniquename] - alias of [uniqueName]
671
+ if (data.url && presentKinds.has("url")) {
375
672
  replacements.set("url", replacer(data.url));
376
673
  }
377
- if (typeof data.runtime === "string") {
378
- replacements.set(
379
- "runtime",
380
- replacer(() =>
381
- (data.prepareId || prepareId)(/** @type {string} */ (data.runtime))
382
- )
383
- );
384
- } else {
385
- replacements.set("runtime", replacer("_"));
674
+ if (
675
+ data.uniqueName !== undefined &&
676
+ (presentKinds.has("uniqueName") || presentKinds.has("uniquename"))
677
+ ) {
678
+ const uniqueNameReplacer = replacer(data.uniqueName);
679
+ if (presentKinds.has("uniqueName")) {
680
+ replacements.set("uniqueName", uniqueNameReplacer);
681
+ }
682
+ if (presentKinds.has("uniquename")) {
683
+ replacements.set("uniquename", uniqueNameReplacer);
684
+ }
386
685
  }
387
-
388
- if (typeof path === "function") {
389
- path = path(data, assetInfo);
686
+ if (presentKinds.has("runtime")) {
687
+ if (typeof data.runtime === "string") {
688
+ replacements.set(
689
+ "runtime",
690
+ replacer(() =>
691
+ (data.prepareId || prepareId)(/** @type {string} */ (data.runtime))
692
+ )
693
+ );
694
+ } else {
695
+ replacements.set("runtime", replacer("_"));
696
+ }
390
697
  }
391
698
 
392
699
  path = path.replace(REGEXP, (match, content) => {
393
700
  if (content.length + 2 === match.length) {
394
- const contentMatch = /^(\w+)(?::(\w+))?$/.exec(content);
701
+ const contentMatch = /^(\w+)(?::(\w+))?(?::(\w+))?$/.exec(content);
395
702
  if (!contentMatch) return match;
396
- const [, kind, arg] = contentMatch;
703
+ const [, kind, arg1, arg2] = contentMatch;
397
704
  const replacer = replacements.get(kind);
398
705
  if (replacer !== undefined) {
399
- return replacer(match, arg, /** @type {string} */ (path));
706
+ // `[kind:length]`, `[kind:digest]` or `[kind:digest:length]`.
707
+ /** @type {string | undefined} */
708
+ let digest;
709
+ /** @type {string | undefined} */
710
+ let length = arg1;
711
+ if (arg2 !== undefined) {
712
+ digest = arg1;
713
+ length = arg2;
714
+ } else if (arg1 !== undefined && !/^\d+$/.test(arg1)) {
715
+ digest = arg1;
716
+ length = undefined;
717
+ }
718
+ return replacer(match, length, /** @type {string} */ (path), digest);
400
719
  }
401
720
  } else if (match.startsWith("[\\") && match.endsWith("\\]")) {
402
721
  return `[${match.slice(2, -2)}]`;
@@ -417,10 +736,33 @@ class TemplatedPathPlugin {
417
736
  */
418
737
  apply(compiler) {
419
738
  compiler.hooks.compilation.tap(plugin, (compilation) => {
420
- compilation.hooks.assetPath.tap(plugin, interpolate);
739
+ compilation.hooks.assetPath.tap(plugin, (path, data, assetInfo) => {
740
+ // Default from output options so `[uniqueName]` resolves in every template
741
+ if (data.uniqueName === undefined) {
742
+ data.uniqueName = compilation.outputOptions.uniqueName;
743
+ }
744
+ // Digest the stored hashes use, so `[hash:<digest>]` can re-encode them
745
+ if (data.hashDigest === undefined) {
746
+ data.hashDigest = compilation.outputOptions.hashDigest;
747
+ }
748
+ // Untruncated compilation hash, so `[fullhash:<digest>]` keeps full entropy
749
+ if (data.fullHash === undefined && data.hash === compilation.hash) {
750
+ data.fullHash = compilation.fullHash;
751
+ }
752
+ // `RealContentHashPlugin` rehashes content; flag it so an inline digest
753
+ // on `[contenthash]` is recorded and the recomputed hash re-encodes in it.
754
+ if (data.realContentHash === undefined) {
755
+ data.realContentHash = Boolean(
756
+ compilation.options.optimization.realContentHash
757
+ );
758
+ }
759
+ return interpolate(path, data, assetInfo);
760
+ });
421
761
  });
422
762
  }
423
763
  }
424
764
 
425
765
  module.exports = TemplatedPathPlugin;
766
+ module.exports.getPresentKinds = getPresentKinds;
426
767
  module.exports.interpolate = interpolate;
768
+ module.exports.reEncodeDigest = reEncodeDigest;