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
@@ -27,6 +27,9 @@ const {
27
27
  /** @type {typeof import("./grammar").Grammar} */
28
28
  const BaseParser = /** @type {EXPECTED_ANY} */ (Parser);
29
29
 
30
+ /** @typedef {EXPECTED_ANY[]} HoistedDeclarations the declarations one scope hoists, in source order */
31
+ /** @typedef {EXPECTED_ANY[]} ModuleDeclarations the program's import and re-export declarations in source order, each followed by the statement written before it */
32
+ /** @typedef {number | number[]} BlockDeclarations which statements of one list declare into its block scope: a mask of their indices, or the indices themselves once one passes `MAX_MASKED_INDEX` */
30
33
  /** @typedef {{ token: string, isExpr: boolean, preserveSpace?: boolean, generator?: boolean, override?: unknown }} TokContextShim the TokContext fields the owned tokenizer reads */
31
34
 
32
35
  // the token contexts used by the inlined finishToken context updates
@@ -93,10 +96,9 @@ const stringToBigInt = (str) => BigInt(str.replace(/_/g, ""));
93
96
  /** @typedef {CollectedComment[] | ((isBlock: boolean, text: string, start: number, end: number) => void)} CommentSink where comments are collected, as an array or a callback */
94
97
  /** @typedef {Omit<Options, "onComment"> & { onComment?: CommentSink, lazyNodes?: boolean, lazyComments?: CollectedComment[], importPhases?: boolean, moduleFallback?: boolean }} ParserOptions the parser's options, carrying webpack's own comment type plus its lazy-node and import-phase switches */
95
98
 
96
- // Symbol-keyed so they stay out of for-in, Object.keys and JSON.stringify
97
- // over AST nodes.
98
- // Per-TokContext "the owned token loop must step aside" flag, cached on the
99
- // context itself so the hot guard reads one slot instead of two.
99
+ // Symbol-keyed so they stay out of for-in, Object.keys and JSON.stringify over
100
+ // AST nodes. `kSlowContext` is the per-TokContext "step aside" flag, cached on
101
+ // the context so the hot guard reads one slot rather than two.
100
102
  const kSlowContext = Symbol("slow context");
101
103
  const kSource = Symbol("source");
102
104
  const kRange = Symbol("range");
@@ -146,11 +148,9 @@ IDENT_START[95] = 1;
146
148
  for (let i = 65; i <= 90; i++) IDENT_START[i] = 1;
147
149
  for (let i = 97; i <= 122; i++) IDENT_START[i] = 1;
148
150
 
149
- // Single-char punctuators that acorn's `getTokenFromCode` reads as just
150
- // `++pos; finishToken(type)` (no value, no operator state machine). Dispatching
151
- // them from `nextToken`'s char table skips the extra `getTokenFromCode` call and
152
- // its switch for the commonest tokens in JS ( ) { } [ ] ; , : — `0` is "not a
153
- // simple punctuator" since token types are truthy objects.
151
+ // Single-char punctuators acorn reads as just `++pos; finishToken(type)`, with
152
+ // no value and no operator state machine. Dispatching them from `nextToken`'s
153
+ // char table skips a call and a switch for the commonest tokens in JS.
154
154
  const SIMPLE_PUNCT = Array.from({ length: 128 });
155
155
  SIMPLE_PUNCT[40] = tokTypes.parenL;
156
156
  SIMPLE_PUNCT[41] = tokTypes.parenR;
@@ -162,10 +162,9 @@ SIMPLE_PUNCT[123] = tokTypes.braceL;
162
162
  SIMPLE_PUNCT[125] = tokTypes.braceR;
163
163
  SIMPLE_PUNCT[58] = tokTypes.colon;
164
164
 
165
- // Characters that can only start a token which cannot continue an expression,
166
- // so an atom directly followed by one is the whole expression (see
167
- // `parseMaybeAssign`'s fast path). `}` included: it only ever closes a block,
168
- // an object or a template substitution.
165
+ // Characters starting only a token that cannot continue an expression, so an
166
+ // atom directly followed by one is the whole expression. `}` is included: it
167
+ // only ever closes a block, an object or a template substitution.
169
168
  const EXPRESSION_END_CHAR = new Uint8Array(128);
170
169
  EXPRESSION_END_CHAR[41] = 1; // )
171
170
  EXPRESSION_END_CHAR[44] = 1; // ,
@@ -186,10 +185,9 @@ const CLS_UNICODE = 5;
186
185
  const CLS_SPACE = 6;
187
186
  const CLS_NEWLINE = 7;
188
187
  const CLS_SLASH = 8;
189
- // Full `charCodeAt` range so the scan loop needs no `code > 127` branch per
190
- // character: every non-ASCII code unit classifies as CLS_UNICODE (which sorts
191
- // below CLS_SPACE, so the loop exits on the same single compare) and the
192
- // dispatch delegates it to acorn's unicode-aware paths.
188
+ // Covers the whole `charCodeAt` range, so the scan loop needs no `code > 127`
189
+ // branch: non-ASCII classifies as CLS_UNICODE, which sorts below CLS_SPACE and
190
+ // so exits on the same compare, then delegates to acorn's unicode paths.
193
191
  const CHAR_CLASS = new Uint8Array(0x10000).fill(CLS_UNICODE, 128);
194
192
  for (let i = 0; i < 128; i++) {
195
193
  if (IDENT_START[i] === 1 || i === 92) CHAR_CLASS[i] = CLS_IDENT;
@@ -410,6 +408,78 @@ class UnaryNode {
410
408
  }
411
409
  }
412
410
 
411
+ // WHY: a sparse symbol slot, not a field: the list is webpack's own record of
412
+ // the scope, and a named key would land in every consumer's view of the AST —
413
+ // `JSON.stringify` included, where it duplicates each declaration's subtree.
414
+ const HOISTED_DECLARATIONS = Symbol("hoistedDeclarations");
415
+
416
+ // The slot of a scope that declared nothing. It has to differ from the empty
417
+ // slot of a node some other parser built, which has no record to read.
418
+ /** @type {HoistedDeclarations} */
419
+ const NO_HOISTED_DECLARATIONS = [];
420
+
421
+ // The program's own import and re-export declarations, read before anything
422
+ // else — same sparse-slot reasoning as the hoisted list above.
423
+ const MODULE_DECLARATIONS = Symbol("moduleDeclarations");
424
+
425
+ /** @type {ModuleDeclarations} */
426
+ const NO_MODULE_DECLARATIONS = [];
427
+
428
+ // Which statements of one list declare into its own block scope, read before
429
+ // any of it is walked — same sparse-slot reasoning as the two lists above. It
430
+ // holds their indices, so `undefined` alone means no record was kept.
431
+ const BLOCK_DECLARATIONS = Symbol("blockDeclarations");
432
+
433
+ // WHY: the indices live in one number rather than an array because 59.4% of the
434
+ // lists that declare anything declare exactly once, and a 4-element array costs
435
+ // ~200 bytes of V8 overhead — 2.33 MB of an 84 MB AST measured over the
436
+ // `js-parser-unit` sources. Only an index past this one needs the array.
437
+ const MAX_MASKED_INDEX = 30;
438
+
439
+ /**
440
+ * Turn a mask that can no longer hold every index into the list it falls back
441
+ * to, holding what the mask held plus the index that overflowed it.
442
+ * @param {number} mask the indices recorded so far
443
+ * @param {number} index the index that does not fit
444
+ * @returns {number[]} every index, in source order
445
+ */
446
+ const overflowFrom = (mask, index) => {
447
+ /** @type {number[]} */
448
+ const indices = [];
449
+ for (let bits = mask; bits !== 0; bits &= bits - 1) {
450
+ indices.push(31 - Math.clz32(bits & -bits));
451
+ }
452
+ indices.push(index);
453
+ return indices;
454
+ };
455
+
456
+ /**
457
+ * Whether a statement declares anything into the block scope holding it, which
458
+ * is what the consumer reads the list for.
459
+ * @param {EXPECTED_ANY} statement the finished statement
460
+ * @returns {boolean} whether it belongs in the list
461
+ */
462
+ const declaresIntoBlock = (statement) => {
463
+ const type = statement.type;
464
+ if (
465
+ type === "VariableDeclaration" ||
466
+ type === "ClassDeclaration" ||
467
+ type === "ExportNamedDeclaration" ||
468
+ type === "ExportDefaultDeclaration"
469
+ ) {
470
+ return true;
471
+ }
472
+ // WHY: only an assignment to an object pattern is read here, for the
473
+ // properties it names. Keeping every expression statement would carry the
474
+ // most common statement there is: 10390 of three-long's 22758, against 1.
475
+ if (type !== "ExpressionStatement") return false;
476
+ const expression = statement.expression;
477
+ return (
478
+ expression.type === "AssignmentExpression" &&
479
+ expression.left.type === "ObjectPattern"
480
+ );
481
+ };
482
+
413
483
  /**
414
484
  * Single-shape `VariableDeclaration` (statement position; `for` heads keep the
415
485
  * generic node since their caller finishes them).
@@ -480,6 +550,11 @@ class BlockStatementNode {
480
550
  this.start = start;
481
551
  this.end = end;
482
552
  this.body = body;
553
+ // filled for a function body only: what hoists to the scope it opens
554
+ /** @type {HoistedDeclarations | undefined} */
555
+ this[HOISTED_DECLARATIONS] = undefined;
556
+ /** @type {BlockDeclarations | undefined} */
557
+ this[BLOCK_DECLARATIONS] = undefined;
483
558
  }
