webpack 5.110.2 → 5.111.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 (226) hide show
  1. package/README.md +5 -2
  2. package/lib/APIPlugin.js +23 -7
  3. package/lib/AutomaticPrefetchPlugin.js +1 -1
  4. package/lib/Cache.js +8 -3
  5. package/lib/CacheFacade.js +1 -1
  6. package/lib/ChunkGraph.js +20 -18
  7. package/lib/CircularModulesPlugin.js +157 -55
  8. package/lib/CleanPlugin.js +2 -2
  9. package/lib/Compilation.js +321 -303
  10. package/lib/Compiler.js +209 -46
  11. package/lib/ConcatenationScope.js +25 -35
  12. package/lib/ContextModule.js +17 -81
  13. package/lib/ContextModuleFactory.js +1 -1
  14. package/lib/CopyPlugin.js +1054 -0
  15. package/lib/DefinePlugin.js +24 -8
  16. package/lib/DotenvPlugin.js +41 -13
  17. package/lib/ExternalModule.js +41 -14
  18. package/lib/FileSystemInfo.js +17 -14
  19. package/lib/FlagDependencyExportsPlugin.js +45 -21
  20. package/lib/FlagDependencyUsagePlugin.js +8 -2
  21. package/lib/HotModuleReplacementPlugin.js +53 -7
  22. package/lib/JavascriptMetaInfoPlugin.js +5 -3
  23. package/lib/MainTemplate.js +5 -1
  24. package/lib/Module.js +16 -7
  25. package/lib/MultiCompiler.js +1 -1
  26. package/lib/MultiWatching.js +1 -1
  27. package/lib/NormalModule.js +58 -32
  28. package/lib/NormalModuleFactory.js +1 -1
  29. package/lib/RuntimeGlobals.js +21 -7
  30. package/lib/RuntimeModule.js +28 -12
  31. package/lib/RuntimePlugin.js +33 -3
  32. package/lib/RuntimeTemplate.js +794 -477
  33. package/lib/SourceMapDevToolPlugin.js +1 -1
  34. package/lib/Watching.js +9 -0
  35. package/lib/WebpackOptionsApply.js +84 -91
  36. package/lib/asset/AssetGenerator.js +25 -8
  37. package/lib/asset/AssetModule.js +3 -0
  38. package/lib/asset/WebManifestParser.js +7 -5
  39. package/lib/async-modules/AsyncModuleHelpers.js +10 -4
  40. package/lib/cache/AddBuildDependenciesPlugin.js +33 -4
  41. package/lib/cache/IdleFileCachePlugin.js +2 -2
  42. package/lib/cache/PackFileCacheStrategy.js +14 -1
  43. package/lib/config/browserslistTargetHandler.js +19 -0
  44. package/lib/config/defaults.js +110 -64
  45. package/lib/config/normalization.js +100 -20
  46. package/lib/config/target.js +10 -0
  47. package/lib/container/ContainerReferencePlugin.js +6 -0
  48. package/lib/container/RemoteRuntimeModule.js +9 -0
  49. package/lib/container/declaredRemotes.js +39 -0
  50. package/lib/css/CssGenerator.js +8 -0
  51. package/lib/css/CssInjectStyleRuntimeModule.js +9 -0
  52. package/lib/css/CssLoadingRuntimeModule.js +94 -36
  53. package/lib/css/CssModule.js +1 -1
  54. package/lib/css/CssModulesPlugin.js +7 -6
  55. package/lib/css/CssParser.js +144 -11
  56. package/lib/css/CssServerStylesRuntimeModule.js +9 -0
  57. package/lib/css/cssMinify.js +11 -3
  58. package/lib/css/data.js +2814 -678
  59. package/lib/css/syntax.js +4082 -248
  60. package/lib/debug/ProfilingPlugin.js +4 -0
  61. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -3
  62. package/lib/dependencies/AMDRuntimeModules.js +18 -0
  63. package/lib/dependencies/CommonJsExportRequireDependency.js +3 -1
  64. package/lib/dependencies/CommonJsExportsParserPlugin.js +12 -13
  65. package/lib/dependencies/CommonJsImportsParserPlugin.js +1 -0
  66. package/lib/dependencies/CommonJsPlugin.js +19 -3
  67. package/lib/dependencies/CommonJsRequireDependency.js +32 -9
  68. package/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +20 -7
  69. package/lib/dependencies/CssIcssExportDependency.js +7 -1
  70. package/lib/dependencies/HarmonyCompatibilityDependency.js +58 -4
  71. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +8 -3
  72. package/lib/dependencies/HarmonyExportExpressionDependency.js +44 -29
  73. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +171 -32
  74. package/lib/dependencies/HarmonyExportInitFragment.js +99 -19
  75. package/lib/dependencies/HarmonyExportSpecifierDependency.js +18 -30
  76. package/lib/dependencies/HarmonyImportBareSideEffectDependency.js +59 -0
  77. package/lib/dependencies/HarmonyImportDependency.js +99 -41
  78. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +20 -3
  79. package/lib/dependencies/HarmonyImportSpecifierDependency.js +24 -1
  80. package/lib/dependencies/HarmonyModulesPlugin.js +20 -0
  81. package/lib/dependencies/HtmlEntryDependency.js +62 -2
  82. package/lib/dependencies/ImportContextDependency.js +43 -3
  83. package/lib/dependencies/ImportDependency.js +8 -29
  84. package/lib/dependencies/ImportMetaMainDependency.js +104 -0
  85. package/lib/dependencies/ImportMetaPlugin.js +59 -15
  86. package/lib/dependencies/ImportParserPlugin.js +24 -14
  87. package/lib/dependencies/RequireHeaderDependency.js +20 -21
  88. package/lib/dependencies/SystemRuntimeModule.js +9 -0
  89. package/lib/dependencies/WorkerDependency.js +1 -2
  90. package/lib/dependencies/WorkletDependency.js +1 -2
  91. package/lib/dependencies/importOptionsCheck.js +47 -0
  92. package/lib/dll/DelegatedModule.js +18 -1
  93. package/lib/dll/DllReferencePlugin.js +11 -8
  94. package/lib/dll/LibManifestPlugin.js +1 -1
  95. package/lib/errors/AnalyzableBailoutsWarning.js +41 -0
  96. package/lib/errors/DotenvFileError.js +29 -0
  97. package/lib/errors/DuplicateModulesWarning.js +12 -7
  98. package/lib/errors/EmptyCopyPatternWarning.js +26 -0
  99. package/lib/errors/ExternalStarReexportError.js +44 -0
  100. package/lib/errors/ImportedBindingAssignmentError.js +30 -0
  101. package/lib/errors/MissingSourceMapsWarning.js +36 -0
  102. package/lib/errors/ModuleParseError.js +2 -1
  103. package/lib/errors/UnusedAssetsWarning.js +36 -0
  104. package/lib/errors/UnusedFederationWarning.js +35 -0
  105. package/lib/errors/UnusedModulesWarning.js +38 -0
  106. package/lib/esm/ExportWebpackRequireRuntimeModule.js +9 -0
  107. package/lib/esm/ModuleChunkFormatPlugin.js +28 -3
  108. package/lib/esm/ModuleChunkLoadingPlugin.js +30 -11
  109. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +92 -60
  110. package/lib/hmr/HotModuleReplacement.runtime.js +8 -2
  111. package/lib/hmr/HotModuleReplacementRuntimeModule.js +9 -0
  112. package/lib/html/HtmlGenerator.js +11 -5
  113. package/lib/html/HtmlModulesPlugin.js +360 -84
  114. package/lib/html/HtmlParser.js +13 -6
  115. package/lib/html/builtinEmbeddedRenderer.js +107 -0
  116. package/lib/html/data.js +121 -7
  117. package/lib/html/htmlMinify.js +84 -113
  118. package/lib/html/syntax.js +1067 -569
  119. package/lib/ids/HashedModuleIdsPlugin.js +2 -1
  120. package/lib/index.js +3 -0
  121. package/lib/javascript/JavascriptModule.js +1 -0
  122. package/lib/javascript/JavascriptModulesPlugin.js +52 -22
  123. package/lib/javascript/JavascriptParser.js +1255 -728
  124. package/lib/javascript/StartupHelpers.js +27 -3
  125. package/lib/javascript/data.js +172 -0
  126. package/lib/javascript/grammar.js +5546 -0
  127. package/lib/javascript/parser.js +1494 -0
  128. package/lib/javascript/regexp.js +1762 -0
  129. package/lib/javascript/regexpData.js +51 -0
  130. package/lib/javascript/syntax.js +8696 -5225
  131. package/lib/library/ModuleLibraryPlugin.js +116 -5
  132. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +22 -0
  133. package/lib/node/RequireChunkLoadingRuntimeModule.js +22 -0
  134. package/lib/optimize/ConcatenatedModule.js +133 -25
  135. package/lib/optimize/ConstExportsPlugin.js +50 -39
  136. package/lib/optimize/InlineExports.js +20 -123
  137. package/lib/optimize/MangleExportsPlugin.js +10 -0
  138. package/lib/optimize/ModuleConcatenationPlugin.js +24 -1
  139. package/lib/optimize/RealContentHashPlugin.js +68 -9
  140. package/lib/optimize/SideEffectsFlagPlugin.js +17 -9
  141. package/lib/performance/AnalyzableBailoutsPlugin.js +115 -0
  142. package/lib/performance/CacheEffectivenessPlugin.js +4 -3
  143. package/lib/performance/DuplicateModulesPlugin.js +57 -13
  144. package/lib/performance/EvalUsagePlugin.js +5 -2
  145. package/lib/performance/MissingSourceMapsPlugin.js +115 -0
  146. package/lib/performance/PureAnnotationsPlugin.js +6 -3
  147. package/lib/performance/TopLevelThisPlugin.js +5 -4
  148. package/lib/performance/UnusedAssetsPlugin.js +109 -0
  149. package/lib/performance/UnusedFederationPlugin.js +147 -0
  150. package/lib/performance/UnusedModulesPlugin.js +141 -0
  151. package/lib/performance/UnusedReexportsPlugin.js +1 -55
  152. package/lib/performance/isOnlyReexported.js +65 -0
  153. package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +25 -5
  154. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +2 -0
  155. package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +9 -0
  156. package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +9 -0
  157. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +9 -0
  158. package/lib/prefetch/ResourceHintPlugin.js +7 -3
  159. package/lib/prefetch/ResourceHintRuntimeModule.js +9 -0
  160. package/lib/prefetch/StartupAssetHintRuntimeModule.js +9 -0
  161. package/lib/rules/RuleSetCompiler.js +211 -4
  162. package/lib/runtime/AsyncModuleRuntimeModule.js +105 -67
  163. package/lib/runtime/AutoPublicPathRuntimeModule.js +9 -0
  164. package/lib/runtime/BaseUriRuntimeModule.js +9 -0
  165. package/lib/runtime/ChunkNameRuntimeModule.js +9 -0
  166. package/lib/runtime/EnsureChunkRuntimeModule.js +35 -16
  167. package/lib/runtime/GetChunkFilenameRuntimeModule.js +9 -0
  168. package/lib/runtime/GetFullHashRuntimeModule.js +9 -0
  169. package/lib/runtime/GetMainFilenameRuntimeModule.js +9 -0
  170. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +9 -0
  171. package/lib/runtime/GlobalRuntimeModule.js +9 -0
  172. package/lib/runtime/HasOwnPropertyRuntimeModule.js +9 -0
  173. package/lib/runtime/HelperRuntimeModule.js +10 -0
  174. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +338 -217
  175. package/lib/runtime/NonceRuntimeModule.js +9 -0
  176. package/lib/runtime/OnChunksLoadedRuntimeModule.js +67 -20
  177. package/lib/runtime/PublicPathRuntimeModule.js +9 -0
  178. package/lib/runtime/RuntimeIdRuntimeModule.js +9 -0
  179. package/lib/runtime/SpecNamespaceObjectRuntimeModule.js +90 -0
  180. package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +9 -0
  181. package/lib/runtime/StartupEntrypointRuntimeModule.js +9 -0
  182. package/lib/runtime/SystemContextRuntimeModule.js +9 -0
  183. package/lib/runtime/ToBinaryRuntimeModule.js +9 -0
  184. package/lib/schemes/HttpUriPlugin.js +22 -5
  185. package/lib/serialization/FileMiddleware.js +15 -2
  186. package/lib/serialization/ObjectMiddleware.js +138 -106
  187. package/lib/sharing/ConsumeSharedPlugin.js +12 -0
  188. package/lib/sharing/ConsumeSharedRuntimeModule.js +11 -0
  189. package/lib/sharing/ShareRuntimeModule.js +9 -0
  190. package/lib/sharing/declaredShared.js +47 -0
  191. package/lib/stats/DefaultStatsFactoryPlugin.js +3 -1
  192. package/lib/stats/DefaultStatsPrinterPlugin.js +3 -0
  193. package/lib/util/ArrayQueue.js +3 -3
  194. package/lib/util/SourceProcessor.js +76 -69
  195. package/lib/util/URLAbsoluteSpecifier.js +3 -1
  196. package/lib/util/async.js +292 -0
  197. package/lib/util/buildDiagnostics.js +69 -0
  198. package/lib/util/conventions.js +5 -1
  199. package/lib/util/fs.js +27 -1
  200. package/lib/util/handlerKeys.js +40 -0
  201. package/lib/util/identifier.js +20 -0
  202. package/lib/util/internalSerializables.js +6 -0
  203. package/lib/util/registerExternalSerializer.js +6 -45
  204. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +9 -0
  205. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +9 -0
  206. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +9 -0
  207. package/lib/web/JsonpChunkLoadingRuntimeModule.js +36 -0
  208. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +19 -0
  209. package/package.json +22 -16
  210. package/schemas/WebpackOptions.check.js +1 -1
  211. package/schemas/WebpackOptions.json +388 -76
  212. package/schemas/plugins/LoaderOptionsPlugin.check.js +1 -1
  213. package/schemas/plugins/ManifestPlugin.check.js +1 -1
  214. package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
  215. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
  216. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
  217. package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
  218. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  219. package/schemas/plugins/debug/ProfilingPlugin.check.js +1 -1
  220. package/schemas/plugins/dll/DllReferencePlugin.check.js +1 -1
  221. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +1 -1
  222. package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
  223. package/types.d.ts +1440 -331
  224. package/lib/dependencies/ExportBindingInitFragment.js +0 -191
  225. package/lib/errors/EntrypointOverlapWarning.js +0 -45
  226. 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,
