webpack 5.108.4 → 5.109.1

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 (200) hide show
  1. package/bin/webpack.js +12 -0
  2. package/lib/APIPlugin.js +48 -29
  3. package/lib/CacheFacade.js +8 -0
  4. package/lib/ChunkGraph.js +17 -15
  5. package/lib/ChunkGroup.js +1 -0
  6. package/lib/CompatibilityPlugin.js +62 -29
  7. package/lib/Compilation.js +58 -6
  8. package/lib/ConstPlugin.js +11 -11
  9. package/lib/ContextModule.js +239 -6
  10. package/lib/ContextModuleFactory.js +139 -14
  11. package/lib/DefinePlugin.js +433 -112
  12. package/lib/Entrypoint.js +1 -1
  13. package/lib/ExportsInfo.js +22 -5
  14. package/lib/ExportsInfoApiPlugin.js +2 -2
  15. package/lib/ExternalModule.js +107 -5
  16. package/lib/ExternalModuleFactoryPlugin.js +20 -1
  17. package/lib/FileSystemInfo.js +256 -100
  18. package/lib/FlagDependencyUsagePlugin.js +33 -12
  19. package/lib/HotModuleReplacementPlugin.js +18 -15
  20. package/lib/InitFragment.js +20 -32
  21. package/lib/Module.js +3 -0
  22. package/lib/ModuleFilenameHelpers.js +2 -2
  23. package/lib/ModuleTypeConstants.js +8 -1
  24. package/lib/MultiCompiler.js +13 -2
  25. package/lib/MultiWatching.js +1 -0
  26. package/lib/NodeStuffPlugin.js +51 -33
  27. package/lib/NormalModule.js +175 -401
  28. package/lib/NormalModuleFactory.js +76 -2
  29. package/lib/ProgressPlugin.js +211 -119
  30. package/lib/ProvidePlugin.js +2 -2
  31. package/lib/RuntimeGlobals.js +47 -0
  32. package/lib/RuntimePlugin.js +67 -107
  33. package/lib/RuntimeTemplate.js +304 -16
  34. package/lib/Template.js +23 -3
  35. package/lib/UseStrictPlugin.js +1 -1
  36. package/lib/WebpackIsIncludedPlugin.js +1 -1
  37. package/lib/WebpackOptionsApply.js +24 -19
  38. package/lib/asset/AssetGenerator.js +110 -28
  39. package/lib/asset/AssetModulesPlugin.js +92 -2
  40. package/lib/asset/WebManifestGenerator.js +164 -0
  41. package/lib/asset/WebManifestParser.js +130 -0
  42. package/lib/async-modules/AwaitDependenciesInitFragment.js +14 -4
  43. package/lib/async-modules/isGeneratorLowered.js +26 -0
  44. package/lib/cache/PackFileCacheStrategy.js +9 -3
  45. package/lib/config/browserslistTargetHandler.js +40 -0
  46. package/lib/config/defaults.js +219 -29
  47. package/lib/config/normalization.js +26 -0
  48. package/lib/config/target.js +9 -1
  49. package/lib/container/HoistContainerReferencesPlugin.js +47 -55
  50. package/lib/css/CssGenerator.js +40 -31
  51. package/lib/css/CssLoadingRuntimeModule.js +5 -1
  52. package/lib/css/CssModulesPlugin.js +13 -0
  53. package/lib/css/CssParser.js +729 -313
  54. package/lib/css/syntax.js +1371 -861
  55. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -6
  56. package/lib/dependencies/AMDPlugin.js +2 -2
  57. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +13 -13
  58. package/lib/dependencies/CommonJsDependencyHelpers.js +39 -0
  59. package/lib/dependencies/CommonJsExportRequireDependency.js +19 -0
  60. package/lib/dependencies/CommonJsExportsDependency.js +47 -2
  61. package/lib/dependencies/CommonJsExportsParserPlugin.js +10 -10
  62. package/lib/dependencies/CommonJsImportsParserPlugin.js +18 -18
  63. package/lib/dependencies/CommonJsPlugin.js +2 -2
  64. package/lib/dependencies/CommonJsRequireDependency.js +26 -1
  65. package/lib/dependencies/CommonJsSelfReferenceDependency.js +32 -1
  66. package/lib/dependencies/ContextDependencyHelpers.js +3 -3
  67. package/lib/dependencies/CreateRequireParserPlugin.js +6 -6
  68. package/lib/dependencies/CssIcssExportDependency.js +162 -71
  69. package/lib/dependencies/CssUrlDependency.js +35 -4
  70. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +2 -2
  71. package/lib/dependencies/HarmonyCompatibilityDependency.js +32 -14
  72. package/lib/dependencies/HarmonyDetectionParserPlugin.js +43 -13
  73. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +2 -1
  74. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +7 -19
  75. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +17 -9
  76. package/lib/dependencies/HarmonyImportDependency.js +13 -2
  77. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +11 -11
  78. package/lib/dependencies/HarmonyImportSpecifierDependency.js +10 -7
  79. package/lib/dependencies/HarmonyModulesPlugin.js +6 -0
  80. package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +1 -1
  81. package/lib/dependencies/HtmlEntryDependency.js +797 -172
  82. package/lib/dependencies/HtmlSourceDependency.js +26 -0
  83. package/lib/dependencies/ImportDependency.js +43 -1
  84. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +31 -18
  85. package/lib/dependencies/ImportMetaContextPlugin.js +38 -7
  86. package/lib/dependencies/ImportMetaGlobDependency.js +81 -0
  87. package/lib/dependencies/ImportMetaGlobDependencyParserPlugin.js +78 -0
  88. package/lib/dependencies/ImportMetaGlobHelpers.js +660 -0
  89. package/lib/dependencies/ImportMetaPlugin.js +532 -180
  90. package/lib/dependencies/ImportMetaResolveDependency.js +90 -0
  91. package/lib/dependencies/ImportParserPlugin.js +80 -17
  92. package/lib/dependencies/ImportPhase.js +10 -8
  93. package/lib/dependencies/LoaderPlugin.js +5 -1
  94. package/lib/dependencies/RequireContextDependencyParserPlugin.js +1 -1
  95. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +3 -6
  96. package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +4 -11
  97. package/lib/dependencies/SystemPlugin.js +2 -4
  98. package/lib/dependencies/TopLevelAwaitDependency.js +93 -0
  99. package/lib/dependencies/URLDependency.js +141 -21
  100. package/lib/dependencies/{WorkerPlugin.js → WorkerAndWorkletPlugin.js} +324 -112
  101. package/lib/dependencies/WorkerDependency.js +86 -18
  102. package/lib/dependencies/WorkletDependency.js +278 -0
  103. package/lib/dll/DelegatedModuleFactoryPlugin.js +19 -0
  104. package/lib/errors/EnvironmentNotSupportAsyncWarning.js +1 -1
  105. package/lib/errors/LoaderLoadingError.js +20 -0
  106. package/lib/errors/ModuleParseError.js +39 -22
  107. package/lib/errors/NodeStuffInWebError.js +1 -1
  108. package/lib/esm/ModuleChunkFormatPlugin.js +47 -14
  109. package/lib/esm/ModuleChunkLoadingPlugin.js +8 -1
  110. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +29 -1
  111. package/lib/hmr/lazyCompilationBackend.js +51 -12
  112. package/lib/html/HtmlGenerator.js +907 -15
  113. package/lib/html/HtmlModule.js +2 -2
  114. package/lib/html/HtmlModulesPlugin.js +610 -166
  115. package/lib/html/HtmlParser.js +603 -247
  116. package/lib/html/favicon.svg +1 -0
  117. package/lib/html/syntax.js +3451 -2762
  118. package/lib/ids/IdHelpers.js +25 -11
  119. package/lib/index.js +6 -0
  120. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +4 -5
  121. package/lib/javascript/BasicEvaluatedExpression.js +366 -48
  122. package/lib/javascript/JavascriptGenerator.js +197 -49
  123. package/lib/javascript/JavascriptModulesPlugin.js +178 -24
  124. package/lib/javascript/JavascriptParser.js +704 -355
  125. package/lib/javascript/JavascriptParserHelpers.js +3 -6
  126. package/lib/javascript/syntax.js +5037 -0
  127. package/lib/library/ModuleLibraryPlugin.js +38 -1
  128. package/lib/loaders/LoaderRunner.js +714 -0
  129. package/lib/loaders/loadLoader.js +100 -0
  130. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +29 -2
  131. package/lib/node/ReadFileCompileWasmPlugin.js +24 -2
  132. package/lib/optimize/AggressiveMergingPlugin.js +19 -15
  133. package/lib/optimize/ConcatenatedModule.js +139 -31
  134. package/lib/optimize/FlagIncludedChunksPlugin.js +13 -3
  135. package/lib/optimize/InnerGraphPlugin.js +50 -30
  136. package/lib/optimize/ModuleConcatenationPlugin.js +139 -24
  137. package/lib/optimize/SideEffectsFlagPlugin.js +86 -43
  138. package/lib/optimize/SplitChunksPlugin.js +146 -44
  139. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +15 -0
  140. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +24 -13
  141. package/lib/prefetch/ResourceHintPlugin.js +687 -0
  142. package/lib/prefetch/ResourceHintRuntimeModule.js +149 -0
  143. package/lib/prefetch/StartupAssetHintRuntimeModule.js +210 -0
  144. package/lib/prefetch/parseResourceHintOptions.js +103 -0
  145. package/lib/rules/RuleSetCompiler.js +114 -0
  146. package/lib/runtime/AsyncModuleGeneratorRuntimeModule.js +56 -0
  147. package/lib/runtime/AsyncModuleRuntimeModule.js +24 -8
  148. package/lib/runtime/AutoPublicPathRuntimeModule.js +7 -1
  149. package/lib/runtime/CommonJsWrapRuntimeModule.js +37 -0
  150. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +59 -0
  151. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +204 -8
  152. package/lib/runtime/SetAnonymousDefaultNameRuntimeModule.js +4 -1
  153. package/lib/schemes/HttpUriPlugin.js +40 -1
  154. package/lib/schemes/VirtualUrlPlugin.js +1 -2
  155. package/lib/serialization/BinaryMiddleware.js +270 -938
  156. package/lib/serialization/FileMiddleware.js +29 -3
  157. package/lib/stats/DefaultStatsFactoryPlugin.js +229 -194
  158. package/lib/stats/DefaultStatsPresetPlugin.js +2 -0
  159. package/lib/stats/DefaultStatsPrinterPlugin.js +36 -168
  160. package/lib/stats/StatsFactory.js +46 -17
  161. package/lib/url/URLParserPlugin.js +66 -13
  162. package/lib/util/AsyncQueue.js +122 -72
  163. package/lib/util/SetHelpers.js +1 -1
  164. package/lib/util/StackedMap.js +122 -48
  165. package/lib/util/binarySearchBounds.js +2 -2
  166. package/lib/util/concatenate.js +40 -14
  167. package/lib/util/createHooksRegistry.js +13 -5
  168. package/lib/util/dataURL.js +2 -2
  169. package/lib/util/deterministicGrouping.js +7 -5
  170. package/lib/util/formatSize.js +6 -2
  171. package/lib/util/globUtils.js +710 -0
  172. package/lib/util/identifier.js +23 -6
  173. package/lib/util/implicitTypeLoaderFallback.js +62 -0
  174. package/lib/util/internalSerializables.js +88 -71
  175. package/lib/util/magicComment.js +121 -25
  176. package/lib/util/numberHash.js +2 -2
  177. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +24 -18
  178. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +33 -22
  179. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +79 -16
  180. package/lib/web/FetchCompileAsyncWasmPlugin.js +19 -0
  181. package/lib/web/FetchCompileWasmPlugin.js +14 -0
  182. package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -0
  183. package/lib/webpack.js +65 -0
  184. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +3 -0
  185. package/module.d.ts +21 -0
  186. package/package.json +12 -11
  187. package/schemas/WebpackOptions.check.js +1 -1
  188. package/schemas/WebpackOptions.json +759 -36
  189. package/schemas/plugins/HtmlParserOptions.check.js +1 -1
  190. package/schemas/plugins/ProgressPlugin.check.js +1 -1
  191. package/schemas/plugins/ProgressPlugin.json +17 -1
  192. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  193. package/schemas/plugins/container/ContainerReferencePlugin.json +1 -0
  194. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  195. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  196. package/schemas/plugins/container/ModuleFederationPlugin.json +1 -0
  197. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +1 -1
  198. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  199. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  200. package/types.d.ts +1212 -99
