webpack 5.111.0 → 5.111.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/lib/APIPlugin.js +3 -4
  2. package/lib/CompatibilityPlugin.js +3 -4
  3. package/lib/Compilation.js +16 -35
  4. package/lib/Compiler.js +4 -5
  5. package/lib/ConstPlugin.js +16 -132
  6. package/lib/DependencyTemplate.js +2 -1
  7. package/lib/DotenvPlugin.js +24 -28
  8. package/lib/ErrorHelpers.js +113 -0
  9. package/lib/ExportsInfo.js +20 -16
  10. package/lib/ExternalModule.js +6 -8
  11. package/lib/FlagDependencyExportsPlugin.js +8 -13
  12. package/lib/FlagDependencyUsagePlugin.js +9 -13
  13. package/lib/Generator.js +24 -2
  14. package/lib/HotModuleReplacementPlugin.js +2 -0
  15. package/lib/IgnorePlugin.js +1 -1
  16. package/lib/LoaderOptionsPlugin.js +1 -1
  17. package/lib/Module.js +3 -3
  18. package/lib/ModuleGraph.js +6 -9
  19. package/lib/MultiCompiler.js +6 -16
  20. package/lib/NormalModule.js +96 -44
  21. package/lib/RuntimeTemplate.js +33 -43
  22. package/lib/SourceMapDevToolPlugin.js +53 -103
  23. package/lib/TemplatedPathPlugin.js +16 -59
  24. package/lib/asset/AssetBytesGenerator.js +7 -1
  25. package/lib/asset/AssetGenerator.js +25 -16
  26. package/lib/asset/AssetSourceGenerator.js +7 -1
  27. package/lib/buildChunkGraph.js +11 -15
  28. package/lib/cache/MemoryCachePlugin.js +4 -4
  29. package/lib/cache/MemoryWithGcCachePlugin.js +7 -8
  30. package/lib/cache/PackFileCacheStrategy.js +3 -18
  31. package/lib/cache/getLazyHashedEtag.js +3 -5
  32. package/lib/config/browserslistTargetHandler.js +2 -8
  33. package/lib/config/defaults.js +52 -78
  34. package/lib/config/getClaimedAssetTypes.js +10 -11
  35. package/lib/config/target.js +3 -4
  36. package/lib/{ContextExclusionPlugin.js → context/ContextExclusionPlugin.js} +1 -1
  37. package/lib/{ContextModule.js → context/ContextModule.js} +37 -34
  38. package/lib/{ContextModuleFactory.js → context/ContextModuleFactory.js} +19 -21
  39. package/lib/{ContextReplacementPlugin.js → context/ContextReplacementPlugin.js} +4 -4
  40. package/lib/css/CssGenerator.js +19 -11
  41. package/lib/css/CssParser.js +18 -20
  42. package/lib/css/cssMinify.js +32 -29
  43. package/lib/css/data.js +797 -288
  44. package/lib/css/syntax.js +2250 -934
  45. package/lib/debug/ProfilingPlugin.js +3 -4
  46. package/lib/dependencies/CommonJsExportRequireDependency.js +10 -11
  47. package/lib/dependencies/CommonJsImportsParserPlugin.js +4 -5
  48. package/lib/dependencies/CommonJsSelfReferenceDependency.js +2 -4
  49. package/lib/dependencies/ContextDependency.js +1 -1
  50. package/lib/dependencies/ContextDependencyHelpers.js +3 -9
  51. package/lib/dependencies/ContextElementDependency.js +1 -1
  52. package/lib/dependencies/CssIcssExportDependency.js +6 -8
  53. package/lib/dependencies/CssIcssImportDependency.js +3 -6
  54. package/lib/dependencies/CssUrlDependency.js +3 -5
  55. package/lib/dependencies/HarmonyCompatibilityDependency.js +11 -20
  56. package/lib/dependencies/HarmonyDetectionParserPlugin.js +3 -4
  57. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +2 -4
  58. package/lib/dependencies/HarmonyExportExpressionDependency.js +3 -4
  59. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +3 -4
  60. package/lib/dependencies/HarmonyExportInitFragment.js +26 -19
  61. package/lib/dependencies/HarmonyExportSpecifierDependency.js +7 -28
  62. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +103 -16
  63. package/lib/dependencies/HarmonyImportSideEffectDependency.js +3 -4
  64. package/lib/dependencies/HarmonyImportSpecifierDependency.js +16 -2
  65. package/lib/dependencies/HtmlEntryDependency.js +74 -102
  66. package/lib/dependencies/HtmlInlineScriptDependency.js +3 -4
  67. package/lib/dependencies/HtmlInlineStyleDependency.js +3 -4
  68. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +1 -1
  69. package/lib/dependencies/ImportMetaGlobHelpers.js +1 -1
  70. package/lib/dependencies/ImportMetaPlugin.js +8 -10
  71. package/lib/dependencies/ImportParserPlugin.js +1 -1
  72. package/lib/dependencies/LoaderPlugin.js +26 -1
  73. package/lib/dependencies/RequireContextDependencyParserPlugin.js +1 -1
  74. package/lib/dependencies/URLContextDependency.js +1 -1
  75. package/lib/dependencies/URLDependency.js +6 -5
  76. package/lib/dependencies/WorkerAndWorkletPlugin.js +15 -21
  77. package/lib/dependencies/WorkerDependency.js +6 -5
  78. package/lib/dependencies/WorkletDependency.js +6 -9
  79. package/lib/errors/HookWebpackError.js +3 -2
  80. package/lib/hmr/LazyCompilationPlugin.js +3 -5
  81. package/lib/html/HtmlGenerator.js +61 -82
  82. package/lib/html/HtmlModulesPlugin.js +88 -139
  83. package/lib/html/HtmlParser.js +97 -141
  84. package/lib/html/data.js +21 -0
  85. package/lib/html/htmlMinify.js +10 -11
  86. package/lib/html/syntax.js +883 -993
  87. package/lib/index.js +46 -3
  88. package/lib/javascript/ChunkFormatHelpers.js +4 -3
  89. package/lib/javascript/JavascriptGenerator.js +8 -1
  90. package/lib/javascript/JavascriptModulesPlugin.js +21 -48
  91. package/lib/javascript/JavascriptParser.js +721 -178
  92. package/lib/javascript/parser.js +6 -0
  93. package/lib/javascript/syntax.js +420 -92
  94. package/lib/json/JsonGenerator.js +7 -1
  95. package/lib/library/ModuleLibraryPlugin.js +64 -136
  96. package/lib/loaders/LoaderRunner.js +137 -9
  97. package/lib/node/NodeWatchFileSystem.js +3 -9
  98. package/lib/optimize/AggressiveMergingPlugin.js +3 -5
  99. package/lib/optimize/ConcatenatedModule.js +81 -100
  100. package/lib/optimize/FlagIncludedChunksPlugin.js +3 -11
  101. package/lib/optimize/InnerGraphPlugin.js +7 -13
  102. package/lib/optimize/LimitChunkCountPlugin.js +5 -8
  103. package/lib/optimize/MangleExportsPlugin.js +3 -4
  104. package/lib/optimize/ModuleConcatenationPlugin.js +3 -4
  105. package/lib/optimize/SideEffectsFlagPlugin.js +7 -19
  106. package/lib/optimize/SplitChunksPlugin.js +2 -4
  107. package/lib/performance/BroadContextsPlugin.js +1 -1
  108. package/lib/performance/CacheEffectivenessPlugin.js +3 -4
  109. package/lib/performance/SizeLimitsPlugin.js +2 -4
  110. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +6 -8
  111. package/lib/prefetch/ResourceHintPlugin.js +17 -21
  112. package/lib/prefetch/StartupAssetHintRuntimeModule.js +7 -10
  113. package/lib/runtime/AsyncModuleRuntimeModule.js +3 -5
  114. package/lib/runtime/GetChunkFilenameRuntimeModule.js +3 -4
  115. package/lib/runtime/GlobalRuntimeModule.js +2 -4
  116. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +55 -85
  117. package/lib/schemes/DataUriPlugin.js +3 -6
  118. package/lib/schemes/VirtualUrlPlugin.js +1 -1
  119. package/lib/serialization/BinaryMiddleware.js +9 -9
  120. package/lib/serialization/FileMiddleware.js +16 -16
  121. package/lib/serialization/ObjectMiddleware.js +30 -33
  122. package/lib/stats/DefaultStatsFactoryPlugin.js +3 -4
  123. package/lib/typescript/TypeScriptPlugin.js +2 -3
  124. package/lib/url/URLParserPlugin.js +6 -8
  125. package/lib/util/LocConverter.js +4 -7
  126. package/lib/util/SourceProcessor.js +15 -22
  127. package/lib/util/chainedImports.js +3 -4
  128. package/lib/util/concatenate.js +4 -4
  129. package/lib/util/createHooksRegistry.js +1 -2
  130. package/lib/util/dataURL.js +2 -3
  131. package/lib/util/deterministicGrouping.js +8 -13
  132. package/lib/util/findGraphRoots.js +6 -13
  133. package/lib/util/globUtils.js +1 -1
  134. package/lib/util/hash/wasm-hash.js +3 -4
  135. package/lib/util/internalSerializables.js +1 -1
  136. package/lib/util/semver.js +5 -3
  137. package/lib/wasm-async/AsyncWebAssemblyGenerator.js +6 -1
  138. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +5 -1
  139. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +3 -4
  140. package/lib/wasm-sync/WebAssemblyGenerator.js +6 -1
  141. package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +5 -1
  142. package/lib/wasm-sync/WebAssemblyUtils.js +2 -4
  143. package/package.json +30 -23
  144. package/types.d.ts +299 -280
