webpack 5.110.3 → 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 (208) hide show
  1. package/README.md +5 -0
  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/CircularModulesPlugin.js +157 -55
  7. package/lib/CleanPlugin.js +2 -2
  8. package/lib/Compilation.js +320 -302
  9. package/lib/Compiler.js +209 -46
  10. package/lib/ContextModule.js +17 -81
  11. package/lib/ContextModuleFactory.js +1 -1
  12. package/lib/CopyPlugin.js +1054 -0
  13. package/lib/DefinePlugin.js +24 -8
  14. package/lib/ExternalModule.js +41 -14
  15. package/lib/FileSystemInfo.js +17 -14
  16. package/lib/FlagDependencyExportsPlugin.js +45 -21
  17. package/lib/HotModuleReplacementPlugin.js +53 -7
  18. package/lib/JavascriptMetaInfoPlugin.js +5 -3
  19. package/lib/MainTemplate.js +5 -1
  20. package/lib/Module.js +16 -7
  21. package/lib/MultiCompiler.js +1 -1
  22. package/lib/MultiWatching.js +1 -1
  23. package/lib/NormalModule.js +45 -12
  24. package/lib/NormalModuleFactory.js +1 -1
  25. package/lib/RuntimeGlobals.js +21 -7
  26. package/lib/RuntimeModule.js +28 -12
  27. package/lib/RuntimePlugin.js +30 -3
  28. package/lib/RuntimeTemplate.js +780 -475
  29. package/lib/SourceMapDevToolPlugin.js +1 -1
  30. package/lib/Watching.js +9 -0
  31. package/lib/WebpackOptionsApply.js +84 -91
  32. package/lib/asset/AssetGenerator.js +25 -8
  33. package/lib/asset/AssetModule.js +3 -0
  34. package/lib/asset/WebManifestParser.js +7 -5
  35. package/lib/cache/AddBuildDependenciesPlugin.js +33 -4
  36. package/lib/cache/IdleFileCachePlugin.js +2 -2
  37. package/lib/cache/PackFileCacheStrategy.js +14 -1
  38. package/lib/config/browserslistTargetHandler.js +19 -0
  39. package/lib/config/defaults.js +86 -50
  40. package/lib/config/normalization.js +82 -12
  41. package/lib/config/target.js +10 -0
  42. package/lib/container/ContainerReferencePlugin.js +6 -0
  43. package/lib/container/RemoteRuntimeModule.js +9 -0
  44. package/lib/container/declaredRemotes.js +39 -0
  45. package/lib/css/CssGenerator.js +8 -0
  46. package/lib/css/CssInjectStyleRuntimeModule.js +9 -0
  47. package/lib/css/CssLoadingRuntimeModule.js +94 -36
  48. package/lib/css/CssModule.js +1 -1
  49. package/lib/css/CssModulesPlugin.js +7 -6
  50. package/lib/css/CssParser.js +144 -11
  51. package/lib/css/CssServerStylesRuntimeModule.js +9 -0
  52. package/lib/css/cssMinify.js +11 -3
  53. package/lib/css/data.js +2814 -678
  54. package/lib/css/syntax.js +4082 -248
  55. package/lib/debug/ProfilingPlugin.js +4 -0
  56. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -3
  57. package/lib/dependencies/AMDRuntimeModules.js +18 -0
  58. package/lib/dependencies/CommonJsExportRequireDependency.js +3 -1
  59. package/lib/dependencies/CommonJsExportsParserPlugin.js +12 -13
  60. package/lib/dependencies/CommonJsImportsParserPlugin.js +1 -0
  61. package/lib/dependencies/CommonJsPlugin.js +19 -3
  62. package/lib/dependencies/CommonJsRequireDependency.js +14 -5
  63. package/lib/dependencies/CssIcssExportDependency.js +7 -1
  64. package/lib/dependencies/HarmonyCompatibilityDependency.js +58 -4
  65. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +8 -3
  66. package/lib/dependencies/HarmonyExportExpressionDependency.js +44 -29
  67. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +71 -13
  68. package/lib/dependencies/HarmonyExportInitFragment.js +99 -19
  69. package/lib/dependencies/HarmonyExportSpecifierDependency.js +18 -30
  70. package/lib/dependencies/HarmonyImportBareSideEffectDependency.js +59 -0
  71. package/lib/dependencies/HarmonyImportDependency.js +6 -1
  72. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +8 -1
  73. package/lib/dependencies/HarmonyImportSpecifierDependency.js +24 -1
  74. package/lib/dependencies/HarmonyModulesPlugin.js +20 -0
  75. package/lib/dependencies/HtmlEntryDependency.js +50 -0
  76. package/lib/dependencies/ImportMetaMainDependency.js +104 -0
  77. package/lib/dependencies/ImportMetaPlugin.js +59 -15
  78. package/lib/dependencies/SystemRuntimeModule.js +9 -0
  79. package/lib/dependencies/WorkerDependency.js +1 -2
  80. package/lib/dependencies/WorkletDependency.js +1 -2
  81. package/lib/dll/DelegatedModule.js +18 -1
  82. package/lib/dll/DllReferencePlugin.js +11 -8
  83. package/lib/dll/LibManifestPlugin.js +1 -1
  84. package/lib/errors/AnalyzableBailoutsWarning.js +41 -0
  85. package/lib/errors/DuplicateModulesWarning.js +12 -7
  86. package/lib/errors/EmptyCopyPatternWarning.js +26 -0
  87. package/lib/errors/ExternalStarReexportError.js +44 -0
  88. package/lib/errors/MissingSourceMapsWarning.js +36 -0
  89. package/lib/errors/ModuleParseError.js +2 -1
  90. package/lib/errors/UnusedAssetsWarning.js +36 -0
  91. package/lib/errors/UnusedFederationWarning.js +35 -0
  92. package/lib/errors/UnusedModulesWarning.js +38 -0
  93. package/lib/esm/ExportWebpackRequireRuntimeModule.js +9 -0
  94. package/lib/esm/ModuleChunkFormatPlugin.js +28 -3
  95. package/lib/esm/ModuleChunkLoadingPlugin.js +30 -11
  96. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +92 -60
  97. package/lib/hmr/HotModuleReplacement.runtime.js +8 -2
  98. package/lib/hmr/HotModuleReplacementRuntimeModule.js +9 -0
  99. package/lib/html/HtmlGenerator.js +11 -5
  100. package/lib/html/HtmlModulesPlugin.js +331 -62
  101. package/lib/html/HtmlParser.js +13 -6
  102. package/lib/html/builtinEmbeddedRenderer.js +107 -0
  103. package/lib/html/data.js +121 -7
  104. package/lib/html/htmlMinify.js +84 -113
  105. package/lib/html/syntax.js +763 -426
  106. package/lib/ids/HashedModuleIdsPlugin.js +2 -1
  107. package/lib/index.js +3 -0
  108. package/lib/javascript/JavascriptModule.js +1 -0
  109. package/lib/javascript/JavascriptModulesPlugin.js +52 -24
  110. package/lib/javascript/JavascriptParser.js +1255 -728
  111. package/lib/javascript/StartupHelpers.js +27 -3
  112. package/lib/javascript/data.js +172 -0
  113. package/lib/javascript/grammar.js +5546 -0
  114. package/lib/javascript/parser.js +1494 -0
  115. package/lib/javascript/regexp.js +1762 -0
  116. package/lib/javascript/regexpData.js +51 -0
  117. package/lib/javascript/syntax.js +8696 -5225
  118. package/lib/library/ModuleLibraryPlugin.js +116 -5
  119. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +22 -0
  120. package/lib/node/RequireChunkLoadingRuntimeModule.js +22 -0
  121. package/lib/optimize/ConcatenatedModule.js +97 -20
  122. package/lib/optimize/ConstExportsPlugin.js +50 -39
  123. package/lib/optimize/InlineExports.js +20 -123
  124. package/lib/optimize/MangleExportsPlugin.js +10 -0
  125. package/lib/optimize/ModuleConcatenationPlugin.js +24 -1
  126. package/lib/optimize/RealContentHashPlugin.js +68 -9
  127. package/lib/optimize/SideEffectsFlagPlugin.js +17 -9
  128. package/lib/performance/AnalyzableBailoutsPlugin.js +115 -0
  129. package/lib/performance/CacheEffectivenessPlugin.js +4 -3
  130. package/lib/performance/DuplicateModulesPlugin.js +57 -13
  131. package/lib/performance/EvalUsagePlugin.js +5 -2
  132. package/lib/performance/MissingSourceMapsPlugin.js +115 -0
  133. package/lib/performance/PureAnnotationsPlugin.js +6 -3
  134. package/lib/performance/TopLevelThisPlugin.js +5 -4
  135. package/lib/performance/UnusedAssetsPlugin.js +109 -0
  136. package/lib/performance/UnusedFederationPlugin.js +147 -0
  137. package/lib/performance/UnusedModulesPlugin.js +141 -0
  138. package/lib/performance/UnusedReexportsPlugin.js +1 -55
  139. package/lib/performance/isOnlyReexported.js +65 -0
  140. package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +25 -5
  141. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +2 -0
  142. package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +9 -0
  143. package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +9 -0
  144. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +9 -0
  145. package/lib/prefetch/ResourceHintPlugin.js +1 -2
  146. package/lib/prefetch/ResourceHintRuntimeModule.js +9 -0
  147. package/lib/prefetch/StartupAssetHintRuntimeModule.js +9 -0
  148. package/lib/rules/RuleSetCompiler.js +211 -4
  149. package/lib/runtime/AsyncModuleRuntimeModule.js +100 -66
  150. package/lib/runtime/AutoPublicPathRuntimeModule.js +9 -0
  151. package/lib/runtime/BaseUriRuntimeModule.js +9 -0
  152. package/lib/runtime/ChunkNameRuntimeModule.js +9 -0
  153. package/lib/runtime/EnsureChunkRuntimeModule.js +35 -16
  154. package/lib/runtime/GetChunkFilenameRuntimeModule.js +9 -0
  155. package/lib/runtime/GetFullHashRuntimeModule.js +9 -0
  156. package/lib/runtime/GetMainFilenameRuntimeModule.js +9 -0
  157. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +9 -0
  158. package/lib/runtime/GlobalRuntimeModule.js +9 -0
  159. package/lib/runtime/HasOwnPropertyRuntimeModule.js +9 -0
  160. package/lib/runtime/HelperRuntimeModule.js +10 -0
  161. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +330 -219
  162. package/lib/runtime/NonceRuntimeModule.js +9 -0
  163. package/lib/runtime/OnChunksLoadedRuntimeModule.js +67 -20
  164. package/lib/runtime/PublicPathRuntimeModule.js +9 -0
  165. package/lib/runtime/RuntimeIdRuntimeModule.js +9 -0
  166. package/lib/runtime/SpecNamespaceObjectRuntimeModule.js +90 -0
  167. package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +9 -0
  168. package/lib/runtime/StartupEntrypointRuntimeModule.js +9 -0
  169. package/lib/runtime/SystemContextRuntimeModule.js +9 -0
  170. package/lib/runtime/ToBinaryRuntimeModule.js +9 -0
  171. package/lib/serialization/ObjectMiddleware.js +138 -106
  172. package/lib/sharing/ConsumeSharedPlugin.js +12 -0
  173. package/lib/sharing/ConsumeSharedRuntimeModule.js +11 -0
  174. package/lib/sharing/ShareRuntimeModule.js +9 -0
  175. package/lib/sharing/declaredShared.js +47 -0
  176. package/lib/stats/DefaultStatsFactoryPlugin.js +3 -1
  177. package/lib/stats/DefaultStatsPrinterPlugin.js +3 -0
  178. package/lib/util/SourceProcessor.js +76 -69
  179. package/lib/util/async.js +292 -0
  180. package/lib/util/buildDiagnostics.js +69 -0
  181. package/lib/util/fs.js +27 -1
  182. package/lib/util/handlerKeys.js +40 -0
  183. package/lib/util/identifier.js +20 -0
  184. package/lib/util/internalSerializables.js +4 -0
  185. package/lib/util/registerExternalSerializer.js +6 -45
  186. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +9 -0
  187. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +9 -0
  188. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +9 -0
  189. package/lib/web/JsonpChunkLoadingRuntimeModule.js +36 -0
  190. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +19 -0
  191. package/package.json +22 -16
  192. package/schemas/WebpackOptions.check.js +1 -1
  193. package/schemas/WebpackOptions.json +379 -66
  194. package/schemas/plugins/LoaderOptionsPlugin.check.js +1 -1
  195. package/schemas/plugins/ManifestPlugin.check.js +1 -1
  196. package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
  197. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
  198. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
  199. package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
  200. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  201. package/schemas/plugins/debug/ProfilingPlugin.check.js +1 -1
  202. package/schemas/plugins/dll/DllReferencePlugin.check.js +1 -1
  203. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +1 -1
  204. package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
  205. package/types.d.ts +1414 -314
  206. package/lib/dependencies/ExportBindingInitFragment.js +0 -191
  207. package/lib/errors/EntrypointOverlapWarning.js +0 -45
  208. package/lib/performance/EntrypointOverlapPlugin.js +0 -122
