webpack 5.108.4 → 5.109.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 (186) hide show
  1. package/lib/APIPlugin.js +48 -29
  2. package/lib/CacheFacade.js +8 -0
  3. package/lib/ChunkGroup.js +1 -0
  4. package/lib/CompatibilityPlugin.js +31 -29
  5. package/lib/Compilation.js +49 -4
  6. package/lib/ConstPlugin.js +11 -11
  7. package/lib/ContextModule.js +239 -6
  8. package/lib/ContextModuleFactory.js +139 -14
  9. package/lib/DefinePlugin.js +396 -101
  10. package/lib/Entrypoint.js +1 -1
  11. package/lib/ExportsInfoApiPlugin.js +2 -2
  12. package/lib/ExternalModule.js +107 -5
  13. package/lib/ExternalModuleFactoryPlugin.js +20 -1
  14. package/lib/FileSystemInfo.js +130 -74
  15. package/lib/HotModuleReplacementPlugin.js +18 -15
  16. package/lib/Module.js +3 -0
  17. package/lib/ModuleFilenameHelpers.js +2 -2
  18. package/lib/ModuleTypeConstants.js +8 -1
  19. package/lib/MultiCompiler.js +13 -2
  20. package/lib/MultiWatching.js +1 -0
  21. package/lib/NodeStuffPlugin.js +51 -33
  22. package/lib/NormalModule.js +169 -401
  23. package/lib/NormalModuleFactory.js +76 -2
  24. package/lib/ProgressPlugin.js +211 -119
  25. package/lib/ProvidePlugin.js +2 -2
  26. package/lib/RuntimeGlobals.js +47 -0
  27. package/lib/RuntimePlugin.js +33 -0
  28. package/lib/RuntimeTemplate.js +304 -16
  29. package/lib/UseStrictPlugin.js +1 -1
  30. package/lib/WebpackIsIncludedPlugin.js +1 -1
  31. package/lib/WebpackOptionsApply.js +24 -19
  32. package/lib/asset/AssetGenerator.js +110 -28
  33. package/lib/asset/AssetModulesPlugin.js +92 -2
  34. package/lib/asset/WebManifestGenerator.js +164 -0
  35. package/lib/asset/WebManifestParser.js +130 -0
  36. package/lib/async-modules/AwaitDependenciesInitFragment.js +14 -4
  37. package/lib/async-modules/isGeneratorLowered.js +26 -0
  38. package/lib/cache/PackFileCacheStrategy.js +9 -3
  39. package/lib/config/browserslistTargetHandler.js +40 -0
  40. package/lib/config/defaults.js +219 -29
  41. package/lib/config/normalization.js +26 -0
  42. package/lib/config/target.js +9 -1
  43. package/lib/css/CssGenerator.js +40 -31
  44. package/lib/css/CssLoadingRuntimeModule.js +5 -1
  45. package/lib/css/CssModulesPlugin.js +13 -0
  46. package/lib/css/CssParser.js +594 -263
  47. package/lib/css/syntax.js +875 -462
  48. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -6
  49. package/lib/dependencies/AMDPlugin.js +2 -2
  50. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +13 -13
  51. package/lib/dependencies/CommonJsDependencyHelpers.js +39 -0
  52. package/lib/dependencies/CommonJsExportsDependency.js +47 -2
  53. package/lib/dependencies/CommonJsExportsParserPlugin.js +10 -10
  54. package/lib/dependencies/CommonJsImportsParserPlugin.js +18 -18
  55. package/lib/dependencies/CommonJsPlugin.js +2 -2
  56. package/lib/dependencies/CommonJsRequireDependency.js +26 -1
  57. package/lib/dependencies/CommonJsSelfReferenceDependency.js +32 -1
  58. package/lib/dependencies/ContextDependencyHelpers.js +3 -3
  59. package/lib/dependencies/CreateRequireParserPlugin.js +6 -6
  60. package/lib/dependencies/CssIcssExportDependency.js +162 -71
  61. package/lib/dependencies/CssUrlDependency.js +35 -4
  62. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +2 -2
  63. package/lib/dependencies/HarmonyCompatibilityDependency.js +32 -14
  64. package/lib/dependencies/HarmonyDetectionParserPlugin.js +43 -13
  65. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +7 -19
  66. package/lib/dependencies/HarmonyImportDependency.js +12 -1
  67. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +11 -11
  68. package/lib/dependencies/HarmonyModulesPlugin.js +6 -0
  69. package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +1 -1
  70. package/lib/dependencies/HtmlEntryDependency.js +797 -172
  71. package/lib/dependencies/HtmlSourceDependency.js +26 -0
  72. package/lib/dependencies/ImportDependency.js +43 -1
  73. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +31 -18
  74. package/lib/dependencies/ImportMetaContextPlugin.js +38 -7
  75. package/lib/dependencies/ImportMetaGlobDependency.js +81 -0
  76. package/lib/dependencies/ImportMetaGlobDependencyParserPlugin.js +78 -0
  77. package/lib/dependencies/ImportMetaGlobHelpers.js +660 -0
  78. package/lib/dependencies/ImportMetaPlugin.js +532 -180
  79. package/lib/dependencies/ImportMetaResolveDependency.js +90 -0
  80. package/lib/dependencies/ImportParserPlugin.js +80 -17
  81. package/lib/dependencies/ImportPhase.js +10 -8
  82. package/lib/dependencies/LoaderPlugin.js +5 -1
  83. package/lib/dependencies/RequireContextDependencyParserPlugin.js +1 -1
  84. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +3 -6
  85. package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +4 -11
  86. package/lib/dependencies/SystemPlugin.js +2 -4
  87. package/lib/dependencies/TopLevelAwaitDependency.js +93 -0
  88. package/lib/dependencies/URLDependency.js +141 -21
  89. package/lib/dependencies/{WorkerPlugin.js → WorkerAndWorkletPlugin.js} +324 -112
  90. package/lib/dependencies/WorkerDependency.js +86 -18
  91. package/lib/dependencies/WorkletDependency.js +278 -0
  92. package/lib/dll/DelegatedModuleFactoryPlugin.js +19 -0
  93. package/lib/errors/EnvironmentNotSupportAsyncWarning.js +1 -1
  94. package/lib/errors/LoaderLoadingError.js +20 -0
  95. package/lib/errors/ModuleParseError.js +39 -22
  96. package/lib/errors/NodeStuffInWebError.js +1 -1
  97. package/lib/esm/ModuleChunkFormatPlugin.js +47 -14
  98. package/lib/esm/ModuleChunkLoadingPlugin.js +8 -1
  99. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +29 -1
  100. package/lib/hmr/lazyCompilationBackend.js +32 -8
  101. package/lib/html/HtmlGenerator.js +887 -15
  102. package/lib/html/HtmlModule.js +2 -2
  103. package/lib/html/HtmlModulesPlugin.js +610 -166
  104. package/lib/html/HtmlParser.js +603 -247
  105. package/lib/html/favicon.svg +1 -0
  106. package/lib/html/syntax.js +1264 -661
  107. package/lib/ids/IdHelpers.js +1 -1
  108. package/lib/index.js +6 -0
  109. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +4 -5
  110. package/lib/javascript/BasicEvaluatedExpression.js +366 -48
  111. package/lib/javascript/JavascriptGenerator.js +197 -49
  112. package/lib/javascript/JavascriptModulesPlugin.js +178 -24
  113. package/lib/javascript/JavascriptParser.js +701 -355
  114. package/lib/javascript/JavascriptParserHelpers.js +3 -6
  115. package/lib/javascript/syntax.js +4380 -0
  116. package/lib/library/ModuleLibraryPlugin.js +38 -1
  117. package/lib/loaders/LoaderRunner.js +714 -0
  118. package/lib/loaders/loadLoader.js +100 -0
  119. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +19 -0
  120. package/lib/node/ReadFileCompileWasmPlugin.js +14 -0
  121. package/lib/optimize/ConcatenatedModule.js +120 -16
  122. package/lib/optimize/FlagIncludedChunksPlugin.js +13 -3
  123. package/lib/optimize/InnerGraphPlugin.js +50 -30
  124. package/lib/optimize/ModuleConcatenationPlugin.js +69 -3
  125. package/lib/optimize/SideEffectsFlagPlugin.js +86 -43
  126. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +15 -0
  127. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +24 -13
  128. package/lib/prefetch/ResourceHintPlugin.js +663 -0
  129. package/lib/prefetch/ResourceHintRuntimeModule.js +149 -0
  130. package/lib/prefetch/StartupAssetHintRuntimeModule.js +210 -0
  131. package/lib/prefetch/parseResourceHintOptions.js +103 -0
  132. package/lib/rules/RuleSetCompiler.js +114 -0
  133. package/lib/runtime/AsyncModuleGeneratorRuntimeModule.js +56 -0
  134. package/lib/runtime/AsyncModuleRuntimeModule.js +24 -8
  135. package/lib/runtime/AutoPublicPathRuntimeModule.js +7 -1
  136. package/lib/runtime/CommonJsWrapRuntimeModule.js +37 -0
  137. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +59 -0
  138. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +204 -8
  139. package/lib/runtime/SetAnonymousDefaultNameRuntimeModule.js +4 -1
  140. package/lib/schemes/HttpUriPlugin.js +40 -1
  141. package/lib/schemes/VirtualUrlPlugin.js +1 -2
  142. package/lib/serialization/FileMiddleware.js +29 -3
  143. package/lib/stats/DefaultStatsFactoryPlugin.js +32 -3
  144. package/lib/stats/DefaultStatsPresetPlugin.js +2 -0
  145. package/lib/stats/DefaultStatsPrinterPlugin.js +12 -2
  146. package/lib/stats/StatsFactory.js +15 -8
  147. package/lib/url/URLParserPlugin.js +66 -13
  148. package/lib/util/AsyncQueue.js +122 -72
  149. package/lib/util/SetHelpers.js +1 -1
  150. package/lib/util/StackedMap.js +122 -48
  151. package/lib/util/binarySearchBounds.js +2 -2
  152. package/lib/util/concatenate.js +40 -14
  153. package/lib/util/createHooksRegistry.js +13 -5
  154. package/lib/util/dataURL.js +2 -2
  155. package/lib/util/deterministicGrouping.js +7 -5
  156. package/lib/util/formatSize.js +6 -2
  157. package/lib/util/globUtils.js +710 -0
  158. package/lib/util/identifier.js +23 -6
  159. package/lib/util/implicitTypeLoaderFallback.js +62 -0
  160. package/lib/util/internalSerializables.js +88 -71
  161. package/lib/util/magicComment.js +121 -25
  162. package/lib/util/numberHash.js +2 -2
  163. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +24 -18
  164. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +33 -22
  165. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +79 -16
  166. package/lib/web/FetchCompileAsyncWasmPlugin.js +19 -0
  167. package/lib/web/FetchCompileWasmPlugin.js +14 -0
  168. package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -0
  169. package/lib/webpack.js +65 -0
  170. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +3 -0
  171. package/module.d.ts +21 -0
  172. package/package.json +13 -12
  173. package/schemas/WebpackOptions.check.js +1 -1
  174. package/schemas/WebpackOptions.json +759 -36
  175. package/schemas/plugins/HtmlParserOptions.check.js +1 -1
  176. package/schemas/plugins/ProgressPlugin.check.js +1 -1
  177. package/schemas/plugins/ProgressPlugin.json +17 -1
  178. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  179. package/schemas/plugins/container/ContainerReferencePlugin.json +1 -0
  180. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  181. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  182. package/schemas/plugins/container/ModuleFederationPlugin.json +1 -0
  183. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +1 -1
  184. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  185. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  186. package/types.d.ts +1213 -96