@@ -80,6 +80,9 @@ class InnerGraphPlugin {
80
80
  * @param {Expression} sup sup
81
81
  */
82
82
  const onUsageSuper = (sup) => {
83
+ // the callback fires after parsing, when the parser can no
84
+ // longer map offsets — take the location now
85
+ const loc = parser.getLocation(sup);
83
86
  innerGraph.onUsage(parser.state, (usedByExports, module) => {
84
87
  switch (usedByExports) {
85
88
  case undefined:
@@ -90,7 +93,7 @@ class InnerGraphPlugin {
90
93
  /** @type {Range} */
91
94
  (sup.range)
92
95
  );
93
- dep.loc = /** @type {DependencyLocation} */ (sup.loc);
96
+ dep.loc = loc;
94
97
  dep.usedByExports = usedByExports;
95
98
  addPureDependency(module, dep);
96
99
  break;
@@ -205,30 +208,36 @@ class InnerGraphPlugin {
205
208
 
206
209
  // The following hooks are used during prewalking:
207
210
 
208
- parser.hooks.preStatement.tap(PLUGIN_NAME, (statement) => {
209
- if (!innerGraph.isEnabled(parser.state)) return;
211
+ parser.hooks.preStatementByType
212
+ .for("FunctionDeclaration")
213
+ .tap(PLUGIN_NAME, (statement) => {
214
+ if (!innerGraph.isEnabled(parser.state)) return;
210
215
 
211
- if (
212
- parser.scope.topLevelScope === true &&
213
- statement.type === "FunctionDeclaration"
214
- ) {
215
- const name = statement.id ? statement.id.name : "*default*";
216
- const symbol = /** @type {TopLevelSymbol} */ (
217
- innerGraph.tagTopLevelSymbol(
218
- parser,
219
- name,
220
- parser.isPure(
221
- statement,
222
- /** @type {Range} */ (statement.range)[0]
216
+ if (
217
+ parser.scope.topLevelScope === true &&
218
+ statement.type === "FunctionDeclaration"
219
+ ) {
220
+ const name = statement.id ? statement.id.name : "*default*";
221
+ const symbol = /** @type {TopLevelSymbol} */ (
222
+ innerGraph.tagTopLevelSymbol(
223
+ parser,
224
+ name,
225
+ parser.isPure(
226
+ statement,
227
+ /** @type {Range} */ (statement.range)[0]
228
+ )
223
229
  )
224
- )
225
- );
226
- statementWithTopLevelSymbol.set(statement, symbol);
227
- return true;
228
- }
229
- });
230
+ );
231
+ statementWithTopLevelSymbol.set(statement, symbol);
232
+ return true;
233
+ }
234
+ });
230
235
 
231
- parser.hooks.blockPreStatement.tap(PLUGIN_NAME, (statement) => {
236
+ /**
237
+ * @param {import("estree").Statement | import("estree").ModuleDeclaration | import("estree").MaybeNamedFunctionDeclaration | import("estree").MaybeNamedClassDeclaration} statement statement
238
+ * @returns {boolean | void} true when handled
239
+ */
240
+ const blockPreStatementHandler = (statement) => {
232
241
  if (!innerGraph.isEnabled(parser.state)) return;
233
242
 
234
243
  if (parser.scope.topLevelScope === true) {
@@ -288,7 +297,13 @@ class InnerGraphPlugin {
288
297
  }
289
298
  }
290
299
  }
291
- });
300
+ };
301
+ parser.hooks.blockPreStatementByType
302
+ .for("ClassDeclaration")
303
+ .tap(PLUGIN_NAME, blockPreStatementHandler);
304
+ parser.hooks.blockPreStatementByType
305
+ .for("ExportDefaultDeclaration")
306
+ .tap(PLUGIN_NAME, blockPreStatementHandler);
292
307
 
293
308
  parser.hooks.preDeclarator.tap(PLUGIN_NAME, (decl, statement) => {
294
309
  if (!innerGraph.isEnabled(parser.state)) return;
@@ -363,6 +378,9 @@ class InnerGraphPlugin {
363
378
  innerGraph.setTopLevelSymbol(parser.state, symbol);
364
379
  const purePart = statementPurePart.get(statement);
365
380
  if (purePart) {
381
+ // the callback fires after parsing, when the parser can no
382
+ // longer map offsets — take the location now
383
+ const loc = parser.getLocation(statement);
366
384
  innerGraph.onUsage(parser.state, (usedByExports, module) => {
367
385
  switch (usedByExports) {
368
386
  case undefined:
@@ -372,9 +390,7 @@ class InnerGraphPlugin {
372
390
  const dep = new PureExpressionDependency(
373
391
  /** @type {Range} */ (purePart.range)
374
392
  );
375
- dep.loc =
376
- /** @type {DependencyLocation} */
377
- (statement.loc);
393
+ dep.loc = loc;
378
394
  dep.usedByExports = usedByExports;
379
395
  addPureDependency(module, dep);
380
396
  break;
@@ -439,6 +455,9 @@ class InnerGraphPlugin {
439
455
  ) {
440
456
  innerGraph.setTopLevelSymbol(parser.state, symbol);
441
457
  if (element.type !== "MethodDefinition" && element.static) {
458
+ // the callback fires after parsing, when the parser can
459
+ // no longer map offsets — take the location now
460
+ const loc = parser.getLocation(expression);
442
461
  innerGraph.onUsage(
443
462
  parser.state,
444
463
  (usedByExports, module) => {
@@ -450,9 +469,7 @@ class InnerGraphPlugin {
450
469
  const dep = new PureExpressionDependency(
451
470
  /** @type {Range} */ (expression.range)
452
471
  );
453
- dep.loc =
454
- /** @type {DependencyLocation} */
455
- (expression.loc);
472
+ dep.loc = loc;
456
473
  dep.usedByExports = usedByExports;
457
474
  addPureDependency(module, dep);
458
475
  break;
@@ -484,6 +501,9 @@ class InnerGraphPlugin {
484
501
  onUsageSuper(decl.init.superClass);
485
502
  }
486
503
  } else {
504
+ // the callback fires after parsing, when the parser can no
505
+ // longer map offsets — take the location now
506
+ const loc = parser.getLocation(decl);
487
507
  innerGraph.onUsage(parser.state, (usedByExports, module) => {
488
508
  switch (usedByExports) {
489
509
  case undefined:
@@ -496,7 +516,7 @@ class InnerGraphPlugin {
496
516
  (decl.init).range
497
517
  )
498
518
  );
499
- dep.loc = /** @type {DependencyLocation} */ (decl.loc);
519
+ dep.loc = loc;
500
520
  dep.usedByExports = usedByExports;
501
521
  addPureDependency(module, dep);
502
522
  break;
@@ -12,6 +12,9 @@ const Module = require("../Module");
12
12
  const ModuleGraph = require("../ModuleGraph");
13
13
  const { JAVASCRIPT_TYPE } = require("../ModuleSourceTypeConstants");
14
14
  const { STAGE_DEFAULT } = require("../OptimizationStages");
15
+ const CommonJsSelfReferenceDependency = require("../dependencies/CommonJsSelfReferenceDependency");
16
+ const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
17
+ const { ImportPhaseUtils } = require("../dependencies/ImportPhase");
15
18
  const { compareModulesByIdentifier } = require("../util/comparators");
16
19
  const {
17
20
  filterRuntime,
@@ -26,6 +29,7 @@ const ConcatenatedModule = require("./ConcatenatedModule");
26
29
  /** @typedef {import("../Compilation")} Compilation */
27
30
  /** @typedef {import("../Compiler")} Compiler */
28
31
  /** @typedef {import("../Module").BuildInfo} BuildInfo */
32
+ /** @typedef {import("../Module").BuildMeta} BuildMeta */
29
33
  /** @typedef {import("../RequestShortener")} RequestShortener */
30
34
  /** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
31
35
 
@@ -66,6 +70,23 @@ const getMergedModuleRuntime = (chunkGraph, cache, module) => {
66
70
  * @property {number} added
67
71
  */
68
72
 
73
+ /**
74
+ * Record why `module` can't be added (so retried lookups hit the cache), bump
75
+ * the matching statistic, and return the problem to bubble up the recursion.
76
+ * Only reached on failure, so it stays off the hot success path.
77
+ * @param {Map<Module, Problem>} failureCache per-module failure cache
78
+ * @param {Statistics} statistics running statistics
79
+ * @param {keyof Statistics} statKey statistic to increment
80
+ * @param {Module} module the module that couldn't be added
81
+ * @param {Problem} problem the failure to cache and return
82
+ * @returns {Problem} the same problem
83
+ */
84
+ const cacheFailure = (failureCache, statistics, statKey, module, problem) => {
85
+ statistics[statKey]++;
86
+ failureCache.set(module, problem);
87
+ return problem;
88
+ };
89
+
69
90
  /**
70
91
  * Format bailout reason.
71
92
  * @param {string} msg message
@@ -176,9 +197,16 @@ class ModuleConcatenationPlugin {
176
197
  const relevantModules = [];
177
198
  /** @type {Set<Module>} */
178
199
  const possibleInners = new Set();
200
+ const concatenateModules =
201
+ compilation.options.optimization.concatenateModules;
179
202
  const context = {
180
203
  chunkGraph,
181
- moduleGraph
204
+ moduleGraph,
205
+ // commonjs concatenation defaults to on; { commonjs: false } opts out
206
+ concatenateCommonJsModules:
207
+ typeof concatenateModules === "object"
208
+ ? concatenateModules.commonjs !== false
209
+ : concatenateModules === true
182
210
  };
183
211
  const deferEnabled = compilation.options.experiments.deferImport;
184
212
  logger.time("select relevant modules");
@@ -197,7 +225,6 @@ class ModuleConcatenationPlugin {
197
225
  setBailoutReason(module, "Module is async");
198
226
  continue;
199
227
  }
200
-
201
228
  // Must be in strict mode
202
229
  if (!(/** @type {BuildInfo} */ (module.buildInfo).strict)) {
203
230
  setBailoutReason(module, "Module is not in strict mode");
@@ -255,6 +282,16 @@ class ModuleConcatenationPlugin {
255
282
  canBeRoot = false;
256
283
  }
257
284
 
285
+ // A concatenated CommonJS module relies on the root's ESM export
286
+ // rendering, so it can only be an inner module
287
+ if (
288
+ module.type.startsWith("javascript/") &&
289
+ /** @type {BuildMeta} */
290
+ (module.buildMeta).exportsType !== "namespace"
291
+ ) {
292
+ canBeRoot = false;
293
+ }
294
+
258
295
  // Module must not be an entry point
259
296
  if (chunkGraph.isEntryModule(module)) {
260
297
  setInnerBailoutReason(module, "Module is an entry point");
@@ -561,6 +598,26 @@ class ModuleConcatenationPlugin {
561
598
  });
562
599
  }
563
600
 
601
+ /**
602
+ * Checks whether the module `import defer`s a module already in the config.
603
+ * @param {ModuleGraph} moduleGraph the module graph
604
+ * @param {Module} module the candidate module
605
+ * @param {ConcatConfiguration} config the concat configuration
606
+ * @returns {boolean} true when a deferred import targets a module in the config
607
+ */
608
+ _defersModuleIn(moduleGraph, module, config) {
609
+ for (const dep of module.dependencies) {
610
+ if (
611
+ dep instanceof HarmonyImportDependency &&
612
+ ImportPhaseUtils.isDefer(dep.phase)
613
+ ) {
614
+ const target = moduleGraph.getModule(dep);
615
+ if (target && config.has(target)) return true;
616
+ }
617
+ }
618
+ return false;
619
+ }
620
+
564
621
  /**
565
622
  * Returns the imported modules.
566
623
  * @param {Compilation} compilation the compilation
@@ -647,9 +704,37 @@ class ModuleConcatenationPlugin {
647
704
 
648
705
  // Not possible to add?
649
706
  if (!possibleModules.has(module)) {
650
- statistics.invalidModule++;
651
- failureCache.set(module, module); // cache failures for performance
652
- return module;
707
+ return cacheFailure(
708
+ failureCache,
709
+ statistics,
710
+ "invalidModule",
711
+ module,
712
+ module
713
+ );
714
+ }
715
+
716
+ // A deferred import must stay a concatenation boundary: concatenating a
717
+ // module with a module it `import defer`s (a cycle) would erase the
718
+ // deferred namespace's lazy-evaluation and exotic-object semantics.
719
+ if (
720
+ compilation.options.experiments.deferImport &&
721
+ this._defersModuleIn(compilation.moduleGraph, module, config)
722
+ ) {
723
+ /**
724
+ * @param {RequestShortener} requestShortener request shortener
725
+ * @returns {string} problem description
726
+ */
727
+ const problem = (requestShortener) =>
728
+ `Module ${module.readableIdentifier(
729
+ requestShortener
730
+ )} imports a module in this configuration via import defer`;
731
+ return cacheFailure(
732
+ failureCache,
733
+ statistics,
734
+ "incorrectDependency",
735
+ module,
736
+ problem
737
+ );
653
738
  }
654
739
 
655
740
  // Module must be in the correct chunks
@@ -681,9 +766,13 @@ class ModuleConcatenationPlugin {
681
766
  ", "
682
767
  )}, module is in chunk(s) ${chunks.join(", ")})`;
683
768
  };
684
- statistics.incorrectChunks++;
685
- failureCache.set(module, problem); // cache failures for performance
686
- return problem;
769
+ return cacheFailure(
770
+ failureCache,
771
+ statistics,
772
+ "incorrectChunks",
773
+ module,
774
+ problem
775
+ );
687
776
  }
688
777
 
689
778
  const moduleGraph = compilation.moduleGraph;
@@ -722,9 +811,13 @@ class ModuleConcatenationPlugin {
722
811
  : "in an unsupported way"
723
812
  }`;
724
813
  };
725
- statistics.incorrectDependency++;
726
- failureCache.set(module, problem); // cache failures for performance
727
- return problem;
814
+ return cacheFailure(
815
+ failureCache,
816
+ statistics,
817
+ "incorrectDependency",
818
+ module,
819
+ problem
820
+ );
728
821
  }
729
822
  }
730
823
 
@@ -781,9 +874,13 @@ class ModuleConcatenationPlugin {
781
874
  ", "
782
875
  )}`;
783
876
  };
784
- statistics.incorrectChunksOfImporter++;
785
- failureCache.set(module, problem); // cache failures for performance
786
- return problem;
877
+ return cacheFailure(
878
+ failureCache,
879
+ statistics,
880
+ "incorrectChunksOfImporter",
881
+ module,
882
+ problem
883
+ );
787
884
  }
788
885
 
789
886
  /** @type {Map<Module, ReadonlyArray<ModuleGraph.ModuleGraphConnection>>} */
@@ -792,7 +889,13 @@ class ModuleConcatenationPlugin {
792
889
  const selected = connections.filter(
793
890
  (connection) =>
794
891
  !connection.dependency ||
795
- !Dependency.canConcatenate(connection.dependency)
892
+ (!Dependency.canConcatenate(connection.dependency) &&
893
+ // exports self-references of a concatenated CommonJS module
894
+ // are rewritten in place, so they don't block concatenation
895
+ !(
896
+ originModule === module &&
897
+ connection.dependency instanceof CommonJsSelfReferenceDependency
898
+ ))
796
899
  );
797
900
  if (selected.length > 0) {
798
901
  nonHarmonyConnections.set(originModule, connections);
@@ -827,9 +930,13 @@ class ModuleConcatenationPlugin {
827
930
  ", "
828
931
  )}`;
829
932
  };
830
- statistics.incorrectModuleDependency++;
831
- failureCache.set(module, problem); // cache failures for performance
832
- return problem;
933
+ return cacheFailure(
934
+ failureCache,
935
+ statistics,
936
+ "incorrectModuleDependency",
937
+ module,
938
+ problem
939
+ );
833
940
  }
834
941
 
835
942
  if (runtime !== undefined && typeof runtime !== "string") {
@@ -880,9 +987,13 @@ class ModuleConcatenationPlugin {
880
987
  /** @type {RuntimeSpec} */ (runtimeCondition)
881
988
  )})`
882
989
  ).join(", ")}`;
883
- statistics.incorrectRuntimeCondition++;
884
- failureCache.set(module, problem); // cache failures for performance
885
- return problem;
990
+ return cacheFailure(
991
+ failureCache,
992
+ statistics,
993
+ "incorrectRuntimeCondition",
994
+ module,
995
+ problem
996
+ );
886
997
  }
887
998
  }
888
999
 
@@ -915,9 +1026,13 @@ class ModuleConcatenationPlugin {
915
1026
  );
916
1027
  if (problem) {
917
1028
  if (backup !== undefined) config.rollback(backup);
918
- statistics.importerFailed++;
919
- failureCache.set(module, problem); // cache failures for performance
920
- return problem;
1029
+ return cacheFailure(
1030
+ failureCache,
1031
+ statistics,
1032
+ "importerFailed",
1033
+ module,
1034
+ problem
1035
+ );
921
1036
  }
922
1037
  }
923
1038
 
@@ -13,7 +13,9 @@ const {
13
13
  } = require("../ModuleTypeConstants");
14
14
  const { STAGE_DEFAULT } = require("../OptimizationStages");
15
15
  const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency");
16
+ const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
16
17
  const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency");
18
+ const { ImportPhaseUtils } = require("../dependencies/ImportPhase");
17
19
  const formatLocation = require("../util/formatLocation");
18
20
  const { CompilerHintNotationRegExp } = require("../util/magicComment");
19
21
 
@@ -48,6 +50,20 @@ const { CompilerHintNotationRegExp } = require("../util/magicComment");
48
50
 
49
51
  /** @typedef {Map<string, RegExp>} CacheItem */
50
52
 
53
+ /**
54
+ * Whether a resolved re-export target is reached through an `import defer` edge.
55
+ * Such edges must not be collapsed by the side-effect-free barrel optimization:
56
+ * the source module has to keep being reached through the barrel's cached
57
+ * deferred namespace so deferred-namespace identity and evaluation semantics are
58
+ * preserved.
59
+ * @param {ModuleGraphConnection | undefined} connection the target connection
60
+ * @returns {boolean} true when the target connection is a deferred import
61
+ */
62
+ const isDeferredTargetConnection = (connection) =>
63
+ connection !== undefined &&
64
+ connection.dependency instanceof HarmonyImportDependency &&
65
+ ImportPhaseUtils.isDefer(connection.dependency.phase);
66
+
51
67
  /** @type {WeakMap<Compiler, CacheItem>} */
52
68
  const globToRegexpCache = new WeakMap();
53
69
 
@@ -305,13 +321,14 @@ class SideEffectsFlagPlugin {
305
321
  /** @type {BuildMeta} */
306
322
  (parser.state.module.buildMeta).sideEffectFree = true;
307
323
  } else {
308
- const { loc, type } = sideEffectsStatement;
324
+ const type = sideEffectsStatement.type;
325
+ const loc = parser.getLocation(sideEffectsStatement);
309
326
  moduleGraph
310
327
  .getOptimizationBailout(parser.state.module)
311
328
  .push(
312
329
  () =>
313
330
  `Statement (${type}) with side effects in source code at ${formatLocation(
314
- /** @type {DependencyLocation} */ (loc)
331
+ loc
315
332
  )}`
316
333
  );
317
334
  }
@@ -354,32 +371,34 @@ class SideEffectsFlagPlugin {
354
371
  // 2. export function foo
355
372
  // 3. export default function foo
356
373
  // 4. export default function / export default () => {} (anonymous)
357
- parser.hooks.preStatement.tap(PLUGIN_NAME, (statement) => {
358
- if (parser.scope.topLevelScope !== true) return;
359
- if (statement.type !== "FunctionDeclaration") {
360
- return;
361
- }
362
- const name = statement.id ? statement.id.name : "default";
363
- if (
364
- pureFunctionsFromOption &&
365
- pureFunctionsFromOption.has(name)
366
- ) {
367
- markPure(name);
368
- return;
369
- }
370
- const commentsStart = parser.prevStatement
371
- ? /** @type {Range} */ (parser.prevStatement.range)[1]
372
- : 0;
373
- if (
374
- hasNoSideEffectsNotation(
375
- parser,
376
- commentsStart,
377
- /** @type {Range} */ (statement.range)[0]
378
- )
379
- ) {
380
- markPure(name);
381
- }
382
- });
374
+ parser.hooks.preStatementByType
375
+ .for("FunctionDeclaration")
376
+ .tap(PLUGIN_NAME, (statement) => {
377
+ if (parser.scope.topLevelScope !== true) return;
378
+ if (statement.type !== "FunctionDeclaration") {
379
+ return;
380
+ }
381
+ const name = statement.id ? statement.id.name : "default";
382
+ if (
383
+ pureFunctionsFromOption &&
384
+ pureFunctionsFromOption.has(name)
385
+ ) {
386
+ markPure(name);
387
+ return;
388
+ }
389
+ const commentsStart = parser.prevStatement
390
+ ? /** @type {Range} */ (parser.prevStatement.range)[1]
391
+ : 0;
392
+ if (
393
+ hasNoSideEffectsNotation(
394
+ parser,
395
+ commentsStart,
396
+ /** @type {Range} */ (statement.range)[0]
397
+ )
398
+ ) {
399
+ markPure(name);
400
+ }
401
+ });
383
402
 
384
403
  // Detect on variable declarations with function init
385
404
  parser.hooks.preDeclarator.tap(PLUGIN_NAME, (decl, statement) => {
@@ -421,21 +440,23 @@ class SideEffectsFlagPlugin {
421
440
  });
422
441
 
423
442
  if (pureFunctionsFromOption) {
424
- parser.hooks.blockPreStatement.tap(PLUGIN_NAME, (statement) => {
425
- if (parser.scope.topLevelScope !== true) return;
426
- if (
427
- statement.type === "ExportDefaultDeclaration" &&
428
- pureFunctionsFromOption.has("default")
429
- ) {
430
- const decl = statement.declaration;
443
+ parser.hooks.blockPreStatementByType
444
+ .for("ExportDefaultDeclaration")
445
+ .tap(PLUGIN_NAME, (statement) => {
446
+ if (parser.scope.topLevelScope !== true) return;
431
447
  if (
432
- decl.type === "ArrowFunctionExpression" ||
433
- decl.type === "FunctionExpression"
448
+ statement.type === "ExportDefaultDeclaration" &&
449
+ pureFunctionsFromOption.has("default")
434
450
  ) {
435
- markPure("default");
451
+ const decl = statement.declaration;
452
+ if (
453
+ decl.type === "ArrowFunctionExpression" ||
454
+ decl.type === "FunctionExpression"
455
+ ) {
456
+ markPure("default");
457
+ }
436
458
  }
437
- }
438
- });
459
+ });
439
460
  }
440
461
 
441
462
  parser.hooks.isPure
@@ -500,6 +521,11 @@ class SideEffectsFlagPlugin {
500
521
  /** @type {Set<Module>} */
501
522
  const optimizedModules = new Set();
502
523
 
524
+ // Only defer builds must protect deferred re-export barrels;
525
+ // skip the per-target check entirely otherwise.
526
+ const deferEnabled =
527
+ compilation.options.experiments.deferImport === true;
528
+
503
529
  // Re-export resolution is idempotent within a pass, so cache it
504
530
  // per export info: a shared barrel imported by many modules
505
531
  // resolves each name once instead of once per consumer.
@@ -581,13 +607,18 @@ class SideEffectsFlagPlugin {
581
607
 
582
608
  exportInfo.moveTarget(
583
609
  moduleGraph,
584
- ({ module }) =>
585
- module.getSideEffectsConnectionState(
610
+ (candidate) =>
611
+ candidate.module.getSideEffectsConnectionState(
586
612
  moduleGraph
587
613
  ) === false &&
614
+ // Keep a deferred re-export's barrel (see below).
615
+ (!deferEnabled ||
616
+ !isDeferredTargetConnection(
617
+ candidate.connection
618
+ )) &&
588
619
  (Boolean(dep.name) ||
589
620
  hasSingleStarReexport(
590
- /** @type {Module} */ (module)
621
+ /** @type {Module} */ (candidate.module)
591
622
  )),
592
623
  ({
593
624
  module: newModule,
@@ -639,6 +670,18 @@ class SideEffectsFlagPlugin {
639
670
  }
640
671
  if (!target) continue;
641
672
 
673
+ // A deferred re-export must keep its side-effect-free
674
+ // barrel: collapsing it here would turn the cached
675
+ // deferred namespace (`.z`) into an eager import of the
676
+ // source module, breaking deferred-namespace identity
677
+ // and evaluation semantics.
678
+ if (
679
+ deferEnabled &&
680
+ isDeferredTargetConnection(target.connection)
681
+ ) {
682
+ continue;
683
+ }
684
+
642
685
  moduleGraph.updateModule(dep, target.module);
643
686
  moduleGraph.updateParent(
644
687
  dep,