@@ -14,9 +14,11 @@ const Template = require("../Template");
14
14
  const HarmonyExportExpressionDependency = require("../dependencies/HarmonyExportExpressionDependency");
15
15
  const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency");
16
16
  const HarmonyExportSpecifierDependency = require("../dependencies/HarmonyExportSpecifierDependency");
17
+ const ExternalStarReexportError = require("../errors/ExternalStarReexportError");
17
18
  const JavascriptModulesPlugin = require("../javascript/JavascriptModulesPlugin");
18
19
  const ConcatenatedModule = require("../optimize/ConcatenatedModule");
19
20
  const { InlinedUsedName } = require("../optimize/InlineExports");
21
+ const { toJsStringLiteral } = require("../util/identifier");
20
22
  const {
21
23
  RESERVED_IDENTIFIER,
22
24
  SAFE_IDENTIFIER,
@@ -44,6 +46,7 @@ const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
44
46
  * ModuleRenderContext
45
47
  * } from "../javascript/JavascriptModulesPlugin"
46
48
  */
49
+ /** @import { ImportAttributes } from "../javascript/JavascriptParser" */
47
50
  /** @import { RuntimeSpec } from "../util/runtime" */
48
51
  /**
49
52
  * @import {
@@ -122,6 +125,18 @@ const definesOnlyNativeExports = (module, moduleGraph) => {
122
125
  const toExportName = (name) =>
123
126
  SAFE_IDENTIFIER.test(name) ? name : JSON.stringify(name);
124
127
 
128
+ /**
129
+ * Renders the import attributes of a reexport in the syntax the author wrote,
130
+ * since a legacy `assert` clause and a `with` clause are not interchangeable.
131
+ * @param {ImportAttributes | undefined} attributes the import attributes
132
+ * @returns {string} the attributes clause, empty when there are none
133
+ */
134
+ const toAttributesClause = (attributes) => {
135
+ if (!attributes) return "";
136
+ const { _isLegacyAssert: isLegacyAssert, ...values } = attributes;
137
+ return ` ${isLegacyAssert ? "assert" : "with"} ${JSON.stringify(values)}`;
138
+ };
139
+
125
140
  /**
126
141
  * Whether the export name can also be used as the declared binding name.
127
142
  * @param {string} name export name
@@ -367,6 +382,7 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
367
382
  }
368
383
  }
369
384
  }
385
+ this._checkStarReexportedExternals(module, compilation);
370
386
  moduleGraph.addExtraReason(module, "used as library export");
371
387
  let entries = libraryEntryModules.get(compilation);
372
388
  if (entries === undefined) {
@@ -376,6 +392,61 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
376
392
  entries.add(module);
377
393
  }
378
394
 
395
+ /**
396
+ * Reports every external the entry star-reexports whose request names a property
397
+ * path, which `export *` has no way to reference.
398
+ * @param {Module} module the library entry module
399
+ * @param {Compilation} compilation the compilation
400
+ * @returns {void}
401
+ */
402
+ _checkStarReexportedExternals(module, compilation) {
403
+ const { moduleGraph } = compilation;
404
+ /** @type {Set<Module>} */
405
+ const visitedReexportModules = new Set([module]);
406
+ /** @type {Module[]} */
407
+ const queue = [module];
408
+ /** @type {Set<ExternalModule>} */
409
+ const unsupportedExternals = new Set();
410
+
411
+ for (const current of queue) {
412
+ for (const connection of moduleGraph.getOutgoingConnections(current)) {
413
+ const dep = connection.dependency;
414
+
415
+ // Only handle star-reexport statement
416
+ if (
417
+ !(dep instanceof HarmonyExportImportedSpecifierDependency) ||
418
+ dep.name !== null
419
+ ) {
420
+ continue;
421
+ }
422
+ const importedModule = connection.resolvedModule;
423
+
424
+ // Only a module providing unknown exports keeps its reexport rendered
425
+ if (
426
+ moduleGraph.getExportsInfo(importedModule)._otherExportsInfo
427
+ .provided !== null
428
+ ) {
429
+ continue;
430
+ }
431
+ if (importedModule instanceof ExternalModule) {
432
+ const request = importedModule.getResolvedRequest();
433
+ if (Array.isArray(request) && request.length > 1) {
434
+ unsupportedExternals.add(importedModule);
435
+ }
436
+ } else if (!visitedReexportModules.has(importedModule)) {
437
+ visitedReexportModules.add(importedModule);
438
+ queue.push(importedModule);
439
+ }
440
+ }
441
+ }
442
+
443
+ for (const externalModule of unsupportedExternals) {
444
+ compilation.errors.push(
445
+ new ExternalStarReexportError(externalModule, module)
446
+ );
447
+ }
448
+ }
449
+
379
450
  /**
380
451
  * Returns preprocess as needed by overriding.
381
452
  * @param {LibraryOptions} library normalized library option
@@ -415,14 +486,17 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
415
486
  ) {
416
487
  const result = new ConcatSource(source);
417
488
  /** @type {Set<string>} */
