webpack 5.108.3 → 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 (191) 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 +50 -8
  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/FlagDependencyExportsPlugin.js +55 -8
  16. package/lib/HotModuleReplacementPlugin.js +18 -15
  17. package/lib/LazyBarrel.js +30 -3
  18. package/lib/Module.js +3 -0
  19. package/lib/ModuleFilenameHelpers.js +2 -2
  20. package/lib/ModuleTypeConstants.js +8 -1
  21. package/lib/MultiCompiler.js +13 -2
  22. package/lib/MultiWatching.js +1 -0
  23. package/lib/NodeStuffPlugin.js +51 -33
  24. package/lib/NormalModule.js +169 -405
  25. package/lib/NormalModuleFactory.js +76 -2
  26. package/lib/ProgressPlugin.js +211 -119
  27. package/lib/ProvidePlugin.js +2 -2
  28. package/lib/RuntimeGlobals.js +47 -0
  29. package/lib/RuntimePlugin.js +33 -0
  30. package/lib/RuntimeTemplate.js +304 -16
  31. package/lib/UseStrictPlugin.js +1 -1
  32. package/lib/WebpackIsIncludedPlugin.js +1 -1
  33. package/lib/WebpackOptionsApply.js +24 -19
  34. package/lib/asset/AssetGenerator.js +110 -28
  35. package/lib/asset/AssetModulesPlugin.js +92 -2
  36. package/lib/asset/WebManifestGenerator.js +164 -0
  37. package/lib/asset/WebManifestParser.js +130 -0
  38. package/lib/async-modules/AwaitDependenciesInitFragment.js +14 -4
  39. package/lib/async-modules/isGeneratorLowered.js +26 -0
  40. package/lib/cache/PackFileCacheStrategy.js +9 -3
  41. package/lib/config/browserslistTargetHandler.js +40 -0
  42. package/lib/config/defaults.js +222 -32
  43. package/lib/config/normalization.js +26 -0
  44. package/lib/config/target.js +9 -1
  45. package/lib/css/CssGenerator.js +73 -73
  46. package/lib/css/CssLoadingRuntimeModule.js +5 -1
  47. package/lib/css/CssModulesPlugin.js +92 -53
  48. package/lib/css/CssParser.js +843 -302
  49. package/lib/css/syntax.js +1219 -483
  50. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -6
  51. package/lib/dependencies/AMDPlugin.js +2 -2
  52. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +13 -13
  53. package/lib/dependencies/CommonJsDependencyHelpers.js +39 -0
  54. package/lib/dependencies/CommonJsExportsDependency.js +47 -2
  55. package/lib/dependencies/CommonJsExportsParserPlugin.js +10 -10
  56. package/lib/dependencies/CommonJsImportsParserPlugin.js +18 -18
  57. package/lib/dependencies/CommonJsPlugin.js +2 -2
  58. package/lib/dependencies/CommonJsRequireDependency.js +26 -1
  59. package/lib/dependencies/CommonJsSelfReferenceDependency.js +32 -1
  60. package/lib/dependencies/ContextDependencyHelpers.js +3 -3
  61. package/lib/dependencies/CreateRequireParserPlugin.js +6 -6
  62. package/lib/dependencies/CssIcssExportDependency.js +190 -87
  63. package/lib/dependencies/CssUrlDependency.js +35 -4
  64. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +2 -2
  65. package/lib/dependencies/HarmonyCompatibilityDependency.js +32 -14
  66. package/lib/dependencies/HarmonyDetectionParserPlugin.js +43 -13
  67. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +7 -19
  68. package/lib/dependencies/HarmonyImportDependency.js +12 -1
  69. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +34 -107
  70. package/lib/dependencies/HarmonyImportGuard.js +192 -20
  71. package/lib/dependencies/HarmonyModulesPlugin.js +6 -0
  72. package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +1 -1
  73. package/lib/dependencies/HtmlEntryDependency.js +797 -172
  74. package/lib/dependencies/HtmlSourceDependency.js +26 -0
  75. package/lib/dependencies/ImportDependency.js +43 -1
  76. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +31 -18
  77. package/lib/dependencies/ImportMetaContextPlugin.js +38 -7
  78. package/lib/dependencies/ImportMetaGlobDependency.js +81 -0
  79. package/lib/dependencies/ImportMetaGlobDependencyParserPlugin.js +78 -0
  80. package/lib/dependencies/ImportMetaGlobHelpers.js +660 -0
  81. package/lib/dependencies/ImportMetaPlugin.js +532 -180
  82. package/lib/dependencies/ImportMetaResolveDependency.js +90 -0
  83. package/lib/dependencies/ImportParserPlugin.js +87 -26
  84. package/lib/dependencies/ImportPhase.js +10 -8
  85. package/lib/dependencies/LoaderPlugin.js +5 -1
  86. package/lib/dependencies/RequireContextDependencyParserPlugin.js +1 -1
  87. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +3 -6
  88. package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +4 -11
  89. package/lib/dependencies/SystemPlugin.js +2 -4
  90. package/lib/dependencies/TopLevelAwaitDependency.js +93 -0
  91. package/lib/dependencies/URLDependency.js +141 -21
  92. package/lib/dependencies/{WorkerPlugin.js → WorkerAndWorkletPlugin.js} +324 -112
  93. package/lib/dependencies/WorkerDependency.js +86 -18
  94. package/lib/dependencies/WorkletDependency.js +278 -0
  95. package/lib/dll/DelegatedModuleFactoryPlugin.js +19 -0
  96. package/lib/errors/EnvironmentNotSupportAsyncWarning.js +1 -1
  97. package/lib/errors/LoaderLoadingError.js +20 -0
  98. package/lib/errors/ModuleParseError.js +39 -22
  99. package/lib/errors/NodeStuffInWebError.js +1 -1
  100. package/lib/esm/ModuleChunkFormatPlugin.js +47 -14
  101. package/lib/esm/ModuleChunkLoadingPlugin.js +8 -1
  102. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +29 -1
  103. package/lib/hmr/lazyCompilationBackend.js +32 -8
  104. package/lib/html/HtmlGenerator.js +940 -91
  105. package/lib/html/HtmlModule.js +3 -2
  106. package/lib/html/HtmlModulesPlugin.js +625 -170
  107. package/lib/html/HtmlParser.js +812 -340
  108. package/lib/html/favicon.svg +1 -0
  109. package/lib/html/syntax.js +2116 -834
  110. package/lib/ids/IdHelpers.js +1 -1
  111. package/lib/index.js +6 -0
  112. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +4 -5
  113. package/lib/javascript/BasicEvaluatedExpression.js +366 -48
  114. package/lib/javascript/JavascriptGenerator.js +197 -49
  115. package/lib/javascript/JavascriptModulesPlugin.js +178 -24
  116. package/lib/javascript/JavascriptParser.js +711 -355
  117. package/lib/javascript/JavascriptParserHelpers.js +3 -6
  118. package/lib/javascript/syntax.js +4380 -0
  119. package/lib/library/ModuleLibraryPlugin.js +38 -1
  120. package/lib/loaders/LoaderRunner.js +714 -0
  121. package/lib/loaders/loadLoader.js +100 -0
  122. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +19 -0
  123. package/lib/node/ReadFileCompileWasmPlugin.js +14 -0
  124. package/lib/optimize/ConcatenatedModule.js +120 -16
  125. package/lib/optimize/FlagIncludedChunksPlugin.js +13 -3
  126. package/lib/optimize/InnerGraphPlugin.js +50 -30
  127. package/lib/optimize/ModuleConcatenationPlugin.js +69 -3
  128. package/lib/optimize/SideEffectsFlagPlugin.js +86 -43
  129. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +15 -0
  130. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +24 -13
  131. package/lib/prefetch/ResourceHintPlugin.js +663 -0
  132. package/lib/prefetch/ResourceHintRuntimeModule.js +149 -0
  133. package/lib/prefetch/StartupAssetHintRuntimeModule.js +210 -0
  134. package/lib/prefetch/parseResourceHintOptions.js +103 -0
  135. package/lib/rules/RuleSetCompiler.js +114 -0
  136. package/lib/runtime/AsyncModuleGeneratorRuntimeModule.js +56 -0
  137. package/lib/runtime/AsyncModuleRuntimeModule.js +24 -8
  138. package/lib/runtime/AutoPublicPathRuntimeModule.js +7 -1
  139. package/lib/runtime/CommonJsWrapRuntimeModule.js +37 -0
  140. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +59 -0
  141. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +204 -8
  142. package/lib/runtime/SetAnonymousDefaultNameRuntimeModule.js +4 -1
  143. package/lib/schemes/HttpUriPlugin.js +40 -1
  144. package/lib/schemes/VirtualUrlPlugin.js +1 -2
  145. package/lib/serialization/FileMiddleware.js +29 -3
  146. package/lib/stats/DefaultStatsFactoryPlugin.js +32 -3
  147. package/lib/stats/DefaultStatsPresetPlugin.js +2 -0
  148. package/lib/stats/DefaultStatsPrinterPlugin.js +12 -2
  149. package/lib/stats/StatsFactory.js +15 -8
  150. package/lib/url/URLParserPlugin.js +98 -19
  151. package/lib/util/AsyncQueue.js +122 -72
  152. package/lib/util/LocConverter.js +9 -8
  153. package/lib/util/SetHelpers.js +1 -1
  154. package/lib/util/SourceProcessor.js +41 -28
  155. package/lib/util/StackedMap.js +122 -48
  156. package/lib/util/binarySearchBounds.js +2 -2
  157. package/lib/util/concatenate.js +40 -14
  158. package/lib/util/createHooksRegistry.js +13 -5
  159. package/lib/util/dataURL.js +2 -2
  160. package/lib/util/deterministicGrouping.js +7 -5
  161. package/lib/util/formatSize.js +6 -2
  162. package/lib/util/globUtils.js +710 -0
  163. package/lib/util/identifier.js +23 -6
  164. package/lib/util/implicitTypeLoaderFallback.js +62 -0
  165. package/lib/util/internalSerializables.js +88 -71
  166. package/lib/util/magicComment.js +121 -25
  167. package/lib/util/numberHash.js +2 -2
  168. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +24 -18
  169. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +33 -22
  170. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +79 -16
  171. package/lib/web/FetchCompileAsyncWasmPlugin.js +19 -0
  172. package/lib/web/FetchCompileWasmPlugin.js +14 -0
  173. package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -0
  174. package/lib/webpack.js +65 -0
  175. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +3 -0
  176. package/module.d.ts +21 -0
  177. package/package.json +14 -13
  178. package/schemas/WebpackOptions.check.js +1 -1
  179. package/schemas/WebpackOptions.json +759 -36
  180. package/schemas/plugins/HtmlParserOptions.check.js +1 -1
  181. package/schemas/plugins/ProgressPlugin.check.js +1 -1
  182. package/schemas/plugins/ProgressPlugin.json +17 -1
  183. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  184. package/schemas/plugins/container/ContainerReferencePlugin.json +1 -0
  185. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  186. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  187. package/schemas/plugins/container/ModuleFederationPlugin.json +1 -0
  188. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +1 -1
  189. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  190. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  191. package/types.d.ts +1300 -325
