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
@@ -745,8 +745,7 @@ class RuntimeTemplate {
745
745
  : undefined;
746
746
  // A reassigned `__webpack_public_path__` cannot reach a baked literal, and `.p`
747
747
  // belongs to a runtime, so only the runtimes it reaches keep the runtime form.
748
- // `url-inline` is unaffected: that form falls back to `.p + <file>`, which reads
749
- // the reassigned value at the call site rather than through the wrapper.
748
+ // `url-inline` is unaffected: it reads the value at the call site.
750
749
  if (
751
750
  form !== "url-inline" &&
752
751
  APIPlugin.runtimeUsesPublicPathOverride(
@@ -774,12 +773,13 @@ class RuntimeTemplate {
774
773
  return true;
775
774
  }
776
775
 
777
- // `url-inline` asks whether the file can be named at the call site at all, and
778
- // its `.p + <file>` fallback spells that without `import.meta` — so the gate
779
- // below does not rule it out, and the asset's javascript wrapper stays dropped.
776
+ // `url-inline` asks only whether the file can be named at the call site, and
777
+ // its `.p + <file>` fallback spells that without `import.meta`, so the gate
778
+ // below does not rule it out.
779
+
780
780
  // `environment.module` is deliberately not consulted: ESM output writes
781
- // `import.meta` regardless (the public path, the chunk loader), so the url forms
782
- // only match what the rest of the bundle already assumes the target reads.
781
+ // `import.meta` regardless, so the url forms match what the rest of the
782
+ // bundle already assumes the target reads.
783
783
  if (form === "url-inline") return true;
784
784
  // `eval` devtool wraps each module in `eval(...)`, where `import.meta` is a
785
785
  // syntax error. Runtime modules are emitted beside them, never wrapped.
@@ -1124,10 +1124,9 @@ class RuntimeTemplate {
1124
1124
  const chunks = this._moduleChunks(module, chunkGraph);
1125
1125
  const parts = this._resolvePublicPathPrefix(publicPath);
1126
1126
  if (parts === null) return null;
1127
- // A protocol-relative base names a host but no scheme, and the runtime reads it
1128
- // against the chunk's own url to get one — the very url this literal is
1129
- // resolved against — so it may stay protocol-relative instead of being settled
1130
- // here. Nothing walks back to the output root first: the base replaces it.
1127
+ // A protocol-relative base names a host but no scheme, and the runtime reads
1128
+ // it against the very url this literal resolves against, so it may stay that
1129
+ // way. Nothing walks back to the output root: the base replaces it.
1131
1130
  if (base.startsWith("//")) {
1132
1131
  return this._specifierOf(
1133
1132
  [["literal", base], ...rootedParts(parts), ["literal", filename]],
@@ -1192,10 +1191,9 @@ class RuntimeTemplate {
1192
1191
  let base;
1193
1192
  let found = false;
1194
1193
  for (const chunk of this.compilation.chunks) {
1195
- // What a literal has to agree with is the one value `BaseUriRuntimeModule`
1196
- // writes out, and it reads the entry options off the chunk it is emitted into
1197
- // — so only a chunk carrying a runtime has a say. Entries sharing one runtime
1198
- // chunk already share the base it sets, however their descriptors differ.
1194
+ // A literal must agree with the one value `BaseUriRuntimeModule` writes, and
1195
+ // that reads the entry options off the chunk it is emitted into, so only a
1196
+ // chunk carrying a runtime has a say.
1199
1197
  if (!chunk.hasRuntime()) continue;
1200
1198
  const entryOptions = chunk.getEntryOptions();
1201
1199
  // An entry this code cannot run under has no say in the base it resolves to.
@@ -1483,14 +1481,13 @@ class RuntimeTemplate {
1483
1481
  }
1484
1482
  if (!this.supportTemplateLiteral()) return this._es5Concatenation(args);
1485
1483
 
1486
- // cost comparison between template literal and concatenation:
1487
- // both need equal surroundings: `xxx` vs "xxx"
1488
- // template literal has constant cost of 3 chars for each expression
1489
- // es5 concatenation has cost of 3 + n chars for n expressions in row
1490
- // when a es5 concatenation ends with an expression it reduces cost by 3
1491
- // when a es5 concatenation starts with an single expression it reduces cost by 3
1492
- // e. g. `${a}${b}${c}` (3*3 = 9) is longer than ""+a+b+c ((3+3)-3 = 3)
1493
- // e. g. `x${a}x${b}x${c}x` (3*3 = 9) is shorter than "x"+a+"x"+b+"x"+c+"x" (4+4+4 = 12)
1484
+ // WHY: cost comparison between a template literal and a concatenation, both
1485
+ // needing equal surroundings (`xxx` against "xxx"). A template literal costs
1486
+ // a constant 3 chars per expression; an es5 concatenation costs 3 + n chars
1487
+ // for n expressions in a row, and reduces by 3 where it ends with an
1488
+ // expression or starts with a single one. So `${a}${b}${c}` (3*3 = 9) is
1489
+ // longer than ""+a+b+c ((3+3)-3 = 3), while `x${a}x${b}x${c}x` (3*3 = 9) is
1490
+ // shorter than "x"+a+"x"+b+"x"+c+"x" (4+4+4 = 12).
1494
1491
 
1495
1492
  let templateCost = 0;
1496
1493
  let concatenationCost = 0;
@@ -2353,10 +2350,9 @@ class RuntimeTemplate {
2353
2350
  request,
2354
2351
  weak
2355
2352
  });
2356
- // Harmony imports may be wrapped in runtime-condition `if` blocks
2357
- // but referenced outside those blocks (e.g. by harmony reexport),
2358
- // so they must remain function-scoped (`var`) rather than
2359
- // block-scoped (`let`/`const`).
2353
+ // A harmony import may sit inside a runtime-condition `if` block yet be
2354
+ // referenced outside it, so it stays function-scoped with `var` rather than
2355
+ // block-scoped.
2360
2356
  const optDeclaration = update ? "" : "var ";
2361
2357
 
2362
2358
  const exportsType = module.getExportsType(
@@ -2495,10 +2491,8 @@ class RuntimeTemplate {
2495
2491
  }
2496
2492
  // accessing the .default property is same thing as `require()` the module.
2497
2493
 
2498
- // For example:
2499
- // import mod from "cjs"; mod.default.x;
2500
- // is translated to
2501
- // var mod = require("cjs"); mod.x;
2494
+ // So `import mod from "cjs"; mod.default.x` translates to
2495
+ // `var mod = require("cjs"); mod.x`.
2502
2496
  switch (exportsType) {
2503
2497
  case "dynamic":
2504
2498
  if (isCall) {
@@ -2538,10 +2532,9 @@ class RuntimeTemplate {
2538
2532
  exportsType === "default-only" ||
2539
2533
  exportsType === "default-with-named"
2540
2534
  ) {
2541
- // now exportName.length is 0, which means the namespace object is used in an unknown way
2542
- // for example:
2543
- // import * as ns from "cjs"; console.log(ns);
2544
- // we will need to createFakeNamespaceObject that simulates ES Module namespace object
2535
+ // `exportName.length` is 0, so the namespace object is used in an unknown
2536
+ // way — `import * as ns from "cjs"; console.log(ns)` — and needs
2537
+ // `createFakeNamespaceObject` to simulate an ES module namespace.
2545
2538
  runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
2546
2539
  initFragments.push(
2547
2540
  new InitFragment(
@@ -3443,9 +3436,8 @@ class RuntimeTemplate {
3443
3436
  // emitted and filled in once the hash exists.
3444
3437
  const deferred = template === undefined || HASH_IN_FILENAME.test(template);
3445
3438
  // An id names the chunk in the stand-in, and one nothing could resolve would
3446
- // reach the bundle verbatim. The whole name is re-resolved later rather than
3447
- // carrying a stand-in of its own, so any hash spelling is fine here.
3448
- // One of the two always names where the reference goes.
3439
+ // reach the bundle verbatim. The whole name is re-resolved later, so any hash
3440
+ // spelling is fine here; one of the two always names the destination.
3449
3441
  const chunks =
3450
3442
  consumingChunks ||
3451
3443
  this._moduleChunks(/** @type {Module} */ (consumingModule), chunkGraph);
@@ -4355,11 +4347,9 @@ class RuntimeTemplate {
4355
4347
  compilation.hooks.processAssets.tapPromise(
4356
4348
  {
4357
4349
  name: PASS_NAME,
4358
- // Before source maps are written and before a minifier runs: both read
4359
- // the asset, and a stand-in is a different length than what replaces it.
4360
- // Every hash it reads is already settled — `createHash` runs ahead of
4361
- // every `processAssets` stage — and `RealContentHashPlugin` still repairs
4362
- // the names afterwards.
4350
+ // Before source maps are written and before a minifier runs, since both
4351
+ // read the asset and a stand-in differs in length from what replaces it.
4352
+ // Every hash it reads is settled: `createHash` precedes every stage.
4363
4353
  stage: getCompilation().PROCESS_ASSETS_STAGE_DERIVED
4364
4354
  },
4365
4355
  async () => {
@@ -152,11 +152,9 @@ const extractSourceAndMap = (file, asset, options, registry) => {
152
152
  if (!registry.has(file)) registry.set(file, asset);
153
153
  return { source, sourceMap, mapSource: asset };
154
154
  }
155
- // The current asset (typically a `RawSource` left by an earlier
156
- // SourceMapDevToolPlugin instance) has no internal map. Re-extract
157
- // the map from the original Source we pinned earlier. We keep using
158
- // `source` from the current asset so that any prior wrappers (e.g.
159
- // appended sourceMappingURL comments) are preserved.
155
+ // The current asset, typically a `RawSource` an earlier instance left, has no
156
+ // internal map, so re-extract one from the pinned original. `source` still
157
+ // comes from the current asset, preserving any wrappers it gained.
160
158
  const original = registry.get(file);
161
159
  if (!original) return;
162
160
  sourceMap = original.sourceAndMap
@@ -262,12 +260,9 @@ class SourceMapDevToolPlugin {
262
260
  this.namespace = options.namespace || "";
263
261
  /** @type {SourceMapDevToolPluginOptions} */
264
262
  this.options = options;
265
- // Cache salt derived from output-affecting options, so that two
266
- // SourceMapDevToolPlugin instances (or `devtool` + a plugin) operating
267
- // on the same asset don't share a cache entry. We serialize via
268
- // `JSON.stringify` rather than a homemade separator so that any
269
- // special characters (e.g. `|` inside a publicPath or sourceRoot)
270
- // can't accidentally make two different option sets collide.
263
+ // Salt from the output-affecting options, so two instances on the same asset
264
+ // never share a cache entry. Serialized with `JSON.stringify` rather than a
265
+ // separator, which a `|` in a publicPath could collide through.
271
266
  /** @type {string} */
272
267
  this._cacheSalt = JSON.stringify([
273
268
  toCacheKeyValue(options.filename),
@@ -326,12 +321,9 @@ class SourceMapDevToolPlugin {
326
321
  compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
327
322
  new SourceMapDevToolModuleOptionsPlugin(options).apply(compilation);
328
323
 
329
- // All SourceMapDevToolPlugin instances on the same compilation share
330
- // a registry of pristine asset sources, so the second instance to
331
- // run can still recover the original map after the first instance
332
- // has replaced the asset with a `RawSource`. The registry lives on a
333
- // module-scoped `WeakMap` keyed by compilation so it is released
334
- // automatically and never pollutes the compilation object.
324
+ // Every instance on a compilation shares this registry of pristine
325
+ // sources, so a later one still recovers the original map after the first
326
+ // replaced the asset. Keyed by compilation, so it releases on its own.
335
327
  const originalSources = getOriginalSourceRegistry(compilation);
336
328
 
337
329
  compilation.hooks.processAssets.tapAsync(
@@ -372,23 +364,12 @@ class SourceMapDevToolPlugin {
372
364
  const tasks = [];
373
365
  let fileIndex = 0;
374
366
 
375
- // Shared deduplication set for `Source#clearCache` calls below.
376
- // Webpack chunks routinely share module-level `CachedSource`
377
- // instances. A per-call WeakSet would re-walk those shared
378
- // subtrees once per chunk — 50 chunks × thousands of shared
379
- // modules in dev/non-minified setups — and worse, every
380
- // chunk's `sourceAndMap` would have to recompute the cleared
381
- // caches, churning allocations (measured: +700 MB peak RSS,
382
- // +6 s wall time on a 50×1000 synthetic build).
383
- //
384
- // Sharing one set lets each shared subtree be walked exactly
385
- // once. The trade-off is that subsequent chunks' `sourceAndMap`
386
- // calls can repopulate a shared module's `_cachedMaps` after
387
- // its own clear was skipped (because the module is already in
388
- // the visited set), leaving at most one populated cache entry
389
- // per shared module at the end of the run — bounded to a few
390
- // MB even at the scale of #20961. That's strictly preferable
391
- // to the alternative's hundreds of MB of transient peak RSS.
367
+ // WHY: chunks share module-level `CachedSource` instances, so a
368
+ // per-call set re-walks each shared subtree once per chunk and every
369
+ // `sourceAndMap` then recomputes the cleared caches — measured at
370
+ // +700 MB peak RSS and +6 s on a 50×1000 build. One shared set walks
371
+ // each subtree once, at the cost of leaving at most one populated
372
+ // cache entry per shared module, a few MB even at #20961's scale.
392
373
  const clearCacheVisited = new WeakSet();
393
374
 
394
375
  asyncLib.each(
@@ -403,14 +384,12 @@ class SourceMapDevToolPlugin {
403
384
  chunk
404
385
  });
405
386
 
406
- // The cache item identifier must include the per-instance
407
- // salt so two SourceMapDevToolPlugin instances that target
408
- // the same `file` don't collide in the persistent cache —
409
- // they'd otherwise write different content to the same key
410
- // and invalidate every pack on each build. We encode via
411
- // `JSON.stringify` so that special characters (e.g. `|`)
412
- // in an asset filename can't be spoofed to collide with the
413
- // salt portion of the identifier.
387
+ // WHY: the cache item identifier carries the per-instance salt, or
388
+ // two SourceMapDevToolPlugin instances targeting the same `file`
389
+ // would write different content to one key and invalidate every pack
390
+ // on each build. `JSON.stringify` encodes it, so a special character
391
+ // such as `|` in an asset filename cannot be spoofed to collide with
392
+ // the salt portion.
414
393
  const cacheItem = cache.getItemCache(
415
394
  JSON.stringify([file, this._cacheSalt]),
416
395
  cache.mergeEtags(
@@ -427,12 +406,9 @@ class SourceMapDevToolPlugin {
427
406
  * If presented in cache, reassigns assets. Cache assets already have source maps.
428
407
  */
429
408
  if (cacheEntry) {
430
- // Pin the still-unwrapped asset source in the registry
431
- // before `compilation.updateAsset` replaces it. This is a
432
- // pointer assignment — no source-map extraction work — and
433
- // it lets a subsequent SourceMapDevToolPlugin instance
434
- // extract the original map on demand even though the
435
- // persistent cache hit lets us skip processing here.
409
+ // Pin the still-unwrapped source before `updateAsset` replaces
410
+ // it — a pointer assignment, no extraction — so a later
411
+ // instance can still reach the original map past this cache hit.
436
412
  if (!originalSources.has(file)) {
437
413
  originalSources.set(file, asset.source);
438
414
  }
@@ -489,33 +465,21 @@ class SourceMapDevToolPlugin {
489
465
  originalSources
490
466
  );
491
467
 
492
- // Release the per-instance caches that `sourceAndMap`
493
- // just populated. The composed map (and, for
494
- // `SourceMapSource`, the parsed `_sourceMapAsObject` /
495
- // `_innerSourceMapAsObject`) otherwise sit on the
496
- // CachedSource — and every shared child — until phase
497
- // 2 replaces the asset, which is what causes the OOM
498
- // spike on builds with thousands of chunks
499
- // (webpack#20961). Keep `source` since downstream
500
- // consumers reading the original asset still need it;
501
- // `hash`/`size` default to retained because they're
502
- // cheap to keep but expensive to rebuild.
503
- // `clearCacheVisited` is shared across every call (see
504
- // its declaration above for the rationale).
468
+ // WHY: the map `sourceAndMap` just composed otherwise sits on
469
+ // the CachedSource and every shared child until phase 2
470
+ // replaces the asset, which is the OOM spike of webpack#20961
471
+ // on builds with thousands of chunks. `source` is kept for
472
+ // downstream consumers, `hash` and `size` because they are
473
+ // cheap to hold and expensive to rebuild.
505
474
  //
506
- // Target `task.mapSource` (not `asset.source`): when
507
- // `extractSourceAndMap` falls back to the pinned
508
- // original (the current asset is a `RawSource` left
509
- // by an earlier plugin instance), the `sourceAndMap`
510
- // call populated the original's caches, not the
511
- // current asset's.
512
- //
513
- // Feature-detected: `clearCache` landed in
514
- // `webpack-sources` 3.5, but `compilation.assets` may
515
- // hold `Source`-like instances from a third-party
516
- // plugin built against an older copy of
517
- // `webpack-sources` (or a hand-rolled implementation).
518
- // Calling it unconditionally would throw on those.
475
+ // `task.mapSource`, not `asset.source`: where the fallback to
476
+ // the pinned original ran — the current asset being a
477
+ // `RawSource` an earlier instance left — the original's caches
478
+ // are the ones `extractSourceAndMap` populated.
479
+
480
+ // Feature-detected, since `clearCache` landed in
481
+ // `webpack-sources` 3.5 and a third-party plugin may hand us a
482
+ // `Source` built against an older copy.
519
483
  if (task && typeof task.mapSource.clearCache === "function") {
520
484
  task.mapSource.clearCache(
521
485
  {
@@ -660,14 +624,9 @@ class SourceMapDevToolPlugin {
660
624
  const moduleFilenames =
661
625
  /** @type {string[]} */
662
626
  (modules.map((m) => moduleToSourceNameMapping.get(m)));
663
- // We deliberately do NOT mutate `sourceMap` in place: the
664
- // task's `sourceMap` reference may be shared with a
665
- // `SourceMapSource` whose internal map cache is the same
666
- // object (webpack-sources keeps it cached). A second
667
- // `SourceMapDevToolPlugin` instance that reads the original
668
- // source through the registry would otherwise see our
669
- // rewrites. Instead we build a fresh `outputSourceMap` for
670
- // the .map file and leave the original alone.
627
+ // `sourceMap` is never mutated in place: the reference may be
628
+ // the same object a `SourceMapSource` has cached, so a second
629
+ // instance reading through the registry would see the rewrites.
671
630
  /** @type {number[] | undefined} */
672
631
  let ignoreList;
673
632
  if (options.ignoreList) {
@@ -736,10 +695,9 @@ class SourceMapDevToolPlugin {
736
695
  } else if (
737
696
  typeof currentSourceMappingURLComment === "function"
738
697
  ) {
739
- // Wrap the user's append function so the debug-id
740
- // comment is prepended at call time. Template-string
741
- // concatenation would coerce the function to a string
742
- // and lose its dynamic behavior.
698
+ // Wrap the user's append function so the debug-id comment is
699
+ // prepended at call time; concatenating would coerce the
700
+ // function to a string and lose its behavior.
743
701
  const wrappedFn = currentSourceMappingURLComment;
744
702
  currentSourceMappingURLComment = (pathData, assetInfo) =>
745
703
  `${debugIdComment}${wrappedFn(pathData, assetInfo)}`;
@@ -766,14 +724,9 @@ class SourceMapDevToolPlugin {
766
724
  }
767
725
 
768
726
  if (sourceMapFilename) {
769
- // External `.map` file: hold the serialized map as a
770
- // `Buffer` instead of a V8 string. `RawSource` accepts
771
- // a buffer directly, and the emitted asset stays in
772
- // `compilation.assets` until the build finishes — so
773
- // storing the bytes off the V8 heap (where Buffers
774
- // live, accounted as `external` memory) avoids keeping
775
- // a large V8 string alive for the rest of the build
776
- // and reduces heap pressure on `--max-old-space-size`.
727
+ // Hold the serialized map as a `Buffer`, which `RawSource`
728
+ // takes directly: the asset lives in `compilation.assets`
729
+ // until the build ends, and these bytes stay off the V8 heap.
777
730
  const sourceMapBuffer = Buffer.from(
778
731
  JSON.stringify(outputSourceMap),
779
732
  "utf8"
@@ -820,10 +773,9 @@ class SourceMapDevToolPlugin {
820
773
  })
821
774
  );
822
775
  }
823
- // Preserve any existing related.sourceMap entries from
824
- // earlier SourceMapDevToolPlugin runs on the same asset so
825
- // that all generated maps remain discoverable via asset
826
- // info (the schema allows string or string[]).
776
+ // Preserve the `related.sourceMap` entries earlier runs left on
777
+ // this asset, so every generated map stays discoverable; the
778
+ // schema allows a string or an array.
827
779
  const existingSourceMap =
828
780
  task.assetInfo.related &&
829
781
  task.assetInfo.related.sourceMap;
@@ -879,11 +831,9 @@ class SourceMapDevToolPlugin {
879
831
  `${PLUGIN_NAME}: append can't be a function when no filename is provided`
880
832
  );
881
833
  }
882
- // Inline data-URL form: `[map]` gets the raw JSON, `[url]`
883
- // gets the same JSON base64-encoded. `URL_COMMENT_REGEXP`
884
- // is a `/g` regex, so a user `append` template with more
885
- // than one `[url]` placeholder would otherwise re-encode
886
- // the same JSON per match. Pre-compute both once.
834
+ // Inline data-URL form: `[map]` takes the raw JSON and `[url]`
835
+ // the same base64-encoded. Both are precomputed, or a template
836
+ // with two `[url]`s would re-encode per match.
887
837
  const sourceMapString = JSON.stringify(outputSourceMap);
888
838
  const sourceMapBase64 = Buffer.from(
889
839
  sourceMapString,
@@ -77,10 +77,9 @@ const getPresentKinds = (path) => {
77
77
  return kinds;
78
78
  };
79
79
 
80
- // `[fullhash:<digest>]`/`[hash:<digest>]` — a non-numeric first argument is a digest
81
- // (a numeric one is just a length). A digest re-encodes the hash rather than reading
82
- // it, so no stand-in or runtime expression can take its place: the settled value has
83
- // to be inlined instead.
80
+ // In `[fullhash:<arg>]` a non-numeric argument names a digest, a numeric one just
81
+ // a length. A digest re-encodes the hash rather than reading it, so no stand-in
82
+ // can stand for it and the settled value must be inlined.
84
83
  const FULL_HASH_DIGEST_REGEXP = /\[(?:fullhash|hash):(?!\d+\])\w/;
85
84
 
86
85
  /**
@@ -408,11 +407,9 @@ const interpolate = (path, data, assetInfo) => {
408
407
  return path;
409
408
  }
410
409
 
411
- // Only build replacers for placeholders the template actually uses — most
412
- // templates reference a handful, so building the whole table per call is
413
- // wasted work. Replacer construction has no side effects (those fire only
414
- // when a replacer is invoked, which happens for present kinds), so this is
415
- // output-identical.
410
+ // Build replacers only for the placeholders a template uses, since most use a
411
+ // handful. Construction has no side effects — those fire on invocation — so
412
+ // the output is identical either way.
416
413
  const presentKinds = getPresentKinds(path);
417
414
 
418
415
  const chunkGraph = data.chunkGraph;
@@ -422,21 +419,9 @@ const interpolate = (path, data, assetInfo) => {
422
419
  /** @type {Map<string, Replacer>} */
423
420
  const replacements = new Map();
424
421
 
425
- // Filename context
426
- //
427
- // Placeholders
428
- //
429
- // for /some/path/file.js?query#fragment:
430
- // [file] - /some/path/file.js
431
- // [query] - ?query
432
- // [fragment] - #fragment
433
- // [base] - file.js
434
- // [path] - /some/path/
435
- // [name] - file
436
- // [ext] - .js
437
- //
438
- // [containedfile] and [containedpath] are [file] and [path] kept inside
439
- // `output.path`
422
+ // Filename context. Of `/some/path/file.js?query#fragment`, `[file]` is the
423
+ // path without query or fragment, `[base]` its basename, `[path]` its
424
+ // directory, `[name]`/`[ext]` its halves; `contained*` stay under `output.path`.
440
425
  if (
441
426
  typeof data.filename === "string" &&
442
427
  (presentKinds.has("file") ||
@@ -534,15 +519,7 @@ const interpolate = (path, data, assetInfo) => {
534
519
  }
535
520
  }
536
521
 
537
- // Compilation context
538
- //
539
- // Placeholders
540
- //
541
- // [fullhash] - data.hash (3a4b5c6e7f)
542
- //
543
- // Legacy Placeholders
544
- //
545
- // [hash] - data.hash (3a4b5c6e7f)
522
+ // Compilation context: `[fullhash]`, with `[hash]` as its legacy spelling.
546
523
  if (data.hash && (presentKinds.has("fullhash") || presentKinds.has("hash"))) {
547
524
  const hashReplacer = hashLength(
548
525
  replacer(data.hash),
@@ -574,14 +551,8 @@ const interpolate = (path, data, assetInfo) => {
574
551
  }
575
552
  }
576
553
 
577
- // Chunk Context
578
- //
579
- // Placeholders
580
- //
581
- // [id] - chunk.id (0.js)
582
- // [name] - chunk.name (app.js)
583
- // [chunkhash] - chunk.hash (7823t4t4.js)
584
- // [contenthash] - chunk.contentHash[type] (3256u3zg.js)
554
+ // Chunk context: `[id]`, `[name]`, `[chunkhash]`, and `[contenthash]` for the
555
+ // chunk's content hash of the requested type.
585
556
  if (data.chunk) {
586
557
  const chunk = data.chunk;
587
558
 
@@ -638,17 +609,8 @@ const interpolate = (path, data, assetInfo) => {
638
609
  }
639
610
  }
640
611
 
641
- // Module Context
642
- //
643
- // Placeholders
644
- //
645
- // [id] - module.id (2.png)
646
- // [hash] - module.hash (6237543873.png)
647
- //
648
- // Legacy Placeholders
649
- //
650
- // [moduleid] - module.id (2.png)
651
- // [modulehash] - module.hash (6237543873.png)
612
+ // Module context: `[id]` and `[hash]`, with `[moduleid]` and `[modulehash]` as
613
+ // their legacy spellings.
652
614
  if (data.module) {
653
615
  const module = data.module;
654
616
  const needId = presentKinds.has("id");
@@ -739,13 +701,8 @@ const interpolate = (path, data, assetInfo) => {
739
701
  }
740
702
  }
741
703
 
742
- // Other things
743
- //
744
- // Placeholders
745
- //
746
- // [url] - data.url
747
- // [uniqueName] - data.uniqueName (output.uniqueName)
748
- // [uniquename] - alias of [uniqueName]
704
+ // Everything else: `[url]`, and `[uniqueName]` from `output.uniqueName`, which
705
+ // `[uniquename]` aliases.
749
706
  if (data.url && presentKinds.has("url")) {
750
707
  replacements.set("url", replacer(data.url));
751
708
  }
@@ -114,7 +114,13 @@ class AssetBytesGenerator extends Generator {
114
114
  generateError(error, module, generateContext) {
115
115
  switch (generateContext.type) {
116
116
  case JAVASCRIPT_TYPE: {
117
- return new RawSource(Generator.throwBuildErrorCode(error));
117
+ return new RawSource(
118
+ Generator.throwBuildErrorCode(
119
+ error,
120
+ undefined,
121
+ generateContext.runtimeTemplate.requestShortener
122
+ )
123
+ );
118
124
  }
119
125
  default:
120
126
  return null;
@@ -791,10 +791,21 @@ class AssetGenerator extends Generator {
791
791
  generateError(error, module, generateContext) {
792
792
  switch (generateContext.type) {
793
793
  case "asset": {
794
- return new RawSource(error.message);
794
+ return new RawSource(
795
+ Generator.buildErrorMessage(
796
+ error,
797
+ generateContext.runtimeTemplate.requestShortener
798
+ )
799
+ );
795
800
  }
796
801
  case JAVASCRIPT_TYPE: {
797
- return new RawSource(Generator.throwBuildErrorCode(error));
802
+ return new RawSource(
803
+ Generator.throwBuildErrorCode(
804
+ error,
805
+ undefined,
806
+ generateContext.runtimeTemplate.requestShortener
807
+ )
808
+ );
798
809
  }
799
810
  default:
800
811
  return null;
@@ -836,13 +847,14 @@ class AssetGenerator extends Generator {
836
847
  /** @type {AssetModuleBuildInfo} */ (module.buildInfo).dataUrl
837
848
  ) && this.emit !== false;
838
849
 
839
- // Only analyzable ESM output can drop a bare `new URL()` to an asset-url; without
840
- // it every JS consumer needs the wrapper, so skip the per-connection dependency
841
- // probe entirely and keep the pre-existing cheap path. Must match the condition
842
- // `URLDependency` uses to emit the literal, or the wrapper is dropped while the
843
- // call site still requires the module — except where the fallback spells the name
844
- // itself (`.p + <file>`), which needs no wrapper to read it out of.
845
- // Build-time execution instead emulates the wrapper (`AssetModulesPlugin`).
850
+ // WHY: only analyzable ESM output can drop a bare `new URL()` to an asset
851
+ // url; without it every JS consumer needs the wrapper, so the per-connection
852
+ // dependency probe is skipped entirely and the cheap path stands. This must
853
+ // match the condition `URLDependency` emits the literal under, or the wrapper
854
+ // is dropped while the call site still requires the module — except where the
855
+ // fallback spells the name itself (`.p + <file>`), which needs no wrapper to
856
+ // read it out of. Build-time execution emulates the wrapper instead
857
+ // (`AssetModulesPlugin`).
846
858
  const isModule = Boolean(
847
859
  this._compilation &&
848
860
  this._compilation.runtimeTemplate.supportsAnalyzable(
@@ -874,9 +886,8 @@ class AssetGenerator extends Generator {
874
886
  hasUrl = true;
875
887
  } else if (
876
888
  // Only a bare `new URL()` becomes the analyzable literal; a relative ref
877
- // keeps the runtime form and still needs the wrapper. Prefetch/preload
878
- // refs don't: their `<link>` is emitted at chunk startup, which resolves
879
- // the href from the asset filename when there is no wrapper.
889
+ // keeps the runtime form and its wrapper. A prefetch or preload ref needs
890
+ // none: its `<link>` resolves the href at chunk startup.
880
891
  isModule &&
881
892
  dependency instanceof URLDependency &&
882
893
  !dependency.relative
@@ -961,10 +972,8 @@ class AssetGenerator extends Generator {
961
972
  return 0;
962
973
  }
963
974
 
964
- // roughly for data url
965
- // Example: m.exports="data:image/png;base64,ag82/f+2=="
966
- // 4/3 = base64 encoding
967
- // 34 = ~ data url header + footer + rounding
975
+ // Rough data-url size: 4/3 for the base64 encoding, plus about 34 bytes
976
+ // of header, footer and rounding.
968
977
  return originalSource.size() * 1.34 + 36;
969
978
  }
970
979
  // it's only estimated so this number is probably fine
@@ -158,7 +158,13 @@ class AssetSourceGenerator extends Generator {
158
158
  generateError(error, module, generateContext) {
159
159
  switch (generateContext.type) {
160
160
  case JAVASCRIPT_TYPE: {
161
- return new RawSource(Generator.throwBuildErrorCode(error));
161
+ return new RawSource(
162
+ Generator.throwBuildErrorCode(
163
+ error,
164
+ undefined,
165
+ generateContext.runtimeTemplate.requestShortener
166
+ )
167
+ );
162
168
  }
163
169
  default:
164
170
  return null;