418
- const moduleRequests = new Set();
489
+ const externalReexports = new Set();
419
490
  /** @type {Map<string, string | InlinedUsedName>} */
420
491
  const unknownProvidedExports = new Map();
492
+ /** @type {Set<Module>} */
493
+ const visitedReexportModules = new Set();
421
494
 
422
495
  /**
423
496
  * Resolves dynamic star reexport.
424
497
  * @param {Module} module the module
425
498
  * @param {boolean} isDynamicReexport if module is dynamic reexported
499
+ * @returns {void}
426
500
  */
427
501
  const resolveDynamicStarReexport = (module, isDynamicReexport) => {
428
502
  for (const connection of moduleGraph.getOutgoingConnections(module)) {
@@ -445,8 +519,22 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
445
519
  ) {
446
520
  // Handle export * from 'external'
447
521
  if (importedModule instanceof ExternalModule) {
448
- moduleRequests.add(importedModule.userRequest);
449
- } else {
522
+ const request = importedModule.getResolvedRequest();
523
+ // A property path is reported by `_checkStarReexportedExternals`,
524
+ // and an absent one by the external's own build
525
+ const specifier =
526
+ typeof request === "string"
527
+ ? request
528
+ : Array.isArray(request) && request.length === 1
529
+ ? request[0]
530
+ : undefined;
531
+ if (specifier !== undefined) {
532
+ externalReexports.add(
533
+ `export * from ${toJsStringLiteral(specifier)}${toAttributesClause(dep.attributes)};\n`
534
+ );
535
+ }
536
+ } else if (!visitedReexportModules.has(importedModule)) {
537
+ visitedReexportModules.add(importedModule);
450
538
  resolveDynamicStarReexport(importedModule, true);
451
539
  }
452
540
  }
@@ -473,8 +561,8 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
473
561
 
474
562
  resolveDynamicStarReexport(module, false);
475
563
 
476
- for (const request of moduleRequests) {
477
- result.add(`export * from "${request}";\n`);
564
+ for (const reexport of externalReexports) {
565
+ result.add(reexport);
478
566
  }
479
567
 
480
568
  for (const [origin, used] of unknownProvidedExports) {
@@ -648,6 +736,29 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
648
736
  }
649
737
  }
650
738
 
739
+ const externalTarget = exportInfo.getTarget(moduleGraph);
740
+ if (
741
+ externalTarget &&
742
+ externalTarget.module instanceof ExternalModule &&
743
+ externalTarget.export &&
744
+ externalTarget.export.length === 1 &&
745
+ codeGenerationResults.has(externalTarget.module, chunk.runtime)
746
+ ) {
747
+ const reexport = codeGenerationResults.getData(
748
+ externalTarget.module,
749
+ chunk.runtime,
750
+ "externalReexport"
751
+ );
752
+ if (reexport) {
753
+ if (!bindingsTakenOver) needExportsDeclaration = true;
754
+ result.add(
755
+ `export { ${toExportName(externalTarget.export[0])} as ${toExportName(originalName)} } ${reexport};\n`
756
+ );
757
+ alreadyRenderedExports.add(originalName);
758
+ continue;
759
+ }
760
+ }
761
+
651
762
  // The exports of entry module are never inlined
652
763
  const usedName =
653
764
  /** @type {string} */
@@ -32,6 +32,28 @@ class ReadFileChunkLoadingRuntimeModule extends RuntimeModule {
32
32
  this.runtimeRequirements = runtimeRequirements;
33
33
  }
34
34
 
35
+ /**
36
+ * The `[handlerMap, key]` pairs this module installs onto a chunk handler map
37
+ * such as `__webpack_require__.f`, or `null` where it cannot name them.
38
+ * @returns {[string, string][] | null} installed chunk handlers (do not mutate)
39
+ */
40
+ getInstalledChunkHandlers() {
41
+ const runtimeRequirements = this.runtimeRequirements;
42
+ /** @type {[string, string][]} */
43
+ const handlers = [];
44
+ if (runtimeRequirements.has(RuntimeGlobals.ensureChunkHandlers)) {
45
+ handlers.push([RuntimeGlobals.ensureChunkHandlers, "readFileVm"]);
46
+ }
47
+ // The hot update flow installs this one onto the same map while it runs.
48
+ if (runtimeRequirements.has(RuntimeGlobals.hmrDownloadUpdateHandlers)) {
49
+ handlers.push([RuntimeGlobals.ensureChunkHandlers, "readFileVmHmr"]);
50
+ }
51
+ if (runtimeRequirements.has(RuntimeGlobals.onChunksLoaded)) {
52
+ handlers.push([RuntimeGlobals.onChunksLoaded, "readFileVm"]);
53
+ }
54
+ return handlers;
55
+ }
56
+
35
57
  /**
36
58
  * Returns generated code.
37
59
  * @private
@@ -32,6 +32,28 @@ class RequireChunkLoadingRuntimeModule extends RuntimeModule {
32
32
  this.runtimeRequirements = runtimeRequirements;
33
33
  }
34
34
 
35
+ /**
36
+ * The `[handlerMap, key]` pairs this module installs onto a chunk handler map
37
+ * such as `__webpack_require__.f`, or `null` where it cannot name them.
38
+ * @returns {[string, string][] | null} installed chunk handlers (do not mutate)
39
+ */
40
+ getInstalledChunkHandlers() {
41
+ const runtimeRequirements = this.runtimeRequirements;
42
+ /** @type {[string, string][]} */
43
+ const handlers = [];
44
+ if (runtimeRequirements.has(RuntimeGlobals.ensureChunkHandlers)) {
45
+ handlers.push([RuntimeGlobals.ensureChunkHandlers, "require"]);
46
+ }
47
+ // The hot update flow installs this one onto the same map while it runs.
48
+ if (runtimeRequirements.has(RuntimeGlobals.hmrDownloadUpdateHandlers)) {
49
+ handlers.push([RuntimeGlobals.ensureChunkHandlers, "requireHmr"]);
50
+ }
51
+ if (runtimeRequirements.has(RuntimeGlobals.onChunksLoaded)) {
52
+ handlers.push([RuntimeGlobals.onChunksLoaded, "require"]);
53
+ }
54
+ return handlers;
55
+ }
56
+
35
57
  /**
36
58
  * Returns generated code.
37
59
  * @private
@@ -34,11 +34,13 @@ const analyzeScope = require("../javascript/ScopeAnalyzer");
34
34
  const {
35
35
  getDeferredCycleModuleIds,
36
36
  getDeferredCycleModules,
37
+ getKnownExportNames,
37
38
  getMakeDeferredNamespaceModeFromExportsType,
38
39
  getOptimizedDeferredModule
39
40
  } = require("../runtime/MakeDeferredNamespaceObjectRuntime");
40
41
  const { equals } = require("../util/ArrayHelpers");
41
42
  const LazySet = require("../util/LazySet");
43
+ const { getBuildDiagnostics } = require("../util/buildDiagnostics");
42
44
  const {
43
45
  compareModulesByFullName,
44
46
  concatComparators
@@ -116,8 +118,7 @@ const { InlinedUsedName } = require("./InlineExports");
116
118
  * @import {
117
119
  * ChunkRenderContext,
118
120
  * Scope,
119
- * Reference,
120
- * Variable
121
+ * Reference
121
122
  * } from "../javascript/JavascriptModulesPlugin"
122
123
  */
123
124
  /** @import { Range } from "../javascript/JavascriptParser" */
@@ -247,6 +248,7 @@ const findIdentifiers = (source) => {
247
248
  * @property {boolean} deferred the module is deferred at least once
248
249
  * @property {boolean} deferredNamespaceObjectUsed deferred namespace object that being used in a not-analyzable way so it must be materialized
249
250
  * @property {string | undefined} deferredNamespaceObjectName deferred namespace object that being used in a not-analyzable way so it must be materialized
251
+ * @property {boolean} specNamespaceObjectUsed an import reads the spec namespace object the module hands out
250
252
  * @property {boolean} interopNamespaceObjectUsed "default-with-named" namespace
251
253
  * @property {string | undefined} interopNamespaceObjectName "default-with-named" namespace
252
254
  * @property {boolean} interopNamespaceObject2Used "default-only" namespace
@@ -423,13 +425,26 @@ const getInteropExpr = (info, interopName) =>
423
425
  * slot, but a wrapped one only runs when its accessor is called, so dropping
424
426
  * the reference would drop the module's side effects with it.
425
427
  * @param {ConcatenatedModuleInfo} info module info
428
+ * @param {boolean | undefined} asiSafe asiSafe
426
429
  * @returns {string} expression evaluating to undefined
427
430
  */
428
- const getUnusedExportExpr = (info) =>
431
+ const getUnusedExportExpr = (info, asiSafe) =>
429
432
  info.wrapped
430
- ? `/* unused export */ (${info.namespaceObjectName}, undefined)`
433
+ ? `${asiSafe === false ? ";" : ""}/* unused export */ (${info.namespaceObjectName}, undefined)`
431
434
  : "/* unused export */ undefined";
432
435
 
436
+ /**
437
+ * Parenthesizes a reference that may already carry an ASI guard of its own,
438
+ * keeping that guard outside the new parentheses — nested it would not parse.
439
+ * @param {string} reference the reference
440
+ * @param {boolean | undefined} asiSafe asiSafe
441
+ * @returns {string} the parenthesized reference
442
+ */
443
+ const parenthesizeReference = (reference, asiSafe) =>
444
+ asiSafe === false
445
+ ? `;(${reference.startsWith(";") ? reference.slice(1) : reference})`
446
+ : `(${reference})`;
447
+
433
448
  /**
434
449
  * @param {ModuleGraph} moduleGraph the module graph
435
450
  * @param {ModuleInfo} info module info
@@ -484,7 +499,7 @@ const getFinalBinding = (
484
499
  if (!usedName) {
485
500
  return {
486
501
  info,
487
- rawName: getUnusedExportExpr(info),
502
+ rawName: getUnusedExportExpr(info, asiSafe),
488
503
  ids: [],
489
504
  exportName
490
505
  };
@@ -667,7 +682,7 @@ const getFinalBinding = (
667
682
  exportName,
668
683
  accessorCall: info.wrapped
669
684
  };
670
- case "external":
685
+ case "external": {
671
686
  if (deferred) {
672
687
  info.deferredNamespaceObjectUsed = true;
673
688
  return {
@@ -677,13 +692,30 @@ const getFinalBinding = (
677
692
  exportName
678
693
  };
679
694
  }
695
+
696
+ // `require()` reads the exports object rather than a namespace, so
697
+ // only an import gets the spec object and interop keeps working.
698
+ const spec =
699
+ !moduleExportsAccess &&
700
+ exportsType === "namespace" &&
701
+ Boolean(
702
+ /** @type {BuildInfo} */
703
+ (info.module.buildInfo).specNamespaceObject
704
+ );
705
+ const rawName = getExternalModuleExpr(info);
706
+
707
+ if (spec) info.specNamespaceObjectUsed = true;
708
+
680
709
  return {
681
710
  info,
682
- rawName: getExternalModuleExpr(info),
711
+ rawName: spec
712
+ ? `${RuntimeGlobals.specNamespaceObject}(${rawName})`
713
+ : rawName,
683
714
  ids: exportName,
684
715
  exportName,
685
- accessorCall: info.wrapped
716
+ accessorCall: spec || info.wrapped
686
717
  };
718
+ }
687
719
  }