package/lib/APIPlugin.js CHANGED
@@ -45,10 +45,9 @@ const getConcatenatedModule = memoize(() =>
45
45
  /** @import { RuntimeSpec } from "./util/runtime" */
46
46
  /** @import JavascriptParser, { Range } from "./javascript/JavascriptParser" */
47
47
 
48
- // Modules that reassign `__webpack_public_path__` at runtime, by compilation. A baked
49
- // analyzable specifier can't reflect that, so those forms fall back. Also recorded per
50
- // module in `buildInfo`, because a module restored from the persistent cache is never
51
- // re-parsed and would otherwise lose the flag.
48
+ // Modules reassigning `__webpack_public_path__` at runtime, per compilation, since
49
+ // a baked specifier cannot reflect that. Also kept in `buildInfo`: a module
50
+ // restored from the persistent cache is never re-parsed.
52
51
  /** @type {WeakMap<Compilation, Set<Module>>} */
53
52
  const runtimePublicPathOverride = new WeakMap();
54
53
 
@@ -180,10 +180,9 @@ class CompatibilityPlugin {
180
180
  });
181
181
  return true;
182
182
  });
183
- // `const`/`let` are block-pre-walked, by which point the name is no
184
- // longer free and `hooks.pattern` is not dispatched for it — tag
185
- // them through the kind-specific declaration hooks instead.
186
- // Returning nothing lets the variable be defined, keeping the tag.
183
+ // `const` and `let` are block-pre-walked, by which point the name is no
184
+ // longer free and `hooks.pattern` never fires, so they are tagged
185
+ // through the declaration hooks instead.
187
186
  for (const hookMap of [
188
187
  parser.hooks.varDeclarationConst,
189
188
  parser.hooks.varDeclarationLet
@@ -27,6 +27,9 @@ const Dependency = require("./Dependency");
27
27
  const DependencyTemplates = require("./DependencyTemplates");
28
28
  const Entrypoint = require("./Entrypoint");
29
29
  const ErrorHelpers = require("./ErrorHelpers");
30
+
31
+ const { toError } = ErrorHelpers;
32
+
30
33
  const FileSystemInfo = require("./FileSystemInfo");
31
34
  const LazyBarrelController = require("./LazyBarrel");
32
35
  const MainTemplate = require("./MainTemplate");
@@ -2371,7 +2374,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
2371
2374
  if (err) {
2372
2375
  const notFoundError = new (getModuleNotFoundError())(
2373
2376
  originModule,
2374
- err,
2377
+ toError(err),
2375
2378
  /** @type {DependencyLocation} */
2376
2379
  (dependencies.map((d) => d.loc).find(Boolean))
2377
2380
  );
@@ -2656,12 +2659,9 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
2656
2659
  return;
2657
2660
  }
2658
2661
 
2659
- // lazy barrel:
2660
- // 1. first call: barrel module is not classified yet, so this records the requested
2661
- // ids and returns undefined; the targets get built below when
2662
- // `processModuleDependencies` runs `_lazyBarrelController.classify` and replays them.
2663
- // 2. later call: barrel module is already built, so `processModuleDependencies` won't
2664
- // re-walk it; the newly requested targets must be built here.
2662
+ // lazy barrel: on the first call the module is unclassified, so this only
2663
+ // records the ids and `processModuleDependencies` replays them. Later the
2664
+ // module is built and never re-walked, so the targets are built here.
2665
2665
  const unlazyItems = this._lazyBarrelController.request(
2666
2666
  module,
2667
2667
  dependencies
@@ -4187,7 +4187,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
4187
4187
  // Reported and carried on with, as the first pass does: a throw
4188
4188
  // here would leave the build with no error to show for it.
4189
4189
  this.errors.push(
4190
- new (getCodeGenerationError())(module, /** @type {Error} */ (err))
4190
+ new (getCodeGenerationError())(module, toError(err))
4191
4191
  );
4192
4192
  result = {
4193
4193
  sources: new Map(),
@@ -4377,9 +4377,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
4377
4377
  compilation: this
4378
4378
  });
4379
4379
  } catch (err) {
4380
- errors.push(
4381
- new (getCodeGenerationError())(module, /** @type {Error} */ (err))
4382
- );
4380
+ errors.push(new (getCodeGenerationError())(module, toError(err)));
4383
4381
  result = {
4384
4382
  sources: new Map(),
4385
4383
  runtimeRequirements: null,
@@ -4430,9 +4428,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
4430
4428
  result.data.set("analyzableBailouts", bailouts);
4431
4429
  }
4432
4430
  } catch (err) {
4433
- errors.push(
4434
- new (getCodeGenerationError())(module, /** @type {Error} */ (err))
4435
- );
4431
+ errors.push(new (getCodeGenerationError())(module, toError(err)));
4436
4432
  result = cachedResult = {
4437
4433
  sources: new Map(),
4438
4434
  runtimeRequirements: null,
@@ -5208,22 +5204,9 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
5208
5204
  }
5209
5205
 
5210
5206
  this.logger.time("hashing: sort chunks");
5211
- /*
5212
- * Chunks are hashed in 4 categories, in this order:
5213
- * 1. Async chunks - no hash dependencies on other chunks
5214
- * 2. Non-entry initial chunks (e.g. shared split chunks) - no hash
5215
- * dependencies on other chunks, but runtime chunks may read their
5216
- * hashes via GetChunkFilenameRuntimeModule (dependentHash)
5217
- * 3. Runtime chunks - may use hashes of async and non-entry initial
5218
- * chunks (via GetChunkFilenameRuntimeModule). Ordered by references
5219
- * between each other (for async entrypoints)
5220
- * 4. Entry chunks - may depend on runtimeChunk.hash (via
5221
- * createChunkHashHandler for ESM/CJS entry importing runtime)
5222
- *
5223
- * This ordering ensures all hash dependencies flow in one direction:
5224
- * async/initial → runtime → entry, with no circular dependencies.
5225
- * Chunks within each category are sorted by id for determinism.
5226
- */
5207
+ // Hashed as async, then non-entry initial, then runtime, then entry chunks,
5208
+ // so hash dependencies flow one way between those groups. A cycle among the
5209
+ // runtime chunks is still possible, and is warned about below.
5227
5210
  /** @type {Chunk[]} */
5228
5211
  const unorderedRuntimeChunks = [];
5229
5212
  /** @type {Chunk[]} */
@@ -5410,9 +5393,7 @@ This prevents using hashes of each other and should be avoided.`);
5410
5393
  this.hooks.contentHash.call(chunk);
5411
5394
  }
5412
5395
  } catch (err) {
5413
- this.errors.push(
5414
- new (getChunkRenderError())(chunk, "", /** @type {Error} */ (err))
5415
- );
5396
+ this.errors.push(new (getChunkRenderError())(chunk, "", toError(err)));
5416
5397
  }
5417
5398
  this.logger.timeAggregate("hashing: hash chunks");
5418
5399
  };
@@ -5926,7 +5907,7 @@ This prevents using hashes of each other and should be avoided.`);
5926
5907
  });
