@depup/webpack 5.109.2-depup.0 → 5.110.3-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/changes.json +7 -7
- package/lib/APIPlugin.js +123 -17
- package/lib/AsyncDependenciesBlock.js +10 -7
- package/lib/AutomaticPrefetchPlugin.js +1 -1
- package/lib/BannerPlugin.js +10 -6
- package/lib/CacheFacade.js +6 -6
- package/lib/Chunk.js +14 -11
- package/lib/ChunkGraph.js +46 -35
- package/lib/ChunkGroup.js +7 -7
- package/lib/ChunkTemplate.js +35 -44
- package/lib/CircularModulesPlugin.js +205 -28
- package/lib/CleanPlugin.js +4 -7
- package/lib/CodeGenerationResults.js +11 -8
- package/lib/CompatibilityPlugin.js +7 -7
- package/lib/Compilation.js +688 -409
- package/lib/Compiler.js +53 -38
- package/lib/ConcatenationScope.js +107 -8
- package/lib/ConditionalInitFragment.js +3 -3
- package/lib/ConstPlugin.js +13 -11
- package/lib/ContextExclusionPlugin.js +1 -1
- package/lib/ContextModule.js +146 -54
- package/lib/ContextModuleFactory.js +46 -14
- package/lib/ContextReplacementPlugin.js +12 -14
- package/lib/DefinePlugin.js +121 -37
- package/lib/DependenciesBlock.js +9 -6
- package/lib/Dependency.js +36 -16
- package/lib/DependencyTemplate.js +11 -12
- package/lib/DependencyTemplates.js +3 -3
- package/lib/DotenvPlugin.js +91 -26
- package/lib/DynamicEntryPlugin.js +8 -4
- package/lib/EntryOptionPlugin.js +8 -4
- package/lib/EntryPlugin.js +2 -2
- package/lib/Entrypoint.js +6 -2
- package/lib/EnvironmentPlugin.js +2 -2
- package/lib/EvalDevToolModulePlugin.js +8 -4
- package/lib/EvalSourceMapDevToolPlugin.js +15 -8
- package/lib/ExportsInfo.js +111 -14
- package/lib/ExportsInfoApiPlugin.js +2 -4
- package/lib/ExternalModule.js +232 -77
- package/lib/ExternalModuleFactoryPlugin.js +97 -38
- package/lib/ExternalsPlugin.js +10 -6
- package/lib/FileSystemInfo.js +44 -70
- package/lib/FlagAllModulesAsUsedPlugin.js +2 -3
- package/lib/FlagDependencyExportsPlugin.js +76 -19
- package/lib/FlagDependencyUsagePlugin.js +40 -49
- package/lib/FlagEntryExportAsUsedPlugin.js +1 -1
- package/lib/Generator.js +36 -15
- package/lib/HotModuleReplacementPlugin.js +16 -44
- package/lib/IgnorePlugin.js +8 -4
- package/lib/IgnoreWarningsPlugin.js +2 -2
- package/lib/InitFragment.js +8 -4
- package/lib/JavascriptMetaInfoPlugin.js +35 -4
- package/lib/LazyBarrel.js +3 -4
- package/lib/LibraryTemplatePlugin.js +10 -6
- package/lib/LoaderOptionsPlugin.js +7 -3
- package/lib/LoaderTargetPlugin.js +1 -1
- package/lib/MainTemplate.js +49 -42
- package/lib/ManifestPlugin.js +12 -11
- package/lib/Module.js +62 -33
- package/lib/ModuleFactory.js +3 -3
- package/lib/ModuleFilenameHelpers.js +9 -4
- package/lib/ModuleGraph.js +195 -21
- package/lib/ModuleGraphConnection.js +6 -13
- package/lib/ModuleInfoHeaderPlugin.js +8 -10
- package/lib/ModuleTemplate.js +62 -63
- package/lib/MultiCompiler.js +130 -64
- package/lib/MultiStats.js +40 -9
- package/lib/MultiWatching.js +3 -3
- package/lib/NoEmitOnErrorsPlugin.js +1 -1
- package/lib/NodeStuffPlugin.js +29 -19
- package/lib/NormalModule.js +152 -103
- package/lib/NormalModuleFactory.js +555 -110
- package/lib/NormalModuleReplacementPlugin.js +5 -8
- package/lib/NullFactory.js +6 -2
- package/lib/OptionsApply.js +7 -3
- package/lib/Parser.js +7 -3
- package/lib/PlatformPlugin.js +2 -2
- package/lib/PrefetchPlugin.js +1 -1
- package/lib/ProgressPlugin.js +16 -13
- package/lib/ProvidePlugin.js +3 -5
- package/lib/RawModule.js +25 -17
- package/lib/RecordIdsPlugin.js +3 -3
- package/lib/RequestShortener.js +1 -1
- package/lib/ResolverFactory.js +2 -2
- package/lib/RuntimeGlobals.js +22 -10
- package/lib/RuntimeModule.js +29 -19
- package/lib/RuntimePlugin.js +335 -169
- package/lib/RuntimeTemplate.js +2761 -316
- package/lib/SelfModuleFactory.js +7 -3
- package/lib/SourceMapDevToolModuleOptionsPlugin.js +6 -2
- package/lib/SourceMapDevToolPlugin.js +30 -20
- package/lib/Stats.js +3 -4
- package/lib/Template.js +32 -22
- package/lib/TemplatedPathPlugin.js +96 -14
- package/lib/UseStrictPlugin.js +4 -6
- package/lib/WarnCaseSensitiveModulesPlugin.js +4 -4
- package/lib/WarnDeprecatedOptionPlugin.js +1 -1
- package/lib/WarnNoModeSetPlugin.js +1 -1
- package/lib/WatchIgnorePlugin.js +8 -6
- package/lib/Watching.js +8 -8
- package/lib/WebpackIsIncludedPlugin.js +2 -4
- package/lib/WebpackOptionsApply.js +308 -18
- package/lib/WebpackOptionsDefaulter.js +6 -2
- package/lib/asset/AssetBytesGenerator.js +12 -10
- package/lib/asset/AssetBytesParser.js +2 -4
- package/lib/asset/AssetGenerator.js +188 -95
- package/lib/asset/AssetModule.js +7 -3
- package/lib/asset/AssetModulesPlugin.js +110 -38
- package/lib/asset/AssetParser.js +9 -7
- package/lib/asset/AssetSourceGenerator.js +60 -13
- package/lib/asset/AssetSourceParser.js +2 -4
- package/lib/asset/RawDataUrlModule.js +24 -16
- package/lib/asset/WebManifestGenerator.js +8 -10
- package/lib/asset/WebManifestParser.js +24 -10
- package/lib/async-modules/AsyncModuleHelpers.js +12 -6
- package/lib/async-modules/AwaitDependenciesInitFragment.js +2 -2
- package/lib/async-modules/InferAsyncModulesPlugin.js +2 -2
- package/lib/async-modules/isGeneratorLowered.js +4 -4
- package/lib/buildChunkGraph.js +36 -27
- package/lib/bun/BunTargetPlugin.js +1 -1
- package/lib/cache/AddBuildDependenciesPlugin.js +1 -1
- package/lib/cache/AddManagedPathsPlugin.js +1 -1
- package/lib/cache/IdleFileCachePlugin.js +2 -2
- package/lib/cache/MemoryCachePlugin.js +18 -10
- package/lib/cache/MemoryWithGcCachePlugin.js +34 -22
- package/lib/cache/PackFileCacheStrategy.js +30 -23
- package/lib/cache/ResolverCachePlugin.js +38 -18
- package/lib/cache/getLazyHashedEtag.js +1 -2
- package/lib/cache/mergeEtags.js +1 -1
- package/lib/cli.js +1 -3
- package/lib/config/browserslistTargetHandler.js +41 -5
- package/lib/config/defaults.js +270 -78
- package/lib/config/defineConfig.js +10 -2
- package/lib/config/getClaimedAssetTypes.js +65 -0
- package/lib/config/normalization.js +46 -16
- package/lib/config/target.js +46 -3
- package/lib/container/ContainerEntryDependency.js +1 -1
- package/lib/container/ContainerEntryModule.js +24 -15
- package/lib/container/ContainerEntryModuleFactory.js +7 -3
- package/lib/container/ContainerPlugin.js +9 -10
- package/lib/container/ContainerReferencePlugin.js +6 -2
- package/lib/container/FallbackDependency.js +1 -1
- package/lib/container/FallbackModule.js +24 -17
- package/lib/container/FallbackModuleFactory.js +7 -3
- package/lib/container/HoistContainerReferencesPlugin.js +6 -11
- package/lib/container/ModuleFederationPlugin.js +7 -24
- package/lib/container/RemoteModule.js +27 -19
- package/lib/container/RemoteRuntimeModule.js +10 -8
- package/lib/container/moduleFederationHooks.js +32 -0
- package/lib/css/CssGenerator.js +171 -43
- package/lib/css/CssInjectStyleRuntimeModule.js +7 -5
- package/lib/css/CssLoadingRuntimeModule.js +84 -32
- package/lib/css/CssModule.js +10 -7
- package/lib/css/CssModulesPlugin.js +172 -100
- package/lib/css/CssParser.js +1113 -568
- package/lib/css/CssServerStylesRuntimeModule.js +54 -0
- package/lib/css/cssMinify.js +168 -0
- package/lib/css/data.js +5334 -0
- package/lib/css/syntax.js +9647 -232
- package/lib/debug/ProfilingPlugin.js +14 -9
- package/lib/deno/DenoTargetPlugin.js +1 -1
- package/lib/dependencies/AMDDefineDependency.js +112 -87
- package/lib/dependencies/AMDDefineDependencyParserPlugin.js +30 -17
- package/lib/dependencies/AMDPlugin.js +9 -7
- package/lib/dependencies/AMDRequireArrayDependency.js +5 -5
- package/lib/dependencies/AMDRequireContextDependency.js +2 -2
- package/lib/dependencies/AMDRequireDependenciesBlock.js +1 -1
- package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +25 -14
- package/lib/dependencies/AMDRequireDependency.js +8 -7
- package/lib/dependencies/AMDRequireItemDependency.js +1 -1
- package/lib/dependencies/AMDRuntimeModules.js +21 -1
- package/lib/dependencies/BuildTimeConstDependency.js +102 -0
- package/lib/dependencies/CachedConstDependency.js +11 -8
- package/lib/dependencies/CommonJsDependencyHelpers.js +67 -46
- package/lib/dependencies/CommonJsExportRequireDependency.js +121 -45
- package/lib/dependencies/CommonJsExportsDependency.js +53 -49
- package/lib/dependencies/CommonJsExportsParserPlugin.js +207 -25
- package/lib/dependencies/CommonJsFullRequireDependency.js +119 -34
- package/lib/dependencies/CommonJsImportsParserPlugin.js +100 -50
- package/lib/dependencies/CommonJsObjectExportDependency.js +188 -0
- package/lib/dependencies/CommonJsPlugin.js +35 -6
- package/lib/dependencies/CommonJsRequireContextDependency.js +5 -6
- package/lib/dependencies/CommonJsRequireDependency.js +170 -27
- package/lib/dependencies/CommonJsSelfReferenceDependency.js +63 -38
- package/lib/dependencies/ConstDependency.js +8 -9
- package/lib/dependencies/ContextDependency.js +12 -8
- package/lib/dependencies/ContextDependencyHelpers.js +14 -9
- package/lib/dependencies/ContextDependencyTemplateAsId.js +4 -4
- package/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +24 -11
- package/lib/dependencies/ContextElementDependency.js +31 -12
- package/lib/dependencies/CreateRequireParserPlugin.js +12 -7
- package/lib/dependencies/CreateScriptUrlDependency.js +4 -4
- package/lib/dependencies/CssIcssExportDependency.js +56 -28
- package/lib/dependencies/CssIcssImportDependency.js +17 -13
- package/lib/dependencies/CssIcssSymbolDependency.js +9 -10
- package/lib/dependencies/CssImportDependency.js +18 -9
- package/lib/dependencies/CssUrlDependency.js +17 -13
- package/lib/dependencies/DllEntryDependency.js +1 -1
- package/lib/dependencies/DynamicExports.js +2 -2
- package/lib/dependencies/ExportBindingInitFragment.js +36 -9
- package/lib/dependencies/ExportsInfoDependency.js +7 -8
- package/lib/dependencies/ExternalModuleDependency.js +9 -5
- package/lib/dependencies/ExternalModuleInitFragment.js +2 -2
- package/lib/dependencies/ExternalModuleInitFragmentDependency.js +8 -5
- package/lib/dependencies/HarmonyAcceptDependency.js +5 -5
- package/lib/dependencies/HarmonyCompatibilityDependency.js +52 -17
- package/lib/dependencies/HarmonyDetectionParserPlugin.js +11 -7
- package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +23 -14
- package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +80 -12
- package/lib/dependencies/HarmonyExportExpressionDependency.js +23 -18
- package/lib/dependencies/HarmonyExportHeaderDependency.js +7 -7
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +286 -80
- package/lib/dependencies/HarmonyExportInitFragment.js +18 -6
- package/lib/dependencies/HarmonyExportSpecifierDependency.js +51 -14
- package/lib/dependencies/HarmonyExports.js +7 -4
- package/lib/dependencies/HarmonyImportDependency.js +121 -60
- package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +124 -38
- package/lib/dependencies/HarmonyImportGuard.js +20 -30
- package/lib/dependencies/HarmonyImportSideEffectDependency.js +152 -9
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +97 -49
- package/lib/dependencies/HarmonyModulesPlugin.js +7 -3
- package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +1 -3
- package/lib/dependencies/HtmlEntryDependency.js +49 -31
- package/lib/dependencies/HtmlInlineHtmlDependency.js +7 -8
- package/lib/dependencies/HtmlInlineScriptDependency.js +11 -8
- package/lib/dependencies/HtmlInlineStyleDependency.js +7 -10
- package/lib/dependencies/HtmlSourceDependency.js +22 -14
- package/lib/dependencies/ImportContextDependency.js +45 -5
- package/lib/dependencies/ImportDependency.js +33 -50
- package/lib/dependencies/ImportEagerDependency.js +6 -9
- package/lib/dependencies/ImportMetaContextDependency.js +2 -2
- package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +14 -13
- package/lib/dependencies/ImportMetaContextPlugin.js +7 -3
- package/lib/dependencies/ImportMetaGlobDependency.js +2 -2
- package/lib/dependencies/ImportMetaGlobDependencyParserPlugin.js +2 -3
- package/lib/dependencies/ImportMetaGlobHelpers.js +19 -22
- package/lib/dependencies/ImportMetaHotAcceptDependency.js +1 -1
- package/lib/dependencies/ImportMetaHotDeclineDependency.js +1 -1
- package/lib/dependencies/ImportMetaPlugin.js +154 -71
- package/lib/dependencies/ImportMetaResolveDependency.js +3 -4
- package/lib/dependencies/ImportParserPlugin.js +73 -49
- package/lib/dependencies/ImportPhase.js +12 -5
- package/lib/dependencies/ImportPlugin.js +7 -3
- package/lib/dependencies/ImportWeakDependency.js +6 -9
- package/lib/dependencies/JsonExportsDependency.js +11 -7
- package/lib/dependencies/LoaderDependency.js +2 -2
- package/lib/dependencies/LoaderImportDependency.js +2 -2
- package/lib/dependencies/LoaderPlugin.js +11 -7
- package/lib/dependencies/LocalModuleDependency.js +5 -5
- package/lib/dependencies/LocalModulesHelpers.js +1 -1
- package/lib/dependencies/ModuleDecoratorDependency.js +6 -7
- package/lib/dependencies/ModuleDependency.js +9 -6
- package/lib/dependencies/ModuleDependencyTemplateAsId.js +4 -4
- package/lib/dependencies/ModuleDependencyTemplateAsRequireId.js +3 -3
- package/lib/dependencies/ModuleHotAcceptDependency.js +1 -1
- package/lib/dependencies/ModuleHotDeclineDependency.js +1 -1
- package/lib/dependencies/ModuleInitFragmentDependency.js +24 -10
- package/lib/dependencies/NullDependency.js +3 -3
- package/lib/dependencies/ProvidedDependency.js +14 -10
- package/lib/dependencies/PureExpressionDependency.js +9 -10
- package/lib/dependencies/RequireContextDependency.js +2 -2
- package/lib/dependencies/RequireContextDependencyParserPlugin.js +2 -4
- package/lib/dependencies/RequireContextPlugin.js +8 -4
- package/lib/dependencies/RequireEnsureDependenciesBlock.js +2 -2
- package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +5 -8
- package/lib/dependencies/RequireEnsureDependency.js +8 -7
- package/lib/dependencies/RequireEnsurePlugin.js +7 -3
- package/lib/dependencies/RequireHeaderDependency.js +50 -12
- package/lib/dependencies/RequireIncludeDependency.js +6 -6
- package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +2 -3
- package/lib/dependencies/RequireIncludePlugin.js +7 -3
- package/lib/dependencies/RequireJsStuffPlugin.js +7 -3
- package/lib/dependencies/RequireResolveContextDependency.js +2 -2
- package/lib/dependencies/RequireResolveDependency.js +4 -4
- package/lib/dependencies/RequireResolveHeaderDependency.js +4 -4
- package/lib/dependencies/RuntimeRequirementsDependency.js +5 -6
- package/lib/dependencies/StaticExportsDependency.js +2 -2
- package/lib/dependencies/SystemPlugin.js +10 -6
- package/lib/dependencies/SystemRuntimeModule.js +10 -0
- package/lib/dependencies/TopLevelAwaitDependency.js +11 -7
- package/lib/dependencies/URLContextDependency.js +2 -2
- package/lib/dependencies/URLDependency.js +110 -64
- package/lib/dependencies/URLPlugin.js +7 -3
- package/lib/dependencies/UnsupportedDependency.js +4 -4
- package/lib/dependencies/WebAssemblyExportImportedDependency.js +3 -4
- package/lib/dependencies/WebAssemblyImportDependency.js +5 -5
- package/lib/dependencies/WebpackIsIncludedDependency.js +6 -6
- package/lib/dependencies/WorkerAndWorkletPlugin.js +47 -28
- package/lib/dependencies/WorkerDependency.js +22 -22
- package/lib/dependencies/WorkletDependency.js +18 -21
- package/lib/dependencies/getFunctionExpression.js +8 -4
- package/lib/dependencies/importOptionsCheck.js +47 -0
- package/lib/dependencies/processExportInfo.js +5 -5
- package/lib/dll/DelegatedModule.js +34 -22
- package/lib/dll/DelegatedModuleFactoryPlugin.js +15 -7
- package/lib/dll/DelegatedPlugin.js +2 -2
- package/lib/dll/DllEntryPlugin.js +2 -2
- package/lib/dll/DllModule.js +22 -15
- package/lib/dll/DllModuleFactory.js +7 -3
- package/lib/dll/DllPlugin.js +7 -5
- package/lib/dll/DllReferencePlugin.js +10 -7
- package/lib/dll/LibManifestPlugin.js +5 -5
- package/lib/electron/ElectronTargetPlugin.js +53 -49
- package/lib/errors/AsyncChunkWaterfallWarning.js +36 -0
- package/lib/errors/AsyncDependencyToInitialChunkError.js +2 -2
- package/lib/errors/BroadContextsWarning.js +43 -0
- package/lib/errors/BuildCycleError.js +1 -1
- package/lib/errors/CacheEffectivenessWarning.js +55 -0
- package/lib/errors/ChunkRenderError.js +1 -1
- package/lib/errors/CircularDependenciesWarning.js +38 -0
- package/lib/errors/CodeGenerationError.js +1 -1
- package/lib/errors/CommentCompilationWarning.js +1 -1
- package/lib/errors/ConflictingResourceHintsWarning.js +35 -0
- package/lib/errors/DotenvFileError.js +29 -0
- package/lib/errors/DuplicateModulesWarning.js +45 -0
- package/lib/errors/DynamicExportsWarning.js +30 -0
- package/lib/errors/EmbeddedSourceMapsWarning.js +25 -0
- package/lib/errors/EntrypointOverlapWarning.js +45 -0
- package/lib/errors/EnvironmentNotSupportAsyncWarning.js +2 -2
- package/lib/errors/EvalUsageWarning.js +28 -0
- package/lib/errors/HookWebpackError.js +5 -5
- package/lib/errors/HotspotsWarning.js +57 -0
- package/lib/errors/IgnoreErrorModuleFactory.js +7 -3
- package/lib/errors/ImportedBindingAssignmentError.js +30 -0
- package/lib/errors/InlinedAssetsWarning.js +36 -0
- package/lib/errors/InvalidDependenciesModuleWarning.js +1 -1
- package/lib/errors/LargeModulesWarning.js +45 -0
- package/lib/errors/LegacyJavascriptWarning.js +48 -0
- package/lib/errors/MissingSideEffectsWarning.js +36 -0
- package/lib/errors/MixedExportsWarning.js +41 -0
- package/lib/errors/ModuleDependencyError.js +13 -16
- package/lib/errors/ModuleDependencyWarning.js +5 -15
- package/lib/errors/ModuleHashingError.js +1 -1
- package/lib/errors/ModuleNotFoundError.js +2 -2
- package/lib/errors/ModuleParseError.js +1 -2
- package/lib/errors/ModuleRestoreError.js +1 -1
- package/lib/errors/ModuleStoreError.js +1 -1
- package/lib/errors/NodeStuffInWebError.js +1 -1
- package/lib/errors/OsDependentRuleWarning.js +31 -0
- package/lib/errors/PureAnnotationsWarning.js +36 -0
- package/lib/errors/RedundantDynamicImportWarning.js +31 -0
- package/lib/errors/ScopeHoistingBailoutsWarning.js +41 -0
- package/lib/errors/SplitChunksCappedWarning.js +41 -0
- package/lib/errors/TinyChunksWarning.js +40 -0
- package/lib/errors/TopLevelThisWarning.js +34 -0
- package/lib/errors/UnsplitVendorsWarning.js +42 -0
- package/lib/errors/UnsupportedFeatureWarning.js +1 -1
- package/lib/errors/UnusedAliasesWarning.js +29 -0
- package/lib/errors/UnusedDefinesWarning.js +29 -0
- package/lib/errors/UnusedExternalsWarning.js +29 -0
- package/lib/errors/UnusedReexportsWarning.js +42 -0
- package/lib/errors/UnusedRuleWarning.js +29 -0
- package/lib/errors/WebpackError.js +9 -5
- package/lib/errors/deriveStackFromNestedError.js +90 -0
- package/lib/esm/ExportWebpackRequireRuntimeModule.js +2 -0
- package/lib/esm/ModuleChunkFormatPlugin.js +37 -19
- package/lib/esm/ModuleChunkLoadingPlugin.js +86 -51
- package/lib/esm/ModuleChunkLoadingRuntimeModule.js +161 -62
- package/lib/hmr/HotModuleReplacement.runtime.js +24 -5
- package/lib/hmr/HotModuleReplacementRuntimeModule.js +1 -1
- package/lib/hmr/LazyCompilationPlugin.js +45 -24
- package/lib/hmr/lazyCompilationBackend.js +9 -6
- package/lib/hmr/parserHooks.js +56 -0
- package/lib/html/HtmlGenerator.js +277 -77
- package/lib/html/HtmlModule.js +7 -3
- package/lib/html/HtmlModulesPlugin.js +366 -200
- package/lib/html/HtmlParser.js +31 -86
- package/lib/html/data.js +1928 -0
- package/lib/html/htmlMinify.js +288 -0
- package/lib/html/syntax.js +6034 -1384
- package/lib/ids/ChunkModuleIdRangePlugin.js +3 -3
- package/lib/ids/DeterministicChunkIdsPlugin.js +1 -1
- package/lib/ids/DeterministicModuleIdsPlugin.js +2 -2
- package/lib/ids/HashedModuleIdsPlugin.js +6 -2
- package/lib/ids/IdHelpers.js +7 -8
- package/lib/ids/NamedChunkIdsPlugin.js +1 -1
- package/lib/ids/NamedModuleIdsPlugin.js +1 -1
- package/lib/ids/NaturalChunkIdsPlugin.js +2 -2
- package/lib/ids/NaturalModuleIdsPlugin.js +1 -1
- package/lib/ids/OccurrenceChunkIdsPlugin.js +7 -3
- package/lib/ids/OccurrenceModuleIdsPlugin.js +7 -3
- package/lib/ids/SyncModuleIdsPlugin.js +4 -4
- package/lib/index.js +10 -0
- package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +3 -3
- package/lib/javascript/BasicEvaluatedExpression.js +18 -14
- package/lib/javascript/ChunkFormatHelpers.js +6 -6
- package/lib/javascript/ChunkHelpers.js +1 -1
- package/lib/javascript/CommonJsChunkFormatPlugin.js +11 -5
- package/lib/javascript/EnableChunkLoadingPlugin.js +2 -2
- package/lib/javascript/JavascriptGenerator.js +65 -165
- package/lib/javascript/JavascriptModule.js +9 -3
- package/lib/javascript/JavascriptModulesPlugin.js +103 -123
- package/lib/javascript/JavascriptParser.js +242 -99
- package/lib/javascript/JavascriptParserHelpers.js +10 -7
- package/lib/javascript/ScopeAnalyzer.js +1094 -0
- package/lib/javascript/StartupHelpers.js +55 -9
- package/lib/javascript/syntax.js +2678 -232
- package/lib/json/JsonData.js +8 -4
- package/lib/json/JsonGenerator.js +38 -16
- package/lib/json/JsonModule.js +7 -3
- package/lib/json/JsonModulesPlugin.js +1 -1
- package/lib/json/JsonParser.js +5 -6
- package/lib/library/AbstractLibraryPlugin.js +20 -14
- package/lib/library/AmdLibraryPlugin.js +11 -7
- package/lib/library/AssignLibraryPlugin.js +19 -13
- package/lib/library/EnableLibraryPlugin.js +2 -2
- package/lib/library/ExportPropertyLibraryPlugin.js +15 -8
- package/lib/library/JsonpLibraryPlugin.js +11 -7
- package/lib/library/ModuleLibraryPlugin.js +256 -64
- package/lib/library/SystemLibraryPlugin.js +12 -8
- package/lib/library/UmdLibraryPlugin.js +62 -25
- package/lib/loaders/LoaderRunner.js +47 -6
- package/lib/loaders/loadLoader.js +8 -4
- package/lib/logging/createConsoleLogger.js +7 -4
- package/lib/node/CommonJsChunkLoadingPlugin.js +36 -22
- package/lib/node/NodeEnvironmentPlugin.js +17 -3
- package/lib/node/NodeSourcePlugin.js +1 -1
- package/lib/node/NodeTargetPlugin.js +4 -3
- package/lib/node/NodeTemplatePlugin.js +1 -1
- package/lib/node/NodeWatchFileSystem.js +70 -9
- package/lib/node/ReadFileChunkLoadingRuntimeModule.js +35 -38
- package/lib/node/ReadFileCompileAsyncWasmPlugin.js +65 -19
- package/lib/node/ReadFileCompileWasmPlugin.js +28 -16
- package/lib/node/RequireChunkLoadingRuntimeModule.js +35 -38
- package/lib/node/nodeConsole.js +7 -3
- package/lib/optimize/AggressiveMergingPlugin.js +2 -2
- package/lib/optimize/AggressiveSplittingPlugin.js +9 -6
- package/lib/optimize/ConcatenatedModule.js +1030 -476
- package/lib/optimize/ConstExportsPlugin.js +16 -7
- package/lib/optimize/EnsureChunkConditionsPlugin.js +3 -3
- package/lib/optimize/FlagIncludedChunksPlugin.js +3 -4
- package/lib/optimize/InlineExports.js +130 -5
- package/lib/optimize/InnerGraph.js +28 -12
- package/lib/optimize/InnerGraphPlugin.js +23 -18
- package/lib/optimize/LimitChunkCountPlugin.js +7 -3
- package/lib/optimize/MangleExportsPlugin.js +7 -8
- package/lib/optimize/MergeDuplicateChunksPlugin.js +7 -3
- package/lib/optimize/MinChunkSizePlugin.js +7 -3
- package/lib/optimize/ModuleConcatenationPlugin.js +51 -35
- package/lib/optimize/RealContentHashPlugin.js +121 -41
- package/lib/optimize/RemoveEmptyChunksPlugin.js +2 -2
- package/lib/optimize/RemoveParentModulesPlugin.js +4 -4
- package/lib/optimize/RuntimeChunkPlugin.js +2 -2
- package/lib/optimize/SideEffectsFlagPlugin.js +262 -39
- package/lib/optimize/SplitChunksPlugin.js +86 -24
- package/lib/performance/AssetsOverSizeLimitWarning.js +10 -2
- package/lib/performance/AsyncChunkWaterfallsPlugin.js +136 -0
- package/lib/performance/BroadContextsPlugin.js +142 -0
- package/lib/performance/CacheEffectivenessPlugin.js +125 -0
- package/lib/performance/ConflictingResourceHintsPlugin.js +99 -0
- package/lib/performance/DuplicateModulesPlugin.js +93 -0
- package/lib/performance/DuplicatePackagesPlugin.js +119 -0
- package/lib/performance/DuplicatePackagesWarning.js +84 -0
- package/lib/performance/DynamicExportsPlugin.js +120 -0
- package/lib/performance/EmbeddedSourceMapsPlugin.js +71 -0
- package/lib/performance/EntrypointOverlapPlugin.js +122 -0
- package/lib/performance/EntrypointsOverSizeLimitWarning.js +1 -1
- package/lib/performance/EvalUsagePlugin.js +115 -0
- package/lib/performance/HotspotsPlugin.js +296 -0
- package/lib/performance/InlinedAssetsPlugin.js +99 -0
- package/lib/performance/LargeModulesPlugin.js +126 -0
- package/lib/performance/LegacyJavascriptPlugin.js +139 -0
- package/lib/performance/MissingSideEffectsPlugin.js +138 -0
- package/lib/performance/MixedExportsPlugin.js +136 -0
- package/lib/performance/OsDependentRuleWarningPlugin.js +178 -0
- package/lib/performance/PureAnnotationsPlugin.js +219 -0
- package/lib/performance/RedundantDynamicImportsPlugin.js +225 -0
- package/lib/performance/RuntimeInLargeChunkWarning.js +27 -0
- package/lib/performance/ScopeHoistingBailoutsPlugin.js +164 -0
- package/lib/performance/SizeLimitsPlugin.js +139 -7
- package/lib/performance/SplitChunksCappedPlugin.js +99 -0
- package/lib/performance/TinyChunksPlugin.js +128 -0
- package/lib/performance/TopLevelThisPlugin.js +208 -0
- package/lib/performance/UnsplitVendorsPlugin.js +112 -0
- package/lib/performance/UnusedAliasesPlugin.js +253 -0
- package/lib/performance/UnusedDefinesPlugin.js +87 -0
- package/lib/performance/UnusedExternalsPlugin.js +110 -0
- package/lib/performance/UnusedReexportsPlugin.js +159 -0
- package/lib/performance/UnusedRuleWarningPlugin.js +105 -0
- package/lib/performance/getModuleSize.js +22 -0
- package/lib/performance/getSourceModules.js +22 -0
- package/lib/performance/hasOnlyUnusedExports.js +40 -0
- package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +24 -10
- package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +63 -46
- package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +2 -3
- package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +2 -2
- package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +2 -2
- package/lib/prefetch/ResourceHintPlugin.js +295 -79
- package/lib/prefetch/ResourceHintRuntimeModule.js +1 -21
- package/lib/prefetch/StartupAssetHintRuntimeModule.js +10 -133
- package/lib/prefetch/parseResourceHintOptions.js +31 -4
- package/lib/rules/BasicEffectRulePlugin.js +2 -2
- package/lib/rules/BasicMatcherRulePlugin.js +8 -4
- package/lib/rules/GlobMatcherRulePlugin.js +68 -0
- package/lib/rules/ObjectMatcherRulePlugin.js +12 -5
- package/lib/rules/RuleSetCompiler.js +146 -12
- package/lib/rules/UseEffectRulePlugin.js +18 -11
- package/lib/runtime/AsyncModuleGeneratorRuntimeModule.js +11 -1
- package/lib/runtime/AsyncModuleRuntimeModule.js +6 -2
- package/lib/runtime/AutoPublicPathRuntimeModule.js +15 -20
- package/lib/runtime/BaseUriRuntimeModule.js +33 -7
- package/lib/runtime/ChunkNameRuntimeModule.js +10 -0
- package/lib/runtime/CompatGetDefaultExportRuntimeModule.js +11 -1
- package/lib/runtime/CompatRuntimeModule.js +5 -3
- package/lib/runtime/ConcatenationWrapRuntimeModule.js +90 -0
- package/lib/runtime/ConstructRequireRuntimeModule.js +52 -0
- package/lib/runtime/CreateFakeNamespaceObjectRuntimeModule.js +8 -6
- package/lib/runtime/CreateScriptRuntimeModule.js +11 -1
- package/lib/runtime/CreateScriptUrlRuntimeModule.js +11 -1
- package/lib/runtime/DefinePropertyGettersRuntimeModule.js +56 -38
- package/lib/runtime/EnsureChunkRuntimeModule.js +18 -2
- package/lib/runtime/GetChunkFilenameRuntimeModule.js +62 -37
- package/lib/runtime/GetFullHashRuntimeModule.js +12 -2
- package/lib/runtime/GetMainFilenameRuntimeModule.js +12 -2
- package/lib/runtime/GetTrustedTypesPolicyRuntimeModule.js +2 -2
- package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +16 -3
- package/lib/runtime/GlobalRuntimeModule.js +18 -0
- package/lib/runtime/HasOwnPropertyRuntimeModule.js +12 -2
- package/lib/runtime/LoadScriptRuntimeModule.js +2 -2
- package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +34 -7
- package/lib/runtime/MakeNamespaceObjectRuntimeModule.js +22 -6
- package/lib/runtime/NonceRuntimeModule.js +10 -0
- package/lib/runtime/OnChunksLoadedRuntimeModule.js +5 -3
- package/lib/runtime/PublicPathRuntimeModule.js +12 -2
- package/lib/runtime/RelativeUrlRuntimeModule.js +11 -1
- package/lib/runtime/RuntimeIdRuntimeModule.js +12 -2
- package/lib/runtime/SetAnonymousDefaultNameRuntimeModule.js +11 -1
- package/lib/runtime/StartupChunkDependenciesPlugin.js +18 -9
- package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +3 -3
- package/lib/runtime/StartupEntrypointRuntimeModule.js +21 -4
- package/lib/runtime/SystemContextRuntimeModule.js +10 -0
- package/lib/runtime/ToBinaryRuntimeModule.js +1 -1
- package/lib/runtime/WorkerRuntimeModule.js +11 -1
- package/lib/runtime/baseUri.js +63 -0
- package/lib/schemes/DataUriPlugin.js +1 -1
- package/lib/schemes/FileUriPlugin.js +1 -1
- package/lib/schemes/HttpUriPlugin.js +46 -20
- package/lib/schemes/VirtualUrlPlugin.js +13 -7
- package/lib/serialization/AggregateErrorSerializer.js +1 -1
- package/lib/serialization/BinaryMiddleware.js +4 -4
- package/lib/serialization/ErrorObjectSerializer.js +1 -1
- package/lib/serialization/FileMiddleware.js +22 -9
- package/lib/serialization/ObjectMiddleware.js +139 -114
- package/lib/serialization/PlainObjectSerializer.js +19 -16
- package/lib/sharing/ConsumeSharedModule.js +30 -21
- package/lib/sharing/ConsumeSharedPlugin.js +18 -10
- package/lib/sharing/ConsumeSharedRuntimeModule.js +6 -9
- package/lib/sharing/ProvideSharedModule.js +25 -16
- package/lib/sharing/ProvideSharedModuleFactory.js +7 -3
- package/lib/sharing/ProvideSharedPlugin.js +8 -4
- package/lib/sharing/SharePlugin.js +17 -5
- package/lib/sharing/ShareRuntimeModule.js +4 -4
- package/lib/sharing/resolveMatchedConfigs.js +9 -6
- package/lib/sharing/utils.js +1 -3
- package/lib/stats/DefaultStatsFactoryPlugin.js +50 -29
- package/lib/stats/DefaultStatsPresetPlugin.js +17 -8
- package/lib/stats/DefaultStatsPrinterPlugin.js +36 -26
- package/lib/stats/StatsFactory.js +25 -26
- package/lib/stats/StatsPrinter.js +16 -12
- package/lib/typescript/TypeScriptPlugin.js +20 -24
- package/lib/url/URLParserPlugin.js +26 -13
- package/lib/util/ArrayQueue.js +3 -3
- package/lib/util/AsyncQueue.js +4 -3
- package/lib/util/Hash.js +5 -1
- package/lib/util/LazySet.js +35 -22
- package/lib/util/LocConverter.js +36 -13
- package/lib/util/SourceProcessor.js +1066 -24
- package/lib/util/StringXor.js +1 -1
- package/lib/util/URLAbsoluteSpecifier.js +3 -1
- package/lib/util/chainedImports.js +9 -5
- package/lib/util/cleverMerge.js +1 -1
- package/lib/util/comparators.js +45 -14
- package/lib/util/concatenate.js +203 -77
- package/lib/util/conventions.js +10 -2
- package/lib/util/createHash.js +2 -2
- package/lib/util/createHooksRegistry.js +8 -10
- package/lib/util/createMappings.js +25 -3
- package/lib/util/dataURL.js +225 -1
- package/lib/util/extractSourceMap.js +4 -3
- package/lib/util/findCaseMismatch.js +139 -0
- package/lib/util/formatLocation.js +1 -2
- package/lib/util/fs.js +22 -5
- package/lib/util/globUtils.js +298 -24
- package/lib/util/hash/BatchedHash.js +5 -1
- package/lib/util/hash/BulkUpdateHash.js +5 -1
- package/lib/util/hash/DebugHash.js +5 -1
- package/lib/util/hash/hash-digest.js +6 -2
- package/lib/util/identifier.js +4 -0
- package/lib/util/implicitTypeLoaderFallback.js +1 -1
- package/lib/util/internalSerializables.js +8 -0
- package/lib/util/lazyModule.js +56 -0
- package/lib/util/makeSerializable.js +7 -3
- package/lib/util/matchAlias.js +25 -0
- package/lib/util/mimeTypes.js +11 -5
- package/lib/util/nonNumericOnlyHash.js +4 -3
- package/lib/util/parseJson.js +5 -3
- package/lib/util/preloadModuleType.js +32 -0
- package/lib/util/registerExternalSerializer.js +7 -5
- package/lib/util/removeBOM.js +82 -1
- package/lib/util/runtime.js +2 -2
- package/lib/util/semver.js +1 -1
- package/lib/util/serialization.js +28 -28
- package/lib/util/source.js +2 -2
- package/lib/util/traverseDestructuringAssignmentProperties.js +6 -2
- package/lib/wasm/EnableWasmLoadingPlugin.js +10 -8
- package/lib/wasm/wasmModuleFilename.js +54 -0
- package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +43 -21
- package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +45 -21
- package/lib/wasm-async/AsyncWasmModule.js +3 -3
- package/lib/wasm-async/AsyncWebAssemblyGenerator.js +4 -5
- package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +57 -17
- package/lib/wasm-async/AsyncWebAssemblyModulesPlugin.js +34 -18
- package/lib/wasm-async/AsyncWebAssemblyParser.js +9 -8
- package/lib/wasm-async/UniversalCompileAsyncWasmPlugin.js +29 -8
- package/lib/wasm-sync/SyncWasmModule.js +2 -2
- package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +18 -13
- package/lib/wasm-sync/WasmFinalizeExportsPlugin.js +4 -5
- package/lib/wasm-sync/WebAssemblyGenerator.js +18 -17
- package/lib/wasm-sync/WebAssemblyInInitialChunkError.js +4 -4
- package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +7 -7
- package/lib/wasm-sync/WebAssemblyModulesPlugin.js +24 -11
- package/lib/wasm-sync/WebAssemblyParser.js +4 -6
- package/lib/wasm-sync/WebAssemblyUtils.js +2 -2
- package/lib/web/FetchCompileAsyncWasmPlugin.js +105 -19
- package/lib/web/FetchCompileWasmPlugin.js +48 -16
- package/lib/web/JsonpChunkLoadingPlugin.js +47 -23
- package/lib/web/JsonpChunkLoadingRuntimeModule.js +50 -20
- package/lib/web/JsonpTemplatePlugin.js +2 -2
- package/lib/webpack.js +22 -11
- package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +60 -26
- package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +30 -32
- package/lib/webworker/WebWorkerTemplatePlugin.js +1 -1
- package/module.d.ts +1 -0
- package/package.json +32 -25
- package/schemas/WebpackOptions.check.js +1 -1
- package/schemas/WebpackOptions.json +667 -34
- package/schemas/plugins/HtmlParserOptions.check.js +1 -1
- package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
- package/schemas/plugins/container/ContainerPlugin.json +10 -0
- package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
- package/schemas/plugins/container/ModuleFederationPlugin.json +10 -0
- package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +1 -1
- package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
- package/schemas/plugins/css/CssParserOptions.check.js +1 -1
- package/types.d.ts +3223 -465
- package/lib/runtime/CommonJsWrapRuntimeModule.js +0 -37
package/lib/javascript/syntax.js
CHANGED
|
@@ -75,24 +75,30 @@ const stringToNumber = (str, isLegacyOctal) =>
|
|
|
75
75
|
*/
|
|
76
76
|
const stringToBigInt = (str) => BigInt(str.replace(/_/g, ""));
|
|
77
77
|
|
|
78
|
-
/**
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
78
|
+
/**
|
|
79
|
+
* @import {
|
|
80
|
+
* Options,
|
|
81
|
+
* Position,
|
|
82
|
+
* Node,
|
|
83
|
+
* Identifier,
|
|
84
|
+
* ImportAttribute,
|
|
85
|
+
* ImportDefaultSpecifier,
|
|
86
|
+
* ImportExpression,
|
|
87
|
+
* Expression,
|
|
88
|
+
* TokenType
|
|
89
|
+
* } from "acorn"
|
|
90
|
+
*/
|
|
86
91
|
/** @typedef {import("acorn").ImportSpecifier | import("acorn").ImportDefaultSpecifier | import("acorn").ImportNamespaceSpecifier} AnyImportSpecifier */
|
|
87
|
-
/** @typedef {
|
|
88
|
-
/** @typedef {TokenType & { beforeExpr: boolean, isAssign?: boolean, prefix?: boolean, postfix?: boolean, binop: number | null, updateContext?: (prevType: TokenType) => void }} TokenTypeInternal acorn's internal TokenType fields, absent from its public types */
|
|
89
|
-
/** @typedef {import("estree").SourceLocation} SourceLocation */
|
|
92
|
+
/** @typedef {TokenType & { beforeExpr: boolean, isAssign?: boolean, prefix?: boolean, postfix?: boolean, binop: number | null, updateContext: ((prevType: TokenType) => void) | null }} TokenTypeInternal acorn's internal TokenType fields, absent from its public types */
|
|
90
93
|
/** @typedef {[number, number]} Range */
|
|
91
94
|
/** @typedef {"defer" | "source"} ImportPhase */
|
|
92
95
|
/** @typedef {import("estree").Comment & { start: number, end: number }} CollectedComment comment as JavascriptParser exposes it */
|
|
93
96
|
|
|
94
97
|
// Symbol-keyed so they stay out of for-in, Object.keys and JSON.stringify
|
|
95
98
|
// over AST nodes.
|
|
99
|
+
// Per-TokContext "the owned token loop must step aside" flag, cached on the
|
|
100
|
+
// context itself so the hot guard reads one slot instead of two.
|
|
101
|
+
const kSlowContext = Symbol("slow context");
|
|
96
102
|
const kSource = Symbol("source");
|
|
97
103
|
const kRange = Symbol("range");
|
|
98
104
|
const kText = Symbol("text");
|
|
@@ -102,12 +108,23 @@ const kTextStart = Symbol("text start");
|
|
|
102
108
|
const LEGACY_ASSERT_ATTRIBUTES = Symbol("assert");
|
|
103
109
|
|
|
104
110
|
// acorn's binding types and scope flags, stable across acorn 8
|
|
111
|
+
const BIND_NONE = 0;
|
|
105
112
|
const BIND_VAR = 1;
|
|
106
113
|
const BIND_LEXICAL = 2;
|
|
114
|
+
const BIND_OUTSIDE = 5;
|
|
107
115
|
const SCOPE_TOP = 1;
|
|
116
|
+
const SCOPE_FUNCTION = 2;
|
|
117
|
+
const SCOPE_ASYNC = 4;
|
|
118
|
+
const SCOPE_GENERATOR = 8;
|
|
119
|
+
const SCOPE_ARROW = 16;
|
|
108
120
|
const SCOPE_SIMPLE_CATCH = 32;
|
|
109
121
|
// SCOPE_TOP | SCOPE_FUNCTION | SCOPE_CLASS_STATIC_BLOCK
|
|
122
|
+
const SCOPE_SWITCH = 1024;
|
|
110
123
|
const SCOPE_VAR = 0b100000011;
|
|
124
|
+
// acorn's parseFunction statement bit flags
|
|
125
|
+
const FUNC_STATEMENT = 1;
|
|
126
|
+
const FUNC_HANGING_STATEMENT = 2;
|
|
127
|
+
const FUNC_NULLABLE_ID = 4;
|
|
111
128
|
|
|
112
129
|
// ASCII identifier-continuation chars ($ 0-9 A-Z _ a-z); css/html-style
|
|
113
130
|
// Uint8Array table so the tokenizer fast path is one load per char
|
|
@@ -142,6 +159,18 @@ SIMPLE_PUNCT[123] = tokTypes.braceL;
|
|
|
142
159
|
SIMPLE_PUNCT[125] = tokTypes.braceR;
|
|
143
160
|
SIMPLE_PUNCT[58] = tokTypes.colon;
|
|
144
161
|
|
|
162
|
+
// Characters that can only start a token which cannot continue an expression,
|
|
163
|
+
// so an atom directly followed by one is the whole expression (see
|
|
164
|
+
// `parseMaybeAssign`'s fast path). `}` included: it only ever closes a block,
|
|
165
|
+
// an object or a template substitution.
|
|
166
|
+
const EXPRESSION_END_CHAR = new Uint8Array(128);
|
|
167
|
+
EXPRESSION_END_CHAR[41] = 1; // )
|
|
168
|
+
EXPRESSION_END_CHAR[44] = 1; // ,
|
|
169
|
+
EXPRESSION_END_CHAR[58] = 1; // :
|
|
170
|
+
EXPRESSION_END_CHAR[59] = 1; // ;
|
|
171
|
+
EXPRESSION_END_CHAR[93] = 1; // ]
|
|
172
|
+
EXPRESSION_END_CHAR[125] = 1; // }
|
|
173
|
+
|
|
145
174
|
// Char classification for the owned `nextToken` (yuku's ws_class): one table
|
|
146
175
|
// load steers both the whitespace skip loop and the token dispatch. Token
|
|
147
176
|
// classes sort below CLS_SPACE so the skip loop exits on a single compare.
|
|
@@ -631,6 +660,235 @@ class PropertyNode {
|
|
|
631
660
|
}
|
|
632
661
|
}
|
|
633
662
|
|
|
663
|
+
/**
|
|
664
|
+
* Single-shape `ForStatement`.
|
|
665
|
+
*/
|
|
666
|
+
class ForStatementNode {
|
|
667
|
+
/**
|
|
668
|
+
* @param {number} start start offset
|
|
669
|
+
* @param {number} end end offset
|
|
670
|
+
* @param {Node | null} init init statement or expression
|
|
671
|
+
* @param {Expression | null} test loop condition
|
|
672
|
+
* @param {Expression | null} update update expression
|
|
673
|
+
* @param {Node} body loop body
|
|
674
|
+
*/
|
|
675
|
+
constructor(start, end, init, test, update, body) {
|
|
676
|
+
this.type = "ForStatement";
|
|
677
|
+
this.start = start;
|
|
678
|
+
this.end = end;
|
|
679
|
+
this.init = init;
|
|
680
|
+
this.test = test;
|
|
681
|
+
this.update = update;
|
|
682
|
+
this.body = body;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* Single-shape `ForInStatement` (no `await` slot, matching acorn).
|
|
688
|
+
*/
|
|
689
|
+
class ForInStatementNode {
|
|
690
|
+
/**
|
|
691
|
+
* @param {number} start start offset
|
|
692
|
+
* @param {number} end end offset
|
|
693
|
+
* @param {Node} left loop target
|
|
694
|
+
* @param {Expression} right iterated expression
|
|
695
|
+
* @param {Node} body loop body
|
|
696
|
+
*/
|
|
697
|
+
constructor(start, end, left, right, body) {
|
|
698
|
+
this.type = "ForInStatement";
|
|
699
|
+
this.start = start;
|
|
700
|
+
this.end = end;
|
|
701
|
+
this.left = left;
|
|
702
|
+
this.right = right;
|
|
703
|
+
this.body = body;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* Single-shape `ForOfStatement`; `await` leads, matching acorn's write order.
|
|
709
|
+
*/
|
|
710
|
+
class ForOfStatementNode {
|
|
711
|
+
/**
|
|
712
|
+
* @param {number} start start offset
|
|
713
|
+
* @param {number} end end offset
|
|
714
|
+
* @param {boolean} isAwait whether this is `for await`
|
|
715
|
+
* @param {Node} left loop target
|
|
716
|
+
* @param {Expression} right iterated expression
|
|
717
|
+
* @param {Node} body loop body
|
|
718
|
+
*/
|
|
719
|
+
constructor(start, end, isAwait, left, right, body) {
|
|
720
|
+
this.type = "ForOfStatement";
|
|
721
|
+
this.start = start;
|
|
722
|
+
this.end = end;
|
|
723
|
+
this.await = isAwait;
|
|
724
|
+
this.left = left;
|
|
725
|
+
this.right = right;
|
|
726
|
+
this.body = body;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* Single-shape `WhileStatement`.
|
|
732
|
+
*/
|
|
733
|
+
class WhileStatementNode {
|
|
734
|
+
/**
|
|
735
|
+
* @param {number} start start offset
|
|
736
|
+
* @param {number} end end offset
|
|
737
|
+
* @param {Expression} test loop condition
|
|
738
|
+
* @param {Node} body loop body
|
|
739
|
+
*/
|
|
740
|
+
constructor(start, end, test, body) {
|
|
741
|
+
this.type = "WhileStatement";
|
|
742
|
+
this.start = start;
|
|
743
|
+
this.end = end;
|
|
744
|
+
this.test = test;
|
|
745
|
+
this.body = body;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* Single-shape `SwitchStatement`.
|
|
751
|
+
*/
|
|
752
|
+
class SwitchStatementNode {
|
|
753
|
+
/**
|
|
754
|
+
* @param {number} start start offset
|
|
755
|
+
* @param {number} end end offset
|
|
756
|
+
* @param {Expression} discriminant switched expression
|
|
757
|
+
* @param {Node[]} cases case clauses
|
|
758
|
+
*/
|
|
759
|
+
constructor(start, end, discriminant, cases) {
|
|
760
|
+
this.type = "SwitchStatement";
|
|
761
|
+
this.start = start;
|
|
762
|
+
this.end = end;
|
|
763
|
+
this.discriminant = discriminant;
|
|
764
|
+
this.cases = cases;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
/**
|
|
769
|
+
* Pre-shaped `SwitchCase`: filled in acorn's write order (`consequent` before
|
|
770
|
+
* `test`), finished via `finishNode` like acorn's.
|
|
771
|
+
*/
|
|
772
|
+
class SwitchCaseNode {
|
|
773
|
+
/**
|
|
774
|
+
* @param {number} start start offset
|
|
775
|
+
*/
|
|
776
|
+
constructor(start) {
|
|
777
|
+
this.type = "";
|
|
778
|
+
this.start = start;
|
|
779
|
+
this.end = 0;
|
|
780
|
+
/** @type {Node[] | null} */
|
|
781
|
+
this.consequent = null;
|
|
782
|
+
/** @type {Expression | null} */
|
|
783
|
+
this.test = null;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
/**
|
|
788
|
+
* Single-shape `ThrowStatement`.
|
|
789
|
+
*/
|
|
790
|
+
class ThrowStatementNode {
|
|
791
|
+
/**
|
|
792
|
+
* @param {number} start start offset
|
|
793
|
+
* @param {number} end end offset
|
|
794
|
+
* @param {Expression} argument thrown expression
|
|
795
|
+
*/
|
|
796
|
+
constructor(start, end, argument) {
|
|
797
|
+
this.type = "ThrowStatement";
|
|
798
|
+
this.start = start;
|
|
799
|
+
this.end = end;
|
|
800
|
+
this.argument = argument;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* Single-shape `BreakStatement`/`ContinueStatement` — identical field sets, so
|
|
806
|
+
* both node types share one hidden class.
|
|
807
|
+
*/
|
|
808
|
+
class BreakContinueNode {
|
|
809
|
+
/**
|
|
810
|
+
* @param {number} start start offset
|
|
811
|
+
* @param {number} end end offset
|
|
812
|
+
* @param {"BreakStatement" | "ContinueStatement"} type node type
|
|
813
|
+
* @param {Identifier | null} label target label
|
|
814
|
+
*/
|
|
815
|
+
constructor(start, end, type, label) {
|
|
816
|
+
this.type = type;
|
|
817
|
+
this.start = start;
|
|
818
|
+
this.end = end;
|
|
819
|
+
this.label = label;
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Single-shape `TryStatement`.
|
|
825
|
+
*/
|
|
826
|
+
class TryStatementNode {
|
|
827
|
+
/**
|
|
828
|
+
* @param {number} start start offset
|
|
829
|
+
* @param {number} end end offset
|
|
830
|
+
* @param {Node} block try block
|
|
831
|
+
* @param {Node | null} handler catch clause
|
|
832
|
+
* @param {Node | null} finalizer finally block
|
|
833
|
+
*/
|
|
834
|
+
constructor(start, end, block, handler, finalizer) {
|
|
835
|
+
this.type = "TryStatement";
|
|
836
|
+
this.start = start;
|
|
837
|
+
this.end = end;
|
|
838
|
+
this.block = block;
|
|
839
|
+
this.handler = handler;
|
|
840
|
+
this.finalizer = finalizer;
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* Single-shape `CatchClause`.
|
|
846
|
+
*/
|
|
847
|
+
class CatchClauseNode {
|
|
848
|
+
/**
|
|
849
|
+
* @param {number} start start offset
|
|
850
|
+
* @param {number} end end offset
|
|
851
|
+
* @param {Node | null} param catch parameter
|
|
852
|
+
* @param {Node} body catch block
|
|
853
|
+
*/
|
|
854
|
+
constructor(start, end, param, body) {
|
|
855
|
+
this.type = "CatchClause";
|
|
856
|
+
this.start = start;
|
|
857
|
+
this.end = end;
|
|
858
|
+
this.param = param;
|
|
859
|
+
this.body = body;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* Pre-shaped `FunctionDeclaration`/`FunctionExpression`/
|
|
865
|
+
* `ArrowFunctionExpression`: acorn fills function nodes through shared
|
|
866
|
+
* subroutines (`parseFunctionParams`/`parseFunctionBody`), so like
|
|
867
|
+
* `PropertyNode` the fields are all declared up-front — in acorn's exact write
|
|
868
|
+
* order (`initFunction` assigns `expression` before `generator`) so JSON key
|
|
869
|
+
* order is unchanged — and acorn's writes land in existing slots: one hidden
|
|
870
|
+
* class for all three function node types, no transitions.
|
|
871
|
+
*/
|
|
872
|
+
class FunctionNode {
|
|
873
|
+
/**
|
|
874
|
+
* @param {number} start start offset
|
|
875
|
+
*/
|
|
876
|
+
constructor(start) {
|
|
877
|
+
this.type = "";
|
|
878
|
+
this.start = start;
|
|
879
|
+
this.end = 0;
|
|
880
|
+
/** @type {Identifier | null} */
|
|
881
|
+
this.id = null;
|
|
882
|
+
this.expression = false;
|
|
883
|
+
this.generator = false;
|
|
884
|
+
this.async = false;
|
|
885
|
+
/** @type {Node[] | null} */
|
|
886
|
+
this.params = null;
|
|
887
|
+
/** @type {Node | null} */
|
|
888
|
+
this.body = null;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
634
892
|
/**
|
|
635
893
|
* Single-shape `SpreadElement`/`RestElement` — identical field sets, so both
|
|
636
894
|
* node types share one hidden class.
|
|
@@ -650,6 +908,10 @@ class RestSpreadNode {
|
|
|
650
908
|
}
|
|
651
909
|
}
|
|
652
910
|
|
|
911
|
+
// Mirrors of acorn's module-level `loopLabel`/`switchLabel`.
|
|
912
|
+
const LOOP_LABEL = { kind: "loop" };
|
|
913
|
+
const SWITCH_LABEL = { kind: "switch" };
|
|
914
|
+
|
|
653
915
|
// Shared zero-length arguments array for `new X` without parens, mirroring
|
|
654
916
|
// acorn's module-level `empty`.
|
|
655
917
|
/** @type {Expression[]} */
|
|
@@ -715,7 +977,18 @@ for (const NodeClass of [
|
|
|
715
977
|
TemplateElementNode,
|
|
716
978
|
ObjectNode,
|
|
717
979
|
PropertyNode,
|
|
718
|
-
RestSpreadNode
|
|
980
|
+
RestSpreadNode,
|
|
981
|
+
FunctionNode,
|
|
982
|
+
ForStatementNode,
|
|
983
|
+
ForInStatementNode,
|
|
984
|
+
ForOfStatementNode,
|
|
985
|
+
WhileStatementNode,
|
|
986
|
+
SwitchStatementNode,
|
|
987
|
+
SwitchCaseNode,
|
|
988
|
+
ThrowStatementNode,
|
|
989
|
+
BreakContinueNode,
|
|
990
|
+
TryStatementNode,
|
|
991
|
+
CatchClauseNode
|
|
719
992
|
]) {
|
|
720
993
|
for (const key of ["range"]) {
|
|
721
994
|
Object.defineProperty(
|
|
@@ -729,8 +1002,9 @@ for (const NodeClass of [
|
|
|
729
1002
|
|
|
730
1003
|
/**
|
|
731
1004
|
* Comment collected without slicing its text out of the source: only magic
|
|
732
|
-
* comments and pure annotations ever get their text read,
|
|
733
|
-
*
|
|
1005
|
+
* comments and pure annotations ever get their text read, and only binary
|
|
1006
|
+
* searches around magic-comment sites read `range`, so the text slice and the
|
|
1007
|
+
* range array are both deferred to first access and memoized like `loc`.
|
|
734
1008
|
*/
|
|
735
1009
|
class LazyComment {
|
|
736
1010
|
/**
|
|
@@ -745,12 +1019,30 @@ class LazyComment {
|
|
|
745
1019
|
this.type = block ? "Block" : "Line";
|
|
746
1020
|
this.start = start;
|
|
747
1021
|
this.end = end;
|
|
748
|
-
/** @type {Range} */
|
|
749
|
-
this.range = [start, end];
|
|
750
1022
|
this[kSource] = source;
|
|
751
1023
|
this[kTextStart] = textStart;
|
|
752
1024
|
}
|
|
753
1025
|
|
|
1026
|
+
/**
|
|
1027
|
+
* Memoized like `LazyLocNode#range`; offsets are final at construction so
|
|
1028
|
+
* the slot is cached unconditionally.
|
|
1029
|
+
* @returns {Range} source range
|
|
1030
|
+
*/
|
|
1031
|
+
get range() {
|
|
1032
|
+
const cached = this[kRange];
|
|
1033
|
+
if (cached !== undefined) return cached;
|
|
1034
|
+
/** @type {Range} */
|
|
1035
|
+
const range = [this.start, this.end];
|
|
1036
|
+
return (this[kRange] = range);
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
/**
|
|
1040
|
+
* @param {Range} value source range
|
|
1041
|
+
*/
|
|
1042
|
+
set range(value) {
|
|
1043
|
+
this[kRange] = value;
|
|
1044
|
+
}
|
|
1045
|
+
|
|
754
1046
|
/**
|
|
755
1047
|
* @returns {string} comment text without the delimiters
|
|
756
1048
|
*/
|
|
@@ -825,9 +1117,10 @@ class Scope {
|
|
|
825
1117
|
* parseLiteral: (value: unknown) => Node,
|
|
826
1118
|
* awaitIdentPos: number,
|
|
827
1119
|
* lastTokStart: number,
|
|
1120
|
+
* lastTokStartLoc?: Position,
|
|
828
1121
|
* yieldPos: number,
|
|
829
1122
|
* awaitPos: number,
|
|
830
|
-
* parseExpression: () => Expression,
|
|
1123
|
+
* parseExpression: (forInit?: boolean | string, refDestructuringErrors?: DestructuringErrorsShim | null) => Expression,
|
|
831
1124
|
* parseSpread: (refDestructuringErrors?: DestructuringErrorsShim | null) => Node,
|
|
832
1125
|
* braceIsBlock: (prevType: TokenType) => boolean,
|
|
833
1126
|
* _gapHasNewline: () => boolean,
|
|
@@ -839,10 +1132,11 @@ class Scope {
|
|
|
839
1132
|
* checkPatternErrors: (refDestructuringErrors: DestructuringErrorsShim, isAssign: boolean) => void,
|
|
840
1133
|
* checkYieldAwaitInDefaultParams: () => void,
|
|
841
1134
|
* checkExpressionErrors: (refDestructuringErrors?: DestructuringErrorsShim | null, andThrow?: boolean) => boolean,
|
|
842
|
-
* parseSubscript: (base: Expression, startPos: number, startLoc: Position | undefined, noCalls: boolean | undefined, maybeAsyncArrow: boolean, optionalChained: boolean, forInit
|
|
1135
|
+
* parseSubscript: (base: Expression, startPos: number, startLoc: Position | undefined, noCalls: boolean | undefined, maybeAsyncArrow: boolean, optionalChained: boolean, forInit?: boolean | string) => Expression,
|
|
843
1136
|
* parseExprAtom: (refDestructuringErrors?: DestructuringErrorsShim | null, forInit?: boolean | string, forNew?: boolean) => Expression,
|
|
844
1137
|
* buildBinary: (startPos: number, startLoc: Position | undefined, left: Expression, right: Expression, op: string, logical: boolean) => Expression,
|
|
845
1138
|
* parseMaybeAssign: (forInit?: boolean | string, refDestructuringErrors?: DestructuringErrorsShim | null, afterLeftParse?: (this: unknown, left: Expression, startPos: number, startLoc?: Position) => Expression) => Expression,
|
|
1139
|
+
* _parseTrivialAtom: (forInit?: boolean | string) => Expression | null,
|
|
846
1140
|
* parseMaybeConditional: (forInit?: boolean | string, refDestructuringErrors?: DestructuringErrorsShim | null) => Expression,
|
|
847
1141
|
* parseMaybeUnary: (refDestructuringErrors: DestructuringErrorsShim | null, sawUnary: boolean, incDec: boolean, forInit?: boolean | string) => Expression,
|
|
848
1142
|
* parseExprSubscripts: (refDestructuringErrors?: DestructuringErrorsShim | null, forInit?: boolean | string) => Expression,
|
|
@@ -874,6 +1168,18 @@ class Scope {
|
|
|
874
1168
|
* _propHashDepth: number,
|
|
875
1169
|
* _acquireDestructuringErrors: () => DestructuringErrorsShim,
|
|
876
1170
|
* _releaseDestructuringErrors: () => void,
|
|
1171
|
+
* _arrStack: EXPECTED_ANY[][],
|
|
1172
|
+
* _arrDepth: number,
|
|
1173
|
+
* _acquireScratch: () => EXPECTED_ANY[],
|
|
1174
|
+
* _releaseScratch: (scratch: EXPECTED_ANY[], count: number) => EXPECTED_ANY[],
|
|
1175
|
+
* parseRestBinding: () => Node,
|
|
1176
|
+
* parseBindingListItem: (param: Node) => Node,
|
|
1177
|
+
* parseAssignableListItem: (allowModifiers?: boolean) => Node,
|
|
1178
|
+
* parseParenItem: (item: Expression | Node) => Expression,
|
|
1179
|
+
* shouldParseArrow: (exprList: Expression[]) => boolean,
|
|
1180
|
+
* parseParenArrowList: (startPos: number, startLoc: Position | undefined, exprList: Expression[], forInit?: boolean | string) => Expression,
|
|
1181
|
+
* finishNodeAt: (node: Node, type: string, pos: number, loc?: Position) => Node,
|
|
1182
|
+
* parseParenAndDistinguishExpression: (canBeArrow: boolean, forInit?: boolean | string) => Expression,
|
|
877
1183
|
* parseSubscripts: (base: Expression, startPos: number, startLoc: Position | undefined, noCalls?: boolean, forInit?: boolean | string) => Expression,
|
|
878
1184
|
* parseNew: () => Expression,
|
|
879
1185
|
* parseTemplateElement: (opts: { isTagged: boolean }) => Node,
|
|
@@ -890,7 +1196,9 @@ class Scope {
|
|
|
890
1196
|
* parseFunction: (node: Node, statement: number, allowExpressionBody?: boolean, isAsync?: boolean, forInit?: boolean | string) => Expression,
|
|
891
1197
|
* parseArrowExpression: (node: Node, params: Node[], isAsync: boolean, forInit?: boolean | string) => Expression,
|
|
892
1198
|
* _subscriptFastPath: boolean,
|
|
893
|
-
* checkLValSimple: (expr: Node, bindingType?: number) => void,
|
|
1199
|
+
* checkLValSimple: (expr: Node, bindingType?: number, checkClashes?: Record<string, boolean> | null) => void,
|
|
1200
|
+
* checkLValInnerPattern: (expr: Node, bindingType?: number, checkClashes?: Record<string, boolean> | null) => void,
|
|
1201
|
+
* declareName: (name: string, bindingType: number, pos: number) => void,
|
|
894
1202
|
* startNode: () => Node,
|
|
895
1203
|
* startNodeAt: (pos: number, loc?: Position) => Node,
|
|
896
1204
|
* finishNode: (node: Node, type: string) => Node,
|
|
@@ -916,6 +1224,7 @@ class Scope {
|
|
|
916
1224
|
* _readNumberCold: (startsWithDot: boolean) => void,
|
|
917
1225
|
* _readRadixNumber: (radix: number) => void,
|
|
918
1226
|
* _readWord1Cold: () => string,
|
|
1227
|
+
* _finishWordSlow: (word: string) => void,
|
|
919
1228
|
* _skipSpaceCold: () => void,
|
|
920
1229
|
* _getUnknownOrPrivate: (code: number) => void,
|
|
921
1230
|
* finishToken: (type: TokenType, value?: unknown) => void,
|
|
@@ -953,6 +1262,20 @@ class Scope {
|
|
|
953
1262
|
* parseExprImport: (forNew: boolean) => Expression,
|
|
954
1263
|
* parseImportMeta: (node: Node) => Expression,
|
|
955
1264
|
* parseDynamicImport: (node: Node) => Expression,
|
|
1265
|
+
* updateContext: (prevType: TokenType) => void,
|
|
1266
|
+
* finishOp: (type: TokenType, size: number) => void,
|
|
1267
|
+
* readToken_dot: () => void,
|
|
1268
|
+
* readToken_slash: () => void,
|
|
1269
|
+
* readToken_mult_modulo_exp: (code: number) => void,
|
|
1270
|
+
* readToken_pipe_amp: (code: number) => void,
|
|
1271
|
+
* readToken_caret: () => void,
|
|
1272
|
+
* readToken_plus_min: (code: number) => void,
|
|
1273
|
+
* readToken_lt_gt: (code: number) => void,
|
|
1274
|
+
* readToken_eq_excl: (code: number) => void,
|
|
1275
|
+
* readToken_question: () => void,
|
|
1276
|
+
* readToken_numberSign: () => void,
|
|
1277
|
+
* _tokenFastPath: boolean,
|
|
1278
|
+
* _inlineFinish: boolean,
|
|
956
1279
|
* _lazy: boolean,
|
|
957
1280
|
* _importPhase: ImportPhase | null,
|
|
958
1281
|
* _importPhasesEnabled: boolean,
|
|
@@ -960,13 +1283,53 @@ class Scope {
|
|
|
960
1283
|
* _newlineBefore: 0 | 1 | 2,
|
|
961
1284
|
* _fullTokenFastPath: boolean,
|
|
962
1285
|
* _stmtFastPath: boolean,
|
|
1286
|
+
* _lastArrow: Expression | null,
|
|
1287
|
+
* _arrowFastPath: boolean,
|
|
1288
|
+
* labels: { kind?: string | null, name?: string, statementStart?: number }[],
|
|
1289
|
+
* initFunction: (node: Node) => void,
|
|
1290
|
+
* parseFunctionStatement: (node: Node, isAsync: boolean, declarationPosition: boolean) => Node,
|
|
1291
|
+
* parseFunctionBody: (node: Node, isArrowFunction: boolean, isMethod: boolean, forInit?: boolean | string) => void,
|
|
1292
|
+
* parseFunctionParams: (node: Node) => void,
|
|
1293
|
+
* isSimpleParamList: (params: Node[]) => boolean,
|
|
1294
|
+
* checkParams: (node: Node, allowDuplicates: boolean) => void,
|
|
1295
|
+
* adaptDirectivePrologue: (statements: Node[]) => void,
|
|
1296
|
+
* toAssignableList: (exprList: Node[], isBinding: boolean) => Node[],
|
|
1297
|
+
* parseBindingList: (close: TokenType, allowEmpty: boolean, allowTrailingComma: boolean, allowModifiers?: boolean) => Node[],
|
|
1298
|
+
* strictDirective: (start: number) => boolean,
|
|
1299
|
+
* _funcFastPath: boolean,
|
|
1300
|
+
* _funcStmtOwn: boolean,
|
|
1301
|
+
* _parseFunctionAt: (start: number, statement: number, allowExpressionBody: boolean, isAsync: boolean, forInit?: boolean | string) => Expression,
|
|
963
1302
|
* isLet: (context?: string | null) => boolean,
|
|
964
1303
|
* parseLabeledStatement: (node: Node, maybeName: string, expr: Identifier, context: string | null) => Node,
|
|
965
|
-
* _parseVarInto: (declarations: Node[], isFor: boolean, kind: string, allowMissingInitializer?: boolean) =>
|
|
1304
|
+
* _parseVarInto: (declarations: Node[], isFor: boolean, kind: string, allowMissingInitializer?: boolean) => number,
|
|
966
1305
|
* _parseVarStatementAt: (start: number, kind: string, allowMissingInitializer?: boolean) => Node,
|
|
967
1306
|
* _parseIfStatementAt: (start: number) => Node,
|
|
968
1307
|
* _parseReturnStatementAt: (start: number) => Node,
|
|
969
1308
|
* _parseExpressionStatementAt: (start: number, expr: Expression) => Node,
|
|
1309
|
+
* eatContextual: (name: string) => boolean,
|
|
1310
|
+
* isUsing: (isFor: boolean) => boolean,
|
|
1311
|
+
* isAwaitUsing: (isFor: boolean) => boolean,
|
|
1312
|
+
* parseForStatement: (node: Node) => Node,
|
|
1313
|
+
* parseFor: (node: Node, init: Node | null) => Node,
|
|
1314
|
+
* parseForIn: (node: Node, init: Node) => Node,
|
|
1315
|
+
* parseForAfterInit: (node: Node, init: Node, awaitAt: number) => Node,
|
|
1316
|
+
* parseWhileStatement: (node: Node) => Node,
|
|
1317
|
+
* parseSwitchStatement: (node: Node) => Node,
|
|
1318
|
+
* parseThrowStatement: (node: Node) => Node,
|
|
1319
|
+
* parseTryStatement: (node: Node) => Node,
|
|
1320
|
+
* parseBreakContinueStatement: (node: Node, keyword: string) => Node,
|
|
1321
|
+
* parseCatchClauseParam: () => Node,
|
|
1322
|
+
* _stmt2FastPath: boolean,
|
|
1323
|
+
* _exprFastPath: boolean,
|
|
1324
|
+
* _parseForStatementAt: (start: number) => Node,
|
|
1325
|
+
* _parseForAt: (start: number, init: Node | null) => Node,
|
|
1326
|
+
* _parseForInAt: (start: number, isAwait: boolean, init: Node) => Node,
|
|
1327
|
+
* _parseForAfterInitAt: (start: number, init: Node, awaitAt: number) => Node,
|
|
1328
|
+
* _parseWhileStatementAt: (start: number) => Node,
|
|
1329
|
+
* _parseSwitchStatementAt: (start: number) => Node,
|
|
1330
|
+
* _parseThrowStatementAt: (start: number) => Node,
|
|
1331
|
+
* _parseTryStatementAt: (start: number) => Node,
|
|
1332
|
+
* _parseBreakContinueStatementAt: (start: number, keyword: string) => Node,
|
|
970
1333
|
* _moduleFallback: boolean,
|
|
971
1334
|
* _moduleSyntaxSeen: boolean,
|
|
972
1335
|
* _tryModuleFallback: () => boolean,
|
|
@@ -1044,6 +1407,10 @@ const createDestructuringErrors = () => {
|
|
|
1044
1407
|
* @property {Map<string, ReservedKind>} reservedKinds identifier name → reserved kind
|
|
1045
1408
|
* @property {number} reservedMaxLen longest key in `reservedKinds`
|
|
1046
1409
|
* @property {{ test: (name: string) => boolean }} reservedBindTest strict-mode binding check, a Set-backed stand-in for acorn's `reservedWordsStrictBind` regexp
|
|
1410
|
+
* @property {Set<string>} reservedBindSet strict-mode binding-reserved names
|
|
1411
|
+
* @property {number} reservedBindMinLen shortest key in `reservedBindSet`
|
|
1412
|
+
* @property {number} reservedBindMaxLen longest key in `reservedBindSet`
|
|
1413
|
+
* @property {number} id owner tag for the shared `WORD_TYPES` classification memo
|
|
1047
1414
|
*/
|
|
1048
1415
|
|
|
1049
1416
|
// One entry per distinct keyword/reserved-word set; webpack parses with a
|
|
@@ -1052,20 +1419,6 @@ const createDestructuringErrors = () => {
|
|
|
1052
1419
|
/** @type {Map<string, WordLookups>} */
|
|
1053
1420
|
const wordLookupsCache = new Map();
|
|
1054
1421
|
|
|
1055
|
-
/**
|
|
1056
|
-
* @param {string} word interned candidate
|
|
1057
|
-
* @param {string} input source code
|
|
1058
|
-
* @param {number} start word start offset
|
|
1059
|
-
* @param {number} len word length (already known equal to `word.length`)
|
|
1060
|
-
* @returns {boolean} whether the source span spells `word`
|
|
1061
|
-
*/
|
|
1062
|
-
const sameWord = (word, input, start, len) => {
|
|
1063
|
-
for (let i = 0; i < len; i++) {
|
|
1064
|
-
if (word.charCodeAt(i) !== input.charCodeAt(start + i)) return false;
|
|
1065
|
-
}
|
|
1066
|
-
return true;
|
|
1067
|
-
};
|
|
1068
|
-
|
|
1069
1422
|
// Direct-mapped identifier cache for `readWord1`: one slot per hash, verified
|
|
1070
1423
|
// by char compare, overwritten on collision. Shared across parses — hits are
|
|
1071
1424
|
// content-checked, so a stale entry is merely a miss. Only words short enough
|
|
@@ -1075,6 +1428,34 @@ const WORD_CACHE_MASK = 0x1fff;
|
|
|
1075
1428
|
const WORD_CACHE = Array.from({ length: WORD_CACHE_MASK + 1 }, () => null);
|
|
1076
1429
|
const WORD_CACHE_MAX_LEN = 12;
|
|
1077
1430
|
|
|
1431
|
+
// Classification memo parallel to `WORD_CACHE`, same slot: every cache write
|
|
1432
|
+
// also writes the word's token type plus the id of the keyword set that
|
|
1433
|
+
// classified it, so a hit skips `classifyWord` and another option set (or a
|
|
1434
|
+
// `readWord1` write, owner 0) invalidates instead of mis-classifying. Keying
|
|
1435
|
+
// by the cache's own slot adds no extra string references — the memo can
|
|
1436
|
+
// never retain a word the cache itself dropped.
|
|
1437
|
+
/** @type {(TokenType | null)[]} */
|
|
1438
|
+
const WORD_TYPES = Array.from({ length: WORD_CACHE_MASK + 1 }, () => null);
|
|
1439
|
+
const WORD_TYPE_OWNERS = new Int32Array(WORD_CACHE_MASK + 1);
|
|
1440
|
+
let nextWordLookupsId = 1;
|
|
1441
|
+
|
|
1442
|
+
/**
|
|
1443
|
+
* Keyword-or-name classification: pure in (word, keywords), so it can be
|
|
1444
|
+
* memoized per `WORD_CACHE` slot.
|
|
1445
|
+
* @param {string} word word
|
|
1446
|
+
* @param {Map<string, TokenType>} keywords keyword name → token type
|
|
1447
|
+
* @returns {TokenType} token type for `word`
|
|
1448
|
+
*/
|
|
1449
|
+
const classifyWord = (word, keywords) => {
|
|
1450
|
+
const len = word.length;
|
|
1451
|
+
// every acorn keyword is 2-10 lowercase ASCII chars (`do`…`instanceof`)
|
|
1452
|
+
if (len >= 2 && len <= 10) {
|
|
1453
|
+
const first = word.charCodeAt(0);
|
|
1454
|
+
if (first >= 97 && first <= 122) return keywords.get(word) || tokTypes.name;
|
|
1455
|
+
}
|
|
1456
|
+
return tokTypes.name;
|
|
1457
|
+
};
|
|
1458
|
+
|
|
1078
1459
|
// Multi-char operator strings for `finishOp` (`=>`, `===`, `&&=`, …), keyed by
|
|
1079
1460
|
// their char codes packed 7 bits apart — collision-free for ASCII operators up
|
|
1080
1461
|
// to acorn's maximum of 4 chars (`>>>=`), so the set stays ~40 entries.
|
|
@@ -1093,9 +1474,9 @@ const VALID_REGEXP_FLAGS = new Map();
|
|
|
1093
1474
|
const getValidRegexpFlags = (ecmaVersion) => {
|
|
1094
1475
|
let flags = VALID_REGEXP_FLAGS.get(ecmaVersion);
|
|
1095
1476
|
if (flags === undefined) {
|
|
1096
|
-
flags = `gim${ecmaVersion >= 6 ? "uy" : ""}${
|
|
1097
|
-
ecmaVersion >=
|
|
1098
|
-
}${ecmaVersion >=
|
|
1477
|
+
flags = `gim${ecmaVersion >= 6 ? "uy" : ""}${ecmaVersion >= 9 ? "s" : ""}${
|
|
1478
|
+
ecmaVersion >= 13 ? "d" : ""
|
|
1479
|
+
}${ecmaVersion >= 15 ? "v" : ""}`;
|
|
1099
1480
|
VALID_REGEXP_FLAGS.set(ecmaVersion, flags);
|
|
1100
1481
|
}
|
|
1101
1482
|
return flags;
|
|
@@ -1172,6 +1553,14 @@ const getWordLookups = (parser) => {
|
|
|
1172
1553
|
// keyword classification wins, matching acorn's keyword-first check
|
|
1173
1554
|
for (const name of keywords.keys()) reservedKinds.set(name, 1);
|
|
1174
1555
|
const reservedBind = wordsRegexpToSet(parser.reservedWordsStrictBind);
|
|
1556
|
+
// length bounds so the owned checkLValSimple can skip the Set probe for
|
|
1557
|
+
// most identifiers
|
|
1558
|
+
let reservedBindMinLen = 0x7fffffff;
|
|
1559
|
+
let reservedBindMaxLen = 0;
|
|
1560
|
+
for (const name of reservedBind) {
|
|
1561
|
+
if (name.length < reservedBindMinLen) reservedBindMinLen = name.length;
|
|
1562
|
+
if (name.length > reservedBindMaxLen) reservedBindMaxLen = name.length;
|
|
1563
|
+
}
|
|
1175
1564
|
let reservedMaxLen = 0;
|
|
1176
1565
|
for (const name of reservedKinds.keys()) {
|
|
1177
1566
|
if (name.length > reservedMaxLen) reservedMaxLen = name.length;
|
|
@@ -1181,7 +1570,11 @@ const getWordLookups = (parser) => {
|
|
|
1181
1570
|
keywords,
|
|
1182
1571
|
reservedKinds,
|
|
1183
1572
|
reservedMaxLen,
|
|
1184
|
-
reservedBindTest: { test: (name) => reservedBind.has(name) }
|
|
1573
|
+
reservedBindTest: { test: (name) => reservedBind.has(name) },
|
|
1574
|
+
reservedBindSet: reservedBind,
|
|
1575
|
+
reservedBindMinLen,
|
|
1576
|
+
reservedBindMaxLen,
|
|
1577
|
+
id: nextWordLookupsId++
|
|
1185
1578
|
};
|
|
1186
1579
|
wordLookupsCache.set(key, lookups);
|
|
1187
1580
|
lastWordLookups = lookups;
|
|
@@ -1260,9 +1653,50 @@ class WebpackParser extends BaseParser {
|
|
|
1260
1653
|
// the owned parseSubscript assumes optional chaining exists (it bakes
|
|
1261
1654
|
// `optional` into the node shape), so gate it on the normalized version
|
|
1262
1655
|
this._subscriptFastPath = lazy && this._ecmaVersion >= 11;
|
|
1656
|
+
const proto = WebpackParser.prototype;
|
|
1657
|
+
const self = /** @type {ParserInternals} */ (/** @type {unknown} */ (this));
|
|
1658
|
+
// the owned per-token loop (nextToken/finishToken/next) also serves the
|
|
1659
|
+
// public non-lazy tokenizer(): locations off, no onToken, and none of the
|
|
1660
|
+
// acorn tokenizer methods it inlines or skips overridden by a plugin
|
|
1661
|
+
// (`nextToken`'s punct/dot/eq shortcuts bypass `getTokenFromCode`,
|
|
1662
|
+
// `finishOp`, `readToken_dot` and `readToken_eq_excl` even when the full
|
|
1663
|
+
// token path below is off, so their overrides must gate this loop too)
|
|
1664
|
+
this._tokenFastPath =
|
|
1665
|
+
lazy ||
|
|
1666
|
+
(this._noLocations &&
|
|
1667
|
+
!normalizedOptions.onToken &&
|
|
1668
|
+
this.nextToken === proto.nextToken &&
|
|
1669
|
+
this.finishToken === proto.finishToken &&
|
|
1670
|
+
this.next === proto.next &&
|
|
1671
|
+
this.skipSpace === proto.skipSpace &&
|
|
1672
|
+
this.getTokenFromCode === proto.getTokenFromCode &&
|
|
1673
|
+
this.finishOp === proto.finishOp &&
|
|
1674
|
+
self.readToken === base.readToken &&
|
|
1675
|
+
self.updateContext === base.updateContext &&
|
|
1676
|
+
self.readToken_dot === base.readToken_dot &&
|
|
1677
|
+
self.readToken_eq_excl === base.readToken_eq_excl);
|
|
1263
1678
|
// the owned getTokenFromCode bakes in every ES2021 operator (?., ??=,
|
|
1264
|
-
// &&=, ...), so it needs at least that version
|
|
1265
|
-
|
|
1679
|
+
// &&=, ...), so it needs at least that version; outside lazy mode it also
|
|
1680
|
+
// bypasses acorn's readToken_* family, so any override there turns it off
|
|
1681
|
+
this._fullTokenFastPath =
|
|
1682
|
+
this._ecmaVersion >= 12 &&
|
|
1683
|
+
(lazy ||
|
|
1684
|
+
(this._tokenFastPath &&
|
|
1685
|
+
self.readToken_slash === base.readToken_slash &&
|
|
1686
|
+
self.readToken_mult_modulo_exp === base.readToken_mult_modulo_exp &&
|
|
1687
|
+
self.readToken_pipe_amp === base.readToken_pipe_amp &&
|
|
1688
|
+
self.readToken_caret === base.readToken_caret &&
|
|
1689
|
+
self.readToken_plus_min === base.readToken_plus_min &&
|
|
1690
|
+
self.readToken_lt_gt === base.readToken_lt_gt &&
|
|
1691
|
+
self.readToken_question === base.readToken_question &&
|
|
1692
|
+
self.readToken_numberSign === base.readToken_numberSign &&
|
|
1693
|
+
self.readRadixNumber === base.readRadixNumber));
|
|
1694
|
+
// the owned nextToken/readWord finish the commonest tokens in place,
|
|
1695
|
+
// which skips this.finishToken: needs the fast token loop (readWord runs
|
|
1696
|
+
// in every mode) and no finishToken override by a plugin
|
|
1697
|
+
this._inlineFinish =
|
|
1698
|
+
this._tokenFastPath &&
|
|
1699
|
+
this.finishToken === WebpackParser.prototype.finishToken;
|
|
1266
1700
|
// whether the gap before the current token holds a line terminator:
|
|
1267
1701
|
// 0 no, 1 yes, 2 unknown (canInsertSemicolon then scans the gap)
|
|
1268
1702
|
/** @type {0 | 1 | 2} */
|
|
@@ -1281,11 +1715,16 @@ class WebpackParser extends BaseParser {
|
|
|
1281
1715
|
/** @type {{ proto: boolean }[]} */
|
|
1282
1716
|
this._propHashStack = [];
|
|
1283
1717
|
this._propHashDepth = 0;
|
|
1718
|
+
// LIFO pool of scratch arrays for list productions: elements are written
|
|
1719
|
+
// by index, then copied out exactly sized — a push-grown array retains
|
|
1720
|
+
// ~17 slots of capacity slack per list otherwise
|
|
1721
|
+
/** @type {unknown[][]} */
|
|
1722
|
+
this._arrStack = [];
|
|
1723
|
+
this._arrDepth = 0;
|
|
1284
1724
|
// `readRegexp`'s flag whitelist depends only on the ecmaVersion
|
|
1285
1725
|
this._validRegexpFlags = getValidRegexpFlags(this._ecmaVersion);
|
|
1286
1726
|
// the owned parseStatement inlines these methods, so a parser plugin
|
|
1287
1727
|
// overriding any of them turns the statement fast path off
|
|
1288
|
-
const proto = WebpackParser.prototype;
|
|
1289
1728
|
this._stmtFastPath =
|
|
1290
1729
|
lazy &&
|
|
1291
1730
|
this.parseVarStatement === proto.parseVarStatement &&
|
|
@@ -1293,6 +1732,62 @@ class WebpackParser extends BaseParser {
|
|
|
1293
1732
|
this.parseIfStatement === proto.parseIfStatement &&
|
|
1294
1733
|
this.parseReturnStatement === proto.parseReturnStatement &&
|
|
1295
1734
|
this.parseExpressionStatement === proto.parseExpressionStatement;
|
|
1735
|
+
// last arrow finished by parseArrowExpression: `expr === this._lastArrow`
|
|
1736
|
+
// replaces the megamorphic `expr.type === "ArrowFunctionExpression"`
|
|
1737
|
+
// probes on the expression spine (arrows are created in exactly one place
|
|
1738
|
+
// and never backtracked, so identity captures the type test)
|
|
1739
|
+
/** @type {Expression | null} */
|
|
1740
|
+
this._lastArrow = null;
|
|
1741
|
+
// arrows must flow through parseArrowExpression for the identity probe;
|
|
1742
|
+
// a plugin overriding it falls back to the type-based probes
|
|
1743
|
+
this._arrowFastPath =
|
|
1744
|
+
lazy && this.parseArrowExpression === proto.parseArrowExpression;
|
|
1745
|
+
// the owned parseFunction/parseFunctionBody inline initFunction and
|
|
1746
|
+
// isSimpleParamList; a plugin overriding either turns the fast path off
|
|
1747
|
+
const internals = /** @type {ParserInternals} */ (
|
|
1748
|
+
/** @type {unknown} */ (this)
|
|
1749
|
+
);
|
|
1750
|
+
this._funcFastPath =
|
|
1751
|
+
lazy &&
|
|
1752
|
+
this._ecmaVersion >= 9 &&
|
|
1753
|
+
internals.initFunction === base.initFunction &&
|
|
1754
|
+
internals.isSimpleParamList === base.isSimpleParamList;
|
|
1755
|
+
// the owned parseStatement inlines parseFunctionStatement's body
|
|
1756
|
+
this._funcStmtOwn =
|
|
1757
|
+
this._funcFastPath &&
|
|
1758
|
+
internals.parseFunctionStatement === base.parseFunctionStatement &&
|
|
1759
|
+
this.parseFunction === proto.parseFunction;
|
|
1760
|
+
// the owned parseStatement inlines these statement parsers too; any
|
|
1761
|
+
// override falls back to acorn's dispatch for these heads
|
|
1762
|
+
this._stmt2FastPath =
|
|
1763
|
+
lazy &&
|
|
1764
|
+
this._ecmaVersion >= 9 &&
|
|
1765
|
+
internals.parseForStatement === base.parseForStatement &&
|
|
1766
|
+
internals.parseFor === base.parseFor &&
|
|
1767
|
+
internals.parseForIn === base.parseForIn &&
|
|
1768
|
+
internals.parseForAfterInit === base.parseForAfterInit &&
|
|
1769
|
+
this.parseVar === proto.parseVar &&
|
|
1770
|
+
internals.parseWhileStatement === base.parseWhileStatement &&
|
|
1771
|
+
internals.parseSwitchStatement === base.parseSwitchStatement &&
|
|
1772
|
+
internals.parseThrowStatement === base.parseThrowStatement &&
|
|
1773
|
+
internals.parseTryStatement === base.parseTryStatement &&
|
|
1774
|
+
internals.parseBreakContinueStatement ===
|
|
1775
|
+
base.parseBreakContinueStatement;
|
|
1776
|
+
// `parseMaybeAssign`'s trivial-atom fast path returns the atom without
|
|
1777
|
+
// descending the seven-layer expression chain, so every layer it skips
|
|
1778
|
+
// must be the owned one
|
|
1779
|
+
this._exprFastPath =
|
|
1780
|
+
lazy &&
|
|
1781
|
+
this.parseMaybeConditional === proto.parseMaybeConditional &&
|
|
1782
|
+
this.parseExprOps === proto.parseExprOps &&
|
|
1783
|
+
this.parseExprOp === proto.parseExprOp &&
|
|
1784
|
+
this.parseMaybeUnary === proto.parseMaybeUnary &&
|
|
1785
|
+
this.parseExprSubscripts === proto.parseExprSubscripts &&
|
|
1786
|
+
this.parseSubscripts === proto.parseSubscripts &&
|
|
1787
|
+
this.parseSubscript === proto.parseSubscript &&
|
|
1788
|
+
this.parseExprAtom === proto.parseExprAtom &&
|
|
1789
|
+
this.checkExpressionErrors === proto.checkExpressionErrors &&
|
|
1790
|
+
internals.isContextual === base.isContextual;
|
|
1296
1791
|
}
|
|
1297
1792
|
|
|
1298
1793
|
/**
|
|
@@ -1327,15 +1822,42 @@ class WebpackParser extends BaseParser {
|
|
|
1327
1822
|
this._deDepth--;
|
|
1328
1823
|
}
|
|
1329
1824
|
|
|
1825
|
+
/**
|
|
1826
|
+
* Fetches a scratch array for a list production: write elements by index,
|
|
1827
|
+
* then materialize with `_releaseScratch`. Entries past the caller's write
|
|
1828
|
+
* index are stale and meaningless.
|
|
1829
|
+
* @returns {EXPECTED_ANY[]} scratch array
|
|
1830
|
+
* @this {ParserInternals}
|
|
1831
|
+
*/
|
|
1832
|
+
_acquireScratch() {
|
|
1833
|
+
const stack = this._arrStack;
|
|
1834
|
+
const depth = this._arrDepth++;
|
|
1835
|
+
const cached = stack[depth];
|
|
1836
|
+
if (cached !== undefined) return cached;
|
|
1837
|
+
return (stack[depth] = []);
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1840
|
+
/**
|
|
1841
|
+
* @param {EXPECTED_ANY[]} scratch scratch array from `_acquireScratch`
|
|
1842
|
+
* @param {number} count number of elements written
|
|
1843
|
+
* @returns {EXPECTED_ANY[]} exactly-sized copy of the first `count` entries
|
|
1844
|
+
* @this {ParserInternals}
|
|
1845
|
+
*/
|
|
1846
|
+
_releaseScratch(scratch, count) {
|
|
1847
|
+
this._arrDepth--;
|
|
1848
|
+
return scratch.slice(0, count);
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1330
1851
|
// ----- tokenizer fast paths -----
|
|
1331
1852
|
|
|
1332
1853
|
/**
|
|
1333
1854
|
* Owned per-token loop: acorn's `nextToken` chains `skipSpace` →
|
|
1334
1855
|
* `fullCharCodeAtPos` → `readToken` → `isIdentifierStart` with a dead
|
|
1335
|
-
* `locations` check at each step. For the common
|
|
1856
|
+
* `locations` check at each step. For the common non-template context of
|
|
1857
|
+
* `_tokenFastPath` mode (lazy, or locations-off with no tokenizer overrides)
|
|
1336
1858
|
* this folds whitespace and comment skipping and the ASCII token dispatch
|
|
1337
1859
|
* into one function so nothing re-enters acorn's per-step option checks.
|
|
1338
|
-
* Template/`preserveSpace` contexts and
|
|
1860
|
+
* Template/`preserveSpace` contexts and other modes use acorn's tokenizer.
|
|
1339
1861
|
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/tokenize.js
|
|
1340
1862
|
* @returns {void}
|
|
1341
1863
|
* @this {ParserInternals}
|
|
@@ -1343,12 +1865,19 @@ class WebpackParser extends BaseParser {
|
|
|
1343
1865
|
nextToken() {
|
|
1344
1866
|
const context = this.context;
|
|
1345
1867
|
const curContext = context[context.length - 1];
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1868
|
+
let slow;
|
|
1869
|
+
if (curContext !== undefined) {
|
|
1870
|
+
const flagged =
|
|
1871
|
+
/** @type {TokContextShim & { [kSlowContext]?: boolean }} */
|
|
1872
|
+
(curContext);
|
|
1873
|
+
slow = flagged[kSlowContext];
|
|
1874
|
+
if (slow === undefined) {
|
|
1875
|
+
slow = flagged[kSlowContext] = Boolean(
|
|
1876
|
+
curContext.preserveSpace || curContext.override
|
|
1877
|
+
);
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
if (!this._tokenFastPath || curContext === undefined || slow) {
|
|
1352
1881
|
this._newlineBefore = 2;
|
|
1353
1882
|
return base.nextToken.call(this);
|
|
1354
1883
|
}
|
|
@@ -1412,9 +1941,71 @@ class WebpackParser extends BaseParser {
|
|
|
1412
1941
|
switch (cls) {
|
|
1413
1942
|
case CLS_IDENT:
|
|
1414
1943
|
return this.readWord();
|
|
1415
|
-
case CLS_PUNCT:
|
|
1944
|
+
case CLS_PUNCT: {
|
|
1945
|
+
const type = /** @type {TokenType} */ (SIMPLE_PUNCT[code]);
|
|
1416
1946
|
this.pos = pos + 1;
|
|
1417
|
-
return this.finishToken(
|
|
1947
|
+
if (!this._inlineFinish) return this.finishToken(type);
|
|
1948
|
+
// finishToken inlined for the simple punctuators (no value, and
|
|
1949
|
+
// their context updates are per-char static)
|
|
1950
|
+
this.end = pos + 1;
|
|
1951
|
+
const prevType = this.type;
|
|
1952
|
+
this.type = type;
|
|
1953
|
+
this.value = undefined;
|
|
1954
|
+
switch (code) {
|
|
1955
|
+
case 41:
|
|
1956
|
+
case 125: {
|
|
1957
|
+
// parenR/braceR.updateContext, inlined
|
|
1958
|
+
if (context.length === 1) {
|
|
1959
|
+
this.exprAllowed = true;
|
|
1960
|
+
break;
|
|
1961
|
+
}
|
|
1962
|
+
let out = /** @type {TokContextShim} */ (context.pop());
|
|
1963
|
+
if (
|
|
1964
|
+
out === CTX_B_STAT &&
|
|
1965
|
+
/** @type {TokContextShim} */ (context[context.length - 1])
|
|
1966
|
+
.token === "function"
|
|
1967
|
+
) {
|
|
1968
|
+
out = /** @type {TokContextShim} */ (context.pop());
|
|
1969
|
+
}
|
|
1970
|
+
this.exprAllowed = !out.isExpr;
|
|
1971
|
+
break;
|
|
1972
|
+
}
|
|
1973
|
+
case 123:
|
|
1974
|
+
// braceL.updateContext, inlined
|
|
1975
|
+
context.push(this.braceIsBlock(prevType) ? CTX_B_STAT : CTX_B_EXPR);
|
|
1976
|
+
this.exprAllowed = true;
|
|
1977
|
+
break;
|
|
1978
|
+
case 40: {
|
|
1979
|
+
// parenL.updateContext, inlined
|
|
1980
|
+
const statementParens =
|
|
1981
|
+
prevType === tokTypes._if ||
|
|
1982
|
+
prevType === tokTypes._for ||
|
|
1983
|
+
prevType === tokTypes._with ||
|
|
1984
|
+
prevType === tokTypes._while;
|
|
1985
|
+
context.push(statementParens ? CTX_P_STAT : CTX_P_EXPR);
|
|
1986
|
+
this.exprAllowed = true;
|
|
1987
|
+
break;
|
|
1988
|
+
}
|
|
1989
|
+
case 58:
|
|
1990
|
+
// colon.updateContext, inlined
|
|
1991
|
+
if (
|
|
1992
|
+
/** @type {TokContextShim} */ (context[context.length - 1])
|
|
1993
|
+
.token === "function"
|
|
1994
|
+
) {
|
|
1995
|
+
context.pop();
|
|
1996
|
+
}
|
|
1997
|
+
this.exprAllowed = true;
|
|
1998
|
+
break;
|
|
1999
|
+
case 93:
|
|
2000
|
+
// bracketR: no context hook, beforeExpr is false
|
|
2001
|
+
this.exprAllowed = false;
|
|
2002
|
+
break;
|
|
2003
|
+
default:
|
|
2004
|
+
// semi, comma, bracketL: no context hook, beforeExpr is true
|
|
2005
|
+
this.exprAllowed = true;
|
|
2006
|
+
}
|
|
2007
|
+
return;
|
|
2008
|
+
}
|
|
1418
2009
|
case CLS_DOT: {
|
|
1419
2010
|
// `.` not starting `.5` or `...`: skip readToken_dot's re-dispatch
|
|
1420
2011
|
const next = input.charCodeAt(pos + 1);
|
|
@@ -1441,10 +2032,10 @@ class WebpackParser extends BaseParser {
|
|
|
1441
2032
|
}
|
|
1442
2033
|
|
|
1443
2034
|
/**
|
|
1444
|
-
*
|
|
1445
|
-
* `endLoc` write on every token and reaches `updateContext` through an
|
|
1446
|
-
* method call. Skip the probe and inline acorn's `updateContext` body —
|
|
1447
|
-
* runs once per token. Other modes use acorn's.
|
|
2035
|
+
* `_tokenFastPath` `finishToken`: acorn probes `options.locations` for a
|
|
2036
|
+
* dead `endLoc` write on every token and reaches `updateContext` through an
|
|
2037
|
+
* extra method call. Skip the probe and inline acorn's `updateContext` body —
|
|
2038
|
+
* this runs once per token. Other modes use acorn's.
|
|
1448
2039
|
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/tokenize.js
|
|
1449
2040
|
* @param {TokenType} type token type
|
|
1450
2041
|
* @param {unknown=} value token value
|
|
@@ -1452,7 +2043,7 @@ class WebpackParser extends BaseParser {
|
|
|
1452
2043
|
* @this {ParserInternals}
|
|
1453
2044
|
*/
|
|
1454
2045
|
finishToken(type, value) {
|
|
1455
|
-
if (!this.
|
|
2046
|
+
if (!this._tokenFastPath) {
|
|
1456
2047
|
return base.finishToken.call(this, type, value);
|
|
1457
2048
|
}
|
|
1458
2049
|
this.end = this.pos;
|
|
@@ -1471,41 +2062,53 @@ class WebpackParser extends BaseParser {
|
|
|
1471
2062
|
(value === "yield" && this.inGeneratorContext())) &&
|
|
1472
2063
|
prevType !== tokTypes.dot &&
|
|
1473
2064
|
this._ecmaVersion >= 6;
|
|
1474
|
-
} else
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
2065
|
+
} else {
|
|
2066
|
+
const update = internal.updateContext;
|
|
2067
|
+
if (update === null) {
|
|
2068
|
+
// no context hook (most punctuation, operators, literals and
|
|
2069
|
+
// keywords): acorn's keyword-after-dot probe, else `beforeExpr` —
|
|
2070
|
+
// checked first so this majority skips the per-type compares below
|
|
2071
|
+
this.exprAllowed =
|
|
2072
|
+
prevType === tokTypes.dot && internal.keyword !== undefined
|
|
2073
|
+
? false
|
|
2074
|
+
: internal.beforeExpr;
|
|
2075
|
+
} else if (type === tokTypes.parenR || type === tokTypes.braceR) {
|
|
2076
|
+
// parenR/braceR.updateContext, inlined
|
|
2077
|
+
const context = this.context;
|
|
2078
|
+
if (context.length === 1) {
|
|
2079
|
+
this.exprAllowed = true;
|
|
2080
|
+
} else {
|
|
2081
|
+
let out = /** @type {TokContextShim} */ (context.pop());
|
|
2082
|
+
if (
|
|
2083
|
+
out === CTX_B_STAT &&
|
|
2084
|
+
/** @type {TokContextShim} */ (context[context.length - 1])
|
|
2085
|
+
.token === "function"
|
|
2086
|
+
) {
|
|
2087
|
+
out = /** @type {TokContextShim} */ (context.pop());
|
|
2088
|
+
}
|
|
2089
|
+
this.exprAllowed = !out.isExpr;
|
|
2090
|
+
}
|
|
2091
|
+
} else if (type === tokTypes.braceL) {
|
|
2092
|
+
// braceL.updateContext, inlined
|
|
2093
|
+
this.context.push(
|
|
2094
|
+
this.braceIsBlock(prevType) ? CTX_B_STAT : CTX_B_EXPR
|
|
2095
|
+
);
|
|
2096
|
+
this.exprAllowed = true;
|
|
2097
|
+
} else if (type === tokTypes.parenL) {
|
|
2098
|
+
// parenL.updateContext, inlined
|
|
2099
|
+
const statementParens =
|
|
2100
|
+
prevType === tokTypes._if ||
|
|
2101
|
+
prevType === tokTypes._for ||
|
|
2102
|
+
prevType === tokTypes._with ||
|
|
2103
|
+
prevType === tokTypes._while;
|
|
2104
|
+
this.context.push(statementParens ? CTX_P_STAT : CTX_P_EXPR);
|
|
1480
2105
|
this.exprAllowed = true;
|
|
2106
|
+
} else if (internal.keyword !== undefined && prevType === tokTypes.dot) {
|
|
2107
|
+
// `.function` etc.: keyword-after-dot wins over the type's own hook
|
|
2108
|
+
this.exprAllowed = false;
|
|
1481
2109
|
} else {
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
out === CTX_B_STAT &&
|
|
1485
|
-
/** @type {TokContextShim} */ (context[context.length - 1]).token ===
|
|
1486
|
-
"function"
|
|
1487
|
-
) {
|
|
1488
|
-
out = /** @type {TokContextShim} */ (context.pop());
|
|
1489
|
-
}
|
|
1490
|
-
this.exprAllowed = !out.isExpr;
|
|
1491
|
-
}
|
|
1492
|
-
} else if (type === tokTypes.braceL) {
|
|
1493
|
-
// braceL.updateContext, inlined
|
|
1494
|
-
this.context.push(this.braceIsBlock(prevType) ? CTX_B_STAT : CTX_B_EXPR);
|
|
1495
|
-
this.exprAllowed = true;
|
|
1496
|
-
} else if (type === tokTypes.parenL) {
|
|
1497
|
-
// parenL.updateContext, inlined
|
|
1498
|
-
const statementParens =
|
|
1499
|
-
prevType === tokTypes._if ||
|
|
1500
|
-
prevType === tokTypes._for ||
|
|
1501
|
-
prevType === tokTypes._with ||
|
|
1502
|
-
prevType === tokTypes._while;
|
|
1503
|
-
this.context.push(statementParens ? CTX_P_STAT : CTX_P_EXPR);
|
|
1504
|
-
this.exprAllowed = true;
|
|
1505
|
-
} else if (internal.updateContext) {
|
|
1506
|
-
internal.updateContext.call(this, prevType);
|
|
1507
|
-
} else {
|
|
1508
|
-
this.exprAllowed = internal.beforeExpr;
|
|
2110
|
+
update.call(this, prevType);
|
|
2111
|
+
}
|
|
1509
2112
|
}
|
|
1510
2113
|
}
|
|
1511
2114
|
|
|
@@ -1585,19 +2188,21 @@ class WebpackParser extends BaseParser {
|
|
|
1585
2188
|
/**
|
|
1586
2189
|
* Owned per-token advance: acorn's `next` writes `lastTokEndLoc`/
|
|
1587
2190
|
* `lastTokStartLoc` and probes `options.onToken` on every token, both dead in
|
|
1588
|
-
*
|
|
1589
|
-
* writes and the keyword-escape guard. Other modes use acorn's.
|
|
2191
|
+
* `_tokenFastPath` mode (locations off, no token stream), leaving only the
|
|
2192
|
+
* two offset writes and the keyword-escape guard. Other modes use acorn's.
|
|
1590
2193
|
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/tokenize.js
|
|
1591
2194
|
* @param {boolean=} ignoreEscapeSequenceInKeyword whether an escape in a keyword is allowed here
|
|
1592
2195
|
* @returns {void}
|
|
1593
2196
|
* @this {ParserInternals}
|
|
1594
2197
|
*/
|
|
1595
2198
|
next(ignoreEscapeSequenceInKeyword) {
|
|
1596
|
-
if (!this.
|
|
2199
|
+
if (!this._tokenFastPath) {
|
|
1597
2200
|
return base.next.call(this, ignoreEscapeSequenceInKeyword);
|
|
1598
2201
|
}
|
|
1599
2202
|
const type = this.type;
|
|
1600
|
-
|
|
2203
|
+
// `containsEsc` is a parser field and almost always false; testing it first
|
|
2204
|
+
// keeps the TokenType load off the common path.
|
|
2205
|
+
if (this.containsEsc && !ignoreEscapeSequenceInKeyword && type.keyword) {
|
|
1601
2206
|
this.raiseRecoverable(
|
|
1602
2207
|
this.start,
|
|
1603
2208
|
`Escape sequence in keyword ${type.keyword}`
|
|
@@ -1986,12 +2591,15 @@ class WebpackParser extends BaseParser {
|
|
|
1986
2591
|
if (
|
|
1987
2592
|
cached !== null &&
|
|
1988
2593
|
cached.length === wordLen &&
|
|
1989
|
-
|
|
2594
|
+
// length already matched, so a prefix test is an exact compare —
|
|
2595
|
+
// one builtin instead of a charCodeAt loop per cached character
|
|
2596
|
+
input.startsWith(cached, start)
|
|
1990
2597
|
) {
|
|
1991
2598
|
return cached;
|
|
1992
2599
|
}
|
|
1993
2600
|
const word = input.slice(start, pos);
|
|
1994
2601
|
WORD_CACHE[slot] = word;
|
|
2602
|
+
WORD_TYPE_OWNERS[slot] = 0;
|
|
1995
2603
|
return word;
|
|
1996
2604
|
}
|
|
1997
2605
|
return input.slice(start, pos);
|
|
@@ -2758,36 +3366,113 @@ class WebpackParser extends BaseParser {
|
|
|
2758
3366
|
// ----- word classification (Map/Set lookups, replaces acorn's regexps) -----
|
|
2759
3367
|
|
|
2760
3368
|
/**
|
|
2761
|
-
* Replaces acorn's `readWord
|
|
2762
|
-
*
|
|
2763
|
-
*
|
|
3369
|
+
* Replaces acorn's `readWord`: `readWord1`'s ASCII fast path inlined so the
|
|
3370
|
+
* token type can be memoized per `WORD_CACHE` slot (classification is pure in
|
|
3371
|
+
* the word and the per-option keyword set) — a cache hit serves the type by
|
|
3372
|
+
* identity compare instead of a keywords Map probe.
|
|
2764
3373
|
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/tokenize.js
|
|
2765
3374
|
* @this {ParserInternals}
|
|
2766
3375
|
* @returns {void}
|
|
2767
3376
|
*/
|
|
2768
3377
|
readWord() {
|
|
2769
|
-
const
|
|
2770
|
-
|
|
2771
|
-
const len =
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
3378
|
+
const input = this.input;
|
|
3379
|
+
const start = this.pos;
|
|
3380
|
+
const len = input.length;
|
|
3381
|
+
let hash = 0;
|
|
3382
|
+
let pos = start;
|
|
3383
|
+
while (pos < len) {
|
|
3384
|
+
const ch = input.charCodeAt(pos);
|
|
3385
|
+
if (ch < 128) {
|
|
3386
|
+
if (IDENT_CHAR[ch] === 0) {
|
|
3387
|
+
// backslash escape: restart cold so escape rules see the word
|
|
3388
|
+
if (ch === 92) return this._finishWordSlow(this._readWord1Cold());
|
|
3389
|
+
break;
|
|
3390
|
+
}
|
|
3391
|
+
hash = (Math.imul(hash, 33) + ch) | 0;
|
|
3392
|
+
pos++;
|
|
3393
|
+
} else {
|
|
3394
|
+
return this._finishWordSlow(this._readWord1Cold());
|
|
2779
3395
|
}
|
|
2780
3396
|
}
|
|
2781
|
-
this.
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
3397
|
+
this.containsEsc = false;
|
|
3398
|
+
this.pos = pos;
|
|
3399
|
+
const wordLen = pos - start;
|
|
3400
|
+
if (wordLen >= 2 && wordLen <= WORD_CACHE_MAX_LEN) {
|
|
3401
|
+
const slot = hash & WORD_CACHE_MASK;
|
|
3402
|
+
const lookups = this._wordLookups;
|
|
3403
|
+
const owner = lookups.id;
|
|
3404
|
+
const cached = WORD_CACHE[slot];
|
|
3405
|
+
/** @type {string} */
|
|
3406
|
+
let word;
|
|
3407
|
+
/** @type {TokenType} */
|
|
3408
|
+
let type;
|
|
3409
|
+
if (
|
|
3410
|
+
cached !== null &&
|
|
3411
|
+
cached.length === wordLen &&
|
|
3412
|
+
// length already matched, so a prefix test is an exact compare —
|
|
3413
|
+
// one builtin instead of a charCodeAt loop per cached character
|
|
3414
|
+
input.startsWith(cached, start)
|
|
3415
|
+
) {
|
|
3416
|
+
word = cached;
|
|
3417
|
+
if (WORD_TYPE_OWNERS[slot] === owner) {
|
|
3418
|
+
type = /** @type {TokenType} */ (WORD_TYPES[slot]);
|
|
3419
|
+
} else {
|
|
3420
|
+
type = classifyWord(cached, lookups.keywords);
|
|
3421
|
+
WORD_TYPES[slot] = type;
|
|
3422
|
+
WORD_TYPE_OWNERS[slot] = owner;
|
|
3423
|
+
}
|
|
3424
|
+
} else {
|
|
3425
|
+
word = input.slice(start, pos);
|
|
3426
|
+
WORD_CACHE[slot] = word;
|
|
3427
|
+
type = classifyWord(word, lookups.keywords);
|
|
3428
|
+
WORD_TYPES[slot] = type;
|
|
3429
|
+
WORD_TYPE_OWNERS[slot] = owner;
|
|
3430
|
+
}
|
|
3431
|
+
if (type === tokTypes.name && this._inlineFinish) {
|
|
3432
|
+
// finishToken(name) inlined: offset/type/value stores plus
|
|
3433
|
+
// name.updateContext (as in the owned finishToken)
|
|
3434
|
+
this.end = pos;
|
|
3435
|
+
const prevType = this.type;
|
|
3436
|
+
this.type = type;
|
|
3437
|
+
this.value = word;
|
|
3438
|
+
this.exprAllowed =
|
|
3439
|
+
((word === "of" && !this.exprAllowed) ||
|
|
3440
|
+
(word === "yield" && this.inGeneratorContext())) &&
|
|
3441
|
+
prevType !== tokTypes.dot &&
|
|
3442
|
+
this._ecmaVersion >= 6;
|
|
3443
|
+
return;
|
|
3444
|
+
}
|
|
3445
|
+
return this.finishToken(type, word);
|
|
3446
|
+
}
|
|
3447
|
+
// Every keyword is 2-10 chars, so a word outside the cacheable range is a
|
|
3448
|
+
// plain name and can be neither `of` nor `yield`.
|
|
3449
|
+
if (this._inlineFinish) {
|
|
3450
|
+
this.end = pos;
|
|
3451
|
+
this.type = tokTypes.name;
|
|
3452
|
+
this.value = input.slice(start, pos);
|
|
3453
|
+
this.exprAllowed = false;
|
|
3454
|
+
return;
|
|
3455
|
+
}
|
|
3456
|
+
return this._finishWordSlow(input.slice(start, pos));
|
|
3457
|
+
}
|
|
3458
|
+
|
|
3459
|
+
/**
|
|
3460
|
+
* Uncached tail of `readWord`: escaped/non-ASCII, 1-char and over-long words.
|
|
3461
|
+
* @this {ParserInternals}
|
|
3462
|
+
* @param {string} word the word
|
|
3463
|
+
* @returns {void}
|
|
3464
|
+
*/
|
|
3465
|
+
_finishWordSlow(word) {
|
|
3466
|
+
this.finishToken(classifyWord(word, this._wordLookups.keywords), word);
|
|
3467
|
+
}
|
|
3468
|
+
|
|
3469
|
+
/**
|
|
3470
|
+
* Mirror of acorn's `checkUnreserved` with its two per-identifier regexp
|
|
3471
|
+
* tests (`keywords` and `reservedWords`/`reservedWordsStrict`) folded into a
|
|
3472
|
+
* single `reservedKinds` lookup — one hash probe instead of two, and the
|
|
3473
|
+
* common plain identifier misses it and returns. Branches and error
|
|
3474
|
+
* messages match acorn exactly.
|
|
3475
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/expression.js
|
|
2791
3476
|
* @param {Identifier} ref identifier node
|
|
2792
3477
|
* @this {ParserInternals}
|
|
2793
3478
|
*/
|
|
@@ -2850,6 +3535,162 @@ class WebpackParser extends BaseParser {
|
|
|
2850
3535
|
}
|
|
2851
3536
|
}
|
|
2852
3537
|
|
|
3538
|
+
/**
|
|
3539
|
+
* Owned `checkLValSimple`, an exact-semantics copy of acorn 8's with the
|
|
3540
|
+
* strict-bind probe inlined: the constructor-installed Set stand-in is one
|
|
3541
|
+
* `has` behind a length gate instead of a closure call per checked name.
|
|
3542
|
+
* A runtime-replaced `reservedWordsStrictBind` falls back to `.test()`.
|
|
3543
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/lval.js
|
|
3544
|
+
* @param {Node} expr assignment/binding target
|
|
3545
|
+
* @param {number=} bindingType acorn BIND_* binding type
|
|
3546
|
+
* @param {Record<string, boolean> | null=} checkClashes param-name clash record
|
|
3547
|
+
* @returns {void}
|
|
3548
|
+
* @this {ParserInternals}
|
|
3549
|
+
*/
|
|
3550
|
+
checkLValSimple(expr, bindingType, checkClashes) {
|
|
3551
|
+
if (bindingType === undefined) bindingType = BIND_NONE;
|
|
3552
|
+
const isBind = bindingType !== BIND_NONE;
|
|
3553
|
+
const type = expr.type;
|
|
3554
|
+
if (type === "Identifier") {
|
|
3555
|
+
const name = /** @type {Identifier} */ (expr).name;
|
|
3556
|
+
if (this.strict) {
|
|
3557
|
+
const lookups = this._wordLookups;
|
|
3558
|
+
let reserved;
|
|
3559
|
+
if (this.reservedWordsStrictBind === lookups.reservedBindTest) {
|
|
3560
|
+
const len = name.length;
|
|
3561
|
+
reserved =
|
|
3562
|
+
len >= lookups.reservedBindMinLen &&
|
|
3563
|
+
len <= lookups.reservedBindMaxLen &&
|
|
3564
|
+
lookups.reservedBindSet.has(name);
|
|
3565
|
+
} else {
|
|
3566
|
+
reserved = this.reservedWordsStrictBind.test(name);
|
|
3567
|
+
}
|
|
3568
|
+
if (reserved) {
|
|
3569
|
+
this.raiseRecoverable(
|
|
3570
|
+
expr.start,
|
|
3571
|
+
`${isBind ? "Binding " : "Assigning to "}${name} in strict mode`
|
|
3572
|
+
);
|
|
3573
|
+
}
|
|
3574
|
+
}
|
|
3575
|
+
if (isBind) {
|
|
3576
|
+
if (bindingType === BIND_LEXICAL && name === "let") {
|
|
3577
|
+
this.raiseRecoverable(
|
|
3578
|
+
expr.start,
|
|
3579
|
+
"let is disallowed as a lexically bound name"
|
|
3580
|
+
);
|
|
3581
|
+
}
|
|
3582
|
+
if (checkClashes) {
|
|
3583
|
+
if (Object.prototype.hasOwnProperty.call(checkClashes, name)) {
|
|
3584
|
+
this.raiseRecoverable(expr.start, "Argument name clash");
|
|
3585
|
+
}
|
|
3586
|
+
checkClashes[name] = true;
|
|
3587
|
+
}
|
|
3588
|
+
if (bindingType !== BIND_OUTSIDE) {
|
|
3589
|
+
this.declareName(name, bindingType, expr.start);
|
|
3590
|
+
}
|
|
3591
|
+
}
|
|
3592
|
+
return;
|
|
3593
|
+
}
|
|
3594
|
+
if (type === "ChainExpression") {
|
|
3595
|
+
this.raiseRecoverable(
|
|
3596
|
+
expr.start,
|
|
3597
|
+
"Optional chaining cannot appear in left-hand side"
|
|
3598
|
+
);
|
|
3599
|
+
return;
|
|
3600
|
+
}
|
|
3601
|
+
if (type === "MemberExpression") {
|
|
3602
|
+
if (isBind) {
|
|
3603
|
+
this.raiseRecoverable(expr.start, "Binding member expression");
|
|
3604
|
+
}
|
|
3605
|
+
return;
|
|
3606
|
+
}
|
|
3607
|
+
if (type === "ParenthesizedExpression") {
|
|
3608
|
+
if (isBind) {
|
|
3609
|
+
this.raiseRecoverable(expr.start, "Binding parenthesized expression");
|
|
3610
|
+
}
|
|
3611
|
+
return this.checkLValSimple(
|
|
3612
|
+
/** @type {Node} */ (
|
|
3613
|
+
/** @type {Node & { expression?: Node }} */ (expr).expression
|
|
3614
|
+
),
|
|
3615
|
+
bindingType,
|
|
3616
|
+
checkClashes
|
|
3617
|
+
);
|
|
3618
|
+
}
|
|
3619
|
+
this.raise(expr.start, `${isBind ? "Binding" : "Assigning to"} rvalue`);
|
|
3620
|
+
}
|
|
3621
|
+
|
|
3622
|
+
/**
|
|
3623
|
+
* Owned `checkLValPattern`, acorn's verbatim, so declarator/assignment
|
|
3624
|
+
* targets stay on owned code down to `checkLValSimple`/`declareName`.
|
|
3625
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/lval.js
|
|
3626
|
+
* @param {Node} expr binding pattern
|
|
3627
|
+
* @param {number=} bindingType acorn BIND_* binding type
|
|
3628
|
+
* @param {Record<string, boolean> | null=} checkClashes param-name clash record
|
|
3629
|
+
* @returns {void}
|
|
3630
|
+
* @this {ParserInternals}
|
|
3631
|
+
*/
|
|
3632
|
+
checkLValPattern(expr, bindingType, checkClashes) {
|
|
3633
|
+
const type = expr.type;
|
|
3634
|
+
if (type === "ObjectPattern") {
|
|
3635
|
+
const properties = /** @type {Node & { properties: Node[] }} */ (expr)
|
|
3636
|
+
.properties;
|
|
3637
|
+
for (let i = 0; i < properties.length; i++) {
|
|
3638
|
+
this.checkLValInnerPattern(properties[i], bindingType, checkClashes);
|
|
3639
|
+
}
|
|
3640
|
+
} else if (type === "ArrayPattern") {
|
|
3641
|
+
const elements = /** @type {Node & { elements: (Node | null)[] }} */ (
|
|
3642
|
+
expr
|
|
3643
|
+
).elements;
|
|
3644
|
+
for (let i = 0; i < elements.length; i++) {
|
|
3645
|
+
const element = elements[i];
|
|
3646
|
+
if (element) {
|
|
3647
|
+
this.checkLValInnerPattern(element, bindingType, checkClashes);
|
|
3648
|
+
}
|
|
3649
|
+
}
|
|
3650
|
+
} else {
|
|
3651
|
+
this.checkLValSimple(expr, bindingType, checkClashes);
|
|
3652
|
+
}
|
|
3653
|
+
}
|
|
3654
|
+
|
|
3655
|
+
/**
|
|
3656
|
+
* Owned `checkLValInnerPattern`, acorn's verbatim.
|
|
3657
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/lval.js
|
|
3658
|
+
* @param {Node} expr pattern element
|
|
3659
|
+
* @param {number=} bindingType acorn BIND_* binding type
|
|
3660
|
+
* @param {Record<string, boolean> | null=} checkClashes param-name clash record
|
|
3661
|
+
* @returns {void}
|
|
3662
|
+
* @this {ParserInternals}
|
|
3663
|
+
*/
|
|
3664
|
+
checkLValInnerPattern(expr, bindingType, checkClashes) {
|
|
3665
|
+
const type = expr.type;
|
|
3666
|
+
if (type === "Property") {
|
|
3667
|
+
// AssignmentProperty has type === "Property"
|
|
3668
|
+
this.checkLValInnerPattern(
|
|
3669
|
+
/** @type {Node} */ (
|
|
3670
|
+
/** @type {Node & { value?: Node }} */ (expr).value
|
|
3671
|
+
),
|
|
3672
|
+
bindingType,
|
|
3673
|
+
checkClashes
|
|
3674
|
+
);
|
|
3675
|
+
} else if (type === "AssignmentPattern") {
|
|
3676
|
+
this.checkLValPattern(
|
|
3677
|
+
/** @type {Node} */ (/** @type {Node & { left?: Node }} */ (expr).left),
|
|
3678
|
+
bindingType,
|
|
3679
|
+
checkClashes
|
|
3680
|
+
);
|
|
3681
|
+
} else if (type === "RestElement") {
|
|
3682
|
+
this.checkLValPattern(
|
|
3683
|
+
/** @type {Node} */ (
|
|
3684
|
+
/** @type {Node & { argument?: Node }} */ (expr).argument
|
|
3685
|
+
),
|
|
3686
|
+
bindingType,
|
|
3687
|
+
checkClashes
|
|
3688
|
+
);
|
|
3689
|
+
} else {
|
|
3690
|
+
this.checkLValPattern(expr, bindingType, checkClashes);
|
|
3691
|
+
}
|
|
3692
|
+
}
|
|
3693
|
+
|
|
2853
3694
|
/**
|
|
2854
3695
|
* Replaces acorn's `canInsertSemicolon`, whose line-break check slices the
|
|
2855
3696
|
* inter-token gap and runs a regexp on it for every ASI decision (hundreds
|
|
@@ -3016,6 +3857,79 @@ class WebpackParser extends BaseParser {
|
|
|
3016
3857
|
return node;
|
|
3017
3858
|
}
|
|
3018
3859
|
|
|
3860
|
+
/**
|
|
3861
|
+
* Owned `parseSubscripts`, an exact-semantics copy of acorn 8's with the
|
|
3862
|
+
* async-arrow-head probe reordered cheapest-first (all operands are pure)
|
|
3863
|
+
* and the arrow exit probe served by `_lastArrow` identity instead of the
|
|
3864
|
+
* megamorphic `.type` load. Delegates when either fast path is off.
|
|
3865
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/expression.js
|
|
3866
|
+
* @param {Expression} baseExpr subscript base
|
|
3867
|
+
* @param {number} startPos expression start offset
|
|
3868
|
+
* @param {Position | undefined} startLoc expression start position
|
|
3869
|
+
* @param {boolean=} noCalls whether calls are forbidden (`new` callee)
|
|
3870
|
+
* @param {boolean | string=} forInit for-init context flag
|
|
3871
|
+
* @returns {Expression} expression with subscripts applied
|
|
3872
|
+
* @this {ParserInternals}
|
|
3873
|
+
*/
|
|
3874
|
+
parseSubscripts(baseExpr, startPos, startLoc, noCalls, forInit) {
|
|
3875
|
+
if (!this._subscriptFastPath || !this._arrowFastPath) {
|
|
3876
|
+
return base.parseSubscripts.call(
|
|
3877
|
+
this,
|
|
3878
|
+
baseExpr,
|
|
3879
|
+
startPos,
|
|
3880
|
+
startLoc,
|
|
3881
|
+
noCalls,
|
|
3882
|
+
forInit
|
|
3883
|
+
);
|
|
3884
|
+
}
|
|
3885
|
+
// acorn's probe order is (ecmaVersion, type, name, offsets, ASI,
|
|
3886
|
+
// potentialArrowAt); every operand is pure, so the SMI compares run
|
|
3887
|
+
// first and the megamorphic `.type` load only when `async` matched
|
|
3888
|
+
const maybeAsyncArrow =
|
|
3889
|
+
baseExpr.start === this.potentialArrowAt &&
|
|
3890
|
+
baseExpr.end - baseExpr.start === 5 &&
|
|
3891
|
+
this.lastTokEnd === baseExpr.end &&
|
|
3892
|
+
this._ecmaVersion >= 8 &&
|
|
3893
|
+
/** @type {Identifier} */ (baseExpr).name === "async" &&
|
|
3894
|
+
baseExpr.type === "Identifier" &&
|
|
3895
|
+
!this.canInsertSemicolon();
|
|
3896
|
+
let optionalChained = false;
|
|
3897
|
+
for (;;) {
|
|
3898
|
+
const element = this.parseSubscript(
|
|
3899
|
+
baseExpr,
|
|
3900
|
+
startPos,
|
|
3901
|
+
startLoc,
|
|
3902
|
+
noCalls,
|
|
3903
|
+
maybeAsyncArrow,
|
|
3904
|
+
optionalChained,
|
|
3905
|
+
forInit
|
|
3906
|
+
);
|
|
3907
|
+
if (
|
|
3908
|
+
/** @type {Expression & { optional?: boolean }} */ (element).optional
|
|
3909
|
+
) {
|
|
3910
|
+
optionalChained = true;
|
|
3911
|
+
}
|
|
3912
|
+
if (element === baseExpr || element === this._lastArrow) {
|
|
3913
|
+
if (optionalChained) {
|
|
3914
|
+
const chainNode =
|
|
3915
|
+
/** @type {Node & { expression?: Expression }} */
|
|
3916
|
+
(this.startNodeAt(startPos, startLoc));
|
|
3917
|
+
chainNode.expression = element;
|
|
3918
|
+
return /** @type {Expression} */ (
|
|
3919
|
+
/** @type {unknown} */ (
|
|
3920
|
+
this.finishNode(
|
|
3921
|
+
/** @type {Node} */ (chainNode),
|
|
3922
|
+
"ChainExpression"
|
|
3923
|
+
)
|
|
3924
|
+
)
|
|
3925
|
+
);
|
|
3926
|
+
}
|
|
3927
|
+
return element;
|
|
3928
|
+
}
|
|
3929
|
+
baseExpr = element;
|
|
3930
|
+
}
|
|
3931
|
+
}
|
|
3932
|
+
|
|
3019
3933
|
/**
|
|
3020
3934
|
* Owned `parseSubscript`, an exact-semantics copy of acorn 8's with the
|
|
3021
3935
|
* node construction replaced: member and call nodes are built fully-formed
|
|
@@ -3201,17 +4115,65 @@ class WebpackParser extends BaseParser {
|
|
|
3201
4115
|
case tokTypes.braceL:
|
|
3202
4116
|
// the owned parseBlock never reads the started node
|
|
3203
4117
|
return this.parseBlock(true);
|
|
4118
|
+
case tokTypes._function: {
|
|
4119
|
+
if (!this._funcStmtOwn) {
|
|
4120
|
+
return base.parseStatement.call(this, context, topLevel, exports);
|
|
4121
|
+
}
|
|
4122
|
+
// acorn's hanging-function guard (context = single-statement position)
|
|
4123
|
+
if (
|
|
4124
|
+
context &&
|
|
4125
|
+
(this.strict || (context !== "if" && context !== "label"))
|
|
4126
|
+
) {
|
|
4127
|
+
this.unexpected();
|
|
4128
|
+
}
|
|
4129
|
+
// parseFunctionStatement, inlined without the started node
|
|
4130
|
+
const start = this.start;
|
|
4131
|
+
this.next();
|
|
4132
|
+
return this._parseFunctionAt(
|
|
4133
|
+
start,
|
|
4134
|
+
FUNC_STATEMENT | (context ? FUNC_HANGING_STATEMENT : 0),
|
|
4135
|
+
false,
|
|
4136
|
+
false,
|
|
4137
|
+
undefined
|
|
4138
|
+
);
|
|
4139
|
+
}
|
|
3204
4140
|
case tokTypes._break:
|
|
3205
4141
|
case tokTypes._continue:
|
|
3206
|
-
|
|
3207
|
-
|
|
4142
|
+
if (!this._stmt2FastPath) {
|
|
4143
|
+
return base.parseStatement.call(this, context, topLevel, exports);
|
|
4144
|
+
}
|
|
4145
|
+
return this._parseBreakContinueStatementAt(
|
|
4146
|
+
this.start,
|
|
4147
|
+
/** @type {string} */ (startType.keyword)
|
|
4148
|
+
);
|
|
3208
4149
|
case tokTypes._for:
|
|
3209
|
-
|
|
3210
|
-
|
|
4150
|
+
if (!this._stmt2FastPath) {
|
|
4151
|
+
return base.parseStatement.call(this, context, topLevel, exports);
|
|
4152
|
+
}
|
|
4153
|
+
return this._parseForStatementAt(this.start);
|
|
3211
4154
|
case tokTypes._switch:
|
|
4155
|
+
if (!this._stmt2FastPath) {
|
|
4156
|
+
return base.parseStatement.call(this, context, topLevel, exports);
|
|
4157
|
+
}
|
|
4158
|
+
return this._parseSwitchStatementAt(this.start);
|
|
3212
4159
|
case tokTypes._throw:
|
|
4160
|
+
if (!this._stmt2FastPath) {
|
|
4161
|
+
return base.parseStatement.call(this, context, topLevel, exports);
|
|
4162
|
+
}
|
|
4163
|
+
return this._parseThrowStatementAt(this.start);
|
|
3213
4164
|
case tokTypes._try:
|
|
4165
|
+
if (!this._stmt2FastPath) {
|
|
4166
|
+
return base.parseStatement.call(this, context, topLevel, exports);
|
|
4167
|
+
}
|
|
4168
|
+
return this._parseTryStatementAt(this.start);
|
|
3214
4169
|
case tokTypes._while:
|
|
4170
|
+
if (!this._stmt2FastPath) {
|
|
4171
|
+
return base.parseStatement.call(this, context, topLevel, exports);
|
|
4172
|
+
}
|
|
4173
|
+
return this._parseWhileStatementAt(this.start);
|
|
4174
|
+
case tokTypes._debugger:
|
|
4175
|
+
case tokTypes._do:
|
|
4176
|
+
case tokTypes._class:
|
|
3215
4177
|
case tokTypes._with:
|
|
3216
4178
|
case tokTypes.semi:
|
|
3217
4179
|
case tokTypes._export:
|
|
@@ -3294,9 +4256,14 @@ class WebpackParser extends BaseParser {
|
|
|
3294
4256
|
*/
|
|
3295
4257
|
_parseVarStatementAt(start, kind, allowMissingInitializer) {
|
|
3296
4258
|
this.next();
|
|
3297
|
-
|
|
3298
|
-
const
|
|
3299
|
-
|
|
4259
|
+
const scratch = this._acquireScratch();
|
|
4260
|
+
const count = this._parseVarInto(
|
|
4261
|
+
scratch,
|
|
4262
|
+
false,
|
|
4263
|
+
kind,
|
|
4264
|
+
allowMissingInitializer
|
|
4265
|
+
);
|
|
4266
|
+
const declarations = this._releaseScratch(scratch, count);
|
|
3300
4267
|
this.semicolon();
|
|
3301
4268
|
return /** @type {Node} */ (
|
|
3302
4269
|
/** @type {unknown} */ (
|
|
@@ -3328,13 +4295,23 @@ class WebpackParser extends BaseParser {
|
|
|
3328
4295
|
allowMissingInitializer
|
|
3329
4296
|
);
|
|
3330
4297
|
}
|
|
3331
|
-
/** @type {Node[]} */
|
|
3332
|
-
const declarations = [];
|
|
3333
4298
|
const target =
|
|
3334
|
-
/** @type {Node & { declarations: Node[], kind: string }} */ (
|
|
3335
|
-
|
|
4299
|
+
/** @type {Node & { declarations: Node[] | null, kind: string }} */ (
|
|
4300
|
+
node
|
|
4301
|
+
);
|
|
4302
|
+
// null placeholder keeps acorn's declarations-then-kind key order while
|
|
4303
|
+
// the list is built in scratch (the node is a local in every caller
|
|
4304
|
+
// until this returns, so the placeholder is unobservable)
|
|
4305
|
+
target.declarations = null;
|
|
3336
4306
|
target.kind = kind;
|
|
3337
|
-
this.
|
|
4307
|
+
const scratch = this._acquireScratch();
|
|
4308
|
+
const count = this._parseVarInto(
|
|
4309
|
+
scratch,
|
|
4310
|
+
isFor,
|
|
4311
|
+
kind,
|
|
4312
|
+
allowMissingInitializer
|
|
4313
|
+
);
|
|
4314
|
+
target.declarations = this._releaseScratch(scratch, count);
|
|
3338
4315
|
return node;
|
|
3339
4316
|
}
|
|
3340
4317
|
|
|
@@ -3342,16 +4319,17 @@ class WebpackParser extends BaseParser {
|
|
|
3342
4319
|
* The declarator loop of the owned `parseVar`, shared with the owned
|
|
3343
4320
|
* `parseStatement`'s node-free statement path.
|
|
3344
4321
|
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/statement.js
|
|
3345
|
-
* @param {Node[]} declarations
|
|
4322
|
+
* @param {Node[]} declarations scratch array for the declarators
|
|
3346
4323
|
* @param {boolean} isFor whether parsing a `for` head
|
|
3347
4324
|
* @param {string} kind declaration kind
|
|
3348
4325
|
* @param {boolean=} allowMissingInitializer whether `const x;` is allowed
|
|
3349
|
-
* @returns {
|
|
4326
|
+
* @returns {number} number of declarators written
|
|
3350
4327
|
* @this {ParserInternals}
|
|
3351
4328
|
*/
|
|
3352
4329
|
_parseVarInto(declarations, isFor, kind, allowMissingInitializer) {
|
|
3353
4330
|
const ecmaVersion = this._ecmaVersion;
|
|
3354
4331
|
const usingKind = kind === "using" || kind === "await using";
|
|
4332
|
+
let count = 0;
|
|
3355
4333
|
for (;;) {
|
|
3356
4334
|
const declStart = this.start;
|
|
3357
4335
|
const id = usingKind ? this.parseIdent() : this.parseBindingAtom();
|
|
@@ -3394,15 +4372,14 @@ class WebpackParser extends BaseParser {
|
|
|
3394
4372
|
"Complex binding patterns require an initialization value"
|
|
3395
4373
|
);
|
|
3396
4374
|
}
|
|
3397
|
-
declarations
|
|
3398
|
-
/** @type {
|
|
3399
|
-
|
|
3400
|
-
new VariableDeclaratorNode(declStart, this.lastTokEnd, id, init)
|
|
3401
|
-
)
|
|
4375
|
+
declarations[count++] = /** @type {Node} */ (
|
|
4376
|
+
/** @type {unknown} */ (
|
|
4377
|
+
new VariableDeclaratorNode(declStart, this.lastTokEnd, id, init)
|
|
3402
4378
|
)
|
|
3403
4379
|
);
|
|
3404
4380
|
if (!this.eat(tokTypes.comma)) break;
|
|
3405
4381
|
}
|
|
4382
|
+
return count;
|
|
3406
4383
|
}
|
|
3407
4384
|
|
|
3408
4385
|
/**
|
|
@@ -3460,19 +4437,23 @@ class WebpackParser extends BaseParser {
|
|
|
3460
4437
|
}
|
|
3461
4438
|
if (createNewLexicalScope === undefined) createNewLexicalScope = true;
|
|
3462
4439
|
const start = this.start;
|
|
3463
|
-
|
|
3464
|
-
|
|
4440
|
+
const scratch = this._acquireScratch();
|
|
4441
|
+
let count = 0;
|
|
3465
4442
|
this.expect(tokTypes.braceL);
|
|
3466
4443
|
if (createNewLexicalScope) this.enterScope(0);
|
|
3467
4444
|
while (this.type !== tokTypes.braceR) {
|
|
3468
|
-
|
|
4445
|
+
scratch[count++] = this.parseStatement(null);
|
|
3469
4446
|
}
|
|
3470
4447
|
if (exitStrict) this.strict = false;
|
|
3471
4448
|
this.next();
|
|
3472
4449
|
if (createNewLexicalScope) this.exitScope();
|
|
3473
4450
|
return /** @type {Node} */ (
|
|
3474
4451
|
/** @type {unknown} */ (
|
|
3475
|
-
new BlockStatementNode(
|
|
4452
|
+
new BlockStatementNode(
|
|
4453
|
+
start,
|
|
4454
|
+
this.lastTokEnd,
|
|
4455
|
+
this._releaseScratch(scratch, count)
|
|
4456
|
+
)
|
|
3476
4457
|
)
|
|
3477
4458
|
);
|
|
3478
4459
|
}
|
|
@@ -3538,109 +4519,1159 @@ class WebpackParser extends BaseParser {
|
|
|
3538
4519
|
*/
|
|
3539
4520
|
_tryModuleFallback() {
|
|
3540
4521
|
if (
|
|
3541
|
-
!this._moduleFallback ||
|
|
3542
|
-
this._moduleSyntaxSeen ||
|
|
3543
|
-
!(this.currentVarScope().flags & SCOPE_TOP)
|
|
4522
|
+
!this._moduleFallback ||
|
|
4523
|
+
this._moduleSyntaxSeen ||
|
|
4524
|
+
!(this.currentVarScope().flags & SCOPE_TOP)
|
|
4525
|
+
) {
|
|
4526
|
+
return false;
|
|
4527
|
+
}
|
|
4528
|
+
this.options.allowReturnOutsideFunction = true;
|
|
4529
|
+
// acorn stamps Program.sourceType from this at parseTopLevel's end
|
|
4530
|
+
this.options.sourceType = "script";
|
|
4531
|
+
this.strict = false;
|
|
4532
|
+
this.inModule = false;
|
|
4533
|
+
this._moduleFallback = false;
|
|
4534
|
+
return true;
|
|
4535
|
+
}
|
|
4536
|
+
|
|
4537
|
+
/**
|
|
4538
|
+
* `parseReturnStatement` without a started node.
|
|
4539
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/statement.js
|
|
4540
|
+
* @param {number} start statement start offset
|
|
4541
|
+
* @returns {Node} return statement
|
|
4542
|
+
* @this {ParserInternals}
|
|
4543
|
+
*/
|
|
4544
|
+
_parseReturnStatementAt(start) {
|
|
4545
|
+
if (!this.allowReturn && !this._tryModuleFallback()) {
|
|
4546
|
+
this.raise(this.start, "'return' outside of function");
|
|
4547
|
+
}
|
|
4548
|
+
this.next();
|
|
4549
|
+
/** @type {Expression | null} */
|
|
4550
|
+
let argument = null;
|
|
4551
|
+
// `return` takes an optional argument, so eagerly look for a semicolon
|
|
4552
|
+
if (!(this.eat(tokTypes.semi) || this.insertSemicolon())) {
|
|
4553
|
+
argument = this.parseExpression();
|
|
4554
|
+
this.semicolon();
|
|
4555
|
+
}
|
|
4556
|
+
return /** @type {Node} */ (
|
|
4557
|
+
/** @type {unknown} */ (
|
|
4558
|
+
new ReturnStatementNode(start, this.lastTokEnd, argument)
|
|
4559
|
+
)
|
|
4560
|
+
);
|
|
4561
|
+
}
|
|
4562
|
+
|
|
4563
|
+
/**
|
|
4564
|
+
* `parseBreakContinueStatement` without a started node, landing on
|
|
4565
|
+
* `BreakContinueNode`'s single shape.
|
|
4566
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/statement.js
|
|
4567
|
+
* @param {number} start statement start offset
|
|
4568
|
+
* @param {string} keyword `break` or `continue`
|
|
4569
|
+
* @returns {Node} break or continue statement
|
|
4570
|
+
* @this {ParserInternals}
|
|
4571
|
+
*/
|
|
4572
|
+
_parseBreakContinueStatementAt(start, keyword) {
|
|
4573
|
+
const isBreak = keyword === "break";
|
|
4574
|
+
this.next();
|
|
4575
|
+
/** @type {Identifier | null} */
|
|
4576
|
+
let label = null;
|
|
4577
|
+
if (this.eat(tokTypes.semi) || this.insertSemicolon()) {
|
|
4578
|
+
// no label
|
|
4579
|
+
} else if (this.type !== tokTypes.name) {
|
|
4580
|
+
this.unexpected();
|
|
4581
|
+
} else {
|
|
4582
|
+
label = this.parseIdent();
|
|
4583
|
+
this.semicolon();
|
|
4584
|
+
}
|
|
4585
|
+
// verify there is an actual destination to break or continue to
|
|
4586
|
+
const labels = this.labels;
|
|
4587
|
+
let i = 0;
|
|
4588
|
+
for (; i < labels.length; ++i) {
|
|
4589
|
+
const lab = labels[i];
|
|
4590
|
+
if (label === null || lab.name === label.name) {
|
|
4591
|
+
if (
|
|
4592
|
+
lab.kind !== null &&
|
|
4593
|
+
lab.kind !== undefined &&
|
|
4594
|
+
(isBreak || lab.kind === "loop")
|
|
4595
|
+
) {
|
|
4596
|
+
break;
|
|
4597
|
+
}
|
|
4598
|
+
if (label && isBreak) break;
|
|
4599
|
+
}
|
|
4600
|
+
}
|
|
4601
|
+
if (i === labels.length) this.raise(start, `Unsyntactic ${keyword}`);
|
|
4602
|
+
return /** @type {Node} */ (
|
|
4603
|
+
/** @type {unknown} */ (
|
|
4604
|
+
new BreakContinueNode(
|
|
4605
|
+
start,
|
|
4606
|
+
this.lastTokEnd,
|
|
4607
|
+
isBreak ? "BreakStatement" : "ContinueStatement",
|
|
4608
|
+
label
|
|
4609
|
+
)
|
|
4610
|
+
)
|
|
4611
|
+
);
|
|
4612
|
+
}
|
|
4613
|
+
|
|
4614
|
+
/**
|
|
4615
|
+
* `parseForStatement` without a started node (fast-path gate guarantees
|
|
4616
|
+
* `ecmaVersion >= 9`, folding acorn's version probes).
|
|
4617
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/statement.js
|
|
4618
|
+
* @param {number} start statement start offset
|
|
4619
|
+
* @returns {Node} for/for-in/for-of statement
|
|
4620
|
+
* @this {ParserInternals}
|
|
4621
|
+
*/
|
|
4622
|
+
_parseForStatementAt(start) {
|
|
4623
|
+
this.next();
|
|
4624
|
+
const awaitAt =
|
|
4625
|
+
this.canAwait && this.eatContextual("await") ? this.lastTokStart : -1;
|
|
4626
|
+
this.labels.push(LOOP_LABEL);
|
|
4627
|
+
this.enterScope(0);
|
|
4628
|
+
this.expect(tokTypes.parenL);
|
|
4629
|
+
if (this.type === tokTypes.semi) {
|
|
4630
|
+
if (awaitAt > -1) this.unexpected(awaitAt);
|
|
4631
|
+
return this._parseForAt(start, null);
|
|
4632
|
+
}
|
|
4633
|
+
const isLet = this.isLet();
|
|
4634
|
+
if (this.type === tokTypes._var || this.type === tokTypes._const || isLet) {
|
|
4635
|
+
const initStart = this.start;
|
|
4636
|
+
const kind = isLet ? "let" : /** @type {string} */ (this.value);
|
|
4637
|
+
this.next();
|
|
4638
|
+
const scratch = this._acquireScratch();
|
|
4639
|
+
const count = this._parseVarInto(scratch, true, kind);
|
|
4640
|
+
const declarations = this._releaseScratch(scratch, count);
|
|
4641
|
+
const init = /** @type {Node} */ (
|
|
4642
|
+
/** @type {unknown} */ (
|
|
4643
|
+
new VariableDeclarationNode(
|
|
4644
|
+
initStart,
|
|
4645
|
+
this.lastTokEnd,
|
|
4646
|
+
declarations,
|
|
4647
|
+
kind
|
|
4648
|
+
)
|
|
4649
|
+
)
|
|
4650
|
+
);
|
|
4651
|
+
return this._parseForAfterInitAt(start, init, awaitAt);
|
|
4652
|
+
}
|
|
4653
|
+
const startsWithLet = this.isContextual("let");
|
|
4654
|
+
let isForOf = false;
|
|
4655
|
+
const usingKind = this.isUsing(true)
|
|
4656
|
+
? "using"
|
|
4657
|
+
: this.isAwaitUsing(true)
|
|
4658
|
+
? "await using"
|
|
4659
|
+
: null;
|
|
4660
|
+
if (usingKind) {
|
|
4661
|
+
const initStart = this.start;
|
|
4662
|
+
this.next();
|
|
4663
|
+
if (usingKind === "await using") {
|
|
4664
|
+
if (!this.canAwait) {
|
|
4665
|
+
this.raise(
|
|
4666
|
+
this.start,
|
|
4667
|
+
"Await using cannot appear outside of async function"
|
|
4668
|
+
);
|
|
4669
|
+
}
|
|
4670
|
+
this.next();
|
|
4671
|
+
}
|
|
4672
|
+
const scratch = this._acquireScratch();
|
|
4673
|
+
const count = this._parseVarInto(scratch, true, usingKind);
|
|
4674
|
+
const declarations = this._releaseScratch(scratch, count);
|
|
4675
|
+
const init = /** @type {Node} */ (
|
|
4676
|
+
/** @type {unknown} */ (
|
|
4677
|
+
new VariableDeclarationNode(
|
|
4678
|
+
initStart,
|
|
4679
|
+
this.lastTokEnd,
|
|
4680
|
+
declarations,
|
|
4681
|
+
usingKind
|
|
4682
|
+
)
|
|
4683
|
+
)
|
|
4684
|
+
);
|
|
4685
|
+
return this._parseForAfterInitAt(start, init, awaitAt);
|
|
4686
|
+
}
|
|
4687
|
+
const containsEsc = this.containsEsc;
|
|
4688
|
+
const refDestructuringErrors = this._acquireDestructuringErrors();
|
|
4689
|
+
const initPos = this.start;
|
|
4690
|
+
const init =
|
|
4691
|
+
awaitAt > -1
|
|
4692
|
+
? this.parseExprSubscripts(refDestructuringErrors, "await")
|
|
4693
|
+
: this.parseExpression(true, refDestructuringErrors);
|
|
4694
|
+
if (this.type === tokTypes._in || (isForOf = this.isContextual("of"))) {
|
|
4695
|
+
let isAwait = false;
|
|
4696
|
+
if (awaitAt > -1) {
|
|
4697
|
+
if (this.type === tokTypes._in) this.unexpected(awaitAt);
|
|
4698
|
+
isAwait = true;
|
|
4699
|
+
} else if (
|
|
4700
|
+
isForOf &&
|
|
4701
|
+
init.start === initPos &&
|
|
4702
|
+
!containsEsc &&
|
|
4703
|
+
init.type === "Identifier" &&
|
|
4704
|
+
/** @type {Identifier} */ (init).name === "async"
|
|
4705
|
+
) {
|
|
4706
|
+
this.unexpected();
|
|
4707
|
+
}
|
|
4708
|
+
if (startsWithLet && isForOf) {
|
|
4709
|
+
this.raise(
|
|
4710
|
+
init.start,
|
|
4711
|
+
"The left-hand side of a for-of loop may not start with 'let'."
|
|
4712
|
+
);
|
|
4713
|
+
}
|
|
4714
|
+
this.toAssignable(init, false, refDestructuringErrors);
|
|
4715
|
+
this.checkLValPattern(init);
|
|
4716
|
+
this._releaseDestructuringErrors();
|
|
4717
|
+
return this._parseForInAt(start, isAwait, /** @type {Node} */ (init));
|
|
4718
|
+
}
|
|
4719
|
+
this.checkExpressionErrors(refDestructuringErrors, true);
|
|
4720
|
+
this._releaseDestructuringErrors();
|
|
4721
|
+
if (awaitAt > -1) this.unexpected(awaitAt);
|
|
4722
|
+
return this._parseForAt(start, /** @type {Node} */ (init));
|
|
4723
|
+
}
|
|
4724
|
+
|
|
4725
|
+
/**
|
|
4726
|
+
* `parseForAfterInit` without a started node.
|
|
4727
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/statement.js
|
|
4728
|
+
* @param {number} start statement start offset
|
|
4729
|
+
* @param {Node} init parsed variable declaration
|
|
4730
|
+
* @param {number} awaitAt offset of a consumed `await`, or -1
|
|
4731
|
+
* @returns {Node} for/for-in/for-of statement
|
|
4732
|
+
* @this {ParserInternals}
|
|
4733
|
+
*/
|
|
4734
|
+
_parseForAfterInitAt(start, init, awaitAt) {
|
|
4735
|
+
const target =
|
|
4736
|
+
/** @type {Node & { declarations: Node[], kind: string }} */ (init);
|
|
4737
|
+
if (
|
|
4738
|
+
(this.type === tokTypes._in || this.isContextual("of")) &&
|
|
4739
|
+
target.declarations.length === 1
|
|
4740
|
+
) {
|
|
4741
|
+
if (this.type === tokTypes._in) {
|
|
4742
|
+
if (
|
|
4743
|
+
(target.kind === "using" || target.kind === "await using") &&
|
|
4744
|
+
!(
|
|
4745
|
+
/** @type {Node & { init: Node | null }} */ (target.declarations[0])
|
|
4746
|
+
.init
|
|
4747
|
+
)
|
|
4748
|
+
) {
|
|
4749
|
+
this.raise(
|
|
4750
|
+
this.start,
|
|
4751
|
+
"Using declaration is not allowed in for-in loops"
|
|
4752
|
+
);
|
|
4753
|
+
}
|
|
4754
|
+
if (awaitAt > -1) this.unexpected(awaitAt);
|
|
4755
|
+
return this._parseForInAt(start, false, init);
|
|
4756
|
+
}
|
|
4757
|
+
return this._parseForInAt(start, awaitAt > -1, init);
|
|
4758
|
+
}
|
|
4759
|
+
if (awaitAt > -1) this.unexpected(awaitAt);
|
|
4760
|
+
return this._parseForAt(start, init);
|
|
4761
|
+
}
|
|
4762
|
+
|
|
4763
|
+
/**
|
|
4764
|
+
* `parseFor` without a started node, landing on `ForStatementNode`'s
|
|
4765
|
+
* single shape.
|
|
4766
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/statement.js
|
|
4767
|
+
* @param {number} start statement start offset
|
|
4768
|
+
* @param {Node | null} init init clause
|
|
4769
|
+
* @returns {Node} for statement
|
|
4770
|
+
* @this {ParserInternals}
|
|
4771
|
+
*/
|
|
4772
|
+
_parseForAt(start, init) {
|
|
4773
|
+
this.expect(tokTypes.semi);
|
|
4774
|
+
const test = this.type === tokTypes.semi ? null : this.parseExpression();
|
|
4775
|
+
this.expect(tokTypes.semi);
|
|
4776
|
+
const update =
|
|
4777
|
+
this.type === tokTypes.parenR ? null : this.parseExpression();
|
|
4778
|
+
this.expect(tokTypes.parenR);
|
|
4779
|
+
const body = this.parseStatement("for");
|
|
4780
|
+
this.exitScope();
|
|
4781
|
+
this.labels.pop();
|
|
4782
|
+
return /** @type {Node} */ (
|
|
4783
|
+
/** @type {unknown} */ (
|
|
4784
|
+
new ForStatementNode(start, this.lastTokEnd, init, test, update, body)
|
|
4785
|
+
)
|
|
4786
|
+
);
|
|
4787
|
+
}
|
|
4788
|
+
|
|
4789
|
+
/**
|
|
4790
|
+
* `parseForIn` without a started node, landing on `ForInStatementNode`/
|
|
4791
|
+
* `ForOfStatementNode`'s single shapes.
|
|
4792
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/statement.js
|
|
4793
|
+
* @param {number} start statement start offset
|
|
4794
|
+
* @param {boolean} isAwait whether this is `for await`
|
|
4795
|
+
* @param {Node} init loop target
|
|
4796
|
+
* @returns {Node} for-in or for-of statement
|
|
4797
|
+
* @this {ParserInternals}
|
|
4798
|
+
*/
|
|
4799
|
+
_parseForInAt(start, isAwait, init) {
|
|
4800
|
+
const isForIn = this.type === tokTypes._in;
|
|
4801
|
+
this.next();
|
|
4802
|
+
if (
|
|
4803
|
+
init.type === "VariableDeclaration" &&
|
|
4804
|
+
/** @type {Node & { init: Node | null }} */ (
|
|
4805
|
+
/** @type {Node & { declarations: Node[] }} */ (init).declarations[0]
|
|
4806
|
+
).init !== null &&
|
|
4807
|
+
(!isForIn ||
|
|
4808
|
+
this.strict ||
|
|
4809
|
+
/** @type {Node & { kind: string }} */ (init).kind !== "var" ||
|
|
4810
|
+
/** @type {Node & { id: Node }} */ (
|
|
4811
|
+
/** @type {Node & { declarations: Node[] }} */ (init).declarations[0]
|
|
4812
|
+
).id.type !== "Identifier")
|
|
4813
|
+
) {
|
|
4814
|
+
this.raise(
|
|
4815
|
+
init.start,
|
|
4816
|
+
`${
|
|
4817
|
+
isForIn ? "for-in" : "for-of"
|
|
4818
|
+
} loop variable declaration may not have an initializer`
|
|
4819
|
+
);
|
|
4820
|
+
}
|
|
4821
|
+
const right = isForIn ? this.parseExpression() : this.parseMaybeAssign();
|
|
4822
|
+
this.expect(tokTypes.parenR);
|
|
4823
|
+
const body = this.parseStatement("for");
|
|
4824
|
+
this.exitScope();
|
|
4825
|
+
this.labels.pop();
|
|
4826
|
+
return /** @type {Node} */ (
|
|
4827
|
+
/** @type {unknown} */ (
|
|
4828
|
+
isForIn
|
|
4829
|
+
? new ForInStatementNode(start, this.lastTokEnd, init, right, body)
|
|
4830
|
+
: new ForOfStatementNode(
|
|
4831
|
+
start,
|
|
4832
|
+
this.lastTokEnd,
|
|
4833
|
+
isAwait,
|
|
4834
|
+
init,
|
|
4835
|
+
right,
|
|
4836
|
+
body
|
|
4837
|
+
)
|
|
4838
|
+
)
|
|
4839
|
+
);
|
|
4840
|
+
}
|
|
4841
|
+
|
|
4842
|
+
/**
|
|
4843
|
+
* `parseSwitchStatement` without a started node, landing on
|
|
4844
|
+
* `SwitchStatementNode`'s single shape with pre-shaped `SwitchCaseNode`s.
|
|
4845
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/statement.js
|
|
4846
|
+
* @param {number} start statement start offset
|
|
4847
|
+
* @returns {Node} switch statement
|
|
4848
|
+
* @this {ParserInternals}
|
|
4849
|
+
*/
|
|
4850
|
+
_parseSwitchStatementAt(start) {
|
|
4851
|
+
this.next();
|
|
4852
|
+
const discriminant = this.parseParenExpression();
|
|
4853
|
+
/** @type {Node[]} */
|
|
4854
|
+
const cases = [];
|
|
4855
|
+
this.expect(tokTypes.braceL);
|
|
4856
|
+
this.labels.push(SWITCH_LABEL);
|
|
4857
|
+
this.enterScope(SCOPE_SWITCH);
|
|
4858
|
+
/** @type {SwitchCaseNode | undefined} */
|
|
4859
|
+
let cur;
|
|
4860
|
+
for (let sawDefault = false; this.type !== tokTypes.braceR;) {
|
|
4861
|
+
if (this.type === tokTypes._case || this.type === tokTypes._default) {
|
|
4862
|
+
const isCase = this.type === tokTypes._case;
|
|
4863
|
+
if (cur) this.finishNode(/** @type {Node} */ (cur), "SwitchCase");
|
|
4864
|
+
cur = new SwitchCaseNode(this.start);
|
|
4865
|
+
cases.push(/** @type {Node} */ (cur));
|
|
4866
|
+
cur.consequent = [];
|
|
4867
|
+
this.next();
|
|
4868
|
+
if (isCase) {
|
|
4869
|
+
cur.test = this.parseExpression();
|
|
4870
|
+
} else {
|
|
4871
|
+
if (sawDefault) {
|
|
4872
|
+
this.raiseRecoverable(
|
|
4873
|
+
this.lastTokStart,
|
|
4874
|
+
"Multiple default clauses"
|
|
4875
|
+
);
|
|
4876
|
+
}
|
|
4877
|
+
sawDefault = true;
|
|
4878
|
+
cur.test = null;
|
|
4879
|
+
}
|
|
4880
|
+
this.expect(tokTypes.colon);
|
|
4881
|
+
} else {
|
|
4882
|
+
if (!cur) this.unexpected();
|
|
4883
|
+
/** @type {Node[]} */ (
|
|
4884
|
+
/** @type {SwitchCaseNode} */ (cur).consequent
|
|
4885
|
+
).push(this.parseStatement(null));
|
|
4886
|
+
}
|
|
4887
|
+
}
|
|
4888
|
+
this.exitScope();
|
|
4889
|
+
if (cur) this.finishNode(/** @type {Node} */ (cur), "SwitchCase");
|
|
4890
|
+
this.next(); // closing brace
|
|
4891
|
+
this.labels.pop();
|
|
4892
|
+
return /** @type {Node} */ (
|
|
4893
|
+
/** @type {unknown} */ (
|
|
4894
|
+
new SwitchStatementNode(start, this.lastTokEnd, discriminant, cases)
|
|
4895
|
+
)
|
|
4896
|
+
);
|
|
4897
|
+
}
|
|
4898
|
+
|
|
4899
|
+
/**
|
|
4900
|
+
* `parseThrowStatement` without a started node; the illegal-newline probe
|
|
4901
|
+
* runs on the tokenizer's newline flag instead of acorn's gap slice+regexp.
|
|
4902
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/statement.js
|
|
4903
|
+
* @param {number} start statement start offset
|
|
4904
|
+
* @returns {Node} throw statement
|
|
4905
|
+
* @this {ParserInternals}
|
|
4906
|
+
*/
|
|
4907
|
+
_parseThrowStatementAt(start) {
|
|
4908
|
+
this.next();
|
|
4909
|
+
if (this._gapHasNewline()) {
|
|
4910
|
+
this.raise(this.lastTokEnd, "Illegal newline after throw");
|
|
4911
|
+
}
|
|
4912
|
+
const argument = this.parseExpression();
|
|
4913
|
+
this.semicolon();
|
|
4914
|
+
return /** @type {Node} */ (
|
|
4915
|
+
/** @type {unknown} */ (
|
|
4916
|
+
new ThrowStatementNode(start, this.lastTokEnd, argument)
|
|
4917
|
+
)
|
|
4918
|
+
);
|
|
4919
|
+
}
|
|
4920
|
+
|
|
4921
|
+
/**
|
|
4922
|
+
* `parseTryStatement` without a started node, landing on
|
|
4923
|
+
* `TryStatementNode`/`CatchClauseNode`'s single shapes.
|
|
4924
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/statement.js
|
|
4925
|
+
* @param {number} start statement start offset
|
|
4926
|
+
* @returns {Node} try statement
|
|
4927
|
+
* @this {ParserInternals}
|
|
4928
|
+
*/
|
|
4929
|
+
_parseTryStatementAt(start) {
|
|
4930
|
+
this.next();
|
|
4931
|
+
const block = this.parseBlock();
|
|
4932
|
+
/** @type {Node | null} */
|
|
4933
|
+
let handler = null;
|
|
4934
|
+
if (this.type === tokTypes._catch) {
|
|
4935
|
+
const clauseStart = this.start;
|
|
4936
|
+
this.next();
|
|
4937
|
+
/** @type {Node | null} */
|
|
4938
|
+
let param;
|
|
4939
|
+
if (this.eat(tokTypes.parenL)) {
|
|
4940
|
+
param = this.parseCatchClauseParam();
|
|
4941
|
+
} else {
|
|
4942
|
+
if (this._ecmaVersion < 10) this.unexpected();
|
|
4943
|
+
param = null;
|
|
4944
|
+
this.enterScope(0);
|
|
4945
|
+
}
|
|
4946
|
+
const body = this.parseBlock(false);
|
|
4947
|
+
this.exitScope();
|
|
4948
|
+
handler = /** @type {Node} */ (
|
|
4949
|
+
/** @type {unknown} */ (
|
|
4950
|
+
new CatchClauseNode(clauseStart, this.lastTokEnd, param, body)
|
|
4951
|
+
)
|
|
4952
|
+
);
|
|
4953
|
+
}
|
|
4954
|
+
const finalizer = this.eat(tokTypes._finally) ? this.parseBlock() : null;
|
|
4955
|
+
if (!handler && !finalizer) {
|
|
4956
|
+
this.raise(start, "Missing catch or finally clause");
|
|
4957
|
+
}
|
|
4958
|
+
return /** @type {Node} */ (
|
|
4959
|
+
/** @type {unknown} */ (
|
|
4960
|
+
new TryStatementNode(start, this.lastTokEnd, block, handler, finalizer)
|
|
4961
|
+
)
|
|
4962
|
+
);
|
|
4963
|
+
}
|
|
4964
|
+
|
|
4965
|
+
/**
|
|
4966
|
+
* `parseWhileStatement` without a started node, landing on
|
|
4967
|
+
* `WhileStatementNode`'s single shape.
|
|
4968
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/statement.js
|
|
4969
|
+
* @param {number} start statement start offset
|
|
4970
|
+
* @returns {Node} while statement
|
|
4971
|
+
* @this {ParserInternals}
|
|
4972
|
+
*/
|
|
4973
|
+
_parseWhileStatementAt(start) {
|
|
4974
|
+
this.next();
|
|
4975
|
+
const test = this.parseParenExpression();
|
|
4976
|
+
this.labels.push(LOOP_LABEL);
|
|
4977
|
+
const body = this.parseStatement("while");
|
|
4978
|
+
this.labels.pop();
|
|
4979
|
+
return /** @type {Node} */ (
|
|
4980
|
+
/** @type {unknown} */ (
|
|
4981
|
+
new WhileStatementNode(start, this.lastTokEnd, test, body)
|
|
4982
|
+
)
|
|
4983
|
+
);
|
|
4984
|
+
}
|
|
4985
|
+
|
|
4986
|
+
/**
|
|
4987
|
+
* Owned `parseSpread` landing on `RestSpreadNode`'s single shape.
|
|
4988
|
+
* Non-lazy mode delegates.
|
|
4989
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/lval.js
|
|
4990
|
+
* @param {DestructuringErrorsShim | null=} refDestructuringErrors destructuring errors to fill
|
|
4991
|
+
* @returns {Node} spread element
|
|
4992
|
+
* @this {ParserInternals}
|
|
4993
|
+
*/
|
|
4994
|
+
parseSpread(refDestructuringErrors) {
|
|
4995
|
+
if (!this._lazy) {
|
|
4996
|
+
return base.parseSpread.call(this, refDestructuringErrors);
|
|
4997
|
+
}
|
|
4998
|
+
const start = this.start;
|
|
4999
|
+
this.next();
|
|
5000
|
+
const argument = this.parseMaybeAssign(false, refDestructuringErrors);
|
|
5001
|
+
return /** @type {Node} */ (
|
|
5002
|
+
/** @type {unknown} */ (
|
|
5003
|
+
new RestSpreadNode(start, this.lastTokEnd, "SpreadElement", argument)
|
|
5004
|
+
)
|
|
5005
|
+
);
|
|
5006
|
+
}
|
|
5007
|
+
|
|
5008
|
+
/**
|
|
5009
|
+
* Owned `parseMaybeConditional` landing on
|
|
5010
|
+
* `ConditionalExpressionNode`'s single shape. Non-lazy mode delegates.
|
|
5011
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/expression.js
|
|
5012
|
+
* @param {boolean | string=} forInit for-init context flag
|
|
5013
|
+
* @param {DestructuringErrorsShim | null=} refDestructuringErrors destructuring errors to fill
|
|
5014
|
+
* @returns {Expression} expression node
|
|
5015
|
+
* @this {ParserInternals}
|
|
5016
|
+
*/
|
|
5017
|
+
parseMaybeConditional(forInit, refDestructuringErrors) {
|
|
5018
|
+
if (!this._lazy) {
|
|
5019
|
+
return base.parseMaybeConditional.call(
|
|
5020
|
+
this,
|
|
5021
|
+
forInit,
|
|
5022
|
+
refDestructuringErrors
|
|
5023
|
+
);
|
|
5024
|
+
}
|
|
5025
|
+
const startPos = this.start;
|
|
5026
|
+
const expr = this.parseExprOps(forInit, refDestructuringErrors);
|
|
5027
|
+
if (this.checkExpressionErrors(refDestructuringErrors)) return expr;
|
|
5028
|
+
const isArrowAtStart = this._arrowFastPath
|
|
5029
|
+
? expr === this._lastArrow && expr.start === startPos
|
|
5030
|
+
: expr.type === "ArrowFunctionExpression" && expr.start === startPos;
|
|
5031
|
+
if (!isArrowAtStart && this.eat(tokTypes.question)) {
|
|
5032
|
+
const consequent = this.parseMaybeAssign();
|
|
5033
|
+
this.expect(tokTypes.colon);
|
|
5034
|
+
const alternate = this.parseMaybeAssign(forInit);
|
|
5035
|
+
return /** @type {Expression} */ (
|
|
5036
|
+
/** @type {unknown} */ (
|
|
5037
|
+
new ConditionalExpressionNode(
|
|
5038
|
+
startPos,
|
|
5039
|
+
this.lastTokEnd,
|
|
5040
|
+
expr,
|
|
5041
|
+
consequent,
|
|
5042
|
+
alternate
|
|
5043
|
+
)
|
|
5044
|
+
)
|
|
5045
|
+
);
|
|
5046
|
+
}
|
|
5047
|
+
return expr;
|
|
5048
|
+
}
|
|
5049
|
+
|
|
5050
|
+
/**
|
|
5051
|
+
* acorn's `parseArrowExpression` plus `_lastArrow` tracking — arrows are
|
|
5052
|
+
* created and returned only here, so the expression-spine probes can test
|
|
5053
|
+
* node identity instead of the megamorphic `.type` load. A plugin fabricating
|
|
5054
|
+
* arrow nodes in an overridden `parseExprAtom` bypasses the gate (same
|
|
5055
|
+
* acceptance class as `_stmtFastPath`).
|
|
5056
|
+
* @param {Node} node started node
|
|
5057
|
+
* @param {Node[]} params parameter expressions
|
|
5058
|
+
* @param {boolean} isAsync async arrow
|
|
5059
|
+
* @param {boolean | string=} forInit for-init context flag
|
|
5060
|
+
* @returns {Expression} arrow function expression
|
|
5061
|
+
* @this {ParserInternals}
|
|
5062
|
+
*/
|
|
5063
|
+
parseArrowExpression(node, params, isAsync, forInit) {
|
|
5064
|
+
if (!this._funcFastPath) {
|
|
5065
|
+
const result = base.parseArrowExpression.call(
|
|
5066
|
+
this,
|
|
5067
|
+
node,
|
|
5068
|
+
params,
|
|
5069
|
+
isAsync,
|
|
5070
|
+
forInit
|
|
5071
|
+
);
|
|
5072
|
+
this._lastArrow = result;
|
|
5073
|
+
return result;
|
|
5074
|
+
}
|
|
5075
|
+
// acorn's body with the started node replaced by the pre-shaped
|
|
5076
|
+
// FunctionNode (initFunction's writes are its constructor defaults)
|
|
5077
|
+
const functionNode = /** @type {Node} */ (
|
|
5078
|
+
/** @type {unknown} */ (new FunctionNode(node.start))
|
|
5079
|
+
);
|
|
5080
|
+
const oldYieldPos = this.yieldPos;
|
|
5081
|
+
const oldAwaitPos = this.awaitPos;
|
|
5082
|
+
const oldAwaitIdentPos = this.awaitIdentPos;
|
|
5083
|
+
this.enterScope(SCOPE_FUNCTION | (isAsync ? SCOPE_ASYNC : 0) | SCOPE_ARROW);
|
|
5084
|
+
/** @type {Node & { async: boolean, params?: Node[] }} */ (
|
|
5085
|
+
functionNode
|
|
5086
|
+
).async = Boolean(isAsync);
|
|
5087
|
+
this.yieldPos = 0;
|
|
5088
|
+
this.awaitPos = 0;
|
|
5089
|
+
this.awaitIdentPos = 0;
|
|
5090
|
+
/** @type {Node & { params?: Node[] }} */ (functionNode).params =
|
|
5091
|
+
/** @type {Node[]} */ (this.toAssignableList(params, true));
|
|
5092
|
+
this.parseFunctionBody(functionNode, true, false, forInit);
|
|
5093
|
+
this.yieldPos = oldYieldPos;
|
|
5094
|
+
this.awaitPos = oldAwaitPos;
|
|
5095
|
+
this.awaitIdentPos = oldAwaitIdentPos;
|
|
5096
|
+
const result = /** @type {Expression} */ (
|
|
5097
|
+
/** @type {unknown} */ (
|
|
5098
|
+
this.finishNode(functionNode, "ArrowFunctionExpression")
|
|
5099
|
+
)
|
|
5100
|
+
);
|
|
5101
|
+
this._lastArrow = result;
|
|
5102
|
+
return result;
|
|
5103
|
+
}
|
|
5104
|
+
|
|
5105
|
+
/**
|
|
5106
|
+
* Owned `parseFunction`, an exact-semantics copy of acorn 8's landing on
|
|
5107
|
+
* `FunctionNode`'s pre-declared shape (the passed started node is discarded,
|
|
5108
|
+
* matching acorn's observable output; `initFunction`'s writes are the
|
|
5109
|
+
* constructor defaults). Non-lazy mode and plugin overrides delegate.
|
|
5110
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/statement.js
|
|
5111
|
+
* @param {Node} node started node from the caller
|
|
5112
|
+
* @param {number} statement FUNC_* statement bit flags
|
|
5113
|
+
* @param {boolean=} allowExpressionBody whether an expression body is allowed
|
|
5114
|
+
* @param {boolean=} isAsync whether the function is async
|
|
5115
|
+
* @param {boolean | string=} forInit for-init context flag
|
|
5116
|
+
* @returns {Expression} function declaration or expression
|
|
5117
|
+
* @this {ParserInternals}
|
|
5118
|
+
*/
|
|
5119
|
+
parseFunction(node, statement, allowExpressionBody, isAsync, forInit) {
|
|
5120
|
+
if (!this._funcFastPath) {
|
|
5121
|
+
return base.parseFunction.call(
|
|
5122
|
+
this,
|
|
5123
|
+
node,
|
|
5124
|
+
statement,
|
|
5125
|
+
allowExpressionBody,
|
|
5126
|
+
isAsync,
|
|
5127
|
+
forInit
|
|
5128
|
+
);
|
|
5129
|
+
}
|
|
5130
|
+
return this._parseFunctionAt(
|
|
5131
|
+
node.start,
|
|
5132
|
+
statement,
|
|
5133
|
+
allowExpressionBody === true,
|
|
5134
|
+
isAsync === true,
|
|
5135
|
+
forInit
|
|
5136
|
+
);
|
|
5137
|
+
}
|
|
5138
|
+
|
|
5139
|
+
/**
|
|
5140
|
+
* `parseFunction` without a started node (fast-path gate guarantees
|
|
5141
|
+
* `ecmaVersion >= 9`, folding acorn's version probes).
|
|
5142
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/statement.js
|
|
5143
|
+
* @param {number} start function start offset
|
|
5144
|
+
* @param {number} statement FUNC_* statement bit flags
|
|
5145
|
+
* @param {boolean} allowExpressionBody whether an expression body is allowed
|
|
5146
|
+
* @param {boolean} isAsync whether the function is async
|
|
5147
|
+
* @param {boolean | string=} forInit for-init context flag
|
|
5148
|
+
* @returns {Expression} function declaration or expression
|
|
5149
|
+
* @this {ParserInternals}
|
|
5150
|
+
*/
|
|
5151
|
+
_parseFunctionAt(start, statement, allowExpressionBody, isAsync, forInit) {
|
|
5152
|
+
const node =
|
|
5153
|
+
/** @type {Node & { id: Identifier | null, generator: boolean, async: boolean }} */ (
|
|
5154
|
+
/** @type {unknown} */ (new FunctionNode(start))
|
|
5155
|
+
);
|
|
5156
|
+
if (this.type === tokTypes.star && statement & FUNC_HANGING_STATEMENT) {
|
|
5157
|
+
this.unexpected();
|
|
5158
|
+
}
|
|
5159
|
+
node.generator = this.eat(tokTypes.star);
|
|
5160
|
+
node.async = isAsync;
|
|
5161
|
+
if (statement & FUNC_STATEMENT) {
|
|
5162
|
+
node.id =
|
|
5163
|
+
statement & FUNC_NULLABLE_ID && this.type !== tokTypes.name
|
|
5164
|
+
? null
|
|
5165
|
+
: this.parseIdent();
|
|
5166
|
+
if (node.id && !(statement & FUNC_HANGING_STATEMENT)) {
|
|
5167
|
+
// Annex B: sloppy-mode function declarations bind like vars
|
|
5168
|
+
this.checkLValSimple(
|
|
5169
|
+
node.id,
|
|
5170
|
+
this.strict || node.generator || node.async
|
|
5171
|
+
? this.treatFunctionsAsVar
|
|
5172
|
+
? BIND_VAR
|
|
5173
|
+
: BIND_LEXICAL
|
|
5174
|
+
: /* BIND_FUNCTION */ 3
|
|
5175
|
+
);
|
|
5176
|
+
}
|
|
5177
|
+
}
|
|
5178
|
+
const oldYieldPos = this.yieldPos;
|
|
5179
|
+
const oldAwaitPos = this.awaitPos;
|
|
5180
|
+
const oldAwaitIdentPos = this.awaitIdentPos;
|
|
5181
|
+
this.yieldPos = 0;
|
|
5182
|
+
this.awaitPos = 0;
|
|
5183
|
+
this.awaitIdentPos = 0;
|
|
5184
|
+
this.enterScope(
|
|
5185
|
+
SCOPE_FUNCTION |
|
|
5186
|
+
(node.async ? SCOPE_ASYNC : 0) |
|
|
5187
|
+
(node.generator ? SCOPE_GENERATOR : 0)
|
|
5188
|
+
);
|
|
5189
|
+
if (!(statement & FUNC_STATEMENT)) {
|
|
5190
|
+
node.id = this.type === tokTypes.name ? this.parseIdent() : null;
|
|
5191
|
+
}
|
|
5192
|
+
this.parseFunctionParams(node);
|
|
5193
|
+
this.parseFunctionBody(node, allowExpressionBody, false, forInit);
|
|
5194
|
+
this.yieldPos = oldYieldPos;
|
|
5195
|
+
this.awaitPos = oldAwaitPos;
|
|
5196
|
+
this.awaitIdentPos = oldAwaitIdentPos;
|
|
5197
|
+
return /** @type {Expression} */ (
|
|
5198
|
+
/** @type {unknown} */ (
|
|
5199
|
+
this.finishNode(
|
|
5200
|
+
node,
|
|
5201
|
+
statement & FUNC_STATEMENT
|
|
5202
|
+
? "FunctionDeclaration"
|
|
5203
|
+
: "FunctionExpression"
|
|
5204
|
+
)
|
|
5205
|
+
)
|
|
5206
|
+
);
|
|
5207
|
+
}
|
|
5208
|
+
|
|
5209
|
+
/**
|
|
5210
|
+
* Owned `parseFunctionBody`, an exact-semantics copy of acorn 8's with
|
|
5211
|
+
* `isSimpleParamList` inlined and computed once (acorn walks the params
|
|
5212
|
+
* twice) — the fast-path gate pins it to acorn's own implementation.
|
|
5213
|
+
* Non-lazy mode and plugin overrides delegate.
|
|
5214
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/statement.js
|
|
5215
|
+
* @param {Node} node function node being filled
|
|
5216
|
+
* @param {boolean} isArrowFunction whether this is an arrow function
|
|
5217
|
+
* @param {boolean} isMethod whether this is an object/class method
|
|
5218
|
+
* @param {boolean | string=} forInit for-init context flag
|
|
5219
|
+
* @returns {void}
|
|
5220
|
+
* @this {ParserInternals}
|
|
5221
|
+
*/
|
|
5222
|
+
parseFunctionBody(node, isArrowFunction, isMethod, forInit) {
|
|
5223
|
+
if (!this._funcFastPath) {
|
|
5224
|
+
return base.parseFunctionBody.call(
|
|
5225
|
+
this,
|
|
5226
|
+
node,
|
|
5227
|
+
isArrowFunction,
|
|
5228
|
+
isMethod,
|
|
5229
|
+
forInit
|
|
5230
|
+
);
|
|
5231
|
+
}
|
|
5232
|
+
const target =
|
|
5233
|
+
/** @type {Node & { id: Identifier | null, params: Node[], body: Node, expression: boolean }} */ (
|
|
5234
|
+
node
|
|
5235
|
+
);
|
|
5236
|
+
const isExpression = isArrowFunction && this.type !== tokTypes.braceL;
|
|
5237
|
+
const oldStrict = this.strict;
|
|
5238
|
+
let useStrict = false;
|
|
5239
|
+
if (isExpression) {
|
|
5240
|
+
target.body = this.parseMaybeAssign(forInit);
|
|
5241
|
+
target.expression = true;
|
|
5242
|
+
this.checkParams(node, false);
|
|
5243
|
+
} else {
|
|
5244
|
+
// acorn's isSimpleParamList, inlined and shared by both its call sites
|
|
5245
|
+
const params = target.params;
|
|
5246
|
+
let simpleParams = true;
|
|
5247
|
+
for (let i = 0; i < params.length; i++) {
|
|
5248
|
+
if (params[i].type !== "Identifier") {
|
|
5249
|
+
simpleParams = false;
|
|
5250
|
+
break;
|
|
5251
|
+
}
|
|
5252
|
+
}
|
|
5253
|
+
if (!oldStrict || !simpleParams) {
|
|
5254
|
+
useStrict = this.strictDirective(this.end);
|
|
5255
|
+
if (useStrict && !simpleParams) {
|
|
5256
|
+
this.raiseRecoverable(
|
|
5257
|
+
node.start,
|
|
5258
|
+
"Illegal 'use strict' directive in function with non-simple parameter list"
|
|
5259
|
+
);
|
|
5260
|
+
}
|
|
5261
|
+
}
|
|
5262
|
+
const oldLabels = this.labels;
|
|
5263
|
+
this.labels = [];
|
|
5264
|
+
if (useStrict) this.strict = true;
|
|
5265
|
+
this.checkParams(
|
|
5266
|
+
node,
|
|
5267
|
+
!oldStrict &&
|
|
5268
|
+
!useStrict &&
|
|
5269
|
+
!isArrowFunction &&
|
|
5270
|
+
!isMethod &&
|
|
5271
|
+
simpleParams
|
|
5272
|
+
);
|
|
5273
|
+
if (this.strict && target.id) {
|
|
5274
|
+
this.checkLValSimple(target.id, BIND_OUTSIDE);
|
|
5275
|
+
}
|
|
5276
|
+
target.body = this.parseBlock(false, undefined, useStrict && !oldStrict);
|
|
5277
|
+
target.expression = false;
|
|
5278
|
+
this.adaptDirectivePrologue(
|
|
5279
|
+
/** @type {Node & { body: Node[] }} */ (target.body).body
|
|
5280
|
+
);
|
|
5281
|
+
this.labels = oldLabels;
|
|
5282
|
+
}
|
|
5283
|
+
this.exitScope();
|
|
5284
|
+
}
|
|
5285
|
+
|
|
5286
|
+
/**
|
|
5287
|
+
* Owned `parseBindingAtom`: acorn's exact dispatch minus the per-call
|
|
5288
|
+
* normalized-options read. Non-lazy mode and pre-ES6 delegate.
|
|
5289
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/lval.js
|
|
5290
|
+
* @returns {Node} binding atom (identifier or pattern)
|
|
5291
|
+
* @this {ParserInternals}
|
|
5292
|
+
*/
|
|
5293
|
+
parseBindingAtom() {
|
|
5294
|
+
if (!this._lazy || this._ecmaVersion < 6) {
|
|
5295
|
+
return base.parseBindingAtom.call(this);
|
|
5296
|
+
}
|
|
5297
|
+
const type = this.type;
|
|
5298
|
+
if (type === tokTypes.bracketL) {
|
|
5299
|
+
const node = /** @type {Node & { elements?: Node[] }} */ (
|
|
5300
|
+
this.startNode()
|
|
5301
|
+
);
|
|
5302
|
+
this.next();
|
|
5303
|
+
node.elements = this.parseBindingList(tokTypes.bracketR, true, true);
|
|
5304
|
+
return this.finishNode(node, "ArrayPattern");
|
|
5305
|
+
}
|
|
5306
|
+
if (type === tokTypes.braceL) return this.parseObj(true);
|
|
5307
|
+
return this.parseIdent();
|
|
5308
|
+
}
|
|
5309
|
+
|
|
5310
|
+
/**
|
|
5311
|
+
* Owned `parseExprSubscripts`, an exact copy of acorn 8's with the arrow
|
|
5312
|
+
* probe served by `_lastArrow` identity. Delegates when the fast path is off.
|
|
5313
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/expression.js
|
|
5314
|
+
* @param {DestructuringErrorsShim | null=} refDestructuringErrors destructuring errors to fill
|
|
5315
|
+
* @param {boolean | string=} forInit for-init context flag
|
|
5316
|
+
* @returns {Expression} expression node
|
|
5317
|
+
* @this {ParserInternals}
|
|
5318
|
+
*/
|
|
5319
|
+
parseExprSubscripts(refDestructuringErrors, forInit) {
|
|
5320
|
+
if (!this._arrowFastPath) {
|
|
5321
|
+
return base.parseExprSubscripts.call(
|
|
5322
|
+
this,
|
|
5323
|
+
refDestructuringErrors,
|
|
5324
|
+
forInit
|
|
5325
|
+
);
|
|
5326
|
+
}
|
|
5327
|
+
const startPos = this.start;
|
|
5328
|
+
const startLoc = this.startLoc;
|
|
5329
|
+
const expr = this.parseExprAtom(refDestructuringErrors, forInit);
|
|
5330
|
+
if (
|
|
5331
|
+
expr === this._lastArrow &&
|
|
5332
|
+
this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")"
|
|
5333
|
+
) {
|
|
5334
|
+
return expr;
|
|
5335
|
+
}
|
|
5336
|
+
const result = this.parseSubscripts(
|
|
5337
|
+
expr,
|
|
5338
|
+
startPos,
|
|
5339
|
+
startLoc,
|
|
5340
|
+
false,
|
|
5341
|
+
forInit
|
|
5342
|
+
);
|
|
5343
|
+
if (refDestructuringErrors && result.type === "MemberExpression") {
|
|
5344
|
+
if (refDestructuringErrors.parenthesizedAssign >= result.start) {
|
|
5345
|
+
refDestructuringErrors.parenthesizedAssign = -1;
|
|
5346
|
+
}
|
|
5347
|
+
if (refDestructuringErrors.parenthesizedBind >= result.start) {
|
|
5348
|
+
refDestructuringErrors.parenthesizedBind = -1;
|
|
5349
|
+
}
|
|
5350
|
+
if (refDestructuringErrors.trailingComma >= result.start) {
|
|
5351
|
+
refDestructuringErrors.trailingComma = -1;
|
|
5352
|
+
}
|
|
5353
|
+
}
|
|
5354
|
+
return result;
|
|
5355
|
+
}
|
|
5356
|
+
|
|
5357
|
+
/**
|
|
5358
|
+
* Owned `parseExprList`, an exact-semantics copy of acorn 8's built in a
|
|
5359
|
+
* scratch array and materialized exactly sized. Non-lazy mode delegates.
|
|
5360
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/expression.js
|
|
5361
|
+
* @param {TokenType} close closing token type
|
|
5362
|
+
* @param {boolean} allowTrailingComma whether a trailing comma is allowed
|
|
5363
|
+
* @param {boolean} allowEmpty whether holes are allowed
|
|
5364
|
+
* @param {DestructuringErrorsShim | null=} refDestructuringErrors destructuring errors to fill
|
|
5365
|
+
* @returns {Expression[]} parsed elements (`null` for holes)
|
|
5366
|
+
* @this {ParserInternals}
|
|
5367
|
+
*/
|
|
5368
|
+
parseExprList(close, allowTrailingComma, allowEmpty, refDestructuringErrors) {
|
|
5369
|
+
if (!this._lazy) {
|
|
5370
|
+
return base.parseExprList.call(
|
|
5371
|
+
this,
|
|
5372
|
+
close,
|
|
5373
|
+
allowTrailingComma,
|
|
5374
|
+
allowEmpty,
|
|
5375
|
+
refDestructuringErrors
|
|
5376
|
+
);
|
|
5377
|
+
}
|
|
5378
|
+
const scratch = this._acquireScratch();
|
|
5379
|
+
let count = 0;
|
|
5380
|
+
let first = true;
|
|
5381
|
+
while (!this.eat(close)) {
|
|
5382
|
+
if (!first) {
|
|
5383
|
+
this.expect(tokTypes.comma);
|
|
5384
|
+
if (allowTrailingComma && this.afterTrailingComma(close)) break;
|
|
5385
|
+
} else {
|
|
5386
|
+
first = false;
|
|
5387
|
+
}
|
|
5388
|
+
let elt;
|
|
5389
|
+
if (allowEmpty && this.type === tokTypes.comma) {
|
|
5390
|
+
elt = null;
|
|
5391
|
+
} else if (this.type === tokTypes.ellipsis) {
|
|
5392
|
+
elt = this.parseSpread(refDestructuringErrors);
|
|
5393
|
+
if (
|
|
5394
|
+
refDestructuringErrors &&
|
|
5395
|
+
this.type === tokTypes.comma &&
|
|
5396
|
+
refDestructuringErrors.trailingComma < 0
|
|
5397
|
+
) {
|
|
5398
|
+
refDestructuringErrors.trailingComma = this.start;
|
|
5399
|
+
}
|
|
5400
|
+
} else {
|
|
5401
|
+
elt = this.parseMaybeAssign(false, refDestructuringErrors);
|
|
5402
|
+
}
|
|
5403
|
+
scratch[count++] = elt;
|
|
5404
|
+
}
|
|
5405
|
+
return this._releaseScratch(scratch, count);
|
|
5406
|
+
}
|
|
5407
|
+
|
|
5408
|
+
/**
|
|
5409
|
+
* Owned `parseBindingList`, an exact-semantics copy of acorn 8's built in a
|
|
5410
|
+
* scratch array and materialized exactly sized. Non-lazy mode delegates.
|
|
5411
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/lval.js
|
|
5412
|
+
* @param {TokenType} close closing token type
|
|
5413
|
+
* @param {boolean} allowEmpty whether holes are allowed
|
|
5414
|
+
* @param {boolean} allowTrailingComma whether a trailing comma is allowed
|
|
5415
|
+
* @param {boolean=} allowModifiers passed through to `parseAssignableListItem`
|
|
5416
|
+
* @returns {Node[]} parsed bindings (`null` for holes)
|
|
5417
|
+
* @this {ParserInternals}
|
|
5418
|
+
*/
|
|
5419
|
+
parseBindingList(close, allowEmpty, allowTrailingComma, allowModifiers) {
|
|
5420
|
+
if (!this._lazy) {
|
|
5421
|
+
return base.parseBindingList.call(
|
|
5422
|
+
this,
|
|
5423
|
+
close,
|
|
5424
|
+
allowEmpty,
|
|
5425
|
+
allowTrailingComma,
|
|
5426
|
+
allowModifiers
|
|
5427
|
+
);
|
|
5428
|
+
}
|
|
5429
|
+
const scratch = this._acquireScratch();
|
|
5430
|
+
let count = 0;
|
|
5431
|
+
let first = true;
|
|
5432
|
+
while (!this.eat(close)) {
|
|
5433
|
+
if (first) first = false;
|
|
5434
|
+
else this.expect(tokTypes.comma);
|
|
5435
|
+
if (allowEmpty && this.type === tokTypes.comma) {
|
|
5436
|
+
scratch[count++] = null;
|
|
5437
|
+
} else if (allowTrailingComma && this.afterTrailingComma(close)) {
|
|
5438
|
+
break;
|
|
5439
|
+
} else if (this.type === tokTypes.ellipsis) {
|
|
5440
|
+
const rest = this.parseRestBinding();
|
|
5441
|
+
this.parseBindingListItem(rest);
|
|
5442
|
+
scratch[count++] = rest;
|
|
5443
|
+
if (this.type === tokTypes.comma) {
|
|
5444
|
+
this.raiseRecoverable(
|
|
5445
|
+
this.start,
|
|
5446
|
+
"Comma is not permitted after the rest element"
|
|
5447
|
+
);
|
|
5448
|
+
}
|
|
5449
|
+
this.expect(close);
|
|
5450
|
+
break;
|
|
5451
|
+
} else {
|
|
5452
|
+
scratch[count++] = this.parseAssignableListItem(allowModifiers);
|
|
5453
|
+
}
|
|
5454
|
+
}
|
|
5455
|
+
return this._releaseScratch(scratch, count);
|
|
5456
|
+
}
|
|
5457
|
+
|
|
5458
|
+
/**
|
|
5459
|
+
* Owned `parseParenAndDistinguishExpression`, an exact-semantics copy of
|
|
5460
|
+
* acorn 8's with the per-paren `DestructuringErrors` record pooled and the
|
|
5461
|
+
* expression list built in a scratch array. Non-lazy mode delegates (the
|
|
5462
|
+
* copy assumes ES6+, which `_lazy` guarantees via `ecmaVersion: "latest"`).
|
|
5463
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/expression.js
|
|
5464
|
+
* @param {boolean} canBeArrow whether this may be an arrow head
|
|
5465
|
+
* @param {boolean | string} forInit for-init context flag
|
|
5466
|
+
* @returns {Expression} expression node
|
|
5467
|
+
* @this {ParserInternals}
|
|
5468
|
+
*/
|
|
5469
|
+
parseParenAndDistinguishExpression(canBeArrow, forInit) {
|
|
5470
|
+
if (!this._lazy || this._ecmaVersion < 6) {
|
|
5471
|
+
return base.parseParenAndDistinguishExpression.call(
|
|
5472
|
+
this,
|
|
5473
|
+
canBeArrow,
|
|
5474
|
+
forInit
|
|
5475
|
+
);
|
|
5476
|
+
}
|
|
5477
|
+
const startPos = this.start;
|
|
5478
|
+
const startLoc = this.startLoc;
|
|
5479
|
+
const allowTrailingComma = this._ecmaVersion >= 8;
|
|
5480
|
+
this.next();
|
|
5481
|
+
|
|
5482
|
+
const innerStartPos = this.start;
|
|
5483
|
+
const innerStartLoc = this.startLoc;
|
|
5484
|
+
const scratch = this._acquireScratch();
|
|
5485
|
+
let count = 0;
|
|
5486
|
+
let first = true;
|
|
5487
|
+
let lastIsComma = false;
|
|
5488
|
+
const refDestructuringErrors = this._acquireDestructuringErrors();
|
|
5489
|
+
const oldYieldPos = this.yieldPos;
|
|
5490
|
+
const oldAwaitPos = this.awaitPos;
|
|
5491
|
+
let spreadStart;
|
|
5492
|
+
this.yieldPos = 0;
|
|
5493
|
+
this.awaitPos = 0;
|
|
5494
|
+
// Do not save awaitIdentPos to allow checking awaits nested in parameters
|
|
5495
|
+
while (this.type !== tokTypes.parenR) {
|
|
5496
|
+
if (first) first = false;
|
|
5497
|
+
else this.expect(tokTypes.comma);
|
|
5498
|
+
if (
|
|
5499
|
+
allowTrailingComma &&
|
|
5500
|
+
this.afterTrailingComma(tokTypes.parenR, true)
|
|
5501
|
+
) {
|
|
5502
|
+
lastIsComma = true;
|
|
5503
|
+
break;
|
|
5504
|
+
} else if (this.type === tokTypes.ellipsis) {
|
|
5505
|
+
spreadStart = this.start;
|
|
5506
|
+
scratch[count++] = this.parseParenItem(this.parseRestBinding());
|
|
5507
|
+
if (this.type === tokTypes.comma) {
|
|
5508
|
+
this.raiseRecoverable(
|
|
5509
|
+
this.start,
|
|
5510
|
+
"Comma is not permitted after the rest element"
|
|
5511
|
+
);
|
|
5512
|
+
}
|
|
5513
|
+
break;
|
|
5514
|
+
} else {
|
|
5515
|
+
scratch[count++] = this.parseMaybeAssign(
|
|
5516
|
+
false,
|
|
5517
|
+
refDestructuringErrors,
|
|
5518
|
+
this.parseParenItem
|
|
5519
|
+
);
|
|
5520
|
+
}
|
|
5521
|
+
}
|
|
5522
|
+
const exprList = this._releaseScratch(scratch, count);
|
|
5523
|
+
const innerEndPos = this.lastTokEnd;
|
|
5524
|
+
this.expect(tokTypes.parenR);
|
|
5525
|
+
|
|
5526
|
+
if (
|
|
5527
|
+
canBeArrow &&
|
|
5528
|
+
this.shouldParseArrow(exprList) &&
|
|
5529
|
+
this.eat(tokTypes.arrow)
|
|
3544
5530
|
) {
|
|
3545
|
-
|
|
5531
|
+
this.checkPatternErrors(refDestructuringErrors, false);
|
|
5532
|
+
this.checkYieldAwaitInDefaultParams();
|
|
5533
|
+
// last read of the pooled record was above, so the arrow body parse
|
|
5534
|
+
// below can already reuse its pool slot
|
|
5535
|
+
this._releaseDestructuringErrors();
|
|
5536
|
+
this.yieldPos = oldYieldPos;
|
|
5537
|
+
this.awaitPos = oldAwaitPos;
|
|
5538
|
+
return this.parseParenArrowList(startPos, startLoc, exprList, forInit);
|
|
3546
5539
|
}
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
this.
|
|
3552
|
-
this.
|
|
3553
|
-
|
|
5540
|
+
|
|
5541
|
+
if (exprList.length === 0 || lastIsComma) {
|
|
5542
|
+
this.unexpected(this.lastTokStart);
|
|
5543
|
+
}
|
|
5544
|
+
if (spreadStart) this.unexpected(spreadStart);
|
|
5545
|
+
this.checkExpressionErrors(refDestructuringErrors, true);
|
|
5546
|
+
this._releaseDestructuringErrors();
|
|
5547
|
+
this.yieldPos = oldYieldPos || this.yieldPos;
|
|
5548
|
+
this.awaitPos = oldAwaitPos || this.awaitPos;
|
|
5549
|
+
|
|
5550
|
+
/** @type {Expression} */
|
|
5551
|
+
let val;
|
|
5552
|
+
if (exprList.length > 1) {
|
|
5553
|
+
const seq = /** @type {Node & { expressions?: Expression[] }} */ (
|
|
5554
|
+
this.startNodeAt(innerStartPos, innerStartLoc)
|
|
5555
|
+
);
|
|
5556
|
+
seq.expressions = exprList;
|
|
5557
|
+
this.finishNodeAt(
|
|
5558
|
+
/** @type {Node} */ (seq),
|
|
5559
|
+
"SequenceExpression",
|
|
5560
|
+
innerEndPos,
|
|
5561
|
+
undefined
|
|
5562
|
+
);
|
|
5563
|
+
val = /** @type {Expression} */ (/** @type {unknown} */ (seq));
|
|
5564
|
+
} else {
|
|
5565
|
+
val = exprList[0];
|
|
5566
|
+
}
|
|
5567
|
+
|
|
5568
|
+
if (this.options.preserveParens) {
|
|
5569
|
+
const par = /** @type {Node & { expression?: Expression }} */ (
|
|
5570
|
+
this.startNodeAt(startPos, startLoc)
|
|
5571
|
+
);
|
|
5572
|
+
par.expression = val;
|
|
5573
|
+
return /** @type {Expression} */ (
|
|
5574
|
+
/** @type {unknown} */ (
|
|
5575
|
+
this.finishNode(/** @type {Node} */ (par), "ParenthesizedExpression")
|
|
5576
|
+
)
|
|
5577
|
+
);
|
|
5578
|
+
}
|
|
5579
|
+
return val;
|
|
3554
5580
|
}
|
|
3555
5581
|
|
|
3556
5582
|
/**
|
|
3557
|
-
* `
|
|
3558
|
-
*
|
|
3559
|
-
*
|
|
3560
|
-
* @
|
|
5583
|
+
* Owned `afterTrailingComma`, acorn's verbatim (mode-independent), so the
|
|
5584
|
+
* owned list parsers do not bounce through the dist for each element.
|
|
5585
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/parseutil.js
|
|
5586
|
+
* @param {TokenType} tokType closing token type
|
|
5587
|
+
* @param {boolean=} notNext whether to leave the closing token unconsumed
|
|
5588
|
+
* @returns {boolean} true when the list ended on a trailing comma
|
|
3561
5589
|
* @this {ParserInternals}
|
|
3562
5590
|
*/
|
|
3563
|
-
|
|
3564
|
-
if (
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
this.semicolon();
|
|
5591
|
+
afterTrailingComma(tokType, notNext) {
|
|
5592
|
+
if (this.type === tokType) {
|
|
5593
|
+
const onTrailingComma =
|
|
5594
|
+
/** @type {Options & { onTrailingComma?: (pos: number, loc?: Position) => void }} */
|
|
5595
|
+
(this.options).onTrailingComma;
|
|
5596
|
+
if (onTrailingComma) {
|
|
5597
|
+
onTrailingComma(this.lastTokStart, this.lastTokStartLoc);
|
|
5598
|
+
}
|
|
5599
|
+
if (!notNext) this.next();
|
|
5600
|
+
return true;
|
|
3574
5601
|
}
|
|
3575
|
-
return
|
|
3576
|
-
/** @type {unknown} */ (
|
|
3577
|
-
new ReturnStatementNode(start, this.lastTokEnd, argument)
|
|
3578
|
-
)
|
|
3579
|
-
);
|
|
5602
|
+
return false;
|
|
3580
5603
|
}
|
|
3581
5604
|
|
|
3582
5605
|
/**
|
|
3583
|
-
* Owned `
|
|
3584
|
-
*
|
|
3585
|
-
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/
|
|
3586
|
-
* @param {DestructuringErrorsShim | null=} refDestructuringErrors
|
|
3587
|
-
* @
|
|
5606
|
+
* Owned `checkExpressionErrors`, acorn's verbatim (mode-independent): it
|
|
5607
|
+
* runs several times per expression from the owned spine.
|
|
5608
|
+
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/parseutil.js
|
|
5609
|
+
* @param {DestructuringErrorsShim | null=} refDestructuringErrors record to inspect
|
|
5610
|
+
* @param {boolean=} andThrow whether to throw on error
|
|
5611
|
+
* @returns {boolean} whether an error position was set
|
|
3588
5612
|
* @this {ParserInternals}
|
|
3589
5613
|
*/
|
|
3590
|
-
|
|
3591
|
-
if (!
|
|
3592
|
-
|
|
5614
|
+
checkExpressionErrors(refDestructuringErrors, andThrow) {
|
|
5615
|
+
if (!refDestructuringErrors) return false;
|
|
5616
|
+
const shorthandAssign = refDestructuringErrors.shorthandAssign;
|
|
5617
|
+
const doubleProto = refDestructuringErrors.doubleProto;
|
|
5618
|
+
if (!andThrow) return shorthandAssign >= 0 || doubleProto >= 0;
|
|
5619
|
+
if (shorthandAssign >= 0) {
|
|
5620
|
+
this.raise(
|
|
5621
|
+
shorthandAssign,
|
|
5622
|
+
"Shorthand property assignments are valid only in destructuring patterns"
|
|
5623
|
+
);
|
|
3593
5624
|
}
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
return
|
|
3598
|
-
/** @type {unknown} */ (
|
|
3599
|
-
new RestSpreadNode(start, this.lastTokEnd, "SpreadElement", argument)
|
|
3600
|
-
)
|
|
3601
|
-
);
|
|
5625
|
+
if (doubleProto >= 0) {
|
|
5626
|
+
this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property");
|
|
5627
|
+
}
|
|
5628
|
+
return false;
|
|
3602
5629
|
}
|
|
3603
5630
|
|
|
3604
5631
|
/**
|
|
3605
|
-
* Owned `
|
|
3606
|
-
*
|
|
5632
|
+
* Owned `parseExpression`: acorn wraps every call in `catchStackOverflow`,
|
|
5633
|
+
* allocating a fresh closure per expression; inline the try/catch instead
|
|
5634
|
+
* (same overflow-message translation, no closure). Non-lazy mode delegates.
|
|
3607
5635
|
* acorn source: https://github.com/acornjs/acorn/blob/8.17.0/acorn/src/expression.js
|
|
3608
5636
|
* @param {boolean | string=} forInit for-init context flag
|
|
3609
5637
|
* @param {DestructuringErrorsShim | null=} refDestructuringErrors destructuring errors to fill
|
|
3610
5638
|
* @returns {Expression} expression node
|
|
3611
5639
|
* @this {ParserInternals}
|
|
3612
5640
|
*/
|
|
3613
|
-
|
|
5641
|
+
parseExpression(forInit, refDestructuringErrors) {
|
|
3614
5642
|
if (!this._lazy) {
|
|
3615
|
-
return base.
|
|
3616
|
-
this,
|
|
3617
|
-
forInit,
|
|
3618
|
-
refDestructuringErrors
|
|
3619
|
-
);
|
|
5643
|
+
return base.parseExpression.call(this, forInit, refDestructuringErrors);
|
|
3620
5644
|
}
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
5645
|
+
try {
|
|
5646
|
+
const startPos = this.start;
|
|
5647
|
+
const startLoc = this.startLoc;
|
|
5648
|
+
const expr = this.parseMaybeAssign(forInit, refDestructuringErrors);
|
|
5649
|
+
if (this.type === tokTypes.comma) {
|
|
5650
|
+
const node =
|
|
5651
|
+
/** @type {Node & { expressions?: Expression[] }} */
|
|
5652
|
+
(this.startNodeAt(startPos, startLoc));
|
|
5653
|
+
node.expressions = [expr];
|
|
5654
|
+
while (this.eat(tokTypes.comma)) {
|
|
5655
|
+
node.expressions.push(
|
|
5656
|
+
this.parseMaybeAssign(forInit, refDestructuringErrors)
|
|
5657
|
+
);
|
|
5658
|
+
}
|
|
5659
|
+
return /** @type {Expression} */ (
|
|
5660
|
+
/** @type {unknown} */ (this.finishNode(node, "SequenceExpression"))
|
|
5661
|
+
);
|
|
5662
|
+
}
|
|
5663
|
+
return expr;
|
|
5664
|
+
} catch (err) {
|
|
5665
|
+
// acorn's catchStackOverflow: translate an engine stack-overflow error
|
|
5666
|
+
if (
|
|
5667
|
+
err instanceof Error &&
|
|
5668
|
+
(/\bstack\b.*\b(exceeded|overflow)\b/i.test(err.message) ||
|
|
5669
|
+
/\btoo much recursion\b/i.test(err.message))
|
|
5670
|
+
) {
|
|
5671
|
+
this.raise(this.start, "Not enough stack space to parse input");
|
|
5672
|
+
}
|
|
5673
|
+
throw err;
|
|
3642
5674
|
}
|
|
3643
|
-
return expr;
|
|
3644
5675
|
}
|
|
3645
5676
|
|
|
3646
5677
|
/**
|
|
@@ -3786,27 +5817,31 @@ class WebpackParser extends BaseParser {
|
|
|
3786
5817
|
const isTagged = (opts !== undefined && opts.isTagged) === true;
|
|
3787
5818
|
const start = this.start;
|
|
3788
5819
|
this.next();
|
|
3789
|
-
|
|
3790
|
-
const
|
|
5820
|
+
const exprScratch = this._acquireScratch();
|
|
5821
|
+
const quasiScratch = this._acquireScratch();
|
|
5822
|
+
let exprCount = 0;
|
|
5823
|
+
let quasiCount = 0;
|
|
3791
5824
|
// one options object for all chunks (only `isTagged` is ever read)
|
|
3792
5825
|
const eltOpts = { isTagged };
|
|
3793
5826
|
let curElt = /** @type {Node & { tail?: boolean }} */ (
|
|
3794
5827
|
this.parseTemplateElement(eltOpts)
|
|
3795
5828
|
);
|
|
3796
|
-
|
|
5829
|
+
quasiScratch[quasiCount++] = curElt;
|
|
3797
5830
|
while (!curElt.tail) {
|
|
3798
5831
|
if (this.type === tokTypes.eof) {
|
|
3799
5832
|
this.raise(this.pos, "Unterminated template literal");
|
|
3800
5833
|
}
|
|
3801
5834
|
this.expect(tokTypes.dollarBraceL);
|
|
3802
|
-
|
|
5835
|
+
exprScratch[exprCount++] = this.parseExpression();
|
|
3803
5836
|
this.expect(tokTypes.braceR);
|
|
3804
5837
|
curElt = /** @type {Node & { tail?: boolean }} */ (
|
|
3805
5838
|
this.parseTemplateElement(eltOpts)
|
|
3806
5839
|
);
|
|
3807
|
-
|
|
5840
|
+
quasiScratch[quasiCount++] = curElt;
|
|
3808
5841
|
}
|
|
3809
5842
|
this.next();
|
|
5843
|
+
const quasis = this._releaseScratch(quasiScratch, quasiCount);
|
|
5844
|
+
const expressions = this._releaseScratch(exprScratch, exprCount);
|
|
3810
5845
|
return /** @type {Node} */ (
|
|
3811
5846
|
/** @type {unknown} */ (
|
|
3812
5847
|
new TemplateLiteralNode(start, this.lastTokEnd, expressions, quasis)
|
|
@@ -3931,6 +5966,57 @@ class WebpackParser extends BaseParser {
|
|
|
3931
5966
|
return expr;
|
|
3932
5967
|
}
|
|
3933
5968
|
|
|
5969
|
+
/**
|
|
5970
|
+
* Collapses the commonest expression shape — a name/number/string/keyword
|
|
5971
|
+
* literal or `this` whose next source character can only begin a token that
|
|
5972
|
+
* cannot continue an expression — into the atom, skipping the seven-layer
|
|
5973
|
+
* `parseMaybeAssign` → `parseExprAtom` descent and its destructuring-error
|
|
5974
|
+
* bookkeeping (which is a net no-op for a bare atom).
|
|
5975
|
+
* @param {boolean | string=} forInit for-init context flag
|
|
5976
|
+
* @returns {Expression | null} the atom, or `null` when the shape does not apply
|
|
5977
|
+
* @this {ParserInternals}
|
|
5978
|
+
*/
|
|
5979
|
+
_parseTrivialAtom(forInit) {
|
|
5980
|
+
const code = this.input.charCodeAt(this.end);
|
|
5981
|
+
if (code >= 128 || EXPRESSION_END_CHAR[code] !== 1) return null;
|
|
5982
|
+
const type = this.type;
|
|
5983
|
+
if (type === tokTypes.name) {
|
|
5984
|
+
// both steer the chain themselves (`yield x`, `await x`)
|
|
5985
|
+
const name = /** @type {string} */ (this.value);
|
|
5986
|
+
if (name === "yield" || name === "await") return null;
|
|
5987
|
+
this.potentialArrowAt = this.start;
|
|
5988
|
+
this.potentialArrowInForAwait = forInit === "await";
|
|
5989
|
+
return /** @type {Expression} */ (
|
|
5990
|
+
/** @type {unknown} */ (this.parseIdent(false))
|
|
5991
|
+
);
|
|
5992
|
+
}
|
|
5993
|
+
if (type === tokTypes.num || type === tokTypes.string) {
|
|
5994
|
+
return /** @type {Expression} */ (
|
|
5995
|
+
/** @type {unknown} */ (this.parseLiteral(this.value))
|
|
5996
|
+
);
|
|
5997
|
+
}
|
|
5998
|
+
if (type === tokTypes._this) {
|
|
5999
|
+
const node = new ThisNode(this.start, this.end);
|
|
6000
|
+
this.next();
|
|
6001
|
+
return /** @type {Expression} */ (/** @type {unknown} */ (node));
|
|
6002
|
+
}
|
|
6003
|
+
if (
|
|
6004
|
+
type === tokTypes._null ||
|
|
6005
|
+
type === tokTypes._true ||
|
|
6006
|
+
type === tokTypes._false
|
|
6007
|
+
) {
|
|
6008
|
+
const node = new LiteralNode(
|
|
6009
|
+
this.start,
|
|
6010
|
+
this.end,
|
|
6011
|
+
type === tokTypes._null ? null : type === tokTypes._true,
|
|
6012
|
+
/** @type {string} */ (type.keyword)
|
|
6013
|
+
);
|
|
6014
|
+
this.next();
|
|
6015
|
+
return /** @type {Expression} */ (/** @type {unknown} */ (node));
|
|
6016
|
+
}
|
|
6017
|
+
return null;
|
|
6018
|
+
}
|
|
6019
|
+
|
|
3934
6020
|
/**
|
|
3935
6021
|
* Owned `parseMaybeAssign`, an exact-semantics copy of acorn 8's: the
|
|
3936
6022
|
* operator is captured before `next()` and the `AssignmentExpression` is
|
|
@@ -3952,6 +6038,10 @@ class WebpackParser extends BaseParser {
|
|
|
3952
6038
|
afterLeftParse
|
|
3953
6039
|
);
|
|
3954
6040
|
}
|
|
6041
|
+
if (this._exprFastPath && afterLeftParse === undefined) {
|
|
6042
|
+
const atom = this._parseTrivialAtom(forInit);
|
|
6043
|
+
if (atom !== null) return atom;
|
|
6044
|
+
}
|
|
3955
6045
|
if (this.isContextual("yield")) {
|
|
3956
6046
|
if (this.inGenerator) return this.parseYield(forInit);
|
|
3957
6047
|
// the tokenizer assumed an expression follows `yield`, but this
|
|
@@ -4052,7 +6142,10 @@ class WebpackParser extends BaseParser {
|
|
|
4052
6142
|
forInit
|
|
4053
6143
|
);
|
|
4054
6144
|
if (this.checkExpressionErrors(refDestructuringErrors)) return expr;
|
|
4055
|
-
|
|
6145
|
+
const isArrow = this._arrowFastPath
|
|
6146
|
+
? expr === this._lastArrow && expr.start === startPos
|
|
6147
|
+
: expr.start === startPos && expr.type === "ArrowFunctionExpression";
|
|
6148
|
+
return isArrow
|
|
4056
6149
|
? expr
|
|
4057
6150
|
: this.parseExprOp(expr, startPos, startLoc, -1, forInit);
|
|
4058
6151
|
}
|
|
@@ -4346,8 +6439,8 @@ class WebpackParser extends BaseParser {
|
|
|
4346
6439
|
} else {
|
|
4347
6440
|
propHash = {};
|
|
4348
6441
|
}
|
|
4349
|
-
|
|
4350
|
-
|
|
6442
|
+
const scratch = this._acquireScratch();
|
|
6443
|
+
let count = 0;
|
|
4351
6444
|
this.next();
|
|
4352
6445
|
while (!this.eat(tokTypes.braceR)) {
|
|
4353
6446
|
if (!first) {
|
|
@@ -4360,7 +6453,7 @@ class WebpackParser extends BaseParser {
|
|
|
4360
6453
|
if (!isPattern) {
|
|
4361
6454
|
this.checkPropClash(prop, propHash, refDestructuringErrors);
|
|
4362
6455
|
}
|
|
4363
|
-
|
|
6456
|
+
scratch[count++] = prop;
|
|
4364
6457
|
}
|
|
4365
6458
|
if (pooled) this._propHashDepth--;
|
|
4366
6459
|
return /** @type {Node} */ (
|
|
@@ -4369,7 +6462,7 @@ class WebpackParser extends BaseParser {
|
|
|
4369
6462
|
start,
|
|
4370
6463
|
this.lastTokEnd,
|
|
4371
6464
|
isPattern ? "ObjectPattern" : "ObjectExpression",
|
|
4372
|
-
|
|
6465
|
+
this._releaseScratch(scratch, count)
|
|
4373
6466
|
)
|
|
4374
6467
|
)
|
|
4375
6468
|
);
|
|
@@ -4956,7 +7049,7 @@ class WebpackParser extends BaseParser {
|
|
|
4956
7049
|
}
|
|
4957
7050
|
}
|
|
4958
7051
|
|
|
4959
|
-
/** @
|
|
7052
|
+
/** @import { SourcePosition } from "../Dependency" */
|
|
4960
7053
|
|
|
4961
7054
|
/**
|
|
4962
7055
|
* Whether a raw string literal contains a legacy octal (`\47`, `\0` followed by
|
|
@@ -4990,13 +7083,13 @@ const hasOctalEscape = (raw) => {
|
|
|
4990
7083
|
// these two helpers.
|
|
4991
7084
|
|
|
4992
7085
|
/**
|
|
4993
|
-
*
|
|
4994
|
-
*
|
|
4995
|
-
*
|
|
7086
|
+
* Exact char-code scan matching acorn's `lineBreak` semantics (CRLF is one
|
|
7087
|
+
* break). Kept as the fallback for the terminators `buildLineStarts` cannot
|
|
7088
|
+
* find with a native search.
|
|
4996
7089
|
* @param {string} source source code
|
|
4997
7090
|
* @returns {number[]} line start offsets
|
|
4998
7091
|
*/
|
|
4999
|
-
const
|
|
7092
|
+
const scanLineStarts = (source) => {
|
|
5000
7093
|
const len = source.length;
|
|
5001
7094
|
const lineStarts = [0];
|
|
5002
7095
|
for (let i = 0; i < len; i++) {
|
|
@@ -5013,6 +7106,33 @@ const buildLineStarts = (source) => {
|
|
|
5013
7106
|
return lineStarts;
|
|
5014
7107
|
};
|
|
5015
7108
|
|
|
7109
|
+
/**
|
|
7110
|
+
* Offset of each line's first character. `indexOf` searches the source natively,
|
|
7111
|
+
* which beats a char-code loop by ~3x; CRLF needs no special case because it
|
|
7112
|
+
* starts the next line after its `\n` either way. A lone `\r` or a unicode
|
|
7113
|
+
* separator does break that equivalence, so those fall back to the char scan.
|
|
7114
|
+
* @param {string} source source code
|
|
7115
|
+
* @returns {number[]} line start offsets
|
|
7116
|
+
*/
|
|
7117
|
+
const buildLineStarts = (source) => {
|
|
7118
|
+
if (!source.includes("\u2028") && !source.includes("\u2029")) {
|
|
7119
|
+
let cr = source.indexOf("\r");
|
|
7120
|
+
while (cr !== -1 && source.charCodeAt(cr + 1) === 10) {
|
|
7121
|
+
cr = source.indexOf("\r", cr + 2);
|
|
7122
|
+
}
|
|
7123
|
+
if (cr === -1) {
|
|
7124
|
+
const lineStarts = [0];
|
|
7125
|
+
let i = source.indexOf("\n");
|
|
7126
|
+
while (i !== -1) {
|
|
7127
|
+
lineStarts.push(i + 1);
|
|
7128
|
+
i = source.indexOf("\n", i + 1);
|
|
7129
|
+
}
|
|
7130
|
+
return lineStarts;
|
|
7131
|
+
}
|
|
7132
|
+
}
|
|
7133
|
+
return scanLineStarts(source);
|
|
7134
|
+
};
|
|
7135
|
+
|
|
5016
7136
|
/**
|
|
5017
7137
|
* Binary search for the line containing the offset.
|
|
5018
7138
|
* @param {number[]} lineStarts line start offsets
|
|
@@ -5030,8 +7150,334 @@ const positionAt = (lineStarts, offset) => {
|
|
|
5030
7150
|
return { line: lo + 1, column: offset - lineStarts[lo] };
|
|
5031
7151
|
};
|
|
5032
7152
|
|
|
7153
|
+
const KEYWORDS_BEFORE_REGEXP = new Set([
|
|
7154
|
+
"await",
|
|
7155
|
+
"case",
|
|
7156
|
+
"delete",
|
|
7157
|
+
"do",
|
|
7158
|
+
"else",
|
|
7159
|
+
"in",
|
|
7160
|
+
"instanceof",
|
|
7161
|
+
"new",
|
|
7162
|
+
"of",
|
|
7163
|
+
"return",
|
|
7164
|
+
"throw",
|
|
7165
|
+
"typeof",
|
|
7166
|
+
"void",
|
|
7167
|
+
"yield"
|
|
7168
|
+
]);
|
|
7169
|
+
|
|
7170
|
+
/**
|
|
7171
|
+
* Whether a `/` at this point starts a regexp rather than division, decided by
|
|
7172
|
+
* what precedes it: after a value (name, number, `)`, `]`) it divides, after an
|
|
7173
|
+
* operator or a keyword it opens a regexp. `)` and `]` are always read as
|
|
7174
|
+
* division — telling `if (a) /re/` from `(a) / b` needs paren-context tracking
|
|
7175
|
+
* this single pass does not carry.
|
|
7176
|
+
* @param {string} source source code
|
|
7177
|
+
* @param {number} slash offset of the `/`
|
|
7178
|
+
* @returns {boolean} true when a regexp literal starts here
|
|
7179
|
+
*/
|
|
7180
|
+
const startsRegExp = (source, slash) => {
|
|
7181
|
+
let i = slash - 1;
|
|
7182
|
+
while (i >= 0) {
|
|
7183
|
+
const code = source.charCodeAt(i);
|
|
7184
|
+
if (code === 32 || code === 9 || code === 10 || code === 13) i--;
|
|
7185
|
+
else break;
|
|
7186
|
+
}
|
|
7187
|
+
if (i < 0) return true;
|
|
7188
|
+
const code = source.charCodeAt(i);
|
|
7189
|
+
if (code === 41 || code === 93) return false;
|
|
7190
|
+
if (!isIdentifierChar(code)) return true;
|
|
7191
|
+
// a keyword before `/` is an operator position (`return /re/`), a name is not
|
|
7192
|
+
let start = i;
|
|
7193
|
+
while (start >= 0 && isIdentifierChar(source.charCodeAt(start))) start--;
|
|
7194
|
+
return KEYWORDS_BEFORE_REGEXP.has(source.slice(start + 1, i + 1));
|
|
7195
|
+
};
|
|
7196
|
+
|
|
7197
|
+
/**
|
|
7198
|
+
* Skips whitespace and comments, returning the next code offset.
|
|
7199
|
+
* @param {string} source source code
|
|
7200
|
+
* @param {number} i offset to start at
|
|
7201
|
+
* @returns {number} offset of the next significant character
|
|
7202
|
+
*/
|
|
7203
|
+
const skipTrivia = (source, i) => {
|
|
7204
|
+
while (i < source.length) {
|
|
7205
|
+
const code = source.charCodeAt(i);
|
|
7206
|
+
if (code === 32 || code === 9 || code === 10 || code === 13) {
|
|
7207
|
+
i++;
|
|
7208
|
+
} else if (code === 47 && source.charCodeAt(i + 1) === 47) {
|
|
7209
|
+
const end = source.indexOf("\n", i + 2);
|
|
7210
|
+
i = end === -1 ? source.length : end + 1;
|
|
7211
|
+
} else if (code === 47 && source.charCodeAt(i + 1) === 42) {
|
|
7212
|
+
const end = source.indexOf("*/", i + 2);
|
|
7213
|
+
i = end === -1 ? source.length : end + 2;
|
|
7214
|
+
} else {
|
|
7215
|
+
break;
|
|
7216
|
+
}
|
|
7217
|
+
}
|
|
7218
|
+
return i;
|
|
7219
|
+
};
|
|
7220
|
+
|
|
7221
|
+
/** @type {Map<number, string>} */
|
|
7222
|
+
const SINGLE_CHARACTER_ESCAPES = new Map([
|
|
7223
|
+
[110, "\n"],
|
|
7224
|
+
[114, "\r"],
|
|
7225
|
+
[116, "\t"],
|
|
7226
|
+
[98, "\b"],
|
|
7227
|
+
[118, "\u000B"],
|
|
7228
|
+
[102, "\f"]
|
|
7229
|
+
]);
|
|
7230
|
+
|
|
7231
|
+
/**
|
|
7232
|
+
* Reads the hex digits of a `\x`/`\u` escape.
|
|
7233
|
+
* @param {string} source source code
|
|
7234
|
+
* @param {number} i offset of the first digit
|
|
7235
|
+
* @param {number} length how many digits to read
|
|
7236
|
+
* @returns {number} the code point, or `-1` when a digit is missing
|
|
7237
|
+
*/
|
|
7238
|
+
const readHexEscapeValue = (source, i, length) => {
|
|
7239
|
+
let value = 0;
|
|
7240
|
+
for (let j = i; j < i + length; j++) {
|
|
7241
|
+
const digit = Number.parseInt(source[j], 16);
|
|
7242
|
+
if (Number.isNaN(digit)) return -1;
|
|
7243
|
+
value = value * 16 + digit;
|
|
7244
|
+
}
|
|
7245
|
+
return value;
|
|
7246
|
+
};
|
|
7247
|
+
|
|
7248
|
+
/**
|
|
7249
|
+
* Cooks one escape sequence, sloppy-mode script semantics (legacy octal included).
|
|
7250
|
+
* @param {string} source source code
|
|
7251
|
+
* @param {number} i offset just past the backslash
|
|
7252
|
+
* @returns {{ value: string, end: number } | undefined} the cooked text, or `undefined` when malformed
|
|
7253
|
+
*/
|
|
7254
|
+
const readEscape = (source, i) => {
|
|
7255
|
+
if (i >= source.length) return;
|
|
7256
|
+
const code = source.charCodeAt(i);
|
|
7257
|
+
const single = SINGLE_CHARACTER_ESCAPES.get(code);
|
|
7258
|
+
if (single !== undefined) return { value: single, end: i + 1 };
|
|
7259
|
+
// a line continuation cooks to nothing; `\r\n` counts as one terminator
|
|
7260
|
+
if (code === 13) {
|
|
7261
|
+
return { value: "", end: source.charCodeAt(i + 1) === 10 ? i + 2 : i + 1 };
|
|
7262
|
+
}
|
|
7263
|
+
if (code === 10 || code === 0x2028 || code === 0x2029) {
|
|
7264
|
+
return { value: "", end: i + 1 };
|
|
7265
|
+
}
|
|
7266
|
+
if (code === 120) {
|
|
7267
|
+
const value = readHexEscapeValue(source, i + 1, 2);
|
|
7268
|
+
if (value === -1) return;
|
|
7269
|
+
return { value: String.fromCodePoint(value), end: i + 3 };
|
|
7270
|
+
}
|
|
7271
|
+
if (code === 117) {
|
|
7272
|
+
if (source.charCodeAt(i + 1) === 123) {
|
|
7273
|
+
const end = source.indexOf("}", i + 2);
|
|
7274
|
+
if (end === -1 || end === i + 2) return;
|
|
7275
|
+
const value = readHexEscapeValue(source, i + 2, end - i - 2);
|
|
7276
|
+
if (value === -1 || value > 0x10ffff) return;
|
|
7277
|
+
return { value: String.fromCodePoint(value), end: end + 1 };
|
|
7278
|
+
}
|
|
7279
|
+
const value = readHexEscapeValue(source, i + 1, 4);
|
|
7280
|
+
if (value === -1) return;
|
|
7281
|
+
return { value: String.fromCodePoint(value), end: i + 5 };
|
|
7282
|
+
}
|
|
7283
|
+
if (code >= 48 && code <= 55) {
|
|
7284
|
+
let digits = /** @type {RegExpMatchArray} */ (
|
|
7285
|
+
source.slice(i, i + 3).match(/^[0-7]+/)
|
|
7286
|
+
)[0];
|
|
7287
|
+
if (Number.parseInt(digits, 8) > 255) digits = digits.slice(0, -1);
|
|
7288
|
+
return {
|
|
7289
|
+
value: String.fromCharCode(Number.parseInt(digits, 8)),
|
|
7290
|
+
end: i + digits.length
|
|
7291
|
+
};
|
|
7292
|
+
}
|
|
7293
|
+
return { value: source[i], end: i + 1 };
|
|
7294
|
+
};
|
|
7295
|
+
|
|
7296
|
+
/**
|
|
7297
|
+
* Reads a `'`/`"` string starting at `i`, cooking its escapes the way the ast
|
|
7298
|
+
* this replaces did — a `Literal` node carries the cooked value, so a specifier
|
|
7299
|
+
* written `"\x2e/a"` is the same dependency as `"./a"`. Templates are not
|
|
7300
|
+
* specifiers here: the ast only matched `Literal` nodes.
|
|
7301
|
+
* @param {string} source source code
|
|
7302
|
+
* @param {number} i offset of the opening quote
|
|
7303
|
+
* @returns {{ value: string, end: number } | undefined} the literal
|
|
7304
|
+
*/
|
|
7305
|
+
const readStringLiteral = (source, i) => {
|
|
7306
|
+
const quote = source.charCodeAt(i);
|
|
7307
|
+
if (quote !== 34 && quote !== 39) return;
|
|
7308
|
+
for (let j = i + 1; j < source.length; j++) {
|
|
7309
|
+
const code = source.charCodeAt(j);
|
|
7310
|
+
if (code === 10 || code === 13) return;
|
|
7311
|
+
if (code === 92) return readEscapedStringLiteral(source, i, j);
|
|
7312
|
+
if (code === quote) return { value: source.slice(i + 1, j), end: j + 1 };
|
|
7313
|
+
}
|
|
7314
|
+
};
|
|
7315
|
+
|
|
7316
|
+
/**
|
|
7317
|
+
* Continues `readStringLiteral` from its first escape, so the unescaped case
|
|
7318
|
+
* stays a single slice.
|
|
7319
|
+
* @param {string} source source code
|
|
7320
|
+
* @param {number} i offset of the opening quote
|
|
7321
|
+
* @param {number} firstEscape offset of the first backslash
|
|
7322
|
+
* @returns {{ value: string, end: number } | undefined} the literal
|
|
7323
|
+
*/
|
|
7324
|
+
const readEscapedStringLiteral = (source, i, firstEscape) => {
|
|
7325
|
+
const quote = source.charCodeAt(i);
|
|
7326
|
+
let value = "";
|
|
7327
|
+
let segment = i + 1;
|
|
7328
|
+
for (let j = firstEscape; j < source.length; j++) {
|
|
7329
|
+
const code = source.charCodeAt(j);
|
|
7330
|
+
if (code === 10 || code === 13) return;
|
|
7331
|
+
if (code === quote) {
|
|
7332
|
+
return { value: value + source.slice(segment, j), end: j + 1 };
|
|
7333
|
+
}
|
|
7334
|
+
if (code !== 92) continue;
|
|
7335
|
+
const escape = readEscape(source, j + 1);
|
|
7336
|
+
if (escape === undefined) return;
|
|
7337
|
+
value += source.slice(segment, j) + escape.value;
|
|
7338
|
+
segment = escape.end;
|
|
7339
|
+
j = escape.end - 1;
|
|
7340
|
+
}
|
|
7341
|
+
};
|
|
7342
|
+
|
|
7343
|
+
/**
|
|
7344
|
+
* Scans a template body from `i` (just past a backtick or a `}` resuming one).
|
|
7345
|
+
* @param {string} source source code
|
|
7346
|
+
* @param {number} i offset inside the template
|
|
7347
|
+
* @returns {{ end: number, substitution: boolean }} where the body stops
|
|
7348
|
+
*/
|
|
7349
|
+
const skipTemplateBody = (source, i) => {
|
|
7350
|
+
for (; i < source.length; i++) {
|
|
7351
|
+
const code = source.charCodeAt(i);
|
|
7352
|
+
if (code === 92) {
|
|
7353
|
+
i++;
|
|
7354
|
+
} else if (code === 96) {
|
|
7355
|
+
return { end: i, substitution: false };
|
|
7356
|
+
} else if (code === 36 && source.charCodeAt(i + 1) === 123) {
|
|
7357
|
+
return { end: i + 1, substitution: true };
|
|
7358
|
+
}
|
|
7359
|
+
}
|
|
7360
|
+
return { end: source.length, substitution: false };
|
|
7361
|
+
};
|
|
7362
|
+
|
|
7363
|
+
/**
|
|
7364
|
+
* Collects the specifiers of static `require("…")` calls. A scan rather than a
|
|
7365
|
+
* parse: it only has to skip what could hide or fake a call — comments, strings,
|
|
7366
|
+
* templates and regexps — so it costs one pass and builds no ast. Template
|
|
7367
|
+
* substitutions are scanned as the code they are, which is why the brace depth
|
|
7368
|
+
* of each open `${` is tracked.
|
|
7369
|
+
* @param {string} source source code
|
|
7370
|
+
* @returns {Set<string>} required specifiers
|
|
7371
|
+
*/
|
|
7372
|
+
const collectCjsRequireSpecifiers = (source) => {
|
|
7373
|
+
/** @type {Set<string>} */
|
|
7374
|
+
const specifiers = new Set();
|
|
7375
|
+
/** @type {number[]} */
|
|
7376
|
+
const templateBraceDepths = [];
|
|
7377
|
+
let braceDepth = 0;
|
|
7378
|
+
for (let i = 0; i < source.length; i++) {
|
|
7379
|
+
const code = source.charCodeAt(i);
|
|
7380
|
+
if (code === 96) {
|
|
7381
|
+
const body = skipTemplateBody(source, i + 1);
|
|
7382
|
+
i = body.end;
|
|
7383
|
+
if (body.substitution) {
|
|
7384
|
+
templateBraceDepths.push(braceDepth);
|
|
7385
|
+
braceDepth++;
|
|
7386
|
+
}
|
|
7387
|
+
continue;
|
|
7388
|
+
}
|
|
7389
|
+
if (code === 123) {
|
|
7390
|
+
braceDepth++;
|
|
7391
|
+
continue;
|
|
7392
|
+
}
|
|
7393
|
+
if (code === 125) {
|
|
7394
|
+
braceDepth--;
|
|
7395
|
+
if (
|
|
7396
|
+
templateBraceDepths.length > 0 &&
|
|
7397
|
+
templateBraceDepths[templateBraceDepths.length - 1] === braceDepth
|
|
7398
|
+
) {
|
|
7399
|
+
templateBraceDepths.pop();
|
|
7400
|
+
const body = skipTemplateBody(source, i + 1);
|
|
7401
|
+
i = body.end;
|
|
7402
|
+
if (body.substitution) {
|
|
7403
|
+
templateBraceDepths.push(braceDepth);
|
|
7404
|
+
braceDepth++;
|
|
7405
|
+
}
|
|
7406
|
+
}
|
|
7407
|
+
continue;
|
|
7408
|
+
}
|
|
7409
|
+
if (code === 34 || code === 39) {
|
|
7410
|
+
for (i++; i < source.length; i++) {
|
|
7411
|
+
const inner = source.charCodeAt(i);
|
|
7412
|
+
if (inner === 92) i++;
|
|
7413
|
+
else if (inner === code) break;
|
|
7414
|
+
}
|
|
7415
|
+
continue;
|
|
7416
|
+
}
|
|
7417
|
+
if (code === 47) {
|
|
7418
|
+
const next = source.charCodeAt(i + 1);
|
|
7419
|
+
if (next === 47) {
|
|
7420
|
+
const end = source.indexOf("\n", i + 2);
|
|
7421
|
+
i = end === -1 ? source.length : end;
|
|
7422
|
+
continue;
|
|
7423
|
+
}
|
|
7424
|
+
if (next === 42) {
|
|
7425
|
+
const end = source.indexOf("*/", i + 2);
|
|
7426
|
+
i = end === -1 ? source.length : end + 1;
|
|
7427
|
+
continue;
|
|
7428
|
+
}
|
|
7429
|
+
if (!startsRegExp(source, i)) continue;
|
|
7430
|
+
let inClass = false;
|
|
7431
|
+
for (i++; i < source.length; i++) {
|
|
7432
|
+
const inner = source.charCodeAt(i);
|
|
7433
|
+
if (inner === 92) i++;
|
|
7434
|
+
else if (inner === 91) inClass = true;
|
|
7435
|
+
else if (inner === 93) inClass = false;
|
|
7436
|
+
else if (inner === 10) break;
|
|
7437
|
+
else if (inner === 47 && !inClass) break;
|
|
7438
|
+
}
|
|
7439
|
+
continue;
|
|
7440
|
+
}
|
|
7441
|
+
// `r` of `require`, as a whole word that is not a member access
|
|
7442
|
+
if (code !== 114 || !source.startsWith("require", i)) continue;
|
|
7443
|
+
if (isIdentifierChar(source.charCodeAt(i + 7))) continue;
|
|
7444
|
+
if (i > 0) {
|
|
7445
|
+
const before = source.charCodeAt(i - 1);
|
|
7446
|
+
if (isIdentifierChar(before) || before === 46) continue;
|
|
7447
|
+
}
|
|
7448
|
+
let j = skipTrivia(source, i + 7);
|
|
7449
|
+
if (source.charCodeAt(j) !== 40) continue;
|
|
7450
|
+
j = skipTrivia(source, j + 1);
|
|
7451
|
+
// a cast wraps the specifier in its own parens: `require(/** … */ ("x"))`
|
|
7452
|
+
let parens = 0;
|
|
7453
|
+
while (source.charCodeAt(j) === 40) {
|
|
7454
|
+
parens++;
|
|
7455
|
+
j = skipTrivia(source, j + 1);
|
|
7456
|
+
}
|
|
7457
|
+
const literal = readStringLiteral(source, j);
|
|
7458
|
+
if (literal === undefined) {
|
|
7459
|
+
i += 6;
|
|
7460
|
+
continue;
|
|
7461
|
+
}
|
|
7462
|
+
j = skipTrivia(source, literal.end);
|
|
7463
|
+
while (parens > 0 && source.charCodeAt(j) === 41) {
|
|
7464
|
+
parens--;
|
|
7465
|
+
j = skipTrivia(source, j + 1);
|
|
7466
|
+
}
|
|
7467
|
+
if (parens !== 0 || source.charCodeAt(j) !== 41) {
|
|
7468
|
+
i += 6;
|
|
7469
|
+
continue;
|
|
7470
|
+
}
|
|
7471
|
+
specifiers.add(literal.value);
|
|
7472
|
+
i = j;
|
|
7473
|
+
}
|
|
7474
|
+
return specifiers;
|
|
7475
|
+
};
|
|
7476
|
+
|
|
5033
7477
|
module.exports.LEGACY_ASSERT_ATTRIBUTES = LEGACY_ASSERT_ATTRIBUTES;
|
|
5034
7478
|
module.exports.WebpackParser = WebpackParser;
|
|
5035
7479
|
module.exports.buildLineStarts = buildLineStarts;
|
|
7480
|
+
module.exports.collectCjsRequireSpecifiers = collectCjsRequireSpecifiers;
|
|
5036
7481
|
module.exports.hasOctalEscape = hasOctalEscape;
|
|
7482
|
+
module.exports.isIdentifierChar = isIdentifierChar;
|
|
5037
7483
|
module.exports.positionAt = positionAt;
|