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
@@ -348,10 +348,9 @@ const getSourceForImportExternal = (
348
348
  }
349
349
  const phase = dependencyMeta && dependencyMeta.phase;
350
350
  checkPhaseIsSupported(phase, runtimeTemplate);
351
- // `import.defer(…)` and `import.source(…)` are only valid forms of the
352
- // native `import(…)` function, so we only emit the phase suffix when the
353
- // importFunctionName is the default `"import"`. Anything else has no phase
354
- // form at all, and dropping it would silently import eagerly instead.
351
+ // `import.defer(…)` and `import.source(…)` are forms of the native `import(…)`
352
+ // alone, so the phase suffix is emitted only for the default name. Anything
353
+ // else has no phase form, and dropping it would import eagerly instead.
355
354
  if (
356
355
  baseImportName !== "import" &&
357
356
  (ImportPhaseUtils.isDefer(phase) || ImportPhaseUtils.isSource(phase))
@@ -695,10 +694,9 @@ const getSourceForModuleExternal = (
695
694
  imported = true;
696
695
  }
697
696
 
698
- // `import defer …` is only valid as `import defer * as ns from "…"`, so
699
- // keep the namespace form even if usage analysis would otherwise narrow
700
- // the import down to specific names. Defer + concatenation is semantically
701
- // at odds (lazy vs. eager), so we preserve the user-written shape here.
697
+ // `import defer` is valid only as `import defer * as ns from "…"`, so the
698
+ // namespace form is kept even where usage analysis would narrow it: defer and
699
+ // concatenation are at odds, lazy against eager.
702
700
  if (ImportPhaseUtils.isDefer(phase)) {
703
701
  imported = true;
704
702
  }
@@ -138,9 +138,8 @@ class FlagDependencyExportsPlugin {
138
138
  hashFunction
139
139
  );
140
140
  // validated by the still-lazy request keys: reference-change
141
- // detection cannot invalidate the mem cache when the un-lazied
142
- // connections are unsafe-cached (they are skipped when comparing
143
- // references)
141
+ // detection cannot invalidate the mem cache while the un-lazied
142
+ // connections are unsafe-cached, being skipped in the comparison
144
143
  if (memCacheEntry !== undefined && memCacheEntry.etag === etag) {
145
144
  statRestoredFromMemCache++;
146
145
  exportsInfo.restoreProvided(memCacheEntry.data);
@@ -172,16 +171,12 @@ class FlagDependencyExportsPlugin {
172
171
  logger.timeEnd("restore cached provided exports");
173
172
  if (err) return callback(err);
174
173
 
175
- // Seed the queue with targets before the modules that read
176
- // them. Enqueueing at the two branches above ordered the work by
177
- // how fast each cache lookup answered — one is synchronous, the
178
- // other a `cache.get` callback — so the persistent cache decided
179
- // it. A module analysed before the module it re-exports from
180
- // reads exports that are not determined yet and over-estimates,
181
- // and this loop can add exports info but never retract it, so
182
- // the over-estimate survives the pass that corrects it. The
183
- // roots are sorted so the walk is stable, and post-order visits
184
- // each module after everything it points at.
174
+ // WHY: enqueueing at the branches above ordered the work by how
175
+ // fast each cache lookup answered, letting the persistent cache
176
+ // decide it. A module analyzed before the one it re-exports from
177
+ // over-estimates its exports, and this loop can add exports info
178
+ // but never retract it, so that over-estimate would survive. Sorted
179
+ // roots and post-order visit each module after what it points at.
185
180
  /** @type {Set<Module>} */
186
181
  const visited = new Set();
187
182
  /** @type {Module[]} */
@@ -93,10 +93,9 @@ class FlagDependencyUsagePlugin {
93
93
  const processReferencedModule = (module, usedExports, runtime) => {
94
94
  const exportsInfo = moduleGraph.getExportsInfo(module);
95
95
  if (usedExports === EXPORTS_OBJECT_REFERENCED_MANGLEABLE) {
96
- // The whole namespace object escapes via a reference that codegen
97
- // can materialize as a decoupled namespace object. When all exports
98
- // are statically known we keep them mangleable instead of marking
99
- // them used-in-unknown-way.
96
+ // The namespace object escapes through a reference codegen can
97
+ // materialize, so with every export statically known they stay
98
+ // mangleable rather than used-in-unknown-way.
100
99
  if (
101
100
  this.mangleEscapingNamespaces &&
102
101
  module.buildMeta &&
@@ -237,10 +236,9 @@ class FlagDependencyUsagePlugin {
237
236
  /** @typedef {Map<string, string[] | ReferencedExport>} ExportMaps */
238
237
  /** @type {Map<Module, ReferencedExports | ExportMaps>} */
239
238
  const map = new Map();
240
- // Modules whose whole namespace object escapes in a mangleable way.
241
- // Tracked separately so specific member references are still merged
242
- // (and marked used) instead of being dropped by the escape marker.
243
- // Lazily allocated — usually empty.
239
+ // Modules whose whole namespace escapes but stays mangleable, kept
240
+ // apart so specific member references are still merged and marked
241
+ // used rather than dropped by the escape marker. Usually empty.
244
242
  /** @type {Set<Module> | undefined} */
245
243
  let mangleableEscapeModules;
246
244
 
@@ -289,11 +287,9 @@ class FlagDependencyUsagePlugin {
289
287
  }
290
288
  continue;
291
289
  }
292
- // A mangleable whole-object escape keeps the module's exports
293
- // mangleable (applied after the merge). Unlike the conservative
294
- // marker it must not drop specific member references: those still
295
- // need their own (possibly non-existent) export marked used so
296
- // they render as a qualified access, not a bare `undefined`.
290
+ // A mangleable escape keeps the exports mangleable, applied after
291
+ // the merge. It must not drop specific member references: each
292
+ // still needs marking, or it renders as a bare `undefined`.
297
293
  if (
298
294
  referencedExports === EXPORTS_OBJECT_REFERENCED_MANGLEABLE
299
295
  ) {
package/lib/Generator.js CHANGED
@@ -5,6 +5,7 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ const { contextifyStackFrames } = require("./ErrorHelpers");
8
9
  const { JAVASCRIPT_TYPE } = require("./ModuleSourceTypeConstants");
9
10
  const memoize = require("./util/memoize");
10
11
 
@@ -23,6 +24,7 @@ const memoize = require("./util/memoize");
23
24
  * } from "./Module"
24
25
  */
25
26
  /** @import ModuleGraph from "./ModuleGraph" */
27
+ /** @import RequestShortener from "./RequestShortener" */
26
28
  /** @import NormalModule from "./NormalModule" */
27
29
  /** @import RuntimeTemplate from "./RuntimeTemplate" */
28
30
  /** @import Hash from "./util/Hash" */
@@ -73,18 +75,38 @@ class Generator {
73
75
  return new ByTypeGenerator(map);
74
76
  }
75
77
 
78
+ /**
79
+ * Returns what a module that failed to build says about it in the output.
80
+ * The stack it carries is written relative to the context, keeping a
81
+ * position only where a second build names the same one.
82
+ * @param {Error} error the build error
83
+ * @param {RequestShortener=} requestShortener request shortener, absolute paths are kept without one
84
+ * @returns {string} message to emit
85
+ */
86
+ static buildErrorMessage(error, requestShortener) {
87
+ return requestShortener
88
+ ? contextifyStackFrames(error.message, requestShortener)
89
+ : error.message;
90
+ }
91
+
76
92
  /**
77
93
  * Returns the statement a module that failed to build throws when executed.
78
94
  * @param {Error} error the build error
79
95
  * @param {string=} parseErrorConstructor constructor for a rejected source, defaults to `SyntaxError` (WebAssembly rejects with `WebAssembly.CompileError` instead)
96
+ * @param {RequestShortener=} requestShortener request shortener for the stack the message carries
80
97
  * @returns {string} javascript statement
81
98
  */
82
- static throwBuildErrorCode(error, parseErrorConstructor = "SyntaxError") {
99
+ static throwBuildErrorCode(
100
+ error,
101
+ parseErrorConstructor = "SyntaxError",
102
+ requestShortener = undefined
103
+ ) {
83
104
  // A source the parser rejected throws what a native load of it would.
84
105
  const name =
85
106
  error instanceof getModuleParseError() ? parseErrorConstructor : "Error";
107
+ const message = Generator.buildErrorMessage(error, requestShortener);
86
108
 
87
- return `throw new ${name}(${JSON.stringify(error.message)});`;
109
+ return `throw new ${name}(${JSON.stringify(message)});`;
88
110
  }
89
111
 
90
112
  /* istanbul ignore next */
@@ -76,6 +76,8 @@ const {
76
76
  /** @typedef {{ updatedChunkIds: ChunkIds, removedChunkIds: ChunkIds, removedModules: ModuleSet, forceLoadChunkIds: ChunkIds, filename: string, assetInfo: AssetInfo }} HotUpdateMainContentByRuntimeItem */
77
77
  /** @typedef {Map<string, HotUpdateMainContentByRuntimeItem>} HotUpdateMainContentByRuntime */
78
78
 
79
+ /** @typedef {{ hot?: boolean }} HotModuleReplacementPluginLoaderContext */
80
+
79
81
  /**
80
82
  * Whether a filename template reads any hash, so the name it gives a chunk can move
81
83
  * between two builds.
@@ -15,7 +15,7 @@ const EntryDependency = require("./dependencies/EntryDependency");
15
15
  */
16
16
  /** @import Compiler from "./Compiler" */
17
17
  /** @import { ResolveData } from "./NormalModuleFactory" */
18
- /** @import { BeforeContextResolveData } from "./ContextModuleFactory" */
18
+ /** @import { BeforeContextResolveData } from "./context/ContextModuleFactory" */
19
19
 
20
20
  /** @typedef {(resource: string, context: string) => boolean} CheckResourceFn */
21
21
 
@@ -19,7 +19,7 @@ const NormalModule = require("./NormalModule");
19
19
  /**
20
20
  * Defines the loader context type used by this module.
21
21
  * @template T
22
- * @typedef {import("../declarations/LoaderContext").LoaderContext<T>} LoaderContext
22
+ * @typedef {import("./NormalModule").LoaderContext<T>} LoaderContext
23
23
  */
24
24
 
25
25
  const PLUGIN_NAME = "LoaderOptionsPlugin";
package/lib/Module.js CHANGED
@@ -129,6 +129,9 @@ const makeSerializable = require("./util/makeSerializable");
129
129
  * @property {Set<string>} freeNames free identifier names in the rendered source for javascript modules
130
130
  * @property {InitFragment<EXPECTED_ANY>[]} chunkInitFragments chunk init fragments for javascript modules
131
131
  * @property {string} externalReexport native external reexport source and attributes
132
+ * @property {string} exportsSource export definitions left out of a javascript module's source on demand (see `KnownMeta.onDemandExports`), to be placed before its body where it is wrapped
133
+ * @property {string} exportsBindingSource export definitions left out on demand that read the module's own declarations, to be placed after its body where it is wrapped
134
+ * @property {Record<string, string>} exportsFinalName final name of each used export of a concatenated module whose definitions were left out on demand
132
135
  * @property {{ javascript?: string, ["asset-url"]?: string }} url url for asset modules
133
136
  * @property {string} filename a filename for asset modules
134
137
  * @property {AssetInfo} assetInfo an asset info for asset modules
@@ -182,9 +185,6 @@ const makeSerializable = require("./util/makeSerializable");
182
185
  * @property {(false | "redirect" | "redirect-warn")=} defaultObject
183
186
  * @property {boolean=} async
184
187
  * @property {boolean=} sideEffectFree
185
- * @property {Map<string, Record<string, string>>=} exportsFinalNameByRuntime using in ModuleLibraryPlugin
186
- * @property {Map<string, string>=} exportsSourceByRuntime using in ModuleLibraryPlugin
187
- * @property {Map<string, string>=} exportsBindingSourceByRuntime export definitions `ModuleLibraryPlugin` took over, re-emitted only where the module is wrapped
188
188
  */
189
189
 
190
190
  /**
@@ -143,6 +143,7 @@ class ModuleGraphModule {
143
143
  * @typedef {object} KnownMeta
144
144
  * @property {Map<Module, string>=} importVarMap
145
145
  * @property {Map<Module, string>=} deferredImportVarMap
146
+ * @property {boolean=} onDemandExports generate export definitions on demand
146
147
  */
147
148
 
148
149
  /** @typedef {KnownMeta & Record<CommonJsExportRequireDependencyIDsSymbol | HarmonyImportSpecifierDependencyIDsSymbol | HarmonyExportImportedSpecifierDependencyIDsSymbol, string[]> & Record<string, EXPECTED_ANY>} Meta */
@@ -342,10 +343,8 @@ class ModuleGraph {
342
343
  }
343
344
  const originDependency = connection.dependency;
344
345
 
345
- // src/index.js
346
- // import { c } from "lib/c" -> c = 0
347
- // import { a, b } from "lib" -> a and b have the same source order -> a = b = 1
348
- // import { d } from "lib/d" -> d = 2
346
+ // Specifiers of one import statement share its source order, so `a` and `b`
347
+ // of `import { a, b } from "lib"` both take the statement's index.
349
348
  const currentSourceOrder =
350
349
  /** @type {HarmonyImportSideEffectDependency | HarmonyImportSpecifierDependency} */
351
350
  (dependency).sourceOrder;
@@ -360,11 +359,9 @@ class ModuleGraph {
360
359
  typeof currentSourceOrder === "number" &&
361
360
  typeof originSourceOrder === "number"
362
361
  ) {
363
- // src/index.js
364
- // import { c } from "lib/c" -> c = 0
365
- // import { a } from "lib/a" -> a = 1.0 = 1(main) + 0.0(sub)
366
- // import { b } from "lib/b" -> b = 1.1 = 1(main) + 0.1(sub)
367
- // import { d } from "lib/d" -> d = 2
362
+ // A re-exported specifier keeps the importing statement's order as `main`
363
+ // and its own position as `sub`, so the pair orders it within that
364
+ // statement without disturbing the statements around it.
368
365
  this._dependencySourceOrderMap.set(dependency, {
369
366
  main: currentSourceOrder,
370
367
  sub: originSourceOrder
@@ -158,11 +158,9 @@ module.exports = class MultiCompiler {
158
158
  doneCompilers--;
159
159
  }
160
160
  });
161
- // Release fields on this child's Compilation once it's done. The
162
- // stage: Infinity tap runs after every afterDone tap at a lower
163
- // stage, so plugins observing compilation state in afterDone still
164
- // see it intact. Stats remains usable; only fields Stats never reads
165
- // (and that the persistent cache never serializes) are dropped.
161
+ // Release this child's Compilation fields once it is done. The
162
+ // `stage: Infinity` tap runs last, so a plugin watching in afterDone still
163
+ // sees it intact, and only fields Stats never reads are dropped.
166
164
 
167
165
  compiler.hooks.afterDone.tap(
168
166
  { name: CLASS_NAME, stage: Infinity },
@@ -478,17 +476,9 @@ module.exports = class MultiCompiler {
478
476
  _runGraph(setup, run, callback) {
479
477
  /** @typedef {{ compiler: Compiler, setupResult: undefined | SetupResult, result: undefined | Stats, state: "pending" | "blocked" | "queued" | "starting" | "running" | "running-outdated" | "done", children: Node[], parents: Node[] }} Node */
480
478
 
481
- // State transitions for nodes:
482
- // -> blocked (initial)
483
- // blocked -> starting [running++] (when all parents done)
484
- // queued -> starting [running++] (when processing the queue)
485
- // starting -> running (when run has been called)
486
- // running -> done [running--] (when compilation is done)
487
- // done -> pending (when invalidated from file change)
488
- // pending -> blocked [add to queue] (when invalidated from aggregated changes)
489
- // done -> blocked [add to queue] (when invalidated, from parent invalidation)
490
- // running -> running-outdated (when invalidated, either from change or parent invalidation)
491
- // running-outdated -> blocked [running--] (when compilation is done)
479
+ // A node starts blocked and reaches `starting` once its parents are done or
480
+ // the queue reaches it, then `running`, then `done`. Invalidation sends it
481
+ // back to `blocked`, or to `running-outdated` if it is mid-compilation.
492
482
 
493
483
  /** @type {Node[]} */
494
484
  const nodes = this.compilers.map((compiler) => ({
@@ -19,6 +19,7 @@ const {
19
19
  SourceMapSource
20
20
  } = require("webpack-sources");
21
21
  const Dependency = require("./Dependency");
22
+ const { toError } = require("./ErrorHelpers");
22
23
  const Module = require("./Module");
23
24
  const ModuleGraphConnection = require("./ModuleGraphConnection");
24
25
  const { JAVASCRIPT_MODULE_TYPE_AUTO } = require("./ModuleTypeConstants");
@@ -68,10 +69,6 @@ const getUnhandledSchemeError = memoize(() =>
68
69
  require("./errors/UnhandledSchemeError")
69
70
  );
70
71
 
71
- const getNonErrorEmittedError = memoize(() =>
72
- require("./errors/NonErrorEmittedError")
73
- );
74
-
75
72
  const getModuleWarning = memoize(() => require("./errors/ModuleWarning"));
76
73
 
77
74
  const getModuleParseError = memoize(() => require("./errors/ModuleParseError"));
@@ -80,17 +77,21 @@ const getModuleError = memoize(() => require("./errors/ModuleError"));
80
77
 
81
78
  const getModuleBuildError = memoize(() => require("./errors/ModuleBuildError"));
82
79
 
83
- /** @import { ResolveContext, ResolveRequest } from "enhanced-resolve" */
80
+ /** @import { ResolveContext, ResolveRequest, Resolver } from "enhanced-resolve" */
84
81
  /** @import { Source, RawSourceMap } from "webpack-sources" */
85
82
  /**
86
83
  * @import {
87
84
  * ResolveOptions,
88
85
  * NoParse,
89
- * HashFunction
86
+ * HashFunction,
87
+ * HashDigest,
88
+ * HashDigestLength,
89
+ * HashSalt
90
90
  * } from "../declarations/WebpackOptions"
91
91
  */
92
92
  /**
93
93
  * @import Compilation, {
94
+ * AssetInfo,
94
95
  * FileSystemDependencies,
95
96
  * UnsafeCacheData
96
97
  * } from "./Compilation"
@@ -137,7 +138,14 @@ const getModuleBuildError = memoize(() => require("./errors/ModuleBuildError"));
137
138
  */
138
139
  /** @import Parser, { PreparsedAst } from "./Parser" */
139
140
  /** @import RequestShortener from "./RequestShortener" */
140
- /** @import { ResolverWithOptions } from "./ResolverFactory" */
141
+ /** @import Compiler from "./Compiler" */
142
+ /** @import { Logger } from "./logging/Logger" */
143
+ /**
144
+ * @import {
145
+ * ResolverWithOptions,
146
+ * ResolveOptionsWithDependencyType
147
+ * } from "./ResolverFactory"
148
+ */
141
149
  /**
142
150
  * @import {
143
151
  * ObjectDeserializerContext,
@@ -155,14 +163,65 @@ const getModuleBuildError = memoize(() => require("./errors/ModuleBuildError"));
155
163
  /** @typedef {{ [k: string]: EXPECTED_ANY }} ParserOptions */
156
164
  /** @typedef {{ [k: string]: EXPECTED_ANY }} GeneratorOptions */
157
165
 
166
+ /** @typedef {Parameters<Resolver["resolve"]>[4]} ResolveCallback */
167
+ /** @typedef {Parameters<typeof import("schema-utils").validate>[0]} Schema */
168
+
158
169
  /**
159
- * @template T
160
- * @typedef {import("../declarations/LoaderContext").LoaderContext<T>} LoaderContext
170
+ * `getOptions` validates against a schema when given one, and TypeScript reads
171
+ * an intersection of call signatures as an overload set
172
+ * @template OptionsType
173
+ * @typedef {{ (): OptionsType } & { (schema: Schema): OptionsType }} GetOptionsMethod
174
+ */
175
+
176
+ /**
177
+ * @typedef {((context: string, request: string, callback: ResolveCallback) => void) & ((context: string, request: string) => Promise<string>)} DualModeResolve
178
+ */
179
+
180
+ /**
181
+ * @typedef {object} LoaderContextUtils
182
+ * @property {(context: string, request: string) => string} absolutify returns a new request string using absolute paths when possible
183
+ * @property {(context: string, request: string) => string} contextify returns a new request string avoiding absolute paths when possible
184
+ * @property {(algorithm?: string | typeof Hash) => Hash} createHash creates a hash with the compilation's function
185
+ */
186
+
187
+ /**
188
+ * These properties are added by the NormalModule
189
+ * @template OptionsType
190
+ * @typedef {object} NormalModuleLoaderContext
191
+ * @property {number} version
192
+ * @property {GetOptionsMethod<OptionsType>} getOptions Extracts and parses the options of the current loader.
193
+ * Parses string options as JSON or a query string.
194
+ * @property {(warning: Error | string) => void} emitWarning Emits a warning for this module.
195
+ * The warning will be displayed to the user during compilation.
196
+ * @property {(error: Error | string) => void} emitError Emits an error for this module.
197
+ * The error will be displayed to the user and typically causes the compilation to fail.
198
+ * @property {(name?: string) => Logger} getLogger Gets a logger instance scoped to this loader and module.
199
+ * Useful for emitting debug or compilation information in a structured way.
200
+ * @property {(context: string, request: string, callback: ResolveCallback) => void} resolve Resolves a module request (e.g., a relative path or module name) to an absolute file path.
201
+ * It uses Webpack's internal resolver, taking into account configured aliases and extensions.
202
+ * @property {(options?: ResolveOptionsWithDependencyType) => DualModeResolve} getResolve Creates a resolve function with specific options.
203
+ * The returned function can be used as a Promise-based resolver or a callback-based resolver.
204
+ * @property {(name: string, content: string | Buffer, sourceMap?: string, assetInfo?: AssetInfo) => void} emitFile Emits a new file (asset) to the compilation output directory.
205
+ * This allows loaders to generate additional files alongside the main module output.
206
+ * @property {(dep: string) => void} addBuildDependency
207
+ * @property {LoaderContextUtils} utils
208
+ * @property {string} rootContext
209
+ * @property {InputFileSystem} fs
210
+ * @property {boolean=} sourceMap
211
+ * @property {"development" | "production" | "none"} mode
212
+ * @property {boolean=} webpack
213
+ * @property {HashFunction} hashFunction
214
+ * @property {HashDigest} hashDigest
215
+ * @property {HashDigestLength} hashDigestLength
216
+ * @property {HashSalt=} hashSalt
217
+ * @property {NormalModule=} _module
218
+ * @property {Compilation=} _compilation
219
+ * @property {Compiler=} _compiler
161
220
  */
162
221
 
163
222
  /**
164
223
  * @template T
165
- * @typedef {import("../declarations/LoaderContext").NormalModuleLoaderContext<T>} NormalModuleLoaderContext
224
+ * @typedef {NormalModuleLoaderContext<T> & import("./loaders/LoaderRunner").LoaderRunnerLoaderContext<T> & import("./dependencies/LoaderPlugin").LoaderPluginLoaderContext & import("./HotModuleReplacementPlugin").HotModuleReplacementPluginLoaderContext} LoaderContext
166
225
  */
167
226
 
168
227
  /** @typedef {(content: string) => boolean} NoParseFn */
@@ -348,10 +407,9 @@ const walkSideEffects = (rootMod, moduleGraph, SideEffectDep) => {
348
407
  }
349
408
  }
350
409
  } else {
351
- // Non-NormalModule (e.g. ConcatenatedModule delegating back
352
- // through here) resolves via a re-entrant walk that may see our
353
- // in-progress modules as circular, so taint this chain: never
354
- // memoize it.
410
+ // A non-NormalModule resolves through a re-entrant walk that may read
411
+ // our in-progress modules as circular, so this chain is tainted and
412
+ // never memoized.
355
413
  state = refModule.getSideEffectsConnectionState(moduleGraph);
356
414
  lowOf.set(mod, -1);
357
415
  }
@@ -952,7 +1010,7 @@ class NormalModule extends Module {
952
1010
  * @param {Compilation} compilation the compilation
953
1011
  * @param {InputFileSystem} fs file system from reading
954
1012
  * @param {NormalModuleCompilationHooks} hooks the hooks
955
- * @returns {import("../declarations/LoaderContext").LoaderContext<T>} loader context
1013
+ * @returns {LoaderContext<T>} loader context
956
1014
  */
957
1015
  _createLoaderContext(resolver, options, compilation, fs, hooks) {
958
1016
  const { requestShortener } = compilation.runtimeTemplate;
@@ -1085,22 +1143,16 @@ class NormalModule extends Module {
1085
1143
  },
1086
1144
  /** @type {LoaderContext<EXPECTED_ANY>["emitWarning"]} */
1087
1145
  emitWarning: (warning) => {
1088
- if (!(warning instanceof Error)) {
1089
- warning = new (getNonErrorEmittedError())(warning);
1090
- }
1091
1146
  this.addWarning(
1092
- new (getModuleWarning())(warning, {
1147
+ new (getModuleWarning())(toError(warning), {
1093
1148
  from: getCurrentLoaderName()
1094
1149
  })
1095
1150
  );
1096
1151
  },
1097
1152
  /** @type {LoaderContext<EXPECTED_ANY>["emitError"]} */
1098
1153
  emitError: (error) => {
1099
- if (!(error instanceof Error)) {
1100
- error = new (getNonErrorEmittedError())(error);
1101
- }
1102
1154
  this.addError(
1103
- new (getModuleError())(error, {
1155
+ new (getModuleError())(toError(error), {
1104
1156
  from: getCurrentLoaderName()
1105
1157
  })
1106
1158
  );
@@ -1124,7 +1176,7 @@ class NormalModule extends Module {
1124
1176
  /** @type {LoaderContext<EXPECTED_ANY>["getResolve"]} */
1125
1177
  getResolve(options) {
1126
1178
  const child = options ? resolver.withOptions(options) : resolver;
1127
- return /** @type {ReturnType<import("../declarations/LoaderContext").NormalModuleLoaderContext<T>["getResolve"]>} */ (
1179
+ return /** @type {ReturnType<NormalModuleLoaderContext<T>["getResolve"]>} */ (
1128
1180
  (context, request, callback) => {
1129
1181
  if (callback) {
1130
1182
  child.resolve(
@@ -1292,11 +1344,8 @@ class NormalModule extends Module {
1292
1344
  */
1293
1345
  const processResult = (err, result_) => {
1294
1346
  if (err) {
1295
- if (!(err instanceof Error)) {
1296
- err = new (getNonErrorEmittedError())(err);
1297
- }
1298
1347
  const currentLoader = this.getCurrentLoader(loaderContext);
1299
- const error = new (getModuleBuildError())(err, {
1348
+ const error = new (getModuleBuildError())(toError(err), {
1300
1349
  from:
1301
1350
  currentLoader &&
1302
1351
  compilation.runtimeTemplate.requestShortener.shorten(
@@ -1313,12 +1362,9 @@ class NormalModule extends Module {
1313
1362
  if (hookErr) {
1314
1363
  // Named, so a tap's failure is not read as a loader's.
1315
1364
  return callback(
1316
- new (getModuleBuildError())(
1317
- hookErr instanceof Error
1318
- ? hookErr
1319
- : new (getNonErrorEmittedError())(hookErr),
1320
- { from: "processResult hook" }
1321
- )
1365
+ new (getModuleBuildError())(toError(hookErr), {
1366
+ from: "processResult hook"
1367
+ })
1322
1368
  );
1323
1369
  }
1324
1370
 
@@ -1534,14 +1580,16 @@ class NormalModule extends Module {
1534
1580
  }
1535
1581
 
1536
1582
  /**
1537
- * @param {Error} error the error
1583
+ * Marks the module as failed, so what it generates says so. A tap or a
1584
+ * loader may fail with anything, and what reads the failure expects an error.
1585
+ * @param {EXPECTED_ANY} error what the module failed with
1538
1586
  * @returns {void}
1539
1587
  */
1540
1588
  markModuleAsErrored(error) {
1541
1589
  // Restore build meta from successful build to keep importing state
1542
1590
  this.buildMeta = { ...this._lastSuccessfulBuildMeta };
1543
- this.error = error;
1544
- this.addError(error);
1591
+ this.error = toError(error);
1592
+ this.addError(this.error);
1545
1593
  }
1546
1594
 
1547
1595
  /**
@@ -1708,7 +1756,7 @@ class NormalModule extends Module {
1708
1756
  try {
1709
1757
  hooks.beforeSnapshot.call(this);
1710
1758
  } catch (err) {
1711
- this.markModuleAsErrored(/** @type {Error} */ (err));
1759
+ this.markModuleAsErrored(err);
1712
1760
  return callback();
1713
1761
  }
1714
1762
 
@@ -1802,7 +1850,7 @@ class NormalModule extends Module {
1802
1850
  try {
1803
1851
  hooks.beforeParse.call(this);
1804
1852
  } catch (err) {
1805
- this.markModuleAsErrored(/** @type {Error} */ (err));
1853
+ this.markModuleAsErrored(err);
1806
1854
  this._initBuildHash(compilation);
1807
1855
  return callback();
1808
1856
  }
@@ -1950,7 +1998,13 @@ class NormalModule extends Module {
1950
1998
  getData,
1951
1999
  type
1952
2000
  })
1953
- : new RawSource(getGenerator().throwBuildErrorCode(this.error))
2001
+ : new RawSource(
2002
+ getGenerator().throwBuildErrorCode(
2003
+ this.error,
2004
+ undefined,
2005
+ runtimeTemplate.requestShortener
2006
+ )
2007
+ )
1954
2008
  : generator.generate(this, {
1955
2009
  dependencyTemplates,
1956
2010
  runtimeTemplate,
@@ -2116,10 +2170,8 @@ class NormalModule extends Module {
2116
2170
  /** @type {string} */
2117
2171
  (buildInfo.hash)
2118
2172
  );
2119
- // Clear cached source types and re-compute so that changes in incoming
2120
- // connections (e.g. asset module newly referenced from JS via lazy
2121
- // compilation) are reflected in the hash and trigger code generation
2122
- // cache invalidation.
2173
+ // Recompute the source types, so a change in the incoming connections reaches
2174
+ // the hash and invalidates the code-generation cache.
2123
2175
  // https://github.com/webpack/webpack/issues/20800
2124
2176
  this._sourceTypes = undefined;
2125
2177
  for (const type of this.getSourceTypes()) {