@@ -41,6 +41,7 @@ const NAMED_PRESETS = {
41
41
  relatedAssets: true,
42
42
  entrypoints: true,
43
43
  chunkGroups: true,
44
+ chunkGroupResourceHints: true,
44
45
  ids: true,
45
46
  modules: false,
46
47
  chunks: true,
@@ -210,6 +211,7 @@ const DEFAULTS = {
210
211
  chunkGroups: OFF_FOR_TO_STRING,
211
212
  chunkGroupAuxiliary: OFF_FOR_TO_STRING,
212
213
  chunkGroupChildren: OFF_FOR_TO_STRING,
214
+ chunkGroupResourceHints: OFF_FOR_TO_STRING,
213
215
  chunkGroupMaxAssets: (o, { forToString }) => (forToString ? 5 : Infinity),
214
216
  chunks: OFF_FOR_TO_STRING,
215
217
  chunkRelations: OFF_FOR_TO_STRING,
@@ -508,8 +508,18 @@ const MODULE_SIMPLE_PRINTERS = {
508
508
  "module.chunks[]": (id, { formatChunkId }) => formatChunkId(id),
509
509
  "module.depth": (depth, { formatFlag }) =>
510
510
  depth !== null ? formatFlag(`depth ${depth}`) : undefined,
511
- "module.cacheable": (cacheable, { formatFlag, red }) =>
512
- cacheable === false ? red(formatFlag("not cacheable")) : undefined,
511
+ "module.cacheable": (cacheable, { formatFlag, red, module }) =>
512
+ cacheable === false
513
+ ? red(
514
+ formatFlag(
515
+ module.notCacheableReasons && module.notCacheableReasons.length > 0
516
+ ? `not cacheable: ${module.notCacheableReasons.join(", ")}`
517
+ : "not cacheable"
518
+ )
519
+ )
520
+ : undefined,
521
+ // rendered as part of the "module.cacheable" flag
522
+ "module.notCacheableReasons": () => undefined,
513
523
  "module.orphan": (orphan, { formatFlag, yellow }) =>
514
524
  orphan ? yellow(formatFlag("orphan")) : undefined,
515
525
  // "module.runtime": (runtime, { formatFlag, yellow }) =>
@@ -310,23 +310,30 @@ class StatsFactory {
310
310
  false
311
311
  );
312
312
 
313
- // for each item
313
+ // reuse one item context; create() spreads it synchronously, so mutating
314
+ // `_index`/the name key between items is safe and skips a per-item spread
315
+ /** @type {StatsFactoryContext} */
316
+ const itemContext = { ...context };
317
+ const itemNameType = `${type}[]`;
318
+ /** @type {string | void} */
319
+ let prevItemName;
314
320
  let resultItems = items2.map((item, i) => {
315
- /** @type {StatsFactoryContext} */
316
- const itemContext = {
317
- ...context,
318
- _index: i
319
- };
321
+ itemContext._index = i;
320
322
 
321
323
  // run getItemName
322
324
  const itemName = this._forEachLevel(
323
325
  this.hooks.getItemName,
324
326
  this._caches.getItemName,
325
- `${type}[]`,
327
+ itemNameType,
326
328
  (h) => h.call(item, itemContext)
327
329
  );
330
+ // drop a previous item's name key before adding this one's
331
+ if (prevItemName !== undefined && prevItemName !== itemName) {
332
+ delete itemContext[prevItemName];
333
+ }
328
334
  if (itemName) itemContext[itemName] = item;
329
- const innerType = itemName ? `${type}[].${itemName}` : `${type}[]`;
335
+ prevItemName = itemName;
336
+ const innerType = itemName ? `${type}[].${itemName}` : itemNameType;
330
337
 
331
338
  // run getItemFactory
332
339
  const itemFactory =
@@ -9,6 +9,9 @@ const { pathToFileURL } = require("url");
9
9
  const RuntimeGlobals = require("../RuntimeGlobals");
10
10
  const ConstDependency = require("../dependencies/ConstDependency");
11
11
  const ContextDependencyHelpers = require("../dependencies/ContextDependencyHelpers");
12
+ const {
13
+ isImportMetaFieldEnabled
14
+ } = require("../dependencies/ImportMetaPlugin");
12
15
  const URLContextDependency = require("../dependencies/URLContextDependency");
13
16
  const URLDependency = require("../dependencies/URLDependency");
14
17
  const CommentCompilationWarning = require("../errors/CommentCompilationWarning");
@@ -16,6 +19,7 @@ const UnsupportedFeatureWarning = require("../errors/UnsupportedFeatureWarning")
16
19
  const BasicEvaluatedExpression = require("../javascript/BasicEvaluatedExpression");
17
20
  const { approve } = require("../javascript/JavascriptParserHelpers");
18
21
  const { getInnerGraphUtils } = require("../optimize/InnerGraph");
22
+ const ResourceHintPlugin = require("../prefetch/ResourceHintPlugin");
19
23
 
20
24
  /** @typedef {import("estree").MemberExpression} MemberExpression */
21
25
  /** @typedef {import("estree").NewExpression} NewExpressionNode */
@@ -56,6 +60,32 @@ const isMetaUrl = (parser, arg) => {
56
60
  return true;
57
61
  };
58
62
 
63
+ /**
64
+ * Whether the request points to a directory and thus can't be an asset.
65
+ * @param {string} request request
66
+ * @returns {boolean} true when the request is a directory reference
67
+ */
68
+ const isDirectoryRequest = (request) =>
69
+ request === "." || request === ".." || request.endsWith("/");
70
+
71
+ /**
72
+ * Replaces `import.meta.url` with the runtime base URI, leaving the
73
+ * `new URL(...)` construction untouched so it's evaluated at runtime.
74
+ * @param {JavascriptParser} parser parser
75
+ * @param {NewExpressionNode} expr expression
76
+ * @returns {void}
77
+ */
78
+ const keepNewURL = (parser, expr) => {
79
+ const [, arg2] = expr.arguments;
80
+ const dep = new ConstDependency(
81
+ RuntimeGlobals.baseURI,
82
+ /** @type {Range} */ (arg2.range),
83
+ [RuntimeGlobals.baseURI]
84
+ );
85
+ dep.loc = parser.getLocation(expr);
86
+ parser.state.module.addPresentationalDependency(dep);
87
+ };
88
+
59
89
  /** @type {WeakMap<NewExpressionNode, BasicEvaluatedExpression | undefined>} */
60
90
  const getEvaluatedExprCache = new WeakMap();
61
91
 
@@ -63,9 +93,10 @@ const getEvaluatedExprCache = new WeakMap();
63
93
  * Gets evaluated expr.
64
94
  * @param {NewExpressionNode} expr expression
65
95
  * @param {JavascriptParser} parser parser parser
96
+ * @param {boolean} importMetaUrlEnabled true when import.meta.url should be handled
66
97
  * @returns {BasicEvaluatedExpression | undefined} basic evaluated expression
67
98
  */
68
- const getEvaluatedExpr = (expr, parser) => {
99
+ const getEvaluatedExpr = (expr, parser, importMetaUrlEnabled) => {
69
100
  let result = getEvaluatedExprCache.get(expr);
70
101
  if (result !== undefined) return result;
71
102
 
@@ -81,7 +112,9 @@ const getEvaluatedExpr = (expr, parser) => {
81
112
  if (arg2.type !== "MemberExpression" || arg1.type === "SpreadElement") {
82
113
  return;
83
114
  }
84
- if (!isMetaUrl(parser, arg2)) return;
115
+ if (!importMetaUrlEnabled || !isMetaUrl(parser, arg2)) {
116
+ return;
117
+ }
85
118
 
86
119
  return parser.evaluateExpression(arg1);
87
120
  };
@@ -92,6 +125,13 @@ const getEvaluatedExpr = (expr, parser) => {
92
125
  return result;
93
126
  };
94
127
 
128
+ /**
129
+ * @typedef {object} ResolvedResourceHints
130
+ * @property {boolean=} prefetch project-wide prefetch default
131
+ * @property {boolean=} preload project-wide preload default
132
+ * @property {("low" | "high" | "auto" | false)=} fetchPriority project-wide fetchPriority default
133
+ */
134
+
95
135
  class URLParserPlugin {
96
136
  /**
97
137
  * Creates an instance of URLParserPlugin.
@@ -109,10 +149,18 @@ class URLParserPlugin {
109
149
  */
110
150
  apply(parser) {
111
151
  const relative = this.options.url === "relative";
152
+ const importMetaUrlEnabled = isImportMetaFieldEnabled(
153
+ this.options.importMeta,
154
+ "url"
155
+ );
112
156
 
113
157
  parser.hooks.canRename.for("URL").tap(PLUGIN_NAME, approve);
114
158
  parser.hooks.evaluateNewExpression.for("URL").tap(PLUGIN_NAME, (expr) => {
115
- const evaluatedExpr = getEvaluatedExpr(expr, parser);
159
+ const evaluatedExpr = getEvaluatedExpr(
160
+ expr,
161
+ parser,
162
+ importMetaUrlEnabled
163
+ );
116
164
  const request = evaluatedExpr && evaluatedExpr.asString();
117
165
 
118
166
  if (!request) return;
@@ -133,7 +181,7 @@ class URLParserPlugin {
133
181
  parser.state.module.addWarning(
134
182
  new CommentCompilationWarning(
135
183
  `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`,
136
- /** @type {DependencyLocation} */ (comment.loc)
184
+ parser.getLocation(comment)
137
185
  )
138
186
  );
139
187
  }
@@ -144,7 +192,7 @@ class URLParserPlugin {
144
192
  parser.state.module.addWarning(
145
193
  new UnsupportedFeatureWarning(
146
194
  `\`webpackIgnore\` expected a boolean, but received: ${importOptions.webpackIgnore}.`,
147
- /** @type {DependencyLocation} */ (expr.loc)
195
+ parser.getLocation(expr)
148
196
  )
149
197
  );
150
198
  return;
@@ -153,23 +201,25 @@ class URLParserPlugin {
153
201
 
154
202
  const [, arg2] = expr.arguments;
155
203
 
156
- if (arg2.type !== "MemberExpression" || !isMetaUrl(parser, arg2)) {
204
+ if (
205
+ arg2.type !== "MemberExpression" ||
206
+ !importMetaUrlEnabled ||
207
+ !isMetaUrl(parser, arg2)
208
+ ) {
157
209
  return;
158
210
  }
159
211
 
160
- const dep = new ConstDependency(
161
- RuntimeGlobals.baseURI,
162
- /** @type {Range} */ (arg2.range),
163
- [RuntimeGlobals.baseURI]
164
- );
165
- dep.loc = /** @type {DependencyLocation} */ (expr.loc);
166
- parser.state.module.addPresentationalDependency(dep);
212
+ keepNewURL(parser, expr);
167
213
 
168
214
  return true;
169
215
  }
170
216
  }
171
217
 
172
- const evaluatedExpr = getEvaluatedExpr(expr, parser);
218
+ const evaluatedExpr = getEvaluatedExpr(
219
+ expr,
220
+ parser,
221
+ importMetaUrlEnabled
222
+ );
173
223
  if (!evaluatedExpr) return;
174
224
 
175
225
  /** @type {string | undefined} */
@@ -177,6 +227,12 @@ class URLParserPlugin {
177
227
 
178
228
  // static URL
179
229
  if ((request = evaluatedExpr.asString())) {
230
+ // A directory is not an asset; keep `new URL(...)` as-is, matching Node/browsers.
231
+ if (isDirectoryRequest(request)) {
232
+ keepNewURL(parser, expr);
233
+ return true;
234
+ }
235
+
180
236
  const [arg1, arg2] = expr.arguments;
181
237
  const dep = new URLDependency(
182
238
  request,
@@ -187,8 +243,27 @@ class URLParserPlugin {
187
243
  /** @type {Range} */ (expr.range),
188
244
  relative
189
245
  );
190
- dep.loc = /** @type {DependencyLocation} */ (expr.loc);
246
+ dep.loc = parser.getLocation(expr);
247
+ // `parser.javascript.urlHints` provides project-wide defaults
248
+ // (resolved per-request, with `test` / `include` / `exclude`
249
+ // matching); a per-URL magic comment for the same hint wins
250
+ // when both are set.
251
+ ResourceHintPlugin.applyResourceHints(
252
+ dep,
253
+ this.options.urlHints,
254
+ request,
255
+ importOptions,
256
+ parser.state.module,
257
+ parser.getLocation(expr)
258
+ );
191
259
  parser.state.current.addDependency(dep);
260
+ // For ESM module output the template embeds the asset's resolved
261
+ // filename, so the asset must be code-generated first. Only added in
262
+ // that mode — a code-gen dependency on an asset that a later watch
263
+ // rebuild leaves unaffected can otherwise deadlock the scheduler.
264
+ if (parser.state.compilation.options.output.module) {
265
+ parser.state.module.addCodeGenerationDependency(dep);
266
+ }
192
267
  getInnerGraphUtils(parser.state.compilation).onUsage(
193
268
  parser.state,
194
269
  (e) => (dep.usedByExports = e)
@@ -213,7 +288,7 @@ class URLParserPlugin {
213
288
  parser.state.module.addWarning(
214
289
  new UnsupportedFeatureWarning(
215
290
  `\`webpackInclude\` expected a regular expression, but received: ${importOptions.webpackInclude}.`,
216
- /** @type {DependencyLocation} */ (expr.loc)
291
+ parser.getLocation(expr)
217
292
  )
218
293
  );
219
294
  } else {
@@ -228,7 +303,7 @@ class URLParserPlugin {
228
303
  parser.state.module.addWarning(
229
304
  new UnsupportedFeatureWarning(
230
305
  `\`webpackExclude\` expected a regular expression, but received: ${importOptions.webpackExclude}.`,
231
- /** @type {DependencyLocation} */ (expr.loc)
306
+ parser.getLocation(expr)
232
307
  )
233
308
  );
234
309
  } else {
@@ -252,7 +327,7 @@ class URLParserPlugin {
252
327
  parser
253
328
  );
254
329
  if (!dep) return;
255
- dep.loc = /** @type {DependencyLocation} */ (expr.loc);
330
+ dep.loc = parser.getLocation(expr);
256
331
  dep.optional = Boolean(parser.scope.inTry);
257
332
  parser.state.current.addDependency(dep);
258
333
  return true;
@@ -264,7 +339,11 @@ class URLParserPlugin {
264
339
  const calleeInfo = parser.getFreeInfoFromVariable(callee.name);
265
340
  if (!calleeInfo || calleeInfo.name !== "URL") return;
266
341
 
267
- const evaluatedExpr = getEvaluatedExpr(expr, parser);
342
+ const evaluatedExpr = getEvaluatedExpr(
343
+ expr,
344
+ parser,
345
+ importMetaUrlEnabled
346
+ );
268
347
  const request = evaluatedExpr && evaluatedExpr.asString();
269
348
 
270
349
  if (request) return true;
@@ -159,6 +159,11 @@ class AsyncQueue {
159
159
  */
160
160
  add(item, callback) {
161
161
  if (this._stopped) return callback(new WebpackError("Queue was stopped"));
162
+ // skip async hook dispatch when unused — this runs per module × queue
163
+ if (!this.hooks.beforeAdd.isUsed()) {
164
+ this._add(item, callback);
165
+ return;
166
+ }
162
167
  this.hooks.beforeAdd.callAsync(item, (err) => {
163
168
  if (err) {
164
169
  callback(
@@ -166,42 +171,52 @@ class AsyncQueue {
166
171
  );
167
172
  return;
168
173
  }
169
- const key = this._getKey(item);
170
- const entry = this._entries.get(key);
171
- if (entry !== undefined) {
172
- if (entry.state === DONE_STATE) {
173
- if (inHandleResult++ > 3) {
174
- process.nextTick(() => callback(entry.error, entry.result));
175
- } else {
176
- callback(entry.error, entry.result);
177
- }
178
- inHandleResult--;
179
- } else if (entry.callbacks === undefined) {
180
- entry.callbacks = [callback];
174
+ this._add(item, callback);
175
+ });
176
+ }
177
+
178
+ /**
179
+ * Processes the provided item, after the beforeAdd hook.
180
+ * @param {T} item an item
181
+ * @param {Callback<R>} callback callback function
182
+ * @returns {void}
183
+ */
184
+ _add(item, callback) {
185
+ const key = this._getKey(item);
186
+ const entry = this._entries.get(key);
187
+ if (entry !== undefined) {
188
+ if (entry.state === DONE_STATE) {
189
+ if (inHandleResult++ > 3) {
190
+ process.nextTick(() => callback(entry.error, entry.result));
181
191
  } else {
182
- entry.callbacks.push(callback);
192
+ callback(entry.error, entry.result);
183
193
  }
184
- return;
185
- }
186
- const newEntry = new AsyncQueueEntry(item, callback);
187
- if (this._stopped) {
188
- this.hooks.added.call(item);
189
- this._root._activeTasks++;
190
- process.nextTick(() =>
191
- this._handleResult(newEntry, new WebpackError("Queue was stopped"))
192
- );
194
+ inHandleResult--;
195
+ } else if (entry.callbacks === undefined) {
196
+ entry.callbacks = [callback];
193
197
  } else {
194
- this._entries.set(key, newEntry);
195
- this._queued.enqueue(newEntry);
196
- const root = this._root;
197
- root._needProcessing = true;
198
- if (root._willEnsureProcessing === false) {
199
- root._willEnsureProcessing = true;
200
- setImmediate(root._ensureProcessing);
201
- }
202
- this.hooks.added.call(item);
198
+ entry.callbacks.push(callback);
203
199
  }
204
- });
200
+ return;
201
+ }
202
+ const newEntry = new AsyncQueueEntry(item, callback);
203
+ if (this._stopped) {
204
+ this.hooks.added.call(item);
205
+ this._root._activeTasks++;
206
+ process.nextTick(() =>
207
+ this._handleResult(newEntry, new WebpackError("Queue was stopped"))
208
+ );
209
+ } else {
210
+ this._entries.set(key, newEntry);
211
+ this._queued.enqueue(newEntry);
212
+ const root = this._root;
213
+ root._needProcessing = true;
214
+ if (root._willEnsureProcessing === false) {
215
+ root._willEnsureProcessing = true;
216
+ setImmediate(root._ensureProcessing);
217
+ }
218
+ this.hooks.added.call(item);
219
+ }
205
220
  }
206
221
 
207
222
  /**
@@ -357,6 +372,11 @@ class AsyncQueue {
357
372
  * @returns {void}
358
373
  */
359
374
  _startProcessing(entry) {
375
+ // skip async hook dispatch when unused — this runs per module × queue
376
+ if (!this.hooks.beforeStart.isUsed()) {
377
+ this._startProcessing2(entry);
378
+ return;
379
+ }
360
380
  this.hooks.beforeStart.callAsync(entry.item, (err) => {
361
381
  if (err) {
362
382
  this._handleResult(
@@ -365,20 +385,29 @@ class AsyncQueue {
365
385
  );
366
386
  return;
367
387
  }
368
- let inCallback = false;
369
- try {
370
- this._processor(entry.item, (e, r) => {
371
- inCallback = true;
372
- this._handleResult(entry, e, r);
373
- });
374
- } catch (err) {
375
- if (inCallback) throw err;
376
- this._handleResult(entry, /** @type {WebpackError} */ (err), null);
377
- }
378
- this.hooks.started.call(entry.item);
388
+ this._startProcessing2(entry);
379
389
  });
380
390
  }
381
391
 
392
+ /**
393
+ * Processes the provided entry, after the beforeStart hook.
394
+ * @param {AsyncQueueEntry<T, K, R>} entry the entry
395
+ * @returns {void}
396
+ */
397
+ _startProcessing2(entry) {
398
+ let inCallback = false;
399
+ try {
400
+ this._processor(entry.item, (e, r) => {
401
+ inCallback = true;
402
+ this._handleResult(entry, e, r);
403
+ });
404
+ } catch (err) {
405
+ if (inCallback) throw err;
406
+ this._handleResult(entry, /** @type {WebpackError} */ (err), null);
407
+ }
408
+ this.hooks.started.call(entry.item);
409
+ }
410
+
382
411
  /**
383
412
  * Processes the provided entry.
384
413
  * @param {AsyncQueueEntry<T, K, R>} entry the entry
@@ -387,45 +416,66 @@ class AsyncQueue {
387
416
  * @returns {void}
388
417
  */
389
418
  _handleResult(entry, err, result) {
419
+ // skip async hook dispatch when unused — this runs per module × queue
420
+ if (!this.hooks.result.isUsed()) {
421
+ this._handleResult2(entry, err, result);
422
+ return;
423
+ }
390
424
  this.hooks.result.callAsync(entry.item, err, result, (hookError) => {
391
- const error = hookError
392
- ? makeWebpackError(hookError, `AsyncQueue(${this._name}).hooks.result`)
393
- : err;
394
-
395
- const callback = /** @type {Callback<R>} */ (entry.callback);
396
- const callbacks = entry.callbacks;
397
- entry.state = DONE_STATE;
398
- entry.callback = undefined;
399
- entry.callbacks = undefined;
400
- entry.result = result;
401
- entry.error = error;
425
+ this._handleResult2(
426
+ entry,
427
+ hookError
428
+ ? makeWebpackError(
429
+ hookError,
430
+ `AsyncQueue(${this._name}).hooks.result`
431
+ )
432
+ : err,
433
+ result
434
+ );
435
+ });
436
+ }
402
437
 
403
- const root = this._root;
404
- root._activeTasks--;
405
- if (root._willEnsureProcessing === false && root._needProcessing) {
406
- root._willEnsureProcessing = true;
407
- setImmediate(root._ensureProcessing);
408
- }
438
+ /**
439
+ * Finalizes the provided entry, after the result hook.
440
+ * @param {AsyncQueueEntry<T, K, R>} entry the entry
441
+ * @param {(WebpackError | null)=} error error, if any
442
+ * @param {(R | null)=} result result, if any
443
+ * @returns {void}
444
+ */
445
+ _handleResult2(entry, error, result) {
446
+ const callback = /** @type {Callback<R>} */ (entry.callback);
447
+ const callbacks = entry.callbacks;
448
+ entry.state = DONE_STATE;
449
+ entry.callback = undefined;
450
+ entry.callbacks = undefined;
451
+ entry.result = result;
452
+ entry.error = error;
409
453
 
410
- if (inHandleResult++ > 3) {
411
- process.nextTick(() => {
412
- callback(error, result);
413
- if (callbacks !== undefined) {
414
- for (const callback of callbacks) {
415
- callback(error, result);
416
- }
417
- }
418
- });
419
- } else {
454
+ const root = this._root;
455
+ root._activeTasks--;
456
+ if (root._willEnsureProcessing === false && root._needProcessing) {
457
+ root._willEnsureProcessing = true;
458
+ setImmediate(root._ensureProcessing);
459
+ }
460
+
461
+ if (inHandleResult++ > 3) {
462
+ process.nextTick(() => {
420
463
  callback(error, result);
421
464
  if (callbacks !== undefined) {
422
465
  for (const callback of callbacks) {
423
466
  callback(error, result);
424
467
  }
425
468
  }
469
+ });
470
+ } else {
471
+ callback(error, result);
472
+ if (callbacks !== undefined) {
473
+ for (const callback of callbacks) {
474
+ callback(error, result);
475
+ }
426
476
  }
427
- inHandleResult--;
428
- });
477
+ }
478
+ inHandleResult--;
429
479
  }
430
480
 
431
481
  clear() {
@@ -29,17 +29,18 @@ class LocConverter {
29
29
  get(pos) {
30
30
  if (this.pos !== pos) {
31
31
  if (this.pos < pos) {
32
- const str = this._input.slice(this.pos, pos);
33
- let i = str.lastIndexOf("\n");
34
- if (i === -1) {
35
- this.column += str.length;
36
- } else {
37
- this.column = str.length - i - 1;
38
- this.line++;
39
- while (i > 0 && (i = str.lastIndexOf("\n", i - 1)) !== -1) {
32
+ // Advance: delta-bounded scan of [this.pos, pos), allocation-free
33
+ // (unbounded index scans go quadratic on newline-free input).
34
+ const input = this._input;
35
+ let last = -1;
36
+ for (let j = this.pos; j < pos; j++) {
37
+ if (input.charCodeAt(j) === 10) {
40
38
  this.line++;
39
+ last = j;
41
40
  }
42
41
  }
42
+ this.column =
43
+ last === -1 ? this.column + (pos - this.pos) : pos - last - 1;
43
44
  } else {
44
45
  // Retreat: count newlines crossed in (pos, this.pos), i.e.
45
46
  // exclude the newline at `this.pos` itself. By convention a
@@ -41,7 +41,7 @@ const intersect = (sets) => {
41
41
  * @template T
42
42
  * @param {Set<T>} bigSet a Set which contains the original elements to compare against
43
43
  * @param {Set<T>} smallSet the set whose elements might be contained inside of bigSet
44
- * @returns {boolean} returns true if smallSet contains all elements inside of the bigSet
44
+ * @returns {boolean} returns true if bigSet contains all elements inside of smallSet
45
45
  */
46
46
  const isSubset = (bigSet, smallSet) => {
47
47
  if (bigSet.size < smallSet.size) return false;