@@ -26,7 +24,8 @@ const ResolverFactory = require("./ResolverFactory");
26
24
  const Stats = require("./Stats");
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,7 +1056,7 @@ ${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();
@@ -1029,7 +1078,7 @@ ${other}`);
1029
1078
  ) {
1030
1079
  return doWrite(content);
1031
1080
  }
1032
- return alreadyWritten();
1081
+ return keepExistingFile(stats);
1033
1082
  });
1034
1083
  }
1035
1084
 
@@ -1132,6 +1181,120 @@ ${other}`);
1132
1181
  });
1133
1182
  }
1134
1183
 
1184
+ /**
1185
+ * Gives the file an asset was written to the permissions and the times the
1186
+ * asset carries. A symbolic link never carries either, as both follow it to
1187
+ * its target.
1188
+ * @private
1189
+ * @param {string} targetPath absolute path of the file
1190
+ * @param {AssetInfo} info info of the asset
1191
+ * @param {ErrorCallback} callback signals when the call finishes
1192
+ * @returns {void}
1193
+ */
1194
+ _setAssetFileAttributes(targetPath, info, callback) {
1195
+ const { mode, timestamps } = info;
1196
+ if (mode === undefined && timestamps === undefined) return callback(null);
1197
+ const fs = /** @type {OutputFileSystem} */ (this.outputFileSystem);
1198
+
1199
+ /**
1200
+ * @param {(Error | null)=} err error of the step before
1201
+ * @returns {void}
1202
+ */
1203
+ const setTimestamps = (err) => {
1204
+ if (err) return callback(err);
1205
+ if (timestamps === undefined) return callback(null);
1206
+ if (!fs.utimes) {
1207
+ return callback(
1208
+ new WebpackError(
1209
+ `Unable to set the times of '${targetPath}': the output file system cannot set them`
1210
+ )
1211
+ );
1212
+ }
1213
+ /** @type {NonNullable<OutputFileSystem["utimes"]>} */
1214
+ (fs.utimes)(
1215
+ targetPath,
1216
+ new Date(timestamps.atime),
1217
+ new Date(timestamps.mtime),
1218
+ (err) => callback(err || null)
1219
+ );
1220
+ };
1221
+
1222
+ if (mode === undefined) return setTimestamps();
1223
+ if (!fs.chmod) {
1224
+ return callback(
1225
+ new WebpackError(
1226
+ `Unable to set the permissions of '${targetPath}': the output file system cannot set them`
1227
+ )
1228
+ );
1229
+ }
1230
+ /** @type {NonNullable<OutputFileSystem["chmod"]>} */
1231
+ (fs.chmod)(targetPath, mode, setTimestamps);
1232
+ }
1233
+
1234
+ /**
1235
+ * Creates an asset which is a symbolic link, replacing whatever else is at
1236
+ * its path. An existing link already pointing there is left alone, so a watch
1237
+ * rebuild does not touch it.
1238
+ * @private
1239
+ * @param {Compilation} compilation the compilation
1240
+ * @param {object} asset the asset which is a link
1241
+ * @param {string} asset.file the filename of the asset
1242
+ * @param {Source} asset.source content of the asset, which is what the link points at
1243
+ * @param {string} asset.outputPath absolute path the assets are emitted into
1244
+ * @param {string} asset.targetPath absolute path the link is created at
1245
+ * @param {AssetSymlink} symlink what the link points at
1246
+ * @param {ErrorCallback} callback signals when the call finishes
1247
+ * @returns {void}
1248
+ */
1249
+ _emitSymlink(compilation, asset, symlink, callback) {
1250
+ const { file, source, outputPath, targetPath } = asset;
1251
+ const fs = /** @type {OutputFileSystem} */ (this.outputFileSystem);
1252
+ if (!fs.symlink) {
1253
+ return callback(
1254
+ new WebpackError(
1255
+ `Unable to emit '${file}' as a symbolic link: the output file system cannot create one`
1256
+ )
1257
+ );
1258
+ }
1259
+ const { target, isDirectory } = symlink;
1260
+
1261
+ const created = () => {
1262
+ compilation.emittedAssets.add(file);
1263
+ this.hooks.assetEmitted.callAsync(
1264
+ file,
1265
+ {
1266
+ content: Buffer.from(target, "utf8"),
1267
+ source,
1268
+ outputPath,
1269
+ compilation,
1270
+ targetPath
1271
+ },
1272
+ callback
1273
+ );
1274
+ };
1275
+
1276
+ const create = () => {
1277
+ /** @type {NonNullable<OutputFileSystem["symlink"]>} */
1278
+ (fs.symlink)(target, targetPath, isDirectory ? "dir" : "file", (err) => {
1279
+ if (err) return callback(err);
1280
+ created();
1281
+ });
1282
+ };
1283
+
1284
+ const replace = () => {
1285
+ if (!fs.unlink) return create();
1286
+ /** @type {NonNullable<OutputFileSystem["unlink"]>} */
1287
+ (fs.unlink)(targetPath, () => create());
1288
+ };
1289
+
1290
+ if (!fs.readlink) return replace();
1291
+ /** @type {NonNullable<OutputFileSystem["readlink"]>} */
1292
+ (fs.readlink)(targetPath, (err, existingTarget) => {
1293
+ if (!err && existingTarget === target) return callback(null);
1294
+ replace();
1295
+ });
1296
+ }
1297
+
1135
1298
  /**
1136
1299
  * Processes the provided error callback.
1137
1300
  * @param {ErrorCallback} callback signals when the call finishes
@@ -19,9 +19,10 @@ const {
19
19
  * ExportName as Ids
20
20
  * } from "./optimize/ConcatenatedModule"
21
21
  */
