webpack 5.108.3 → 5.109.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/lib/APIPlugin.js +48 -29
  2. package/lib/CacheFacade.js +8 -0
  3. package/lib/ChunkGroup.js +1 -0
  4. package/lib/CompatibilityPlugin.js +31 -29
  5. package/lib/Compilation.js +50 -8
  6. package/lib/ConstPlugin.js +11 -11
  7. package/lib/ContextModule.js +239 -6
  8. package/lib/ContextModuleFactory.js +139 -14
  9. package/lib/DefinePlugin.js +396 -101
  10. package/lib/Entrypoint.js +1 -1
  11. package/lib/ExportsInfoApiPlugin.js +2 -2
  12. package/lib/ExternalModule.js +107 -5
  13. package/lib/ExternalModuleFactoryPlugin.js +20 -1
  14. package/lib/FileSystemInfo.js +130 -74
  15. package/lib/FlagDependencyExportsPlugin.js +55 -8
  16. package/lib/HotModuleReplacementPlugin.js +18 -15
  17. package/lib/LazyBarrel.js +30 -3
  18. package/lib/Module.js +3 -0
  19. package/lib/ModuleFilenameHelpers.js +2 -2
  20. package/lib/ModuleTypeConstants.js +8 -1
  21. package/lib/MultiCompiler.js +13 -2
  22. package/lib/MultiWatching.js +1 -0
  23. package/lib/NodeStuffPlugin.js +51 -33
  24. package/lib/NormalModule.js +169 -405
  25. package/lib/NormalModuleFactory.js +76 -2
  26. package/lib/ProgressPlugin.js +211 -119
  27. package/lib/ProvidePlugin.js +2 -2
  28. package/lib/RuntimeGlobals.js +47 -0
  29. package/lib/RuntimePlugin.js +33 -0
  30. package/lib/RuntimeTemplate.js +304 -16
  31. package/lib/UseStrictPlugin.js +1 -1
  32. package/lib/WebpackIsIncludedPlugin.js +1 -1
  33. package/lib/WebpackOptionsApply.js +24 -19
  34. package/lib/asset/AssetGenerator.js +110 -28
  35. package/lib/asset/AssetModulesPlugin.js +92 -2
  36. package/lib/asset/WebManifestGenerator.js +164 -0
  37. package/lib/asset/WebManifestParser.js +130 -0
  38. package/lib/async-modules/AwaitDependenciesInitFragment.js +14 -4
  39. package/lib/async-modules/isGeneratorLowered.js +26 -0
  40. package/lib/cache/PackFileCacheStrategy.js +9 -3
  41. package/lib/config/browserslistTargetHandler.js +40 -0
  42. package/lib/config/defaults.js +222 -32
  43. package/lib/config/normalization.js +26 -0
  44. package/lib/config/target.js +9 -1
  45. package/lib/css/CssGenerator.js +73 -73
  46. package/lib/css/CssLoadingRuntimeModule.js +5 -1
  47. package/lib/css/CssModulesPlugin.js +92 -53
  48. package/lib/css/CssParser.js +843 -302
  49. package/lib/css/syntax.js +1219 -483
  50. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -6
  51. package/lib/dependencies/AMDPlugin.js +2 -2
  52. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +13 -13
  53. package/lib/dependencies/CommonJsDependencyHelpers.js +39 -0
  54. package/lib/dependencies/CommonJsExportsDependency.js +47 -2
  55. package/lib/dependencies/CommonJsExportsParserPlugin.js +10 -10
  56. package/lib/dependencies/CommonJsImportsParserPlugin.js +18 -18
  57. package/lib/dependencies/CommonJsPlugin.js +2 -2
  58. package/lib/dependencies/CommonJsRequireDependency.js +26 -1
  59. package/lib/dependencies/CommonJsSelfReferenceDependency.js +32 -1
  60. package/lib/dependencies/ContextDependencyHelpers.js +3 -3
  61. package/lib/dependencies/CreateRequireParserPlugin.js +6 -6
  62. package/lib/dependencies/CssIcssExportDependency.js +190 -87
  63. package/lib/dependencies/CssUrlDependency.js +35 -4
  64. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +2 -2
  65. package/lib/dependencies/HarmonyCompatibilityDependency.js +32 -14
  66. package/lib/dependencies/HarmonyDetectionParserPlugin.js +43 -13
  67. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +7 -19
  68. package/lib/dependencies/HarmonyImportDependency.js +12 -1
  69. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +34 -107
  70. package/lib/dependencies/HarmonyImportGuard.js +192 -20
  71. package/lib/dependencies/HarmonyModulesPlugin.js +6 -0
  72. package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +1 -1
  73. package/lib/dependencies/HtmlEntryDependency.js +797 -172
  74. package/lib/dependencies/HtmlSourceDependency.js +26 -0
  75. package/lib/dependencies/ImportDependency.js +43 -1
  76. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +31 -18
  77. package/lib/dependencies/ImportMetaContextPlugin.js +38 -7
  78. package/lib/dependencies/ImportMetaGlobDependency.js +81 -0
  79. package/lib/dependencies/ImportMetaGlobDependencyParserPlugin.js +78 -0
  80. package/lib/dependencies/ImportMetaGlobHelpers.js +660 -0
  81. package/lib/dependencies/ImportMetaPlugin.js +532 -180
  82. package/lib/dependencies/ImportMetaResolveDependency.js +90 -0
  83. package/lib/dependencies/ImportParserPlugin.js +87 -26
  84. package/lib/dependencies/ImportPhase.js +10 -8
  85. package/lib/dependencies/LoaderPlugin.js +5 -1
  86. package/lib/dependencies/RequireContextDependencyParserPlugin.js +1 -1
  87. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +3 -6
  88. package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +4 -11
  89. package/lib/dependencies/SystemPlugin.js +2 -4
  90. package/lib/dependencies/TopLevelAwaitDependency.js +93 -0
  91. package/lib/dependencies/URLDependency.js +141 -21
  92. package/lib/dependencies/{WorkerPlugin.js → WorkerAndWorkletPlugin.js} +324 -112
  93. package/lib/dependencies/WorkerDependency.js +86 -18
  94. package/lib/dependencies/WorkletDependency.js +278 -0
  95. package/lib/dll/DelegatedModuleFactoryPlugin.js +19 -0
  96. package/lib/errors/EnvironmentNotSupportAsyncWarning.js +1 -1
  97. package/lib/errors/LoaderLoadingError.js +20 -0
  98. package/lib/errors/ModuleParseError.js +39 -22
  99. package/lib/errors/NodeStuffInWebError.js +1 -1
  100. package/lib/esm/ModuleChunkFormatPlugin.js +47 -14
  101. package/lib/esm/ModuleChunkLoadingPlugin.js +8 -1
  102. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +29 -1
  103. package/lib/hmr/lazyCompilationBackend.js +32 -8
  104. package/lib/html/HtmlGenerator.js +940 -91
  105. package/lib/html/HtmlModule.js +3 -2
  106. package/lib/html/HtmlModulesPlugin.js +625 -170
  107. package/lib/html/HtmlParser.js +812 -340
  108. package/lib/html/favicon.svg +1 -0
  109. package/lib/html/syntax.js +2116 -834
  110. package/lib/ids/IdHelpers.js +1 -1
  111. package/lib/index.js +6 -0
  112. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +4 -5
  113. package/lib/javascript/BasicEvaluatedExpression.js +366 -48
  114. package/lib/javascript/JavascriptGenerator.js +197 -49
  115. package/lib/javascript/JavascriptModulesPlugin.js +178 -24
  116. package/lib/javascript/JavascriptParser.js +711 -355
  117. package/lib/javascript/JavascriptParserHelpers.js +3 -6
  118. package/lib/javascript/syntax.js +4380 -0
  119. package/lib/library/ModuleLibraryPlugin.js +38 -1
  120. package/lib/loaders/LoaderRunner.js +714 -0
  121. package/lib/loaders/loadLoader.js +100 -0
  122. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +19 -0
  123. package/lib/node/ReadFileCompileWasmPlugin.js +14 -0
  124. package/lib/optimize/ConcatenatedModule.js +120 -16
  125. package/lib/optimize/FlagIncludedChunksPlugin.js +13 -3
  126. package/lib/optimize/InnerGraphPlugin.js +50 -30
  127. package/lib/optimize/ModuleConcatenationPlugin.js +69 -3
  128. package/lib/optimize/SideEffectsFlagPlugin.js +86 -43
  129. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +15 -0
  130. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +24 -13
  131. package/lib/prefetch/ResourceHintPlugin.js +663 -0
  132. package/lib/prefetch/ResourceHintRuntimeModule.js +149 -0
  133. package/lib/prefetch/StartupAssetHintRuntimeModule.js +210 -0
  134. package/lib/prefetch/parseResourceHintOptions.js +103 -0
  135. package/lib/rules/RuleSetCompiler.js +114 -0
  136. package/lib/runtime/AsyncModuleGeneratorRuntimeModule.js +56 -0
  137. package/lib/runtime/AsyncModuleRuntimeModule.js +24 -8
  138. package/lib/runtime/AutoPublicPathRuntimeModule.js +7 -1
  139. package/lib/runtime/CommonJsWrapRuntimeModule.js +37 -0
  140. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +59 -0
  141. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +204 -8
  142. package/lib/runtime/SetAnonymousDefaultNameRuntimeModule.js +4 -1
  143. package/lib/schemes/HttpUriPlugin.js +40 -1
  144. package/lib/schemes/VirtualUrlPlugin.js +1 -2
  145. package/lib/serialization/FileMiddleware.js +29 -3
  146. package/lib/stats/DefaultStatsFactoryPlugin.js +32 -3
  147. package/lib/stats/DefaultStatsPresetPlugin.js +2 -0
  148. package/lib/stats/DefaultStatsPrinterPlugin.js +12 -2
  149. package/lib/stats/StatsFactory.js +15 -8
  150. package/lib/url/URLParserPlugin.js +98 -19
  151. package/lib/util/AsyncQueue.js +122 -72
  152. package/lib/util/LocConverter.js +9 -8
  153. package/lib/util/SetHelpers.js +1 -1
  154. package/lib/util/SourceProcessor.js +41 -28
  155. package/lib/util/StackedMap.js +122 -48
  156. package/lib/util/binarySearchBounds.js +2 -2
  157. package/lib/util/concatenate.js +40 -14
  158. package/lib/util/createHooksRegistry.js +13 -5
  159. package/lib/util/dataURL.js +2 -2
  160. package/lib/util/deterministicGrouping.js +7 -5
  161. package/lib/util/formatSize.js +6 -2
  162. package/lib/util/globUtils.js +710 -0
  163. package/lib/util/identifier.js +23 -6
  164. package/lib/util/implicitTypeLoaderFallback.js +62 -0
  165. package/lib/util/internalSerializables.js +88 -71
  166. package/lib/util/magicComment.js +121 -25
  167. package/lib/util/numberHash.js +2 -2
  168. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +24 -18
  169. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +33 -22
  170. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +79 -16
  171. package/lib/web/FetchCompileAsyncWasmPlugin.js +19 -0
  172. package/lib/web/FetchCompileWasmPlugin.js +14 -0
  173. package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -0
  174. package/lib/webpack.js +65 -0
  175. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +3 -0
  176. package/module.d.ts +21 -0
  177. package/package.json +14 -13
  178. package/schemas/WebpackOptions.check.js +1 -1
  179. package/schemas/WebpackOptions.json +759 -36
  180. package/schemas/plugins/HtmlParserOptions.check.js +1 -1
  181. package/schemas/plugins/ProgressPlugin.check.js +1 -1
  182. package/schemas/plugins/ProgressPlugin.json +17 -1
  183. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  184. package/schemas/plugins/container/ContainerReferencePlugin.json +1 -0
  185. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  186. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  187. package/schemas/plugins/container/ModuleFederationPlugin.json +1 -0
  188. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +1 -1
  189. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  190. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  191. package/types.d.ts +1300 -325
