webpack 5.110.2 → 5.111.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/README.md +5 -2
  2. package/lib/APIPlugin.js +23 -7
  3. package/lib/AutomaticPrefetchPlugin.js +1 -1
  4. package/lib/Cache.js +8 -3
  5. package/lib/CacheFacade.js +1 -1
  6. package/lib/ChunkGraph.js +20 -18
  7. package/lib/CircularModulesPlugin.js +157 -55
  8. package/lib/CleanPlugin.js +2 -2
  9. package/lib/Compilation.js +321 -303
  10. package/lib/Compiler.js +209 -46
  11. package/lib/ConcatenationScope.js +25 -35
  12. package/lib/ContextModule.js +17 -81
  13. package/lib/ContextModuleFactory.js +1 -1
  14. package/lib/CopyPlugin.js +1054 -0
  15. package/lib/DefinePlugin.js +24 -8
  16. package/lib/DotenvPlugin.js +41 -13
  17. package/lib/ExternalModule.js +41 -14
  18. package/lib/FileSystemInfo.js +17 -14
  19. package/lib/FlagDependencyExportsPlugin.js +45 -21
  20. package/lib/FlagDependencyUsagePlugin.js +8 -2
  21. package/lib/HotModuleReplacementPlugin.js +53 -7
  22. package/lib/JavascriptMetaInfoPlugin.js +5 -3
  23. package/lib/MainTemplate.js +5 -1
  24. package/lib/Module.js +16 -7
  25. package/lib/MultiCompiler.js +1 -1
  26. package/lib/MultiWatching.js +1 -1
  27. package/lib/NormalModule.js +58 -32
  28. package/lib/NormalModuleFactory.js +1 -1
  29. package/lib/RuntimeGlobals.js +21 -7
  30. package/lib/RuntimeModule.js +28 -12
  31. package/lib/RuntimePlugin.js +33 -3
  32. package/lib/RuntimeTemplate.js +794 -477
  33. package/lib/SourceMapDevToolPlugin.js +1 -1
  34. package/lib/Watching.js +9 -0
  35. package/lib/WebpackOptionsApply.js +84 -91
  36. package/lib/asset/AssetGenerator.js +25 -8
  37. package/lib/asset/AssetModule.js +3 -0
  38. package/lib/asset/WebManifestParser.js +7 -5
  39. package/lib/async-modules/AsyncModuleHelpers.js +10 -4
  40. package/lib/cache/AddBuildDependenciesPlugin.js +33 -4
  41. package/lib/cache/IdleFileCachePlugin.js +2 -2
  42. package/lib/cache/PackFileCacheStrategy.js +14 -1
  43. package/lib/config/browserslistTargetHandler.js +19 -0
  44. package/lib/config/defaults.js +110 -64
  45. package/lib/config/normalization.js +100 -20
  46. package/lib/config/target.js +10 -0
  47. package/lib/container/ContainerReferencePlugin.js +6 -0
  48. package/lib/container/RemoteRuntimeModule.js +9 -0
  49. package/lib/container/declaredRemotes.js +39 -0
  50. package/lib/css/CssGenerator.js +8 -0
  51. package/lib/css/CssInjectStyleRuntimeModule.js +9 -0
  52. package/lib/css/CssLoadingRuntimeModule.js +94 -36
  53. package/lib/css/CssModule.js +1 -1
  54. package/lib/css/CssModulesPlugin.js +7 -6
  55. package/lib/css/CssParser.js +144 -11
  56. package/lib/css/CssServerStylesRuntimeModule.js +9 -0
  57. package/lib/css/cssMinify.js +11 -3
  58. package/lib/css/data.js +2814 -678
  59. package/lib/css/syntax.js +4082 -248
  60. package/lib/debug/ProfilingPlugin.js +4 -0
  61. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -3
  62. package/lib/dependencies/AMDRuntimeModules.js +18 -0
  63. package/lib/dependencies/CommonJsExportRequireDependency.js +3 -1
  64. package/lib/dependencies/CommonJsExportsParserPlugin.js +12 -13
  65. package/lib/dependencies/CommonJsImportsParserPlugin.js +1 -0
  66. package/lib/dependencies/CommonJsPlugin.js +19 -3
  67. package/lib/dependencies/CommonJsRequireDependency.js +32 -9
  68. package/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +20 -7
  69. package/lib/dependencies/CssIcssExportDependency.js +7 -1
  70. package/lib/dependencies/HarmonyCompatibilityDependency.js +58 -4
  71. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +8 -3
  72. package/lib/dependencies/HarmonyExportExpressionDependency.js +44 -29
  73. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +171 -32
  74. package/lib/dependencies/HarmonyExportInitFragment.js +99 -19
  75. package/lib/dependencies/HarmonyExportSpecifierDependency.js +18 -30
  76. package/lib/dependencies/HarmonyImportBareSideEffectDependency.js +59 -0
  77. package/lib/dependencies/HarmonyImportDependency.js +99 -41
  78. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +20 -3
  79. package/lib/dependencies/HarmonyImportSpecifierDependency.js +24 -1
  80. package/lib/dependencies/HarmonyModulesPlugin.js +20 -0
  81. package/lib/dependencies/HtmlEntryDependency.js +62 -2
  82. package/lib/dependencies/ImportContextDependency.js +43 -3
  83. package/lib/dependencies/ImportDependency.js +8 -29
  84. package/lib/dependencies/ImportMetaMainDependency.js +104 -0
  85. package/lib/dependencies/ImportMetaPlugin.js +59 -15
  86. package/lib/dependencies/ImportParserPlugin.js +24 -14
  87. package/lib/dependencies/RequireHeaderDependency.js +20 -21
  88. package/lib/dependencies/SystemRuntimeModule.js +9 -0
  89. package/lib/dependencies/WorkerDependency.js +1 -2
  90. package/lib/dependencies/WorkletDependency.js +1 -2
  91. package/lib/dependencies/importOptionsCheck.js +47 -0
  92. package/lib/dll/DelegatedModule.js +18 -1
  93. package/lib/dll/DllReferencePlugin.js +11 -8
  94. package/lib/dll/LibManifestPlugin.js +1 -1
  95. package/lib/errors/AnalyzableBailoutsWarning.js +41 -0
  96. package/lib/errors/DotenvFileError.js +29 -0
  97. package/lib/errors/DuplicateModulesWarning.js +12 -7
  98. package/lib/errors/EmptyCopyPatternWarning.js +26 -0
  99. package/lib/errors/ExternalStarReexportError.js +44 -0
  100. package/lib/errors/ImportedBindingAssignmentError.js +30 -0
  101. package/lib/errors/MissingSourceMapsWarning.js +36 -0
  102. package/lib/errors/ModuleParseError.js +2 -1
  103. package/lib/errors/UnusedAssetsWarning.js +36 -0
  104. package/lib/errors/UnusedFederationWarning.js +35 -0
  105. package/lib/errors/UnusedModulesWarning.js +38 -0
  106. package/lib/esm/ExportWebpackRequireRuntimeModule.js +9 -0
  107. package/lib/esm/ModuleChunkFormatPlugin.js +28 -3
  108. package/lib/esm/ModuleChunkLoadingPlugin.js +30 -11
  109. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +92 -60
  110. package/lib/hmr/HotModuleReplacement.runtime.js +8 -2
  111. package/lib/hmr/HotModuleReplacementRuntimeModule.js +9 -0
  112. package/lib/html/HtmlGenerator.js +11 -5
  113. package/lib/html/HtmlModulesPlugin.js +360 -84
  114. package/lib/html/HtmlParser.js +13 -6
  115. package/lib/html/builtinEmbeddedRenderer.js +107 -0
  116. package/lib/html/data.js +121 -7
  117. package/lib/html/htmlMinify.js +84 -113
  118. package/lib/html/syntax.js +1067 -569
  119. package/lib/ids/HashedModuleIdsPlugin.js +2 -1
  120. package/lib/index.js +3 -0
  121. package/lib/javascript/JavascriptModule.js +1 -0
  122. package/lib/javascript/JavascriptModulesPlugin.js +52 -22
  123. package/lib/javascript/JavascriptParser.js +1255 -728
  124. package/lib/javascript/StartupHelpers.js +27 -3
  125. package/lib/javascript/data.js +172 -0
  126. package/lib/javascript/grammar.js +5546 -0
  127. package/lib/javascript/parser.js +1494 -0
  128. package/lib/javascript/regexp.js +1762 -0
  129. package/lib/javascript/regexpData.js +51 -0
  130. package/lib/javascript/syntax.js +8696 -5225
  131. package/lib/library/ModuleLibraryPlugin.js +116 -5
  132. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +22 -0
  133. package/lib/node/RequireChunkLoadingRuntimeModule.js +22 -0
  134. package/lib/optimize/ConcatenatedModule.js +133 -25
  135. package/lib/optimize/ConstExportsPlugin.js +50 -39
  136. package/lib/optimize/InlineExports.js +20 -123
  137. package/lib/optimize/MangleExportsPlugin.js +10 -0
  138. package/lib/optimize/ModuleConcatenationPlugin.js +24 -1
  139. package/lib/optimize/RealContentHashPlugin.js +68 -9
  140. package/lib/optimize/SideEffectsFlagPlugin.js +17 -9
  141. package/lib/performance/AnalyzableBailoutsPlugin.js +115 -0
  142. package/lib/performance/CacheEffectivenessPlugin.js +4 -3
  143. package/lib/performance/DuplicateModulesPlugin.js +57 -13
  144. package/lib/performance/EvalUsagePlugin.js +5 -2
  145. package/lib/performance/MissingSourceMapsPlugin.js +115 -0
  146. package/lib/performance/PureAnnotationsPlugin.js +6 -3
  147. package/lib/performance/TopLevelThisPlugin.js +5 -4
  148. package/lib/performance/UnusedAssetsPlugin.js +109 -0
  149. package/lib/performance/UnusedFederationPlugin.js +147 -0
  150. package/lib/performance/UnusedModulesPlugin.js +141 -0
  151. package/lib/performance/UnusedReexportsPlugin.js +1 -55
  152. package/lib/performance/isOnlyReexported.js +65 -0
  153. package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +25 -5
  154. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +2 -0
  155. package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +9 -0
  156. package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +9 -0
  157. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +9 -0
  158. package/lib/prefetch/ResourceHintPlugin.js +7 -3
  159. package/lib/prefetch/ResourceHintRuntimeModule.js +9 -0
  160. package/lib/prefetch/StartupAssetHintRuntimeModule.js +9 -0
  161. package/lib/rules/RuleSetCompiler.js +211 -4
  162. package/lib/runtime/AsyncModuleRuntimeModule.js +105 -67
  163. package/lib/runtime/AutoPublicPathRuntimeModule.js +9 -0
  164. package/lib/runtime/BaseUriRuntimeModule.js +9 -0
  165. package/lib/runtime/ChunkNameRuntimeModule.js +9 -0
  166. package/lib/runtime/EnsureChunkRuntimeModule.js +35 -16
  167. package/lib/runtime/GetChunkFilenameRuntimeModule.js +9 -0
  168. package/lib/runtime/GetFullHashRuntimeModule.js +9 -0
  169. package/lib/runtime/GetMainFilenameRuntimeModule.js +9 -0
  170. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +9 -0
  171. package/lib/runtime/GlobalRuntimeModule.js +9 -0
  172. package/lib/runtime/HasOwnPropertyRuntimeModule.js +9 -0
  173. package/lib/runtime/HelperRuntimeModule.js +10 -0
  174. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +338 -217
  175. package/lib/runtime/NonceRuntimeModule.js +9 -0
  176. package/lib/runtime/OnChunksLoadedRuntimeModule.js +67 -20
  177. package/lib/runtime/PublicPathRuntimeModule.js +9 -0
  178. package/lib/runtime/RuntimeIdRuntimeModule.js +9 -0
  179. package/lib/runtime/SpecNamespaceObjectRuntimeModule.js +90 -0
  180. package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +9 -0
  181. package/lib/runtime/StartupEntrypointRuntimeModule.js +9 -0
  182. package/lib/runtime/SystemContextRuntimeModule.js +9 -0
  183. package/lib/runtime/ToBinaryRuntimeModule.js +9 -0
  184. package/lib/schemes/HttpUriPlugin.js +22 -5
  185. package/lib/serialization/FileMiddleware.js +15 -2
  186. package/lib/serialization/ObjectMiddleware.js +138 -106
  187. package/lib/sharing/ConsumeSharedPlugin.js +12 -0
  188. package/lib/sharing/ConsumeSharedRuntimeModule.js +11 -0
  189. package/lib/sharing/ShareRuntimeModule.js +9 -0
  190. package/lib/sharing/declaredShared.js +47 -0
  191. package/lib/stats/DefaultStatsFactoryPlugin.js +3 -1
  192. package/lib/stats/DefaultStatsPrinterPlugin.js +3 -0
  193. package/lib/util/ArrayQueue.js +3 -3
  194. package/lib/util/SourceProcessor.js +76 -69
  195. package/lib/util/URLAbsoluteSpecifier.js +3 -1
  196. package/lib/util/async.js +292 -0
  197. package/lib/util/buildDiagnostics.js +69 -0
  198. package/lib/util/conventions.js +5 -1
  199. package/lib/util/fs.js +27 -1
  200. package/lib/util/handlerKeys.js +40 -0
  201. package/lib/util/identifier.js +20 -0
  202. package/lib/util/internalSerializables.js +6 -0
  203. package/lib/util/registerExternalSerializer.js +6 -45
  204. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +9 -0
  205. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +9 -0
  206. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +9 -0
  207. package/lib/web/JsonpChunkLoadingRuntimeModule.js +36 -0
  208. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +19 -0
  209. package/package.json +22 -16
  210. package/schemas/WebpackOptions.check.js +1 -1
  211. package/schemas/WebpackOptions.json +388 -76
  212. package/schemas/plugins/LoaderOptionsPlugin.check.js +1 -1
  213. package/schemas/plugins/ManifestPlugin.check.js +1 -1
  214. package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
  215. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
  216. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
  217. package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
  218. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  219. package/schemas/plugins/debug/ProfilingPlugin.check.js +1 -1
  220. package/schemas/plugins/dll/DllReferencePlugin.check.js +1 -1
  221. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +1 -1
  222. package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
  223. package/types.d.ts +1440 -331
  224. package/lib/dependencies/ExportBindingInitFragment.js +0 -191
  225. package/lib/errors/EntrypointOverlapWarning.js +0 -45
  226. package/lib/performance/EntrypointOverlapPlugin.js +0 -122