22
- /** @import { Range } from "./javascript/JavascriptParser" */
23
22
 
24
- /** @typedef {{ start: number, end: number, name: string }} ModuleReferenceMatch */
23
+ /** @typedef {{ start: number, end: number, name: string, leaked: boolean }} ModuleReferenceMatch */
24
+
25
+ const MODULE_REFERENCE_TOKEN = "__WEBPACK_MODULE_REFERENCE__";
25
26
 
26
27
  const MODULE_REFERENCE_REGEXP =
27
28
  /^__WEBPACK_MODULE_REFERENCE__(\d+)_([\da-f]+|ns)(_call)?(_directImport)?(_deferredImport)?(_mangleableNs)?(_moduleExportsAccess)?(?:_asiSafe(\d))?__$/;
@@ -33,6 +34,8 @@ const MODULE_REFERENCE_SCAN_REGEXP = new RegExp(
33
34
  "g"
34
35
  );
35
36
 
37
+ const IDENTIFIER_CHARACTER_REGEXP = /[\w$]/;
38
+
36
39
  /** @type {WeakMap<Source, ModuleReferenceMatch[]>} */
37
40
  const moduleReferencesCache = new WeakMap();
38
41
 
@@ -76,10 +79,6 @@ class ConcatenationScope {
76
79
  this.usedNames = usedNames;
77
80
  /** @type {Map<Module, ModuleInfo>} */
78
81
  this._modulesMap = modulesMap;
79
- // written and read by dependency templates within a single code
80
- // generation pass, never across passes
81
- /** @type {Range[] | undefined} */
82
- this._replacedRequireRanges = undefined;
83
82
  }