@@ -98,7 +98,7 @@ class CreateRequireParserPlugin {
98
98
  "undefined",
99
99
  /** @type {Range} */ (expr.range)
100
100
  );
101
- dep.loc = /** @type {DependencyLocation} */ (expr.loc);
101
+ dep.loc = parser.getLocation(expr);
102
102
  parser.state.module.addPresentationalDependency(dep);
103
103
  return false;
104
104
  };
@@ -161,7 +161,7 @@ class CreateRequireParserPlugin {
161
161
  const err = new WebpackError(
162
162
  "module.createRequire supports only one argument."
163
163
  );
164
- err.loc = /** @type {DependencyLocation} */ (expr.loc);
164
+ err.loc = parser.getLocation(expr);
165
165
  parser.state.module.addWarning(err);
166
166
  return;
167
167
  }
@@ -171,7 +171,7 @@ class CreateRequireParserPlugin {
171
171
  const err = new WebpackError(
172
172
  "module.createRequire failed parsing argument."
173
173
  );
174
- err.loc = /** @type {DependencyLocation} */ (arg.loc);
174
+ err.loc = parser.getLocation(arg);
175
175
  parser.state.module.addWarning(err);
176
176
  return;
177
177
  }
@@ -249,7 +249,7 @@ class CreateRequireParserPlugin {
249
249
  : "",
250
250
  /** @type {Range} */ (statement.range)
251
251
  );