5927
5908
  } catch (err) {
5928
5909
  this.errors.push(
5929
- new (getChunkRenderError())(chunk, "", /** @type {Error} */ (err))
5910
+ new (getChunkRenderError())(chunk, "", toError(err))
5930
5911
  );
5931
5912
  return callback();
5932
5913
  }
@@ -5965,7 +5946,7 @@ This prevents using hashes of each other and should be avoided.`);
5965
5946
  : "");
5966
5947
 
5967
5948
  this.errors.push(
5968
- new (getChunkRenderError())(chunk, filename, err)
5949
+ new (getChunkRenderError())(chunk, filename, toError(err))
5969
5950
  );
5970
5951
  inTry = false;
5971
5952
  return callback();
package/lib/Compiler.js CHANGED
@@ -16,12 +16,12 @@ const Cache = require("./Cache");
16
16
  const CacheFacade = require("./CacheFacade");
17
17
  const ChunkGraph = require("./ChunkGraph");
18
18
  const Compilation = require("./Compilation");
19
- const ContextModuleFactory = require("./ContextModuleFactory");
20
19
  const ModuleGraph = require("./ModuleGraph");
21
20
  const NormalModuleFactory = require("./NormalModuleFactory");
22
21
  const RequestShortener = require("./RequestShortener");
23
22
  const ResolverFactory = require("./ResolverFactory");
24
23
  const Stats = require("./Stats");
24
+ const ContextModuleFactory = require("./context/ContextModuleFactory");
25
25
  const WebpackError = require("./errors/WebpackError");
26
26
  const { Logger } = require("./logging/Logger");
27
27
  const asyncLib = require("./util/async");
@@ -1063,10 +1063,9 @@ ${other}`);
1063
1063
 