84
83
 
85
84
  /**
@@ -121,33 +120,6 @@ class ConcatenationScope {
121
120
  return this._currentModule.wrapped;
122
121
  }
123
122
 
124
- /**
125
- * Records a `require(...)` call that was replaced as a whole by a
126
- * concatenation reference, so nothing else rewrites a range inside it.
127
- * @param {Range} range source range of the replaced call
128
- */
129
- registerReplacedRequire(range) {
130
- if (this._replacedRequireRanges === undefined) {
131
- this._replacedRequireRanges = [];
132
- }
133
- this._replacedRequireRanges.push(range);
134
- }
135
-
136
- /**
137
- * Checks whether an offset sits inside an already-replaced `require(...)` call.
138
- * Containment, not exact match: `new require(...)` is replaced from `new`.
139
- * @param {number} start start offset to test
140
- * @returns {boolean} true, when the offset was replaced already
141
- */
142
- isInsideReplacedRequire(start) {
143
- const ranges = this._replacedRequireRanges;
144
- if (ranges === undefined) return false;
145
- for (const [rangeStart, rangeEnd] of ranges) {
146
- if (start >= rangeStart && start < rangeEnd) return true;
147
- }
148
- return false;
149
- }
150
-
151
123
  /**
152
124
  * Records the symbol that should be used when the current module exports a
153
125
  * named binding.
@@ -263,7 +235,22 @@ class ConcatenationScope {
263
235
  }
264
236
 
265
237
  /**
266
- * Finds all encoded module references in a generated source.
238
+ * Checks whether an identifier buries a reference token without being one,
239
+ * which nothing can resolve: it would reach the output as an undeclared global.
240
+ * @param {string} name the identifier
241
+ * @returns {boolean} true, when a reference token is buried in the identifier
242
+ */
243
+ static isLeakedModuleReference(name) {
244
+ return (
245
+ name.includes(MODULE_REFERENCE_TOKEN) &&
246
+ !MODULE_REFERENCE_REGEXP.test(name)
247
+ );
248
+ }
249
+
250
+ /**
251
+ * Finds all encoded module references in a generated source. A match that
252
+ * continues an identifier is reported as `leaked`: it is a token a wider
253
+ * replacement swallowed, so substituting it would rewrite the middle of a name.
267
254
  * @param {Source} source generated source
268
255
  * @returns {ModuleReferenceMatch[]} reference token positions (end is exclusive, excludes the appended "._")
269
256
  */