@@ -7,6 +7,7 @@
7
7
 
8
8
  const { SyncHook } = require("tapable");
9
9
  const { createPathGlobMatcher } = require("../util/globUtils");
10
+ const { fileUrlToPath } = require("../util/identifier");
10
11
 
11
12
  /** @import { ResolveRequest } from "enhanced-resolve" */
12
13
  /**
@@ -352,9 +353,10 @@ class RuleSetCompiler {
352
353
  );
353
354
  }
354
355
  if (typeof condition === "string") {
356
+ const prefix = fileUrlToPath(condition);
355
357
  return {
356
- matchWhenEmpty: condition.length === 0,
357
- fn: (str) => typeof str === "string" && str.startsWith(condition)
358
+ matchWhenEmpty: prefix.length === 0,
359
+ fn: (str) => typeof str === "string" && str.startsWith(prefix)
358
360
  };
359
361
  }
360
362
  if (typeof condition === "function") {
@@ -640,6 +642,200 @@ const matchRuleSetCondition = (condition, resource) => {
640
642
  }
641
643
  };
642
644
 
645
+ // Cap on the spellings one pattern is expanded into, so a pattern built from
646
+ // many alternations stays cheap to probe.
647
+ const MAX_EXPANDED_SPELLINGS = 64;
648
+
649
+ // A rule naming an extension is short; a pattern generated from a list of paths
650
+ // runs to kilobytes and costs more to expand than the answer is worth.
651
+ const MAX_EXPANDED_PATTERN_LENGTH = 256;
652
+
653
+ /**
654
+ * Index of the `]` closing the character class opened at `start`, or the end of
655
+ * the source when it is unterminated.
656
+ * @param {string} source regexp source
657
+ * @param {number} start index of the opening `[`
658
+ * @returns {number} index of the closing `]`
659
+ */
660
+ const findCharacterClassEnd = (source, start) => {
661
+ for (let i = start + 1; i < source.length; i++) {
662
+ if (source[i] === "\\") i++;
663
+ else if (source[i] === "]") return i;
664
+ }
665
+ return source.length;
666
+ };
667
+
668
+ /**
669
+ * Index of the `)` closing the group opened at `start`, skipping nested groups
670
+ * and character classes, or the end of the source when it is unterminated.
671
+ * @param {string} source regexp source
672
+ * @param {number} start index of the opening `(`
673
+ * @returns {number} index of the closing `)`
674
+ */
675
+ const findGroupEnd = (source, start) => {
676
+ let depth = 0;
677
+ for (let i = start; i < source.length; i++) {
678
+ const char = source[i];
679
+ if (char === "\\") i++;
680
+ else if (char === "[") i = findCharacterClassEnd(source, i);
681
+ else if (char === "(") depth++;
682
+ else if (char === ")" && --depth === 0) return i;
683
+ }
684
+ return source.length;
685
+ };
686
+
687
+ /**
688
+ * Splits a group body on its top-level `|`, skipping nested groups and
689
+ * character classes.
690
+ * @param {string} body group body without the enclosing parentheses
691
+ * @returns {string[]} the alternatives
692
+ */
693
+ const splitAlternatives = (body) => {
694
+ const alternatives = [];
695
+ let depth = 0;
696
+ let start = 0;
697
+ for (let i = 0; i < body.length; i++) {
698
+ const char = body[i];
699
+ if (char === "\\") {
700
+ i++;
701
+ } else if (char === "[") {
702
+ i = findCharacterClassEnd(body, i);
703
+ } else if (char === "(") {
704
+ depth++;
705
+ } else if (char === ")") {
706
+ depth--;
707
+ } else if (char === "|" && depth === 0) {
708
+ alternatives.push(body.slice(start, i));
709
+ start = i + 1;
710
+ }
711
+ }
712
+ alternatives.push(body.slice(start));
713
+ return alternatives;
714
+ };
715
+
716
+ /**
717
+ * The part of a group body that the match spells — past a `?:` or `?<name>`
718
+ * prefix, and nothing at all for a lookaround, which spells nothing.
719
+ * @param {string} body group body without the enclosing parentheses
720
+ * @returns {string | undefined} the spelled part, or `undefined` for a lookaround
721
+ */
722
+ const groupContent = (body) => {
723
+ if (!body.startsWith("?")) return body;
724
+ if (body.startsWith("?:")) return body.slice(2);
725
+ const named = /^\?<[^=!][^>]*>/.exec(body);
726
+ return named ? body.slice(named[0].length) : undefined;
727
+ };
728
+
729
+ /**
730
+ * Rewrites the first group, word-character class or optional atom
731
+ * in the source into the spellings it can match, leaving the rest as written.
732
+ * @param {string} source regexp source
733
+ * @returns {string[] | undefined} the rewritten sources, or `undefined` when the source holds no such construct
734
+ */
735
+ const expandFirstConstruct = (source) => {
736
+ for (let i = 0; i < source.length; i++) {
737
+ const char = source[i];
738
+ let end = i + 1;
739
+ /** @type {string[] | undefined} */
740
+ let spellings;
741
+ if (char === "\\") {
742
+ end = i + 2;
743
+ } else if (char === "[") {
744
+ const close = findCharacterClassEnd(source, i);
745
+ end = close + 1;
746
+ const body = source.slice(i + 1, close);
747
+ // only a plain list of word characters spells out safely (no range,
748
+ // no negation, no escape)
749
+ if (/^\w+$/.test(body)) spellings = [...body];
750
+ } else if (char === "(") {
751
+ const close = findGroupEnd(source, i);
752
+ end = close + 1;
753
+ const content = groupContent(source.slice(i + 1, close));
754
+ if (content !== undefined) spellings = splitAlternatives(content);
755
+ }
756
+ // `?` makes the atom optional, so its absence is a spelling as well
757
+ if (source[end] === "?") {
758
+ spellings = [...(spellings || [source.slice(i, end)]), ""];
759
+ end += 1;
760
+ }
761
+ if (spellings) {
762
+ return spellings.map(
763
+ (spelling) => source.slice(0, i) + spelling + source.slice(end)
764
+ );
765
+ }
766
+ i = end - 1;
767
+ }
768
+ };
769
+
770
+ /**
771
+ * Rewrites the first brace alternative in a glob pattern (e.g. `*.{css,scss}`)
772
+ * into the spellings it can match.
773
+ * @param {string} pattern glob pattern
774
+ * @returns {string[] | undefined} the rewritten patterns, or `undefined` when the pattern holds no brace
775
+ */
776
+ const expandFirstBrace = (pattern) => {
777
+ const open = pattern.indexOf("{");
778
+ const close = open === -1 ? -1 : pattern.indexOf("}", open);
779
+ if (close === -1) return;
780
+ return pattern
781
+ .slice(open + 1, close)
782
+ .split(",")
783
+ .map(
784
+ (alternative) =>
785
+ pattern.slice(0, open) + alternative + pattern.slice(close + 1)
786
+ );
787
+ };
788
+
789
+ /**
790
+ * Whether `probe` occurs in `pattern` as a subsequence. Expanding a pattern only
791
+ * ever drops characters, so a probe failing this is spelled by none of its
792
+ * spellings and the expansion is not worth starting.
793
+ * @param {string} pattern pattern to search
794
+ * @param {string} probe probe to find
795
+ * @returns {boolean} whether the probe is a subsequence of the pattern
796
+ */
797
+ const containsSubsequence = (pattern, probe) => {
798
+ let found = 0;
799
+ for (let i = 0; i < pattern.length && found < probe.length; i++) {
800
+ if (pattern[i] === probe[found]) found++;
801
+ }
802
+ return found === probe.length;
803
+ };
804
+
805
+ /**
806
+ * Whether any spelling of the pattern contains the probe, rewriting one
807
+ * construct at a time until none is left or `MAX_EXPANDED_SPELLINGS` is reached.
808
+ * @param {string} pattern pattern to expand
809
+ * @param {string} probe probe the spellings are searched for
810
+ * @param {(pattern: string) => string[] | undefined} expandFirst rewrites the first expandable construct
811
+ * @returns {boolean} whether a spelling contains the probe
812
+ */
813
+ const someSpellingContains = (pattern, probe, expandFirst) => {
814
+ if (pattern.includes(probe)) return true;
815
+ if (pattern.length > MAX_EXPANDED_PATTERN_LENGTH) return false;
816
+ if (!containsSubsequence(pattern, probe)) return false;
817
+ let spellings = [pattern];
818
+ for (;;) {
819
+ /** @type {string[]} */
820
+ const expanded = [];
821
+ for (const spelling of spellings) {
822
+ const rewritten = expandFirst(spelling);
823
+ // every spelling was searched as it was produced, so one with nothing
824
+ // left to rewrite is settled
825
+ if (!rewritten) continue;
826
+ for (const alternative of rewritten) {
827
+ if (alternative.includes(probe)) return true;
828
+ // an alternative that dropped the probe's characters expands no
829
+ // further into it
830
+ if (containsSubsequence(alternative, probe)) expanded.push(alternative);
831
+ }
832
+ if (expanded.length > MAX_EXPANDED_SPELLINGS) return false;
833
+ }
834
+ if (expanded.length === 0) return false;
835
+ spellings = expanded;
836
+ }
837
+ };
838
+
643
839
  /**
644
840
  * @param {EXPECTED_ANY} glob glob pattern(s)
645
841
  * @param {string} extension extension including the dot (e.g. `".css"`)
@@ -648,7 +844,10 @@ const matchRuleSetCondition = (condition, resource) => {
648
844
  const globReferencesExtension = (glob, extension) => {
649
845
  // a `!` pattern subtracts the extension instead of targeting it
650
846
  if (typeof glob === "string") {
651
- return !glob.startsWith("!") && glob.includes(extension);
847
+ return (
848
+ !glob.startsWith("!") &&
849
+ someSpellingContains(glob, extension, expandFirstBrace)
850
+ );
652
851
  }
653
852
  return (
654
853
  Array.isArray(glob) &&
@@ -660,12 +859,20 @@ const globReferencesExtension = (glob, extension) => {
660
859
  * Whether any regexp or glob in the condition references the extension probe
661
860
  * (e.g. `\.css`), i.e. the rule clearly targets that extension even if the
662
861
  * generic sample path doesn't match its (possibly filename-scoped) pattern.
862
+ * The extension may be spelled by an alternation (`\.(css|scss)$`) or a
863
+ * character class (`\.[jt]sx?$`), so those are expanded before probing.
663
864
  * @param {EXPECTED_ANY} condition condition
664
865
  * @param {string} extProbe escaped extension probe (e.g. `"\\.css"`)
665
866
  * @returns {boolean} whether a regexp in the condition targets the extension
666
867
  */