252
- clearDep.loc = /** @type {DependencyLocation} */ (statement.loc);
252
+ clearDep.loc = parser.getLocation(statement);
253
253
  parser.state.module.addPresentationalDependency(clearDep);
254
254
  parser.unsetAsiPosition(/** @type {Range} */ (statement.range)[1]);
255
255
  return true;
@@ -342,7 +342,7 @@ class CreateRequireParserPlugin {
342
342
  "/* createRequire */ undefined",
343
343
  /** @type {Range} */ (expr.range)
344
344
  );
345
- clearDep.loc = /** @type {DependencyLocation} */ (expr.loc);
345
+ clearDep.loc = parser.getLocation(expr);
346
346
  parser.state.module.addPresentationalDependency(clearDep);
347
347
  return true;
348
348
  });
@@ -353,7 +353,7 @@ class CreateRequireParserPlugin {
353
353
  "/* createRequire() */ undefined",
354
354
  /** @type {Range} */ (expr.range)
355
355
  );
356
- clearDep.loc = /** @type {DependencyLocation} */ (expr.loc);
356
+ clearDep.loc = parser.getLocation(expr);
357
357
  parser.state.module.addPresentationalDependency(clearDep);
358
358
  return true;
359
359
  });
@@ -292,6 +292,28 @@ class CssIcssExportDependency extends NullDependency {
292
292
  this.entries = entries;
293
293
  /** @type {undefined | string} */
294
294
  this._hashUpdate = undefined;
295
+ /** @type {undefined | Map<string, CssExportEntry[]>} lazily-built `name -> entries` index, reused across every importer's codegen */
296
+ this._entriesByName = undefined;
297
+ }
298
+
299
+ /**
300
+ * The `entries` grouped by export name, built once and reused. `entries` is
301
+ * immutable after construction/deserialization, so this stays valid for the
302
+ * dependency's lifetime (the composes/`@value` target of many importers).
303
+ * @returns {Map<string, CssExportEntry[]>} entries grouped by export name
304
+ */
305
+ getEntriesByName() {
306
+ if (this._entriesByName === undefined) {
307
+ /** @type {Map<string, CssExportEntry[]>} */
308
+ const map = new Map();
309
+ for (const e of this.entries) {
310
+ const list = map.get(e.name);
311
+ if (list) list.push(e);
312
+ else map.set(e.name, [e]);
313
+ }
314
+ this._entriesByName = map;
315
+ }
316
+ return this._entriesByName;
295
317
  }
296
318
 
297
319
  get type() {
@@ -506,53 +528,131 @@ class CssIcssExportDependency extends NullDependency {
506
528
  }
507
529
  this.entries = entries;
508
530
  this._hashUpdate = undefined;
531
+ this._entriesByName = undefined;
509
532
  super.deserialize(context);
510
533
  }
511
534
  }
512
535
 
