@depup/webpack 5.110.3-depup.0 → 5.111.1-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 (283) hide show
  1. package/README.md +7 -8
  2. package/changes.json +7 -11
  3. package/lib/APIPlugin.js +26 -11
  4. package/lib/AutomaticPrefetchPlugin.js +1 -1
  5. package/lib/Cache.js +8 -3
  6. package/lib/CacheFacade.js +1 -1
  7. package/lib/CircularModulesPlugin.js +157 -55
  8. package/lib/CleanPlugin.js +2 -2
  9. package/lib/CompatibilityPlugin.js +3 -4
  10. package/lib/Compilation.js +336 -337
  11. package/lib/Compiler.js +213 -51
  12. package/lib/ConstPlugin.js +16 -132
  13. package/lib/CopyPlugin.js +1054 -0
  14. package/lib/DefinePlugin.js +24 -8
  15. package/lib/DependencyTemplate.js +2 -1
  16. package/lib/DotenvPlugin.js +24 -28
  17. package/lib/ErrorHelpers.js +113 -0
  18. package/lib/ExportsInfo.js +20 -16
  19. package/lib/ExternalModule.js +47 -22
  20. package/lib/FileSystemInfo.js +17 -14
  21. package/lib/FlagDependencyExportsPlugin.js +53 -34
  22. package/lib/FlagDependencyUsagePlugin.js +9 -13
  23. package/lib/Generator.js +24 -2
  24. package/lib/HotModuleReplacementPlugin.js +55 -7
  25. package/lib/IgnorePlugin.js +1 -1
  26. package/lib/JavascriptMetaInfoPlugin.js +5 -3
  27. package/lib/LoaderOptionsPlugin.js +1 -1
  28. package/lib/MainTemplate.js +5 -1
  29. package/lib/Module.js +19 -10
  30. package/lib/ModuleGraph.js +6 -9
  31. package/lib/MultiCompiler.js +7 -17
  32. package/lib/MultiWatching.js +1 -1
  33. package/lib/NormalModule.js +135 -50
  34. package/lib/NormalModuleFactory.js +1 -1
  35. package/lib/RuntimeGlobals.js +21 -7
  36. package/lib/RuntimeModule.js +28 -12
  37. package/lib/RuntimePlugin.js +30 -3
  38. package/lib/RuntimeTemplate.js +813 -518
  39. package/lib/SourceMapDevToolPlugin.js +54 -104
  40. package/lib/TemplatedPathPlugin.js +16 -59
  41. package/lib/Watching.js +9 -0
  42. package/lib/WebpackOptionsApply.js +84 -91
  43. package/lib/asset/AssetBytesGenerator.js +7 -1
  44. package/lib/asset/AssetGenerator.js +50 -24
  45. package/lib/asset/AssetModule.js +3 -0
  46. package/lib/asset/AssetSourceGenerator.js +7 -1
  47. package/lib/asset/WebManifestParser.js +7 -5
  48. package/lib/buildChunkGraph.js +11 -15
  49. package/lib/cache/AddBuildDependenciesPlugin.js +33 -4
  50. package/lib/cache/IdleFileCachePlugin.js +2 -2
  51. package/lib/cache/MemoryCachePlugin.js +4 -4
  52. package/lib/cache/MemoryWithGcCachePlugin.js +7 -8
  53. package/lib/cache/PackFileCacheStrategy.js +17 -19
  54. package/lib/cache/getLazyHashedEtag.js +3 -5
  55. package/lib/config/browserslistTargetHandler.js +17 -4
  56. package/lib/config/defaults.js +138 -128
  57. package/lib/config/getClaimedAssetTypes.js +10 -11
  58. package/lib/config/normalization.js +82 -12
  59. package/lib/config/target.js +13 -4
  60. package/lib/container/ContainerReferencePlugin.js +6 -0
  61. package/lib/container/RemoteRuntimeModule.js +9 -0
  62. package/lib/container/declaredRemotes.js +39 -0
  63. package/lib/{ContextExclusionPlugin.js → context/ContextExclusionPlugin.js} +1 -1
  64. package/lib/{ContextModule.js → context/ContextModule.js} +54 -115
  65. package/lib/{ContextModuleFactory.js → context/ContextModuleFactory.js} +19 -21
  66. package/lib/{ContextReplacementPlugin.js → context/ContextReplacementPlugin.js} +4 -4
  67. package/lib/css/CssGenerator.js +27 -11
  68. package/lib/css/CssInjectStyleRuntimeModule.js +9 -0
  69. package/lib/css/CssLoadingRuntimeModule.js +94 -36
  70. package/lib/css/CssModule.js +1 -1
  71. package/lib/css/CssModulesPlugin.js +7 -6
  72. package/lib/css/CssParser.js +162 -31
  73. package/lib/css/CssServerStylesRuntimeModule.js +9 -0
  74. package/lib/css/cssMinify.js +43 -32
  75. package/lib/css/data.js +3514 -869
  76. package/lib/css/syntax.js +6370 -1220
  77. package/lib/debug/ProfilingPlugin.js +7 -4
  78. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -3
  79. package/lib/dependencies/AMDRuntimeModules.js +18 -0
  80. package/lib/dependencies/CommonJsExportRequireDependency.js +13 -12
  81. package/lib/dependencies/CommonJsExportsParserPlugin.js +12 -13
  82. package/lib/dependencies/CommonJsImportsParserPlugin.js +5 -5
  83. package/lib/dependencies/CommonJsPlugin.js +19 -3
  84. package/lib/dependencies/CommonJsRequireDependency.js +14 -5
  85. package/lib/dependencies/CommonJsSelfReferenceDependency.js +2 -4
  86. package/lib/dependencies/ContextDependency.js +1 -1
  87. package/lib/dependencies/ContextDependencyHelpers.js +3 -9
  88. package/lib/dependencies/ContextElementDependency.js +1 -1
  89. package/lib/dependencies/CssIcssExportDependency.js +13 -9
  90. package/lib/dependencies/CssIcssImportDependency.js +3 -6
  91. package/lib/dependencies/CssUrlDependency.js +3 -5
  92. package/lib/dependencies/HarmonyCompatibilityDependency.js +67 -22
  93. package/lib/dependencies/HarmonyDetectionParserPlugin.js +3 -4
  94. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +10 -7
  95. package/lib/dependencies/HarmonyExportExpressionDependency.js +47 -33
  96. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +74 -17
  97. package/lib/dependencies/HarmonyExportInitFragment.js +110 -23
  98. package/lib/dependencies/HarmonyExportSpecifierDependency.js +25 -58
  99. package/lib/dependencies/HarmonyImportBareSideEffectDependency.js +59 -0
  100. package/lib/dependencies/HarmonyImportDependency.js +6 -1
  101. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +111 -17
  102. package/lib/dependencies/HarmonyImportSideEffectDependency.js +3 -4
  103. package/lib/dependencies/HarmonyImportSpecifierDependency.js +40 -3
  104. package/lib/dependencies/HarmonyModulesPlugin.js +20 -0
  105. package/lib/dependencies/HtmlEntryDependency.js +124 -102
  106. package/lib/dependencies/HtmlInlineScriptDependency.js +3 -4
  107. package/lib/dependencies/HtmlInlineStyleDependency.js +3 -4
  108. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +1 -1
  109. package/lib/dependencies/ImportMetaGlobHelpers.js +1 -1
  110. package/lib/dependencies/ImportMetaMainDependency.js +104 -0
  111. package/lib/dependencies/ImportMetaPlugin.js +67 -25
  112. package/lib/dependencies/ImportParserPlugin.js +1 -1
  113. package/lib/dependencies/LoaderPlugin.js +26 -1
  114. package/lib/dependencies/RequireContextDependencyParserPlugin.js +1 -1
  115. package/lib/dependencies/SystemRuntimeModule.js +9 -0
  116. package/lib/dependencies/URLContextDependency.js +1 -1
  117. package/lib/dependencies/URLDependency.js +6 -5
  118. package/lib/dependencies/WorkerAndWorkletPlugin.js +15 -21
  119. package/lib/dependencies/WorkerDependency.js +7 -7
  120. package/lib/dependencies/WorkletDependency.js +7 -11
  121. package/lib/dll/DelegatedModule.js +18 -1
  122. package/lib/dll/DllReferencePlugin.js +11 -8
  123. package/lib/dll/LibManifestPlugin.js +1 -1
  124. package/lib/errors/AnalyzableBailoutsWarning.js +41 -0
  125. package/lib/errors/DuplicateModulesWarning.js +12 -7
  126. package/lib/errors/EmptyCopyPatternWarning.js +26 -0
  127. package/lib/errors/ExternalStarReexportError.js +44 -0
  128. package/lib/errors/HookWebpackError.js +3 -2
  129. package/lib/errors/MissingSourceMapsWarning.js +36 -0
  130. package/lib/errors/ModuleParseError.js +2 -1
  131. package/lib/errors/UnusedAssetsWarning.js +36 -0
  132. package/lib/errors/UnusedFederationWarning.js +35 -0
  133. package/lib/errors/UnusedModulesWarning.js +38 -0
  134. package/lib/esm/ExportWebpackRequireRuntimeModule.js +9 -0
  135. package/lib/esm/ModuleChunkFormatPlugin.js +28 -3
  136. package/lib/esm/ModuleChunkLoadingPlugin.js +30 -11
  137. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +92 -60
  138. package/lib/hmr/HotModuleReplacement.runtime.js +8 -2
  139. package/lib/hmr/HotModuleReplacementRuntimeModule.js +9 -0
  140. package/lib/hmr/LazyCompilationPlugin.js +3 -5
  141. package/lib/html/HtmlGenerator.js +72 -87
  142. package/lib/html/HtmlModulesPlugin.js +418 -200
  143. package/lib/html/HtmlParser.js +110 -147
  144. package/lib/html/builtinEmbeddedRenderer.js +107 -0
  145. package/lib/html/data.js +142 -7
  146. package/lib/html/htmlMinify.js +92 -122
  147. package/lib/html/syntax.js +1618 -1391
  148. package/lib/ids/HashedModuleIdsPlugin.js +2 -1
  149. package/lib/index.js +49 -3
  150. package/lib/javascript/ChunkFormatHelpers.js +4 -3
  151. package/lib/javascript/JavascriptGenerator.js +8 -1
  152. package/lib/javascript/JavascriptModule.js +1 -0
  153. package/lib/javascript/JavascriptModulesPlugin.js +73 -72
  154. package/lib/javascript/JavascriptParser.js +1970 -900
  155. package/lib/javascript/StartupHelpers.js +27 -3
  156. package/lib/javascript/data.js +172 -0
  157. package/lib/javascript/grammar.js +5546 -0
  158. package/lib/javascript/parser.js +1500 -0
  159. package/lib/javascript/regexp.js +1762 -0
  160. package/lib/javascript/regexpData.js +51 -0
  161. package/lib/javascript/syntax.js +9061 -5262
  162. package/lib/json/JsonGenerator.js +7 -1
  163. package/lib/library/ModuleLibraryPlugin.js +171 -132
  164. package/lib/loaders/LoaderRunner.js +137 -9
  165. package/lib/node/NodeWatchFileSystem.js +3 -9
  166. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +22 -0
  167. package/lib/node/RequireChunkLoadingRuntimeModule.js +22 -0
  168. package/lib/optimize/AggressiveMergingPlugin.js +3 -5
  169. package/lib/optimize/ConcatenatedModule.js +178 -120
  170. package/lib/optimize/ConstExportsPlugin.js +50 -39
  171. package/lib/optimize/FlagIncludedChunksPlugin.js +3 -11
  172. package/lib/optimize/InlineExports.js +20 -123
  173. package/lib/optimize/InnerGraphPlugin.js +7 -13
  174. package/lib/optimize/LimitChunkCountPlugin.js +5 -8
  175. package/lib/optimize/MangleExportsPlugin.js +13 -4
  176. package/lib/optimize/ModuleConcatenationPlugin.js +27 -5
  177. package/lib/optimize/RealContentHashPlugin.js +68 -9
  178. package/lib/optimize/SideEffectsFlagPlugin.js +24 -28
  179. package/lib/optimize/SplitChunksPlugin.js +2 -4
  180. package/lib/performance/AnalyzableBailoutsPlugin.js +115 -0
  181. package/lib/performance/BroadContextsPlugin.js +1 -1
  182. package/lib/performance/CacheEffectivenessPlugin.js +7 -7
  183. package/lib/performance/DuplicateModulesPlugin.js +57 -13
  184. package/lib/performance/EvalUsagePlugin.js +5 -2
  185. package/lib/performance/MissingSourceMapsPlugin.js +115 -0
  186. package/lib/performance/PureAnnotationsPlugin.js +6 -3
  187. package/lib/performance/SizeLimitsPlugin.js +2 -4
  188. package/lib/performance/TopLevelThisPlugin.js +5 -4
  189. package/lib/performance/UnusedAssetsPlugin.js +109 -0
  190. package/lib/performance/UnusedFederationPlugin.js +147 -0
  191. package/lib/performance/UnusedModulesPlugin.js +141 -0
  192. package/lib/performance/UnusedReexportsPlugin.js +1 -55
  193. package/lib/performance/isOnlyReexported.js +65 -0
  194. package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +25 -5
  195. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +8 -8
  196. package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +9 -0
  197. package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +9 -0
  198. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +9 -0
  199. package/lib/prefetch/ResourceHintPlugin.js +18 -23
  200. package/lib/prefetch/ResourceHintRuntimeModule.js +9 -0
  201. package/lib/prefetch/StartupAssetHintRuntimeModule.js +16 -10
  202. package/lib/rules/RuleSetCompiler.js +211 -4
  203. package/lib/runtime/AsyncModuleRuntimeModule.js +98 -66
  204. package/lib/runtime/AutoPublicPathRuntimeModule.js +9 -0
  205. package/lib/runtime/BaseUriRuntimeModule.js +9 -0
  206. package/lib/runtime/ChunkNameRuntimeModule.js +9 -0
  207. package/lib/runtime/EnsureChunkRuntimeModule.js +35 -16
  208. package/lib/runtime/GetChunkFilenameRuntimeModule.js +12 -4
  209. package/lib/runtime/GetFullHashRuntimeModule.js +9 -0
  210. package/lib/runtime/GetMainFilenameRuntimeModule.js +9 -0
  211. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +9 -0
  212. package/lib/runtime/GlobalRuntimeModule.js +11 -4
  213. package/lib/runtime/HasOwnPropertyRuntimeModule.js +9 -0
  214. package/lib/runtime/HelperRuntimeModule.js +10 -0
  215. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +305 -224
  216. package/lib/runtime/NonceRuntimeModule.js +9 -0
  217. package/lib/runtime/OnChunksLoadedRuntimeModule.js +67 -20
  218. package/lib/runtime/PublicPathRuntimeModule.js +9 -0
  219. package/lib/runtime/RuntimeIdRuntimeModule.js +9 -0
  220. package/lib/runtime/SpecNamespaceObjectRuntimeModule.js +90 -0
  221. package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +9 -0
  222. package/lib/runtime/StartupEntrypointRuntimeModule.js +9 -0
  223. package/lib/runtime/SystemContextRuntimeModule.js +9 -0
  224. package/lib/runtime/ToBinaryRuntimeModule.js +9 -0
  225. package/lib/schemes/DataUriPlugin.js +3 -6
  226. package/lib/schemes/VirtualUrlPlugin.js +1 -1
  227. package/lib/serialization/BinaryMiddleware.js +9 -9
  228. package/lib/serialization/FileMiddleware.js +16 -16
  229. package/lib/serialization/ObjectMiddleware.js +168 -139
  230. package/lib/sharing/ConsumeSharedPlugin.js +12 -0
  231. package/lib/sharing/ConsumeSharedRuntimeModule.js +11 -0
  232. package/lib/sharing/ShareRuntimeModule.js +9 -0
  233. package/lib/sharing/declaredShared.js +47 -0
  234. package/lib/stats/DefaultStatsFactoryPlugin.js +6 -5
  235. package/lib/stats/DefaultStatsPrinterPlugin.js +3 -0
  236. package/lib/typescript/TypeScriptPlugin.js +2 -3
  237. package/lib/url/URLParserPlugin.js +6 -8
  238. package/lib/util/LocConverter.js +4 -7
  239. package/lib/util/SourceProcessor.js +91 -91
  240. package/lib/util/async.js +292 -0
  241. package/lib/util/buildDiagnostics.js +69 -0
  242. package/lib/util/chainedImports.js +3 -4
  243. package/lib/util/concatenate.js +4 -4
  244. package/lib/util/createHooksRegistry.js +1 -2
  245. package/lib/util/dataURL.js +2 -3
  246. package/lib/util/deterministicGrouping.js +8 -13
  247. package/lib/util/findGraphRoots.js +6 -13
  248. package/lib/util/fs.js +27 -1
  249. package/lib/util/globUtils.js +1 -1
  250. package/lib/util/handlerKeys.js +40 -0
  251. package/lib/util/hash/wasm-hash.js +3 -4
  252. package/lib/util/identifier.js +20 -0
  253. package/lib/util/internalSerializables.js +5 -1
  254. package/lib/util/registerExternalSerializer.js +6 -45
  255. package/lib/util/semver.js +5 -3
  256. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +9 -0
  257. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +9 -0
  258. package/lib/wasm-async/AsyncWebAssemblyGenerator.js +6 -1
  259. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +5 -1
  260. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +12 -4
  261. package/lib/wasm-sync/WebAssemblyGenerator.js +6 -1
  262. package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +5 -1
  263. package/lib/wasm-sync/WebAssemblyUtils.js +2 -4
  264. package/lib/web/JsonpChunkLoadingRuntimeModule.js +36 -0
  265. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +19 -0
  266. package/package.json +55 -46
  267. package/schemas/WebpackOptions.check.js +1 -1
  268. package/schemas/WebpackOptions.json +379 -66
  269. package/schemas/plugins/LoaderOptionsPlugin.check.js +1 -1
  270. package/schemas/plugins/ManifestPlugin.check.js +1 -1
  271. package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
  272. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
  273. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
  274. package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
  275. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  276. package/schemas/plugins/debug/ProfilingPlugin.check.js +1 -1
  277. package/schemas/plugins/dll/DllReferencePlugin.check.js +1 -1
  278. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +1 -1
  279. package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
  280. package/types.d.ts +1723 -604
  281. package/lib/dependencies/ExportBindingInitFragment.js +0 -191
  282. package/lib/errors/EntrypointOverlapWarning.js +0 -45
  283. package/lib/performance/EntrypointOverlapPlugin.js +0 -122