667
868
  const conditionReferencesExtension = (condition, extProbe) => {
668
- if (condition instanceof RegExp) return condition.source.includes(extProbe);
869
+ if (condition instanceof RegExp) {
870
+ // an `/i` rule spells the extension in any case; the probe is lower case
871
+ const source = condition.ignoreCase
872
+ ? condition.source.toLowerCase()
873
+ : condition.source;
874
+ return someSpellingContains(source, extProbe, expandFirstConstruct);
875
+ }
669
876
  if (Array.isArray(condition)) {
670
877
  return condition.some((c) => conditionReferencesExtension(c, extProbe));
671
878
  }
@@ -13,11 +13,14 @@ const HelperRuntimeModule = require("./HelperRuntimeModule");
13
13
  class AsyncModuleRuntimeModule extends HelperRuntimeModule {
14
14
  /**
15
15
  * @param {boolean=} deferInterop if defer import is used.
16
+ * @param {boolean=} strictModuleErrorHandling if a recorded evaluation error is kept.
16
17
  */
17
- constructor(deferInterop = false) {
18
+ constructor(deferInterop = false, strictModuleErrorHandling = false) {
18
19
  super("async module");
19
20
  /** @type {boolean} */
20
21
  this._deferInterop = deferInterop;
22
+ /** @type {boolean} */
23
+ this._strictModuleErrorHandling = strictModuleErrorHandling;
21
24
  }
22
25
 
23
26
  /**
@@ -29,6 +32,11 @@ class AsyncModuleRuntimeModule extends HelperRuntimeModule {
29
32
  const { runtimeTemplate } = compilation;
30
33
  const fn = RuntimeGlobals.asyncModule;
31
34
  const defer = this._deferInterop;
35
+ const strictErrors = this._strictModuleErrorHandling;
36
+ const rejectCall = "reject(promise[webpackError] = err)";
37
+ const rejectExpression = strictErrors
38
+ ? `(markCycle(err), ${rejectCall})`
39
+ : rejectCall;
32
40
  const cst = runtimeTemplate.renderConst();
33
41
  const lt = runtimeTemplate.renderLet();
34
42
  const supportsSymbol = runtimeTemplate.supportsSymbol();
@@ -46,6 +54,7 @@ class AsyncModuleRuntimeModule extends HelperRuntimeModule {
46
54
  defer ? `${RuntimeGlobals.asyncModuleExportSymbol}= ` : ""
47
55
  }${renderSymbol("webpack exports", RuntimeGlobals.exports)};`,
48
56
  `${cst} webpackError = ${renderSymbol("webpack error", "__webpack_error__")};`,
57
+ ...(strictErrors ? [`${cst} cycleGroups = {};`] : []),
49
58
  defer
50
59
  ? Template.asString([
51
60
  `${cst} webpackDone = ${RuntimeGlobals.asyncModuleDoneSymbol} = ${renderSymbol("webpack done", "__webpack_done__")};`,
@@ -57,7 +66,11 @@ class AsyncModuleRuntimeModule extends HelperRuntimeModule {
57
66
  `${cst} hasUnresolvedAsyncSubgraph = asyncDeps.some((id) => {`,
58
67
  Template.indent([
59
68
  `${cst} cache = __webpack_module_cache__[id];`,
60
- "return !cache || cache[webpackDone] === false;"
69
+ "if (!cache) return true;",
70
+ // A cached entry no longer means finished, and a rejected
71
+ // one is done but its error must still reach the importer.
72
+ `${cst} deps = cache.exports;`,
73
+ "return deps[webpackDone] !== true || deps[webpackError] !== undefined;"
61
74
  ]),
62
75
  "});",
63
76
  "if (hasUnresolvedAsyncSubgraph) {",
@@ -144,73 +157,98 @@ class AsyncModuleRuntimeModule extends HelperRuntimeModule {
144
157
  ])})`,
145
158
  "deps"
146
159
  )};`,
147
- `${fn} = ${runtimeTemplate.basicFunction("module, body, hasAwait", [
148
- `${lt} queue;`,
149
- "hasAwait && ((queue = []).d = -1);",
150
- `${cst} depQueues = new Set();`,
151
- `${cst} exports = module.exports;`,
152
- `${lt} currentDeps;`,
153
- `${lt} outerResolve;`,
154
- `${lt} reject;`,
155
- `${cst} promise = new Promise(${runtimeTemplate.basicFunction(
156
- "resolve, rej",
157
- ["reject = rej;", "outerResolve = resolve;"]
158
- )});`,
159
- "promise[webpackExports] = exports;",
160
- `promise[webpackQueues] = ${runtimeTemplate.expressionFunction(
161
- `queue && fn(queue), depQueues.forEach(fn), promise["catch"](${runtimeTemplate.emptyFunction()})`,
162
- "fn"
163
- )};`,
164
- "module.exports = promise;",
165
- `${cst} handle = ${runtimeTemplate.basicFunction("deps", [
166
- "currentDeps = wrapDeps(deps);",
167
- `${lt} fn;`,
168
- `${cst} getResult = ${runtimeTemplate.returningFunction(
169
- `currentDeps.map(${runtimeTemplate.basicFunction("d", [
170
- defer ? "if(d[webpackDefer]) return d;" : "",
171
- "if(d[webpackError]) throw d[webpackError];",
172
- "return d[webpackExports];"
173
- ])})`
174
- )}`,
160
+ `${fn} = ${runtimeTemplate.basicFunction(
161
+ strictErrors
162
+ ? "module, body, hasAwait, cycleGroup"
163
+ : "module, body, hasAwait",
164
+ [
165
+ `${lt} queue;`,
166
+ "hasAwait && ((queue = []).d = -1);",
167
+ `${cst} depQueues = new Set();`,
168
+ `${cst} exports = module.exports;`,
169
+ `${lt} currentDeps;`,
170
+ `${lt} outerResolve;`,
171
+ `${lt} reject;`,
175
172
  `${cst} promise = new Promise(${runtimeTemplate.basicFunction(
176
- "resolve",
177
- [
178
- `fn = ${runtimeTemplate.expressionFunction(
179
- "resolve(getResult)",
180
- ""
181
- )};`,
182
- "fn.r = 0;",
183
- `${cst} fnQueue = ${runtimeTemplate.expressionFunction(
184
- "q !== queue && !depQueues.has(q) && (depQueues.add(q), q && !q.d && (fn.r++, q.push(fn)))",
185
- "q"
186
- )};`,
187
- `currentDeps.forEach(${runtimeTemplate.expressionFunction(
188
- `${
189
- defer ? "dep[webpackDefer]||" : ""
190
- }dep[webpackQueues](fnQueue)`,
191
- "dep"
192
- )});`
193
- ]
173
+ "resolve, rej",
174
+ ["reject = rej;", "outerResolve = resolve;"]
194
175
  )});`,
195
- "return fn.r ? promise : getResult();"
196
- ])}`,
197
- `${cst} done = ${runtimeTemplate.expressionFunction(
198
- `(err ? reject(promise[webpackError] = err) : outerResolve(exports)), resolveQueue(queue)${
199
- defer
200
- ? ", promise[webpackDone] = true, module.evaluatingAsync = false"
201
- : ""
202
- }`,
203
- "err"
204
- )}`,
205
- // Track the async body's whole lifetime (evaluating +
206
- // evaluating-async states) with a dedicated flag — the sync require
207
- // wrapper clears `module.evaluating` as soon as `.a` returns, so a
208
- // deferred namespace reaching this module through a cycle relies on
209
- // `evaluatingAsync` to keep throwing until it is fully evaluated.
210
- defer ? "module.evaluatingAsync = true;" : "",
211
- "body(handle, done);",
212
- `${runtimeTemplate.optionalChaining("queue", "d < 0")} && (queue.d = 0);`
213
- ])};`
176
+ "promise[webpackExports] = exports;",
177
+ `promise[webpackQueues] = ${runtimeTemplate.expressionFunction(
178
+ `queue && fn(queue), depQueues.forEach(fn), promise["catch"](${runtimeTemplate.emptyFunction()})`,
179
+ "fn"
180
+ )};`,
181
+ "module.exports = promise;",
182
+ `${cst} handle = ${runtimeTemplate.basicFunction("deps", [
183
+ "currentDeps = wrapDeps(deps);",
184
+ `${lt} fn;`,
185
+ `${cst} getResult = ${runtimeTemplate.returningFunction(
186
+ `currentDeps.map(${runtimeTemplate.basicFunction("d", [
187
+ defer ? "if(d[webpackDefer]) return d;" : "",
188
+ "if(d[webpackError]) throw d[webpackError];",
189
+ "return d[webpackExports];"
190
+ ])})`
191
+ )}`,
192
+ `${cst} promise = new Promise(${runtimeTemplate.basicFunction(
193
+ "resolve",
194
+ [
195
+ `fn = ${runtimeTemplate.expressionFunction(
196
+ "resolve(getResult)",
197
+ ""
198
+ )};`,
199
+ "fn.r = 0;",
200
+ `${cst} fnQueue = ${runtimeTemplate.expressionFunction(
201
+ "q !== queue && !depQueues.has(q) && (depQueues.add(q), q && !q.d && (fn.r++, q.push(fn)))",
202
+ "q"
203
+ )};`,
204
+ `currentDeps.forEach(${runtimeTemplate.expressionFunction(
205
+ `${
206
+ defer ? "dep[webpackDefer]||" : ""
207
+ }dep[webpackQueues](fnQueue)`,
208
+ "dep"
209
+ )});`
210
+ ]
211
+ )});`,
212
+ "return fn.r ? promise : getResult();"
213
+ ])}`,
214
+ // One `[[EvaluationError]]` is recorded for a whole strongly-connected
215
+ // component, so a peer that already fulfilled must report it too.
216
+ ...(strictErrors
217
+ ? [
218
+ `${cst} group = cycleGroup === undefined ? undefined : (cycleGroups[cycleGroup] = cycleGroups[cycleGroup] || []);`,
219
+ // Ids, not module objects: hot replacement swaps a member for a
220
+ // new object under the same id, and the error belongs to that one.
221
+ "group && group.indexOf(module.id) < 0 && group.push(module.id);",
222
+ `${cst} markCycle = ${runtimeTemplate.expressionFunction(
223
+ `group && group.forEach(${runtimeTemplate.basicFunction(
224
+ "id",
225
+ [
226
+ `${cst} peer = __webpack_module_cache__[id];`,
227
+ "if (peer && peer.error === undefined) peer.error = err;"
228
+ ]
229
+ )})`,
230
+ "err"
231
+ )};`
232
+ ]
233
+ : []),
234
+ `${cst} done = ${runtimeTemplate.expressionFunction(
235
+ `(err ? ${rejectExpression} : outerResolve(exports)), resolveQueue(queue)${
236
+ defer
237
+ ? ", promise[webpackDone] = true, module.evaluatingAsync = false"
238
+ : ""
239
+ }`,
240
+ "err"
241
+ )}`,
242
+ // Track the async body's whole lifetime (evaluating +
243
+ // evaluating-async states) with a dedicated flag — the sync require
244
+ // wrapper clears `module.evaluating` as soon as `.a` returns, so a
245
+ // deferred namespace reaching this module through a cycle relies on
246
+ // `evaluatingAsync` to keep throwing until it is fully evaluated.
247
+ defer ? "module.evaluatingAsync = true;" : "",
248
+ "body(handle, done);",
249
+ `${runtimeTemplate.optionalChaining("queue", "d < 0")} && (queue.d = 0);`
250
+ ]
251
+ )};`
214
252
  ]);
215
253
  }
216
254
  }
@@ -17,6 +17,15 @@ class AutoPublicPathRuntimeModule extends RuntimeModule {
17
17
  super("publicPath", RuntimeModule.STAGE_BASIC);
18
18
  }
19
19
 
20
+ /**
21
+ * The `[handlerMap, key]` pairs this module installs onto a chunk handler map
22
+ * such as `__webpack_require__.f`, or `null` where it cannot name them.
23
+ * @returns {[string, string][] | null} installed chunk handlers (do not mutate)
24
+ */
25
+ getInstalledChunkHandlers() {
26
+ return RuntimeModule.NO_CHUNK_HANDLERS;
27
+ }
28
+
20
29
  /**
21
30
  * Generates runtime code for this runtime module.
22
31
  * @returns {string | null} runtime code
@@ -32,6 +32,15 @@ class BaseUriRuntimeModule extends RuntimeModule {
32
32
  return false;
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
+ return RuntimeModule.NO_CHUNK_HANDLERS;
42
+ }
43
+
35
44
  /**
36
45
  * Generates runtime code for this runtime module.
37
46
  * @returns {string | null} runtime code
@@ -27,6 +27,15 @@ class ChunkNameRuntimeModule extends RuntimeModule {
27
27
  this.chunkName = chunkName;
28
28
  }
29
29
 
30
+ /**
31
+ * The `[handlerMap, key]` pairs this module installs onto a chunk handler map
32
+ * such as `__webpack_require__.f`, or `null` where it cannot name them.
33
+ * @returns {[string, string][] | null} installed chunk handlers (do not mutate)
34
+ */
35
+ getInstalledChunkHandlers() {
36
+ return RuntimeModule.NO_CHUNK_HANDLERS;
37
+ }
38
+
30
39
  /**
31
40
  * Generates runtime code for this runtime module.
32
41
  * @returns {string | null} runtime code
@@ -7,6 +7,8 @@
7
7
  const RuntimeGlobals = require("../RuntimeGlobals");
8
8
  const RuntimeModule = require("../RuntimeModule");
9
9
  const Template = require("../Template");
10
+ const { getOnlyHandlerKey } = require("../util/handlerKeys");
11
+ const { propertyAccess } = require("../util/property");
10
12
 
11
13
  /** @import Compilation from "../Compilation" */
12
14
  /** @import { ReadOnlyRuntimeRequirements } from "../Module" */
@@ -31,6 +33,17 @@ class EnsureChunkRuntimeModule extends RuntimeModule {
31
33
  this.runtimeRequirements = runtimeRequirements;
32
34
  }
33
35
 
36
+ /**
37
+ * The `[handlerMap, key]` pairs this module installs onto a chunk handler map
38
+ * such as `__webpack_require__.f`, or `null` where it cannot name them.
39
+ * @returns {[string, string][] | null} installed chunk handlers (do not mutate)
40
+ */
41
+ getInstalledChunkHandlers() {
42
+ // Reads a map rather than installing onto one, so reading its code back would
43
+ // render it in a cycle.
44
+ return RuntimeModule.NO_CHUNK_HANDLERS;
45
+ }
46
+
34
47
  /**
35
48
  * Generates runtime code for this runtime module.
36
49
  * @returns {string | null} runtime code
@@ -38,8 +51,8 @@ class EnsureChunkRuntimeModule extends RuntimeModule {
38
51
  generate() {
39
52
  const compilation = /** @type {Compilation} */ (this.compilation);
40
53
  const { runtimeTemplate } = compilation;
41
- // An analyzable `import()` dispatches the handlers itself, so a build can need the
42
- // map without the function around it.
54
+ // HMR force-loads through the handler map by bare chunk id, so a build can need
55
+ // the map without the function around it.
43
56
  const withEnsureChunk = this.runtimeRequirements.has(
44
57
  RuntimeGlobals.ensureChunk
45
58
  );
@@ -50,24 +63,30 @@ class EnsureChunkRuntimeModule extends RuntimeModule {
50
63
  );
51
64
  const handlers = RuntimeGlobals.ensureChunkHandlers;
52
65
  if (!withEnsureChunk) return `${handlers} = {};`;
66
+ const args = `chunkId${withFetchPriority ? ", fetchPriority" : ""}`;
67
+ const forwarded = `chunkId, promises${
68
+ withFetchPriority ? ", fetchPriority" : ""
69
+ }`;
70
+ const only = getOnlyHandlerKey(this, handlers);
71
+ // One handler needs no walk over the others, and most chunks carry one.
72
+ const body =
73
+ only === null
74
+ ? `return Promise.all(Object.keys(${handlers}).reduce(${runtimeTemplate.basicFunction(
75
+ "promises, key",
76
+ [`${handlers}[key](${forwarded});`, "return promises;"]
77
+ )}, []));`
78
+ : Template.asString([
79
+ `${runtimeTemplate.renderConst()} promises = [];`,
80
+ `${handlers}${propertyAccess([only])}(${forwarded});`,
81
+ "return Promise.all(promises);"
82
+ ]);
53
83
  return Template.asString([
54
84
  `${handlers} = {};`,
55
85
  "// This file contains only the entry chunk.",
56
86
  "// The chunk loading function for additional chunks",
57
- `${RuntimeGlobals.ensureChunk} = ${runtimeTemplate.basicFunction(
58
- `chunkId${withFetchPriority ? ", fetchPriority" : ""}`,
59
- [
60
- `return Promise.all(Object.keys(${handlers}).reduce(${runtimeTemplate.basicFunction(
61
- "promises, key",
62
- [
63
- `${handlers}[key](chunkId, promises${
64
- withFetchPriority ? ", fetchPriority" : ""
65
- });`,
66
- "return promises;"
67
- ]
68
- )}, []));`
69
- ]
70
- )};`
87
+ `${RuntimeGlobals.ensureChunk} = ${runtimeTemplate.basicFunction(args, [
88
+ body
89
+ ])};`
71
90
  ]);
72
91
  }
73
92
  // There ensureChunk is used somewhere in the tree, so we need an empty requireEnsure
@@ -67,6 +67,15 @@ class GetChunkFilenameRuntimeModule extends RuntimeModule {
67
67
  }
68
68
  }
69
69
 
70
+ /**
71
+ * The `[handlerMap, key]` pairs this module installs onto a chunk handler map
72
+ * such as `__webpack_require__.f`, or `null` where it cannot name them.
73
+ * @returns {[string, string][] | null} installed chunk handlers (do not mutate)
74
+ */
75
+ getInstalledChunkHandlers() {
76
+ return RuntimeModule.NO_CHUNK_HANDLERS;
77
+ }
78
+
70
79
  /**
71
80
  * Generates runtime code for this runtime module.
72
81
  * @returns {string | null} runtime code
@@ -26,6 +26,15 @@ class GetFullHashRuntimeModule extends RuntimeModule {
26
26
  return false;
27
27
  }
28
28
 
29
+ /**
30
+ * The `[handlerMap, key]` pairs this module installs onto a chunk handler map
31
+ * such as `__webpack_require__.f`, or `null` where it cannot name them.
32
+ * @returns {[string, string][] | null} installed chunk handlers (do not mutate)
33
+ */
34
+ getInstalledChunkHandlers() {
35
+ return RuntimeModule.NO_CHUNK_HANDLERS;
36
+ }
37
+
29
38
  /**
30
39
  * Generates runtime code for this runtime module.
31
40
  * @returns {string | null} runtime code
@@ -35,6 +35,15 @@ class GetMainFilenameRuntimeModule extends RuntimeModule {
35
35
  this.filename = filename;
36
36
  }
37
37
 
38
+ /**
39
+ * The `[handlerMap, key]` pairs this module installs onto a chunk handler map
40
+ * such as `__webpack_require__.f`, or `null` where it cannot name them.
41
+ * @returns {[string, string][] | null} installed chunk handlers (do not mutate)
42
+ */
43
+ getInstalledChunkHandlers() {
44
+ return RuntimeModule.NO_CHUNK_HANDLERS;
45
+ }
46
+
38
47
  /**
39
48
  * Generates runtime code for this runtime module.
40
49
  * @returns {string | null} runtime code
@@ -33,6 +33,15 @@ class GetWorkletBootstrapRuntimeModule extends RuntimeModule {
33
33
  return false;
34
34
  }
35
35
 
36
+ /**
37
+ * The `[handlerMap, key]` pairs this module installs onto a chunk handler map
38
+ * such as `__webpack_require__.f`, or `null` where it cannot name them.
39
+ * @returns {[string, string][] | null} installed chunk handlers (do not mutate)
40
+ */
41
+ getInstalledChunkHandlers() {
42
+ return RuntimeModule.NO_CHUNK_HANDLERS;
43
+ }
44
+
36
45
  /**
37
46
  * Generates runtime code for this runtime module.
38
47
  * @returns {string | null} runtime code