688
720
  }
689
721
  const exportsInfo = moduleGraph.getExportsInfo(info.module);
@@ -981,12 +1013,12 @@ const getFinalName = (
981
1013
  ? `;(0,${reference})`
982
1014
  : `/*#__PURE__*/Object(${reference})`;
983
1015
  } else if (binding.info.wrapped) {
984
- return asiSafe === false ? `;(${reference})` : `(${reference})`;
1016
+ return parenthesizeReference(reference, asiSafe);
985
1017
  }
986
1018
  } else if (accessorCall && !asCall) {
987
1019
  // without parentheses `new X()` would construct the accessor rather
988
1020
  // than what it returns
989
- return asiSafe === false ? `;(${reference})` : `(${reference})`;
1021
+ return parenthesizeReference(reference, asiSafe);
990
1022
  }
991
1023
 
992
1024
  return reference;
@@ -1183,15 +1215,17 @@ class ConcatenatedModule extends Module {
1183
1215
 
1184
1216
  for (const m of this._modules) {
1185
1217
  // populate cacheable
1186
- const { cacheable, notCacheableReasons } = /** @type {BuildInfo} */ (
1187
- m.buildInfo
1188
- );
1218
+ const { cacheable, diagnostics } = /** @type {BuildInfo} */ (m.buildInfo);
1189
1219
  if (!cacheable) {
1190
1220
  this.buildInfo.cacheable = false;
1221
+ const notCacheableReasons =
1222
+ diagnostics === undefined
1223
+ ? undefined
1224
+ : diagnostics.notCacheableReasons;
1191
1225
  if (notCacheableReasons) {
1226
+ const own = getBuildDiagnostics(this.buildInfo);
1192
1227
  const reasons =
1193
- this.buildInfo.notCacheableReasons ||
1194
- (this.buildInfo.notCacheableReasons = []);
1228
+ own.notCacheableReasons || (own.notCacheableReasons = []);
1195
1229
  for (const reason of notCacheableReasons) {
1196
1230
  if (!reasons.includes(reason)) reasons.push(reason);
1197
1231
  }
@@ -1821,6 +1855,15 @@ class ConcatenatedModule extends Module {
1821
1855
  return info.escapeNamespaceObjectName;
1822
1856
  }
1823
1857
  const exportsInfo = moduleGraph.getExportsInfo(info.module);
1858
+ // Its names are not mangled, and the wrapped binding is already the
1859
+ // namespace, so a decoupled object would only shadow it.
1860
+ if (
1861
+ /** @type {BuildInfo} */
1862
+ (info.module.buildInfo).specNamespaceObject
1863
+ ) {
1864
+ return undefined;
1865
+ }
1866
+
1824
1867
  let mangled = false;
1825
1868
  for (const exportInfo of exportsInfo.orderedExports) {
1826
1869
  if (exportInfo.provided === false) continue;
@@ -2719,10 +2762,18 @@ ${defineGetters}`
2719
2762
  runtimeRequirements
2720
2763
  });
2721
2764
  const moduleId = JSON.stringify(chunkGraph.getModuleId(info.module));
2765
+ const required = `${RuntimeGlobals.require}(${moduleId})`;
2766
+
2767
+ // The wrapping happens per reference, so only the helper has to be
2768
+ // declared here.
2769
+ if (info.specNamespaceObjectUsed) {
2770
+ runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
2771
+ }
2772
+
2722
2773
  const body =
2723
2774
  condition === "true"
2724
- ? `return ${RuntimeGlobals.require}(${moduleId});`
2725
- : `if (${condition}) return ${RuntimeGlobals.require}(${moduleId});`;
2775
+ ? `return ${required};`
2776
+ : `if (${condition}) return ${required};`;
2726
2777
  result.add(
2727
2778
  `\n// EXTERNAL MODULE: ${info.module.readableIdentifier(
2728
2779
  requestShortener
@@ -2778,14 +2829,31 @@ ${defineGetters}`
2778
2829
  );
2779
2830
  if (info.deferredNamespaceObjectUsed) {
2780
2831
  runtimeRequirements.add(RuntimeGlobals.makeDeferredNamespaceObject);
2832
+ // Every call site for a module must agree on the shape, since the
2833
+ // runtime caches one namespace object per module and mode.
2834
+ const deferredExportsType = getExportsType(
2835
+ moduleGraph,
2836
+ info,
2837
+ strictHarmonyModule
2838
+ );
2839
+ const names = getKnownExportNames(
2840
+ moduleGraph,
2841
+ info.module,
2842
+ deferredExportsType
2843
+ );
2844
+ runtimeRequirements.add(
2845
+ names
2846
+ ? RuntimeGlobals.hasSealedDeferredNamespace
2847
+ : RuntimeGlobals.hasSynthesizedDeferredNamespace
2848
+ );
2781
2849
  result.add(
2782
2850
  `\nvar ${info.deferredNamespaceObjectName} = /*#__PURE__*/${
2783
2851
  RuntimeGlobals.makeDeferredNamespaceObject
2784
2852
  }(${JSON.stringify(
2785
2853
  chunkGraph.getModuleId(info.module)
2786
2854
  )}, ${getMakeDeferredNamespaceModeFromExportsType(
2787
- getExportsType(moduleGraph, info, strictHarmonyModule)
2788
- )});`
2855
+ deferredExportsType
2856
+ )}${names ? `, ${JSON.stringify(names)}` : ""});`
2789
2857
  );
2790
2858
  }
2791
2859
  }
@@ -2871,7 +2939,15 @@ ${defineGetters}`
2871
2939
  // External module bindings may be wrapped in
2872
2940
  // runtime-condition `if` blocks but referenced outside,
2873
2941
  // so they must remain function-scoped (`var`).
2874
- result.add(`var ${info.name} = __webpack_require__(${moduleId});`);
2942
+ const required = `__webpack_require__(${moduleId})`;
2943
+
2944
+ // The wrapping happens per reference, so only the helper has
2945
+ // to be declared here.
2946
+ if (info.specNamespaceObjectUsed) {
2947
+ runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
2948
+ }
2949
+
2950
+ result.add(`var ${info.name} = ${required};`);
2875
2951
 
2876
2952
  // Decoupled namespace object for an escaping mangled external
2877
2953
  // module must come after its import variable is defined.
@@ -3179,6 +3255,7 @@ ${defineGetters}`
3179
3255
  namespaceFnName: undefined,
3180
3256
  escapeNamespaceObjectName: undefined,
3181
3257
  deferredName: undefined,
3258
+ specNamespaceObjectUsed: false,
3182
3259
  interopNamespaceObjectUsed: false,
3183
3260
  interopNamespaceObjectName: undefined,
3184
3261
  interopNamespaceObject2Used: false,
@@ -5,6 +5,7 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ const CircularModulesPlugin = require("../CircularModulesPlugin");
8
9
  const { UsageState } = require("../ExportsInfo");
9
10
  const {
10
11
  JAVASCRIPT_MODULE_TYPE_AUTO,
@@ -15,10 +16,11 @@ const { VariableInfoFlags } = require("../javascript/JavascriptParser");
15
16
  const {
16
17
  InlinedUsedName,
17
18
  enableInlineExports,
18
- findModulesInCycles,
19
19
  toInlinedValue
20
20
  } = require("./InlineExports");
21
21
 
22
+ const { CircularKind } = CircularModulesPlugin;
23
+
22
24
  /** @import { InlinedValue } from "./InlineExports" */
23
25
  /** @import Compiler from "../Compiler" */
24
26
  /** @import ExportsInfo from "../ExportsInfo" */
@@ -162,54 +164,63 @@ class ConstExportsPlugin {
162
164
  enableInlineExports(compilation.moduleGraph);
163
165
 
164
166
  const moduleGraph = compilation.moduleGraph;
165
- compilation.hooks.optimizeDependencies.tap(PLUGIN_NAME, (modules) => {
166
- // A cycle peer may read an export during its temporal dead zone,
167
- // where the binding must throw and a literal would answer.
168
- const inCycle = findModulesInCycles(moduleGraph, modules);
169
- /** @type {Set<ExportsInfo>} */
170
- const visited = new Set();
171
- /** @type {ExportsInfo[]} */
172
- let queue = [];
173
- for (const module of modules) {
174
- if (inCycle.has(module)) continue;
175
- queue.push(moduleGraph.getExportsInfo(module));
176
- }
177
- while (queue.length > 0) {
178
- const items = queue;
179
- queue = [];
180
- for (const exportsInfo of items) {
181
- if (visited.has(exportsInfo)) continue;
182
- visited.add(exportsInfo);
183
- // Other-export usage means we can't safely inline (some non-statically-known consumer)
167
+ // After CircularModulesPlugin (STAGE_DETECT): needs Binding kind flags.
168
+ compilation.hooks.optimizeDependencies.tap(
169
+ {
170
+ name: PLUGIN_NAME,
171
+ stage: CircularModulesPlugin.STAGE_DETECT + 1
172
+ },
173
+ (modules) => {
174
+ /** @type {Set<ExportsInfo>} */
175
+ const visited = new Set();
176
+ /** @type {ExportsInfo[]} */
177
+ let queue = [];
178
+ for (const module of modules) {
179
+ // Binding-observable cycle peers must keep TDZ live bindings.
184
180
  if (
185
- exportsInfo.otherExportsInfo.getUsed(undefined) !==
186
- UsageState.Unused
181
+ CircularModulesPlugin.isCircular(module, CircularKind.Binding)
187
182
  ) {
188
183
  continue;
189
184
  }
190
- for (const exportInfo of exportsInfo.ownedExports) {
191
- const inlined = exportInfo.canInline();
192
- const doInline =
193
- !exportInfo.hasUsedName() &&
194
- inlined !== undefined &&
195
- exportInfo.provided === true;
196
- if (doInline) {
197
- exportInfo.setUsedName(new InlinedUsedName(inlined));
198
- exportsInfo.markInlinedExports();
185
+ queue.push(moduleGraph.getExportsInfo(module));
186
+ }
187
+ while (queue.length > 0) {
188
+ const items = queue;
189
+ queue = [];
190
+ for (const exportsInfo of items) {
191
+ if (visited.has(exportsInfo)) continue;
192
+ visited.add(exportsInfo);
193
+ // Other-export usage means we can't safely inline (some non-statically-known consumer)
194
+ if (
195
+ exportsInfo.otherExportsInfo.getUsed(undefined) !==
196
+ UsageState.Unused
197
+ ) {
198
+ continue;
199
199
  }
200
- if (exportInfo.exportsInfoOwned && exportInfo.exportsInfo) {
201
- const used = exportInfo.getUsed(undefined);
202
- if (
203
- used === UsageState.OnlyPropertiesUsed ||
204
- used === UsageState.Unused
205
- ) {
206
- queue.push(exportInfo.exportsInfo);
200
+ for (const exportInfo of exportsInfo.ownedExports) {
201
+ const inlined = exportInfo.canInline();
202
+ const doInline =
203
+ !exportInfo.hasUsedName() &&
204
+ inlined !== undefined &&
205
+ exportInfo.provided === true;
206
+ if (doInline) {
207
+ exportInfo.setUsedName(new InlinedUsedName(inlined));
208
+ exportsInfo.markInlinedExports();
209
+ }
210
+ if (exportInfo.exportsInfoOwned && exportInfo.exportsInfo) {
211
+ const used = exportInfo.getUsed(undefined);
212
+ if (
213
+ used === UsageState.OnlyPropertiesUsed ||
214
+ used === UsageState.Unused
215
+ ) {
216
+ queue.push(exportInfo.exportsInfo);
217
+ }
207
218
  }
208
219
  }
209
220
  }
210
221
  }
211
222
  }
212
- });
223
+ );
213
224
  }
214
225
  );
215
226
  }