@@ -279,7 +266,10 @@ class ConcatenationScope {
279
266
  result.push({
280
267
  start: match.index,
281
268
  end: match.index + match[0].length,
282
- name: match[0]
269
+ name: match[0],
270
+ leaked:
271
+ match.index > 0 &&
272
+ IDENTIFIER_CHARACTER_REGEXP.test(code[match.index - 1])
283
273
  });
284
274
  match = MODULE_REFERENCE_SCAN_REGEXP.exec(code);
285
275
  }
@@ -213,6 +213,7 @@ class ContextModule extends Module {
213
213
  * @returns {void}
214
214
  */
215
215
  updateCacheModule(module) {
216
+ super.updateCacheModule(module);
216
217
  const m = /** @type {ContextModule} */ (module);
217
218
  this.resolveDependencies = m.resolveDependencies;
218
219
  this.options = m.options;
@@ -878,7 +879,9 @@ class ContextModule extends Module {
878
879
  }
879
880
  const type =
880
881
  typeof fakeMap === "number" ? fakeMap : fakeMapDataExpression;
881
- return `${asyncDeps} ? ${asyncDeps}.length ? ${RuntimeGlobals.deferredModuleAsyncTransitiveDependencies}(${asyncDeps}).then(${RuntimeGlobals.makeDeferredNamespaceObject}.bind(${RuntimeGlobals.require}, id, ${type} ^ 1, true)) : ${RuntimeGlobals.makeDeferredNamespaceObject}(id, ${type} ^ 1 | 16) : ${source}`;
882
+ // The bound third argument absorbs the promise's resolved value, which
883
+ // would otherwise land in the export-names parameter.
884
+ return `${asyncDeps} ? ${asyncDeps}.length ? ${RuntimeGlobals.deferredModuleAsyncTransitiveDependencies}(${asyncDeps}).then(${RuntimeGlobals.makeDeferredNamespaceObject}.bind(${RuntimeGlobals.require}, id, ${type} ^ 1, undefined)) : ${RuntimeGlobals.makeDeferredNamespaceObject}(id, ${type} ^ 1 | 16) : ${source}`;
882
885
  }
883
886
  return source;
884
887
  }