@@ -15,16 +15,19 @@ const memoize = require("../util/memoize");
15
15
  /** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
16
16
  /** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
17
17
  /** @typedef {import("./CommonJsRequireDependency")} CommonJsRequireDependency */
18
+ /** @typedef {import("./HarmonyEvaluatedImportSpecifierDependency")} HarmonyEvaluatedImportSpecifierDependency */
18
19
  /** @typedef {import("./HarmonyImportSpecifierDependency")} HarmonyImportSpecifierDependency */
19
20
  /** @typedef {import("./ImportDependency")} ImportDependency */
20
21
 
21
22
  // Tuple-encoded boolean formula over guard dependencies. Split into per-shape
22
23
  // aliases so the recursive references resolve through array/object types.
24
+ // `v` = dependency-liveness atom, `p` = `"x" in ns` presence atom.
23
25
  /** @typedef {["v", Dependency]} GuardAtom */
26
+ /** @typedef {["p", HarmonyEvaluatedImportSpecifierDependency]} GuardPresenceAtom */
24
27
  /** @typedef {["?"]} GuardUnknown */
25
28
  /** @typedef {["!", GuardFormula]} GuardNot */
26
29
  /** @typedef {["&&" | "||" | "??", GuardFormula, GuardFormula]} GuardLogical */