513
536
  /**
514
- * Get (or lazily build into `indexCache`) a name -> entries index for `dep`,
515
- * so composes resolution does a Map lookup instead of scanning all entries per
516
- * reference. The cache is owned by one `apply` call and GC'd with it.
517
- * @param {Map<CssIcssExportDependency, Map<string, CssExportEntry[]>>} indexCache transient cache
518
- * @param {CssIcssExportDependency} dep export dependency
519
- * @returns {Map<string, CssExportEntry[]>} entries grouped by name
537
+ * @typedef {object} ResolutionCache
538
+ * @property {Map<CssModule, Map<string, CssExportEntry[]>>} exports module -> (export name -> entries) across all its export deps
539
+ * @property {Map<CssIcssImportDependency, CssModule | null>} targets import dep -> resolved target module
540
+ */
541
+
542
+ /**
543
+ * Creates the transient per-`apply` cache shared by `resolve` and
544
+ * `resolveReferences`. It is GC'd when the codegen call returns and is never
545
+ * retained on the dependency.
546
+ * @returns {ResolutionCache} empty resolution cache
547
+ */
548
+ const createResolutionCache = () => ({
549
+ exports: new Map(),
550
+ targets: new Map()
551
+ });
552
+
553
+ /**
554
+ * Shared read-only index for modules that own no export dep.
555
+ * @type {Map<string, CssExportEntry[]>}
556
+ */
557
+ const EMPTY_INDEX = new Map();
558
+
559
+ /**
560
+ * Per-module `local name -> import deps` index, keyed by module and validated by
561
+ * `buildInfo` identity (a fresh object per build). `apply` runs once per source
562
+ * type (CSS and JS), so this survives both passes — the index is built once per
563
+ * build instead of once per `apply`. Weakly held, so it never keeps a module
564
+ * alive.
565
+ * @type {WeakMap<CssModule, { buildInfo: unknown, index: Map<string, CssIcssImportDependency[]> }>}
566
+ */
567
+ const moduleImportIndexes = new WeakMap();
568
+
569
+ /**
570
+ * Get (or lazily resolve) the target module of an `@value`/composes import dep.
571
+ * The same import dep is followed by many entries within one codegen, so the
572
+ * `moduleGraph.getModule` lookup is memoized per dep.
573
+ * @param {ResolutionCache} cache resolution cache
574
+ * @param {ModuleGraph} moduleGraph module graph
575
+ * @param {CssIcssImportDependency} importDep import dependency
576
+ * @returns {CssModule | null} resolved target module, or `null` if none
577
+ */
578
+ const getTargetModule = (cache, moduleGraph, importDep) => {
579
+ let module = cache.targets.get(importDep);
580
+ if (module === undefined) {
581
+ module = /** @type {CssModule | null} */ (moduleGraph.getModule(importDep));
582
+ cache.targets.set(importDep, module);
583
+ }
584
+ return module;
585
+ };
586
+
587
+ /**
588
+ * Get (or lazily build) the `name -> entries` index for `module`. There is one
589
+ * consolidated `CssIcssExportDependency` per module, and its own index is cached
590
+ * on the dep — so a module composed/imported by many others builds its index
591
+ * once per build rather than once per importer, and resolution does a single Map
592
+ * lookup instead of re-scanning `module.dependencies` per reference.
593
+ * @param {ResolutionCache} cache resolution cache
594
+ * @param {CssModule} module css module
595
+ * @returns {Map<string, CssExportEntry[]>} entries grouped by export name
520
596
  */