@@ -1212,60 +1215,11 @@ module.exports = webpackAsyncContext;`;
1212
1215
  }
1213
1216
  const shortMode = hasNoChunk && hasNoModuleDeferred && !hasFakeMap;
1214
1217
  // Sorted before anything is keyed by request, so two items sharing one leave the
1215
- // same last writer in the map and in the loaders beside it.
1218
+ // same last writer in the map.
1216
1219
  const sortedItems = items.sort((a, b) => {
1217
1220
  if (a.userRequest === b.userRequest) return 0;
1218
1221
  return a.userRequest < b.userRequest ? -1 : 1;
1219
1222
  });
1220
- let needEnsureChunk = !hasNoChunk;
1221
- /** @type {Map<string, string[]> | undefined} */
1222
- let loaders;
1223
- // Only module output can name a chunk in an `import()`, so nothing else pays for
1224
- // building the loaders just to throw them away.
1225
- if (!hasNoChunk && runtimeTemplate.isModule()) {
1226
- /** @type {Map<string, string[]>} */
1227
- const perRequest = new Map();
1228
- let hasAnalyzable = false;
1229
- let hasFallback = false;
1230
- /**
1231
- * @param {Chunk} chunk one chunk a request needs
1232
- * @returns {string} a thunk loading it, by literal name where the chunk has one
1233
- */
1234
- const loaderFor = (chunk) => {
1235
- // `.ei` always imports, where `.e` skips a chunk already loaded — the same
1236
- // filter `blockPromise` applies before reaching for it.
1237
- const analyzable =
1238
- chunk.hasRuntime() || chunk.id === null
1239
- ? null
1240
- : runtimeTemplate.analyzableChunkImport(
1241
- chunk,
1242
- "",
1243
- runtimeRequirements,
1244
- this,
1245
- chunkGraph
1246
- );
1247
- if (analyzable !== null) {
1248
- hasAnalyzable = true;
1249
- return runtimeTemplate.returningFunction(analyzable);
1250
- }
1251
- hasFallback = true;
1252
- return runtimeTemplate.returningFunction(
1253
- `${RuntimeGlobals.ensureChunk}(${JSON.stringify(chunk.id)})`
1254
- );
1255
- };
1256
- for (const item of sortedItems) {
1257
- perRequest.set(
1258
- item.userRequest,
1259
- /** @type {Chunk[]} */ (item.chunks).map(loaderFor)
1260
- );
1261
- }
1262
- // Nothing gained when no chunk can be spelled out, and the plain id map is
1263
- // smaller, so the loaders are only written when at least one names its chunk.
1264
- if (hasAnalyzable) {
1265
- loaders = perRequest;
1266
- needEnsureChunk = hasFallback;
1267
- }
1268
- }
1269
1223
  /** @type {Record<string, ModuleId | (ModuleId | FakeMapType | ChunkId[] | (ModuleId[] | undefined))[]>} */
1270
1224
  const map = Object.create(null);
1271
1225
  for (const item of sortedItems) {
@@ -1299,16 +1253,16 @@ module.exports = webpackAsyncContext;`;
1299
1253
  const asyncDepsPosition = hasNoChunk ? chunksPosition : chunksPosition + 1;
