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.
- package/lib/APIPlugin.js +3 -4
- package/lib/CompatibilityPlugin.js +3 -4
- package/lib/Compilation.js +16 -35
- package/lib/Compiler.js +4 -5
- package/lib/ConstPlugin.js +16 -132
- package/lib/DependencyTemplate.js +2 -1
- package/lib/DotenvPlugin.js +24 -28
- package/lib/ErrorHelpers.js +113 -0
- package/lib/ExportsInfo.js +20 -16
- package/lib/ExternalModule.js +6 -8
- package/lib/FlagDependencyExportsPlugin.js +8 -13
- package/lib/FlagDependencyUsagePlugin.js +9 -13
- package/lib/Generator.js +24 -2
- package/lib/HotModuleReplacementPlugin.js +2 -0
- package/lib/IgnorePlugin.js +1 -1
- package/lib/LoaderOptionsPlugin.js +1 -1
- package/lib/Module.js +3 -3
- package/lib/ModuleGraph.js +6 -9
- package/lib/MultiCompiler.js +6 -16
- package/lib/NormalModule.js +96 -44
- package/lib/RuntimeTemplate.js +33 -43
- package/lib/SourceMapDevToolPlugin.js +53 -103
- package/lib/TemplatedPathPlugin.js +16 -59
- package/lib/asset/AssetBytesGenerator.js +7 -1
- package/lib/asset/AssetGenerator.js +25 -16
- package/lib/asset/AssetSourceGenerator.js +7 -1
- package/lib/buildChunkGraph.js +11 -15
- package/lib/cache/MemoryCachePlugin.js +4 -4
- package/lib/cache/MemoryWithGcCachePlugin.js +7 -8
- package/lib/cache/PackFileCacheStrategy.js +3 -18
- package/lib/cache/getLazyHashedEtag.js +3 -5
- package/lib/config/browserslistTargetHandler.js +2 -8
- package/lib/config/defaults.js +52 -78
- package/lib/config/getClaimedAssetTypes.js +10 -11
- package/lib/config/target.js +3 -4
- package/lib/{ContextExclusionPlugin.js → context/ContextExclusionPlugin.js} +1 -1
- package/lib/{ContextModule.js → context/ContextModule.js} +37 -34
- package/lib/{ContextModuleFactory.js → context/ContextModuleFactory.js} +19 -21
- package/lib/{ContextReplacementPlugin.js → context/ContextReplacementPlugin.js} +4 -4
- package/lib/css/CssGenerator.js +19 -11
- package/lib/css/CssParser.js +18 -20
- package/lib/css/cssMinify.js +32 -29
- package/lib/css/data.js +797 -288
- package/lib/css/syntax.js +2250 -934
- package/lib/debug/ProfilingPlugin.js +3 -4
- package/lib/dependencies/CommonJsExportRequireDependency.js +10 -11
- package/lib/dependencies/CommonJsImportsParserPlugin.js +4 -5
- package/lib/dependencies/CommonJsSelfReferenceDependency.js +2 -4
- package/lib/dependencies/ContextDependency.js +1 -1
- package/lib/dependencies/ContextDependencyHelpers.js +3 -9
- package/lib/dependencies/ContextElementDependency.js +1 -1
- package/lib/dependencies/CssIcssExportDependency.js +6 -8
- package/lib/dependencies/CssIcssImportDependency.js +3 -6
- package/lib/dependencies/CssUrlDependency.js +3 -5
- package/lib/dependencies/HarmonyCompatibilityDependency.js +11 -20
- package/lib/dependencies/HarmonyDetectionParserPlugin.js +3 -4
- package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +2 -4
- package/lib/dependencies/HarmonyExportExpressionDependency.js +3 -4
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +3 -4
- package/lib/dependencies/HarmonyExportInitFragment.js +26 -19
- package/lib/dependencies/HarmonyExportSpecifierDependency.js +7 -28
- package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +103 -16
- package/lib/dependencies/HarmonyImportSideEffectDependency.js +3 -4
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +16 -2
- package/lib/dependencies/HtmlEntryDependency.js +74 -102
- package/lib/dependencies/HtmlInlineScriptDependency.js +3 -4
- package/lib/dependencies/HtmlInlineStyleDependency.js +3 -4
- package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +1 -1
- package/lib/dependencies/ImportMetaGlobHelpers.js +1 -1
- package/lib/dependencies/ImportMetaPlugin.js +8 -10
- package/lib/dependencies/ImportParserPlugin.js +1 -1
- package/lib/dependencies/LoaderPlugin.js +26 -1
- package/lib/dependencies/RequireContextDependencyParserPlugin.js +1 -1
- package/lib/dependencies/URLContextDependency.js +1 -1
- package/lib/dependencies/URLDependency.js +6 -5
- package/lib/dependencies/WorkerAndWorkletPlugin.js +15 -21
- package/lib/dependencies/WorkerDependency.js +6 -5
- package/lib/dependencies/WorkletDependency.js +6 -9
- package/lib/errors/HookWebpackError.js +3 -2
- package/lib/hmr/LazyCompilationPlugin.js +3 -5
- package/lib/html/HtmlGenerator.js +61 -82
- package/lib/html/HtmlModulesPlugin.js +88 -139
- package/lib/html/HtmlParser.js +97 -141
- package/lib/html/data.js +21 -0
- package/lib/html/htmlMinify.js +10 -11
- package/lib/html/syntax.js +883 -993
- package/lib/index.js +46 -3
- package/lib/javascript/ChunkFormatHelpers.js +4 -3
- package/lib/javascript/JavascriptGenerator.js +8 -1
- package/lib/javascript/JavascriptModulesPlugin.js +21 -48
- package/lib/javascript/JavascriptParser.js +721 -178
- package/lib/javascript/parser.js +6 -0
- package/lib/javascript/syntax.js +420 -92
- package/lib/json/JsonGenerator.js +7 -1
- package/lib/library/ModuleLibraryPlugin.js +64 -136
- package/lib/loaders/LoaderRunner.js +137 -9
- package/lib/node/NodeWatchFileSystem.js +3 -9
- package/lib/optimize/AggressiveMergingPlugin.js +3 -5
- package/lib/optimize/ConcatenatedModule.js +81 -100
- package/lib/optimize/FlagIncludedChunksPlugin.js +3 -11
- package/lib/optimize/InnerGraphPlugin.js +7 -13
- package/lib/optimize/LimitChunkCountPlugin.js +5 -8
- package/lib/optimize/MangleExportsPlugin.js +3 -4
- package/lib/optimize/ModuleConcatenationPlugin.js +3 -4
- package/lib/optimize/SideEffectsFlagPlugin.js +7 -19
- package/lib/optimize/SplitChunksPlugin.js +2 -4
- package/lib/performance/BroadContextsPlugin.js +1 -1
- package/lib/performance/CacheEffectivenessPlugin.js +3 -4
- package/lib/performance/SizeLimitsPlugin.js +2 -4
- package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +6 -8
- package/lib/prefetch/ResourceHintPlugin.js +17 -21
- package/lib/prefetch/StartupAssetHintRuntimeModule.js +7 -10
- package/lib/runtime/AsyncModuleRuntimeModule.js +3 -5
- package/lib/runtime/GetChunkFilenameRuntimeModule.js +3 -4
- package/lib/runtime/GlobalRuntimeModule.js +2 -4
- package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +55 -85
- package/lib/schemes/DataUriPlugin.js +3 -6
- package/lib/schemes/VirtualUrlPlugin.js +1 -1
- package/lib/serialization/BinaryMiddleware.js +9 -9
- package/lib/serialization/FileMiddleware.js +16 -16
- package/lib/serialization/ObjectMiddleware.js +30 -33
- package/lib/stats/DefaultStatsFactoryPlugin.js +3 -4
- package/lib/typescript/TypeScriptPlugin.js +2 -3
- package/lib/url/URLParserPlugin.js +6 -8
- package/lib/util/LocConverter.js +4 -7
- package/lib/util/SourceProcessor.js +15 -22
- package/lib/util/chainedImports.js +3 -4
- package/lib/util/concatenate.js +4 -4
- package/lib/util/createHooksRegistry.js +1 -2
- package/lib/util/dataURL.js +2 -3
- package/lib/util/deterministicGrouping.js +8 -13
- package/lib/util/findGraphRoots.js +6 -13
- package/lib/util/globUtils.js +1 -1
- package/lib/util/hash/wasm-hash.js +3 -4
- package/lib/util/internalSerializables.js +1 -1
- package/lib/util/semver.js +5 -3
- package/lib/wasm-async/AsyncWebAssemblyGenerator.js +6 -1
- package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +5 -1
- package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +3 -4
- package/lib/wasm-sync/WebAssemblyGenerator.js +6 -1
- package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +5 -1
- package/lib/wasm-sync/WebAssemblyUtils.js +2 -4
- package/package.json +30 -23
- package/types.d.ts +299 -280
package/lib/javascript/syntax.js
CHANGED
|
@@ -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
|
-
//
|
|
98
|
-
//
|
|
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
|
|
150
|
-
//
|
|
151
|
-
//
|
|
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
|
|
166
|
-
//
|
|
167
|
-
//
|
|
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
|
-
//
|
|
190
|
-
//
|
|
191
|
-
//
|
|
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
|
-
//
|
|
1835
|
-
// content-checked
|
|
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
|
-
//
|
|
1848
|
-
// to literal text
|
|
1849
|
-
// more number literals than distinct raws
|
|
1850
|
-
// too, so serving them from one shared string cuts
|
|
1851
|
-
// retained AST strings. Same rules as WORD_CACHE:
|
|
1852
|
-
// lengths V8 stores flat
|
|
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
|
|
2002
|
-
//
|
|
2003
|
-
//
|
|
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
|
|
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
|
|
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
|
-
//
|
|
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
|
-
//
|
|
2513
|
-
// `
|
|
2514
|
-
//
|
|
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
|
|
2616
|
-
// replaces the megamorphic
|
|
2617
|
-
//
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
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)
|
|
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
|
-
|
|
6754
|
-
/** @type {
|
|
6755
|
-
|
|
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)
|
|
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
|
-
|
|
7098
|
-
|
|
7099
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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;
|