27
- /** @typedef {GuardAtom | GuardUnknown | GuardNot | GuardLogical} GuardFormula */
30
+ /** @typedef {GuardAtom | GuardPresenceAtom | GuardUnknown | GuardNot | GuardLogical} GuardFormula */
28
31
  /** @typedef {{ formula: GuardFormula, value: boolean }} DependencyGuard branch guard: the dependency is live only when the formula evaluates to `value` */
29
32
  /** @typedef {HarmonyImportSpecifierDependency | CommonJsRequireDependency | ImportDependency} GuardableDependency */
30
33
 
@@ -33,16 +36,19 @@ const memoize = require("../util/memoize");
33
36
  * conditional branch body. Carries the `"x" in ns` presence guards and/or the
34
37
  * dead-branch dependency guard for that branch.
35
38
  * @typedef {object} GuardFrame
36
- * @property {Map<string, Set<string>>=} presence `"x" in ns` presence guards active in this branch
37
39
  * @property {Expression=} test the conditional test (for the lazily built formula)
38
40
  * @property {number=} depStart dependency count before the test was walked
39
41
  * @property {boolean=} condition branch truthiness the dependency guard is live for
40
- * @property {GuardFormula | null=} formula memoized formula (null = no knowable atom)
42
+ * @property {GuardFormula | null=} formula memoized dependency-guard formula (null = no knowable atom)
43
+ * @property {GuardFormula | null=} presenceFormula memoized presence formula (null = no presence atom)
41
44
  */