1064
1064
  updateWithReplacementSource(content.length);
1065
1065
 
1066
- // if it exists and content on disk matches content
1067
- // skip writing the same content again
1068
- // (to keep mtime and don't trigger watchers)
1069
- // for a fast negative match file size is compared first
1066
+ // Skip rewriting content already on disk, which would move the
1067
+ // mtime and wake watchers. Size is compared first, as a cheap
1068
+ // negative match.
1070
1069
  if (content.length === stats.size) {
1071
1070
  compilation.comparedForEmitAssets.add(file);
1072
1071
  return /** @type {OutputFileSystem} */ (
@@ -219,17 +219,8 @@ class ConstPlugin {
219
219
  } else {
220
220
  parser.walkExpression(expression.test);
221
221
  }
222
- // Expressions do not hoist.
223
- // It is safe to remove the dead branch.
224
- //
225
- // Given the following code:
226
- //
227
- // false ? someExpression() : otherExpression();
228
- //
229
- // the generated code is:
230
- //
231
- // false ? 0 : otherExpression();
232
- //
222
+ // Expressions do not hoist, so the dead branch is safe to remove:
223
+ // `false ? someExpression() : other()` becomes `false ? 0 : other()`.
233
224
  const branchToRemove = bool
234
225
  ? expression.alternate
235
226
  : expression.consequent;
@@ -254,49 +245,9 @@ class ConstPlugin {
254
245
  const param = parser.evaluateExpression(expression.left);
255
246
  const bool = param.asBool();
256
247
  if (typeof bool === "boolean") {
257
- // Expressions do not hoist.
258
- // It is safe to remove the dead branch.
259
- //
260
- // ------------------------------------------
261
- //
262
- // Given the following code:
263
- //
264
- // falsyExpression() && someExpression();
265
- //
266
- // the generated code is:
267
- //
268
- // falsyExpression() && false;
269
- //
270
- // ------------------------------------------
271
- //
272
- // Given the following code:
273
- //
274
- // truthyExpression() && someExpression();
275
- //
276
- // the generated code is:
277
- //
278
- // true && someExpression();
279
- //
280
- // ------------------------------------------
281
- //
282
- // Given the following code:
283
- //
284
- // truthyExpression() || someExpression();
285
- //
286
- // the generated code is:
287
- //
288
- // truthyExpression() || false;
289
- //
290
- // ------------------------------------------
291
- //
292
- // Given the following code:
293
- //
294
- // falsyExpression() || someExpression();
295
- //
296
- // the generated code is:
297
- //
298
- // false && someExpression();
299
- //
248
+ // Expressions do not hoist, so the dead branch is safe to remove.
249
+ // Whichever side cannot decide the result is replaced, leaving the
250
+ // deciding side and its side effects in place.
300
251
  const keepRight =
301
252
  (expression.operator === "&&" && bool) ||
302
253
  (expression.operator === "||" && !bool);
@@ -305,14 +256,8 @@ class ConstPlugin {
305
256
  !param.couldHaveSideEffects() &&
306
257
  (param.isBoolean() || keepRight)
307
258
  ) {
308
- // for case like
309
- //
310
- // return'development'===process.env.NODE_ENV&&'foo'
311
- //
312
- // we need a space before the bool to prevent result like
313
- //
314
- // returnfalse&&'foo'
315
- //
259
+ // The bool needs a leading space: `return'a'===b&&'foo'` would
260
+ // otherwise become `returnfalse&&'foo'`.
316
261
  const dep = new ConstDependency(
317
262
  ` ${bool}`,
318
263
  /** @type {Range} */ (param.range)
@@ -336,36 +281,12 @@ class ConstPlugin {
336
281
  const param = parser.evaluateExpression(expression.left);
337
282
  const keepRight = param.asNullish();
338
283
  if (typeof keepRight === "boolean") {
339
- // ------------------------------------------
340
- //
341
- // Given the following code:
342
- //
343
- // nonNullish ?? someExpression();
344
- //
345
- // the generated code is:
346
- //
347
- // nonNullish ?? 0;
348
- //
349
- // ------------------------------------------
350
- //
351
- // Given the following code:
352
- //
353
- // nullish ?? someExpression();
354
- //
355
- // the generated code is:
356
- //
357
- // null ?? someExpression();
358
- //
284
+ // `nonNullish ?? x` becomes `nonNullish ?? 0`, and `nullish ?? x`
285
+ // becomes `null ?? x`: the unreachable side is replaced.
359
286
  if (!param.couldHaveSideEffects() && keepRight) {
360
287
  // cspell:word returnnull
361
- // for case like
362
- //
363
- // return('development'===process.env.NODE_ENV&&null)??'foo'
364
- //
365
- // we need a space before the bool to prevent result like
366
- //
367
- // returnnull??'foo'
368
- //
288
+ // As above, the value needs a leading space, or `return(…&&null)`
289
+ // would become `returnnull??'foo'`.
369
290
  const dep = new ConstDependency(
370
291
  " null",
371
292
  /** @type {Range} */ (param.range)
@@ -423,18 +344,8 @@ class ConstPlugin {
423
344
  );
424
345
 
425
346
  if (evaluated.asNullish()) {
426
- // ------------------------------------------
427
- //
428
- // Given the following code:
429
- //
430
- // nullishMemberChain?.a.b();
431
- //
432
- // the generated code is:
433
- //
434
- // undefined;
435
- //
436
- // ------------------------------------------
437
- //
347
+ // A nullish chain short-circuits whole, so `nullish?.a.b()`
348
+ // becomes `undefined`.
438
349
  const dep = new ConstDependency(
439
350
  " undefined",
440
351
  /** @type {Range} */ (expr.range)
@@ -519,36 +430,9 @@ class ConstPlugin {
519
430
  * @returns {void}
520
431
  */
521
432
  eliminateUnusedStatement(parser, statement, alwaysInBlock) {
522
- // Before removing the unused branch, the hoisted declarations
523
- // must be collected.
524
- //
525
- // Given the following code:
526
- //
527
- // if (true) f() else g()
528
- // if (false) {
529
- // function f() {}
530
- // const g = function g() {}
531
- // if (someTest) {
532
- // let a = 1
533
- // var x, {y, z} = obj
534
- // }
535
- // } else {
536
- // …
537
- // }
538
- //
539
- // the generated code is:
540
- //
541
- // if (true) f() else {}
542
- // if (false) {
543
- // var f, x, y, z; (in loose mode)
544
- // var x, y, z; (in strict mode)
545
- // } else {
546
- // …
547
- // }
548
- //
549
- // NOTE: When code runs in strict mode, `var` declarations
550
- // are hoisted but `function` declarations don't.
551
- //
433
+ // The hoisted declarations must be collected before the unused branch goes,
434
+ // since the removed code still contributes them. In strict mode `var` is
435
+ // hoisted but `function` is not, so the two modes collect different sets.
552
436
  const declarations = parser.scope.isStrict
553
437
  ? getHoistedDeclarations(statement, false)
554
438
  : getHoistedDeclarations(statement, true);
@@ -12,7 +12,7 @@
12
12
  /** @import Dependency from "./Dependency" */
13
13
  /** @import DependencyTemplates from "./DependencyTemplates" */
14
14
  /** @import { GenerateContext } from "./Generator" */
15
- /** @import Module, { RuntimeRequirements } from "./Module" */
15
+ /** @import Module, { CodeGenerationResultData, RuntimeRequirements } from "./Module" */
16
16
  /** @import ModuleGraph from "./ModuleGraph" */
17
17
  /** @import RuntimeTemplate from "./RuntimeTemplate" */
18
18
  /** @import { RuntimeSpec } from "./util/runtime" */
@@ -37,6 +37,7 @@
37
37
  * @property {ConcatenationScope=} concatenationScope when in a concatenated module, information about other concatenated modules
38
38
  * @property {CodeGenerationResults} codeGenerationResults the code generation results
39
39
  * @property {InitFragment<GenerateContext>[]} chunkInitFragments chunkInitFragments
40
+ * @property {(() => CodeGenerationResultData)=} getData get access to the code generation data
40
41
  */
41
42
 
42
43
  /**
@@ -3,28 +3,6 @@
3
3
  Author Natsu @xiaoxiaojx
4
4
  */
5
5
 
6
- "use strict";
7
-
8
- const FileSystemInfo = require("./FileSystemInfo");
9
- const DotenvFileError = require("./errors/DotenvFileError");
10
- const { join } = require("./util/fs");
11
-
12
- /** @import { DotenvPluginOptions } from "../declarations/WebpackOptions" */
13
- /** @import Compiler from "./Compiler" */
14
- /** @import { ItemCacheFacade } from "./CacheFacade" */
15
- /** @import { InputFileSystem } from "./util/fs" */
16
- /** @import { Snapshot } from "./FileSystemInfo" */
17
-
18
- /** @typedef {Exclude<DotenvPluginOptions["prefix"], string | undefined>} Prefix */
19
- /** @typedef {Record<string, string>} Env */
20
-
21
- const DEFAULT_TEMPLATE = [
22
- ".env",
23
- ".env.local",
24
- ".env.[mode]",
25
- ".env.[mode].local"
26
- ];
27
-
28
6
  // cspell:ignore Motte, motdotla
29
7
 
30
8
  /*
@@ -62,6 +40,28 @@ const DEFAULT_TEMPLATE = [
62
40
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63
41
  */
64
42
 
43
+ "use strict";
44
+
45
+ const FileSystemInfo = require("./FileSystemInfo");
46
+ const DotenvFileError = require("./errors/DotenvFileError");
47
+ const { join } = require("./util/fs");
48
+
49
+ /** @import { DotenvPluginOptions } from "../declarations/WebpackOptions" */
50
+ /** @import Compiler from "./Compiler" */
51
+ /** @import { ItemCacheFacade } from "./CacheFacade" */
52
+ /** @import { InputFileSystem } from "./util/fs" */
53
+ /** @import { Snapshot } from "./FileSystemInfo" */
54
+
55
+ /** @typedef {Exclude<DotenvPluginOptions["prefix"], string | undefined>} Prefix */
56
+ /** @typedef {Record<string, string>} Env */
57
+
58
+ const DEFAULT_TEMPLATE = [
59
+ ".env",
60
+ ".env.local",
61
+ ".env.[mode]",
62
+ ".env.[mode].local"
63
+ ];
64
+
65
65
  // Regex for parsing .env files
66
66
  // ported from https://github.com/motdotla/dotenv/blob/v17.4.2/lib/main.js#L38
67
67
  const LINE =
@@ -223,12 +223,8 @@ function expand(options) {
223
223
  runningParsed[key] = resolvedValue;
224
224
  }
225
225
 
226
- // Part of `dotenv-expand` code, but we don't need it because of we don't modify `process.env`
227
- // for (const processKey in options.parsed) {
228
- // if (processEnv) {
229
- // processEnv[processKey] = options.parsed[processKey];
230
- // }
231
- // }
226
+ // `dotenv-expand` writes the parsed values back into `process.env` here.
227
+ // Omitted: webpack never mutates the ambient environment.
232
228
 
233
229
  return options;
234
230
  }
@@ -5,10 +5,39 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ const path = require("path");
9
+ const { fileUrlToPath } = require("./util/identifier");
10
+ const memoize = require("./util/memoize");
11
+
12
+ /** @import RequestShortener from "./RequestShortener" */
13
+
14
+ const getNonErrorEmittedError = memoize(() =>
15
+ require("./errors/NonErrorEmittedError")
16
+ );
17
+
8
18
  const loaderFlag = "LOADER_EXECUTION";
9
19
 
10
20
  const webpackOptionsFlag = "WEBPACK_OPTIONS";
11
21
 
22
+ // Every frame of a stack is indented, so a line opening with `at ` after
23
+ // whitespace is a frame rather than a part of the message itself.
24
+ const STACK_FRAME_REGEXP = /^\s+at\s/;
25
+
26
+ // `at name (file:line:column)`, and the `at file:line:column` a frame with no
27
+ // name is written as.
28
+ const STACK_FRAME_FILE_REGEXP = /^(\s+at\s(?:.*\()?)(.+?):(\d+):(\d+)(\)?)$/;
29
+
30
+ // A generated function nests its parentheses and carries a position of its
31
+ // own, so each `file:line:column` in it is read on its own.
32
+ const GENERATED_FRAME_REGEXP = /\beval at /;
33
+ const POSITION_REGEXP = /([^\s()]+):\d+:\d+/g;
34
+
35
+ const WEBPACK_SOURCE_PATH = path.join(__dirname, path.sep);
36
+
37
+ // The engine's own frames name no file of the project: `node:internal/…` under
38
+ // node and deno, the bare `native` under bun.
39
+ const ENGINE_FILE_REGEXP = /^(?:node:|native$)/;
40
+
12
41
  /**
13
42
  * Returns stack trace without the specified flag included.
14
43
  * @param {string} stack stack trace
@@ -74,6 +103,88 @@ const cutOffMessage = (stack, message) => {
74
103
  return firstLine === message ? stack.slice(nextLine + 1) : stack;
75
104
  };
76
105
 
106
+ /**
107
+ * Returns the file a stack frame names, or undefined when the line names none.
108
+ * @param {string} line line of a stack
109
+ * @returns {string | undefined} the file the frame names
110
+ */
111
+ const frameFile = (line) => {
112
+ const match = STACK_FRAME_FILE_REGEXP.exec(line);
113
+ return match === null ? undefined : fileUrlToPath(match[2]);
114
+ };
115
+
116
+ /**
117
+ * Returns the stack without the frames this file's own wrapping put on it.
118
+ * @param {string | undefined} stack stack trace
119
+ * @returns {string | undefined} stack trace starting at the caller
120
+ */
121
+ const cutOffWrappingFrames = (stack) => {
122
+ if (typeof stack !== "string") return stack;
123
+ const lines = stack.split("\n");
124
+ const index = lines.findIndex((line) => STACK_FRAME_REGEXP.test(line));
125
+ if (index === -1) return stack;
126
+ while (index < lines.length && frameFile(lines[index]) === __filename) {
127
+ lines.splice(index, 1);
128
+ }
129
+ return lines.join("\n");
130
+ };
131
+
132
+ /**
133
+ * Returns the value as an error, naming whatever a tap, a loader or a plugin
134
+ * failed with when that is not one. Everything reading a failure expects one.
135
+ * @param {EXPECTED_ANY} value value something failed with
136
+ * @returns {Error} the value, or an error naming it
137
+ */
138
+ const toError = (value) => {
139
+ if (value instanceof Error) return value;
140
+ const error = new (getNonErrorEmittedError())(value);
141
+ // The wrapping is not the site: the stack starts where the value was caught.
142
+ // Cut rather than `captureStackTrace`, which elides every frame under bun.
143
+ error.stack = cutOffWrappingFrames(error.stack);
144
+ return error;
145
+ };
146
+
147
+ /**
148
+ * Returns whether a rebuild of the same project names the same position in the
149
+ * file. Webpack's own sources move with a release, and the engine's with it.
150
+ * @param {string} file file a stack frame names
151
+ * @returns {boolean} whether the position is worth keeping
152
+ */
153
+ const isReproduciblePosition = (file) =>
154
+ !file.startsWith(WEBPACK_SOURCE_PATH) && !ENGINE_FILE_REGEXP.test(file);
155
+
156
+ /**
157
+ * Returns the message with every stack frame naming its file relative to the
158
+ * context, and a position only where {@link isReproduciblePosition} allows one.
159
+ * @param {string} message error message
160
+ * @param {RequestShortener} requestShortener request shortener
161
+ * @returns {string} message whose frames a second build writes the same way
162
+ */
163
+ const contextifyStackFrames = (message, requestShortener) =>
164
+ message
165
+ .split("\n")
166
+ .map((line) => {
167
+ if (!STACK_FRAME_REGEXP.test(line)) return line;
168
+ if (GENERATED_FRAME_REGEXP.test(line)) {
169
+ return line.replace(
170
+ POSITION_REGEXP,
171
+ (position, file) =>
172
+ /** @type {string} */
173
+ (requestShortener.shorten(fileUrlToPath(file)))
174
+ );
175
+ }
176
+ const match = STACK_FRAME_FILE_REGEXP.exec(line);
177
+ if (match === null) return line;
178
+ const [, frame, url, lineNumber, column, end] = match;
179
+ // An engine may name the file as a URL rather than as a path.
180
+ const file = fileUrlToPath(url);
181
+ const position = isReproduciblePosition(file)
182
+ ? `:${lineNumber}:${column}`
183
+ : "";
184
+ return `${frame}${requestShortener.shorten(file)}${position}${end}`;
185
+ })
186
+ .join("\n");
187
+
77
188
  /**
78
189
  * Returns stack trace without the loader execution flag and message included.
79
190
  * @param {string} stack stack trace
@@ -100,8 +211,10 @@ const cleanUpWebpackOptions = (stack, message) => {
100
211
 
101
212
  module.exports.cleanUp = cleanUp;
102
213
  module.exports.cleanUpWebpackOptions = cleanUpWebpackOptions;
214
+ module.exports.contextifyStackFrames = contextifyStackFrames;
103
215
  module.exports.cutOffByFlag = cutOffByFlag;
104
216
  module.exports.cutOffLoaderExecution = cutOffLoaderExecution;
105
217
  module.exports.cutOffMessage = cutOffMessage;
106
218
  module.exports.cutOffMultilineMessage = cutOffMultilineMessage;
107
219
  module.exports.cutOffWebpackOptions = cutOffWebpackOptions;
220
+ module.exports.toError = toError;
@@ -151,20 +151,20 @@ class ExportsInfo {
151
151
  /** @type {Exports} */
152
152
  this._exports = new Map();
153
153
 
154
- // `_otherExportsInfo` is a fallback entry for unlisted exports. Two roles:
155
- // 1. factory template — `getExportInfo` creates `new ExportInfo(name, this)`,
156
- // so created export info extends its properties.
157
- // 2. flags whether the whole exportsInfo can be statically analyzed.
158
- // Its `used` reachable values:
159
- // - NoInfo: no use analysis yet (`optimization#usedExports` off), or used without info
160
- // - Unused: analyzed, no unlisted export needed
161
- // - Unknown: used in unknown way
162
- // - Used/OnlyPropertiesUsed: never reached
163
- // Its `provided` reachable values:
164
- // - undefined: provision not determined yet
165
- // - false: determined, no unlisted export is provided
166
- // - null: only runtime knows (dynamic/unknown exports)
167
- // - true: never reached
154
+ // WHY: a fallback entry for the unlisted exports, in two roles — the factory
155
+ // template `getExportInfo` extends with `new ExportInfo(name, this)`, and the
156
+ // flag for whether this exportsInfo can be statically analyzed at all.
157
+ // Its reachable `used` values:
158
+ // - NoInfo: no use analysis yet (`optimization#usedExports` off), or used
159
+ // without info
160
+ // - Unused: analyzed, no unlisted export needed
161
+ // - Unknown: used in an unknown way
162
+ // - Used/OnlyPropertiesUsed: never reached
163
+ // Its reachable `provided` values:
164
+ // - undefined: provision not determined yet
165
+ // - false: determined, no unlisted export is provided
166
+ // - null: only runtime knows (dynamic or unknown exports)
167
+ // - true: never reached
168
168
  /** @type {ExportInfo} */
169
169
  this._otherExportsInfo = new ExportInfo(null);
170
170
  /** @type {ExportInfo} */
@@ -1671,7 +1671,9 @@ class ExportInfo {
1671
1671
  }
1672
1672
 
1673
1673
  /**
1674
- * Returns the target, undefined when there is no target, false when no target is valid.
1674
+ * Walks the reexport chain and returns the first target whose module passes
1675
+ * `validTargetModuleFilter`. Returns undefined when there is no target, false
1676
+ * when the chain ends without a valid module.
1675
1677
  * @param {ModuleGraph} moduleGraph the module graph
1676
1678
  * @param {ValidTargetModuleFilter} validTargetModuleFilter a valid target module
1677
1679
  * @returns {TargetItemWithoutConnection | null | undefined | false} the target, undefined when there is no target, false when no target is valid
@@ -1736,7 +1738,9 @@ class ExportInfo {
1736
1738
  }
1737
1739
 
1738
1740
  /**
1739
- * Returns the target.
1741
+ * Resolves the reexport chain as far as `resolveTargetFilter` allows and
1742
+ * returns where it ends. Returns undefined when there is no target, the
1743
+ * targets disagree, or the chain is circular.
1740
1744
  * @param {ModuleGraph} moduleGraph the module graph
1741
1745
  * @param {ResolveTargetFilter} resolveTargetFilter filter function to further resolve target
1742
1746
  * @returns {TargetItemWithConnection | undefined} the target