484
559
  }
485
560
 
@@ -784,6 +859,8 @@ class SwitchCaseNode {
784
859
  this.consequent = null;
785
860
  /** @type {Expression | null} */
786
861
  this.test = null;
862
+ /** @type {BlockDeclarations | undefined} */
863
+ this[BLOCK_DECLARATIONS] = undefined;
787
864
  }
788
865
  }
789
866
 
@@ -995,6 +1072,8 @@ class StaticBlockNode {
995
1072
  this.end = 0;
996
1073
  /** @type {Node[] | null} */
997
1074
  this.body = null;
1075
+ /** @type {BlockDeclarations | undefined} */
1076
+ this[BLOCK_DECLARATIONS] = undefined;
998
1077
  }
999
1078
  }
1000
1079
 
@@ -1337,6 +1416,12 @@ class ProgramNode {
1337
1416
  this.end = end;
1338
1417
  this.body = body;
1339
1418
  this.sourceType = sourceType;
1419
+ /** @type {HoistedDeclarations | undefined} */
1420
+ this[HOISTED_DECLARATIONS] = undefined;
1421
+ /** @type {ModuleDeclarations | undefined} */
1422
+ this[MODULE_DECLARATIONS] = undefined;
1423
+ /** @type {BlockDeclarations | undefined} */
1424
+ this[BLOCK_DECLARATIONS] = undefined;
1340
1425
  }
1341
1426
  }
1342
1427
 