1300
1254
  const requestPrefix = hasNoChunk
1301
1255
  ? "Promise.resolve()"
1302
- : loaders !== undefined
1303
- ? hasMultipleOrNoChunks
1304
- ? `Promise.all(ids[${chunksPosition}].map(${runtimeTemplate.returningFunction("load()", "load")}))`
1305
- : `ids[${chunksPosition}][0]()`
1306
- : hasMultipleOrNoChunks
1307
- ? `Promise.all(ids[${chunksPosition}].map(${RuntimeGlobals.ensureChunk}))`
1308
- : `${RuntimeGlobals.ensureChunk}(ids[${chunksPosition}][0])`;
1309
- // Only the id map reads it; nothing loads a chunk when there is none to load, and
1310
- // a map of loaders spells out every one it could reach for.
1311
- if (needEnsureChunk) {
1256
+ : hasMultipleOrNoChunks
1257
+ ? // Wrapped because `map` hands its callback an index too, which the loader
1258
+ // would otherwise read as a fetch priority.
1259
+ `Promise.all(ids[${chunksPosition}].map(${runtimeTemplate.returningFunction(
1260
+ `${RuntimeGlobals.ensureChunk}(id)`,
1261
+ "id"
1262
+ )}))`
1263
+ : `${RuntimeGlobals.ensureChunk}(ids[${chunksPosition}][0])`;
1264
+ // Nothing loads a chunk when there is none to load.
1265
+ if (!hasNoChunk) {
1312
1266
  runtimeRequirements.add(RuntimeGlobals.ensureChunk);
1313
1267
  }
1314
1268
  const returnModuleObject = this.getReturnModuleObjectSource(
@@ -1352,26 +1306,7 @@ function webpackAsyncContext(req) {
1352
1306
  return ${requestPrefix}.then(${runtimeTemplate.returningFunction(returnModuleObject)});
1353
1307
  }`;
1354
1308
 
1355
- // A loader is source, not data, so the map holding one is written out rather than
1356
- // serialized — one entry per line, keeping the request next to what loads it.
1357
- const mapSource =
1358
- loaders === undefined
1359
- ? JSON.stringify(map, null, "\t")
1360
- : `{\n${Object.keys(map)
1361
- .map((request) => {
1362
- const slots =
1363
- /** @type {(ModuleId | FakeMapType | ChunkId[] | (ModuleId[] | undefined))[]} */
1364
- (map[request]).map((slot, index) =>
1365
- index === chunksPosition
1366
- ? `[${/** @type {string[]} */ (loaders.get(request)).join(", ")}]`
1367
- : // An absent `asyncDeps` slot is `null` to `JSON.stringify`.
1368
- slot === undefined
1369
- ? "null"
1370
- : JSON.stringify(slot)
1371
- );
1372
- return `\t${JSON.stringify(request)}: [${slots.join(", ")}]`;
1373
- })
1374
- .join(",\n")}\n}`;
1309
+ const mapSource = JSON.stringify(map, null, "\t");
1375
1310
 
1376
1311
  return `${cst} map = ${mapSource};
1377
1312
  ${webpackAsyncContext}
@@ -1742,6 +1677,7 @@ module.exports = webpackEmptyAsyncContext;`;
1742
1677
  ImportPhaseUtils.isDefer(this.options.phase || ImportPhase.Evaluation)
1743
1678
  ) {
1744
1679
  set.add(RuntimeGlobals.makeDeferredNamespaceObject);
1680
+ set.add(RuntimeGlobals.hasSynthesizedDeferredNamespace);
1745
1681
  }
1746
1682
  }
1747
1683
  return {
@@ -5,12 +5,12 @@
5
5
 
6
6
  "use strict";
7
7
 
8
- const asyncLib = require("neo-async");
9
8
  const { AsyncSeriesWaterfallHook, SyncWaterfallHook } = require("tapable");
10
9
  const ContextModule = require("./ContextModule");
11
10
  const ModuleFactory = require("./ModuleFactory");
12
11
  const ContextElementDependency = require("./dependencies/ContextElementDependency");
13
12
  const LazySet = require("./util/LazySet");
13
+ const asyncLib = require("./util/async");
14
14
  const { cachedSetProperty } = require("./util/cleverMerge");
15
15
  const { createFakeHook } = require("./util/deprecation");
16
16
  const { join } = require("./util/fs");