package/lib/Compiler.js CHANGED
@@ -5,8 +5,6 @@
5
5
 
6
6
  "use strict";
7
7
 
8
- const asyncLib = require("neo-async");
9
-
10
8
  const {
11
9
  AsyncParallelHook,
12
10
  AsyncSeriesHook,
@@ -18,15 +16,16 @@ const Cache = require("./Cache");
18
16
  const CacheFacade = require("./CacheFacade");
19
17
  const ChunkGraph = require("./ChunkGraph");
20
18
  const Compilation = require("./Compilation");
21
- const ContextModuleFactory = require("./ContextModuleFactory");
22
19
  const ModuleGraph = require("./ModuleGraph");
23
20
  const NormalModuleFactory = require("./NormalModuleFactory");
24
21
  const RequestShortener = require("./RequestShortener");
25
22
  const ResolverFactory = require("./ResolverFactory");
26
23
  const Stats = require("./Stats");
24
+ const ContextModuleFactory = require("./context/ContextModuleFactory");
27
25
  const WebpackError = require("./errors/WebpackError");
28
26
  const { Logger } = require("./logging/Logger");
29
- const { dirname, join, mkdirp } = require("./util/fs");
27
+ const asyncLib = require("./util/async");
28
+ const { PERMISSIONS_MASK, dirname, join, mkdirp } = require("./util/fs");
30
29
  const {
31
30
  WINDOWS_ABS_PATH_REGEXP,
32
31
  makePathsRelative
@@ -45,6 +44,7 @@ const getConcurrentCompilationError = memoize(() =>
45
44
  );
46
45
 
47
46
  /** @import { Source } from "webpack-sources" */
47
+ /** @import { AssetInfo, AssetSymlink } from "./Compilation" */
48
48
  /**
49
49
  * @import {
50
50
  * EntryNormalized as Entry,
@@ -497,29 +497,33 @@ class Compiler {
497
497
  // e.g. move compilation specific info from Modules into ModuleGraph
498
498
  _cleanupLastCompilation() {
499
499
  if (this._lastCompilation !== undefined) {
500
- for (const childCompilation of this._lastCompilation.children) {
501
- for (const module of childCompilation.modules) {
502
- ChunkGraph.clearChunkGraphForModule(module);
503
- ModuleGraph.clearModuleGraphForModule(module);
504
- module.cleanupForCache();
505
- }
506
- for (const chunk of childCompilation.chunks) {
507
- ChunkGraph.clearChunkGraphForChunk(chunk);
508
- }
509
- }
510
-
511
- for (const module of this._lastCompilation.modules) {
512
- ChunkGraph.clearChunkGraphForModule(module);
513
- ModuleGraph.clearModuleGraphForModule(module);
514
- module.cleanupForCache();
515
- }
516
- for (const chunk of this._lastCompilation.chunks) {
517
- ChunkGraph.clearChunkGraphForChunk(chunk);
518
- }
500
+ this._cleanupCompilationForCache(this._lastCompilation);
519
501
  this._lastCompilation = undefined;
520
502
  }
521
503
  }
522
504
 
505
+ /**
506
+ * Drops the graph references a finished compilation left on its modules and
507
+ * chunks. Recurses, because child compilations nest: a module only reached
508
+ * below the first level keeps its parser, generator and memoized
509
+ * `ModuleGraph`, which pins the whole stale compilation.
510
+ * @param {Compilation} compilation compilation to clean up
511
+ * @returns {void}
512
+ */
513
+ _cleanupCompilationForCache(compilation) {
514
+ for (const childCompilation of compilation.children) {
515
+ this._cleanupCompilationForCache(childCompilation);
516
+ }
517
+ for (const module of compilation.modules) {
518
+ ChunkGraph.clearChunkGraphForModule(module);
519
+ ModuleGraph.clearModuleGraphForModule(module);
520
+ module.cleanupForCache();
521
+ }
522
+ for (const chunk of compilation.chunks) {
523
+ ChunkGraph.clearChunkGraphForChunk(chunk);
524
+ }
525
+ }
526
+
523
527
  // TODO webpack 6: solve this in a better way
524
528
  _cleanupLastNormalModuleFactory() {
525
529
  if (this._lastNormalModuleFactory !== undefined) {
@@ -671,6 +675,7 @@ class Compiler {
671
675
  if (err) return finalCallback(err);
672
676
  this.cache.storeBuildDependencies(
673
677
  compilation.buildDependencies,
678
+ compilation.optionalBuildDependencies,
674
679
  (err) => {
675
680
  if (err) return finalCallback(err);
676
681
  return finalCallback(null, stats);
@@ -796,7 +801,7 @@ class Compiler {
796
801
  const caseInsensitiveMap = new Map();
797
802
  /** @type {Set<string>} */
798
803
  const allTargetPaths = new Set();
799
- asyncLib.forEachLimit(
804
+ asyncLib.eachLimit(
800
805
  assets,
801
806
  15,
802
807
  ({ name: file, source, info }, callback) => {
@@ -833,6 +838,17 @@ class Compiler {
833
838
  if (err) return callback(err);
834
839
  allTargetPaths.add(targetPath);
835
840
 
841
+ // a link is created rather than written, and none of the content
842
+ // caching below applies to one
843
+ if (info.symlink) {
844
+ return this._emitSymlink(
845
+ compilation,
846
+ { file, source, outputPath, targetPath },
847
+ info.symlink,
848
+ callback
849
+ );
850
+ }
851
+
836
852
  // check if the target file has already been written by this Compiler
837
853
  const targetFileGeneration =
838
854
  this._assetEmittingWrittenFiles.get(targetPath);
@@ -928,28 +944,37 @@ ${other}`);
928
944
  (this.outputFileSystem).writeFile(targetPath, content, (err) => {
929
945
  if (err) return callback(err);
930
946
 
931
- // information marker that the asset has been emitted
932
- compilation.emittedAssets.add(file);
947
+ // set on what was just written, so a file the comparison above
948
+ // left alone keeps what it already carries
949
+ this._setAssetFileAttributes(targetPath, info, (err) => {
950
+ if (err) return callback(err);
933
951
 
934
- // cache the information that the Source has been written to that location
935
- const newGeneration =
936
- targetFileGeneration === undefined
937
- ? 1
938
- : targetFileGeneration + 1;
939
- /** @type {CacheEntry} */
940
- (cacheEntry).writtenTo.set(targetPath, newGeneration);
941
- this._assetEmittingWrittenFiles.set(targetPath, newGeneration);
942
- this.hooks.assetEmitted.callAsync(
943
- file,
944
- {
945
- content,
946
- source,
947
- outputPath,
948
- compilation,
949
- targetPath
950
- },
951
- callback
952
- );
952
+ // information marker that the asset has been emitted
953
+ compilation.emittedAssets.add(file);
954
+
955
+ // cache the information that the Source has been written to that location
956
+ const newGeneration =
957
+ targetFileGeneration === undefined
958
+ ? 1
959
+ : targetFileGeneration + 1;
960
+ /** @type {CacheEntry} */
961
+ (cacheEntry).writtenTo.set(targetPath, newGeneration);
962
+ this._assetEmittingWrittenFiles.set(
963
+ targetPath,
964
+ newGeneration
965
+ );
966
+ this.hooks.assetEmitted.callAsync(
967
+ file,
968
+ {
969
+ content,
970
+ source,
971
+ outputPath,
972
+ compilation,
973
+ targetPath
974
+ },
975
+ callback
976
+ );
977
+ });
953
978
  });
954
979
  };
955
980
 
@@ -998,6 +1023,30 @@ ${other}`);
998
1023
  });
999
1024
  };
1000
1025
 
1026
+ /**
1027
+ * Keeps the file already on disk, giving it the permissions and times
1028
+ * the asset carries — the build which wrote it may not have set them.
1029
+ * Only the modification time is compared, as reading a file moves its
1030
+ * access time.
1031
+ * @param {IStats} stats stats of the file on disk
1032
+ * @returns {void}
1033
+ */
1034
+ const keepExistingFile = (stats) => {
1035
+ const differs =
1036
+ (info.mode !== undefined &&
1037
+ (stats.mode & PERMISSIONS_MASK) !== info.mode) ||
1038
+ (info.timestamps !== undefined &&
1039
+ // compared at the precision `utimes` wrote, as a `Date` drops
1040
+ // the sub-millisecond part a filesystem may report
1041
+ Math.trunc(stats.mtimeMs) !==
1042
+ Math.trunc(info.timestamps.mtime));
1043
+ if (!differs) return alreadyWritten();
1044
+ this._setAssetFileAttributes(targetPath, info, (err) => {
1045
+ if (err) return callback(err);
1046
+ alreadyWritten();
1047
+ });
1048
+ };
1049
+
1001
1050
  /**
1002
1051
  * Process existing file.
1003
1052
  * @param {IStats} stats stats
@@ -1007,17 +1056,16 @@ ${other}`);
1007
1056
  // skip emitting if it's already there and an immutable file
1008
1057
  if (immutable) {
1009
1058
  updateWithReplacementSource(/** @type {number} */ (stats.size));
1010
- return alreadyWritten();
1059
+ return keepExistingFile(stats);
1011
1060
  }
1012
1061
 
1013
1062
  const content = getContent();
1014
1063
 
1015
1064
  updateWithReplacementSource(content.length);
1016
1065
 
1017
- // if it exists and content on disk matches content
1018
- // skip writing the same content again
1019
- // (to keep mtime and don't trigger watchers)
1020
- // for a fast negative match file size is compared first
1066
+ // Skip rewriting content already on disk, which would move the
1067
+ // mtime and wake watchers. Size is compared first, as a cheap
1068
+ // negative match.
1021
1069
  if (content.length === stats.size) {
1022
1070
  compilation.comparedForEmitAssets.add(file);
1023
1071
  return /** @type {OutputFileSystem} */ (
@@ -1029,7 +1077,7 @@ ${other}`);
1029
1077
  ) {
1030
1078
  return doWrite(content);
1031
1079
  }
1032
- return alreadyWritten();
1080
+ return keepExistingFile(stats);
1033
1081
  });
1034
1082
  }
1035
1083
 
@@ -1132,6 +1180,120 @@ ${other}`);
1132
1180
  });
1133
1181
  }
1134
1182
 
1183
+ /**
1184
+ * Gives the file an asset was written to the permissions and the times the
1185
+ * asset carries. A symbolic link never carries either, as both follow it to
1186
+ * its target.
1187
+ * @private
1188
+ * @param {string} targetPath absolute path of the file
1189
+ * @param {AssetInfo} info info of the asset
1190
+ * @param {ErrorCallback} callback signals when the call finishes
1191
+ * @returns {void}
1192
+ */
1193
+ _setAssetFileAttributes(targetPath, info, callback) {
1194
+ const { mode, timestamps } = info;
1195
+ if (mode === undefined && timestamps === undefined) return callback(null);
1196
+ const fs = /** @type {OutputFileSystem} */ (this.outputFileSystem);
1197
+
1198
+ /**
1199
+ * @param {(Error | null)=} err error of the step before
1200
+ * @returns {void}
1201
+ */
1202
+ const setTimestamps = (err) => {
1203
+ if (err) return callback(err);
1204
+ if (timestamps === undefined) return callback(null);
1205
+ if (!fs.utimes) {
1206
+ return callback(
1207
+ new WebpackError(
1208
+ `Unable to set the times of '${targetPath}': the output file system cannot set them`
1209
+ )
1210
+ );
1211
+ }
1212
+ /** @type {NonNullable<OutputFileSystem["utimes"]>} */
1213
+ (fs.utimes)(
1214
+ targetPath,
1215
+ new Date(timestamps.atime),
1216
+ new Date(timestamps.mtime),
1217
+ (err) => callback(err || null)
1218
+ );
1219
+ };
1220
+
1221
+ if (mode === undefined) return setTimestamps();
1222
+ if (!fs.chmod) {
1223
+ return callback(
1224
+ new WebpackError(
1225
+ `Unable to set the permissions of '${targetPath}': the output file system cannot set them`
1226
+ )
1227
+ );
1228
+ }
1229
+ /** @type {NonNullable<OutputFileSystem["chmod"]>} */
1230
+ (fs.chmod)(targetPath, mode, setTimestamps);
1231
+ }
1232
+
1233
+ /**
1234
+ * Creates an asset which is a symbolic link, replacing whatever else is at
1235
+ * its path. An existing link already pointing there is left alone, so a watch
1236
+ * rebuild does not touch it.
1237
+ * @private
1238
+ * @param {Compilation} compilation the compilation
1239
+ * @param {object} asset the asset which is a link
1240
+ * @param {string} asset.file the filename of the asset
1241
+ * @param {Source} asset.source content of the asset, which is what the link points at
1242
+ * @param {string} asset.outputPath absolute path the assets are emitted into
1243
+ * @param {string} asset.targetPath absolute path the link is created at
1244
+ * @param {AssetSymlink} symlink what the link points at
1245
+ * @param {ErrorCallback} callback signals when the call finishes
1246
+ * @returns {void}
1247
+ */
1248
+ _emitSymlink(compilation, asset, symlink, callback) {
1249
+ const { file, source, outputPath, targetPath } = asset;
1250
+ const fs = /** @type {OutputFileSystem} */ (this.outputFileSystem);
1251
+ if (!fs.symlink) {
1252
+ return callback(
1253
+ new WebpackError(
1254
+ `Unable to emit '${file}' as a symbolic link: the output file system cannot create one`
1255
+ )
1256
+ );
1257
+ }
1258
+ const { target, isDirectory } = symlink;
1259
+
1260
+ const created = () => {
1261
+ compilation.emittedAssets.add(file);
1262
+ this.hooks.assetEmitted.callAsync(
1263
+ file,
1264
+ {
1265
+ content: Buffer.from(target, "utf8"),
1266
+ source,
1267
+ outputPath,
1268
+ compilation,
1269
+ targetPath
1270
+ },
1271
+ callback
1272
+ );
1273
+ };
1274
+
1275
+ const create = () => {
1276
+ /** @type {NonNullable<OutputFileSystem["symlink"]>} */
1277
+ (fs.symlink)(target, targetPath, isDirectory ? "dir" : "file", (err) => {
1278
+ if (err) return callback(err);
1279
+ created();
1280
+ });
1281
+ };
1282
+
1283
+ const replace = () => {
1284
+ if (!fs.unlink) return create();
1285
+ /** @type {NonNullable<OutputFileSystem["unlink"]>} */
1286
+ (fs.unlink)(targetPath, () => create());
1287
+ };
1288
+
1289
+ if (!fs.readlink) return replace();
1290
+ /** @type {NonNullable<OutputFileSystem["readlink"]>} */
1291
+ (fs.readlink)(targetPath, (err, existingTarget) => {
1292
+ if (!err && existingTarget === target) return callback(null);
1293
+ replace();
1294
+ });
1295
+ }
1296
+
1135
1297
  /**
1136
1298
  * Processes the provided error callback.
1137
1299
  * @param {ErrorCallback} callback signals when the call finishes
@@ -219,17 +219,8 @@ class ConstPlugin {
219
219
  } else {
220
220
  parser.walkExpression(expression.test);
221
221
  }
222
- // Expressions do not hoist.
223
- // It is safe to remove the dead branch.
224
- //
225
- // Given the following code:
226
- //
227
- // false ? someExpression() : otherExpression();
228
- //
229
- // the generated code is:
230
- //
231
- // false ? 0 : otherExpression();
232
- //
222
+ // Expressions do not hoist, so the dead branch is safe to remove:
223
+ // `false ? someExpression() : other()` becomes `false ? 0 : other()`.
233
224
  const branchToRemove = bool
234
225
  ? expression.alternate
235
226
  : expression.consequent;
@@ -254,49 +245,9 @@ class ConstPlugin {
254
245
  const param = parser.evaluateExpression(expression.left);
255
246
  const bool = param.asBool();
256
247
  if (typeof bool === "boolean") {
257
- // Expressions do not hoist.
258
- // It is safe to remove the dead branch.
259
- //
260
- // ------------------------------------------
261
- //
262
- // Given the following code:
263
- //
264
- // falsyExpression() && someExpression();
265
- //
266
- // the generated code is:
267
- //
268
- // falsyExpression() && false;
269
- //
270
- // ------------------------------------------
271
- //
272
- // Given the following code:
273
- //
274
- // truthyExpression() && someExpression();
275
- //
276
- // the generated code is:
277
- //
278
- // true && someExpression();
279
- //
280
- // ------------------------------------------
281
- //
282
- // Given the following code:
283
- //
284
- // truthyExpression() || someExpression();
285
- //
286
- // the generated code is:
287
- //
288
- // truthyExpression() || false;
289
- //
290
- // ------------------------------------------
291
- //
292
- // Given the following code:
293
- //
294
- // falsyExpression() || someExpression();
295
- //
296
- // the generated code is:
297
- //
298
- // false && someExpression();
299
- //
248
+ // Expressions do not hoist, so the dead branch is safe to remove.
249
+ // Whichever side cannot decide the result is replaced, leaving the
250
+ // deciding side and its side effects in place.
300
251
  const keepRight =
301
252
  (expression.operator === "&&" && bool) ||
302
253
  (expression.operator === "||" && !bool);
@@ -305,14 +256,8 @@ class ConstPlugin {
305
256
  !param.couldHaveSideEffects() &&
306
257
  (param.isBoolean() || keepRight)
307
258
  ) {
308
- // for case like
309
- //
310
- // return'development'===process.env.NODE_ENV&&'foo'
311
- //
312
- // we need a space before the bool to prevent result like
313
- //
314
- // returnfalse&&'foo'
315
- //
259
+ // The bool needs a leading space: `return'a'===b&&'foo'` would
260
+ // otherwise become `returnfalse&&'foo'`.
316
261
  const dep = new ConstDependency(
317
262
  ` ${bool}`,
318
263
  /** @type {Range} */ (param.range)
@@ -336,36 +281,12 @@ class ConstPlugin {
336
281
  const param = parser.evaluateExpression(expression.left);
337
282
  const keepRight = param.asNullish();
338
283
  if (typeof keepRight === "boolean") {
339
- // ------------------------------------------
340
- //
341
- // Given the following code:
342
- //
343
- // nonNullish ?? someExpression();
344
- //
345
- // the generated code is:
346
- //
347
- // nonNullish ?? 0;
348
- //
349
- // ------------------------------------------
350
- //
351
- // Given the following code:
352
- //
353
- // nullish ?? someExpression();
354
- //
355
- // the generated code is:
356
- //
357
- // null ?? someExpression();
358
- //
284
+ // `nonNullish ?? x` becomes `nonNullish ?? 0`, and `nullish ?? x`
285
+ // becomes `null ?? x`: the unreachable side is replaced.
359
286
  if (!param.couldHaveSideEffects() && keepRight) {
360
287
  // cspell:word returnnull
361
- // for case like
362
- //
363
- // return('development'===process.env.NODE_ENV&&null)??'foo'
364
- //
365
- // we need a space before the bool to prevent result like
366
- //
367
- // returnnull??'foo'
368
- //
288
+ // As above, the value needs a leading space, or `return(…&&null)`
289
+ // would become `returnnull??'foo'`.
369
290
  const dep = new ConstDependency(
370
291
  " null",
371
292
  /** @type {Range} */ (param.range)
@@ -423,18 +344,8 @@ class ConstPlugin {
423
344
  );
424
345
 
425
346
  if (evaluated.asNullish()) {
426
- // ------------------------------------------
427
- //
428
- // Given the following code:
429
- //
430
- // nullishMemberChain?.a.b();
431
- //
432
- // the generated code is:
433
- //
434
- // undefined;
435
- //
436
- // ------------------------------------------
437
- //
347
+ // A nullish chain short-circuits whole, so `nullish?.a.b()`
348
+ // becomes `undefined`.
438
349
  const dep = new ConstDependency(
439
350
  " undefined",
440
351
  /** @type {Range} */ (expr.range)
@@ -519,36 +430,9 @@ class ConstPlugin {
519
430
  * @returns {void}
520
431
  */
521
432
  eliminateUnusedStatement(parser, statement, alwaysInBlock) {
522
- // Before removing the unused branch, the hoisted declarations
523
- // must be collected.
524
- //
525
- // Given the following code:
526
- //
527
- // if (true) f() else g()
528
- // if (false) {
529
- // function f() {}
530
- // const g = function g() {}
531
- // if (someTest) {
532
- // let a = 1
533
- // var x, {y, z} = obj
534
- // }
535
- // } else {
536
- // …
537
- // }
538
- //
539
- // the generated code is:
540
- //
541
- // if (true) f() else {}
542
- // if (false) {
543
- // var f, x, y, z; (in loose mode)
544
- // var x, y, z; (in strict mode)
545
- // } else {
546
- // …
547
- // }
548
- //
549
- // NOTE: When code runs in strict mode, `var` declarations
550
- // are hoisted but `function` declarations don't.
551
- //
433
+ // The hoisted declarations must be collected before the unused branch goes,
434
+ // since the removed code still contributes them. In strict mode `var` is
435
+ // hoisted but `function` is not, so the two modes collect different sets.
552
436
  const declarations = parser.scope.isStrict
553
437
  ? getHoistedDeclarations(statement, false)
554
438
  : getHoistedDeclarations(statement, true);