@@ -1727,6 +1812,10 @@ class LazyComment {
1727
1812
  * lineStart: number,
1728
1813
  * _scopePool: Scope[],
1729
1814
  * _setPool: Set<string>[],
1815
+ * _exportHeadDepth: number,
1816
+ * _exitedHoisted: HoistedDeclarations | undefined,
1817
+ * _moduleDeclarations: ModuleDeclarations | undefined,
1818
+ * _previousTopLevelStatement: Node | undefined,
1730
1819
  * _takeSet: () => Set<string>,
1731
1820
  * _labelsStack: { kind?: string | null, name?: string, statementStart?: number }[][],
1732
1821
  * _labelsDepth: number,
@@ -1830,10 +1919,9 @@ const wordLookupsCache = new Map();
1830
1919
  // parser constructor, so the hot paths never observe the nulls behind it.
1831
1920
  const NO_CACHE = /** @type {EXPECTED_ANY} */ (null);
1832
1921
 
1833
- // Direct-mapped identifier cache for `readWord1`: one slot per hash, verified
1834
- // by char compare, overwritten on collision. Shared across parses — hits are
1835
- // content-checked, so a stale entry is merely a miss. Only words short enough
1836
- // to be flat V8 strings (never slices retaining their whole source) are stored.
1922
+ // Direct-mapped identifier cache for `readWord1`: one slot per hash, verified by
1923
+ // char compare, overwritten on collision. Shared across parses, since a hit is
1924
+ // content-checked. Only lengths V8 stores flat, never source-retaining slices.
1837
1925
  const WORD_CACHE_MASK = 0xfff;
1838
1926
  const WORD_CACHE_MAX_LEN = 12;
1839
1927
 
@@ -1844,12 +1932,13 @@ let WORD_CACHE = NO_CACHE;
1844
1932
  const WORD_CACHE_STRIDE = 4;
1845
1933
  let nextWordLookupsId = 1;
1846
1934
 
1847
- // Direct-mapped cache for short non-word slices, WORD_CACHE's regime applied
1848
- // to literal text: number raws repeat heavily (a typical large input has ~10x
1849
- // more number literals than distinct raws) and short string values/raws repeat
1850
- // too, so serving them from one shared string cuts both allocation churn and
1851
- // retained AST strings. Same rules as WORD_CACHE: content-checked hits, only
1852
- // lengths V8 stores flat (never slices retaining the source).
1935
+ // WHY: a direct-mapped cache for short non-word slices — WORD_CACHE's regime
1936
+ // applied to literal text. Number raws repeat heavily, a typical large input
1937
+ // holding some ten times more number literals than distinct raws, and short
1938
+ // string values and raws repeat too, so serving them from one shared string cuts
1939
+ // both allocation churn and retained AST strings. Same rules as WORD_CACHE:
1940
+ // content-checked hits, and only the lengths V8 stores flat, never a slice
1941
+ // retaining the source.
1853
1942
  const SLICE_CACHE_MASK = 0xfff;
1854
1943
  /** @type {(string | null)[]} */
1855
1944
  let SLICE_CACHE = NO_CACHE;
@@ -1998,10 +2087,9 @@ const wordsRegexpToSet = (re) => {
1998
2087
  return new Set(body ? body.split("|") : []);
1999
2088
  };
2000
2089
 
2001
- // One-entry identity memo in front of the string-keyed cache: acorn's
2002
- // `wordsRegexp` interns its regexps, so identity captures the whole word set,
2003
- // and builds construct thousands of parsers with one option set — this makes
2004
- // the per-construction lookup three compares instead of a long key concat.
2090
+ // One-entry identity memo in front of the string-keyed cache. `wordsRegexp`
2091
+ // interns its regexps, so identity captures the whole word set, and a build
2092
+ // constructs thousands of parsers from one option set.
2005
2093
  /** @type {RegExp | undefined} */
2006
2094
  let lastKeywordsRe;
2007
2095
  /** @type {RegExp | undefined} */
@@ -2273,17 +2361,14 @@ class WebpackParser extends BaseParser {
2273
2361
  */
2274
2362
  constructor(options, input, startPos) {
2275
2363
  ensureParserCaches();
2276
- // fast construction for the gated hot-path shape: skip acorn's per-parse
2364
+ // fast construction for the gated hot-path shape, skipping acorn's per-parse
2277
2365
  // getOptions/wordsRegexp work. A derived constructor may return an object
2278
- // without calling super(); a plugin subclass's constructor body then runs
2279
- // on the returned object exactly as it would after its super() call.
2366
+ // without super(), and a plugin's body then runs on it just the same.
2280
2367
  const shape = getFastConstructionShape(options, input, startPos);
2281
2368
  if (shape !== null) {
2282
- // write order below is load-bearing: acorn's constructor fields first,
2283
- // in dist order (a chained `a = b = v` creates b before a), then the
2284
- // WebpackParser fields in slow-constructor order — so fast- and
2369
+ // write order below is load-bearing: acorn's constructor fields first, in
2370
+ // dist order, then WebpackParser's in slow-constructor order, so fast- and
2285
2371
  // slow-built instances walk one hidden-class transition chain
2286
- // acorn source: https://github.com/acornjs/acorn/blob/8.18.0/acorn/src/state.js
2287
2372
  const self = /** @type {ParserInternals} */ (
2288
2373
  /** @type {unknown} */ (Object.create(new.target.prototype))
2289
2374
  );
@@ -2375,6 +2460,10 @@ class WebpackParser extends BaseParser {
2375
2460
  self._arrDepth = 0;
2376
2461
  self._scopePool = [];
2377
2462
  self._setPool = [];
2463
+ self._exportHeadDepth = -1;
2464
+ self._exitedHoisted = undefined;
2465
+ self._moduleDeclarations = undefined;
2466
+ self._previousTopLevelStatement = undefined;
2378
2467
  self._labelsStack = [];
2379
2468
  self._labelsDepth = 0;
2380
2469
  self._scanGapNewline = false;
@@ -2506,12 +2595,12 @@ class WebpackParser extends BaseParser {
2506
2595
  this._subscriptFastPath = lazy && this._ecmaVersion >= 11;
2507
2596
  const proto = WebpackParser.prototype;
2508
2597
  const self = /** @type {ParserInternals} */ (/** @type {unknown} */ (this));
2509
- // the owned per-token loop (nextToken/finishToken/next) also serves the
2598
+ // WHY: the owned per-token loop (nextToken/finishToken/next) also serves the
2510
2599
  // public non-lazy tokenizer(): locations off, no onToken, and none of the
2511
- // acorn tokenizer methods it inlines or skips overridden by a plugin
2512
- // (`nextToken`'s punct/dot/eq shortcuts bypass `getTokenFromCode`,
2513
- // `finishOp`, `readToken_dot` and `readToken_eq_excl` even when the full
2514
- // token path below is off, so their overrides must gate this loop too)
2600
+ // acorn tokenizer methods it inlines or skips overridden by a plugin.
2601
+ // `nextToken`'s punct/dot/eq shortcuts bypass `getTokenFromCode`, `finishOp`,
2602
+ // `readToken_dot` and `readToken_eq_excl` even when the full token path below
2603
+ // is off, so their overrides must gate this loop too.
2515
2604
  /** @type {boolean} */
2516
2605
  this._tokenFastPath =
2517
2606
  lazy ||
@@ -2586,6 +2675,24 @@ class WebpackParser extends BaseParser {
2586
2675
  // pool of emptied name Sets harvested by exitScope for declareName
2587
2676
  /** @type {Set<string>[]} */
2588
2677
  this._setPool = [];
2678
+ // WHY: a declaration directly under an `export` head is reported by the
2679
+ // export statement that holds it, never by the scope, so recording is
2680
+ // held back for exactly the one scope depth the head opened at.
2681
+ /** @type {number} */
2682
+ this._exportHeadDepth = -1;
2683
+ // what the scope `exitScope` just closed had recorded, for the caller
2684
+ // that owns that scope's node and reads it right after the call
2685
+ /** @type {HoistedDeclarations | undefined} */
2686
+ this._exitedHoisted = undefined;
2687
+ // the program's import and re-export declarations, in source order, each
2688
+ // followed by the top-level statement written before it
2689
+ /** @type {ModuleDeclarations | undefined} */
2690
+ this._moduleDeclarations = undefined;
2691
+ // WHY: what precedes a module declaration decides whether removing it
2692
+ // joins two statements through ASI, so the consumer needs it and cannot
2693
+ // read it back off a list holding declarations alone.
2694
+ /** @type {Node | undefined} */
2695
+ this._previousTopLevelStatement = undefined;
2589
2696
  // per-depth pool of function-body label arrays (see parseFunctionBody)
2590
2697
  /** @type {{ kind?: string | null, name?: string, statementStart?: number }[][]} */
2591
2698
  this._labelsStack = [];
@@ -2612,10 +2719,9 @@ class WebpackParser extends BaseParser {
2612
2719
  this.parseIfStatement === proto.parseIfStatement &&
2613
2720
  this.parseReturnStatement === proto.parseReturnStatement &&
2614
2721
  this.parseExpressionStatement === proto.parseExpressionStatement;
2615
- // last arrow finished by parseArrowExpression: `expr === this._lastArrow`
2616
- // replaces the megamorphic `expr.type === "ArrowFunctionExpression"`
2617
- // probes on the expression spine (arrows are created in exactly one place
2618
- // and never backtracked, so identity captures the type test)
2722
+ // last arrow finished by parseArrowExpression, so `expr === this._lastArrow`
2723
+ // replaces the megamorphic type probes on the expression spine: arrows are
2724
+ // created in one place and never backtracked, so identity captures the test
2619
2725
  /** @type {Expression | null} */
2620
2726
  this._lastArrow = null;
2621
2727
  // arrows must flow through parseArrowExpression for the identity probe;
@@ -2908,7 +3014,7 @@ class WebpackParser extends BaseParser {
2908
3014
  * @returns {EXPECTED_ANY} the exported declaration
2909
3015
  */
2910
3016
  parseExportDeclaration(node) {
2911
- return this.parseStatement(null);
3017
+ return this._inExportHead(() => this.parseStatement(null));
2912
3018
  }
2913
3019
 
2914
3020
  /**
@@ -5158,9 +5264,8 @@ class WebpackParser extends BaseParser {
5158
5264
  // acorn no-ops on it — no keyword or reserved set contains a non-string
5159
5265
  if (typeof name !== "string") return;
5160
5266
  // every reserved word and special name below is short lowercase ASCII, so
5161
- // most identifiers exit on this shape gate before any string compare
5162
- // (`yield`/`await`/`arguments` all pass it: lengths 5/5/9 ≤ reservedMaxLen,
5163
- // which keywords like `instanceof` keep at ≥ 10)
5267
+ // most identifiers exit on this shape gate before any string compare;
5268
+ // `yield`, `await` and `arguments` all pass it
5164
5269
  const lookups = this._wordLookups;
5165
5270
  const nameLen = name.length;
5166
5271
  if (nameLen < 2 || nameLen > lookups.reservedMaxLen) return;
@@ -5770,14 +5875,30 @@ class WebpackParser extends BaseParser {
5770
5875
  // a `program` continuation node must be appended to and returned as-is,
5771
5876
  // which only acorn's copy does (base parse() reaches here via dispatch)
5772
5877
  if (!this._lazy || this.options.program) {
5773
- return baseProto().parseTopLevel.call(this, node);
5878
+ const program = baseProto().parseTopLevel.call(this, node);
5879
+ /** @type {EXPECTED_ANY} */
5880
+ (program)[HOISTED_DECLARATIONS] = this._takeHoisted(this.scopeStack[0]);
5881
+ // acorn's own loop reports no statement order, so what precedes each
5882
+ // module declaration is unknown and the record is not kept
5883
+ this._moduleDeclarations = undefined;
5884
+ return program;
5774
5885
  }
5775
5886
  /** @type {Record<string, boolean>} */
5776
5887
  const exports = Object.create(null);
5777
5888
  const scratch = this._acquireScratch();
5778
5889
  let count = 0;
5890
+ let blockMask = 0;
5891
+ /** @type {number[] | undefined} */
5892
+ let blockOverflow;
5779
5893
  while (this.type !== tokTypes.eof) {
5780
- scratch[count++] = this.parseStatement(null, true, exports);
5894
+ const statement = this.parseStatement(null, true, exports);
5895
+ if (declaresIntoBlock(statement)) {
5896
+ if (blockOverflow !== undefined) blockOverflow.push(count);
5897
+ else if (count <= MAX_MASKED_INDEX) blockMask |= 1 << count;
5898
+ else blockOverflow = overflowFrom(blockMask, count);
5899
+ }
5900
+ scratch[count++] = statement;
5901
+ this._previousTopLevelStatement = statement;
5781
5902
  }
5782
5903
  const body = this._releaseScratch(scratch, count);
5783
5904
  if (this.inModule) {
@@ -5790,18 +5911,19 @@ class WebpackParser extends BaseParser {
5790
5911
  }
5791
5912
  this.adaptDirectivePrologue(body);
5792
5913
  this.next();
5793
- return /** @type {Node} */ (
5794
- /** @type {unknown} */ (
5795
- new ProgramNode(
5796
- node.start,
5797
- this.lastTokEnd,
5798
- body,
5799
- this.options.sourceType === "commonjs"
5800
- ? "script"
5801
- : /** @type {string} */ (this.options.sourceType)
5802
- )
5803
- )
5914
+ const program = new ProgramNode(
5915
+ node.start,
5916
+ this.lastTokEnd,
5917
+ body,
5918
+ this.options.sourceType === "commonjs"
5919
+ ? "script"
5920
+ : /** @type {string} */ (this.options.sourceType)
5804
5921
  );
5922
+ program[HOISTED_DECLARATIONS] = this._takeHoisted(this.scopeStack[0]);
5923
+ program[MODULE_DECLARATIONS] = this._takeModuleDeclarations();
5924
+ program[BLOCK_DECLARATIONS] =
5925
+ blockOverflow === undefined ? blockMask : blockOverflow;
5926
+ return /** @type {Node} */ (/** @type {unknown} */ (program));
5805
5927
  }
5806
5928
 
5807
5929
  /**
@@ -6139,12 +6261,14 @@ class WebpackParser extends BaseParser {
6139
6261
  */
6140
6262
  parseVarStatement(node, kind, allowMissingInitializer) {
6141
6263
  if (!this._lazy || !this._varIdOwn) {
6142
- return baseProto().parseVarStatement.call(
6264
+ const declaration = baseProto().parseVarStatement.call(
6143
6265
  this,
6144
6266
  node,
6145
6267
  kind,
6146
6268
  allowMissingInitializer
6147
6269
  );
6270
+ if (kind === "var") this._recordHoisted(declaration);
6271
+ return declaration;
6148
6272
  }
6149
6273
  return this._parseVarStatementAt(node.start, kind, allowMissingInitializer);
6150
6274
  }
@@ -6169,11 +6293,13 @@ class WebpackParser extends BaseParser {
6169
6293
  );
6170
6294
  const declarations = this._releaseScratch(scratch, count);
6171
6295
  this.semicolon();
6172
- return /** @type {Node} */ (
6296
+ const node = /** @type {Node} */ (
6173
6297
  /** @type {unknown} */ (
6174
6298
  new VariableDeclarationNode(start, this.lastTokEnd, declarations, kind)
6175
6299
  )
6176
6300
  );
6301
+ if (kind === "var") this._recordHoisted(node);
6302
+ return node;
6177
6303
  }
6178
6304
 
6179
6305
  /**
@@ -6326,23 +6452,31 @@ class WebpackParser extends BaseParser {
6326
6452
  const start = this.start;
6327
6453
  const scratch = this._acquireScratch();
6328
6454
  let count = 0;
6455
+ let blockMask = 0;
6456
+ /** @type {number[] | undefined} */
6457
+ let blockOverflow;
6329
6458
  this.expect(tokTypes.braceL);
6330
6459
  if (createNewLexicalScope) this.enterScope(0);
6331
6460
  while (this.type !== tokTypes.braceR) {
6332
- scratch[count++] = this.parseStatement(null);
6461
+ const statement = this.parseStatement(null);
6462
+ if (declaresIntoBlock(statement)) {
6463
+ if (blockOverflow !== undefined) blockOverflow.push(count);
6464
+ else if (count <= MAX_MASKED_INDEX) blockMask |= 1 << count;
6465
+ else blockOverflow = overflowFrom(blockMask, count);
6466
+ }
6467
+ scratch[count++] = statement;
6333
6468
  }
6334
6469
  if (exitStrict) this.strict = false;
6335
6470
  this.next();
6336
6471
  if (createNewLexicalScope) this.exitScope();
6337
- return /** @type {Node} */ (
6338
- /** @type {unknown} */ (
6339
- new BlockStatementNode(
6340
- start,
6341
- this.lastTokEnd,
6342
- this._releaseScratch(scratch, count)
6343
- )
6344
- )
6472
+ const block = new BlockStatementNode(
6473
+ start,
6474
+ this.lastTokEnd,
6475
+ this._releaseScratch(scratch, count)
6345
6476
  );
6477
+ block[BLOCK_DECLARATIONS] =
6478
+ blockOverflow === undefined ? blockMask : blockOverflow;
6479
+ return /** @type {Node} */ (/** @type {unknown} */ (block));
6346
6480
  }
6347
6481
 
6348
6482
  /**
@@ -6522,6 +6656,7 @@ class WebpackParser extends BaseParser {
6522
6656
  )
6523
6657
  )
6524
6658
  );
6659
+ if (kind === "var") this._recordHoisted(init);
6525
6660
  return this._parseForAfterInitAt(start, init, awaitAt);
6526
6661
  }
6527
6662
  const startsWithLet = this.isContextual("let");
@@ -6727,10 +6862,19 @@ class WebpackParser extends BaseParser {
6727
6862
  this.enterScope(SCOPE_SWITCH);
6728
6863
  /** @type {SwitchCaseNode | undefined} */
6729
6864
  let cur;
6865
+ let caseMask = 0;
6866
+ /** @type {number[] | undefined} */
6867
+ let caseOverflow;
6730
6868
  for (let sawDefault = false; this.type !== tokTypes.braceR;) {
6731
6869
  if (this.type === tokTypes._case || this.type === tokTypes._default) {
6732
6870
  const isCase = this.type === tokTypes._case;
6733
- if (cur) this.finishNode(/** @type {Node} */ (cur), "SwitchCase");
6871
+ if (cur) {
6872
+ cur[BLOCK_DECLARATIONS] =
6873
+ caseOverflow === undefined ? caseMask : caseOverflow;
6874
+ this.finishNode(/** @type {Node} */ (cur), "SwitchCase");
6875
+ }
6876
+ caseMask = 0;
6877
+ caseOverflow = undefined;
6734
6878
  cur = new SwitchCaseNode(this.start);
6735
6879
  cases.push(/** @type {Node} */ (cur));
6736
6880
  cur.consequent = [];
@@ -6750,13 +6894,25 @@ class WebpackParser extends BaseParser {
6750
6894
  this.expect(tokTypes.colon);
6751
6895
  } else {
6752
6896
  if (!cur) this.unexpected();
6753
- /** @type {Node[]} */ (
6754
- /** @type {SwitchCaseNode} */ (cur).consequent
6755
- ).push(this.parseStatement(null));
6897
+ const consequent =
6898
+ /** @type {Node[]} */
6899
+ (/** @type {SwitchCaseNode} */ (cur).consequent);
6900
+ const statement = this.parseStatement(null);
6901
+ if (declaresIntoBlock(statement)) {
6902
+ const index = consequent.length;
6903
+ if (caseOverflow !== undefined) caseOverflow.push(index);
6904
+ else if (index <= MAX_MASKED_INDEX) caseMask |= 1 << index;
6905
+ else caseOverflow = overflowFrom(caseMask, index);
6906
+ }
6907
+ consequent.push(statement);
6756
6908
  }
6757
6909
  }
6758
6910
  this.exitScope();
6759
- if (cur) this.finishNode(/** @type {Node} */ (cur), "SwitchCase");
6911
+ if (cur) {
6912
+ cur[BLOCK_DECLARATIONS] =
6913
+ caseOverflow === undefined ? caseMask : caseOverflow;
6914
+ this.finishNode(/** @type {Node} */ (cur), "SwitchCase");
6915
+ }
6760
6916
  this.next(); // closing brace
6761
6917
  this.labels.pop();
6762
6918
  return /** @type {Node} */ (
@@ -7094,16 +7250,12 @@ class WebpackParser extends BaseParser {
7094
7250
  this.yieldPos = oldYieldPos;
7095
7251
  this.awaitPos = oldAwaitPos;
7096
7252
  this.awaitIdentPos = oldAwaitIdentPos;
7097
- return /** @type {Expression} */ (
7098
- /** @type {unknown} */ (
7099
- this.finishNode(
7100
- node,
7101
- statement & FUNC_STATEMENT
7102
- ? "FunctionDeclaration"
7103
- : "FunctionExpression"
7104
- )
7105
- )
7253
+ const finished = this.finishNode(
7254
+ node,
7255
+ statement & FUNC_STATEMENT ? "FunctionDeclaration" : "FunctionExpression"
7106
7256
  );
7257
+ if (statement & FUNC_STATEMENT) this._recordHoisted(finished);
7258
+ return /** @type {Expression} */ (/** @type {unknown} */ (finished));
7107
7259
  }
7108
7260
 
7109
7261
  /**
@@ -7115,13 +7267,23 @@ class WebpackParser extends BaseParser {
7115
7267
  */
7116
7268
  parseFunctionBody(node, isArrowFunction, isMethod, forInit) {
7117
7269
  if (!this._funcFastPath) {
7118
- return baseProto().parseFunctionBody.call(
7270
+ baseProto().parseFunctionBody.call(
7119
7271
  this,
7120
7272
  node,
7121
7273
  isArrowFunction,
7122
7274
  isMethod,
7123
7275
  forInit
7124
7276
  );
7277
+ const body = /** @type {Node & { body: Node }} */ (node).body;
7278
+ if (body.type === "BlockStatement") {
7279
+ /** @type {EXPECTED_ANY} */
7280
+ (body)[HOISTED_DECLARATIONS] = !this._recordsHoisted()
7281
+ ? undefined
7282
+ : this._exitedHoisted === undefined
7283
+ ? NO_HOISTED_DECLARATIONS
7284
+ : this._exitedHoisted;
7285
+ }
7286
+ return;
7125
7287
  }
7126
7288
  const target =
7127
7289
  /** @type {Node & { id: Identifier | null, params: Node[], body: Node, expression: boolean }} */ (
@@ -7181,6 +7343,11 @@ class WebpackParser extends BaseParser {
7181
7343
  );
7182
7344
  this._labelsDepth--;
7183
7345
  this.labels = oldLabels;
7346
+ /** @type {EXPECTED_ANY} */
7347
+ (target.body)[HOISTED_DECLARATIONS] = this._takeHoisted(
7348
+ this.currentScope()
7349
+ );
7350
+ this._exitedHoisted = undefined;
7184
7351
  }
7185
7352
  this.exitScope();
7186
7353
  }
@@ -8726,7 +8893,9 @@ class WebpackParser extends BaseParser {
8726
8893
  */
8727
8894
  parseClass(node, isStatement) {
8728
8895
  if (!this._classFastPath) {
8729
- return baseProto().parseClass.call(this, node, isStatement);
8896
+ const parsed = baseProto().parseClass.call(this, node, isStatement);
8897
+ if (isStatement) this._recordHoisted(parsed);
8898
+ return parsed;
8730
8899
  }
8731
8900
  const classNode =
8732
8901
  /** @type {Node & { id: Identifier | null, superClass: Expression | null, body: Node | null }} */ (
@@ -8786,10 +8955,12 @@ class WebpackParser extends BaseParser {
8786
8955
  )
8787
8956
  );
8788
8957
  this.exitClassBody();
8789
- return this.finishNode(
8958
+ const finished = this.finishNode(
8790
8959
  /** @type {Node} */ (/** @type {unknown} */ (classNode)),
8791
8960
  isStatement ? "ClassDeclaration" : "ClassExpression"
8792
8961
  );
8962
+ if (isStatement) this._recordHoisted(finished);
8963
+ return finished;
8793
8964
  }
8794
8965
 
8795
8966
  /**
@@ -9031,11 +9202,23 @@ class WebpackParser extends BaseParser {
9031
9202
  target.body = [];
9032
9203
  const oldLabels = this.labels;
9033
9204
  this.labels = [];
9205
+ let blockMask = 0;
9206
+ /** @type {number[] | undefined} */
9207
+ let blockOverflow;
9034
9208
  this.enterScope(SCOPE_CLASS_STATIC_BLOCK | SCOPE_SUPER);
9035
9209
  while (this.type !== tokTypes.braceR) {
9036
9210
  const statement = this.parseStatement(null);
9211
+ if (declaresIntoBlock(statement)) {
9212
+ const index = target.body.length;
9213
+ if (blockOverflow !== undefined) blockOverflow.push(index);
9214
+ else if (index <= MAX_MASKED_INDEX) blockMask |= 1 << index;
9215
+ else blockOverflow = overflowFrom(blockMask, index);
9216
+ }
9037
9217
  target.body.push(statement);
9038
9218
  }
9219
+ /** @type {EXPECTED_ANY} */
9220
+ (target)[BLOCK_DECLARATIONS] =
9221
+ blockOverflow === undefined ? blockMask : blockOverflow;
9039
9222
  this.next();
9040
9223
  this.exitScope();
9041
9224
  this.labels = oldLabels;
@@ -9537,6 +9720,10 @@ class WebpackParser extends BaseParser {
9537
9720
  scope.functions = undefined;
9538
9721
  }
9539
9722
  scope.firstLexical = undefined;
9723
+ this._exitedHoisted = scope.hoisted;
9724
+ scope.hoisted = undefined;
9725
+ // a recorded list is the consumer's now, and an empty one is still a
9726
+ // record — what must never reach it is the list of some earlier scope
9540
9727
  this._scopePool.push(scope);
9541
9728
  }
9542
9729
 
@@ -9548,6 +9735,115 @@ class WebpackParser extends BaseParser {
9548
9735
  return cached === undefined ? new Set() : cached;
9549
9736
  }
9550
9737
 
9738
+ /**
9739
+ * Record a declaration statement on the var scope it hoists to, in source
9740
+ * order. A declaration under an `export` head belongs to that statement.
9741
+ * @param {EXPECTED_ANY} node the declaration statement
9742
+ * @returns {void}
9743
+ */
9744
+ _recordHoisted(node) {
9745
+ if (!this._recordsHoisted()) return;
9746
+ if (this.scopeStack.length === this._exportHeadDepth) return;
9747
+ const scope = this.currentVarScope();
9748
+ if (scope.hoisted === undefined) scope.hoisted = [node];
9749
+ else scope.hoisted.push(node);
9750
+ }
9751
+
9752
+ /**
9753
+ * Hand the scope's recorded declarations to the node that owns it, leaving
9754
+ * the slot empty for the pool. Call it before the matching `exitScope`.
9755
+ * @param {Scope} scope the scope being closed
9756
+ * @returns {HoistedDeclarations | undefined} the declarations, in source order
9757
+ */
9758
+ _takeHoisted(scope) {
9759
+ if (!this._recordsHoisted()) return undefined;
9760
+ const hoisted = scope.hoisted;
9761
+ if (hoisted === undefined) return NO_HOISTED_DECLARATIONS;
9762
+ scope.hoisted = undefined;
9763
+ return hoisted;
9764
+ }
9765
+
9766
+ /**
9767
+ * Whether the declarations of each scope are recorded at all: only when every
9768
+ * production that reaches a recording site is this class's own, since an
9769
+ * override of any of them leaves the record silently short.
9770
+ * @returns {boolean} whether the record is kept
9771
+ */
9772
+ _recordsHoisted() {
9773
+ return (
9774
+ this._lazy &&
9775
+ this._stmtFastPath &&
9776
+ this._funcStmtOwn &&
9777
+ this._stmt2FastPath &&
9778
+ this.parseClass === WebpackParser.prototype.parseClass
9779
+ );
9780
+ }
9781
+
9782
+ /**
9783
+ * Record an import or re-export the program states directly. One nested
9784
+ * deeper belongs to no program, so only the top-level list is kept.
9785
+ * @param {EXPECTED_ANY} node the finished declaration
9786
+ * @returns {void}
9787
+ */
9788
+ _recordModuleDeclaration(node) {
9789
+ if (this.scopeStack.length !== 1) return;
9790
+ const type = node.type;
9791
+ if (
9792
+ type !== "ImportDeclaration" &&
9793
+ type !== "ExportNamedDeclaration" &&
9794
+ type !== "ExportAllDeclaration"
9795
+ ) {
9796
+ return;
9797
+ }
9798
+ const previous = this._previousTopLevelStatement;
9799
+ if (this._moduleDeclarations === undefined) {
9800
+ this._moduleDeclarations = [node, previous];
9801
+ } else {
9802
+ this._moduleDeclarations.push(node, previous);
9803
+ }
9804
+ }
9805
+
9806
+ /**
9807
+ * Hand the program its module declarations, leaving the slot empty.
9808
+ * @returns {ModuleDeclarations | undefined} them, in source order
9809
+ */
9810
+ _takeModuleDeclarations() {
9811
+ if (!this._recordsModuleDeclarations()) return undefined;
9812
+ const declarations = this._moduleDeclarations;
9813
+ if (declarations === undefined) return NO_MODULE_DECLARATIONS;
9814
+ this._moduleDeclarations = undefined;
9815
+ return declarations;
9816
+ }
9817
+
9818
+ /**
9819
+ * Whether imports and re-exports are recorded at all: only when this class
9820
+ * reads them, since an override of either is what would go unrecorded.
9821
+ * @returns {boolean} whether the record is kept
9822
+ */
9823
+ _recordsModuleDeclarations() {
9824
+ const proto = WebpackParser.prototype;
9825
+ return (
9826
+ this._lazy &&
9827
+ this.parseImport === proto.parseImport &&
9828
+ this.parseExport === proto.parseExport
9829
+ );
9830
+ }
9831
+
9832
+ /**
9833
+ * Run `parse` with declaration recording held back for the scope depth it
9834
+ * opens at, which is how an `export` head keeps its own declaration.
9835
+ * @template T
9836
+ * @param {() => T} parse what reads the declaration
9837
+ * @returns {T} whatever it read
9838
+ */
9839
+ _inExportHead(parse) {
9840
+ const previous = this._exportHeadDepth;
9841
+ this._exportHeadDepth = this.scopeStack.length;
9842
+ const declaration = parse();
9843
+ this._exportHeadDepth = previous;
9844
+ return declaration;
9845
+ }
9846
+
9551
9847
  /**
9552
9848
  * Record a name in the scope its binding belongs to, and report a name that
9553
9849
  * was already declared there.
@@ -9744,6 +10040,16 @@ class WebpackParser extends BaseParser {
9744
10040
  * @returns {EXPECTED_ANY} the finished import
9745
10041
  */
9746
10042
  parseImport(node) {
10043
+ const declaration = this._parseImport(node);
10044
+ this._recordModuleDeclaration(declaration);
10045
+ return declaration;
10046
+ }
10047
+
10048
+ /**
10049
+ * @param {EXPECTED_ANY} node the import node
10050
+ * @returns {EXPECTED_ANY} the finished import
10051
+ */
10052
+ _parseImport(node) {
9747
10053
  this._moduleSyntaxSeen = true;
9748
10054
  this._importPhase = null;
9749
10055
  if (!this._moduleDeclFastPath) {
@@ -9900,6 +10206,17 @@ class WebpackParser extends BaseParser {
9900
10206
  * @returns {EXPECTED_ANY} the finished export
9901
10207
  */
9902
10208
  parseExport(node, exports) {
10209
+ const declaration = this._parseExport(node, exports);
10210
+ this._recordModuleDeclaration(declaration);
10211
+ return declaration;
10212
+ }
10213
+
10214
+ /**
10215
+ * @param {EXPECTED_ANY} node the export node
10216
+ * @param {EXPECTED_ANY} exports where module exports are tracked
10217
+ * @returns {EXPECTED_ANY} the finished export
10218
+ */
10219
+ _parseExport(node, exports) {
9903
10220
  this._moduleSyntaxSeen = true;
9904
10221
  if (!this._moduleDeclFastPath) {
9905
10222
  return baseProto().parseExport.call(this, node, exports);
@@ -10026,6 +10343,11 @@ class WebpackParser extends BaseParser {
10026
10343
 
10027
10344
  /** @returns {EXPECTED_ANY} what `export default` exports */
10028
10345
  parseExportDefaultDeclaration() {
10346
+ return this._inExportHead(() => this._parseExportDefaultDeclaration());
10347
+ }
10348
+
10349
+ /** @returns {EXPECTED_ANY} what `export default` exports */
10350
+ _parseExportDefaultDeclaration() {
10029
10351
  if (!this._moduleDeclFastPath) {
10030
10352
  return baseProto().parseExportDefaultDeclaration.call(this);
10031
10353
  }
@@ -10942,11 +11264,17 @@ const parse = (input, options) =>
10942
11264
  )
10943
11265
  );
10944
11266
 
11267
+ module.exports.BLOCK_DECLARATIONS = BLOCK_DECLARATIONS;
11268
+ module.exports.MAX_MASKED_INDEX = MAX_MASKED_INDEX;
11269
+ module.exports.HOISTED_DECLARATIONS = HOISTED_DECLARATIONS;
11270
+ module.exports.MODULE_DECLARATIONS = MODULE_DECLARATIONS;
10945
11271
  module.exports.LEGACY_ASSERT_ATTRIBUTES = LEGACY_ASSERT_ATTRIBUTES;
10946
11272
  module.exports.ParserPosition = ParserPosition;
10947
11273
  module.exports.WebpackParser = WebpackParser;
10948
11274
  module.exports.buildLineStarts = buildLineStarts;
10949
11275
  module.exports.collectCjsRequireSpecifiers = collectCjsRequireSpecifiers;
11276
+ module.exports.declaresIntoBlock = declaresIntoBlock;
11277
+ module.exports.overflowFrom = overflowFrom;
10950
11278
  module.exports.hasOctalEscape = hasOctalEscape;
10951
11279
  module.exports.isIdentifierChar = isIdentifierChar;
10952
11280
  module.exports.parse = parse;