521
- const indexEntries = (indexCache, dep) => {
522
- let map = indexCache.get(dep);
597
+ const getExportIndex = (cache, module) => {
598
+ let map = cache.exports.get(module);
523
599
  if (map === undefined) {
524
- map = new Map();
525
- for (const e of dep.entries) {
526
- const list = map.get(e.name);
527
- if (list) list.push(e);
528
- else map.set(e.name, [e]);
600
+ map = EMPTY_INDEX;
601
+ for (const dep of module.dependencies) {
602
+ if (dep instanceof CssIcssExportDependency) {
603
+ map = dep.getEntriesByName();
604
+ break;
605
+ }
529
606
  }
530
- indexCache.set(dep, map);
607
+ cache.exports.set(module, map);
531
608
  }
532
609
  return map;
533
610
  };
534
611
 
612
+ /**
613
+ * Get (or lazily build) the `local name -> import deps` index for `module`, so
614
+ * `findImportDep` is a Map lookup instead of a linear scan of every dependency.
615
+ * Cached per build on the module (validated by `buildInfo` identity) so both the
616
+ * CSS and JS codegen passes reuse one scan of `module.dependencies`.
617
+ * @param {CssModule} module css module
618
+ * @returns {Map<string, CssIcssImportDependency[]>} import deps grouped by local name
619
+ */
620
+ const getImportIndex = (module) => {
621
+ const buildInfo = module.buildInfo;
622
+ const cached = moduleImportIndexes.get(module);
623
+ if (cached !== undefined && cached.buildInfo === buildInfo) {
624
+ return cached.index;
625
+ }
626
+ /** @type {Map<string, CssIcssImportDependency[]>} */
627
+ const index = new Map();
628
+ for (const d of module.dependencies) {
629
+ if (!(d instanceof CssIcssImportDependency)) continue;
630
+ const list = index.get(d.localName);
631
+ if (list) list.push(d);
632
+ else index.set(d.localName, [d]);
633
+ }
634
+ moduleImportIndexes.set(module, { buildInfo, index });
635
+ return index;
636
+ };
637
+
535
638
  /**
536
639
  * Finds the active `CssIcssImportDependency` for a given local name. When a
537
640
  * `request` is provided the lookup also requires the import dependency's
538
641
  * `request` to match, so references between two `@value foo from "..."`
539
642
  * declarations resolve through the import in scope at the reference site.
540
- * @param {Iterable<Dependency>} dependencies module dependencies to search
643
+ * @param {CssModule} module module owning the dependencies to search
541
644
  * @param {string} localName local name
542
645
  * @param {string=} request user request of the `@value` import to match
543
646
  * @returns {CssIcssImportDependency | undefined} matching import dep, if any
544
647
  */
545
- const findImportDep = (dependencies, localName, request) => {
546
- /** @type {CssIcssImportDependency | undefined} */
547
- let firstMatch;
548
- for (const d of dependencies) {
549
- if (d instanceof CssIcssImportDependency && d.localName === localName) {
550
- if (request === undefined) return d;
551
- if (d.request === request) return d;
552
- if (firstMatch === undefined) firstMatch = d;
553
- }
554
- }
555
- return firstMatch;
648
+ const findImportDep = (module, localName, request) => {
649
+ const list = getImportIndex(module).get(localName);
650
+ if (list === undefined) return undefined;
651
+ // Import deps keep dependency order, so `list[0]` is the first match (the
652
+ // legacy `firstMatch` fallback when no request-specific match exists).
653
+ if (request === undefined) return list[0];
654
+ for (const d of list) if (d.request === request) return d;
655
+ return list[0];
556
656
  };
557
657
 
558
658
  CssIcssExportDependency.Template = class CssIcssExportDependencyTemplate extends (
@@ -567,7 +667,7 @@ CssIcssExportDependency.Template = class CssIcssExportDependencyTemplate extends
567
667
  * @param {DependencyTemplateContext} templateContext the context object
568
668
  * @param {string | undefined} request user request of the `@value` import
569
669
  * @param {Set<CssExportEntry>=} seen cycle guard
570
- * @param {Map<CssIcssExportDependency, Map<string, CssExportEntry[]>>=} indexCache transient per-codegen name index (shared with `resolveReferences` within one `apply`)
670
+ * @param {ResolutionCache=} cache transient per-codegen index (shared with `resolveReferences` within one `apply`)
571
671
  * @returns {string | undefined} found reference
572
672
  */
573
673
  static resolve(
@@ -576,29 +676,21 @@ CssIcssExportDependency.Template = class CssIcssExportDependencyTemplate extends
576
676
  templateContext,
577
677
  request,
578
678
  seen = new Set(),
579
- indexCache = new Map()
679
+ cache = createResolutionCache()
580
680
  ) {
581
681
  const { moduleGraph } = templateContext;
582
682
  const importDep = findImportDep(
583
- templateContext.module.dependencies,
683
+ /** @type {CssModule} */ (templateContext.module),
584
684
  localName,
585
685
  request
586
686
  );
587
687
  if (!importDep) return undefined;
588
688
 
589
- const module = /** @type {CssModule} */ (moduleGraph.getModule(importDep));
689
+ const module = getTargetModule(cache, moduleGraph, importDep);
590
690
  if (!module) return undefined;
591
691
 
592
- /** @type {CssExportEntry | undefined} */
593
- let exportEntry;
594
- for (const dep of module.dependencies) {
595
- if (!(dep instanceof CssIcssExportDependency)) continue;
596
- const matches = indexEntries(indexCache, dep).get(importName);
597
- if (matches) {
598
- exportEntry = matches[0];
599
- break;
600
- }
601
- }
692
+ const matches = getExportIndex(cache, module).get(importName);
693
+ const exportEntry = matches && matches[0];
602
694
  if (!exportEntry) return undefined;
603
695
  if (seen.has(exportEntry)) return undefined;
604
696
  seen.add(exportEntry);
@@ -612,7 +704,7 @@ CssIcssExportDependency.Template = class CssIcssExportDependencyTemplate extends
612
704
  { ...templateContext, module },
613
705
  value[2],
614
706
  seen,
615
- indexCache
707
+ cache
616
708
  );
617
709
  }
618
710
 
@@ -631,10 +723,10 @@ CssIcssExportDependency.Template = class CssIcssExportDependencyTemplate extends
631
723
  * @param {CssExportEntry} entry composes entry
632
724
  * @param {DependencyTemplateContext} templateContext template context
633
725
  * @param {Set<CssExportEntry>} seen cycle guard
634
- * @param {Map<CssIcssExportDependency, Map<string, CssExportEntry[]>>} indexCache transient per-codegen name index, discarded after the module's `apply` (so it isn't retained on the dependency)
726
+ * @param {ResolutionCache} cache transient per-codegen index, discarded after the module's `apply` (so it isn't retained on the dependency)
635
727
  * @returns {string[]} final names
636
728
  */
637
- static resolveReferences(entry, templateContext, seen, indexCache) {
729
+ static resolveReferences(entry, templateContext, seen, cache) {
638
730
  /** @type {string[]} */
639
731
  const references = [];
640
732
 
@@ -643,24 +735,24 @@ CssIcssExportDependency.Template = class CssIcssExportDependencyTemplate extends
643
735
 
644
736
  if (Array.isArray(entry.value)) {
645
737
  const importDep = findImportDep(
646
- templateContext.module.dependencies,
738
+ /** @type {CssModule} */ (templateContext.module),
647
739
  entry.value[0],
648
740
  entry.value[2]
649
741
  );
650
742
  if (!importDep) return references;
651
743
 
652
- const module =
653
- /** @type {CssModule} */
654
- (templateContext.moduleGraph.getModule(importDep));
744
+ const module = getTargetModule(
745
+ cache,
746
+ templateContext.moduleGraph,
747
+ importDep
748
+ );
655
749
  if (!module) return references;
656
750
 
657
751
  // Same overridden context and target name for every matched entry — build once, not per entry.
658
752
  const subContext = { ...templateContext, module };
659
753
  const name = /** @type {string[]} */ (entry.value)[1];
660
- for (const dep of module.dependencies) {
661
- if (!(dep instanceof CssIcssExportDependency)) continue;
662
- const matches = indexEntries(indexCache, dep).get(name);
663
- if (!matches) continue;
754
+ const matches = getExportIndex(cache, module).get(name);
755
+ if (matches) {
664
756
  for (const d of matches) {
665
757
  if (Array.isArray(d.value)) {
666
758
  references.push(
@@ -668,7 +760,7 @@ CssIcssExportDependency.Template = class CssIcssExportDependencyTemplate extends
668
760
  d,
669
761
  subContext,
670
762
  seen,
671
- indexCache
763
+ cache
672
764
  )
673
765
  );
674
766
  } else {
@@ -691,12 +783,11 @@ CssIcssExportDependency.Template = class CssIcssExportDependencyTemplate extends
691
783
  )
692
784
  );
693
785
 
694
- for (const dep of templateContext.module.dependencies) {
695
- if (!(dep instanceof CssIcssExportDependency)) continue;
696
- const matches = indexEntries(indexCache, dep).get(
697
- /** @type {string} */ (entry.value)
698
- );
699
- if (!matches) continue;
786
+ const matches = getExportIndex(
787
+ cache,
788
+ /** @type {CssModule} */ (templateContext.module)
789
+ ).get(/** @type {string} */ (entry.value));
790
+ if (matches) {
700
791
  for (const d of matches) {
701
792
  if (d.exportType !== EXPORT_TYPE.COMPOSES) continue;
702
793
  if (Array.isArray(d.value)) {
@@ -705,7 +796,7 @@ CssIcssExportDependency.Template = class CssIcssExportDependencyTemplate extends
705
796
  d,
706
797
  templateContext,
707
798
  seen,
708
- indexCache
799
+ cache
709
800
  )
710
801
  );
711
802
  } else {
@@ -761,9 +852,9 @@ CssIcssExportDependency.Template = class CssIcssExportDependencyTemplate extends
761
852
  // All entries belong to this one module, so resolve its ExportsInfo once
762
853
  // instead of re-resolving `module -> exportsInfo` per export name.
763
854
  const exportsInfo = isJs ? moduleGraph.getExportsInfo(module) : undefined;
764
- // Transient name index for composes resolution within this module's codegen; GC'd when apply returns (never retained on the dependency).
765
- /** @type {Map<CssIcssExportDependency, Map<string, CssExportEntry[]>>} */
766
- const indexCache = new Map();
855
+ // Transient per-module indexes for composes resolution within this
856
+ // module's codegen; GC'd when apply returns (never retained on the dependency).
857
+ const cache = createResolutionCache();
767
858
 
768
859
  for (const entry of dep.entries) {
769
860
  if (!entry.range && !isJs) continue;
@@ -776,7 +867,7 @@ CssIcssExportDependency.Template = class CssIcssExportDependencyTemplate extends
776
867
  entry,
777
868
  templateContext,
778
869
  new Set(),
779
- indexCache
870
+ cache
780
871
  ).join(" ");
781
872
  } else if (isReference) {
782
873
  const resolved = CssIcssExportDependencyTemplate.resolve(
@@ -785,7 +876,7 @@ CssIcssExportDependency.Template = class CssIcssExportDependencyTemplate extends
785
876
  templateContext,
786
877
  /** @type {string[]} */ (entry.value)[2],
787
878
  new Set(),
788
- indexCache
879
+ cache
789
880
  );
790
881
  value = resolved || /** @type {string[]} */ (entry.value)[0];
791
882
  } else {
@@ -809,14 +900,14 @@ CssIcssExportDependency.Template = class CssIcssExportDependencyTemplate extends
809
900
  /** @type {Set<string>} */
810
901
  const allNames = new Set();
811
902
  for (const name of names) {
812
- const usedName = /** @type {NonNullable<typeof exportsInfo>} */ (
813
- exportsInfo
814
- )
815
- .getExportInfo(name)
816
- .getUsedName(name, runtime);
817
- if (usedName) allNames.add(/** @type {string} */ (usedName));
903
+ if (
904
+ /** @type {NonNullable<typeof exportsInfo>} */ (exportsInfo)
905
+ .getExportInfo(name)
906
+ .getUsedName(name, runtime)
907
+ ) {
908
+ allNames.add(name);
909
+ }
818
910
  }
819
- for (const name of names) allNames.add(name);
820
911
  const unescaped = getCssTokens().unescapeIdentifier(
821
912
  value,
822
913
  templateContext.runtimeTemplate.compilation.compiler.root
@@ -21,8 +21,8 @@ const ModuleDependency = require("./ModuleDependency");
21
21
  /** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */
22
22
  /** @typedef {import("../Module").CodeGenerationResultData} CodeGenerationResultData */
23
23
  /** @typedef {import("../javascript/JavascriptParser").Range} Range */
24
- /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext<["string" | "url" | "src"]>} ObjectDeserializerContext */
25
- /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext<["string" | "url" | "src"]>} ObjectSerializerContext */
24
+ /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext<["string" | "url" | "src", true | undefined, true | undefined, ("high" | "low" | "auto" | undefined), string | undefined, string | undefined, string | undefined]>} ObjectDeserializerContext */
25
+ /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext<["string" | "url" | "src", true | undefined, true | undefined, ("high" | "low" | "auto" | undefined), string | undefined, string | undefined, string | undefined]>} ObjectSerializerContext */
26
26
  /** @typedef {import("../util/Hash")} Hash */
27
27
  /** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
28
28
  /** @typedef {import("../NormalModule").NormalModuleBuildInfo} NormalModuleBuildInfo */
@@ -42,6 +42,18 @@ class CssUrlDependency extends ModuleDependency {
42
42
  super(request);
43
43
  this.range = range;
44
44
  this.urlType = urlType;
45
+ /** @type {true | undefined} */
46
+ this.prefetch = undefined;
47
+ /** @type {true | undefined} */
48
+ this.preload = undefined;
49
+ /** @type {"low" | "high" | "auto" | undefined} */
50
+ this.fetchPriority = undefined;
51
+ /** @type {string | undefined} */
52
+ this.asAttribute = undefined;
53
+ /** @type {string | undefined} */
54
+ this.typeAttribute = undefined;
55
+ /** @type {string | undefined} */
56
+ this.mediaAttribute = undefined;
45
57
  }
46
58
 
47
59
  get type() {
@@ -89,7 +101,14 @@ class CssUrlDependency extends ModuleDependency {
89
101
  * @param {ObjectSerializerContext} context context
90
102
  */
91
103
  serialize(context) {
92
- context.write(this.urlType);
104
+ context
105
+ .write(this.urlType)
106
+ .write(this.prefetch)
107
+ .write(this.preload)
108
+ .write(this.fetchPriority)
109
+ .write(this.asAttribute)
110
+ .write(this.typeAttribute)
111
+ .write(this.mediaAttribute);
93
112
  super.serialize(context);
94
113
  }
95
114
 
@@ -99,7 +118,19 @@ class CssUrlDependency extends ModuleDependency {
99
118
  */
100
119
  deserialize(context) {
101
120
  this.urlType = context.read();
102
- super.deserialize(context.rest);
121
+ const c1 = context.rest;
122
+ this.prefetch = c1.read();
123
+ const c2 = c1.rest;
124
+ this.preload = c2.read();
125
+ const c3 = c2.rest;
126
+ this.fetchPriority = c3.read();
127
+ const c4 = c3.rest;
128
+ this.asAttribute = c4.read();
129
+ const c5 = c4.rest;
130
+ this.typeAttribute = c5.read();
131
+ const c6 = c5.rest;
132
+ this.mediaAttribute = c6.read();
133
+ super.deserialize(c6.rest);
103
134
  }
104
135
  }
105
136
 
@@ -60,10 +60,10 @@ class ExternalModuleInitFragmentDependency extends NullDependency {
60
60
 
61
61
  makeSerializable(
62
62
  ExternalModuleInitFragmentDependency,
63
- "webpack/lib/dependencies/ExternalModuleConstDependency"
63
+ "webpack/lib/dependencies/ExternalModuleInitFragmentDependency"
64
64
  );
65
65
 
66
- ExternalModuleInitFragmentDependency.Template = class ExternalModuleConstDependencyTemplate extends (
66
+ ExternalModuleInitFragmentDependency.Template = class ExternalModuleInitFragmentDependencyTemplate extends (
67
67
  DependencyTemplate
68
68
  ) {
69
69
  /**
@@ -8,6 +8,7 @@
8
8
  const { UsageState } = require("../ExportsInfo");
9
9
  const InitFragment = require("../InitFragment");
10
10
  const RuntimeGlobals = require("../RuntimeGlobals");
11
+ const isGeneratorLowered = require("../async-modules/isGeneratorLowered");
11
12
  const makeSerializable = require("../util/makeSerializable");
12
13
  const NullDependency = require("./NullDependency");
13
14
 
@@ -71,20 +72,37 @@ HarmonyCompatibilityDependency.Template = class HarmonyExportDependencyTemplate
71
72
  }
72
73
  if (moduleGraph.isAsync(module)) {
73
74
  runtimeRequirements.add(RuntimeGlobals.module);
74
- runtimeRequirements.add(RuntimeGlobals.asyncModule);
75
- initFragments.push(
76
- new InitFragment(
77
- runtimeTemplate.supportsArrowFunction()
78
- ? `${RuntimeGlobals.asyncModule}(${module.moduleArgument}, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n`
79
- : `${RuntimeGlobals.asyncModule}(${module.moduleArgument}, async function (__webpack_handle_async_dependencies__, __webpack_async_result__) { try {\n`,
80
- InitFragment.STAGE_ASYNC_BOUNDARY,
81
- 0,
82
- undefined,
83
- `\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } }${
84
- /** @type {BuildMeta} */ (module.buildMeta).async ? ", 1" : ""
85
- });`
86
- )
87
- );
75
+ const hasAwait = /** @type {BuildMeta} */ (module.buildMeta).async
76
+ ? ", 1"
77
+ : "";
78
+ // Target has no `async`/`await` but has generators: drive the body as a
79
+ // generator so `await` becomes `yield`, keeping the module in a single
80
+ // scope (unlike a `.then` callback) without transpiling to a state machine.
81
+ if (isGeneratorLowered(module, moduleGraph, runtimeTemplate)) {
82
+ runtimeRequirements.add(RuntimeGlobals.asyncModuleGenerator);
83
+ initFragments.push(
84
+ new InitFragment(
85
+ `${RuntimeGlobals.asyncModule}(${module.moduleArgument}, ${RuntimeGlobals.asyncModuleGenerator}(function* (__webpack_handle_async_dependencies__, __webpack_async_result__) { try {\n`,
86
+ InitFragment.STAGE_ASYNC_BOUNDARY,
87
+ 0,
88
+ undefined,
89
+ `\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } })${hasAwait});`
90
+ )
91
+ );
92
+ } else {
93
+ runtimeRequirements.add(RuntimeGlobals.asyncModule);
94
+ initFragments.push(
95
+ new InitFragment(
96
+ runtimeTemplate.supportsArrowFunction()
97
+ ? `${RuntimeGlobals.asyncModule}(${module.moduleArgument}, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n`
98
+ : `${RuntimeGlobals.asyncModule}(${module.moduleArgument}, async function (__webpack_handle_async_dependencies__, __webpack_async_result__) { try {\n`,
99
+ InitFragment.STAGE_ASYNC_BOUNDARY,
100
+ 0,
101
+ undefined,
102
+ `\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } }${hasAwait});`
103
+ )
104
+ );
105
+ }
88
106
  }
89
107
  }
90
108
  };
@@ -10,10 +10,16 @@ const EnvironmentNotSupportAsyncWarning = require("../errors/EnvironmentNotSuppo
10
10
  const DynamicExports = require("./DynamicExports");
11
11
  const HarmonyCompatibilityDependency = require("./HarmonyCompatibilityDependency");
12
12
  const HarmonyExports = require("./HarmonyExports");
13
- const { IMPORT_META_NAMES } = require("./ImportMetaPlugin");
13
+ const {
14
+ IMPORT_META_NAMES,
15
+ IMPORT_META_STAGE_ESM_DETECTION
16
+ } = require("./ImportMetaPlugin");
17
+ const TopLevelAwaitDependency = require("./TopLevelAwaitDependency");
14
18
 
19
+ /** @typedef {import("../Module").BuildInfo} BuildInfo */
15
20
  /** @typedef {import("../Module").BuildMeta} BuildMeta */
16
21
  /** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
22
+ /** @typedef {import("../javascript/JavascriptParser").Range} Range */
17
23
 
18
24
  const PLUGIN_NAME = "HarmonyDetectionParserPlugin";
19
25
 
@@ -68,34 +74,58 @@ module.exports = class HarmonyDetectionParserPlugin {
68
74
  }
69
75
  });
70
76
 
71
- parser.hooks.topLevelAwait.tap(PLUGIN_NAME, () => {
77
+ parser.hooks.topLevelAwait.tap(PLUGIN_NAME, (node) => {
72
78
  const module = parser.state.module;
73
79
  enableHarmony(false);
74
80
  /** @type {BuildMeta} */
75
81
  (module.buildMeta).async = true;
76
- EnvironmentNotSupportAsyncWarning.check(
77
- module,
78
- parser.state.compilation.runtimeTemplate,
79
- "topLevelAwait"
80
- );
82
+ const buildInfo = /** @type {BuildInfo} */ (module.buildInfo);
83
+ if (node.type === "AwaitExpression") {
84
+ // Record for a possible `await` -> `(yield …)` rewrite when the module
85
+ // is lowered to a generator (target without `async`/`await`).
86
+ module.addPresentationalDependency(
87
+ new TopLevelAwaitDependency(
88
+ /** @type {Range} */ (node.range),
89
+ /** @type {Range} */ (node.argument.range)
90
+ )
91
+ );
92
+ } else {
93
+ // `for await…of` can't be expressed as a generator; never lower it.
94
+ buildInfo.usesTopLevelAwaitForOf = true;
95
+ }
96
+ const { runtimeTemplate } = parser.state.compilation;
97
+ if (
98
+ !runtimeTemplate.supportsAsyncFunction() &&
99
+ (!runtimeTemplate.supportsGenerator() ||
100
+ buildInfo.usesTopLevelAwaitForOf)
101
+ ) {
102
+ module.addWarning(
103
+ new EnvironmentNotSupportAsyncWarning(module, "topLevelAwait")
104
+ );
105
+ }
81
106
  });
82
107
 
83
108
  // Using `import.meta` only parses as a module, so it marks the module ESM.
84
- // Non-bailing and run before ImportMetaPlugin so its handling still runs;
85
- // unknown members go through `unhandledExpressionMemberChain`.
109
+ // Non-bailing; staged before the bailing DefinePlugin and ImportMetaPlugin
110
+ // replacement taps so it observes every access; unknown members go
111
+ // through `unhandledExpressionMemberChain`.
86
112
  const onImportMeta = () => {
87
113
  enableHarmony(false);
88
114
  };
115
+ const earlyTapOptions = {
116
+ name: PLUGIN_NAME,
117
+ stage: IMPORT_META_STAGE_ESM_DETECTION
118
+ };
89
119
  for (const name of IMPORT_META_NAMES) {
90
- parser.hooks.expression.for(name).tap(PLUGIN_NAME, onImportMeta);
91
- parser.hooks.typeof.for(name).tap(PLUGIN_NAME, onImportMeta);
120
+ parser.hooks.expression.for(name).tap(earlyTapOptions, onImportMeta);
121
+ parser.hooks.typeof.for(name).tap(earlyTapOptions, onImportMeta);
92
122
  }
93
123
  parser.hooks.expressionMemberChain
94
124
  .for("import.meta")
95
- .tap(PLUGIN_NAME, onImportMeta);
125
+ .tap(earlyTapOptions, onImportMeta);
96
126
  parser.hooks.unhandledExpressionMemberChain
97
127
  .for("import.meta")
98
- .tap(PLUGIN_NAME, onImportMeta);
128
+ .tap(earlyTapOptions, onImportMeta);
99
129
 
100
130
  /**
101
131
  * Returns true if in harmony.