42
45
 
43
46
  const getHarmonyImportSpecifierDependency = memoize(() =>
44
47
  require("./HarmonyImportSpecifierDependency")
45
48
  );
49
+ const getHarmonyEvaluatedImportSpecifierDependency = memoize(() =>
50
+ require("./HarmonyEvaluatedImportSpecifierDependency")
51
+ );
46
52
 
47
53
  // Tri-state truthiness: UNKNOWN means not statically known.
48
54
  const UNKNOWN = 0;
@@ -62,12 +68,12 @@ const flip = (t) => (t === TRUE ? FALSE : t === FALSE ? TRUE : UNKNOWN);
62
68
  const fromBool = (b) => (b ? TRUE : FALSE);
63
69
 
64
70
  /**
65
- * Build a guard formula from a conditional test AST.
71
+ * Build a liveness formula from a conditional test AST.
66
72
  * @param {Expression} test conditional test expression
67
73
  * @param {Map<number, HarmonyImportSpecifierDependency>} depByRangeStart import-specifier deps in the test, keyed by range start
68
74
  * @returns {GuardFormula | null} formula, or null when it has no knowable atom
69
75
  */
70
- const buildGuardFormula = (test, depByRangeStart) => {
76
+ const buildLivenessFormula = (test, depByRangeStart) => {
71
77
  /**
72
78
  * @param {Expression} node ast node
73
79
  * @returns {GuardFormula} formula node
@@ -104,6 +110,7 @@ const buildGuardFormula = (test, depByRangeStart) => {
104
110
  const hasAtom = (formula) => {
105
111
  switch (formula[0]) {
106
112
  case "v":
113
+ case "p":
107
114
  return true;
108
115
  case "!":
109
116
  return hasAtom(formula[1]);
@@ -122,7 +129,7 @@ const hasAtom = (formula) => {
122
129
  * @param {RuntimeSpec} runtime runtime
123
130
  * @returns {{ t: number, n: number }} truthy `t` and null `n` tri-states
124
131
  */
125
- const evalNode = (formula, moduleGraph, runtime) => {
132
+ const evalLivenessFormula = (formula, moduleGraph, runtime) => {
126
133
  switch (formula[0]) {
127
134
  case "v": {
128
135
  const dep = /** @type {HarmonyImportSpecifierDependency} */ (formula[1]);
@@ -145,12 +152,12 @@ const evalNode = (formula, moduleGraph, runtime) => {
145
152
  case "!":
146
153
  // `!x` always yields a boolean → never nullish.
147
154
  return {
148
- t: flip(evalNode(formula[1], moduleGraph, runtime).t),
155
+ t: flip(evalLivenessFormula(formula[1], moduleGraph, runtime).t),
149
156
  n: FALSE
150
157
  };
151
158
  case "&&": {
152
- const l = evalNode(formula[1], moduleGraph, runtime);
153
- const r = evalNode(formula[2], moduleGraph, runtime);
159
+ const l = evalLivenessFormula(formula[1], moduleGraph, runtime);
160
+ const r = evalLivenessFormula(formula[2], moduleGraph, runtime);
154
161
  const t =
155
162
  l.t === FALSE || r.t === FALSE
156
163
  ? FALSE
@@ -160,8 +167,8 @@ const evalNode = (formula, moduleGraph, runtime) => {
160
167
  return { t, n: UNKNOWN };
161
168
  }
162
169
  case "||": {
163
- const l = evalNode(formula[1], moduleGraph, runtime);
164
- const r = evalNode(formula[2], moduleGraph, runtime);
170
+ const l = evalLivenessFormula(formula[1], moduleGraph, runtime);
171
+ const r = evalLivenessFormula(formula[2], moduleGraph, runtime);
165
172
  const t =
166
173
  l.t === TRUE || r.t === TRUE
167
174
  ? TRUE
@@ -171,8 +178,8 @@ const evalNode = (formula, moduleGraph, runtime) => {
171
178
  return { t, n: UNKNOWN };
172
179
  }
173
180
  case "??": {
174
- const l = evalNode(formula[1], moduleGraph, runtime);
175
- const r = evalNode(formula[2], moduleGraph, runtime);
181
+ const l = evalLivenessFormula(formula[1], moduleGraph, runtime);
182
+ const r = evalLivenessFormula(formula[2], moduleGraph, runtime);
176
183
  // `l ?? r` is l when l non-nullish, else r.
177
184
  const t =
178
185
  l.n === FALSE ? l.t : l.n === TRUE ? r.t : l.t === r.t ? l.t : UNKNOWN;
@@ -192,37 +199,201 @@ const evalNode = (formula, moduleGraph, runtime) => {
192
199
  */
193
200
  const isDeadByGuards = (guards, moduleGraph, runtime) => {
194
201
  for (const guard of guards) {
195
- const t = evalNode(guard.formula, moduleGraph, runtime).t;
202
+ const t = evalLivenessFormula(guard.formula, moduleGraph, runtime).t;
196
203
  if (t !== UNKNOWN && t !== (guard.value ? TRUE : FALSE)) return true;
197
204
  }
198
205
  return false;
199
206
  };
200
207
 
201
208
  /**
202
- * Builds (once) the dependency-guard formula for a frame from the import
203
- * specifier deps created while walking the test.
209
+ * Builds (once) the liveness formula for a frame from the import specifier deps
210
+ * created while walking the test.
204
211
  * @param {JavascriptParser} parser the parser
205
212
  * @param {GuardFrame} frame guard frame
206
213
  * @returns {GuardFormula | null} formula, or null when it has no knowable atom
207
214
  */
208
- const buildFrameFormula = (parser, frame) => {
215
+ const buildFrameLivenessFormula = (parser, frame) => {
209
216
  const HarmonyImportSpecifierDependency =
210
217
  getHarmonyImportSpecifierDependency();
218
+ const HarmonyEvaluatedImportSpecifierDependency =
219
+ getHarmonyEvaluatedImportSpecifierDependency();
211
220
  const deps = /** @type {Module} */ (parser.state.module).dependencies;
212
221
  /** @type {Map<number, HarmonyImportSpecifierDependency>} */
213
222
  const depByRangeStart = new Map();
214
223
  for (let i = /** @type {number} */ (frame.depStart); i < deps.length; i++) {
215
224
  const dep = deps[i];
216
- if (dep instanceof HarmonyImportSpecifierDependency && dep.range) {
225
+ // Exclude `"x" in ns` evaluated deps; those feed the presence formula only.
226
+ if (
227
+ dep instanceof HarmonyImportSpecifierDependency &&
228
+ !(dep instanceof HarmonyEvaluatedImportSpecifierDependency) &&
229
+ dep.range
230
+ ) {
231
+ depByRangeStart.set(dep.range[0], dep);
232
+ }
233
+ }
234
+ return buildLivenessFormula(
235
+ /** @type {Expression} */ (frame.test),
236
+ depByRangeStart
237
+ );
238
+ };
239
+
240
+ /**
241
+ * Build a presence formula from a conditional test AST. Statically-decided
242
+ * `||`/`??` operands are folded away at build time, so the result contains only
243
+ * `"x" in ns` presence atoms (plus `&&`/`!`).
244
+ * @param {JavascriptParser} parser the parser
245
+ * @param {Expression} test conditional test expression
246
+ * @param {Map<number, HarmonyEvaluatedImportSpecifierDependency>} depByRangeStart in-operator deps in the test, keyed by range start
247
+ * @returns {GuardFormula | null} formula, or null when it has no presence atom
248
+ */
249
+ const buildPresenceFormula = (parser, test, depByRangeStart) => {
250
+ /**
251
+ * @param {Expression} node ast node
252
+ * @returns {GuardFormula} formula node
253
+ */
254
+ const build = (node) => {
255
+ if (node.type === "UnaryExpression" && node.operator === "!") {
256
+ return ["!", build(/** @type {Expression} */ (node.argument))];
257
+ }
258
+ if (node.type === "LogicalExpression") {
259
+ if (node.operator === "&&") {
260
+ return [
261
+ "&&",
262
+ build(/** @type {Expression} */ (node.left)),
263
+ build(/** @type {Expression} */ (node.right))
264
+ ];
265
+ }
266
+
267
+ if (node.operator === "||") {
268
+ if (parser.evaluateExpression(node.left).asBool() === false) {
269
+ return build(/** @type {Expression} */ (node.right));
270
+ }
271
+ if (parser.evaluateExpression(node.right).asBool() === false) {
272
+ return build(/** @type {Expression} */ (node.left));
273
+ }
274
+ return ["?"];
275
+ }
276
+
277
+ if (node.operator === "??") {
278
+ const nullish = parser.evaluateExpression(node.left).asNullish();
279
+ if (nullish === true) {
280
+ return build(/** @type {Expression} */ (node.right));
281
+ }
282
+ if (nullish === false) {
283
+ return build(/** @type {Expression} */ (node.left));
284
+ }
285
+ return ["?"];
286
+ }
287
+ }
288
+ const dep =
289
+ node.range && depByRangeStart.get(/** @type {number} */ (node.range[0]));
290
+ return dep ? ["p", dep] : ["?"];
291
+ };
292
+
293
+ const formula = build(test);
294
+ return hasAtom(formula) ? formula : null;
295
+ };
296
+
297
+ /**
298
+ * Whether a presence formula guarantees `ns.member` is present. "Must be truthy"
299
+ * semantics: the member is guaranteed when some `"member" in ns` atom must hold
300
+ * for the branch condition. Statically-dead branches never reach here — the
301
+ * parser eliminates them before the branch body is walked.
302
+ * @param {GuardFormula} formula presence formula
303
+ * @param {string} name namespace binding name
304
+ * @param {string} member member key
305
+ * @param {boolean} needTruthy whether the formula must be truthy
306
+ * @returns {boolean} true when the member is guaranteed present
307
+ */
308
+ const evalPresenceFormula = (formula, name, member, needTruthy) => {
309
+ switch (formula[0]) {
310
+ case "p": {
311
+ const dep = /** @type {HarmonyEvaluatedImportSpecifierDependency} */ (
312
+ formula[1]
313
+ );
314
+ return (
315
+ needTruthy &&
316
+ dep.directImport === true &&
317
+ dep.name === name &&
318
+ dep.ids.length === 1 &&
319
+ dep.ids[0] === member
320
+ );
321
+ }
322
+ case "!":
323
+ return evalPresenceFormula(formula[1], name, member, !needTruthy);
324
+ case "&&":
325
+ return (
326
+ needTruthy &&
327
+ (evalPresenceFormula(formula[1], name, member, true) ||
328
+ evalPresenceFormula(formula[2], name, member, true))
329
+ );
330
+ default:
331
+ return false;
332
+ }
333
+ };
334
+
335
+ /**
336
+ * Builds (once) the presence formula for a frame from the in-operator deps
337
+ * created while walking the test.
338
+ * @param {JavascriptParser} parser the parser
339
+ * @param {GuardFrame} frame guard frame
340
+ * @returns {GuardFormula | null} formula, or null when it has no presence atom
341
+ */
342
+ const buildFramePresenceFormula = (parser, frame) => {
343
+ const HarmonyEvaluatedImportSpecifierDependency =
344
+ getHarmonyEvaluatedImportSpecifierDependency();
345
+ const deps = /** @type {Module} */ (parser.state.module).dependencies;
346
+ /** @type {Map<number, HarmonyEvaluatedImportSpecifierDependency>} */
347
+ const depByRangeStart = new Map();
348
+ for (let i = /** @type {number} */ (frame.depStart); i < deps.length; i++) {
349
+ const dep = deps[i];
350
+ if (dep instanceof HarmonyEvaluatedImportSpecifierDependency && dep.range) {
217
351
  depByRangeStart.set(dep.range[0], dep);
218
352
  }
219
353
  }
220
- return buildGuardFormula(
354
+ return buildPresenceFormula(
355
+ parser,
221
356
  /** @type {Expression} */ (frame.test),
222
357
  depByRangeStart
223
358
  );
224
359
  };
225
360
 
361
+ /**
362
+ * Whether an active presence guard proves `ns.member` present, suppressing
363
+ * export-presence errors. Each frame is evaluated against its branch condition,
364
+ * so the `else` of `if (!("x" in ns))` also guards `ns.x`.
365
+ * @param {JavascriptParser} parser the parser
366
+ * @param {GuardFrame[]} stack the guard stack
367
+ * @param {string} name namespace binding name
368
+ * @param {string} member member key
369
+ * @returns {boolean} true when a guard proves the member present
370
+ */
371
+ const isPresentByGuards = (parser, stack, name, member) => {
372
+ for (let i = stack.length - 1; i >= 0; i--) {
373
+ const frame = stack[i];
374
+ if (frame.depStart === undefined) continue;
375
+ let formula = frame.presenceFormula;
376
+ if (formula === undefined) {
377
+ formula = frame.presenceFormula = buildFramePresenceFormula(
378
+ parser,
379
+ frame
380
+ );
381
+ }
382
+ if (
383
+ formula !== null &&
384
+ evalPresenceFormula(
385
+ formula,
386
+ name,
387
+ member,
388
+ /** @type {boolean} */ (frame.condition)
389
+ )
390
+ ) {
391
+ return true;
392
+ }
393
+ }
394
+ return false;
395
+ };
396
+
226
397
  /**
227
398
  * Tags a freshly created dependency with the active dependency guards.
228
399
  * @param {JavascriptParser} parser the parser
@@ -239,7 +410,7 @@ const attachDependencyGuards = (parser, dep) => {
239
410
  if (frame.depStart === undefined) continue;
240
411
  let formula = frame.formula;
241
412
  if (formula === undefined) {
242
- formula = frame.formula = buildFrameFormula(parser, frame);
413
+ formula = frame.formula = buildFrameLivenessFormula(parser, frame);
243
414
  }
244
415
  if (formula === null) continue;
245
416
  (guards || (guards = [])).push({
@@ -252,3 +423,4 @@ const attachDependencyGuards = (parser, dep) => {
252
423
 
253
424
  module.exports.attachDependencyGuards = attachDependencyGuards;
254
425
  module.exports.isDeadByGuards = isDeadByGuards;
426
+ module.exports.isPresentByGuards = isPresentByGuards;
@@ -25,6 +25,7 @@ const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDepe
25
25
  const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency");
26
26
 
27
27
  const HarmonyTopLevelThisParserPlugin = require("./HarmonyTopLevelThisParserPlugin");
28
+ const TopLevelAwaitDependency = require("./TopLevelAwaitDependency");
28
29
 
29
30
  /** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
30
31
  /** @typedef {import("../Compiler")} Compiler */
@@ -62,6 +63,11 @@ class HarmonyModulesPlugin {
62
63
  new HarmonyCompatibilityDependency.Template()
63
64
  );
64
65
 
66
+ compilation.dependencyTemplates.set(
67
+ TopLevelAwaitDependency,
68
+ new TopLevelAwaitDependency.Template()
69
+ );
70
+
65
71
  compilation.dependencyFactories.set(
66
72
  HarmonyImportSideEffectDependency,
67
73
  normalModuleFactory
@@ -29,7 +29,7 @@ class HarmonyTopLevelThisParserPlugin {
29
29
  /** @type {Range} */ (node.range),
30
30
  null
31
31
  );
32
- dep.loc = /** @type {DependencyLocation} */ (node.loc);
32
+ dep.loc = parser.getLocation(node);
33
33
  parser.state.module.addPresentationalDependency(dep);
34
34
  return true;
35
35
  }