webpack 5.97.1 → 5.104.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +368 -434
- package/bin/webpack.js +15 -9
- package/hot/dev-server.js +18 -3
- package/hot/emitter-event-target.js +7 -0
- package/hot/lazy-compilation-node.js +45 -29
- package/hot/lazy-compilation-universal.js +18 -0
- package/hot/lazy-compilation-web.js +15 -5
- package/hot/load-http.js +7 -0
- package/hot/log.js +15 -15
- package/hot/only-dev-server.js +19 -4
- package/hot/poll.js +1 -0
- package/lib/APIPlugin.js +48 -50
- package/lib/AbstractMethodError.js +1 -0
- package/lib/AsyncDependenciesBlock.js +4 -5
- package/lib/AutomaticPrefetchPlugin.js +22 -22
- package/lib/BannerPlugin.js +35 -40
- package/lib/Cache.js +12 -9
- package/lib/CacheFacade.js +13 -13
- package/lib/CaseSensitiveModulesWarning.js +6 -6
- package/lib/Chunk.js +68 -47
- package/lib/ChunkGraph.js +174 -95
- package/lib/ChunkGroup.js +32 -24
- package/lib/ChunkTemplate.js +8 -8
- package/lib/CleanPlugin.js +90 -42
- package/lib/CodeGenerationResults.js +12 -9
- package/lib/CompatibilityPlugin.js +70 -21
- package/lib/Compilation.js +827 -550
- package/lib/Compiler.js +137 -109
- package/lib/ConcatenationScope.js +45 -8
- package/lib/ConditionalInitFragment.js +1 -1
- package/lib/ConstPlugin.js +89 -59
- package/lib/ContextExclusionPlugin.js +5 -4
- package/lib/ContextModule.js +66 -51
- package/lib/ContextModuleFactory.js +51 -30
- package/lib/ContextReplacementPlugin.js +89 -34
- package/lib/CssModule.js +8 -4
- package/lib/DefinePlugin.js +209 -57
- package/lib/DelegatedModule.js +34 -23
- package/lib/DelegatedModuleFactoryPlugin.js +27 -24
- package/lib/DelegatedPlugin.js +4 -2
- package/lib/DependenciesBlock.js +0 -2
- package/lib/Dependency.js +37 -19
- package/lib/DependencyTemplate.js +2 -0
- package/lib/DependencyTemplates.js +5 -6
- package/lib/DllEntryPlugin.js +8 -4
- package/lib/DllModule.js +11 -12
- package/lib/DllModuleFactory.js +2 -2
- package/lib/DllPlugin.js +9 -6
- package/lib/DllReferencePlugin.js +60 -65
- package/lib/DotenvPlugin.js +462 -0
- package/lib/DynamicEntryPlugin.js +8 -8
- package/lib/EntryOptionPlugin.js +8 -6
- package/lib/EntryPlugin.js +5 -3
- package/lib/Entrypoint.js +19 -0
- package/lib/EnvironmentNotSupportAsyncWarning.js +0 -3
- package/lib/EnvironmentPlugin.js +26 -19
- package/lib/ErrorHelpers.js +6 -6
- package/lib/EvalDevToolModulePlugin.js +17 -14
- package/lib/EvalSourceMapDevToolPlugin.js +156 -142
- package/lib/ExportsInfo.js +180 -115
- package/lib/ExportsInfoApiPlugin.js +2 -2
- package/lib/ExternalModule.js +256 -102
- package/lib/ExternalModuleFactoryPlugin.js +66 -29
- package/lib/ExternalsPlugin.js +57 -2
- package/lib/FileSystemInfo.js +313 -247
- package/lib/FlagAllModulesAsUsedPlugin.js +2 -2
- package/lib/FlagDependencyExportsPlugin.js +29 -19
- package/lib/FlagDependencyUsagePlugin.js +9 -10
- package/lib/FlagEntryExportAsUsedPlugin.js +1 -1
- package/lib/Generator.js +43 -10
- package/lib/GraphHelpers.js +11 -3
- package/lib/HookWebpackError.js +35 -7
- package/lib/HotModuleReplacementPlugin.js +149 -108
- package/lib/HotUpdateChunk.js +0 -3
- package/lib/IgnoreErrorModuleFactory.js +2 -2
- package/lib/IgnorePlugin.js +16 -13
- package/lib/IgnoreWarningsPlugin.js +6 -4
- package/lib/InitFragment.js +41 -23
- package/lib/InvalidDependenciesModuleWarning.js +2 -3
- package/lib/JavascriptMetaInfoPlugin.js +2 -4
- package/lib/LibManifestPlugin.js +12 -13
- package/lib/LoaderOptionsPlugin.js +12 -14
- package/lib/LoaderTargetPlugin.js +5 -3
- package/lib/MainTemplate.js +18 -29
- package/lib/ManifestPlugin.js +235 -0
- package/lib/Module.js +138 -60
- package/lib/ModuleBuildError.js +4 -2
- package/lib/ModuleDependencyError.js +4 -3
- package/lib/ModuleDependencyWarning.js +4 -3
- package/lib/ModuleError.js +1 -1
- package/lib/ModuleFactory.js +10 -3
- package/lib/ModuleFilenameHelpers.js +63 -60
- package/lib/ModuleGraph.js +195 -70
- package/lib/ModuleGraphConnection.js +14 -20
- package/lib/ModuleInfoHeaderPlugin.js +15 -16
- package/lib/ModuleNotFoundError.js +1 -1
- package/lib/ModuleParseError.js +8 -4
- package/lib/ModuleSourceTypeConstants.js +189 -0
- package/lib/ModuleTemplate.js +7 -8
- package/lib/ModuleTypeConstants.js +37 -15
- package/lib/ModuleWarning.js +1 -1
- package/lib/MultiCompiler.js +64 -49
- package/lib/MultiStats.js +19 -14
- package/lib/MultiWatching.js +7 -11
- package/lib/NoEmitOnErrorsPlugin.js +5 -3
- package/lib/NodeStuffPlugin.js +438 -126
- package/lib/NormalModule.js +322 -201
- package/lib/NormalModuleFactory.js +230 -117
- package/lib/NormalModuleReplacementPlugin.js +37 -39
- package/lib/NullFactory.js +3 -2
- package/lib/OptimizationStages.js +1 -1
- package/lib/OptionsApply.js +1 -1
- package/lib/Parser.js +5 -3
- package/lib/PlatformPlugin.js +3 -1
- package/lib/PrefetchPlugin.js +6 -4
- package/lib/ProgressPlugin.js +48 -49
- package/lib/ProvidePlugin.js +7 -5
- package/lib/RawModule.js +26 -12
- package/lib/RecordIdsPlugin.js +88 -110
- package/lib/RequestShortener.js +3 -1
- package/lib/ResolverFactory.js +15 -14
- package/lib/RuntimeGlobals.js +216 -153
- package/lib/RuntimeModule.js +7 -6
- package/lib/RuntimePlugin.js +115 -62
- package/lib/RuntimeTemplate.js +248 -76
- package/lib/SelfModuleFactory.js +2 -2
- package/lib/SizeFormatHelpers.js +2 -2
- package/lib/SourceMapDevToolModuleOptionsPlugin.js +17 -27
- package/lib/SourceMapDevToolPlugin.js +72 -59
- package/lib/Stats.js +2 -3
- package/lib/Template.js +31 -24
- package/lib/TemplatedPathPlugin.js +24 -21
- package/lib/UseStrictPlugin.js +1 -1
- package/lib/WarnCaseSensitiveModulesPlugin.js +36 -37
- package/lib/WarnDeprecatedOptionPlugin.js +7 -8
- package/lib/WarnNoModeSetPlugin.js +3 -1
- package/lib/WatchIgnorePlugin.js +11 -9
- package/lib/Watching.js +27 -29
- package/lib/WebpackError.js +10 -3
- package/lib/WebpackIsIncludedPlugin.js +4 -5
- package/lib/WebpackOptionsApply.js +263 -135
- package/lib/asset/AssetBytesGenerator.js +171 -0
- package/lib/asset/AssetBytesParser.js +37 -0
- package/lib/asset/AssetGenerator.js +285 -223
- package/lib/asset/AssetModulesPlugin.js +103 -41
- package/lib/asset/AssetParser.js +7 -3
- package/lib/asset/AssetSourceGenerator.js +41 -17
- package/lib/asset/RawDataUrlModule.js +17 -9
- package/lib/async-modules/AsyncModuleHelpers.js +52 -0
- package/lib/async-modules/AwaitDependenciesInitFragment.js +39 -24
- package/lib/async-modules/InferAsyncModulesPlugin.js +25 -26
- package/lib/buildChunkGraph.js +36 -17
- package/lib/cache/AddBuildDependenciesPlugin.js +5 -6
- package/lib/cache/IdleFileCachePlugin.js +22 -20
- package/lib/cache/MemoryCachePlugin.js +3 -3
- package/lib/cache/MemoryWithGcCachePlugin.js +17 -11
- package/lib/cache/PackFileCacheStrategy.js +198 -170
- package/lib/cache/ResolverCachePlugin.js +58 -48
- package/lib/cache/getLazyHashedEtag.js +5 -4
- package/lib/cli.js +197 -39
- package/lib/config/browserslistTargetHandler.js +110 -85
- package/lib/config/defaults.js +514 -113
- package/lib/config/normalization.js +91 -64
- package/lib/config/target.js +30 -18
- package/lib/container/ContainerEntryDependency.js +0 -1
- package/lib/container/ContainerEntryModule.js +16 -15
- package/lib/container/ContainerEntryModuleFactory.js +2 -2
- package/lib/container/ContainerPlugin.js +5 -6
- package/lib/container/ContainerReferencePlugin.js +27 -30
- package/lib/container/FallbackDependency.js +2 -1
- package/lib/container/FallbackModule.js +19 -14
- package/lib/container/FallbackModuleFactory.js +2 -2
- package/lib/container/HoistContainerReferencesPlugin.js +7 -7
- package/lib/container/ModuleFederationPlugin.js +4 -4
- package/lib/container/RemoteModule.js +14 -14
- package/lib/container/RemoteRuntimeModule.js +2 -2
- package/lib/container/options.js +9 -9
- package/lib/css/CssGenerator.js +366 -74
- package/lib/css/CssLoadingRuntimeModule.js +26 -16
- package/lib/css/CssMergeStyleSheetsRuntimeModule.js +56 -0
- package/lib/css/CssModulesPlugin.js +191 -142
- package/lib/css/CssParser.js +1756 -740
- package/lib/css/walkCssTokens.js +180 -67
- package/lib/debug/ProfilingPlugin.js +135 -51
- package/lib/dependencies/AMDDefineDependencyParserPlugin.js +29 -28
- package/lib/dependencies/AMDPlugin.js +18 -11
- package/lib/dependencies/AMDRequireArrayDependency.js +5 -4
- package/lib/dependencies/AMDRequireContextDependency.js +2 -1
- package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +35 -26
- package/lib/dependencies/AMDRuntimeModules.js +3 -1
- package/lib/dependencies/CachedConstDependency.js +24 -18
- package/lib/dependencies/CommonJsExportRequireDependency.js +31 -24
- package/lib/dependencies/CommonJsExportsDependency.js +2 -1
- package/lib/dependencies/CommonJsExportsParserPlugin.js +50 -36
- package/lib/dependencies/CommonJsFullRequireDependency.js +7 -13
- package/lib/dependencies/CommonJsImportsParserPlugin.js +146 -127
- package/lib/dependencies/CommonJsPlugin.js +29 -18
- package/lib/dependencies/CommonJsRequireContextDependency.js +4 -3
- package/lib/dependencies/CommonJsSelfReferenceDependency.js +4 -4
- package/lib/dependencies/ConstDependency.js +2 -2
- package/lib/dependencies/ContextDependency.js +10 -5
- package/lib/dependencies/ContextDependencyHelpers.js +21 -13
- package/lib/dependencies/ContextDependencyTemplateAsId.js +10 -9
- package/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +13 -10
- package/lib/dependencies/ContextElementDependency.js +23 -12
- package/lib/dependencies/CssIcssExportDependency.js +402 -22
- package/lib/dependencies/CssIcssImportDependency.js +116 -51
- package/lib/dependencies/CssIcssSymbolDependency.js +33 -35
- package/lib/dependencies/CssImportDependency.js +17 -14
- package/lib/dependencies/CssUrlDependency.js +8 -13
- package/lib/dependencies/DynamicExports.js +19 -19
- package/lib/dependencies/ExportsInfoDependency.js +13 -10
- package/lib/dependencies/ExternalModuleDependency.js +7 -7
- package/lib/dependencies/ExternalModuleInitFragment.js +3 -2
- package/lib/dependencies/ExternalModuleInitFragmentDependency.js +96 -0
- package/lib/dependencies/HarmonyAcceptDependency.js +96 -5
- package/lib/dependencies/HarmonyAcceptImportDependency.js +2 -5
- package/lib/dependencies/HarmonyCompatibilityDependency.js +0 -1
- package/lib/dependencies/HarmonyDetectionParserPlugin.js +10 -30
- package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +19 -8
- package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +136 -99
- package/lib/dependencies/HarmonyExportExpressionDependency.js +1 -1
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +152 -61
- package/lib/dependencies/HarmonyExportInitFragment.js +2 -2
- package/lib/dependencies/HarmonyExportSpecifierDependency.js +2 -2
- package/lib/dependencies/HarmonyExports.js +5 -5
- package/lib/dependencies/HarmonyImportDependency.js +92 -45
- package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +201 -163
- package/lib/dependencies/HarmonyImportSideEffectDependency.js +5 -6
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +69 -42
- package/lib/dependencies/HarmonyModulesPlugin.js +16 -11
- package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +15 -15
- package/lib/dependencies/ImportContextDependency.js +15 -1
- package/lib/dependencies/ImportDependency.js +25 -7
- package/lib/dependencies/ImportEagerDependency.js +7 -5
- package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +23 -13
- package/lib/dependencies/ImportMetaContextPlugin.js +2 -2
- package/lib/dependencies/ImportMetaPlugin.js +172 -20
- package/lib/dependencies/ImportParserPlugin.js +327 -49
- package/lib/dependencies/ImportPhase.js +121 -0
- package/lib/dependencies/ImportPlugin.js +3 -1
- package/lib/dependencies/ImportWeakDependency.js +7 -5
- package/lib/dependencies/JsonExportsDependency.js +54 -28
- package/lib/dependencies/LoaderDependency.js +0 -3
- package/lib/dependencies/LoaderImportDependency.js +0 -3
- package/lib/dependencies/LoaderPlugin.js +24 -25
- package/lib/dependencies/LocalModulesHelpers.js +4 -4
- package/lib/dependencies/ModuleDecoratorDependency.js +2 -4
- package/lib/dependencies/ModuleDependency.js +14 -13
- package/lib/dependencies/ModuleDependencyTemplateAsRequireId.js +1 -0
- package/lib/dependencies/ModuleHotAcceptDependency.js +1 -1
- package/lib/dependencies/NullDependency.js +2 -0
- package/lib/dependencies/ProvidedDependency.js +8 -10
- package/lib/dependencies/PureExpressionDependency.js +1 -2
- package/lib/dependencies/RequireContextDependency.js +2 -1
- package/lib/dependencies/RequireContextDependencyParserPlugin.js +47 -44
- package/lib/dependencies/RequireContextPlugin.js +5 -2
- package/lib/dependencies/RequireEnsureDependenciesBlock.js +3 -3
- package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +101 -99
- package/lib/dependencies/RequireEnsurePlugin.js +6 -6
- package/lib/dependencies/RequireIncludeDependency.js +2 -2
- package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +33 -34
- package/lib/dependencies/RequireIncludePlugin.js +1 -0
- package/lib/dependencies/RequireResolveContextDependency.js +1 -1
- package/lib/dependencies/RequireResolveDependency.js +3 -3
- package/lib/dependencies/RuntimeRequirementsDependency.js +3 -4
- package/lib/dependencies/StaticExportsDependency.js +3 -5
- package/lib/dependencies/SystemPlugin.js +4 -4
- package/lib/dependencies/URLContextDependency.js +65 -0
- package/lib/dependencies/URLDependency.js +3 -8
- package/lib/dependencies/URLPlugin.js +18 -159
- package/lib/dependencies/WebAssemblyExportImportedDependency.js +3 -3
- package/lib/dependencies/WebAssemblyImportDependency.js +2 -2
- package/lib/dependencies/WebpackIsIncludedDependency.js +2 -3
- package/lib/dependencies/WorkerDependency.js +8 -6
- package/lib/dependencies/WorkerPlugin.js +131 -67
- package/lib/dependencies/getFunctionExpression.js +2 -2
- package/lib/dependencies/processExportInfo.js +4 -4
- package/lib/esm/ExportWebpackRequireRuntimeModule.js +1 -1
- package/lib/esm/ModuleChunkFormatPlugin.js +232 -179
- package/lib/esm/ModuleChunkLoadingPlugin.js +112 -57
- package/lib/esm/ModuleChunkLoadingRuntimeModule.js +102 -28
- package/lib/formatLocation.js +2 -2
- package/lib/hmr/HotModuleReplacement.runtime.js +41 -29
- package/lib/hmr/HotModuleReplacementRuntimeModule.js +1 -1
- package/lib/hmr/JavascriptHotModuleReplacement.runtime.js +43 -33
- package/lib/hmr/JavascriptHotModuleReplacementHelper.js +37 -0
- package/lib/hmr/LazyCompilationPlugin.js +67 -54
- package/lib/hmr/lazyCompilationBackend.js +23 -18
- package/lib/ids/ChunkModuleIdRangePlugin.js +14 -11
- package/lib/ids/DeterministicChunkIdsPlugin.js +32 -37
- package/lib/ids/DeterministicModuleIdsPlugin.js +52 -52
- package/lib/ids/HashedModuleIdsPlugin.js +15 -13
- package/lib/ids/IdHelpers.js +66 -49
- package/lib/ids/NamedChunkIdsPlugin.js +14 -17
- package/lib/ids/NamedModuleIdsPlugin.js +12 -14
- package/lib/ids/NaturalChunkIdsPlugin.js +6 -4
- package/lib/ids/NaturalModuleIdsPlugin.js +4 -3
- package/lib/ids/OccurrenceChunkIdsPlugin.js +7 -5
- package/lib/ids/OccurrenceModuleIdsPlugin.js +8 -7
- package/lib/ids/SyncModuleIdsPlugin.js +18 -13
- package/lib/index.js +54 -14
- package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +116 -119
- package/lib/javascript/BasicEvaluatedExpression.js +26 -18
- package/lib/javascript/ChunkFormatHelpers.js +70 -0
- package/lib/javascript/ChunkHelpers.js +17 -5
- package/lib/javascript/CommonJsChunkFormatPlugin.js +114 -141
- package/lib/javascript/EnableChunkLoadingPlugin.js +7 -4
- package/lib/javascript/JavascriptGenerator.js +122 -100
- package/lib/javascript/JavascriptModulesPlugin.js +332 -152
- package/lib/javascript/JavascriptParser.js +1488 -1052
- package/lib/javascript/JavascriptParserHelpers.js +48 -47
- package/lib/javascript/StartupHelpers.js +23 -22
- package/lib/json/JsonData.js +4 -4
- package/lib/json/JsonGenerator.js +66 -32
- package/lib/json/JsonModulesPlugin.js +16 -6
- package/lib/json/JsonParser.js +23 -8
- package/lib/library/AbstractLibraryPlugin.js +45 -10
- package/lib/library/AmdLibraryPlugin.js +7 -5
- package/lib/library/AssignLibraryPlugin.js +71 -17
- package/lib/library/EnableLibraryPlugin.js +51 -25
- package/lib/library/ExportPropertyLibraryPlugin.js +12 -18
- package/lib/library/JsonpLibraryPlugin.js +5 -2
- package/lib/library/ModuleLibraryPlugin.js +230 -18
- package/lib/library/SystemLibraryPlugin.js +29 -11
- package/lib/library/UmdLibraryPlugin.js +35 -32
- package/lib/logging/Logger.js +18 -15
- package/lib/logging/createConsoleLogger.js +27 -27
- package/lib/logging/runtime.js +11 -11
- package/lib/logging/truncateArgs.js +5 -5
- package/lib/node/CommonJsChunkLoadingPlugin.js +72 -75
- package/lib/node/NodeEnvironmentPlugin.js +9 -3
- package/lib/node/NodeTargetPlugin.js +9 -1
- package/lib/node/NodeTemplatePlugin.js +2 -2
- package/lib/node/NodeWatchFileSystem.js +4 -4
- package/lib/node/ReadFileChunkLoadingRuntimeModule.js +22 -38
- package/lib/node/ReadFileCompileAsyncWasmPlugin.js +10 -11
- package/lib/node/ReadFileCompileWasmPlugin.js +11 -14
- package/lib/node/RequireChunkLoadingRuntimeModule.js +22 -30
- package/lib/node/nodeConsole.js +12 -7
- package/lib/optimize/AggressiveMergingPlugin.js +46 -47
- package/lib/optimize/AggressiveSplittingPlugin.js +233 -238
- package/lib/optimize/ConcatenatedModule.js +620 -251
- package/lib/optimize/EnsureChunkConditionsPlugin.js +58 -58
- package/lib/optimize/FlagIncludedChunksPlugin.js +93 -96
- package/lib/optimize/InnerGraph.js +139 -124
- package/lib/optimize/InnerGraphPlugin.js +29 -24
- package/lib/optimize/LimitChunkCountPlugin.js +32 -8
- package/lib/optimize/MangleExportsPlugin.js +22 -22
- package/lib/optimize/MergeDuplicateChunksPlugin.js +80 -81
- package/lib/optimize/MinChunkSizePlugin.js +12 -7
- package/lib/optimize/ModuleConcatenationPlugin.js +92 -71
- package/lib/optimize/RealContentHashPlugin.js +58 -44
- package/lib/optimize/RemoveEmptyChunksPlugin.js +8 -5
- package/lib/optimize/RemoveParentModulesPlugin.js +7 -4
- package/lib/optimize/RuntimeChunkPlugin.js +22 -25
- package/lib/optimize/SideEffectsFlagPlugin.js +44 -26
- package/lib/optimize/SplitChunksPlugin.js +209 -158
- package/lib/performance/AssetsOverSizeLimitWarning.js +1 -1
- package/lib/performance/EntrypointsOverSizeLimitWarning.js +2 -2
- package/lib/performance/SizeLimitsPlugin.js +8 -5
- package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +5 -7
- package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +61 -64
- package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +3 -4
- package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +2 -2
- package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +2 -2
- package/lib/rules/BasicEffectRulePlugin.js +14 -5
- package/lib/rules/BasicMatcherRulePlugin.js +18 -7
- package/lib/rules/ObjectMatcherRulePlugin.js +17 -6
- package/lib/rules/RuleSetCompiler.js +73 -32
- package/lib/rules/UseEffectRulePlugin.js +61 -25
- package/lib/runtime/AsyncModuleRuntimeModule.js +74 -9
- package/lib/runtime/AutoPublicPathRuntimeModule.js +9 -4
- package/lib/runtime/BaseUriRuntimeModule.js +2 -2
- package/lib/runtime/CompatRuntimeModule.js +0 -1
- package/lib/runtime/CreateFakeNamespaceObjectRuntimeModule.js +1 -1
- package/lib/runtime/GetChunkFilenameRuntimeModule.js +34 -35
- package/lib/runtime/GetMainFilenameRuntimeModule.js +1 -1
- package/lib/runtime/GetTrustedTypesPolicyRuntimeModule.js +1 -1
- package/lib/runtime/LoadScriptRuntimeModule.js +0 -2
- package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +248 -0
- package/lib/runtime/PublicPathRuntimeModule.js +2 -2
- package/lib/runtime/RuntimeIdRuntimeModule.js +2 -1
- package/lib/runtime/StartupChunkDependenciesPlugin.js +39 -42
- package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +10 -9
- package/lib/runtime/StartupEntrypointRuntimeModule.js +0 -1
- package/lib/runtime/SystemContextRuntimeModule.js +0 -2
- package/lib/runtime/ToBinaryRuntimeModule.js +64 -0
- package/lib/schemes/DataUriPlugin.js +9 -31
- package/lib/schemes/FileUriPlugin.js +11 -6
- package/lib/schemes/HttpUriPlugin.js +381 -261
- package/lib/schemes/VirtualUrlPlugin.js +222 -0
- package/lib/serialization/AggregateErrorSerializer.js +41 -0
- package/lib/serialization/BinaryMiddleware.js +51 -33
- package/lib/serialization/ErrorObjectSerializer.js +7 -2
- package/lib/serialization/FileMiddleware.js +101 -71
- package/lib/serialization/NullPrototypeObjectSerializer.js +5 -3
- package/lib/serialization/ObjectMiddleware.js +130 -54
- package/lib/serialization/PlainObjectSerializer.js +1 -1
- package/lib/serialization/Serializer.js +38 -20
- package/lib/serialization/SerializerMiddleware.js +121 -49
- package/lib/serialization/SingleItemMiddleware.js +9 -7
- package/lib/serialization/types.js +1 -1
- package/lib/sharing/ConsumeSharedModule.js +9 -9
- package/lib/sharing/ConsumeSharedPlugin.js +14 -14
- package/lib/sharing/ConsumeSharedRuntimeModule.js +11 -8
- package/lib/sharing/ProvideSharedModule.js +9 -11
- package/lib/sharing/ProvideSharedModuleFactory.js +5 -3
- package/lib/sharing/ProvideSharedPlugin.js +15 -10
- package/lib/sharing/SharePlugin.js +3 -4
- package/lib/sharing/ShareRuntimeModule.js +7 -6
- package/lib/sharing/resolveMatchedConfigs.js +27 -13
- package/lib/sharing/utils.js +37 -43
- package/lib/stats/DefaultStatsFactoryPlugin.js +455 -286
- package/lib/stats/DefaultStatsPresetPlugin.js +77 -46
- package/lib/stats/DefaultStatsPrinterPlugin.js +583 -419
- package/lib/stats/StatsFactory.js +75 -32
- package/lib/stats/StatsPrinter.js +71 -51
- package/lib/url/URLParserPlugin.js +264 -0
- package/lib/util/ArrayHelpers.js +6 -8
- package/lib/util/ArrayQueue.js +1 -1
- package/lib/util/AsyncQueue.js +11 -10
- package/lib/util/Hash.js +37 -5
- package/lib/util/IterableHelpers.js +4 -4
- package/lib/util/LazyBucketSortedSet.js +46 -27
- package/lib/util/LazySet.js +16 -10
- package/lib/util/MapHelpers.js +1 -1
- package/lib/util/ParallelismFactorCalculator.js +2 -2
- package/lib/util/Semaphore.js +3 -3
- package/lib/util/SetHelpers.js +6 -6
- package/lib/util/SortableSet.js +11 -9
- package/lib/util/StackedCacheMap.js +2 -2
- package/lib/util/StackedMap.js +3 -3
- package/lib/util/StringXor.js +2 -1
- package/lib/util/TupleQueue.js +11 -8
- package/lib/util/TupleSet.js +44 -19
- package/lib/util/URLAbsoluteSpecifier.js +3 -4
- package/lib/util/WeakTupleMap.js +56 -42
- package/lib/util/binarySearchBounds.js +4 -3
- package/lib/util/chainedImports.js +3 -1
- package/lib/util/cleverMerge.js +171 -107
- package/lib/util/comparators.js +265 -162
- package/lib/util/compileBooleanMatcher.js +120 -41
- package/lib/util/concatenate.js +20 -16
- package/lib/util/conventions.js +73 -74
- package/lib/util/create-schema-validation.js +8 -8
- package/lib/util/createHash.js +32 -135
- package/lib/util/dataURL.js +39 -0
- package/lib/util/deprecation.js +119 -116
- package/lib/util/deterministicGrouping.js +56 -47
- package/lib/util/extractSourceMap.js +319 -0
- package/lib/util/extractUrlAndGlobal.js +1 -1
- package/lib/util/findGraphRoots.js +19 -9
- package/lib/util/fs.js +169 -141
- package/lib/util/hash/BatchedHash.js +50 -10
- package/lib/util/hash/BulkUpdateHash.js +138 -0
- package/lib/util/hash/DebugHash.js +75 -0
- package/lib/util/hash/hash-digest.js +216 -0
- package/lib/util/hash/md4.js +2 -2
- package/lib/util/hash/wasm-hash.js +59 -17
- package/lib/util/identifier.js +124 -61
- package/lib/util/internalSerializables.js +4 -6
- package/lib/util/magicComment.js +9 -5
- package/lib/util/makeSerializable.js +2 -2
- package/lib/util/memoize.js +5 -2
- package/lib/util/objectToMap.js +3 -2
- package/lib/util/processAsyncTree.js +5 -5
- package/lib/util/propertyAccess.js +1 -1
- package/lib/util/propertyName.js +2 -3
- package/lib/util/registerExternalSerializer.js +16 -20
- package/lib/util/removeBOM.js +25 -0
- package/lib/util/runtime.js +72 -56
- package/lib/util/semver.js +44 -33
- package/lib/util/serialization.js +56 -56
- package/lib/util/smartGrouping.js +42 -27
- package/lib/util/source.js +5 -4
- package/lib/util/traverseDestructuringAssignmentProperties.js +45 -0
- package/lib/validateSchema.js +7 -9
- package/lib/wasm/EnableWasmLoadingPlugin.js +22 -12
- package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +9 -5
- package/lib/wasm-async/AsyncWebAssemblyGenerator.js +15 -3
- package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +28 -22
- package/lib/wasm-async/AsyncWebAssemblyModulesPlugin.js +47 -57
- package/lib/wasm-async/AsyncWebAssemblyParser.js +2 -10
- package/lib/wasm-async/UniversalCompileAsyncWasmPlugin.js +8 -4
- package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +23 -17
- package/lib/wasm-sync/WasmFinalizeExportsPlugin.js +55 -57
- package/lib/wasm-sync/WebAssemblyGenerator.js +56 -41
- package/lib/wasm-sync/WebAssemblyInInitialChunkError.js +6 -3
- package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +25 -10
- package/lib/wasm-sync/WebAssemblyModulesPlugin.js +11 -12
- package/lib/wasm-sync/WebAssemblyParser.js +10 -17
- package/lib/wasm-sync/WebAssemblyUtils.js +1 -1
- package/lib/web/FetchCompileAsyncWasmPlugin.js +4 -4
- package/lib/web/FetchCompileWasmPlugin.js +6 -8
- package/lib/web/JsonpChunkLoadingPlugin.js +74 -74
- package/lib/web/JsonpChunkLoadingRuntimeModule.js +10 -26
- package/lib/web/JsonpTemplatePlugin.js +0 -1
- package/lib/webpack.js +107 -87
- package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +79 -75
- package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +38 -51
- package/lib/webworker/WebWorkerTemplatePlugin.js +1 -0
- package/module.d.ts +5 -0
- package/package.json +149 -129
- package/schemas/WebpackOptions.check.d.ts +1 -1
- package/schemas/WebpackOptions.check.js +2 -2
- package/schemas/WebpackOptions.json +543 -190
- package/schemas/plugins/BannerPlugin.check.d.ts +1 -1
- package/schemas/plugins/BannerPlugin.check.js +2 -2
- package/schemas/plugins/BannerPlugin.json +4 -0
- package/schemas/plugins/DllPlugin.check.d.ts +1 -1
- package/schemas/plugins/DllPlugin.check.js +1 -1
- package/schemas/plugins/DllReferencePlugin.check.d.ts +1 -1
- package/schemas/plugins/DllReferencePlugin.check.js +1 -1
- package/schemas/plugins/IgnorePlugin.check.d.ts +1 -1
- package/schemas/plugins/IgnorePlugin.check.js +1 -1
- package/schemas/plugins/IgnorePlugin.json +1 -1
- package/schemas/plugins/LoaderOptionsPlugin.check.d.ts +1 -1
- package/schemas/plugins/LoaderOptionsPlugin.check.js +1 -1
- package/schemas/plugins/{HashedModuleIdsPlugin.check.d.ts → ManifestPlugin.check.d.ts} +2 -2
- package/schemas/plugins/ManifestPlugin.check.js +6 -0
- package/schemas/plugins/ManifestPlugin.json +98 -0
- package/schemas/plugins/ProgressPlugin.check.d.ts +1 -1
- package/schemas/plugins/ProgressPlugin.check.js +1 -1
- package/schemas/plugins/ProgressPlugin.json +1 -1
- package/schemas/plugins/SourceMapDevToolPlugin.check.d.ts +1 -1
- package/schemas/plugins/SourceMapDevToolPlugin.check.js +2 -2
- package/schemas/plugins/SourceMapDevToolPlugin.json +23 -6
- package/schemas/plugins/WatchIgnorePlugin.check.d.ts +1 -1
- package/schemas/plugins/WatchIgnorePlugin.check.js +1 -1
- package/schemas/plugins/asset/AssetGeneratorOptions.check.d.ts +1 -1
- package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
- package/schemas/plugins/asset/AssetInlineGeneratorOptions.check.d.ts +1 -1
- package/schemas/plugins/asset/AssetInlineGeneratorOptions.check.js +1 -1
- package/schemas/plugins/asset/AssetParserOptions.check.d.ts +1 -1
- package/schemas/plugins/asset/AssetParserOptions.check.js +1 -1
- package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.d.ts +1 -1
- package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
- package/schemas/plugins/container/ContainerPlugin.check.d.ts +1 -1
- package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
- package/schemas/plugins/container/ContainerReferencePlugin.check.d.ts +1 -1
- package/schemas/plugins/container/ContainerReferencePlugin.check.js +2 -2
- package/schemas/plugins/container/ContainerReferencePlugin.json +4 -1
- package/schemas/plugins/container/ExternalsType.check.d.ts +1 -1
- package/schemas/plugins/container/ExternalsType.check.js +2 -2
- package/schemas/plugins/container/ModuleFederationPlugin.check.d.ts +1 -1
- package/schemas/plugins/container/ModuleFederationPlugin.check.js +2 -2
- package/schemas/plugins/container/ModuleFederationPlugin.json +4 -1
- package/schemas/plugins/css/CssGeneratorOptions.check.d.ts +1 -1
- package/schemas/plugins/css/CssGeneratorOptions.check.js +1 -1
- package/schemas/plugins/css/CssModuleGeneratorOptions.check.d.ts +1 -1
- package/schemas/plugins/css/CssModuleGeneratorOptions.check.js +2 -2
- package/schemas/plugins/css/CssModuleParserOptions.check.d.ts +1 -1
- package/schemas/plugins/css/CssModuleParserOptions.check.js +2 -2
- package/schemas/plugins/css/CssParserOptions.check.d.ts +1 -1
- package/schemas/plugins/css/CssParserOptions.check.js +2 -2
- package/schemas/plugins/debug/ProfilingPlugin.check.d.ts +1 -1
- package/schemas/plugins/debug/ProfilingPlugin.check.js +1 -1
- package/schemas/plugins/ids/HashedModuleIdsPlugin.check.d.ts +7 -0
- package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +6 -0
- package/schemas/plugins/{HashedModuleIdsPlugin.json → ids/HashedModuleIdsPlugin.json} +15 -2
- package/schemas/plugins/ids/OccurrenceChunkIdsPlugin.check.d.ts +1 -1
- package/schemas/plugins/ids/OccurrenceChunkIdsPlugin.check.js +1 -1
- package/schemas/plugins/ids/OccurrenceModuleIdsPlugin.check.d.ts +1 -1
- package/schemas/plugins/ids/OccurrenceModuleIdsPlugin.check.js +1 -1
- package/schemas/plugins/{css/CssGlobalParserOptions.check.d.ts → json/JsonModulesPluginGenerator.check.d.ts} +1 -1
- package/schemas/plugins/json/JsonModulesPluginGenerator.check.js +6 -0
- package/schemas/plugins/json/JsonModulesPluginGenerator.json +3 -0
- package/schemas/plugins/{css/CssGlobalGeneratorOptions.check.d.ts → json/JsonModulesPluginParser.check.d.ts} +1 -1
- package/schemas/plugins/json/JsonModulesPluginParser.check.js +6 -0
- package/schemas/plugins/json/JsonModulesPluginParser.json +3 -0
- package/schemas/plugins/optimize/AggressiveSplittingPlugin.check.d.ts +1 -1
- package/schemas/plugins/optimize/AggressiveSplittingPlugin.check.js +1 -1
- package/schemas/plugins/optimize/LimitChunkCountPlugin.check.d.ts +1 -1
- package/schemas/plugins/optimize/LimitChunkCountPlugin.check.js +1 -1
- package/schemas/plugins/optimize/MergeDuplicateChunksPlugin.check.d.ts +1 -1
- package/schemas/plugins/optimize/MergeDuplicateChunksPlugin.check.js +1 -1
- package/schemas/plugins/optimize/MinChunkSizePlugin.check.d.ts +1 -1
- package/schemas/plugins/optimize/MinChunkSizePlugin.check.js +1 -1
- package/schemas/plugins/schemes/HttpUriPlugin.check.d.ts +1 -1
- package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
- package/schemas/plugins/schemes/VirtualUrlPlugin.check.d.ts +7 -0
- package/schemas/plugins/schemes/VirtualUrlPlugin.check.js +6 -0
- package/schemas/plugins/schemes/VirtualUrlPlugin.json +77 -0
- package/schemas/plugins/sharing/ConsumeSharedPlugin.check.d.ts +1 -1
- package/schemas/plugins/sharing/ConsumeSharedPlugin.check.js +1 -1
- package/schemas/plugins/sharing/ProvideSharedPlugin.check.d.ts +1 -1
- package/schemas/plugins/sharing/ProvideSharedPlugin.check.js +1 -1
- package/schemas/plugins/sharing/SharePlugin.check.d.ts +1 -1
- package/schemas/plugins/sharing/SharePlugin.check.js +1 -1
- package/types.d.ts +5115 -1863
- package/SECURITY.md +0 -9
- package/lib/ModuleSourceTypesConstants.js +0 -112
- package/lib/dependencies/CssLocalIdentifierDependency.js +0 -250
- package/lib/dependencies/CssSelfLocalIdentifierDependency.js +0 -111
- package/lib/library/ModernModuleLibraryPlugin.js +0 -144
- package/schemas/plugins/HashedModuleIdsPlugin.check.js +0 -6
- package/schemas/plugins/JsonModulesPluginParser.check.d.ts +0 -7
- package/schemas/plugins/JsonModulesPluginParser.check.js +0 -6
- package/schemas/plugins/JsonModulesPluginParser.json +0 -12
- package/schemas/plugins/css/CssAutoGeneratorOptions.check.d.ts +0 -7
- package/schemas/plugins/css/CssAutoGeneratorOptions.check.js +0 -6
- package/schemas/plugins/css/CssAutoGeneratorOptions.json +0 -3
- package/schemas/plugins/css/CssAutoParserOptions.check.d.ts +0 -7
- package/schemas/plugins/css/CssAutoParserOptions.check.js +0 -6
- package/schemas/plugins/css/CssAutoParserOptions.json +0 -3
- package/schemas/plugins/css/CssGlobalGeneratorOptions.check.js +0 -6
- package/schemas/plugins/css/CssGlobalGeneratorOptions.json +0 -3
- package/schemas/plugins/css/CssGlobalParserOptions.check.js +0 -6
- package/schemas/plugins/css/CssGlobalParserOptions.json +0 -3
|
@@ -5,37 +5,41 @@
|
|
|
5
5
|
|
|
6
6
|
"use strict";
|
|
7
7
|
|
|
8
|
-
const { Parser: AcornParser, tokTypes } = require("acorn");
|
|
9
|
-
const { SyncBailHook, HookMap } = require("tapable");
|
|
10
8
|
const vm = require("vm");
|
|
9
|
+
const { Parser: AcornParser, tokTypes } = require("acorn");
|
|
10
|
+
const { HookMap, SyncBailHook } = require("tapable");
|
|
11
|
+
const NormalModule = require("../NormalModule");
|
|
11
12
|
const Parser = require("../Parser");
|
|
12
13
|
const StackedMap = require("../util/StackedMap");
|
|
13
14
|
const binarySearchBounds = require("../util/binarySearchBounds");
|
|
14
15
|
const {
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
createMagicCommentContext,
|
|
17
|
+
webpackCommentRegExp
|
|
17
18
|
} = require("../util/magicComment");
|
|
18
19
|
const memoize = require("../util/memoize");
|
|
19
20
|
const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
|
|
20
21
|
|
|
21
22
|
/** @typedef {import("acorn").Options} AcornOptions */
|
|
23
|
+
/** @typedef {import("acorn").ecmaVersion} EcmaVersion */
|
|
22
24
|
/** @typedef {import("estree").AssignmentExpression} AssignmentExpression */
|
|
23
25
|
/** @typedef {import("estree").BinaryExpression} BinaryExpression */
|
|
24
26
|
/** @typedef {import("estree").BlockStatement} BlockStatement */
|
|
25
27
|
/** @typedef {import("estree").SequenceExpression} SequenceExpression */
|
|
26
28
|
/** @typedef {import("estree").CallExpression} CallExpression */
|
|
27
|
-
/** @typedef {import("estree").BaseCallExpression} BaseCallExpression */
|
|
28
29
|
/** @typedef {import("estree").StaticBlock} StaticBlock */
|
|
29
30
|
/** @typedef {import("estree").ClassDeclaration} ClassDeclaration */
|
|
30
31
|
/** @typedef {import("estree").ForStatement} ForStatement */
|
|
31
32
|
/** @typedef {import("estree").SwitchStatement} SwitchStatement */
|
|
32
33
|
/** @typedef {import("estree").ClassExpression} ClassExpression */
|
|
33
|
-
/** @typedef {import("estree").
|
|
34
|
+
/** @typedef {import("estree").SourceLocation} SourceLocation */
|
|
35
|
+
/** @typedef {import("estree").Comment & { start: number, end: number, loc: SourceLocation }} Comment */
|
|
34
36
|
/** @typedef {import("estree").ConditionalExpression} ConditionalExpression */
|
|
35
37
|
/** @typedef {import("estree").Declaration} Declaration */
|
|
36
38
|
/** @typedef {import("estree").PrivateIdentifier} PrivateIdentifier */
|
|
37
39
|
/** @typedef {import("estree").PropertyDefinition} PropertyDefinition */
|
|
38
40
|
/** @typedef {import("estree").Expression} Expression */
|
|
41
|
+
/** @typedef {import("estree").ImportAttribute} ImportAttribute */
|
|
42
|
+
/** @typedef {import("estree").ImportDeclaration} ImportDeclaration */
|
|
39
43
|
/** @typedef {import("estree").Identifier} Identifier */
|
|
40
44
|
/** @typedef {import("estree").VariableDeclaration} VariableDeclaration */
|
|
41
45
|
/** @typedef {import("estree").IfStatement} IfStatement */
|
|
@@ -48,7 +52,6 @@ const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
|
|
|
48
52
|
/** @typedef {import("estree").MetaProperty} MetaProperty */
|
|
49
53
|
/** @typedef {import("estree").Property} Property */
|
|
50
54
|
/** @typedef {import("estree").AssignmentPattern} AssignmentPattern */
|
|
51
|
-
/** @typedef {import("estree").ChainElement} ChainElement */
|
|
52
55
|
/** @typedef {import("estree").Pattern} Pattern */
|
|
53
56
|
/** @typedef {import("estree").UpdateExpression} UpdateExpression */
|
|
54
57
|
/** @typedef {import("estree").ObjectExpression} ObjectExpression */
|
|
@@ -74,6 +77,8 @@ const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
|
|
|
74
77
|
/** @typedef {import("estree").WhileStatement} WhileStatement */
|
|
75
78
|
/** @typedef {import("estree").ArrowFunctionExpression} ArrowFunctionExpression */
|
|
76
79
|
/** @typedef {import("estree").ExpressionStatement} ExpressionStatement */
|
|
80
|
+
/** @typedef {import("estree").ExportAllDeclaration} ExportAllDeclaration */
|
|
81
|
+
/** @typedef {import("estree").ExportNamedDeclaration} ExportNamedDeclaration */
|
|
77
82
|
/** @typedef {import("estree").FunctionDeclaration} FunctionDeclaration */
|
|
78
83
|
/** @typedef {import("estree").DoWhileStatement} DoWhileStatement */
|
|
79
84
|
/** @typedef {import("estree").TryStatement} TryStatement */
|
|
@@ -85,27 +90,42 @@ const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
|
|
|
85
90
|
/** @typedef {import("estree").Super} Super */
|
|
86
91
|
/** @typedef {import("estree").TaggedTemplateExpression} TaggedTemplateExpression */
|
|
87
92
|
/** @typedef {import("estree").TemplateLiteral} TemplateLiteral */
|
|
88
|
-
/** @typedef {import("estree").
|
|
93
|
+
/** @typedef {import("estree").ModuleDeclaration} ModuleDeclaration */
|
|
94
|
+
/** @typedef {import("estree").MaybeNamedFunctionDeclaration} MaybeNamedFunctionDeclaration */
|
|
95
|
+
/** @typedef {import("estree").MaybeNamedClassDeclaration} MaybeNamedClassDeclaration */
|
|
89
96
|
/**
|
|
90
97
|
* @template T
|
|
91
98
|
* @typedef {import("tapable").AsArray<T>} AsArray<T>
|
|
92
99
|
*/
|
|
93
100
|
/** @typedef {import("../Parser").ParserState} ParserState */
|
|
94
101
|
/** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
|
|
95
|
-
|
|
96
|
-
/** @typedef {
|
|
97
|
-
/** @typedef {
|
|
98
|
-
|
|
99
|
-
/**
|
|
102
|
+
|
|
103
|
+
/** @typedef {import("../dependencies/LocalModule")} LocalModule */
|
|
104
|
+
/** @typedef {import("../dependencies/HarmonyExportImportedSpecifierDependency").HarmonyStarExportsList} HarmonyStarExportsList */
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @typedef {object} KnownJavascriptParserState
|
|
108
|
+
* @property {Set<string>=} harmonyNamedExports
|
|
109
|
+
* @property {HarmonyStarExportsList=} harmonyStarExports
|
|
110
|
+
* @property {number=} lastHarmonyImportOrder
|
|
111
|
+
* @property {LocalModule[]=} localModules
|
|
112
|
+
*/
|
|
113
|
+
|
|
114
|
+
/** @typedef {ParserState & KnownJavascriptParserState} JavascriptParserState */
|
|
115
|
+
|
|
116
|
+
/** @typedef {import("../Compilation")} Compilation */
|
|
117
|
+
/** @typedef {import("../Module")} Module */
|
|
118
|
+
|
|
119
|
+
/** @typedef {{ name: string | VariableInfo, rootInfo: string | VariableInfo, getMembers: () => Members, getMembersOptionals: () => MembersOptionals, getMemberRanges: () => MemberRanges }} GetInfoResult */
|
|
120
|
+
/** @typedef {Statement | ModuleDeclaration | Expression | MaybeNamedFunctionDeclaration | MaybeNamedClassDeclaration} StatementPathItem */
|
|
121
|
+
/** @typedef {(ident: string) => void} OnIdentString */
|
|
122
|
+
/** @typedef {(ident: string, identifier: Identifier) => void} OnIdent */
|
|
100
123
|
/** @typedef {StatementPathItem[]} StatementPath */
|
|
101
124
|
|
|
125
|
+
/** @typedef {Set<DestructuringAssignmentProperty>} DestructuringAssignmentProperties */
|
|
126
|
+
|
|
102
127
|
// TODO remove cast when @types/estree has been updated to import assertions
|
|
103
|
-
/** @typedef {import("estree").
|
|
104
|
-
/** @typedef {import("estree").ImportDeclaration & { attributes?: Array<ImportAttribute> }} ImportDeclaration */
|
|
105
|
-
/** @typedef {import("estree").ExportNamedDeclaration & { attributes?: Array<ImportAttribute> }} ExportNamedDeclaration */
|
|
106
|
-
/** @typedef {import("estree").ExportAllDeclaration & { attributes?: Array<ImportAttribute> }} ExportAllDeclaration */
|
|
107
|
-
/** @typedef {import("estree").ImportExpression & { options?: Expression | null }} ImportExpression */
|
|
108
|
-
/** @typedef {ImportDeclaration | ExportNamedDeclaration | ExportDefaultDeclaration | ExportAllDeclaration} ModuleDeclaration */
|
|
128
|
+
/** @typedef {import("estree").ImportExpression & { phase?: "defer" }} ImportExpression */
|
|
109
129
|
|
|
110
130
|
/** @type {string[]} */
|
|
111
131
|
const EMPTY_ARRAY = [];
|
|
@@ -115,69 +135,71 @@ const ALLOWED_MEMBER_TYPES_ALL = 0b11;
|
|
|
115
135
|
|
|
116
136
|
const LEGACY_ASSERT_ATTRIBUTES = Symbol("assert");
|
|
117
137
|
|
|
118
|
-
/**
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const isAssertLegacy = this.value === "assert";
|
|
130
|
-
|
|
131
|
-
if (isAssertLegacy) {
|
|
132
|
-
if (!this.eat(tokTypes.name)) {
|
|
133
|
-
return nodes;
|
|
134
|
-
}
|
|
135
|
-
} else if (!this.eat(tokTypes._with)) {
|
|
136
|
-
return nodes;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
this.expect(tokTypes.braceL);
|
|
138
|
+
/** @type {(BaseParser: typeof AcornParser) => typeof AcornParser} */
|
|
139
|
+
const importAssertions = (Parser) =>
|
|
140
|
+
class extends Parser {
|
|
141
|
+
/**
|
|
142
|
+
* @this {InstanceType<AcornParser>}
|
|
143
|
+
* @returns {ImportAttribute[]} import attributes
|
|
144
|
+
*/
|
|
145
|
+
parseWithClause() {
|
|
146
|
+
/** @type {ImportAttribute[]} */
|
|
147
|
+
const nodes = [];
|
|
140
148
|
|
|
141
|
-
|
|
142
|
-
let first = true;
|
|
149
|
+
const isAssertLegacy = this.value === "assert";
|
|
143
150
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
first = false;
|
|
152
|
-
}
|
|
151
|
+
if (isAssertLegacy) {
|
|
152
|
+
if (!this.eat(tokTypes.name)) {
|
|
153
|
+
return nodes;
|
|
154
|
+
}
|
|
155
|
+
} else if (!this.eat(tokTypes._with)) {
|
|
156
|
+
return nodes;
|
|
157
|
+
}
|
|
153
158
|
|
|
154
|
-
|
|
155
|
-
const keyName =
|
|
156
|
-
attr.key.type === "Identifier" ? attr.key.name : attr.key.value;
|
|
159
|
+
this.expect(tokTypes.braceL);
|
|
157
160
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
`Duplicate attribute key '${keyName}'`
|
|
162
|
-
);
|
|
163
|
-
}
|
|
161
|
+
/** @type {Record<string, boolean>} */
|
|
162
|
+
const attributeKeys = {};
|
|
163
|
+
let first = true;
|
|
164
164
|
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
while (!this.eat(tokTypes.braceR)) {
|
|
166
|
+
if (!first) {
|
|
167
|
+
this.expect(tokTypes.comma);
|
|
168
|
+
if (this.afterTrailingComma(tokTypes.braceR)) {
|
|
169
|
+
break;
|
|
167
170
|
}
|
|
171
|
+
} else {
|
|
172
|
+
first = false;
|
|
173
|
+
}
|
|
168
174
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
175
|
+
const attr =
|
|
176
|
+
/** @type {ImportAttribute} */
|
|
177
|
+
this.parseImportAttribute();
|
|
178
|
+
const keyName =
|
|
179
|
+
attr.key.type === "Identifier" ? attr.key.name : attr.key.value;
|
|
172
180
|
|
|
173
|
-
|
|
181
|
+
if (Object.prototype.hasOwnProperty.call(attributeKeys, keyName)) {
|
|
182
|
+
this.raiseRecoverable(
|
|
183
|
+
attr.key.start,
|
|
184
|
+
`Duplicate attribute key '${keyName}'`
|
|
185
|
+
);
|
|
174
186
|
}
|
|
187
|
+
|
|
188
|
+
attributeKeys[keyName] = true;
|
|
189
|
+
nodes.push(attr);
|
|
175
190
|
}
|
|
176
|
-
|
|
177
|
-
|
|
191
|
+
|
|
192
|
+
if (isAssertLegacy) {
|
|
193
|
+
/** @type {EXPECTED_ANY} */
|
|
194
|
+
(nodes)[LEGACY_ASSERT_ATTRIBUTES] = true;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return nodes;
|
|
198
|
+
}
|
|
199
|
+
};
|
|
178
200
|
|
|
179
201
|
// Syntax: https://developer.mozilla.org/en/SpiderMonkey/Parser_API
|
|
180
|
-
|
|
202
|
+
let parser = AcornParser.extend(importAssertions);
|
|
181
203
|
|
|
182
204
|
/** @typedef {Record<string, string> & { _isLegacyAssert?: boolean }} ImportAttributes */
|
|
183
205
|
|
|
@@ -185,7 +207,7 @@ const parser = AcornParser.extend(importAssertions);
|
|
|
185
207
|
* @param {ImportDeclaration | ExportNamedDeclaration | ExportAllDeclaration | ImportExpression} node node with assertions
|
|
186
208
|
* @returns {ImportAttributes | undefined} import attributes
|
|
187
209
|
*/
|
|
188
|
-
const getImportAttributes = node => {
|
|
210
|
+
const getImportAttributes = (node) => {
|
|
189
211
|
if (node.type === "ImportExpression") {
|
|
190
212
|
if (
|
|
191
213
|
node.options &&
|
|
@@ -247,37 +269,107 @@ const getImportAttributes = node => {
|
|
|
247
269
|
result[key] = /** @type {string} */ (attribute.value.value);
|
|
248
270
|
}
|
|
249
271
|
|
|
250
|
-
if (node.attributes[LEGACY_ASSERT_ATTRIBUTES]) {
|
|
272
|
+
if (/** @type {EXPECTED_ANY} */ (node.attributes)[LEGACY_ASSERT_ATTRIBUTES]) {
|
|
251
273
|
result._isLegacyAssert = true;
|
|
252
274
|
}
|
|
253
275
|
|
|
254
276
|
return result;
|
|
255
277
|
};
|
|
256
278
|
|
|
279
|
+
/** @typedef {typeof VariableInfoFlags.Evaluated | typeof VariableInfoFlags.Free | typeof VariableInfoFlags.Normal | typeof VariableInfoFlags.Tagged} VariableInfoFlagsType */
|
|
280
|
+
|
|
281
|
+
const VariableInfoFlags = Object.freeze({
|
|
282
|
+
Evaluated: 0b000,
|
|
283
|
+
Free: 0b001,
|
|
284
|
+
Normal: 0b010,
|
|
285
|
+
Tagged: 0b100
|
|
286
|
+
});
|
|
287
|
+
|
|
257
288
|
class VariableInfo {
|
|
258
289
|
/**
|
|
259
290
|
* @param {ScopeInfo} declaredScope scope in which the variable is declared
|
|
260
|
-
* @param {string |
|
|
291
|
+
* @param {string | undefined} name which name the variable use, defined name or free name or tagged name
|
|
292
|
+
* @param {VariableInfoFlagsType} flags how the variable is created
|
|
261
293
|
* @param {TagInfo | undefined} tagInfo info about tags
|
|
262
294
|
*/
|
|
263
|
-
constructor(declaredScope,
|
|
295
|
+
constructor(declaredScope, name, flags, tagInfo) {
|
|
264
296
|
this.declaredScope = declaredScope;
|
|
265
|
-
this.
|
|
297
|
+
this.name = name;
|
|
298
|
+
this.flags = flags;
|
|
266
299
|
this.tagInfo = tagInfo;
|
|
267
300
|
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* @returns {boolean} the variable is free or not
|
|
304
|
+
*/
|
|
305
|
+
isFree() {
|
|
306
|
+
return (this.flags & VariableInfoFlags.Free) > 0;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* @returns {boolean} the variable is tagged by tagVariable or not
|
|
311
|
+
*/
|
|
312
|
+
isTagged() {
|
|
313
|
+
return (this.flags & VariableInfoFlags.Tagged) > 0;
|
|
314
|
+
}
|
|
268
315
|
}
|
|
269
316
|
|
|
270
317
|
/** @typedef {string | ScopeInfo | VariableInfo} ExportedVariableInfo */
|
|
271
318
|
/** @typedef {Literal | string | null | undefined} ImportSource */
|
|
272
|
-
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* @typedef {Omit<ParseOptions, "sourceType"> & {sourceType: "module" | "script" | "auto"}} InternalParseOptions
|
|
322
|
+
*/
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* @typedef {object} ParseOptions
|
|
326
|
+
* @property {"module" | "script"} sourceType
|
|
327
|
+
* @property {EcmaVersion=} ecmaVersion
|
|
328
|
+
* @property {boolean=} locations
|
|
329
|
+
* @property {boolean=} comments
|
|
330
|
+
* @property {boolean=} ranges
|
|
331
|
+
* @property {boolean=} semicolons
|
|
332
|
+
* @property {boolean=} allowHashBang
|
|
333
|
+
* @property {boolean=} allowReturnOutsideFunction
|
|
334
|
+
*/
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* @typedef {object} ParseResult
|
|
338
|
+
* @property {Program} ast
|
|
339
|
+
* @property {Comment[]} comments
|
|
340
|
+
* @property {Set<number>} semicolons
|
|
341
|
+
*/
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* @typedef {(code: string, options: ParseOptions) => ParseResult} ParseFunction
|
|
345
|
+
*/
|
|
346
|
+
|
|
347
|
+
/** @typedef {symbol} Tag */
|
|
348
|
+
|
|
349
|
+
/** @typedef {import("../dependencies/HarmonyImportDependencyParserPlugin").HarmonySettings} HarmonySettings */
|
|
350
|
+
/** @typedef {import("../dependencies/ImportParserPlugin").ImportSettings} ImportSettings */
|
|
351
|
+
/** @typedef {import("../dependencies/CommonJsImportsParserPlugin").CommonJsImportSettings} CommonJsImportSettings */
|
|
352
|
+
/** @typedef {import("../CompatibilityPlugin").CompatibilitySettings} CompatibilitySettings */
|
|
353
|
+
/** @typedef {import("../optimize/InnerGraph").TopLevelSymbol} TopLevelSymbol */
|
|
354
|
+
|
|
355
|
+
/** @typedef {HarmonySettings | ImportSettings | CommonJsImportSettings | TopLevelSymbol | CompatibilitySettings} KnownTagData */
|
|
356
|
+
/** @typedef {KnownTagData | Record<string, EXPECTED_ANY>} TagData */
|
|
273
357
|
|
|
274
358
|
/**
|
|
275
359
|
* @typedef {object} TagInfo
|
|
276
|
-
* @property {
|
|
277
|
-
* @property {
|
|
360
|
+
* @property {Tag} tag
|
|
361
|
+
* @property {TagData=} data
|
|
278
362
|
* @property {TagInfo | undefined} next
|
|
279
363
|
*/
|
|
280
364
|
|
|
365
|
+
/** @typedef {string[]} CalleeMembers */
|
|
366
|
+
/** @typedef {string[]} Members */
|
|
367
|
+
/** @typedef {boolean[]} MembersOptionals */
|
|
368
|
+
/** @typedef {Range[]} MemberRanges */
|
|
369
|
+
|
|
370
|
+
const SCOPE_INFO_TERMINATED_RETURN = 1;
|
|
371
|
+
const SCOPE_INFO_TERMINATED_THROW = 2;
|
|
372
|
+
|
|
281
373
|
/**
|
|
282
374
|
* @typedef {object} ScopeInfo
|
|
283
375
|
* @property {StackedMap<string, VariableInfo | ScopeInfo>} definitions
|
|
@@ -287,6 +379,7 @@ class VariableInfo {
|
|
|
287
379
|
* @property {boolean} inTry
|
|
288
380
|
* @property {boolean} isStrict
|
|
289
381
|
* @property {boolean} isAsmJs
|
|
382
|
+
* @property {undefined | 1 | 2} terminated
|
|
290
383
|
*/
|
|
291
384
|
|
|
292
385
|
/** @typedef {[number, number]} Range */
|
|
@@ -294,7 +387,9 @@ class VariableInfo {
|
|
|
294
387
|
/**
|
|
295
388
|
* @typedef {object} DestructuringAssignmentProperty
|
|
296
389
|
* @property {string} id
|
|
297
|
-
* @property {Range
|
|
390
|
+
* @property {Range} range
|
|
391
|
+
* @property {SourceLocation} loc
|
|
392
|
+
* @property {Set<DestructuringAssignmentProperty> | undefined=} pattern
|
|
298
393
|
* @property {boolean | string} shorthand
|
|
299
394
|
*/
|
|
300
395
|
|
|
@@ -302,9 +397,9 @@ class VariableInfo {
|
|
|
302
397
|
* Helper function for joining two ranges into a single range. This is useful
|
|
303
398
|
* when working with AST nodes, as it allows you to combine the ranges of child nodes
|
|
304
399
|
* to create the range of the _parent node_.
|
|
305
|
-
* @param {
|
|
306
|
-
* @param {
|
|
307
|
-
* @returns {
|
|
400
|
+
* @param {Range} startRange start range to join
|
|
401
|
+
* @param {Range} endRange end range to join
|
|
402
|
+
* @returns {Range} joined range
|
|
308
403
|
* @example
|
|
309
404
|
* ```js
|
|
310
405
|
* const startRange = [0, 5];
|
|
@@ -323,7 +418,7 @@ const joinRanges = (startRange, endRange) => {
|
|
|
323
418
|
* Helper function used to generate a string representation of a
|
|
324
419
|
* [member expression](https://github.com/estree/estree/blob/master/es5.md#memberexpression).
|
|
325
420
|
* @param {string} object object to name
|
|
326
|
-
* @param {
|
|
421
|
+
* @param {Members} membersReversed reversed list of members
|
|
327
422
|
* @returns {string} member expression as a string
|
|
328
423
|
* @example
|
|
329
424
|
* ```js
|
|
@@ -350,7 +445,7 @@ const objectAndMembersToName = (object, membersReversed) => {
|
|
|
350
445
|
* @param {Expression | SpreadElement | Super} expression expression
|
|
351
446
|
* @returns {string | "this" | undefined} name or variable info
|
|
352
447
|
*/
|
|
353
|
-
const getRootName = expression => {
|
|
448
|
+
const getRootName = (expression) => {
|
|
354
449
|
switch (expression.type) {
|
|
355
450
|
case "Identifier":
|
|
356
451
|
return expression.name;
|
|
@@ -363,15 +458,15 @@ const getRootName = expression => {
|
|
|
363
458
|
}
|
|
364
459
|
};
|
|
365
460
|
|
|
366
|
-
/** @type {
|
|
461
|
+
/** @type {ParseOptions} */
|
|
367
462
|
const defaultParserOptions = {
|
|
368
|
-
ranges: true,
|
|
369
|
-
locations: true,
|
|
370
|
-
ecmaVersion: "latest",
|
|
371
463
|
sourceType: "module",
|
|
464
|
+
ecmaVersion: "latest",
|
|
465
|
+
ranges: false,
|
|
466
|
+
locations: false,
|
|
467
|
+
comments: false,
|
|
372
468
|
// https://github.com/tc39/proposal-hashbang
|
|
373
|
-
allowHashBang: true
|
|
374
|
-
onComment: undefined
|
|
469
|
+
allowHashBang: true
|
|
375
470
|
};
|
|
376
471
|
|
|
377
472
|
const EMPTY_COMMENT_OPTIONS = {
|
|
@@ -379,16 +474,19 @@ const EMPTY_COMMENT_OPTIONS = {
|
|
|
379
474
|
errors: null
|
|
380
475
|
};
|
|
381
476
|
|
|
477
|
+
const CLASS_NAME = "JavascriptParser";
|
|
478
|
+
|
|
382
479
|
class JavascriptParser extends Parser {
|
|
383
480
|
/**
|
|
384
|
-
* @param {"module" | "script" | "auto"} sourceType default source type
|
|
481
|
+
* @param {"module" | "script" | "auto"=} sourceType default source type
|
|
482
|
+
* @param {{ parse?: ParseFunction }=} options parser options
|
|
385
483
|
*/
|
|
386
|
-
constructor(sourceType = "auto") {
|
|
484
|
+
constructor(sourceType = "auto", options = {}) {
|
|
387
485
|
super();
|
|
388
486
|
this.hooks = Object.freeze({
|
|
389
487
|
/** @type {HookMap<SyncBailHook<[UnaryExpression], BasicEvaluatedExpression | null | undefined>>} */
|
|
390
488
|
evaluateTypeof: new HookMap(() => new SyncBailHook(["expression"])),
|
|
391
|
-
/** @type {HookMap<SyncBailHook<[Expression | SpreadElement | PrivateIdentifier], BasicEvaluatedExpression | null | undefined>>} */
|
|
489
|
+
/** @type {HookMap<SyncBailHook<[Expression | SpreadElement | PrivateIdentifier | Super], BasicEvaluatedExpression | null | undefined>>} */
|
|
392
490
|
evaluate: new HookMap(() => new SyncBailHook(["expression"])),
|
|
393
491
|
/** @type {HookMap<SyncBailHook<[Identifier | ThisExpression | MemberExpression | MetaProperty], BasicEvaluatedExpression | null | undefined>>} */
|
|
394
492
|
evaluateIdentifier: new HookMap(() => new SyncBailHook(["expression"])),
|
|
@@ -408,27 +506,27 @@ class JavascriptParser extends Parser {
|
|
|
408
506
|
evaluateCallExpressionMember: new HookMap(
|
|
409
507
|
() => new SyncBailHook(["expression", "param"])
|
|
410
508
|
),
|
|
411
|
-
/** @type {HookMap<SyncBailHook<[Expression | Declaration | PrivateIdentifier, number], boolean | void>>} */
|
|
509
|
+
/** @type {HookMap<SyncBailHook<[Expression | Declaration | PrivateIdentifier | MaybeNamedFunctionDeclaration | MaybeNamedClassDeclaration, number], boolean | void>>} */
|
|
412
510
|
isPure: new HookMap(
|
|
413
511
|
() => new SyncBailHook(["expression", "commentsStartPosition"])
|
|
414
512
|
),
|
|
415
|
-
/** @type {SyncBailHook<[Statement | ModuleDeclaration], boolean | void>} */
|
|
513
|
+
/** @type {SyncBailHook<[Statement | ModuleDeclaration | MaybeNamedClassDeclaration | MaybeNamedFunctionDeclaration], boolean | void>} */
|
|
416
514
|
preStatement: new SyncBailHook(["statement"]),
|
|
417
515
|
|
|
418
|
-
/** @type {SyncBailHook<[Statement | ModuleDeclaration], boolean | void>} */
|
|
516
|
+
/** @type {SyncBailHook<[Statement | ModuleDeclaration | MaybeNamedClassDeclaration | MaybeNamedFunctionDeclaration], boolean | void>} */
|
|
419
517
|
blockPreStatement: new SyncBailHook(["declaration"]),
|
|
420
|
-
/** @type {SyncBailHook<[Statement | ModuleDeclaration], boolean | void>} */
|
|
518
|
+
/** @type {SyncBailHook<[Statement | ModuleDeclaration | MaybeNamedFunctionDeclaration | MaybeNamedClassDeclaration], boolean | void>} */
|
|
421
519
|
statement: new SyncBailHook(["statement"]),
|
|
422
520
|
/** @type {SyncBailHook<[IfStatement], boolean | void>} */
|
|
423
521
|
statementIf: new SyncBailHook(["statement"]),
|
|
424
|
-
/** @type {SyncBailHook<[Expression, ClassExpression | ClassDeclaration], boolean | void>} */
|
|
522
|
+
/** @type {SyncBailHook<[Expression, ClassExpression | ClassDeclaration | MaybeNamedClassDeclaration], boolean | void>} */
|
|
425
523
|
classExtendsExpression: new SyncBailHook([
|
|
426
524
|
"expression",
|
|
427
525
|
"classDefinition"
|
|
428
526
|
]),
|
|
429
|
-
/** @type {SyncBailHook<[MethodDefinition | PropertyDefinition | StaticBlock, ClassExpression | ClassDeclaration], boolean | void>} */
|
|
527
|
+
/** @type {SyncBailHook<[MethodDefinition | PropertyDefinition | StaticBlock, ClassExpression | ClassDeclaration | MaybeNamedClassDeclaration], boolean | void>} */
|
|
430
528
|
classBodyElement: new SyncBailHook(["element", "classDefinition"]),
|
|
431
|
-
/** @type {SyncBailHook<[Expression, MethodDefinition | PropertyDefinition, ClassExpression | ClassDeclaration], boolean | void>} */
|
|
529
|
+
/** @type {SyncBailHook<[Expression, MethodDefinition | PropertyDefinition, ClassExpression | ClassDeclaration | MaybeNamedClassDeclaration], boolean | void>} */
|
|
432
530
|
classBodyValue: new SyncBailHook([
|
|
433
531
|
"expression",
|
|
434
532
|
"element",
|
|
@@ -451,8 +549,8 @@ class JavascriptParser extends Parser {
|
|
|
451
549
|
exportImport: new SyncBailHook(["statement", "source"]),
|
|
452
550
|
/** @type {SyncBailHook<[ExportDefaultDeclaration | ExportNamedDeclaration | ExportAllDeclaration, Declaration], boolean | void>} */
|
|
453
551
|
exportDeclaration: new SyncBailHook(["statement", "declaration"]),
|
|
454
|
-
/** @type {SyncBailHook<[ExportDefaultDeclaration,
|
|
455
|
-
exportExpression: new SyncBailHook(["statement", "
|
|
552
|
+
/** @type {SyncBailHook<[ExportDefaultDeclaration, MaybeNamedFunctionDeclaration | MaybeNamedClassDeclaration | Expression], boolean | void>} */
|
|
553
|
+
exportExpression: new SyncBailHook(["statement", "node"]),
|
|
456
554
|
/** @type {SyncBailHook<[ExportDefaultDeclaration | ExportNamedDeclaration | ExportAllDeclaration, string, string, number | undefined], boolean | void>} */
|
|
457
555
|
exportSpecifier: new SyncBailHook([
|
|
458
556
|
"statement",
|
|
@@ -472,36 +570,42 @@ class JavascriptParser extends Parser {
|
|
|
472
570
|
preDeclarator: new SyncBailHook(["declarator", "statement"]),
|
|
473
571
|
/** @type {SyncBailHook<[VariableDeclarator, Statement], boolean | void>} */
|
|
474
572
|
declarator: new SyncBailHook(["declarator", "statement"]),
|
|
475
|
-
/** @type {HookMap<SyncBailHook<[
|
|
573
|
+
/** @type {HookMap<SyncBailHook<[Identifier], boolean | void>>} */
|
|
476
574
|
varDeclaration: new HookMap(() => new SyncBailHook(["declaration"])),
|
|
477
|
-
/** @type {HookMap<SyncBailHook<[
|
|
575
|
+
/** @type {HookMap<SyncBailHook<[Identifier], boolean | void>>} */
|
|
478
576
|
varDeclarationLet: new HookMap(() => new SyncBailHook(["declaration"])),
|
|
479
|
-
/** @type {HookMap<SyncBailHook<[
|
|
577
|
+
/** @type {HookMap<SyncBailHook<[Identifier], boolean | void>>} */
|
|
480
578
|
varDeclarationConst: new HookMap(() => new SyncBailHook(["declaration"])),
|
|
481
|
-
/** @type {HookMap<SyncBailHook<[
|
|
579
|
+
/** @type {HookMap<SyncBailHook<[Identifier], boolean | void>>} */
|
|
580
|
+
varDeclarationUsing: new HookMap(() => new SyncBailHook(["declaration"])),
|
|
581
|
+
/** @type {HookMap<SyncBailHook<[Identifier], boolean | void>>} */
|
|
482
582
|
varDeclarationVar: new HookMap(() => new SyncBailHook(["declaration"])),
|
|
483
583
|
/** @type {HookMap<SyncBailHook<[Identifier], boolean | void>>} */
|
|
484
584
|
pattern: new HookMap(() => new SyncBailHook(["pattern"])),
|
|
585
|
+
/** @type {SyncBailHook<[Expression], boolean | void>} */
|
|
586
|
+
collectDestructuringAssignmentProperties: new SyncBailHook([
|
|
587
|
+
"expression"
|
|
588
|
+
]),
|
|
485
589
|
/** @type {HookMap<SyncBailHook<[Expression], boolean | void>>} */
|
|
486
590
|
canRename: new HookMap(() => new SyncBailHook(["initExpression"])),
|
|
487
591
|
/** @type {HookMap<SyncBailHook<[Expression], boolean | void>>} */
|
|
488
592
|
rename: new HookMap(() => new SyncBailHook(["initExpression"])),
|
|
489
593
|
/** @type {HookMap<SyncBailHook<[AssignmentExpression], boolean | void>>} */
|
|
490
594
|
assign: new HookMap(() => new SyncBailHook(["expression"])),
|
|
491
|
-
/** @type {HookMap<SyncBailHook<[AssignmentExpression,
|
|
595
|
+
/** @type {HookMap<SyncBailHook<[AssignmentExpression, Members], boolean | void>>} */
|
|
492
596
|
assignMemberChain: new HookMap(
|
|
493
597
|
() => new SyncBailHook(["expression", "members"])
|
|
494
598
|
),
|
|
495
599
|
/** @type {HookMap<SyncBailHook<[Expression], boolean | void>>} */
|
|
496
600
|
typeof: new HookMap(() => new SyncBailHook(["expression"])),
|
|
497
|
-
/** @type {SyncBailHook<[ImportExpression], boolean | void>} */
|
|
498
|
-
importCall: new SyncBailHook(["expression"]),
|
|
601
|
+
/** @type {SyncBailHook<[ImportExpression, CallExpression?], boolean | void>} */
|
|
602
|
+
importCall: new SyncBailHook(["expression", "importThen"]),
|
|
499
603
|
/** @type {SyncBailHook<[Expression | ForOfStatement], boolean | void>} */
|
|
500
604
|
topLevelAwait: new SyncBailHook(["expression"]),
|
|
501
605
|
/** @type {HookMap<SyncBailHook<[CallExpression], boolean | void>>} */
|
|
502
606
|
call: new HookMap(() => new SyncBailHook(["expression"])),
|
|
503
607
|
/** Something like "a.b()" */
|
|
504
|
-
/** @type {HookMap<SyncBailHook<[CallExpression,
|
|
608
|
+
/** @type {HookMap<SyncBailHook<[CallExpression, Members, MembersOptionals, MemberRanges], boolean | void>>} */
|
|
505
609
|
callMemberChain: new HookMap(
|
|
506
610
|
() =>
|
|
507
611
|
new SyncBailHook([
|
|
@@ -512,7 +616,7 @@ class JavascriptParser extends Parser {
|
|
|
512
616
|
])
|
|
513
617
|
),
|
|
514
618
|
/** Something like "a.b().c.d" */
|
|
515
|
-
/** @type {HookMap<SyncBailHook<[Expression,
|
|
619
|
+
/** @type {HookMap<SyncBailHook<[Expression, CalleeMembers, CallExpression, Members, MemberRanges], boolean | void>>} */
|
|
516
620
|
memberChainOfCallMemberChain: new HookMap(
|
|
517
621
|
() =>
|
|
518
622
|
new SyncBailHook([
|
|
@@ -524,7 +628,7 @@ class JavascriptParser extends Parser {
|
|
|
524
628
|
])
|
|
525
629
|
),
|
|
526
630
|
/** Something like "a.b().c.d()"" */
|
|
527
|
-
/** @type {HookMap<SyncBailHook<[CallExpression,
|
|
631
|
+
/** @type {HookMap<SyncBailHook<[CallExpression, CalleeMembers, CallExpression, Members, MemberRanges], boolean | void>>} */
|
|
528
632
|
callMemberChainOfCallMemberChain: new HookMap(
|
|
529
633
|
() =>
|
|
530
634
|
new SyncBailHook([
|
|
@@ -543,7 +647,7 @@ class JavascriptParser extends Parser {
|
|
|
543
647
|
binaryExpression: new SyncBailHook(["binaryExpression"]),
|
|
544
648
|
/** @type {HookMap<SyncBailHook<[Expression], boolean | void>>} */
|
|
545
649
|
expression: new HookMap(() => new SyncBailHook(["expression"])),
|
|
546
|
-
/** @type {HookMap<SyncBailHook<[MemberExpression,
|
|
650
|
+
/** @type {HookMap<SyncBailHook<[MemberExpression, Members, MembersOptionals, MemberRanges], boolean | void>>} */
|
|
547
651
|
expressionMemberChain: new HookMap(
|
|
548
652
|
() =>
|
|
549
653
|
new SyncBailHook([
|
|
@@ -553,7 +657,7 @@ class JavascriptParser extends Parser {
|
|
|
553
657
|
"memberRanges"
|
|
554
658
|
])
|
|
555
659
|
),
|
|
556
|
-
/** @type {HookMap<SyncBailHook<[MemberExpression,
|
|
660
|
+
/** @type {HookMap<SyncBailHook<[MemberExpression, Members], boolean | void>>} */
|
|
557
661
|
unhandledExpressionMemberChain: new HookMap(
|
|
558
662
|
() => new SyncBailHook(["expression", "members"])
|
|
559
663
|
),
|
|
@@ -563,31 +667,38 @@ class JavascriptParser extends Parser {
|
|
|
563
667
|
expressionLogicalOperator: new SyncBailHook(["expression"]),
|
|
564
668
|
/** @type {SyncBailHook<[Program, Comment[]], boolean | void>} */
|
|
565
669
|
program: new SyncBailHook(["ast", "comments"]),
|
|
670
|
+
/** @type {SyncBailHook<[ThrowStatement | ReturnStatement], boolean | void>} */
|
|
671
|
+
terminate: new SyncBailHook(["statement"]),
|
|
566
672
|
/** @type {SyncBailHook<[Program, Comment[]], boolean | void>} */
|
|
567
|
-
finish: new SyncBailHook(["ast", "comments"])
|
|
673
|
+
finish: new SyncBailHook(["ast", "comments"]),
|
|
674
|
+
/** @type {SyncBailHook<[Statement], boolean | void>} */
|
|
675
|
+
unusedStatement: new SyncBailHook(["statement"])
|
|
568
676
|
});
|
|
569
677
|
this.sourceType = sourceType;
|
|
678
|
+
this.options = options;
|
|
679
|
+
|
|
570
680
|
/** @type {ScopeInfo} */
|
|
571
|
-
this.scope = undefined;
|
|
572
|
-
/** @type {
|
|
573
|
-
this.state = undefined;
|
|
681
|
+
this.scope = /** @type {EXPECTED_ANY} */ (undefined);
|
|
682
|
+
/** @type {JavascriptParserState} */
|
|
683
|
+
this.state = /** @type {EXPECTED_ANY} */ (undefined);
|
|
574
684
|
/** @type {Comment[] | undefined} */
|
|
575
685
|
this.comments = undefined;
|
|
576
686
|
/** @type {Set<number> | undefined} */
|
|
577
687
|
this.semicolons = undefined;
|
|
578
688
|
/** @type {StatementPath | undefined} */
|
|
579
689
|
this.statementPath = undefined;
|
|
580
|
-
/** @type {Statement | ModuleDeclaration | Expression | undefined} */
|
|
690
|
+
/** @type {Statement | ModuleDeclaration | Expression | MaybeNamedFunctionDeclaration | MaybeNamedClassDeclaration | undefined} */
|
|
581
691
|
this.prevStatement = undefined;
|
|
582
|
-
/** @type {WeakMap<Expression,
|
|
692
|
+
/** @type {WeakMap<Expression, DestructuringAssignmentProperties> | undefined} */
|
|
583
693
|
this.destructuringAssignmentProperties = undefined;
|
|
694
|
+
/** @type {TagData | undefined} */
|
|
584
695
|
this.currentTagData = undefined;
|
|
585
696
|
this.magicCommentContext = createMagicCommentContext();
|
|
586
697
|
this._initializeEvaluating();
|
|
587
698
|
}
|
|
588
699
|
|
|
589
700
|
_initializeEvaluating() {
|
|
590
|
-
this.hooks.evaluate.for("Literal").tap(
|
|
701
|
+
this.hooks.evaluate.for("Literal").tap(CLASS_NAME, (_expr) => {
|
|
591
702
|
const expr = /** @type {Literal} */ (_expr);
|
|
592
703
|
|
|
593
704
|
switch (typeof expr.value) {
|
|
@@ -619,7 +730,7 @@ class JavascriptParser extends Parser {
|
|
|
619
730
|
.setRange(/** @type {Range} */ (expr.range));
|
|
620
731
|
}
|
|
621
732
|
});
|
|
622
|
-
this.hooks.evaluate.for("NewExpression").tap(
|
|
733
|
+
this.hooks.evaluate.for("NewExpression").tap(CLASS_NAME, (_expr) => {
|
|
623
734
|
const expr = /** @type {NewExpression} */ (_expr);
|
|
624
735
|
const callee = expr.callee;
|
|
625
736
|
if (callee.type !== "Identifier") return;
|
|
@@ -632,8 +743,9 @@ class JavascriptParser extends Parser {
|
|
|
632
743
|
} else if (
|
|
633
744
|
expr.arguments.length > 2 ||
|
|
634
745
|
this.getVariableInfo("RegExp") !== "RegExp"
|
|
635
|
-
)
|
|
746
|
+
) {
|
|
636
747
|
return;
|
|
748
|
+
}
|
|
637
749
|
|
|
638
750
|
let regExp;
|
|
639
751
|
const arg1 = expr.arguments[0];
|
|
@@ -673,8 +785,9 @@ class JavascriptParser extends Parser {
|
|
|
673
785
|
if (
|
|
674
786
|
flags === undefined ||
|
|
675
787
|
!BasicEvaluatedExpression.isValidRegExpFlags(flags)
|
|
676
|
-
)
|
|
788
|
+
) {
|
|
677
789
|
return;
|
|
790
|
+
}
|
|
678
791
|
}
|
|
679
792
|
}
|
|
680
793
|
|
|
@@ -682,52 +795,55 @@ class JavascriptParser extends Parser {
|
|
|
682
795
|
.setRegExp(flags ? new RegExp(regExp, flags) : new RegExp(regExp))
|
|
683
796
|
.setRange(/** @type {Range} */ (expr.range));
|
|
684
797
|
});
|
|
685
|
-
this.hooks.evaluate
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
if (
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
if (leftAsNullish !== true) return;
|
|
711
|
-
returnRight = true;
|
|
712
|
-
} else return;
|
|
713
|
-
const right = this.evaluateExpression(expr.right);
|
|
714
|
-
if (returnRight) {
|
|
715
|
-
if (left.couldHaveSideEffects()) right.setSideEffects();
|
|
716
|
-
return right.setRange(/** @type {Range} */ (expr.range));
|
|
798
|
+
this.hooks.evaluate.for("LogicalExpression").tap(CLASS_NAME, (_expr) => {
|
|
799
|
+
const expr = /** @type {LogicalExpression} */ (_expr);
|
|
800
|
+
|
|
801
|
+
const left = this.evaluateExpression(expr.left);
|
|
802
|
+
let returnRight = false;
|
|
803
|
+
/** @type {boolean | undefined} */
|
|
804
|
+
let allowedRight;
|
|
805
|
+
if (expr.operator === "&&") {
|
|
806
|
+
const leftAsBool = left.asBool();
|
|
807
|
+
if (leftAsBool === false) {
|
|
808
|
+
return left.setRange(/** @type {Range} */ (expr.range));
|
|
809
|
+
}
|
|
810
|
+
returnRight = leftAsBool === true;
|
|
811
|
+
allowedRight = false;
|
|
812
|
+
} else if (expr.operator === "||") {
|
|
813
|
+
const leftAsBool = left.asBool();
|
|
814
|
+
if (leftAsBool === true) {
|
|
815
|
+
return left.setRange(/** @type {Range} */ (expr.range));
|
|
816
|
+
}
|
|
817
|
+
returnRight = leftAsBool === false;
|
|
818
|
+
allowedRight = true;
|
|
819
|
+
} else if (expr.operator === "??") {
|
|
820
|
+
const leftAsNullish = left.asNullish();
|
|
821
|
+
if (leftAsNullish === false) {
|
|
822
|
+
return left.setRange(/** @type {Range} */ (expr.range));
|
|
717
823
|
}
|
|
824
|
+
if (leftAsNullish !== true) return;
|
|
825
|
+
returnRight = true;
|
|
826
|
+
} else {
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
const right = this.evaluateExpression(expr.right);
|
|
830
|
+
if (returnRight) {
|
|
831
|
+
if (left.couldHaveSideEffects()) right.setSideEffects();
|
|
832
|
+
return right.setRange(/** @type {Range} */ (expr.range));
|
|
833
|
+
}
|
|
718
834
|
|
|
719
|
-
|
|
835
|
+
const asBool = right.asBool();
|
|
720
836
|
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
837
|
+
if (allowedRight === true && asBool === true) {
|
|
838
|
+
return new BasicEvaluatedExpression()
|
|
839
|
+
.setRange(/** @type {Range} */ (expr.range))
|
|
840
|
+
.setTruthy();
|
|
841
|
+
} else if (allowedRight === false && asBool === false) {
|
|
842
|
+
return new BasicEvaluatedExpression()
|
|
843
|
+
.setRange(/** @type {Range} */ (expr.range))
|
|
844
|
+
.setFalsy();
|
|
845
|
+
}
|
|
846
|
+
});
|
|
731
847
|
|
|
732
848
|
/**
|
|
733
849
|
* In simple logical cases, we can use valueAsExpression to assist us in evaluating the expression on
|
|
@@ -797,550 +913,541 @@ class JavascriptParser extends Parser {
|
|
|
797
913
|
}
|
|
798
914
|
};
|
|
799
915
|
|
|
800
|
-
this.hooks.evaluate
|
|
801
|
-
|
|
802
|
-
.tap("JavascriptParser", _expr => {
|
|
803
|
-
const expr = /** @type {BinaryExpression} */ (_expr);
|
|
804
|
-
|
|
805
|
-
/**
|
|
806
|
-
* Evaluates a binary expression if and only if it is a const operation (e.g. 1 + 2, "a" + "b", etc.).
|
|
807
|
-
* @template T
|
|
808
|
-
* @param {(leftOperand: T, rightOperand: T) => boolean | number | bigint | string} operandHandler the handler for the operation (e.g. (a, b) => a + b)
|
|
809
|
-
* @returns {BasicEvaluatedExpression | undefined} the evaluated expression
|
|
810
|
-
*/
|
|
811
|
-
const handleConstOperation = operandHandler => {
|
|
812
|
-
const left = this.evaluateExpression(expr.left);
|
|
813
|
-
if (!left.isCompileTimeValue()) return;
|
|
916
|
+
this.hooks.evaluate.for("BinaryExpression").tap(CLASS_NAME, (_expr) => {
|
|
917
|
+
const expr = /** @type {BinaryExpression} */ (_expr);
|
|
814
918
|
|
|
815
|
-
|
|
816
|
-
|
|
919
|
+
/**
|
|
920
|
+
* Evaluates a binary expression if and only if it is a const operation (e.g. 1 + 2, "a" + "b", etc.).
|
|
921
|
+
* @template T
|
|
922
|
+
* @param {(leftOperand: T, rightOperand: T) => boolean | number | bigint | string} operandHandler the handler for the operation (e.g. (a, b) => a + b)
|
|
923
|
+
* @returns {BasicEvaluatedExpression | undefined} the evaluated expression
|
|
924
|
+
*/
|
|
925
|
+
const handleConstOperation = (operandHandler) => {
|
|
926
|
+
const left = this.evaluateExpression(expr.left);
|
|
927
|
+
if (!left.isCompileTimeValue()) return;
|
|
817
928
|
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
right.asCompileTimeValue()
|
|
821
|
-
);
|
|
822
|
-
return valueAsExpression(
|
|
823
|
-
result,
|
|
824
|
-
expr,
|
|
825
|
-
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
|
826
|
-
);
|
|
827
|
-
};
|
|
929
|
+
const right = this.evaluateExpression(expr.right);
|
|
930
|
+
if (!right.isCompileTimeValue()) return;
|
|
828
931
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
932
|
+
const result = operandHandler(
|
|
933
|
+
/** @type {T} */ (left.asCompileTimeValue()),
|
|
934
|
+
/** @type {T} */ (right.asCompileTimeValue())
|
|
935
|
+
);
|
|
936
|
+
return valueAsExpression(
|
|
937
|
+
result,
|
|
938
|
+
expr,
|
|
939
|
+
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
|
940
|
+
);
|
|
941
|
+
};
|
|
838
942
|
|
|
943
|
+
/**
|
|
944
|
+
* Helper function to determine if two booleans are always different. This is used in `handleStrictEqualityComparison`
|
|
945
|
+
* to determine if an expressions boolean or nullish conversion is equal or not.
|
|
946
|
+
* @param {boolean} a first boolean to compare
|
|
947
|
+
* @param {boolean} b second boolean to compare
|
|
948
|
+
* @returns {boolean} true if the two booleans are always different, false otherwise
|
|
949
|
+
*/
|
|
950
|
+
const isAlwaysDifferent = (a, b) =>
|
|
951
|
+
(a === true && b === false) || (a === false && b === true);
|
|
952
|
+
|
|
953
|
+
/**
|
|
954
|
+
* @param {BasicEvaluatedExpression} left left
|
|
955
|
+
* @param {BasicEvaluatedExpression} right right
|
|
956
|
+
* @param {BasicEvaluatedExpression} res res
|
|
957
|
+
* @param {boolean} eql true for "===" and false for "!=="
|
|
958
|
+
* @returns {BasicEvaluatedExpression | undefined} result
|
|
959
|
+
*/
|
|
960
|
+
const handleTemplateStringCompare = (left, right, res, eql) => {
|
|
839
961
|
/**
|
|
840
|
-
* @param {BasicEvaluatedExpression}
|
|
841
|
-
* @
|
|
842
|
-
* @param {BasicEvaluatedExpression} res res
|
|
843
|
-
* @param {boolean} eql true for "===" and false for "!=="
|
|
844
|
-
* @returns {BasicEvaluatedExpression | undefined} result
|
|
962
|
+
* @param {BasicEvaluatedExpression[]} parts parts
|
|
963
|
+
* @returns {string} value
|
|
845
964
|
*/
|
|
846
|
-
const
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
let value = "";
|
|
853
|
-
for (const p of parts) {
|
|
854
|
-
const v = p.asString();
|
|
855
|
-
if (v !== undefined) value += v;
|
|
856
|
-
else break;
|
|
857
|
-
}
|
|
858
|
-
return value;
|
|
859
|
-
};
|
|
860
|
-
/**
|
|
861
|
-
* @param {BasicEvaluatedExpression[]} parts parts
|
|
862
|
-
* @returns {string} value
|
|
863
|
-
*/
|
|
864
|
-
const getSuffix = parts => {
|
|
865
|
-
let value = "";
|
|
866
|
-
for (let i = parts.length - 1; i >= 0; i--) {
|
|
867
|
-
const v = parts[i].asString();
|
|
868
|
-
if (v !== undefined) value = v + value;
|
|
869
|
-
else break;
|
|
870
|
-
}
|
|
871
|
-
return value;
|
|
872
|
-
};
|
|
873
|
-
const leftPrefix = getPrefix(
|
|
874
|
-
/** @type {BasicEvaluatedExpression[]} */ (left.parts)
|
|
875
|
-
);
|
|
876
|
-
const rightPrefix = getPrefix(
|
|
877
|
-
/** @type {BasicEvaluatedExpression[]} */ (right.parts)
|
|
878
|
-
);
|
|
879
|
-
const leftSuffix = getSuffix(
|
|
880
|
-
/** @type {BasicEvaluatedExpression[]} */ (left.parts)
|
|
881
|
-
);
|
|
882
|
-
const rightSuffix = getSuffix(
|
|
883
|
-
/** @type {BasicEvaluatedExpression[]} */ (right.parts)
|
|
884
|
-
);
|
|
885
|
-
const lenPrefix = Math.min(leftPrefix.length, rightPrefix.length);
|
|
886
|
-
const lenSuffix = Math.min(leftSuffix.length, rightSuffix.length);
|
|
887
|
-
const prefixMismatch =
|
|
888
|
-
lenPrefix > 0 &&
|
|
889
|
-
leftPrefix.slice(0, lenPrefix) !== rightPrefix.slice(0, lenPrefix);
|
|
890
|
-
const suffixMismatch =
|
|
891
|
-
lenSuffix > 0 &&
|
|
892
|
-
leftSuffix.slice(-lenSuffix) !== rightSuffix.slice(-lenSuffix);
|
|
893
|
-
if (prefixMismatch || suffixMismatch) {
|
|
894
|
-
return res
|
|
895
|
-
.setBoolean(!eql)
|
|
896
|
-
.setSideEffects(
|
|
897
|
-
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
|
898
|
-
);
|
|
965
|
+
const getPrefix = (parts) => {
|
|
966
|
+
let value = "";
|
|
967
|
+
for (const p of parts) {
|
|
968
|
+
const v = p.asString();
|
|
969
|
+
if (v !== undefined) value += v;
|
|
970
|
+
else break;
|
|
899
971
|
}
|
|
972
|
+
return value;
|
|
900
973
|
};
|
|
901
|
-
|
|
902
974
|
/**
|
|
903
|
-
*
|
|
904
|
-
* @
|
|
905
|
-
* @returns {BasicEvaluatedExpression | undefined} the evaluated expression
|
|
975
|
+
* @param {BasicEvaluatedExpression[]} parts parts
|
|
976
|
+
* @returns {string} value
|
|
906
977
|
*/
|
|
907
|
-
const
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
const leftConst = left.isCompileTimeValue();
|
|
914
|
-
const rightConst = right.isCompileTimeValue();
|
|
915
|
-
|
|
916
|
-
if (leftConst && rightConst) {
|
|
917
|
-
return res
|
|
918
|
-
.setBoolean(
|
|
919
|
-
eql ===
|
|
920
|
-
(left.asCompileTimeValue() === right.asCompileTimeValue())
|
|
921
|
-
)
|
|
922
|
-
.setSideEffects(
|
|
923
|
-
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
|
924
|
-
);
|
|
978
|
+
const getSuffix = (parts) => {
|
|
979
|
+
let value = "";
|
|
980
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
|
981
|
+
const v = parts[i].asString();
|
|
982
|
+
if (v !== undefined) value = v + value;
|
|
983
|
+
else break;
|
|
925
984
|
}
|
|
985
|
+
return value;
|
|
986
|
+
};
|
|
987
|
+
const leftPrefix = getPrefix(
|
|
988
|
+
/** @type {BasicEvaluatedExpression[]} */ (left.parts)
|
|
989
|
+
);
|
|
990
|
+
const rightPrefix = getPrefix(
|
|
991
|
+
/** @type {BasicEvaluatedExpression[]} */ (right.parts)
|
|
992
|
+
);
|
|
993
|
+
const leftSuffix = getSuffix(
|
|
994
|
+
/** @type {BasicEvaluatedExpression[]} */ (left.parts)
|
|
995
|
+
);
|
|
996
|
+
const rightSuffix = getSuffix(
|
|
997
|
+
/** @type {BasicEvaluatedExpression[]} */ (right.parts)
|
|
998
|
+
);
|
|
999
|
+
const lenPrefix = Math.min(leftPrefix.length, rightPrefix.length);
|
|
1000
|
+
const lenSuffix = Math.min(leftSuffix.length, rightSuffix.length);
|
|
1001
|
+
const prefixMismatch =
|
|
1002
|
+
lenPrefix > 0 &&
|
|
1003
|
+
leftPrefix.slice(0, lenPrefix) !== rightPrefix.slice(0, lenPrefix);
|
|
1004
|
+
const suffixMismatch =
|
|
1005
|
+
lenSuffix > 0 &&
|
|
1006
|
+
leftSuffix.slice(-lenSuffix) !== rightSuffix.slice(-lenSuffix);
|
|
1007
|
+
if (prefixMismatch || suffixMismatch) {
|
|
1008
|
+
return res
|
|
1009
|
+
.setBoolean(!eql)
|
|
1010
|
+
.setSideEffects(
|
|
1011
|
+
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
|
1012
|
+
);
|
|
1013
|
+
}
|
|
1014
|
+
};
|
|
926
1015
|
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
1016
|
+
/**
|
|
1017
|
+
* Helper function to handle BinaryExpressions using strict equality comparisons (e.g. "===" and "!==").
|
|
1018
|
+
* @param {boolean} eql true for "===" and false for "!=="
|
|
1019
|
+
* @returns {BasicEvaluatedExpression | undefined} the evaluated expression
|
|
1020
|
+
*/
|
|
1021
|
+
const handleStrictEqualityComparison = (eql) => {
|
|
1022
|
+
const left = this.evaluateExpression(expr.left);
|
|
1023
|
+
const right = this.evaluateExpression(expr.right);
|
|
1024
|
+
const res = new BasicEvaluatedExpression();
|
|
1025
|
+
res.setRange(/** @type {Range} */ (expr.range));
|
|
937
1026
|
|
|
938
|
-
|
|
939
|
-
|
|
1027
|
+
const leftConst = left.isCompileTimeValue();
|
|
1028
|
+
const rightConst = right.isCompileTimeValue();
|
|
940
1029
|
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
(leftConst || rightPrimitive === true)) ||
|
|
946
|
-
(rightPrimitive === false &&
|
|
947
|
-
(rightConst || leftPrimitive === true)) ||
|
|
948
|
-
// Different nullish or boolish status also means not equal
|
|
949
|
-
isAlwaysDifferent(
|
|
950
|
-
/** @type {boolean} */ (left.asBool()),
|
|
951
|
-
/** @type {boolean} */ (right.asBool())
|
|
952
|
-
) ||
|
|
953
|
-
isAlwaysDifferent(
|
|
954
|
-
/** @type {boolean} */ (left.asNullish()),
|
|
955
|
-
/** @type {boolean} */ (right.asNullish())
|
|
1030
|
+
if (leftConst && rightConst) {
|
|
1031
|
+
return res
|
|
1032
|
+
.setBoolean(
|
|
1033
|
+
eql === (left.asCompileTimeValue() === right.asCompileTimeValue())
|
|
956
1034
|
)
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
|
962
|
-
);
|
|
963
|
-
}
|
|
964
|
-
};
|
|
1035
|
+
.setSideEffects(
|
|
1036
|
+
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
965
1039
|
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
const leftConst = left.isCompileTimeValue();
|
|
978
|
-
const rightConst = right.isCompileTimeValue();
|
|
979
|
-
|
|
980
|
-
if (leftConst && rightConst) {
|
|
981
|
-
return res
|
|
982
|
-
.setBoolean(
|
|
983
|
-
eql ===
|
|
984
|
-
// eslint-disable-next-line eqeqeq
|
|
985
|
-
(left.asCompileTimeValue() == right.asCompileTimeValue())
|
|
986
|
-
)
|
|
987
|
-
.setSideEffects(
|
|
988
|
-
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
|
989
|
-
);
|
|
990
|
-
}
|
|
1040
|
+
if (left.isArray() && right.isArray()) {
|
|
1041
|
+
return res
|
|
1042
|
+
.setBoolean(!eql)
|
|
1043
|
+
.setSideEffects(
|
|
1044
|
+
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
|
1045
|
+
);
|
|
1046
|
+
}
|
|
1047
|
+
if (left.isTemplateString() && right.isTemplateString()) {
|
|
1048
|
+
return handleTemplateStringCompare(left, right, res, eql);
|
|
1049
|
+
}
|
|
991
1050
|
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
.setBoolean(!eql)
|
|
995
|
-
.setSideEffects(
|
|
996
|
-
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
|
997
|
-
);
|
|
998
|
-
}
|
|
999
|
-
if (left.isTemplateString() && right.isTemplateString()) {
|
|
1000
|
-
return handleTemplateStringCompare(left, right, res, eql);
|
|
1001
|
-
}
|
|
1002
|
-
};
|
|
1051
|
+
const leftPrimitive = left.isPrimitiveType();
|
|
1052
|
+
const rightPrimitive = right.isPrimitiveType();
|
|
1003
1053
|
|
|
1004
|
-
if (
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
)
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1054
|
+
if (
|
|
1055
|
+
// Primitive !== Object or
|
|
1056
|
+
// compile-time object types are never equal to something at runtime
|
|
1057
|
+
(leftPrimitive === false && (leftConst || rightPrimitive === true)) ||
|
|
1058
|
+
(rightPrimitive === false &&
|
|
1059
|
+
(rightConst || leftPrimitive === true)) ||
|
|
1060
|
+
// Different nullish or boolish status also means not equal
|
|
1061
|
+
isAlwaysDifferent(
|
|
1062
|
+
/** @type {boolean} */ (left.asBool()),
|
|
1063
|
+
/** @type {boolean} */ (right.asBool())
|
|
1064
|
+
) ||
|
|
1065
|
+
isAlwaysDifferent(
|
|
1066
|
+
/** @type {boolean} */ (left.asNullish()),
|
|
1067
|
+
/** @type {boolean} */ (right.asNullish())
|
|
1068
|
+
)
|
|
1069
|
+
) {
|
|
1070
|
+
return res
|
|
1071
|
+
.setBoolean(!eql)
|
|
1072
|
+
.setSideEffects(
|
|
1073
|
+
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
|
1074
|
+
);
|
|
1075
|
+
}
|
|
1076
|
+
};
|
|
1077
|
+
|
|
1078
|
+
/**
|
|
1079
|
+
* Helper function to handle BinaryExpressions using abstract equality comparisons (e.g. "==" and "!=").
|
|
1080
|
+
* @param {boolean} eql true for "==" and false for "!="
|
|
1081
|
+
* @returns {BasicEvaluatedExpression | undefined} the evaluated expression
|
|
1082
|
+
*/
|
|
1083
|
+
const handleAbstractEqualityComparison = (eql) => {
|
|
1084
|
+
const left = this.evaluateExpression(expr.left);
|
|
1085
|
+
const right = this.evaluateExpression(expr.right);
|
|
1086
|
+
const res = new BasicEvaluatedExpression();
|
|
1087
|
+
res.setRange(/** @type {Range} */ (expr.range));
|
|
1088
|
+
|
|
1089
|
+
const leftConst = left.isCompileTimeValue();
|
|
1090
|
+
const rightConst = right.isCompileTimeValue();
|
|
1091
|
+
|
|
1092
|
+
if (leftConst && rightConst) {
|
|
1093
|
+
return res
|
|
1094
|
+
.setBoolean(
|
|
1095
|
+
eql ===
|
|
1096
|
+
// eslint-disable-next-line eqeqeq
|
|
1097
|
+
(left.asCompileTimeValue() == right.asCompileTimeValue())
|
|
1098
|
+
)
|
|
1099
|
+
.setSideEffects(
|
|
1100
|
+
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
|
1101
|
+
);
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
if (left.isArray() && right.isArray()) {
|
|
1105
|
+
return res
|
|
1106
|
+
.setBoolean(!eql)
|
|
1107
|
+
.setSideEffects(
|
|
1108
|
+
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
|
1109
|
+
);
|
|
1110
|
+
}
|
|
1111
|
+
if (left.isTemplateString() && right.isTemplateString()) {
|
|
1112
|
+
return handleTemplateStringCompare(left, right, res, eql);
|
|
1113
|
+
}
|
|
1114
|
+
};
|
|
1115
|
+
|
|
1116
|
+
if (expr.operator === "+") {
|
|
1117
|
+
const left = this.evaluateExpression(expr.left);
|
|
1118
|
+
const right = this.evaluateExpression(expr.right);
|
|
1119
|
+
const res = new BasicEvaluatedExpression();
|
|
1120
|
+
if (left.isString()) {
|
|
1121
|
+
if (right.isString()) {
|
|
1122
|
+
res.setString(
|
|
1123
|
+
/** @type {string} */ (left.string) +
|
|
1124
|
+
/** @type {string} */ (right.string)
|
|
1125
|
+
);
|
|
1126
|
+
} else if (right.isNumber()) {
|
|
1127
|
+
res.setString(/** @type {string} */ (left.string) + right.number);
|
|
1128
|
+
} else if (
|
|
1129
|
+
right.isWrapped() &&
|
|
1130
|
+
right.prefix &&
|
|
1131
|
+
right.prefix.isString()
|
|
1132
|
+
) {
|
|
1133
|
+
// "left" + ("prefix" + inner + "postfix")
|
|
1134
|
+
// => ("leftPrefix" + inner + "postfix")
|
|
1135
|
+
res.setWrapped(
|
|
1136
|
+
new BasicEvaluatedExpression()
|
|
1137
|
+
.setString(
|
|
1138
|
+
/** @type {string} */ (left.string) +
|
|
1139
|
+
/** @type {string} */ (right.prefix.string)
|
|
1140
|
+
)
|
|
1141
|
+
.setRange(
|
|
1142
|
+
joinRanges(
|
|
1143
|
+
/** @type {Range} */ (left.range),
|
|
1144
|
+
/** @type {Range} */ (right.prefix.range)
|
|
1079
1145
|
)
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1146
|
+
),
|
|
1147
|
+
right.postfix,
|
|
1148
|
+
right.wrappedInnerExpressions
|
|
1149
|
+
);
|
|
1150
|
+
} else if (right.isWrapped()) {
|
|
1151
|
+
// "left" + ([null] + inner + "postfix")
|
|
1152
|
+
// => ("left" + inner + "postfix")
|
|
1153
|
+
res.setWrapped(left, right.postfix, right.wrappedInnerExpressions);
|
|
1154
|
+
} else {
|
|
1155
|
+
// "left" + expr
|
|
1156
|
+
// => ("left" + expr + "")
|
|
1157
|
+
res.setWrapped(left, null, [right]);
|
|
1158
|
+
}
|
|
1159
|
+
} else if (left.isNumber()) {
|
|
1160
|
+
if (right.isString()) {
|
|
1161
|
+
res.setString(left.number + /** @type {string} */ (right.string));
|
|
1162
|
+
} else if (right.isNumber()) {
|
|
1163
|
+
res.setNumber(
|
|
1164
|
+
/** @type {number} */ (left.number) +
|
|
1165
|
+
/** @type {number} */ (right.number)
|
|
1166
|
+
);
|
|
1167
|
+
} else {
|
|
1168
|
+
return;
|
|
1169
|
+
}
|
|
1170
|
+
} else if (left.isBigInt()) {
|
|
1171
|
+
if (right.isBigInt()) {
|
|
1172
|
+
res.setBigInt(
|
|
1173
|
+
/** @type {bigint} */ (left.bigint) +
|
|
1174
|
+
/** @type {bigint} */ (right.bigint)
|
|
1175
|
+
);
|
|
1176
|
+
}
|
|
1177
|
+
} else if (left.isWrapped()) {
|
|
1178
|
+
if (left.postfix && left.postfix.isString() && right.isString()) {
|
|
1179
|
+
// ("prefix" + inner + "postfix") + "right"
|
|
1180
|
+
// => ("prefix" + inner + "postfixRight")
|
|
1181
|
+
res.setWrapped(
|
|
1182
|
+
left.prefix,
|
|
1183
|
+
new BasicEvaluatedExpression()
|
|
1184
|
+
.setString(
|
|
1185
|
+
/** @type {string} */ (left.postfix.string) +
|
|
1186
|
+
/** @type {string} */ (right.string)
|
|
1187
|
+
)
|
|
1188
|
+
.setRange(
|
|
1189
|
+
joinRanges(
|
|
1190
|
+
/** @type {Range} */ (left.postfix.range),
|
|
1191
|
+
/** @type {Range} */ (right.range)
|
|
1101
1192
|
)
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
);
|
|
1124
|
-
} else if (right.isWrapped()) {
|
|
1125
|
-
// ("prefix1" + inner1 + "postfix1") + ("prefix2" + inner2 + "postfix2")
|
|
1126
|
-
// ("prefix1" + inner1 + "postfix1" + "prefix2" + inner2 + "postfix2")
|
|
1127
|
-
res.setWrapped(
|
|
1128
|
-
left.prefix,
|
|
1129
|
-
right.postfix,
|
|
1130
|
-
left.wrappedInnerExpressions &&
|
|
1131
|
-
right.wrappedInnerExpressions &&
|
|
1132
|
-
left.wrappedInnerExpressions
|
|
1133
|
-
.concat(left.postfix ? [left.postfix] : [])
|
|
1134
|
-
.concat(right.prefix ? [right.prefix] : [])
|
|
1135
|
-
.concat(right.wrappedInnerExpressions)
|
|
1136
|
-
);
|
|
1137
|
-
} else {
|
|
1138
|
-
// ("prefix" + inner + postfix) + expr
|
|
1139
|
-
// => ("prefix" + inner + postfix + expr + [null])
|
|
1140
|
-
res.setWrapped(
|
|
1141
|
-
left.prefix,
|
|
1142
|
-
null,
|
|
1143
|
-
left.wrappedInnerExpressions &&
|
|
1144
|
-
left.wrappedInnerExpressions.concat(
|
|
1145
|
-
left.postfix ? [left.postfix, right] : [right]
|
|
1193
|
+
),
|
|
1194
|
+
left.wrappedInnerExpressions
|
|
1195
|
+
);
|
|
1196
|
+
} else if (
|
|
1197
|
+
left.postfix &&
|
|
1198
|
+
left.postfix.isString() &&
|
|
1199
|
+
right.isNumber()
|
|
1200
|
+
) {
|
|
1201
|
+
// ("prefix" + inner + "postfix") + 123
|
|
1202
|
+
// => ("prefix" + inner + "postfix123")
|
|
1203
|
+
res.setWrapped(
|
|
1204
|
+
left.prefix,
|
|
1205
|
+
new BasicEvaluatedExpression()
|
|
1206
|
+
.setString(
|
|
1207
|
+
/** @type {string} */ (left.postfix.string) +
|
|
1208
|
+
/** @type {number} */ (right.number)
|
|
1209
|
+
)
|
|
1210
|
+
.setRange(
|
|
1211
|
+
joinRanges(
|
|
1212
|
+
/** @type {Range} */ (left.postfix.range),
|
|
1213
|
+
/** @type {Range} */ (right.range)
|
|
1146
1214
|
)
|
|
1147
|
-
|
|
1148
|
-
|
|
1215
|
+
),
|
|
1216
|
+
left.wrappedInnerExpressions
|
|
1217
|
+
);
|
|
1149
1218
|
} else if (right.isString()) {
|
|
1150
|
-
//
|
|
1151
|
-
// => (
|
|
1152
|
-
res.setWrapped(
|
|
1219
|
+
// ("prefix" + inner + [null]) + "right"
|
|
1220
|
+
// => ("prefix" + inner + "right")
|
|
1221
|
+
res.setWrapped(left.prefix, right, left.wrappedInnerExpressions);
|
|
1222
|
+
} else if (right.isNumber()) {
|
|
1223
|
+
// ("prefix" + inner + [null]) + 123
|
|
1224
|
+
// => ("prefix" + inner + "123")
|
|
1225
|
+
res.setWrapped(
|
|
1226
|
+
left.prefix,
|
|
1227
|
+
new BasicEvaluatedExpression()
|
|
1228
|
+
.setString(String(right.number))
|
|
1229
|
+
.setRange(/** @type {Range} */ (right.range)),
|
|
1230
|
+
left.wrappedInnerExpressions
|
|
1231
|
+
);
|
|
1153
1232
|
} else if (right.isWrapped()) {
|
|
1154
|
-
//
|
|
1155
|
-
//
|
|
1233
|
+
// ("prefix1" + inner1 + "postfix1") + ("prefix2" + inner2 + "postfix2")
|
|
1234
|
+
// ("prefix1" + inner1 + "postfix1" + "prefix2" + inner2 + "postfix2")
|
|
1156
1235
|
res.setWrapped(
|
|
1157
|
-
|
|
1236
|
+
left.prefix,
|
|
1158
1237
|
right.postfix,
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1238
|
+
left.wrappedInnerExpressions &&
|
|
1239
|
+
right.wrappedInnerExpressions && [
|
|
1240
|
+
...left.wrappedInnerExpressions,
|
|
1241
|
+
...(left.postfix ? [left.postfix] : []),
|
|
1242
|
+
...(right.prefix ? [right.prefix] : []),
|
|
1243
|
+
...right.wrappedInnerExpressions
|
|
1244
|
+
]
|
|
1163
1245
|
);
|
|
1164
1246
|
} else {
|
|
1165
|
-
|
|
1247
|
+
// ("prefix" + inner + postfix) + expr
|
|
1248
|
+
// => ("prefix" + inner + postfix + expr + [null])
|
|
1249
|
+
res.setWrapped(
|
|
1250
|
+
left.prefix,
|
|
1251
|
+
null,
|
|
1252
|
+
left.wrappedInnerExpressions && [
|
|
1253
|
+
...left.wrappedInnerExpressions,
|
|
1254
|
+
...(left.postfix ? [left.postfix, right] : [right])
|
|
1255
|
+
]
|
|
1256
|
+
);
|
|
1166
1257
|
}
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
} else if (
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
} else if (expr.operator === "==") {
|
|
1182
|
-
return handleAbstractEqualityComparison(true);
|
|
1183
|
-
} else if (expr.operator === "!==") {
|
|
1184
|
-
return handleStrictEqualityComparison(false);
|
|
1185
|
-
} else if (expr.operator === "!=") {
|
|
1186
|
-
return handleAbstractEqualityComparison(false);
|
|
1187
|
-
} else if (expr.operator === "&") {
|
|
1188
|
-
return handleConstOperation((l, r) => l & r);
|
|
1189
|
-
} else if (expr.operator === "|") {
|
|
1190
|
-
return handleConstOperation((l, r) => l | r);
|
|
1191
|
-
} else if (expr.operator === "^") {
|
|
1192
|
-
return handleConstOperation((l, r) => l ^ r);
|
|
1193
|
-
} else if (expr.operator === ">>>") {
|
|
1194
|
-
return handleConstOperation((l, r) => l >>> r);
|
|
1195
|
-
} else if (expr.operator === ">>") {
|
|
1196
|
-
return handleConstOperation((l, r) => l >> r);
|
|
1197
|
-
} else if (expr.operator === "<<") {
|
|
1198
|
-
return handleConstOperation((l, r) => l << r);
|
|
1199
|
-
} else if (expr.operator === "<") {
|
|
1200
|
-
return handleConstOperation((l, r) => l < r);
|
|
1201
|
-
} else if (expr.operator === ">") {
|
|
1202
|
-
return handleConstOperation((l, r) => l > r);
|
|
1203
|
-
} else if (expr.operator === "<=") {
|
|
1204
|
-
return handleConstOperation((l, r) => l <= r);
|
|
1205
|
-
} else if (expr.operator === ">=") {
|
|
1206
|
-
return handleConstOperation((l, r) => l >= r);
|
|
1207
|
-
}
|
|
1208
|
-
});
|
|
1209
|
-
this.hooks.evaluate
|
|
1210
|
-
.for("UnaryExpression")
|
|
1211
|
-
.tap("JavascriptParser", _expr => {
|
|
1212
|
-
const expr = /** @type {UnaryExpression} */ (_expr);
|
|
1213
|
-
|
|
1214
|
-
/**
|
|
1215
|
-
* Evaluates a UnaryExpression if and only if it is a basic const operator (e.g. +a, -a, ~a).
|
|
1216
|
-
* @template T
|
|
1217
|
-
* @param {(operand: T) => boolean | number | bigint | string} operandHandler handler for the operand
|
|
1218
|
-
* @returns {BasicEvaluatedExpression | undefined} evaluated expression
|
|
1219
|
-
*/
|
|
1220
|
-
const handleConstOperation = operandHandler => {
|
|
1221
|
-
const argument = this.evaluateExpression(expr.argument);
|
|
1222
|
-
if (!argument.isCompileTimeValue()) return;
|
|
1223
|
-
const result = operandHandler(argument.asCompileTimeValue());
|
|
1224
|
-
return valueAsExpression(
|
|
1225
|
-
result,
|
|
1226
|
-
expr,
|
|
1227
|
-
argument.couldHaveSideEffects()
|
|
1258
|
+
} else if (right.isString()) {
|
|
1259
|
+
// left + "right"
|
|
1260
|
+
// => ([null] + left + "right")
|
|
1261
|
+
res.setWrapped(null, right, [left]);
|
|
1262
|
+
} else if (right.isWrapped()) {
|
|
1263
|
+
// left + (prefix + inner + "postfix")
|
|
1264
|
+
// => ([null] + left + prefix + inner + "postfix")
|
|
1265
|
+
res.setWrapped(
|
|
1266
|
+
null,
|
|
1267
|
+
right.postfix,
|
|
1268
|
+
right.wrappedInnerExpressions && [
|
|
1269
|
+
...(right.prefix ? [left, right.prefix] : [left]),
|
|
1270
|
+
...right.wrappedInnerExpressions
|
|
1271
|
+
]
|
|
1228
1272
|
);
|
|
1229
|
-
}
|
|
1273
|
+
} else {
|
|
1274
|
+
return;
|
|
1275
|
+
}
|
|
1276
|
+
if (left.couldHaveSideEffects() || right.couldHaveSideEffects()) {
|
|
1277
|
+
res.setSideEffects();
|
|
1278
|
+
}
|
|
1279
|
+
res.setRange(/** @type {Range} */ (expr.range));
|
|
1280
|
+
return res;
|
|
1281
|
+
} else if (expr.operator === "-") {
|
|
1282
|
+
return handleConstOperation((l, r) => l - r);
|
|
1283
|
+
} else if (expr.operator === "*") {
|
|
1284
|
+
return handleConstOperation((l, r) => l * r);
|
|
1285
|
+
} else if (expr.operator === "/") {
|
|
1286
|
+
return handleConstOperation((l, r) => l / r);
|
|
1287
|
+
} else if (expr.operator === "**") {
|
|
1288
|
+
return handleConstOperation((l, r) => l ** r);
|
|
1289
|
+
} else if (expr.operator === "===") {
|
|
1290
|
+
return handleStrictEqualityComparison(true);
|
|
1291
|
+
} else if (expr.operator === "==") {
|
|
1292
|
+
return handleAbstractEqualityComparison(true);
|
|
1293
|
+
} else if (expr.operator === "!==") {
|
|
1294
|
+
return handleStrictEqualityComparison(false);
|
|
1295
|
+
} else if (expr.operator === "!=") {
|
|
1296
|
+
return handleAbstractEqualityComparison(false);
|
|
1297
|
+
} else if (expr.operator === "&") {
|
|
1298
|
+
return handleConstOperation((l, r) => l & r);
|
|
1299
|
+
} else if (expr.operator === "|") {
|
|
1300
|
+
return handleConstOperation((l, r) => l | r);
|
|
1301
|
+
} else if (expr.operator === "^") {
|
|
1302
|
+
return handleConstOperation((l, r) => l ^ r);
|
|
1303
|
+
} else if (expr.operator === ">>>") {
|
|
1304
|
+
return handleConstOperation((l, r) => l >>> r);
|
|
1305
|
+
} else if (expr.operator === ">>") {
|
|
1306
|
+
return handleConstOperation((l, r) => l >> r);
|
|
1307
|
+
} else if (expr.operator === "<<") {
|
|
1308
|
+
return handleConstOperation((l, r) => l << r);
|
|
1309
|
+
} else if (expr.operator === "<") {
|
|
1310
|
+
return handleConstOperation((l, r) => l < r);
|
|
1311
|
+
} else if (expr.operator === ">") {
|
|
1312
|
+
return handleConstOperation((l, r) => l > r);
|
|
1313
|
+
} else if (expr.operator === "<=") {
|
|
1314
|
+
return handleConstOperation((l, r) => l <= r);
|
|
1315
|
+
} else if (expr.operator === ">=") {
|
|
1316
|
+
return handleConstOperation((l, r) => l >= r);
|
|
1317
|
+
}
|
|
1318
|
+
});
|
|
1319
|
+
this.hooks.evaluate.for("UnaryExpression").tap(CLASS_NAME, (_expr) => {
|
|
1320
|
+
const expr = /** @type {UnaryExpression} */ (_expr);
|
|
1321
|
+
|
|
1322
|
+
/**
|
|
1323
|
+
* Evaluates a UnaryExpression if and only if it is a basic const operator (e.g. +a, -a, ~a).
|
|
1324
|
+
* @template T
|
|
1325
|
+
* @param {(operand: T) => boolean | number | bigint | string} operandHandler handler for the operand
|
|
1326
|
+
* @returns {BasicEvaluatedExpression | undefined} evaluated expression
|
|
1327
|
+
*/
|
|
1328
|
+
const handleConstOperation = (operandHandler) => {
|
|
1329
|
+
const argument = this.evaluateExpression(expr.argument);
|
|
1330
|
+
if (!argument.isCompileTimeValue()) return;
|
|
1331
|
+
const result = operandHandler(
|
|
1332
|
+
/** @type {T} */ (argument.asCompileTimeValue())
|
|
1333
|
+
);
|
|
1334
|
+
return valueAsExpression(result, expr, argument.couldHaveSideEffects());
|
|
1335
|
+
};
|
|
1230
1336
|
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
}
|
|
1242
|
-
case "MetaProperty": {
|
|
1243
|
-
const res = this.callHooksForName(
|
|
1244
|
-
this.hooks.evaluateTypeof,
|
|
1245
|
-
/** @type {string} */ (getRootName(expr.argument)),
|
|
1246
|
-
expr
|
|
1247
|
-
);
|
|
1248
|
-
if (res !== undefined) return res;
|
|
1249
|
-
break;
|
|
1250
|
-
}
|
|
1251
|
-
case "MemberExpression": {
|
|
1252
|
-
const res = this.callHooksForExpression(
|
|
1253
|
-
this.hooks.evaluateTypeof,
|
|
1254
|
-
expr.argument,
|
|
1255
|
-
expr
|
|
1256
|
-
);
|
|
1257
|
-
if (res !== undefined) return res;
|
|
1258
|
-
break;
|
|
1259
|
-
}
|
|
1260
|
-
case "ChainExpression": {
|
|
1261
|
-
const res = this.callHooksForExpression(
|
|
1262
|
-
this.hooks.evaluateTypeof,
|
|
1263
|
-
expr.argument.expression,
|
|
1264
|
-
expr
|
|
1265
|
-
);
|
|
1266
|
-
if (res !== undefined) return res;
|
|
1267
|
-
break;
|
|
1268
|
-
}
|
|
1269
|
-
case "FunctionExpression": {
|
|
1270
|
-
return new BasicEvaluatedExpression()
|
|
1271
|
-
.setString("function")
|
|
1272
|
-
.setRange(/** @type {Range} */ (expr.range));
|
|
1273
|
-
}
|
|
1274
|
-
}
|
|
1275
|
-
const arg = this.evaluateExpression(expr.argument);
|
|
1276
|
-
if (arg.isUnknown()) return;
|
|
1277
|
-
if (arg.isString()) {
|
|
1278
|
-
return new BasicEvaluatedExpression()
|
|
1279
|
-
.setString("string")
|
|
1280
|
-
.setRange(/** @type {Range} */ (expr.range));
|
|
1281
|
-
}
|
|
1282
|
-
if (arg.isWrapped()) {
|
|
1283
|
-
return new BasicEvaluatedExpression()
|
|
1284
|
-
.setString("string")
|
|
1285
|
-
.setSideEffects()
|
|
1286
|
-
.setRange(/** @type {Range} */ (expr.range));
|
|
1287
|
-
}
|
|
1288
|
-
if (arg.isUndefined()) {
|
|
1289
|
-
return new BasicEvaluatedExpression()
|
|
1290
|
-
.setString("undefined")
|
|
1291
|
-
.setRange(/** @type {Range} */ (expr.range));
|
|
1292
|
-
}
|
|
1293
|
-
if (arg.isNumber()) {
|
|
1294
|
-
return new BasicEvaluatedExpression()
|
|
1295
|
-
.setString("number")
|
|
1296
|
-
.setRange(/** @type {Range} */ (expr.range));
|
|
1337
|
+
if (expr.operator === "typeof") {
|
|
1338
|
+
switch (expr.argument.type) {
|
|
1339
|
+
case "Identifier": {
|
|
1340
|
+
const res = this.callHooksForName(
|
|
1341
|
+
this.hooks.evaluateTypeof,
|
|
1342
|
+
expr.argument.name,
|
|
1343
|
+
expr
|
|
1344
|
+
);
|
|
1345
|
+
if (res !== undefined) return res;
|
|
1346
|
+
break;
|
|
1297
1347
|
}
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
.
|
|
1301
|
-
|
|
1348
|
+
case "MetaProperty": {
|
|
1349
|
+
const res = this.callHooksForName(
|
|
1350
|
+
this.hooks.evaluateTypeof,
|
|
1351
|
+
/** @type {string} */
|
|
1352
|
+
(getRootName(expr.argument)),
|
|
1353
|
+
expr
|
|
1354
|
+
);
|
|
1355
|
+
if (res !== undefined) return res;
|
|
1356
|
+
break;
|
|
1302
1357
|
}
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
.
|
|
1306
|
-
|
|
1358
|
+
case "MemberExpression": {
|
|
1359
|
+
const res = this.callHooksForExpression(
|
|
1360
|
+
this.hooks.evaluateTypeof,
|
|
1361
|
+
expr.argument,
|
|
1362
|
+
expr
|
|
1363
|
+
);
|
|
1364
|
+
if (res !== undefined) return res;
|
|
1365
|
+
break;
|
|
1307
1366
|
}
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
.
|
|
1311
|
-
|
|
1367
|
+
case "ChainExpression": {
|
|
1368
|
+
const res = this.callHooksForExpression(
|
|
1369
|
+
this.hooks.evaluateTypeof,
|
|
1370
|
+
expr.argument.expression,
|
|
1371
|
+
expr
|
|
1372
|
+
);
|
|
1373
|
+
if (res !== undefined) return res;
|
|
1374
|
+
break;
|
|
1312
1375
|
}
|
|
1313
|
-
|
|
1376
|
+
case "FunctionExpression": {
|
|
1314
1377
|
return new BasicEvaluatedExpression()
|
|
1315
|
-
.setString("
|
|
1316
|
-
.setSideEffects(arg.couldHaveSideEffects())
|
|
1378
|
+
.setString("function")
|
|
1317
1379
|
.setRange(/** @type {Range} */ (expr.range));
|
|
1318
1380
|
}
|
|
1319
|
-
}
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1381
|
+
}
|
|
1382
|
+
const arg = this.evaluateExpression(expr.argument);
|
|
1383
|
+
if (arg.isUnknown()) return;
|
|
1384
|
+
if (arg.isString()) {
|
|
1323
1385
|
return new BasicEvaluatedExpression()
|
|
1324
|
-
.
|
|
1325
|
-
.setSideEffects(argument.couldHaveSideEffects())
|
|
1386
|
+
.setString("string")
|
|
1326
1387
|
.setRange(/** @type {Range} */ (expr.range));
|
|
1327
|
-
} else if (expr.operator === "~") {
|
|
1328
|
-
return handleConstOperation(v => ~v);
|
|
1329
|
-
} else if (expr.operator === "+") {
|
|
1330
|
-
// eslint-disable-next-line no-implicit-coercion
|
|
1331
|
-
return handleConstOperation(v => +v);
|
|
1332
|
-
} else if (expr.operator === "-") {
|
|
1333
|
-
return handleConstOperation(v => -v);
|
|
1334
1388
|
}
|
|
1335
|
-
|
|
1389
|
+
if (arg.isWrapped()) {
|
|
1390
|
+
return new BasicEvaluatedExpression()
|
|
1391
|
+
.setString("string")
|
|
1392
|
+
.setSideEffects()
|
|
1393
|
+
.setRange(/** @type {Range} */ (expr.range));
|
|
1394
|
+
}
|
|
1395
|
+
if (arg.isUndefined()) {
|
|
1396
|
+
return new BasicEvaluatedExpression()
|
|
1397
|
+
.setString("undefined")
|
|
1398
|
+
.setRange(/** @type {Range} */ (expr.range));
|
|
1399
|
+
}
|
|
1400
|
+
if (arg.isNumber()) {
|
|
1401
|
+
return new BasicEvaluatedExpression()
|
|
1402
|
+
.setString("number")
|
|
1403
|
+
.setRange(/** @type {Range} */ (expr.range));
|
|
1404
|
+
}
|
|
1405
|
+
if (arg.isBigInt()) {
|
|
1406
|
+
return new BasicEvaluatedExpression()
|
|
1407
|
+
.setString("bigint")
|
|
1408
|
+
.setRange(/** @type {Range} */ (expr.range));
|
|
1409
|
+
}
|
|
1410
|
+
if (arg.isBoolean()) {
|
|
1411
|
+
return new BasicEvaluatedExpression()
|
|
1412
|
+
.setString("boolean")
|
|
1413
|
+
.setRange(/** @type {Range} */ (expr.range));
|
|
1414
|
+
}
|
|
1415
|
+
if (arg.isConstArray() || arg.isRegExp() || arg.isNull()) {
|
|
1416
|
+
return new BasicEvaluatedExpression()
|
|
1417
|
+
.setString("object")
|
|
1418
|
+
.setRange(/** @type {Range} */ (expr.range));
|
|
1419
|
+
}
|
|
1420
|
+
if (arg.isArray()) {
|
|
1421
|
+
return new BasicEvaluatedExpression()
|
|
1422
|
+
.setString("object")
|
|
1423
|
+
.setSideEffects(arg.couldHaveSideEffects())
|
|
1424
|
+
.setRange(/** @type {Range} */ (expr.range));
|
|
1425
|
+
}
|
|
1426
|
+
} else if (expr.operator === "!") {
|
|
1427
|
+
const argument = this.evaluateExpression(expr.argument);
|
|
1428
|
+
const bool = argument.asBool();
|
|
1429
|
+
if (typeof bool !== "boolean") return;
|
|
1430
|
+
return new BasicEvaluatedExpression()
|
|
1431
|
+
.setBoolean(!bool)
|
|
1432
|
+
.setSideEffects(argument.couldHaveSideEffects())
|
|
1433
|
+
.setRange(/** @type {Range} */ (expr.range));
|
|
1434
|
+
} else if (expr.operator === "~") {
|
|
1435
|
+
return handleConstOperation((v) => ~v);
|
|
1436
|
+
} else if (expr.operator === "+") {
|
|
1437
|
+
// eslint-disable-next-line no-implicit-coercion
|
|
1438
|
+
return handleConstOperation((v) => +v);
|
|
1439
|
+
} else if (expr.operator === "-") {
|
|
1440
|
+
return handleConstOperation((v) => -v);
|
|
1441
|
+
}
|
|
1442
|
+
});
|
|
1336
1443
|
this.hooks.evaluateTypeof
|
|
1337
1444
|
.for("undefined")
|
|
1338
|
-
.tap(
|
|
1445
|
+
.tap(CLASS_NAME, (expr) =>
|
|
1339
1446
|
new BasicEvaluatedExpression()
|
|
1340
1447
|
.setString("undefined")
|
|
1341
1448
|
.setRange(/** @type {Range} */ (expr.range))
|
|
1342
1449
|
);
|
|
1343
|
-
this.hooks.evaluate.for("Identifier").tap(
|
|
1450
|
+
this.hooks.evaluate.for("Identifier").tap(CLASS_NAME, (expr) => {
|
|
1344
1451
|
if (/** @type {Identifier} */ (expr).name === "undefined") {
|
|
1345
1452
|
return new BasicEvaluatedExpression()
|
|
1346
1453
|
.setUndefined()
|
|
@@ -1349,7 +1456,7 @@ class JavascriptParser extends Parser {
|
|
|
1349
1456
|
});
|
|
1350
1457
|
/**
|
|
1351
1458
|
* @param {"Identifier" | "ThisExpression" | "MemberExpression"} exprType expression type name
|
|
1352
|
-
* @param {
|
|
1459
|
+
* @param {(node: Expression | SpreadElement) => GetInfoResult | undefined} getInfo get info
|
|
1353
1460
|
* @returns {void}
|
|
1354
1461
|
*/
|
|
1355
1462
|
const tapEvaluateWithVariableInfo = (exprType, getInfo) => {
|
|
@@ -1357,7 +1464,7 @@ class JavascriptParser extends Parser {
|
|
|
1357
1464
|
let cachedExpression;
|
|
1358
1465
|
/** @type {GetInfoResult | undefined} */
|
|
1359
1466
|
let cachedInfo;
|
|
1360
|
-
this.hooks.evaluate.for(exprType).tap(
|
|
1467
|
+
this.hooks.evaluate.for(exprType).tap(CLASS_NAME, (expr) => {
|
|
1361
1468
|
const expression =
|
|
1362
1469
|
/** @type {Identifier | ThisExpression | MemberExpression} */ (expr);
|
|
1363
1470
|
|
|
@@ -1366,11 +1473,12 @@ class JavascriptParser extends Parser {
|
|
|
1366
1473
|
return this.callHooksForInfoWithFallback(
|
|
1367
1474
|
this.hooks.evaluateIdentifier,
|
|
1368
1475
|
info.name,
|
|
1369
|
-
|
|
1476
|
+
(_name) => {
|
|
1370
1477
|
cachedExpression = expression;
|
|
1371
1478
|
cachedInfo = info;
|
|
1479
|
+
return undefined;
|
|
1372
1480
|
},
|
|
1373
|
-
name => {
|
|
1481
|
+
(name) => {
|
|
1374
1482
|
const hook = this.hooks.evaluateDefinedIdentifier.get(name);
|
|
1375
1483
|
if (hook !== undefined) {
|
|
1376
1484
|
return hook.call(expression);
|
|
@@ -1382,7 +1490,7 @@ class JavascriptParser extends Parser {
|
|
|
1382
1490
|
});
|
|
1383
1491
|
this.hooks.evaluate
|
|
1384
1492
|
.for(exprType)
|
|
1385
|
-
.tap({ name:
|
|
1493
|
+
.tap({ name: CLASS_NAME, stage: 100 }, (expr) => {
|
|
1386
1494
|
const expression =
|
|
1387
1495
|
/** @type {Identifier | ThisExpression | MemberExpression} */
|
|
1388
1496
|
(expr);
|
|
@@ -1400,16 +1508,16 @@ class JavascriptParser extends Parser {
|
|
|
1400
1508
|
.setRange(/** @type {Range} */ (expression.range));
|
|
1401
1509
|
}
|
|
1402
1510
|
});
|
|
1403
|
-
this.hooks.finish.tap(
|
|
1511
|
+
this.hooks.finish.tap(CLASS_NAME, () => {
|
|
1404
1512
|
// Cleanup for GC
|
|
1405
1513
|
cachedExpression = cachedInfo = undefined;
|
|
1406
1514
|
});
|
|
1407
1515
|
};
|
|
1408
|
-
tapEvaluateWithVariableInfo("Identifier", expr => {
|
|
1516
|
+
tapEvaluateWithVariableInfo("Identifier", (expr) => {
|
|
1409
1517
|
const info = this.getVariableInfo(/** @type {Identifier} */ (expr).name);
|
|
1410
1518
|
if (
|
|
1411
1519
|
typeof info === "string" ||
|
|
1412
|
-
(info instanceof VariableInfo &&
|
|
1520
|
+
(info instanceof VariableInfo && (info.isFree() || info.isTagged()))
|
|
1413
1521
|
) {
|
|
1414
1522
|
return {
|
|
1415
1523
|
name: info,
|
|
@@ -1420,11 +1528,11 @@ class JavascriptParser extends Parser {
|
|
|
1420
1528
|
};
|
|
1421
1529
|
}
|
|
1422
1530
|
});
|
|
1423
|
-
tapEvaluateWithVariableInfo("ThisExpression",
|
|
1531
|
+
tapEvaluateWithVariableInfo("ThisExpression", (_expr) => {
|
|
1424
1532
|
const info = this.getVariableInfo("this");
|
|
1425
1533
|
if (
|
|
1426
1534
|
typeof info === "string" ||
|
|
1427
|
-
(info instanceof VariableInfo &&
|
|
1535
|
+
(info instanceof VariableInfo && (info.isFree() || info.isTagged()))
|
|
1428
1536
|
) {
|
|
1429
1537
|
return {
|
|
1430
1538
|
name: info,
|
|
@@ -1435,23 +1543,24 @@ class JavascriptParser extends Parser {
|
|
|
1435
1543
|
};
|
|
1436
1544
|
}
|
|
1437
1545
|
});
|
|
1438
|
-
this.hooks.evaluate.for("MetaProperty").tap(
|
|
1546
|
+
this.hooks.evaluate.for("MetaProperty").tap(CLASS_NAME, (expr) => {
|
|
1439
1547
|
const metaProperty = /** @type {MetaProperty} */ (expr);
|
|
1440
1548
|
|
|
1441
1549
|
return this.callHooksForName(
|
|
1442
1550
|
this.hooks.evaluateIdentifier,
|
|
1443
|
-
/** @type {string} */
|
|
1551
|
+
/** @type {string} */
|
|
1552
|
+
(getRootName(metaProperty)),
|
|
1444
1553
|
metaProperty
|
|
1445
1554
|
);
|
|
1446
1555
|
});
|
|
1447
|
-
tapEvaluateWithVariableInfo("MemberExpression", expr =>
|
|
1556
|
+
tapEvaluateWithVariableInfo("MemberExpression", (expr) =>
|
|
1448
1557
|
this.getMemberExpressionInfo(
|
|
1449
1558
|
/** @type {MemberExpression} */ (expr),
|
|
1450
1559
|
ALLOWED_MEMBER_TYPES_EXPRESSION
|
|
1451
1560
|
)
|
|
1452
1561
|
);
|
|
1453
1562
|
|
|
1454
|
-
this.hooks.evaluate.for("CallExpression").tap(
|
|
1563
|
+
this.hooks.evaluate.for("CallExpression").tap(CLASS_NAME, (_expr) => {
|
|
1455
1564
|
const expr = /** @type {CallExpression} */ (_expr);
|
|
1456
1565
|
if (
|
|
1457
1566
|
expr.callee.type === "MemberExpression" &&
|
|
@@ -1480,7 +1589,7 @@ class JavascriptParser extends Parser {
|
|
|
1480
1589
|
});
|
|
1481
1590
|
this.hooks.evaluateCallExpressionMember
|
|
1482
1591
|
.for("indexOf")
|
|
1483
|
-
.tap(
|
|
1592
|
+
.tap(CLASS_NAME, (expr, param) => {
|
|
1484
1593
|
if (!param.isString()) return;
|
|
1485
1594
|
if (expr.arguments.length === 0) return;
|
|
1486
1595
|
const [arg1, arg2] = expr.arguments;
|
|
@@ -1508,7 +1617,7 @@ class JavascriptParser extends Parser {
|
|
|
1508
1617
|
});
|
|
1509
1618
|
this.hooks.evaluateCallExpressionMember
|
|
1510
1619
|
.for("replace")
|
|
1511
|
-
.tap(
|
|
1620
|
+
.tap(CLASS_NAME, (expr, param) => {
|
|
1512
1621
|
if (!param.isString()) return;
|
|
1513
1622
|
if (expr.arguments.length !== 2) return;
|
|
1514
1623
|
if (expr.arguments[0].type === "SpreadElement") return;
|
|
@@ -1531,7 +1640,7 @@ class JavascriptParser extends Parser {
|
|
|
1531
1640
|
for (const fn of ["substr", "substring", "slice"]) {
|
|
1532
1641
|
this.hooks.evaluateCallExpressionMember
|
|
1533
1642
|
.for(fn)
|
|
1534
|
-
.tap(
|
|
1643
|
+
.tap(CLASS_NAME, (expr, param) => {
|
|
1535
1644
|
if (!param.isString()) return;
|
|
1536
1645
|
let arg1;
|
|
1537
1646
|
let result;
|
|
@@ -1623,22 +1732,20 @@ class JavascriptParser extends Parser {
|
|
|
1623
1732
|
};
|
|
1624
1733
|
};
|
|
1625
1734
|
|
|
1626
|
-
this.hooks.evaluate
|
|
1627
|
-
|
|
1628
|
-
.tap("JavascriptParser", _node => {
|
|
1629
|
-
const node = /** @type {TemplateLiteral} */ (_node);
|
|
1735
|
+
this.hooks.evaluate.for("TemplateLiteral").tap(CLASS_NAME, (_node) => {
|
|
1736
|
+
const node = /** @type {TemplateLiteral} */ (_node);
|
|
1630
1737
|
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1738
|
+
const { quasis, parts } = getSimplifiedTemplateResult("cooked", node);
|
|
1739
|
+
if (parts.length === 1) {
|
|
1740
|
+
return parts[0].setRange(/** @type {Range} */ (node.range));
|
|
1741
|
+
}
|
|
1742
|
+
return new BasicEvaluatedExpression()
|
|
1743
|
+
.setTemplateString(quasis, parts, "cooked")
|
|
1744
|
+
.setRange(/** @type {Range} */ (node.range));
|
|
1745
|
+
});
|
|
1639
1746
|
this.hooks.evaluate
|
|
1640
1747
|
.for("TaggedTemplateExpression")
|
|
1641
|
-
.tap(
|
|
1748
|
+
.tap(CLASS_NAME, (_node) => {
|
|
1642
1749
|
const node = /** @type {TaggedTemplateExpression} */ (_node);
|
|
1643
1750
|
const tag = this.evaluateExpression(node.tag);
|
|
1644
1751
|
|
|
@@ -1655,10 +1762,11 @@ class JavascriptParser extends Parser {
|
|
|
1655
1762
|
|
|
1656
1763
|
this.hooks.evaluateCallExpressionMember
|
|
1657
1764
|
.for("concat")
|
|
1658
|
-
.tap(
|
|
1765
|
+
.tap(CLASS_NAME, (expr, param) => {
|
|
1659
1766
|
if (!param.isString() && !param.isWrapped()) return;
|
|
1660
1767
|
let stringSuffix = null;
|
|
1661
1768
|
let hasUnknownParams = false;
|
|
1769
|
+
/** @type {BasicEvaluatedExpression[]} */
|
|
1662
1770
|
const innerExpressions = [];
|
|
1663
1771
|
for (let i = expr.arguments.length - 1; i >= 0; i--) {
|
|
1664
1772
|
const arg = expr.arguments[i];
|
|
@@ -1673,13 +1781,14 @@ class JavascriptParser extends Parser {
|
|
|
1673
1781
|
continue;
|
|
1674
1782
|
}
|
|
1675
1783
|
|
|
1676
|
-
/** @type {string} */
|
|
1677
1784
|
const value = argExpr.isString()
|
|
1678
1785
|
? /** @type {string} */ (argExpr.string)
|
|
1679
|
-
: String(
|
|
1786
|
+
: String(argExpr.number);
|
|
1680
1787
|
|
|
1681
1788
|
/** @type {string} */
|
|
1682
|
-
const newString =
|
|
1789
|
+
const newString =
|
|
1790
|
+
value +
|
|
1791
|
+
(stringSuffix ? /** @type {string} */ (stringSuffix.string) : "");
|
|
1683
1792
|
const newRange = /** @type {Range} */ ([
|
|
1684
1793
|
/** @type {Range} */ (argExpr.range)[0],
|
|
1685
1794
|
/** @type {Range} */ ((stringSuffix || argExpr).range)[1]
|
|
@@ -1697,7 +1806,10 @@ class JavascriptParser extends Parser {
|
|
|
1697
1806
|
const prefix = param.isString() ? param : param.prefix;
|
|
1698
1807
|
const inner =
|
|
1699
1808
|
param.isWrapped() && param.wrappedInnerExpressions
|
|
1700
|
-
?
|
|
1809
|
+
? [
|
|
1810
|
+
...param.wrappedInnerExpressions,
|
|
1811
|
+
...innerExpressions.reverse()
|
|
1812
|
+
]
|
|
1701
1813
|
: innerExpressions.reverse();
|
|
1702
1814
|
return new BasicEvaluatedExpression()
|
|
1703
1815
|
.setWrapped(prefix, stringSuffix, inner)
|
|
@@ -1705,7 +1817,7 @@ class JavascriptParser extends Parser {
|
|
|
1705
1817
|
} else if (param.isWrapped()) {
|
|
1706
1818
|
const postfix = stringSuffix || param.postfix;
|
|
1707
1819
|
const inner = param.wrappedInnerExpressions
|
|
1708
|
-
? param.wrappedInnerExpressions
|
|
1820
|
+
? [...param.wrappedInnerExpressions, ...innerExpressions.reverse()]
|
|
1709
1821
|
: innerExpressions.reverse();
|
|
1710
1822
|
return new BasicEvaluatedExpression()
|
|
1711
1823
|
.setWrapped(param.prefix, postfix, inner)
|
|
@@ -1724,7 +1836,7 @@ class JavascriptParser extends Parser {
|
|
|
1724
1836
|
});
|
|
1725
1837
|
this.hooks.evaluateCallExpressionMember
|
|
1726
1838
|
.for("split")
|
|
1727
|
-
.tap(
|
|
1839
|
+
.tap(CLASS_NAME, (expr, param) => {
|
|
1728
1840
|
if (!param.isString()) return;
|
|
1729
1841
|
if (expr.arguments.length !== 1) return;
|
|
1730
1842
|
if (expr.arguments[0].type === "SpreadElement") return;
|
|
@@ -1748,7 +1860,7 @@ class JavascriptParser extends Parser {
|
|
|
1748
1860
|
});
|
|
1749
1861
|
this.hooks.evaluate
|
|
1750
1862
|
.for("ConditionalExpression")
|
|
1751
|
-
.tap(
|
|
1863
|
+
.tap(CLASS_NAME, (_expr) => {
|
|
1752
1864
|
const expr = /** @type {ConditionalExpression} */ (_expr);
|
|
1753
1865
|
|
|
1754
1866
|
const condition = this.evaluateExpression(expr.test);
|
|
@@ -1781,71 +1893,67 @@ class JavascriptParser extends Parser {
|
|
|
1781
1893
|
res.setRange(/** @type {Range} */ (expr.range));
|
|
1782
1894
|
return res;
|
|
1783
1895
|
});
|
|
1784
|
-
this.hooks.evaluate
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
element
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
});
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
next.
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
// SuperNode can not be optional
|
|
1824
|
-
optionalExpressionsStack.push(
|
|
1825
|
-
/** @type {Expression} */ (next.callee)
|
|
1826
|
-
);
|
|
1827
|
-
}
|
|
1828
|
-
next = next.callee;
|
|
1896
|
+
this.hooks.evaluate.for("ArrayExpression").tap(CLASS_NAME, (_expr) => {
|
|
1897
|
+
const expr = /** @type {ArrayExpression} */ (_expr);
|
|
1898
|
+
|
|
1899
|
+
const items = expr.elements.map(
|
|
1900
|
+
(element) =>
|
|
1901
|
+
element !== null &&
|
|
1902
|
+
element.type !== "SpreadElement" &&
|
|
1903
|
+
this.evaluateExpression(element)
|
|
1904
|
+
);
|
|
1905
|
+
if (!items.every(Boolean)) return;
|
|
1906
|
+
return new BasicEvaluatedExpression()
|
|
1907
|
+
.setItems(/** @type {BasicEvaluatedExpression[]} */ (items))
|
|
1908
|
+
.setRange(/** @type {Range} */ (expr.range));
|
|
1909
|
+
});
|
|
1910
|
+
this.hooks.evaluate.for("ChainExpression").tap(CLASS_NAME, (_expr) => {
|
|
1911
|
+
const expr = /** @type {ChainExpression} */ (_expr);
|
|
1912
|
+
/** @type {Expression[]} */
|
|
1913
|
+
const optionalExpressionsStack = [];
|
|
1914
|
+
/** @type {Expression | Super} */
|
|
1915
|
+
let next = expr.expression;
|
|
1916
|
+
|
|
1917
|
+
while (
|
|
1918
|
+
next.type === "MemberExpression" ||
|
|
1919
|
+
next.type === "CallExpression"
|
|
1920
|
+
) {
|
|
1921
|
+
if (next.type === "MemberExpression") {
|
|
1922
|
+
if (next.optional) {
|
|
1923
|
+
// SuperNode can not be optional
|
|
1924
|
+
optionalExpressionsStack.push(
|
|
1925
|
+
/** @type {Expression} */ (next.object)
|
|
1926
|
+
);
|
|
1927
|
+
}
|
|
1928
|
+
next = next.object;
|
|
1929
|
+
} else {
|
|
1930
|
+
if (next.optional) {
|
|
1931
|
+
// SuperNode can not be optional
|
|
1932
|
+
optionalExpressionsStack.push(
|
|
1933
|
+
/** @type {Expression} */ (next.callee)
|
|
1934
|
+
);
|
|
1829
1935
|
}
|
|
1936
|
+
next = next.callee;
|
|
1830
1937
|
}
|
|
1938
|
+
}
|
|
1831
1939
|
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1940
|
+
while (optionalExpressionsStack.length > 0) {
|
|
1941
|
+
const expression =
|
|
1942
|
+
/** @type {Expression} */
|
|
1943
|
+
(optionalExpressionsStack.pop());
|
|
1944
|
+
const evaluated = this.evaluateExpression(expression);
|
|
1837
1945
|
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
}
|
|
1946
|
+
if (evaluated.asNullish()) {
|
|
1947
|
+
return evaluated.setRange(/** @type {Range} */ (_expr.range));
|
|
1841
1948
|
}
|
|
1842
|
-
|
|
1843
|
-
|
|
1949
|
+
}
|
|
1950
|
+
return this.evaluateExpression(expr.expression);
|
|
1951
|
+
});
|
|
1844
1952
|
}
|
|
1845
1953
|
|
|
1846
1954
|
/**
|
|
1847
1955
|
* @param {Expression} node node
|
|
1848
|
-
* @returns {
|
|
1956
|
+
* @returns {DestructuringAssignmentProperties | undefined} destructured identifiers
|
|
1849
1957
|
*/
|
|
1850
1958
|
destructuringAssignmentPropertiesFor(node) {
|
|
1851
1959
|
if (!this.destructuringAssignmentProperties) return;
|
|
@@ -1854,7 +1962,7 @@ class JavascriptParser extends Parser {
|
|
|
1854
1962
|
|
|
1855
1963
|
/**
|
|
1856
1964
|
* @param {Expression | SpreadElement} expr expression
|
|
1857
|
-
* @returns {string |
|
|
1965
|
+
* @returns {string | VariableInfo | undefined} identifier
|
|
1858
1966
|
*/
|
|
1859
1967
|
getRenameIdentifier(expr) {
|
|
1860
1968
|
const result = this.evaluateExpression(expr);
|
|
@@ -1864,7 +1972,7 @@ class JavascriptParser extends Parser {
|
|
|
1864
1972
|
}
|
|
1865
1973
|
|
|
1866
1974
|
/**
|
|
1867
|
-
* @param {ClassExpression | ClassDeclaration} classy a class node
|
|
1975
|
+
* @param {ClassExpression | ClassDeclaration | MaybeNamedClassDeclaration} classy a class node
|
|
1868
1976
|
* @returns {void}
|
|
1869
1977
|
*/
|
|
1870
1978
|
walkClass(classy) {
|
|
@@ -1881,13 +1989,20 @@ class JavascriptParser extends Parser {
|
|
|
1881
1989
|
scopeParams.push(classy.id);
|
|
1882
1990
|
}
|
|
1883
1991
|
this.inClassScope(true, scopeParams, () => {
|
|
1884
|
-
for (const classElement of
|
|
1992
|
+
for (const classElement of classy.body.body) {
|
|
1885
1993
|
if (!this.hooks.classBodyElement.call(classElement, classy)) {
|
|
1886
|
-
if (classElement.
|
|
1887
|
-
this.
|
|
1888
|
-
|
|
1889
|
-
|
|
1994
|
+
if (classElement.type === "StaticBlock") {
|
|
1995
|
+
const wasTopLevel = this.scope.topLevelScope;
|
|
1996
|
+
this.scope.topLevelScope = false;
|
|
1997
|
+
this.walkBlockStatement(classElement);
|
|
1998
|
+
this.scope.topLevelScope = wasTopLevel;
|
|
1999
|
+
} else {
|
|
2000
|
+
if (classElement.computed && classElement.key) {
|
|
2001
|
+
this.walkExpression(classElement.key);
|
|
2002
|
+
}
|
|
2003
|
+
|
|
1890
2004
|
if (
|
|
2005
|
+
classElement.value &&
|
|
1891
2006
|
!this.hooks.classBodyValue.call(
|
|
1892
2007
|
classElement.value,
|
|
1893
2008
|
classElement,
|
|
@@ -1899,11 +2014,6 @@ class JavascriptParser extends Parser {
|
|
|
1899
2014
|
this.walkExpression(classElement.value);
|
|
1900
2015
|
this.scope.topLevelScope = wasTopLevel;
|
|
1901
2016
|
}
|
|
1902
|
-
} else if (classElement.type === "StaticBlock") {
|
|
1903
|
-
const wasTopLevel = this.scope.topLevelScope;
|
|
1904
|
-
this.scope.topLevelScope = false;
|
|
1905
|
-
this.walkBlockStatement(classElement);
|
|
1906
|
-
this.scope.topLevelScope = wasTopLevel;
|
|
1907
2017
|
}
|
|
1908
2018
|
}
|
|
1909
2019
|
}
|
|
@@ -1911,6 +2021,32 @@ class JavascriptParser extends Parser {
|
|
|
1911
2021
|
}
|
|
1912
2022
|
}
|
|
1913
2023
|
|
|
2024
|
+
/**
|
|
2025
|
+
* Module pre walking iterates the scope for import entries
|
|
2026
|
+
* @param {(Statement | ModuleDeclaration)[]} statements statements
|
|
2027
|
+
*/
|
|
2028
|
+
modulePreWalkStatements(statements) {
|
|
2029
|
+
for (let index = 0, len = statements.length; index < len; index++) {
|
|
2030
|
+
const statement = statements[index];
|
|
2031
|
+
/** @type {StatementPath} */
|
|
2032
|
+
(this.statementPath).push(statement);
|
|
2033
|
+
switch (statement.type) {
|
|
2034
|
+
case "ImportDeclaration":
|
|
2035
|
+
this.modulePreWalkImportDeclaration(statement);
|
|
2036
|
+
break;
|
|
2037
|
+
case "ExportAllDeclaration":
|
|
2038
|
+
this.modulePreWalkExportAllDeclaration(statement);
|
|
2039
|
+
break;
|
|
2040
|
+
case "ExportNamedDeclaration":
|
|
2041
|
+
this.modulePreWalkExportNamedDeclaration(statement);
|
|
2042
|
+
break;
|
|
2043
|
+
}
|
|
2044
|
+
this.prevStatement =
|
|
2045
|
+
/** @type {StatementPath} */
|
|
2046
|
+
(this.statementPath).pop();
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
|
|
1914
2050
|
/**
|
|
1915
2051
|
* Pre walking iterates the scope for variable declarations
|
|
1916
2052
|
* @param {(Statement | ModuleDeclaration)[]} statements statements
|
|
@@ -1938,15 +2074,30 @@ class JavascriptParser extends Parser {
|
|
|
1938
2074
|
* @param {(Statement | ModuleDeclaration)[]} statements statements
|
|
1939
2075
|
*/
|
|
1940
2076
|
walkStatements(statements) {
|
|
2077
|
+
let onlyFunctionDeclaration = false;
|
|
2078
|
+
|
|
1941
2079
|
for (let index = 0, len = statements.length; index < len; index++) {
|
|
1942
2080
|
const statement = statements[index];
|
|
2081
|
+
|
|
2082
|
+
if (
|
|
2083
|
+
onlyFunctionDeclaration &&
|
|
2084
|
+
statement.type !== "FunctionDeclaration" &&
|
|
2085
|
+
this.hooks.unusedStatement.call(/** @type {Statement} */ (statement))
|
|
2086
|
+
) {
|
|
2087
|
+
continue;
|
|
2088
|
+
}
|
|
2089
|
+
|
|
1943
2090
|
this.walkStatement(statement);
|
|
2091
|
+
|
|
2092
|
+
if (this.scope.terminated) {
|
|
2093
|
+
onlyFunctionDeclaration = true;
|
|
2094
|
+
}
|
|
1944
2095
|
}
|
|
1945
2096
|
}
|
|
1946
2097
|
|
|
1947
2098
|
/**
|
|
1948
2099
|
* Walking iterates the statements and expressions and processes them
|
|
1949
|
-
* @param {Statement | ModuleDeclaration} statement statement
|
|
2100
|
+
* @param {Statement | ModuleDeclaration | MaybeNamedClassDeclaration | MaybeNamedFunctionDeclaration} statement statement
|
|
1950
2101
|
*/
|
|
1951
2102
|
preWalkStatement(statement) {
|
|
1952
2103
|
/** @type {StatementPath} */
|
|
@@ -2004,7 +2155,7 @@ class JavascriptParser extends Parser {
|
|
|
2004
2155
|
}
|
|
2005
2156
|
|
|
2006
2157
|
/**
|
|
2007
|
-
* @param {Statement | ModuleDeclaration} statement statement
|
|
2158
|
+
* @param {Statement | ModuleDeclaration | MaybeNamedClassDeclaration | MaybeNamedFunctionDeclaration} statement statement
|
|
2008
2159
|
*/
|
|
2009
2160
|
blockPreWalkStatement(statement) {
|
|
2010
2161
|
/** @type {StatementPath} */
|
|
@@ -2016,12 +2167,6 @@ class JavascriptParser extends Parser {
|
|
|
2016
2167
|
return;
|
|
2017
2168
|
}
|
|
2018
2169
|
switch (statement.type) {
|
|
2019
|
-
case "ImportDeclaration":
|
|
2020
|
-
this.blockPreWalkImportDeclaration(statement);
|
|
2021
|
-
break;
|
|
2022
|
-
case "ExportAllDeclaration":
|
|
2023
|
-
this.blockPreWalkExportAllDeclaration(statement);
|
|
2024
|
-
break;
|
|
2025
2170
|
case "ExportDefaultDeclaration":
|
|
2026
2171
|
this.blockPreWalkExportDefaultDeclaration(statement);
|
|
2027
2172
|
break;
|
|
@@ -2043,7 +2188,7 @@ class JavascriptParser extends Parser {
|
|
|
2043
2188
|
}
|
|
2044
2189
|
|
|
2045
2190
|
/**
|
|
2046
|
-
* @param {Statement | ModuleDeclaration} statement statement
|
|
2191
|
+
* @param {Statement | ModuleDeclaration | MaybeNamedFunctionDeclaration | MaybeNamedClassDeclaration} statement statement
|
|
2047
2192
|
*/
|
|
2048
2193
|
walkStatement(statement) {
|
|
2049
2194
|
/** @type {StatementPath} */
|
|
@@ -2138,7 +2283,7 @@ class JavascriptParser extends Parser {
|
|
|
2138
2283
|
}
|
|
2139
2284
|
|
|
2140
2285
|
/**
|
|
2141
|
-
* @param {BlockStatement} statement block statement
|
|
2286
|
+
* @param {BlockStatement | StaticBlock} statement block statement
|
|
2142
2287
|
*/
|
|
2143
2288
|
walkBlockStatement(statement) {
|
|
2144
2289
|
this.inBlockScope(() => {
|
|
@@ -2147,7 +2292,7 @@ class JavascriptParser extends Parser {
|
|
|
2147
2292
|
this.blockPreWalkStatements(body);
|
|
2148
2293
|
this.prevStatement = prev;
|
|
2149
2294
|
this.walkStatements(body);
|
|
2150
|
-
});
|
|
2295
|
+
}, true);
|
|
2151
2296
|
}
|
|
2152
2297
|
|
|
2153
2298
|
/**
|
|
@@ -2175,9 +2320,20 @@ class JavascriptParser extends Parser {
|
|
|
2175
2320
|
if (result === undefined) {
|
|
2176
2321
|
this.walkExpression(statement.test);
|
|
2177
2322
|
this.walkNestedStatement(statement.consequent);
|
|
2323
|
+
|
|
2324
|
+
const consequentTerminated = this.scope.terminated;
|
|
2325
|
+
this.scope.terminated = undefined;
|
|
2326
|
+
|
|
2178
2327
|
if (statement.alternate) {
|
|
2179
2328
|
this.walkNestedStatement(statement.alternate);
|
|
2180
2329
|
}
|
|
2330
|
+
|
|
2331
|
+
const alternateTerminated = this.scope.terminated;
|
|
2332
|
+
|
|
2333
|
+
this.scope.terminated =
|
|
2334
|
+
consequentTerminated && alternateTerminated
|
|
2335
|
+
? alternateTerminated
|
|
2336
|
+
: undefined;
|
|
2181
2337
|
} else if (result) {
|
|
2182
2338
|
this.walkNestedStatement(statement.consequent);
|
|
2183
2339
|
} else if (statement.alternate) {
|
|
@@ -2201,7 +2357,9 @@ class JavascriptParser extends Parser {
|
|
|
2201
2357
|
const result = hook.call(statement);
|
|
2202
2358
|
if (result === true) return;
|
|
2203
2359
|
}
|
|
2204
|
-
this.
|
|
2360
|
+
this.inBlockScope(() => {
|
|
2361
|
+
this.walkNestedStatement(statement.body);
|
|
2362
|
+
});
|
|
2205
2363
|
}
|
|
2206
2364
|
|
|
2207
2365
|
/**
|
|
@@ -2215,8 +2373,10 @@ class JavascriptParser extends Parser {
|
|
|
2215
2373
|
* @param {WithStatement} statement with statement
|
|
2216
2374
|
*/
|
|
2217
2375
|
walkWithStatement(statement) {
|
|
2218
|
-
this.
|
|
2219
|
-
|
|
2376
|
+
this.inBlockScope(() => {
|
|
2377
|
+
this.walkExpression(statement.object);
|
|
2378
|
+
this.walkNestedStatement(statement.body);
|
|
2379
|
+
});
|
|
2220
2380
|
}
|
|
2221
2381
|
|
|
2222
2382
|
/**
|
|
@@ -2239,6 +2399,14 @@ class JavascriptParser extends Parser {
|
|
|
2239
2399
|
*/
|
|
2240
2400
|
walkTerminatingStatement(statement) {
|
|
2241
2401
|
if (statement.argument) this.walkExpression(statement.argument);
|
|
2402
|
+
// Skip top level scope because to handle `export` and `module.exports` after terminate
|
|
2403
|
+
if (this.scope.topLevelScope === true) return;
|
|
2404
|
+
if (this.hooks.terminate.call(statement)) {
|
|
2405
|
+
this.scope.terminated =
|
|
2406
|
+
statement.type === "ReturnStatement"
|
|
2407
|
+
? SCOPE_INFO_TERMINATED_RETURN
|
|
2408
|
+
: SCOPE_INFO_TERMINATED_THROW;
|
|
2409
|
+
}
|
|
2242
2410
|
}
|
|
2243
2411
|
|
|
2244
2412
|
/**
|
|
@@ -2275,8 +2443,30 @@ class JavascriptParser extends Parser {
|
|
|
2275
2443
|
this.walkStatement(statement.block);
|
|
2276
2444
|
this.scope.inTry = false;
|
|
2277
2445
|
}
|
|
2446
|
+
|
|
2447
|
+
const tryTerminated = this.scope.terminated;
|
|
2448
|
+
this.scope.terminated = undefined;
|
|
2449
|
+
|
|
2278
2450
|
if (statement.handler) this.walkCatchClause(statement.handler);
|
|
2279
|
-
|
|
2451
|
+
|
|
2452
|
+
const handlerTerminated = this.scope.terminated;
|
|
2453
|
+
this.scope.terminated = undefined;
|
|
2454
|
+
|
|
2455
|
+
if (statement.finalizer) {
|
|
2456
|
+
this.walkStatement(statement.finalizer);
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2459
|
+
const finalizerTerminated = this.scope.terminated;
|
|
2460
|
+
this.scope.terminated = undefined;
|
|
2461
|
+
|
|
2462
|
+
if (finalizerTerminated) {
|
|
2463
|
+
this.scope.terminated = finalizerTerminated;
|
|
2464
|
+
} else if (
|
|
2465
|
+
tryTerminated &&
|
|
2466
|
+
(statement.handler ? handlerTerminated : true)
|
|
2467
|
+
) {
|
|
2468
|
+
this.scope.terminated = handlerTerminated || tryTerminated;
|
|
2469
|
+
}
|
|
2280
2470
|
}
|
|
2281
2471
|
|
|
2282
2472
|
/**
|
|
@@ -2290,8 +2480,10 @@ class JavascriptParser extends Parser {
|
|
|
2290
2480
|
* @param {WhileStatement} statement while statement
|
|
2291
2481
|
*/
|
|
2292
2482
|
walkWhileStatement(statement) {
|
|
2293
|
-
this.
|
|
2294
|
-
|
|
2483
|
+
this.inBlockScope(() => {
|
|
2484
|
+
this.walkExpression(statement.test);
|
|
2485
|
+
this.walkNestedStatement(statement.body);
|
|
2486
|
+
});
|
|
2295
2487
|
}
|
|
2296
2488
|
|
|
2297
2489
|
/**
|
|
@@ -2305,8 +2497,10 @@ class JavascriptParser extends Parser {
|
|
|
2305
2497
|
* @param {DoWhileStatement} statement do while statement
|
|
2306
2498
|
*/
|
|
2307
2499
|
walkDoWhileStatement(statement) {
|
|
2308
|
-
this.
|
|
2309
|
-
|
|
2500
|
+
this.inBlockScope(() => {
|
|
2501
|
+
this.walkNestedStatement(statement.body);
|
|
2502
|
+
this.walkExpression(statement.test);
|
|
2503
|
+
});
|
|
2310
2504
|
}
|
|
2311
2505
|
|
|
2312
2506
|
/**
|
|
@@ -2339,7 +2533,9 @@ class JavascriptParser extends Parser {
|
|
|
2339
2533
|
if (statement.update) {
|
|
2340
2534
|
this.walkExpression(statement.update);
|
|
2341
2535
|
}
|
|
2536
|
+
|
|
2342
2537
|
const body = statement.body;
|
|
2538
|
+
|
|
2343
2539
|
if (body.type === "BlockStatement") {
|
|
2344
2540
|
// no need to add additional scope
|
|
2345
2541
|
const prev = this.prevStatement;
|
|
@@ -2373,8 +2569,11 @@ class JavascriptParser extends Parser {
|
|
|
2373
2569
|
} else {
|
|
2374
2570
|
this.walkPattern(statement.left);
|
|
2375
2571
|
}
|
|
2572
|
+
|
|
2376
2573
|
this.walkExpression(statement.right);
|
|
2574
|
+
|
|
2377
2575
|
const body = statement.body;
|
|
2576
|
+
|
|
2378
2577
|
if (body.type === "BlockStatement") {
|
|
2379
2578
|
// no need to add additional scope
|
|
2380
2579
|
const prev = this.prevStatement;
|
|
@@ -2411,8 +2610,11 @@ class JavascriptParser extends Parser {
|
|
|
2411
2610
|
} else {
|
|
2412
2611
|
this.walkPattern(statement.left);
|
|
2413
2612
|
}
|
|
2613
|
+
|
|
2414
2614
|
this.walkExpression(statement.right);
|
|
2615
|
+
|
|
2415
2616
|
const body = statement.body;
|
|
2617
|
+
|
|
2416
2618
|
if (body.type === "BlockStatement") {
|
|
2417
2619
|
// no need to add additional scope
|
|
2418
2620
|
const prev = this.prevStatement;
|
|
@@ -2426,7 +2628,7 @@ class JavascriptParser extends Parser {
|
|
|
2426
2628
|
}
|
|
2427
2629
|
|
|
2428
2630
|
/**
|
|
2429
|
-
* @param {FunctionDeclaration} statement function declaration
|
|
2631
|
+
* @param {FunctionDeclaration | MaybeNamedFunctionDeclaration} statement function declaration
|
|
2430
2632
|
*/
|
|
2431
2633
|
preWalkFunctionDeclaration(statement) {
|
|
2432
2634
|
if (statement.id) {
|
|
@@ -2435,7 +2637,7 @@ class JavascriptParser extends Parser {
|
|
|
2435
2637
|
}
|
|
2436
2638
|
|
|
2437
2639
|
/**
|
|
2438
|
-
* @param {FunctionDeclaration} statement function declaration
|
|
2640
|
+
* @param {FunctionDeclaration | MaybeNamedFunctionDeclaration} statement function declaration
|
|
2439
2641
|
*/
|
|
2440
2642
|
walkFunctionDeclaration(statement) {
|
|
2441
2643
|
const wasTopLevel = this.scope.topLevelScope;
|
|
@@ -2444,15 +2646,14 @@ class JavascriptParser extends Parser {
|
|
|
2444
2646
|
for (const param of statement.params) {
|
|
2445
2647
|
this.walkPattern(param);
|
|
2446
2648
|
}
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
}
|
|
2649
|
+
|
|
2650
|
+
this.detectMode(statement.body.body);
|
|
2651
|
+
|
|
2652
|
+
const prev = this.prevStatement;
|
|
2653
|
+
|
|
2654
|
+
this.preWalkStatement(statement.body);
|
|
2655
|
+
this.prevStatement = prev;
|
|
2656
|
+
this.walkStatement(statement.body);
|
|
2456
2657
|
});
|
|
2457
2658
|
this.scope.topLevelScope = wasTopLevel;
|
|
2458
2659
|
}
|
|
@@ -2472,39 +2673,54 @@ class JavascriptParser extends Parser {
|
|
|
2472
2673
|
* @param {AssignmentExpression} expression assignment expression
|
|
2473
2674
|
*/
|
|
2474
2675
|
preWalkAssignmentExpression(expression) {
|
|
2676
|
+
this.enterDestructuringAssignment(expression.left, expression.right);
|
|
2677
|
+
}
|
|
2678
|
+
|
|
2679
|
+
/**
|
|
2680
|
+
* @param {Pattern} pattern pattern
|
|
2681
|
+
* @param {Expression} expression assignment expression
|
|
2682
|
+
* @returns {Expression | undefined} destructuring expression
|
|
2683
|
+
*/
|
|
2684
|
+
enterDestructuringAssignment(pattern, expression) {
|
|
2475
2685
|
if (
|
|
2476
|
-
|
|
2686
|
+
pattern.type !== "ObjectPattern" ||
|
|
2477
2687
|
!this.destructuringAssignmentProperties
|
|
2478
|
-
)
|
|
2688
|
+
) {
|
|
2479
2689
|
return;
|
|
2480
|
-
const keys = this._preWalkObjectPattern(expression.left);
|
|
2481
|
-
if (!keys) return;
|
|
2482
|
-
|
|
2483
|
-
// check multiple assignments
|
|
2484
|
-
if (this.destructuringAssignmentProperties.has(expression)) {
|
|
2485
|
-
const set =
|
|
2486
|
-
/** @type {Set<DestructuringAssignmentProperty>} */
|
|
2487
|
-
(this.destructuringAssignmentProperties.get(expression));
|
|
2488
|
-
this.destructuringAssignmentProperties.delete(expression);
|
|
2489
|
-
for (const id of set) keys.add(id);
|
|
2490
2690
|
}
|
|
2491
2691
|
|
|
2492
|
-
|
|
2493
|
-
expression.
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2692
|
+
const expr =
|
|
2693
|
+
expression.type === "AwaitExpression" ? expression.argument : expression;
|
|
2694
|
+
|
|
2695
|
+
const destructuring =
|
|
2696
|
+
expr.type === "AssignmentExpression"
|
|
2697
|
+
? this.enterDestructuringAssignment(expr.left, expr.right)
|
|
2698
|
+
: this.hooks.collectDestructuringAssignmentProperties.call(expr)
|
|
2699
|
+
? expr
|
|
2700
|
+
: undefined;
|
|
2701
|
+
|
|
2702
|
+
if (destructuring) {
|
|
2703
|
+
const keys = this._preWalkObjectPattern(pattern);
|
|
2704
|
+
if (!keys) return;
|
|
2705
|
+
|
|
2706
|
+
// check multiple assignments
|
|
2707
|
+
if (this.destructuringAssignmentProperties.has(destructuring)) {
|
|
2708
|
+
const set =
|
|
2709
|
+
/** @type {DestructuringAssignmentProperties} */
|
|
2710
|
+
(this.destructuringAssignmentProperties.get(destructuring));
|
|
2711
|
+
for (const id of keys) set.add(id);
|
|
2712
|
+
} else {
|
|
2713
|
+
this.destructuringAssignmentProperties.set(destructuring, keys);
|
|
2714
|
+
}
|
|
2501
2715
|
}
|
|
2716
|
+
|
|
2717
|
+
return destructuring;
|
|
2502
2718
|
}
|
|
2503
2719
|
|
|
2504
2720
|
/**
|
|
2505
2721
|
* @param {ImportDeclaration} statement statement
|
|
2506
2722
|
*/
|
|
2507
|
-
|
|
2723
|
+
modulePreWalkImportDeclaration(statement) {
|
|
2508
2724
|
const source = /** @type {ImportSource} */ (statement.source.value);
|
|
2509
2725
|
this.hooks.import.call(statement, source);
|
|
2510
2726
|
for (const specifier of statement.specifiers) {
|
|
@@ -2574,14 +2790,49 @@ class JavascriptParser extends Parser {
|
|
|
2574
2790
|
/**
|
|
2575
2791
|
* @param {ExportNamedDeclaration} statement statement
|
|
2576
2792
|
*/
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2793
|
+
modulePreWalkExportNamedDeclaration(statement) {
|
|
2794
|
+
if (!statement.source) return;
|
|
2795
|
+
const source = /** @type {ImportSource} */ (statement.source.value);
|
|
2796
|
+
this.hooks.exportImport.call(statement, source);
|
|
2797
|
+
if (statement.specifiers) {
|
|
2798
|
+
for (
|
|
2799
|
+
let specifierIndex = 0;
|
|
2800
|
+
specifierIndex < statement.specifiers.length;
|
|
2801
|
+
specifierIndex++
|
|
2802
|
+
) {
|
|
2803
|
+
const specifier = statement.specifiers[specifierIndex];
|
|
2804
|
+
switch (specifier.type) {
|
|
2805
|
+
case "ExportSpecifier": {
|
|
2806
|
+
const localName =
|
|
2807
|
+
/** @type {Identifier} */ (specifier.local).name ||
|
|
2808
|
+
/** @type {string} */ (
|
|
2809
|
+
/** @type {Literal} */ (specifier.local).value
|
|
2810
|
+
);
|
|
2811
|
+
const name =
|
|
2812
|
+
/** @type {Identifier} */
|
|
2813
|
+
(specifier.exported).name ||
|
|
2814
|
+
/** @type {string} */
|
|
2815
|
+
(/** @type {Literal} */ (specifier.exported).value);
|
|
2816
|
+
this.hooks.exportImportSpecifier.call(
|
|
2817
|
+
statement,
|
|
2818
|
+
source,
|
|
2819
|
+
localName,
|
|
2820
|
+
name,
|
|
2821
|
+
specifierIndex
|
|
2822
|
+
);
|
|
2823
|
+
break;
|
|
2824
|
+
}
|
|
2825
|
+
}
|
|
2826
|
+
}
|
|
2584
2827
|
}
|
|
2828
|
+
}
|
|
2829
|
+
|
|
2830
|
+
/**
|
|
2831
|
+
* @param {ExportNamedDeclaration} statement statement
|
|
2832
|
+
*/
|
|
2833
|
+
blockPreWalkExportNamedDeclaration(statement) {
|
|
2834
|
+
if (statement.source) return;
|
|
2835
|
+
this.hooks.export.call(statement);
|
|
2585
2836
|
if (
|
|
2586
2837
|
statement.declaration &&
|
|
2587
2838
|
!this.hooks.exportDeclaration.call(statement, statement.declaration)
|
|
@@ -2591,7 +2842,7 @@ class JavascriptParser extends Parser {
|
|
|
2591
2842
|
this.prevStatement = prev;
|
|
2592
2843
|
this.blockPreWalkStatement(statement.declaration);
|
|
2593
2844
|
let index = 0;
|
|
2594
|
-
this.enterDeclaration(statement.declaration, def => {
|
|
2845
|
+
this.enterDeclaration(statement.declaration, (def) => {
|
|
2595
2846
|
this.hooks.exportSpecifier.call(statement, def, def, index++);
|
|
2596
2847
|
});
|
|
2597
2848
|
}
|
|
@@ -2614,22 +2865,12 @@ class JavascriptParser extends Parser {
|
|
|
2614
2865
|
(specifier.exported).name ||
|
|
2615
2866
|
/** @type {string} */
|
|
2616
2867
|
(/** @type {Literal} */ (specifier.exported).value);
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
specifierIndex
|
|
2624
|
-
);
|
|
2625
|
-
} else {
|
|
2626
|
-
this.hooks.exportSpecifier.call(
|
|
2627
|
-
statement,
|
|
2628
|
-
localName,
|
|
2629
|
-
name,
|
|
2630
|
-
specifierIndex
|
|
2631
|
-
);
|
|
2632
|
-
}
|
|
2868
|
+
this.hooks.exportSpecifier.call(
|
|
2869
|
+
statement,
|
|
2870
|
+
localName,
|
|
2871
|
+
name,
|
|
2872
|
+
specifierIndex
|
|
2873
|
+
);
|
|
2633
2874
|
break;
|
|
2634
2875
|
}
|
|
2635
2876
|
}
|
|
@@ -2647,26 +2888,34 @@ class JavascriptParser extends Parser {
|
|
|
2647
2888
|
}
|
|
2648
2889
|
|
|
2649
2890
|
/**
|
|
2650
|
-
* @param {
|
|
2891
|
+
* @param {ExportDefaultDeclaration} statement statement
|
|
2651
2892
|
*/
|
|
2652
2893
|
blockPreWalkExportDefaultDeclaration(statement) {
|
|
2653
|
-
const prev = this.prevStatement;
|
|
2654
|
-
this.preWalkStatement(statement.declaration);
|
|
2655
|
-
this.prevStatement = prev;
|
|
2656
|
-
this.blockPreWalkStatement(statement.declaration);
|
|
2657
2894
|
if (
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2895
|
+
statement.declaration.type === "FunctionDeclaration" ||
|
|
2896
|
+
statement.declaration.type === "ClassDeclaration"
|
|
2897
|
+
) {
|
|
2898
|
+
const prev = this.prevStatement;
|
|
2899
|
+
|
|
2900
|
+
this.preWalkStatement(statement.declaration);
|
|
2901
|
+
this.prevStatement = prev;
|
|
2902
|
+
this.blockPreWalkStatement(statement.declaration);
|
|
2903
|
+
}
|
|
2904
|
+
|
|
2905
|
+
if (
|
|
2906
|
+
/** @type {MaybeNamedFunctionDeclaration | MaybeNamedClassDeclaration} */
|
|
2907
|
+
(statement.declaration).id &&
|
|
2661
2908
|
statement.declaration.type !== "FunctionExpression" &&
|
|
2662
2909
|
statement.declaration.type !== "ClassExpression"
|
|
2663
2910
|
) {
|
|
2664
2911
|
const declaration =
|
|
2665
|
-
/** @type {
|
|
2912
|
+
/** @type {MaybeNamedFunctionDeclaration | MaybeNamedClassDeclaration} */
|
|
2666
2913
|
(statement.declaration);
|
|
2914
|
+
|
|
2667
2915
|
this.hooks.exportSpecifier.call(
|
|
2668
2916
|
statement,
|
|
2669
|
-
|
|
2917
|
+
/** @type {Identifier} */
|
|
2918
|
+
(declaration.id).name,
|
|
2670
2919
|
"default",
|
|
2671
2920
|
undefined
|
|
2672
2921
|
);
|
|
@@ -2679,9 +2928,8 @@ class JavascriptParser extends Parser {
|
|
|
2679
2928
|
walkExportDefaultDeclaration(statement) {
|
|
2680
2929
|
this.hooks.export.call(statement);
|
|
2681
2930
|
if (
|
|
2682
|
-
/** @type {FunctionDeclaration | ClassDeclaration} */
|
|
2683
|
-
|
|
2684
|
-
).id &&
|
|
2931
|
+
/** @type {FunctionDeclaration | ClassDeclaration} */
|
|
2932
|
+
(statement.declaration).id &&
|
|
2685
2933
|
statement.declaration.type !== "FunctionExpression" &&
|
|
2686
2934
|
statement.declaration.type !== "ClassExpression"
|
|
2687
2935
|
) {
|
|
@@ -2699,34 +2947,19 @@ class JavascriptParser extends Parser {
|
|
|
2699
2947
|
statement.declaration.type === "FunctionDeclaration" ||
|
|
2700
2948
|
statement.declaration.type === "ClassDeclaration"
|
|
2701
2949
|
) {
|
|
2702
|
-
this.walkStatement(
|
|
2703
|
-
/** @type {FunctionDeclaration | ClassDeclaration} */
|
|
2704
|
-
(statement.declaration)
|
|
2705
|
-
);
|
|
2950
|
+
this.walkStatement(statement.declaration);
|
|
2706
2951
|
} else {
|
|
2707
2952
|
this.walkExpression(statement.declaration);
|
|
2708
2953
|
}
|
|
2709
2954
|
|
|
2710
|
-
|
|
2711
|
-
!this.hooks.exportExpression.call(
|
|
2712
|
-
statement,
|
|
2713
|
-
/** @type {TODO} */ (statement).declaration
|
|
2714
|
-
)
|
|
2715
|
-
) {
|
|
2716
|
-
this.hooks.exportSpecifier.call(
|
|
2717
|
-
statement,
|
|
2718
|
-
/** @type {TODO} */ (statement.declaration),
|
|
2719
|
-
"default",
|
|
2720
|
-
undefined
|
|
2721
|
-
);
|
|
2722
|
-
}
|
|
2955
|
+
this.hooks.exportExpression.call(statement, statement.declaration);
|
|
2723
2956
|
}
|
|
2724
2957
|
}
|
|
2725
2958
|
|
|
2726
2959
|
/**
|
|
2727
2960
|
* @param {ExportAllDeclaration} statement statement
|
|
2728
2961
|
*/
|
|
2729
|
-
|
|
2962
|
+
modulePreWalkExportAllDeclaration(statement) {
|
|
2730
2963
|
const source = /** @type {ImportSource} */ (statement.source.value);
|
|
2731
2964
|
const name = statement.exported
|
|
2732
2965
|
? /** @type {Identifier} */
|
|
@@ -2751,16 +2984,19 @@ class JavascriptParser extends Parser {
|
|
|
2751
2984
|
*/
|
|
2752
2985
|
blockPreWalkVariableDeclaration(statement) {
|
|
2753
2986
|
if (statement.kind === "var") return;
|
|
2987
|
+
|
|
2754
2988
|
const hookMap =
|
|
2755
2989
|
statement.kind === "const"
|
|
2756
2990
|
? this.hooks.varDeclarationConst
|
|
2757
|
-
:
|
|
2991
|
+
: statement.kind === "using" || statement.kind === "await using"
|
|
2992
|
+
? this.hooks.varDeclarationUsing
|
|
2993
|
+
: this.hooks.varDeclarationLet;
|
|
2758
2994
|
this._preWalkVariableDeclaration(statement, hookMap);
|
|
2759
2995
|
}
|
|
2760
2996
|
|
|
2761
2997
|
/**
|
|
2762
2998
|
* @param {VariableDeclaration} statement variable declaration
|
|
2763
|
-
* @param {
|
|
2999
|
+
* @param {HookMap<SyncBailHook<[Identifier], boolean | void>>} hookMap map of hooks
|
|
2764
3000
|
*/
|
|
2765
3001
|
_preWalkVariableDeclaration(statement, hookMap) {
|
|
2766
3002
|
for (const declarator of statement.declarations) {
|
|
@@ -2768,11 +3004,11 @@ class JavascriptParser extends Parser {
|
|
|
2768
3004
|
case "VariableDeclarator": {
|
|
2769
3005
|
this.preWalkVariableDeclarator(declarator);
|
|
2770
3006
|
if (!this.hooks.preDeclarator.call(declarator, statement)) {
|
|
2771
|
-
this.enterPattern(declarator.id, (name,
|
|
3007
|
+
this.enterPattern(declarator.id, (name, ident) => {
|
|
2772
3008
|
let hook = hookMap.get(name);
|
|
2773
|
-
if (hook === undefined || !hook.call(
|
|
3009
|
+
if (hook === undefined || !hook.call(ident)) {
|
|
2774
3010
|
hook = this.hooks.varDeclaration.get(name);
|
|
2775
|
-
if (hook === undefined || !hook.call(
|
|
3011
|
+
if (hook === undefined || !hook.call(ident)) {
|
|
2776
3012
|
this.defineVariable(name);
|
|
2777
3013
|
}
|
|
2778
3014
|
}
|
|
@@ -2786,32 +3022,55 @@ class JavascriptParser extends Parser {
|
|
|
2786
3022
|
|
|
2787
3023
|
/**
|
|
2788
3024
|
* @param {ObjectPattern} objectPattern object pattern
|
|
2789
|
-
* @returns {
|
|
3025
|
+
* @returns {DestructuringAssignmentProperties | undefined} set of names or undefined if not all keys are identifiers
|
|
2790
3026
|
*/
|
|
2791
3027
|
_preWalkObjectPattern(objectPattern) {
|
|
2792
|
-
/** @type {
|
|
3028
|
+
/** @type {DestructuringAssignmentProperties} */
|
|
2793
3029
|
const props = new Set();
|
|
2794
3030
|
const properties = objectPattern.properties;
|
|
2795
3031
|
for (let i = 0; i < properties.length; i++) {
|
|
2796
3032
|
const property = properties[i];
|
|
2797
3033
|
if (property.type !== "Property") return;
|
|
2798
|
-
if (property.shorthand
|
|
2799
|
-
|
|
3034
|
+
if (property.shorthand) {
|
|
3035
|
+
if (property.value.type === "Identifier") {
|
|
3036
|
+
this.scope.inShorthand = property.value.name;
|
|
3037
|
+
} else if (
|
|
3038
|
+
property.value.type === "AssignmentPattern" &&
|
|
3039
|
+
property.value.left.type === "Identifier"
|
|
3040
|
+
) {
|
|
3041
|
+
this.scope.inShorthand = property.value.left.name;
|
|
3042
|
+
}
|
|
2800
3043
|
}
|
|
2801
3044
|
const key = property.key;
|
|
2802
|
-
if (key.type === "Identifier") {
|
|
3045
|
+
if (key.type === "Identifier" && !property.computed) {
|
|
3046
|
+
const pattern =
|
|
3047
|
+
property.value.type === "ObjectPattern"
|
|
3048
|
+
? this._preWalkObjectPattern(property.value)
|
|
3049
|
+
: property.value.type === "ArrayPattern"
|
|
3050
|
+
? this._preWalkArrayPattern(property.value)
|
|
3051
|
+
: undefined;
|
|
2803
3052
|
props.add({
|
|
2804
3053
|
id: key.name,
|
|
2805
|
-
range: key.range,
|
|
3054
|
+
range: /** @type {Range} */ (key.range),
|
|
3055
|
+
loc: /** @type {SourceLocation} */ (key.loc),
|
|
3056
|
+
pattern,
|
|
2806
3057
|
shorthand: this.scope.inShorthand
|
|
2807
3058
|
});
|
|
2808
3059
|
} else {
|
|
2809
3060
|
const id = this.evaluateExpression(key);
|
|
2810
3061
|
const str = id.asString();
|
|
2811
3062
|
if (str) {
|
|
3063
|
+
const pattern =
|
|
3064
|
+
property.value.type === "ObjectPattern"
|
|
3065
|
+
? this._preWalkObjectPattern(property.value)
|
|
3066
|
+
: property.value.type === "ArrayPattern"
|
|
3067
|
+
? this._preWalkArrayPattern(property.value)
|
|
3068
|
+
: undefined;
|
|
2812
3069
|
props.add({
|
|
2813
3070
|
id: str,
|
|
2814
|
-
range: key.range,
|
|
3071
|
+
range: /** @type {Range} */ (key.range),
|
|
3072
|
+
loc: /** @type {SourceLocation} */ (key.loc),
|
|
3073
|
+
pattern,
|
|
2815
3074
|
shorthand: this.scope.inShorthand
|
|
2816
3075
|
});
|
|
2817
3076
|
} else {
|
|
@@ -2825,28 +3084,42 @@ class JavascriptParser extends Parser {
|
|
|
2825
3084
|
return props;
|
|
2826
3085
|
}
|
|
2827
3086
|
|
|
3087
|
+
/**
|
|
3088
|
+
* @param {ArrayPattern} arrayPattern array pattern
|
|
3089
|
+
* @returns {Set<DestructuringAssignmentProperty> | undefined} set of names or undefined if not all keys are identifiers
|
|
3090
|
+
*/
|
|
3091
|
+
_preWalkArrayPattern(arrayPattern) {
|
|
3092
|
+
/** @type {Set<DestructuringAssignmentProperty>} */
|
|
3093
|
+
const props = new Set();
|
|
3094
|
+
const elements = arrayPattern.elements;
|
|
3095
|
+
for (let i = 0; i < elements.length; i++) {
|
|
3096
|
+
const element = elements[i];
|
|
3097
|
+
if (!element) continue;
|
|
3098
|
+
if (element.type === "RestElement") return;
|
|
3099
|
+
const pattern =
|
|
3100
|
+
element.type === "ObjectPattern"
|
|
3101
|
+
? this._preWalkObjectPattern(element)
|
|
3102
|
+
: element.type === "ArrayPattern"
|
|
3103
|
+
? this._preWalkArrayPattern(element)
|
|
3104
|
+
: undefined;
|
|
3105
|
+
props.add({
|
|
3106
|
+
id: `${i}`,
|
|
3107
|
+
range: /** @type {Range} */ (element.range),
|
|
3108
|
+
loc: /** @type {SourceLocation} */ (element.loc),
|
|
3109
|
+
pattern,
|
|
3110
|
+
shorthand: false
|
|
3111
|
+
});
|
|
3112
|
+
}
|
|
3113
|
+
|
|
3114
|
+
return props;
|
|
3115
|
+
}
|
|
3116
|
+
|
|
2828
3117
|
/**
|
|
2829
3118
|
* @param {VariableDeclarator} declarator variable declarator
|
|
2830
3119
|
*/
|
|
2831
3120
|
preWalkVariableDeclarator(declarator) {
|
|
2832
|
-
if (
|
|
2833
|
-
|
|
2834
|
-
declarator.id.type !== "ObjectPattern" ||
|
|
2835
|
-
!this.destructuringAssignmentProperties
|
|
2836
|
-
)
|
|
2837
|
-
return;
|
|
2838
|
-
const keys = this._preWalkObjectPattern(declarator.id);
|
|
2839
|
-
|
|
2840
|
-
if (!keys) return;
|
|
2841
|
-
this.destructuringAssignmentProperties.set(
|
|
2842
|
-
declarator.init.type === "AwaitExpression"
|
|
2843
|
-
? declarator.init.argument
|
|
2844
|
-
: declarator.init,
|
|
2845
|
-
keys
|
|
2846
|
-
);
|
|
2847
|
-
|
|
2848
|
-
if (declarator.init.type === "AssignmentExpression") {
|
|
2849
|
-
this.preWalkAssignmentExpression(declarator.init);
|
|
3121
|
+
if (declarator.init) {
|
|
3122
|
+
this.enterDestructuringAssignment(declarator.id, declarator.init);
|
|
2850
3123
|
}
|
|
2851
3124
|
}
|
|
2852
3125
|
|
|
@@ -2887,7 +3160,7 @@ class JavascriptParser extends Parser {
|
|
|
2887
3160
|
}
|
|
2888
3161
|
|
|
2889
3162
|
/**
|
|
2890
|
-
* @param {ClassDeclaration} statement class declaration
|
|
3163
|
+
* @param {ClassDeclaration | MaybeNamedClassDeclaration} statement class declaration
|
|
2891
3164
|
*/
|
|
2892
3165
|
blockPreWalkClassDeclaration(statement) {
|
|
2893
3166
|
if (statement.id) {
|
|
@@ -2896,7 +3169,7 @@ class JavascriptParser extends Parser {
|
|
|
2896
3169
|
}
|
|
2897
3170
|
|
|
2898
3171
|
/**
|
|
2899
|
-
* @param {ClassDeclaration} statement class declaration
|
|
3172
|
+
* @param {ClassDeclaration | MaybeNamedClassDeclaration} statement class declaration
|
|
2900
3173
|
*/
|
|
2901
3174
|
walkClassDeclaration(statement) {
|
|
2902
3175
|
this.walkClass(statement);
|
|
@@ -2943,8 +3216,10 @@ class JavascriptParser extends Parser {
|
|
|
2943
3216
|
if (switchCase.test) {
|
|
2944
3217
|
this.walkExpression(switchCase.test);
|
|
2945
3218
|
}
|
|
3219
|
+
|
|
2946
3220
|
if (switchCase.consequent.length > 0) {
|
|
2947
3221
|
this.walkStatements(switchCase.consequent);
|
|
3222
|
+
this.scope.terminated = undefined;
|
|
2948
3223
|
}
|
|
2949
3224
|
}
|
|
2950
3225
|
});
|
|
@@ -2964,7 +3239,7 @@ class JavascriptParser extends Parser {
|
|
|
2964
3239
|
this.inBlockScope(() => {
|
|
2965
3240
|
// Error binding is optional in catch clause since ECMAScript 2019
|
|
2966
3241
|
if (catchClause.param !== null) {
|
|
2967
|
-
this.enterPattern(catchClause.param, ident => {
|
|
3242
|
+
this.enterPattern(catchClause.param, (ident) => {
|
|
2968
3243
|
this.defineVariable(ident);
|
|
2969
3244
|
});
|
|
2970
3245
|
this.walkPattern(catchClause.param);
|
|
@@ -2973,7 +3248,7 @@ class JavascriptParser extends Parser {
|
|
|
2973
3248
|
this.blockPreWalkStatement(catchClause.body);
|
|
2974
3249
|
this.prevStatement = prev;
|
|
2975
3250
|
this.walkStatement(catchClause.body);
|
|
2976
|
-
});
|
|
3251
|
+
}, true);
|
|
2977
3252
|
}
|
|
2978
3253
|
|
|
2979
3254
|
/**
|
|
@@ -3052,7 +3327,7 @@ class JavascriptParser extends Parser {
|
|
|
3052
3327
|
}
|
|
3053
3328
|
|
|
3054
3329
|
/**
|
|
3055
|
-
* @param {
|
|
3330
|
+
* @param {Expression | SpreadElement | PrivateIdentifier | Super} expression expression
|
|
3056
3331
|
*/
|
|
3057
3332
|
walkExpression(expression) {
|
|
3058
3333
|
switch (expression.type) {
|
|
@@ -3138,8 +3413,9 @@ class JavascriptParser extends Parser {
|
|
|
3138
3413
|
* @param {AwaitExpression} expression await expression
|
|
3139
3414
|
*/
|
|
3140
3415
|
walkAwaitExpression(expression) {
|
|
3141
|
-
if (this.scope.topLevelScope === true)
|
|
3416
|
+
if (this.scope.topLevelScope === true) {
|
|
3142
3417
|
this.hooks.topLevelAwait.call(expression);
|
|
3418
|
+
}
|
|
3143
3419
|
this.walkExpression(expression.argument);
|
|
3144
3420
|
}
|
|
3145
3421
|
|
|
@@ -3191,7 +3467,10 @@ class JavascriptParser extends Parser {
|
|
|
3191
3467
|
this.walkIdentifier(prop.value);
|
|
3192
3468
|
this.scope.inShorthand = false;
|
|
3193
3469
|
} else {
|
|
3194
|
-
this.walkExpression(
|
|
3470
|
+
this.walkExpression(
|
|
3471
|
+
/** @type {Exclude<Property["value"], AssignmentPattern | ObjectPattern | ArrayPattern | RestElement>} */
|
|
3472
|
+
(prop.value)
|
|
3473
|
+
);
|
|
3195
3474
|
}
|
|
3196
3475
|
}
|
|
3197
3476
|
|
|
@@ -3212,15 +3491,14 @@ class JavascriptParser extends Parser {
|
|
|
3212
3491
|
for (const param of expression.params) {
|
|
3213
3492
|
this.walkPattern(param);
|
|
3214
3493
|
}
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
}
|
|
3494
|
+
|
|
3495
|
+
this.detectMode(expression.body.body);
|
|
3496
|
+
|
|
3497
|
+
const prev = this.prevStatement;
|
|
3498
|
+
|
|
3499
|
+
this.preWalkStatement(expression.body);
|
|
3500
|
+
this.prevStatement = prev;
|
|
3501
|
+
this.walkStatement(expression.body);
|
|
3224
3502
|
});
|
|
3225
3503
|
this.scope.topLevelScope = wasTopLevel;
|
|
3226
3504
|
}
|
|
@@ -3377,16 +3655,17 @@ class JavascriptParser extends Parser {
|
|
|
3377
3655
|
return;
|
|
3378
3656
|
}
|
|
3379
3657
|
this.walkExpression(expression.right);
|
|
3380
|
-
this.enterPattern(expression.left, (name,
|
|
3658
|
+
this.enterPattern(expression.left, (name, _decl) => {
|
|
3381
3659
|
if (!this.callHooksForName(this.hooks.assign, name, expression)) {
|
|
3382
|
-
this.walkExpression(
|
|
3660
|
+
this.walkExpression(
|
|
3661
|
+
/** @type {MemberExpression} */
|
|
3662
|
+
(expression.left)
|
|
3663
|
+
);
|
|
3383
3664
|
}
|
|
3384
3665
|
});
|
|
3385
|
-
|
|
3386
|
-
}
|
|
3387
|
-
if (expression.left.type.endsWith("Pattern")) {
|
|
3666
|
+
} else if (expression.left.type.endsWith("Pattern")) {
|
|
3388
3667
|
this.walkExpression(expression.right);
|
|
3389
|
-
this.enterPattern(expression.left, (name,
|
|
3668
|
+
this.enterPattern(expression.left, (name, _decl) => {
|
|
3390
3669
|
if (!this.callHooksForName(this.hooks.assign, name, expression)) {
|
|
3391
3670
|
this.defineVariable(name);
|
|
3392
3671
|
}
|
|
@@ -3412,7 +3691,10 @@ class JavascriptParser extends Parser {
|
|
|
3412
3691
|
this.walkExpression(expression.left);
|
|
3413
3692
|
} else {
|
|
3414
3693
|
this.walkExpression(expression.right);
|
|
3415
|
-
this.walkExpression(
|
|
3694
|
+
this.walkExpression(
|
|
3695
|
+
/** @type {Exclude<AssignmentExpression["left"], Identifier | RestElement | MemberExpression | ObjectPattern | ArrayPattern | AssignmentPattern>} */
|
|
3696
|
+
(expression.left)
|
|
3697
|
+
);
|
|
3416
3698
|
}
|
|
3417
3699
|
}
|
|
3418
3700
|
|
|
@@ -3424,6 +3706,7 @@ class JavascriptParser extends Parser {
|
|
|
3424
3706
|
if (result === undefined) {
|
|
3425
3707
|
this.walkExpression(expression.test);
|
|
3426
3708
|
this.walkExpression(expression.consequent);
|
|
3709
|
+
|
|
3427
3710
|
if (expression.alternate) {
|
|
3428
3711
|
this.walkExpression(expression.alternate);
|
|
3429
3712
|
}
|
|
@@ -3513,9 +3796,9 @@ class JavascriptParser extends Parser {
|
|
|
3513
3796
|
_walkIIFE(functionExpression, options, currentThis) {
|
|
3514
3797
|
/**
|
|
3515
3798
|
* @param {Expression | SpreadElement} argOrThis arg or this
|
|
3516
|
-
* @returns {string |
|
|
3799
|
+
* @returns {string | VariableInfo | undefined} var info
|
|
3517
3800
|
*/
|
|
3518
|
-
const getVarInfo = argOrThis => {
|
|
3801
|
+
const getVarInfo = (argOrThis) => {
|
|
3519
3802
|
const renameIdentifier = this.getRenameIdentifier(argOrThis);
|
|
3520
3803
|
if (
|
|
3521
3804
|
renameIdentifier &&
|
|
@@ -3597,19 +3880,19 @@ class JavascriptParser extends Parser {
|
|
|
3597
3880
|
* @param {FunctionExpression | ArrowFunctionExpression} fn function
|
|
3598
3881
|
* @returns {boolean} true when simple function
|
|
3599
3882
|
*/
|
|
3600
|
-
const isSimpleFunction = fn =>
|
|
3601
|
-
fn.params.every(p => p.type === "Identifier");
|
|
3883
|
+
const isSimpleFunction = (fn) =>
|
|
3884
|
+
fn.params.every((p) => p.type === "Identifier");
|
|
3602
3885
|
if (
|
|
3603
3886
|
expression.callee.type === "MemberExpression" &&
|
|
3604
3887
|
expression.callee.object.type.endsWith("FunctionExpression") &&
|
|
3605
3888
|
!expression.callee.computed &&
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3889
|
+
/** @type {boolean} */
|
|
3890
|
+
(
|
|
3891
|
+
/** @type {Identifier} */
|
|
3892
|
+
(expression.callee.property).name === "call" ||
|
|
3893
|
+
/** @type {Identifier} */
|
|
3894
|
+
(expression.callee.property).name === "bind"
|
|
3895
|
+
) &&
|
|
3613
3896
|
expression.arguments.length > 0 &&
|
|
3614
3897
|
isSimpleFunction(
|
|
3615
3898
|
/** @type {FunctionExpression | ArrowFunctionExpression} */
|
|
@@ -3655,10 +3938,20 @@ class JavascriptParser extends Parser {
|
|
|
3655
3938
|
);
|
|
3656
3939
|
if (result === true) return;
|
|
3657
3940
|
}
|
|
3941
|
+
// import("./m").then(m => { ... })
|
|
3942
|
+
if (
|
|
3943
|
+
expression.callee.object.type === "ImportExpression" &&
|
|
3944
|
+
expression.callee.property.type === "Identifier" &&
|
|
3945
|
+
expression.callee.property.name === "then"
|
|
3946
|
+
) {
|
|
3947
|
+
const result = this.hooks.importCall.call(
|
|
3948
|
+
expression.callee.object,
|
|
3949
|
+
expression
|
|
3950
|
+
);
|
|
3951
|
+
if (result === true) return;
|
|
3952
|
+
}
|
|
3658
3953
|
}
|
|
3659
|
-
const callee = this.evaluateExpression(
|
|
3660
|
-
/** @type {TODO} */ (expression.callee)
|
|
3661
|
-
);
|
|
3954
|
+
const callee = this.evaluateExpression(expression.callee);
|
|
3662
3955
|
if (callee.isIdentifier()) {
|
|
3663
3956
|
const result1 = this.callHooksForInfo(
|
|
3664
3957
|
this.hooks.callMemberChain,
|
|
@@ -3687,8 +3980,9 @@ class JavascriptParser extends Parser {
|
|
|
3687
3980
|
if (expression.callee.type === "MemberExpression") {
|
|
3688
3981
|
// because of call context we need to walk the call context as expression
|
|
3689
3982
|
this.walkExpression(expression.callee.object);
|
|
3690
|
-
if (expression.callee.computed === true)
|
|
3983
|
+
if (expression.callee.computed === true) {
|
|
3691
3984
|
this.walkExpression(expression.callee.property);
|
|
3985
|
+
}
|
|
3692
3986
|
} else {
|
|
3693
3987
|
this.walkExpression(expression.callee);
|
|
3694
3988
|
}
|
|
@@ -3730,7 +4024,7 @@ class JavascriptParser extends Parser {
|
|
|
3730
4024
|
expression,
|
|
3731
4025
|
exprInfo.name,
|
|
3732
4026
|
exprInfo.rootInfo,
|
|
3733
|
-
members
|
|
4027
|
+
[...members],
|
|
3734
4028
|
() =>
|
|
3735
4029
|
this.callHooksForInfo(
|
|
3736
4030
|
this.hooks.unhandledExpressionMemberChain,
|
|
@@ -3764,11 +4058,12 @@ class JavascriptParser extends Parser {
|
|
|
3764
4058
|
}
|
|
3765
4059
|
|
|
3766
4060
|
/**
|
|
3767
|
-
* @
|
|
4061
|
+
* @template R
|
|
4062
|
+
* @param {MemberExpression} expression member expression
|
|
3768
4063
|
* @param {string} name name
|
|
3769
4064
|
* @param {string | VariableInfo} rootInfo root info
|
|
3770
|
-
* @param {
|
|
3771
|
-
* @param {
|
|
4065
|
+
* @param {Members} members members
|
|
4066
|
+
* @param {() => R | undefined} onUnhandled on unhandled callback
|
|
3772
4067
|
*/
|
|
3773
4068
|
walkMemberExpressionWithExpressionName(
|
|
3774
4069
|
expression,
|
|
@@ -3781,7 +4076,9 @@ class JavascriptParser extends Parser {
|
|
|
3781
4076
|
// optimize the case where expression.object is a MemberExpression too.
|
|
3782
4077
|
// we can keep info here when calling walkMemberExpression directly
|
|
3783
4078
|
const property =
|
|
3784
|
-
|
|
4079
|
+
/** @type {Identifier} */
|
|
4080
|
+
(expression.property).name ||
|
|
4081
|
+
`${/** @type {Literal} */ (expression.property).value}`;
|
|
3785
4082
|
name = name.slice(0, -property.length - 1);
|
|
3786
4083
|
members.pop();
|
|
3787
4084
|
const result = this.callHooksForInfo(
|
|
@@ -3847,8 +4144,8 @@ class JavascriptParser extends Parser {
|
|
|
3847
4144
|
* @template R
|
|
3848
4145
|
* @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
|
|
3849
4146
|
* @param {Expression | Super} expr expression info
|
|
3850
|
-
* @param {(
|
|
3851
|
-
* @param {(
|
|
4147
|
+
* @param {((name: string, rootInfo: string | ScopeInfo | VariableInfo, getMembers: () => Members) => R) | undefined} fallback callback when variable in not handled by hooks
|
|
4148
|
+
* @param {((result?: string) => R | undefined) | undefined} defined callback when variable is defined
|
|
3852
4149
|
* @param {AsArray<T>} args args for the hook
|
|
3853
4150
|
* @returns {R | undefined} result of hook
|
|
3854
4151
|
*/
|
|
@@ -3869,7 +4166,7 @@ class JavascriptParser extends Parser {
|
|
|
3869
4166
|
hookMap,
|
|
3870
4167
|
members.length === 0 ? exprName.rootInfo : exprName.name,
|
|
3871
4168
|
fallback &&
|
|
3872
|
-
(name => fallback(name, exprName.rootInfo, exprName.getMembers)),
|
|
4169
|
+
((name) => fallback(name, exprName.rootInfo, exprName.getMembers)),
|
|
3873
4170
|
defined && (() => defined(exprName.name)),
|
|
3874
4171
|
...args
|
|
3875
4172
|
);
|
|
@@ -3899,7 +4196,7 @@ class JavascriptParser extends Parser {
|
|
|
3899
4196
|
* @template R
|
|
3900
4197
|
* @param {HookMap<SyncBailHook<T, R>>} hookMap hooks that should be called
|
|
3901
4198
|
* @param {ExportedVariableInfo} info variable info
|
|
3902
|
-
* @param
|
|
4199
|
+
* @param {AsArray<T>} args args for the hook
|
|
3903
4200
|
* @returns {R | undefined} result of hook
|
|
3904
4201
|
*/
|
|
3905
4202
|
callHooksForInfo(hookMap, info, ...args) {
|
|
@@ -3917,8 +4214,8 @@ class JavascriptParser extends Parser {
|
|
|
3917
4214
|
* @template R
|
|
3918
4215
|
* @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
|
|
3919
4216
|
* @param {ExportedVariableInfo} info variable info
|
|
3920
|
-
* @param {(
|
|
3921
|
-
* @param {(
|
|
4217
|
+
* @param {((name: string) => R | undefined) | undefined} fallback callback when variable in not handled by hooks
|
|
4218
|
+
* @param {((result?: string) => R | undefined) | undefined} defined callback when variable is defined
|
|
3922
4219
|
* @param {AsArray<T>} args args for the hook
|
|
3923
4220
|
* @returns {R | undefined} result of hook
|
|
3924
4221
|
*/
|
|
@@ -3944,13 +4241,13 @@ class JavascriptParser extends Parser {
|
|
|
3944
4241
|
}
|
|
3945
4242
|
tagInfo = tagInfo.next;
|
|
3946
4243
|
}
|
|
3947
|
-
if (info.
|
|
4244
|
+
if (!info.isFree() && !info.isTagged()) {
|
|
3948
4245
|
if (defined !== undefined) {
|
|
3949
4246
|
return defined();
|
|
3950
4247
|
}
|
|
3951
4248
|
return;
|
|
3952
4249
|
}
|
|
3953
|
-
name = info.
|
|
4250
|
+
name = info.name;
|
|
3954
4251
|
}
|
|
3955
4252
|
const hook = hookMap.get(name);
|
|
3956
4253
|
if (hook !== undefined) {
|
|
@@ -3967,8 +4264,8 @@ class JavascriptParser extends Parser {
|
|
|
3967
4264
|
* @template R
|
|
3968
4265
|
* @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
|
|
3969
4266
|
* @param {string} name key in map
|
|
3970
|
-
* @param {(
|
|
3971
|
-
* @param {(
|
|
4267
|
+
* @param {((value: string) => R | undefined) | undefined} fallback callback when variable in not handled by hooks
|
|
4268
|
+
* @param {(() => R) | undefined} defined callback when variable is defined
|
|
3972
4269
|
* @param {AsArray<T>} args args for the hook
|
|
3973
4270
|
* @returns {R | undefined} result of hook
|
|
3974
4271
|
*/
|
|
@@ -3984,8 +4281,8 @@ class JavascriptParser extends Parser {
|
|
|
3984
4281
|
|
|
3985
4282
|
/**
|
|
3986
4283
|
* @deprecated
|
|
3987
|
-
* @param {
|
|
3988
|
-
* @param {
|
|
4284
|
+
* @param {(string | Pattern | Property)[]} params scope params
|
|
4285
|
+
* @param {() => void} fn inner function
|
|
3989
4286
|
* @returns {void}
|
|
3990
4287
|
*/
|
|
3991
4288
|
inScope(params, fn) {
|
|
@@ -3997,12 +4294,13 @@ class JavascriptParser extends Parser {
|
|
|
3997
4294
|
inTaggedTemplateTag: false,
|
|
3998
4295
|
isStrict: oldScope.isStrict,
|
|
3999
4296
|
isAsmJs: oldScope.isAsmJs,
|
|
4297
|
+
terminated: undefined,
|
|
4000
4298
|
definitions: oldScope.definitions.createChild()
|
|
4001
4299
|
};
|
|
4002
4300
|
|
|
4003
4301
|
this.undefineVariable("this");
|
|
4004
4302
|
|
|
4005
|
-
this.enterPatterns(params, ident => {
|
|
4303
|
+
this.enterPatterns(params, (ident) => {
|
|
4006
4304
|
this.defineVariable(ident);
|
|
4007
4305
|
});
|
|
4008
4306
|
|
|
@@ -4014,7 +4312,7 @@ class JavascriptParser extends Parser {
|
|
|
4014
4312
|
/**
|
|
4015
4313
|
* @param {boolean} hasThis true, when this is defined
|
|
4016
4314
|
* @param {Identifier[]} params scope params
|
|
4017
|
-
* @param {
|
|
4315
|
+
* @param {() => void} fn inner function
|
|
4018
4316
|
* @returns {void}
|
|
4019
4317
|
*/
|
|
4020
4318
|
inClassScope(hasThis, params, fn) {
|
|
@@ -4026,6 +4324,7 @@ class JavascriptParser extends Parser {
|
|
|
4026
4324
|
inTaggedTemplateTag: false,
|
|
4027
4325
|
isStrict: oldScope.isStrict,
|
|
4028
4326
|
isAsmJs: oldScope.isAsmJs,
|
|
4327
|
+
terminated: undefined,
|
|
4029
4328
|
definitions: oldScope.definitions.createChild()
|
|
4030
4329
|
};
|
|
4031
4330
|
|
|
@@ -4033,7 +4332,7 @@ class JavascriptParser extends Parser {
|
|
|
4033
4332
|
this.undefineVariable("this");
|
|
4034
4333
|
}
|
|
4035
4334
|
|
|
4036
|
-
this.enterPatterns(params, ident => {
|
|
4335
|
+
this.enterPatterns(params, (ident) => {
|
|
4037
4336
|
this.defineVariable(ident);
|
|
4038
4337
|
});
|
|
4039
4338
|
|
|
@@ -4045,7 +4344,7 @@ class JavascriptParser extends Parser {
|
|
|
4045
4344
|
/**
|
|
4046
4345
|
* @param {boolean} hasThis true, when this is defined
|
|
4047
4346
|
* @param {(Pattern | string)[]} params scope params
|
|
4048
|
-
* @param {
|
|
4347
|
+
* @param {() => void} fn inner function
|
|
4049
4348
|
* @returns {void}
|
|
4050
4349
|
*/
|
|
4051
4350
|
inFunctionScope(hasThis, params, fn) {
|
|
@@ -4057,6 +4356,7 @@ class JavascriptParser extends Parser {
|
|
|
4057
4356
|
inTaggedTemplateTag: false,
|
|
4058
4357
|
isStrict: oldScope.isStrict,
|
|
4059
4358
|
isAsmJs: oldScope.isAsmJs,
|
|
4359
|
+
terminated: undefined,
|
|
4060
4360
|
definitions: oldScope.definitions.createChild()
|
|
4061
4361
|
};
|
|
4062
4362
|
|
|
@@ -4064,7 +4364,7 @@ class JavascriptParser extends Parser {
|
|
|
4064
4364
|
this.undefineVariable("this");
|
|
4065
4365
|
}
|
|
4066
4366
|
|
|
4067
|
-
this.enterPatterns(params, ident => {
|
|
4367
|
+
this.enterPatterns(params, (ident) => {
|
|
4068
4368
|
this.defineVariable(ident);
|
|
4069
4369
|
});
|
|
4070
4370
|
|
|
@@ -4074,10 +4374,11 @@ class JavascriptParser extends Parser {
|
|
|
4074
4374
|
}
|
|
4075
4375
|
|
|
4076
4376
|
/**
|
|
4077
|
-
* @param {
|
|
4377
|
+
* @param {() => void} fn inner function
|
|
4378
|
+
* @param {boolean} inExecutedPath executed state
|
|
4078
4379
|
* @returns {void}
|
|
4079
4380
|
*/
|
|
4080
|
-
inBlockScope(fn) {
|
|
4381
|
+
inBlockScope(fn, inExecutedPath = false) {
|
|
4081
4382
|
const oldScope = this.scope;
|
|
4082
4383
|
this.scope = {
|
|
4083
4384
|
topLevelScope: oldScope.topLevelScope,
|
|
@@ -4086,16 +4387,23 @@ class JavascriptParser extends Parser {
|
|
|
4086
4387
|
inTaggedTemplateTag: false,
|
|
4087
4388
|
isStrict: oldScope.isStrict,
|
|
4088
4389
|
isAsmJs: oldScope.isAsmJs,
|
|
4390
|
+
terminated: oldScope.terminated,
|
|
4089
4391
|
definitions: oldScope.definitions.createChild()
|
|
4090
4392
|
};
|
|
4091
4393
|
|
|
4092
4394
|
fn();
|
|
4093
4395
|
|
|
4396
|
+
const terminated = this.scope.terminated;
|
|
4397
|
+
|
|
4398
|
+
if (inExecutedPath && terminated) {
|
|
4399
|
+
oldScope.terminated = terminated;
|
|
4400
|
+
}
|
|
4401
|
+
|
|
4094
4402
|
this.scope = oldScope;
|
|
4095
4403
|
}
|
|
4096
4404
|
|
|
4097
4405
|
/**
|
|
4098
|
-
* @param {
|
|
4406
|
+
* @param {(Directive | Statement | ModuleDeclaration)[]} statements statements
|
|
4099
4407
|
*/
|
|
4100
4408
|
detectMode(statements) {
|
|
4101
4409
|
const isLiteral =
|
|
@@ -4228,7 +4536,7 @@ class JavascriptParser extends Parser {
|
|
|
4228
4536
|
}
|
|
4229
4537
|
|
|
4230
4538
|
/**
|
|
4231
|
-
* @param {Expression | SpreadElement | PrivateIdentifier} expression expression node
|
|
4539
|
+
* @param {Expression | SpreadElement | PrivateIdentifier | Super} expression expression node
|
|
4232
4540
|
* @returns {BasicEvaluatedExpression} evaluation result
|
|
4233
4541
|
*/
|
|
4234
4542
|
evaluateExpression(expression) {
|
|
@@ -4242,6 +4550,7 @@ class JavascriptParser extends Parser {
|
|
|
4242
4550
|
}
|
|
4243
4551
|
}
|
|
4244
4552
|
} catch (err) {
|
|
4553
|
+
// eslint-disable-next-line no-console
|
|
4245
4554
|
console.warn(err);
|
|
4246
4555
|
// ignore error
|
|
4247
4556
|
}
|
|
@@ -4272,9 +4581,11 @@ class JavascriptParser extends Parser {
|
|
|
4272
4581
|
);
|
|
4273
4582
|
}
|
|
4274
4583
|
|
|
4584
|
+
/** @typedef {{ range?: Range, value: string, code: boolean, conditional: false | CalculatedStringResult[] }} CalculatedStringResult */
|
|
4585
|
+
|
|
4275
4586
|
/**
|
|
4276
4587
|
* @param {Expression} expression expression
|
|
4277
|
-
* @returns {
|
|
4588
|
+
* @returns {CalculatedStringResult} result
|
|
4278
4589
|
*/
|
|
4279
4590
|
parseCalculatedString(expression) {
|
|
4280
4591
|
switch (expression.type) {
|
|
@@ -4322,6 +4633,7 @@ class JavascriptParser extends Parser {
|
|
|
4322
4633
|
case "ConditionalExpression": {
|
|
4323
4634
|
const consequent = this.parseCalculatedString(expression.consequent);
|
|
4324
4635
|
const alternate = this.parseCalculatedString(expression.alternate);
|
|
4636
|
+
/** @type {CalculatedStringResult[]} */
|
|
4325
4637
|
const items = [];
|
|
4326
4638
|
if (consequent.conditional) {
|
|
4327
4639
|
items.push(...consequent.conditional);
|
|
@@ -4366,26 +4678,44 @@ class JavascriptParser extends Parser {
|
|
|
4366
4678
|
* @returns {ParserState} the parser state
|
|
4367
4679
|
*/
|
|
4368
4680
|
parse(source, state) {
|
|
4369
|
-
let ast;
|
|
4370
|
-
/** @type {import("acorn").Comment[]} */
|
|
4371
|
-
let comments;
|
|
4372
|
-
const semicolons = new Set();
|
|
4373
4681
|
if (source === null) {
|
|
4374
4682
|
throw new Error("source must not be null");
|
|
4375
4683
|
}
|
|
4684
|
+
|
|
4376
4685
|
if (Buffer.isBuffer(source)) {
|
|
4377
|
-
source = source.toString("
|
|
4686
|
+
source = source.toString("utf8");
|
|
4378
4687
|
}
|
|
4688
|
+
|
|
4689
|
+
let ast;
|
|
4690
|
+
/** @type {Comment[]} */
|
|
4691
|
+
let comments;
|
|
4692
|
+
/** @type {Set<number>} */
|
|
4693
|
+
let semicolons;
|
|
4694
|
+
|
|
4379
4695
|
if (typeof source === "object") {
|
|
4696
|
+
semicolons = new Set();
|
|
4697
|
+
|
|
4380
4698
|
ast = /** @type {Program} */ (source);
|
|
4381
4699
|
comments = source.comments;
|
|
4700
|
+
if (source.semicolons) {
|
|
4701
|
+
// Forward semicolon information from the preparsed AST if present
|
|
4702
|
+
// This ensures the output is consistent with that of a fresh AST
|
|
4703
|
+
for (const pos of source.semicolons) {
|
|
4704
|
+
semicolons.add(pos);
|
|
4705
|
+
}
|
|
4706
|
+
}
|
|
4382
4707
|
} else {
|
|
4383
|
-
comments =
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4708
|
+
({ ast, comments, semicolons } = JavascriptParser._parse(
|
|
4709
|
+
source,
|
|
4710
|
+
{
|
|
4711
|
+
sourceType: this.sourceType,
|
|
4712
|
+
locations: true,
|
|
4713
|
+
ranges: true,
|
|
4714
|
+
comments: true,
|
|
4715
|
+
semicolons: true
|
|
4716
|
+
},
|
|
4717
|
+
this.options.parse
|
|
4718
|
+
));
|
|
4389
4719
|
}
|
|
4390
4720
|
|
|
4391
4721
|
const oldScope = this.scope;
|
|
@@ -4401,9 +4731,9 @@ class JavascriptParser extends Parser {
|
|
|
4401
4731
|
inTaggedTemplateTag: false,
|
|
4402
4732
|
isStrict: false,
|
|
4403
4733
|
isAsmJs: false,
|
|
4734
|
+
terminated: undefined,
|
|
4404
4735
|
definitions: new StackedMap()
|
|
4405
4736
|
};
|
|
4406
|
-
/** @type {ParserState} */
|
|
4407
4737
|
this.state = state;
|
|
4408
4738
|
this.comments = comments;
|
|
4409
4739
|
this.semicolons = semicolons;
|
|
@@ -4412,6 +4742,7 @@ class JavascriptParser extends Parser {
|
|
|
4412
4742
|
if (this.hooks.program.call(ast, comments) === undefined) {
|
|
4413
4743
|
this.destructuringAssignmentProperties = new WeakMap();
|
|
4414
4744
|
this.detectMode(ast.body);
|
|
4745
|
+
this.modulePreWalkStatements(ast.body);
|
|
4415
4746
|
this.preWalkStatements(ast.body);
|
|
4416
4747
|
this.prevStatement = undefined;
|
|
4417
4748
|
this.blockPreWalkStatements(ast.body);
|
|
@@ -4421,7 +4752,6 @@ class JavascriptParser extends Parser {
|
|
|
4421
4752
|
}
|
|
4422
4753
|
this.hooks.finish.call(ast, comments);
|
|
4423
4754
|
this.scope = oldScope;
|
|
4424
|
-
/** @type {ParserState} */
|
|
4425
4755
|
this.state = oldState;
|
|
4426
4756
|
this.comments = oldComments;
|
|
4427
4757
|
this.semicolons = oldSemicolons;
|
|
@@ -4435,10 +4765,11 @@ class JavascriptParser extends Parser {
|
|
|
4435
4765
|
* @returns {BasicEvaluatedExpression} evaluation result
|
|
4436
4766
|
*/
|
|
4437
4767
|
evaluate(source) {
|
|
4438
|
-
const ast = JavascriptParser._parse(
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4768
|
+
const { ast } = JavascriptParser._parse(
|
|
4769
|
+
`(${source})`,
|
|
4770
|
+
{ sourceType: this.sourceType },
|
|
4771
|
+
this.options.parse
|
|
4772
|
+
);
|
|
4442
4773
|
if (ast.body.length !== 1 || ast.body[0].type !== "ExpressionStatement") {
|
|
4443
4774
|
throw new Error("evaluate: Source is not a expression");
|
|
4444
4775
|
}
|
|
@@ -4446,7 +4777,7 @@ class JavascriptParser extends Parser {
|
|
|
4446
4777
|
}
|
|
4447
4778
|
|
|
4448
4779
|
/**
|
|
4449
|
-
* @param {Expression | Declaration | PrivateIdentifier | null | undefined} expr an expression
|
|
4780
|
+
* @param {Expression | Declaration | PrivateIdentifier | MaybeNamedFunctionDeclaration | MaybeNamedClassDeclaration | null | undefined} expr an expression
|
|
4450
4781
|
* @param {number} commentsStartPos source position from which annotation comments are checked
|
|
4451
4782
|
* @returns {boolean} true, when the expression is pure
|
|
4452
4783
|
*/
|
|
@@ -4467,14 +4798,20 @@ class JavascriptParser extends Parser {
|
|
|
4467
4798
|
) {
|
|
4468
4799
|
return false;
|
|
4469
4800
|
}
|
|
4470
|
-
const items =
|
|
4471
|
-
|
|
4472
|
-
(
|
|
4473
|
-
|
|
4801
|
+
const items = expr.body.body;
|
|
4802
|
+
return items.every((item) => {
|
|
4803
|
+
if (item.type === "StaticBlock") {
|
|
4804
|
+
return false;
|
|
4805
|
+
}
|
|
4806
|
+
|
|
4474
4807
|
if (
|
|
4475
4808
|
item.computed &&
|
|
4476
4809
|
item.key &&
|
|
4477
|
-
!this.isPure(
|
|
4810
|
+
!this.isPure(
|
|
4811
|
+
item.key,
|
|
4812
|
+
/** @type {Range} */
|
|
4813
|
+
(item.range)[0]
|
|
4814
|
+
)
|
|
4478
4815
|
) {
|
|
4479
4816
|
return false;
|
|
4480
4817
|
}
|
|
@@ -4484,16 +4821,14 @@ class JavascriptParser extends Parser {
|
|
|
4484
4821
|
item.value &&
|
|
4485
4822
|
!this.isPure(
|
|
4486
4823
|
item.value,
|
|
4487
|
-
item.key
|
|
4824
|
+
item.key
|
|
4825
|
+
? /** @type {Range} */ (item.key.range)[1]
|
|
4826
|
+
: /** @type {Range} */ (item.range)[0]
|
|
4488
4827
|
)
|
|
4489
4828
|
) {
|
|
4490
4829
|
return false;
|
|
4491
4830
|
}
|
|
4492
4831
|
|
|
4493
|
-
if (item.type === "StaticBlock") {
|
|
4494
|
-
return false;
|
|
4495
|
-
}
|
|
4496
|
-
|
|
4497
4832
|
if (
|
|
4498
4833
|
expr.superClass &&
|
|
4499
4834
|
item.type === "MethodDefinition" &&
|
|
@@ -4517,7 +4852,7 @@ class JavascriptParser extends Parser {
|
|
|
4517
4852
|
return true;
|
|
4518
4853
|
|
|
4519
4854
|
case "VariableDeclaration":
|
|
4520
|
-
return expr.declarations.every(decl =>
|
|
4855
|
+
return expr.declarations.every((decl) =>
|
|
4521
4856
|
this.isPure(decl.init, /** @type {Range} */ (decl.range)[0])
|
|
4522
4857
|
);
|
|
4523
4858
|
|
|
@@ -4541,7 +4876,7 @@ class JavascriptParser extends Parser {
|
|
|
4541
4876
|
);
|
|
4542
4877
|
|
|
4543
4878
|
case "SequenceExpression":
|
|
4544
|
-
return expr.expressions.every(expr => {
|
|
4879
|
+
return expr.expressions.every((expr) => {
|
|
4545
4880
|
const pureFlag = this.isPure(expr, commentsStartPos);
|
|
4546
4881
|
commentsStartPos = /** @type {Range} */ (expr.range)[1];
|
|
4547
4882
|
return pureFlag;
|
|
@@ -4554,13 +4889,13 @@ class JavascriptParser extends Parser {
|
|
|
4554
4889
|
commentsStartPos,
|
|
4555
4890
|
/** @type {Range} */ (expr.range)[0]
|
|
4556
4891
|
]).some(
|
|
4557
|
-
comment =>
|
|
4892
|
+
(comment) =>
|
|
4558
4893
|
comment.type === "Block" &&
|
|
4559
4894
|
/^\s*(#|@)__PURE__\s*$/.test(comment.value)
|
|
4560
4895
|
);
|
|
4561
4896
|
if (!pureFlag) return false;
|
|
4562
4897
|
commentsStartPos = /** @type {Range} */ (expr.callee.range)[1];
|
|
4563
|
-
return expr.arguments.every(arg => {
|
|
4898
|
+
return expr.arguments.every((arg) => {
|
|
4564
4899
|
if (arg.type === "SpreadElement") return false;
|
|
4565
4900
|
const pureFlag = this.isPure(arg, commentsStartPos);
|
|
4566
4901
|
commentsStartPos = /** @type {Range} */ (arg.range)[1];
|
|
@@ -4666,8 +5001,8 @@ class JavascriptParser extends Parser {
|
|
|
4666
5001
|
|
|
4667
5002
|
/**
|
|
4668
5003
|
* @param {string} name name
|
|
4669
|
-
* @param {
|
|
4670
|
-
* @returns {
|
|
5004
|
+
* @param {Tag} tag tag info
|
|
5005
|
+
* @returns {TagData | undefined} tag data
|
|
4671
5006
|
*/
|
|
4672
5007
|
getTagData(name, tag) {
|
|
4673
5008
|
const info = this.scope.definitions.get(name);
|
|
@@ -4682,27 +5017,33 @@ class JavascriptParser extends Parser {
|
|
|
4682
5017
|
|
|
4683
5018
|
/**
|
|
4684
5019
|
* @param {string} name name
|
|
4685
|
-
* @param {
|
|
4686
|
-
* @param {
|
|
5020
|
+
* @param {Tag} tag tag info
|
|
5021
|
+
* @param {TagData=} data data
|
|
5022
|
+
* @param {VariableInfoFlagsType=} flags flags
|
|
4687
5023
|
*/
|
|
4688
|
-
tagVariable(name, tag, data) {
|
|
5024
|
+
tagVariable(name, tag, data, flags = VariableInfoFlags.Tagged) {
|
|
4689
5025
|
const oldInfo = this.scope.definitions.get(name);
|
|
4690
5026
|
/** @type {VariableInfo} */
|
|
4691
5027
|
let newInfo;
|
|
4692
5028
|
if (oldInfo === undefined) {
|
|
4693
|
-
newInfo = new VariableInfo(this.scope, name, {
|
|
5029
|
+
newInfo = new VariableInfo(this.scope, name, flags, {
|
|
4694
5030
|
tag,
|
|
4695
5031
|
data,
|
|
4696
5032
|
next: undefined
|
|
4697
5033
|
});
|
|
4698
5034
|
} else if (oldInfo instanceof VariableInfo) {
|
|
4699
|
-
newInfo = new VariableInfo(
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
5035
|
+
newInfo = new VariableInfo(
|
|
5036
|
+
oldInfo.declaredScope,
|
|
5037
|
+
oldInfo.name,
|
|
5038
|
+
/** @type {VariableInfoFlagsType} */ (oldInfo.flags | flags),
|
|
5039
|
+
{
|
|
5040
|
+
tag,
|
|
5041
|
+
data,
|
|
5042
|
+
next: oldInfo.tagInfo
|
|
5043
|
+
}
|
|
5044
|
+
);
|
|
4704
5045
|
} else {
|
|
4705
|
-
newInfo = new VariableInfo(oldInfo,
|
|
5046
|
+
newInfo = new VariableInfo(oldInfo, name, flags, {
|
|
4706
5047
|
tag,
|
|
4707
5048
|
data,
|
|
4708
5049
|
next: undefined
|
|
@@ -4717,8 +5058,12 @@ class JavascriptParser extends Parser {
|
|
|
4717
5058
|
defineVariable(name) {
|
|
4718
5059
|
const oldInfo = this.scope.definitions.get(name);
|
|
4719
5060
|
// Don't redefine variable in same scope to keep existing tags
|
|
4720
|
-
if (
|
|
5061
|
+
if (
|
|
5062
|
+
oldInfo instanceof VariableInfo &&
|
|
5063
|
+
oldInfo.declaredScope === this.scope
|
|
5064
|
+
) {
|
|
4721
5065
|
return;
|
|
5066
|
+
}
|
|
4722
5067
|
this.scope.definitions.set(name, this.scope);
|
|
4723
5068
|
}
|
|
4724
5069
|
|
|
@@ -4737,14 +5082,14 @@ class JavascriptParser extends Parser {
|
|
|
4737
5082
|
const info = this.scope.definitions.get(name);
|
|
4738
5083
|
if (info === undefined) return false;
|
|
4739
5084
|
if (info instanceof VariableInfo) {
|
|
4740
|
-
return info.
|
|
5085
|
+
return !info.isFree();
|
|
4741
5086
|
}
|
|
4742
5087
|
return true;
|
|
4743
5088
|
}
|
|
4744
5089
|
|
|
4745
5090
|
/**
|
|
4746
5091
|
* @param {string} name variable name
|
|
4747
|
-
* @returns {
|
|
5092
|
+
* @returns {ExportedVariableInfo} info for this variable
|
|
4748
5093
|
*/
|
|
4749
5094
|
getVariableInfo(name) {
|
|
4750
5095
|
const value = this.scope.definitions.get(name);
|
|
@@ -4756,7 +5101,7 @@ class JavascriptParser extends Parser {
|
|
|
4756
5101
|
|
|
4757
5102
|
/**
|
|
4758
5103
|
* @param {string} name variable name
|
|
4759
|
-
* @param {
|
|
5104
|
+
* @param {ExportedVariableInfo} variableInfo new info for this variable
|
|
4760
5105
|
* @returns {void}
|
|
4761
5106
|
*/
|
|
4762
5107
|
setVariable(name, variableInfo) {
|
|
@@ -4766,7 +5111,12 @@ class JavascriptParser extends Parser {
|
|
|
4766
5111
|
} else {
|
|
4767
5112
|
this.scope.definitions.set(
|
|
4768
5113
|
name,
|
|
4769
|
-
new VariableInfo(
|
|
5114
|
+
new VariableInfo(
|
|
5115
|
+
this.scope,
|
|
5116
|
+
variableInfo,
|
|
5117
|
+
VariableInfoFlags.Free,
|
|
5118
|
+
undefined
|
|
5119
|
+
)
|
|
4770
5120
|
);
|
|
4771
5121
|
}
|
|
4772
5122
|
} else {
|
|
@@ -4779,19 +5129,24 @@ class JavascriptParser extends Parser {
|
|
|
4779
5129
|
* @returns {VariableInfo} variable info
|
|
4780
5130
|
*/
|
|
4781
5131
|
evaluatedVariable(tagInfo) {
|
|
4782
|
-
return new VariableInfo(
|
|
5132
|
+
return new VariableInfo(
|
|
5133
|
+
this.scope,
|
|
5134
|
+
undefined,
|
|
5135
|
+
VariableInfoFlags.Evaluated,
|
|
5136
|
+
tagInfo
|
|
5137
|
+
);
|
|
4783
5138
|
}
|
|
4784
5139
|
|
|
4785
5140
|
/**
|
|
4786
5141
|
* @param {Range} range range of the comment
|
|
4787
|
-
* @returns {{ options: Record<string,
|
|
5142
|
+
* @returns {{ options: Record<string, EXPECTED_ANY> | null, errors: (Error & { comment: Comment })[] | null }} result
|
|
4788
5143
|
*/
|
|
4789
5144
|
parseCommentOptions(range) {
|
|
4790
5145
|
const comments = this.getComments(range);
|
|
4791
5146
|
if (comments.length === 0) {
|
|
4792
5147
|
return EMPTY_COMMENT_OPTIONS;
|
|
4793
5148
|
}
|
|
4794
|
-
/** @type {Record<string, EXPECTED_ANY>
|
|
5149
|
+
/** @type {Record<string, EXPECTED_ANY>} */
|
|
4795
5150
|
const options = {};
|
|
4796
5151
|
/** @type {(Error & { comment: Comment })[]} */
|
|
4797
5152
|
const errors = [];
|
|
@@ -4827,7 +5182,7 @@ class JavascriptParser extends Parser {
|
|
|
4827
5182
|
|
|
4828
5183
|
/**
|
|
4829
5184
|
* @param {Expression | Super} expression a member expression
|
|
4830
|
-
* @returns {{ members:
|
|
5185
|
+
* @returns {{ members: Members, object: Expression | Super, membersOptionals: MembersOptionals, memberRanges: MemberRanges }} member names (reverse order) and remaining object
|
|
4831
5186
|
*/
|
|
4832
5187
|
extractMemberExpressionChain(expression) {
|
|
4833
5188
|
/** @type {Node} */
|
|
@@ -4864,9 +5219,27 @@ class JavascriptParser extends Parser {
|
|
|
4864
5219
|
getFreeInfoFromVariable(varName) {
|
|
4865
5220
|
const info = this.getVariableInfo(varName);
|
|
4866
5221
|
let name;
|
|
4867
|
-
if (info instanceof VariableInfo) {
|
|
4868
|
-
|
|
4869
|
-
|
|
5222
|
+
if (info instanceof VariableInfo && info.name) {
|
|
5223
|
+
if (!info.isFree()) return;
|
|
5224
|
+
name = info.name;
|
|
5225
|
+
} else if (typeof info !== "string") {
|
|
5226
|
+
return;
|
|
5227
|
+
} else {
|
|
5228
|
+
name = info;
|
|
5229
|
+
}
|
|
5230
|
+
return { info, name };
|
|
5231
|
+
}
|
|
5232
|
+
|
|
5233
|
+
/**
|
|
5234
|
+
* @param {string} varName variable name
|
|
5235
|
+
* @returns {{name: string, info: VariableInfo | string} | undefined} name of the free variable and variable info for that
|
|
5236
|
+
*/
|
|
5237
|
+
getNameInfoFromVariable(varName) {
|
|
5238
|
+
const info = this.getVariableInfo(varName);
|
|
5239
|
+
let name;
|
|
5240
|
+
if (info instanceof VariableInfo && info.name) {
|
|
5241
|
+
if (!info.isFree() && !info.isTagged()) return;
|
|
5242
|
+
name = info.name;
|
|
4870
5243
|
} else if (typeof info !== "string") {
|
|
4871
5244
|
return;
|
|
4872
5245
|
} else {
|
|
@@ -4875,8 +5248,8 @@ class JavascriptParser extends Parser {
|
|
|
4875
5248
|
return { info, name };
|
|
4876
5249
|
}
|
|
4877
5250
|
|
|
4878
|
-
/** @typedef {{ type: "call", call: CallExpression, calleeName: string, rootInfo: string | VariableInfo, getCalleeMembers: () =>
|
|
4879
|
-
/** @typedef {{ type: "expression", rootInfo: string | VariableInfo, name: string, getMembers: () =>
|
|
5251
|
+
/** @typedef {{ type: "call", call: CallExpression, calleeName: string, rootInfo: string | VariableInfo, getCalleeMembers: () => CalleeMembers, name: string, getMembers: () => Members, getMembersOptionals: () => MembersOptionals, getMemberRanges: () => MemberRanges }} CallExpressionInfo */
|
|
5252
|
+
/** @typedef {{ type: "expression", rootInfo: string | VariableInfo, name: string, getMembers: () => Members, getMembersOptionals: () => MembersOptionals, getMemberRanges: () => MemberRanges }} ExpressionExpressionInfo */
|
|
4880
5253
|
|
|
4881
5254
|
/**
|
|
4882
5255
|
* @param {Expression | Super} expression a member expression
|
|
@@ -4897,7 +5270,7 @@ class JavascriptParser extends Parser {
|
|
|
4897
5270
|
}
|
|
4898
5271
|
const rootName = getRootName(callee);
|
|
4899
5272
|
if (!rootName) return;
|
|
4900
|
-
const result = this.
|
|
5273
|
+
const result = this.getNameInfoFromVariable(rootName);
|
|
4901
5274
|
if (!result) return;
|
|
4902
5275
|
const { info: rootInfo, name: resolvedRoot } = result;
|
|
4903
5276
|
const calleeName = objectAndMembersToName(resolvedRoot, rootMembers);
|
|
@@ -4920,7 +5293,7 @@ class JavascriptParser extends Parser {
|
|
|
4920
5293
|
const rootName = getRootName(object);
|
|
4921
5294
|
if (!rootName) return;
|
|
4922
5295
|
|
|
4923
|
-
const result = this.
|
|
5296
|
+
const result = this.getNameInfoFromVariable(rootName);
|
|
4924
5297
|
if (!result) return;
|
|
4925
5298
|
const { info: rootInfo, name: resolvedRoot } = result;
|
|
4926
5299
|
return {
|
|
@@ -4936,8 +5309,8 @@ class JavascriptParser extends Parser {
|
|
|
4936
5309
|
}
|
|
4937
5310
|
|
|
4938
5311
|
/**
|
|
4939
|
-
* @param {
|
|
4940
|
-
* @returns {{ name: string, rootInfo: ExportedVariableInfo, getMembers: () =>
|
|
5312
|
+
* @param {Expression} expression an expression
|
|
5313
|
+
* @returns {{ name: string, rootInfo: ExportedVariableInfo, getMembers: () => Members } | undefined} name info
|
|
4941
5314
|
*/
|
|
4942
5315
|
getNameForExpression(expression) {
|
|
4943
5316
|
return this.getMemberExpressionInfo(
|
|
@@ -4946,27 +5319,84 @@ class JavascriptParser extends Parser {
|
|
|
4946
5319
|
);
|
|
4947
5320
|
}
|
|
4948
5321
|
|
|
5322
|
+
/**
|
|
5323
|
+
* @param {Compilation} compilation compilation
|
|
5324
|
+
* @param {Module} module module
|
|
5325
|
+
* @returns {ParseFunction | undefined} parser
|
|
5326
|
+
*/
|
|
5327
|
+
static _getModuleParseFunction(compilation, module) {
|
|
5328
|
+
// Get from module if available
|
|
5329
|
+
if (
|
|
5330
|
+
module instanceof NormalModule &&
|
|
5331
|
+
module.parser instanceof JavascriptParser
|
|
5332
|
+
) {
|
|
5333
|
+
return module.parser.options.parse;
|
|
5334
|
+
}
|
|
5335
|
+
|
|
5336
|
+
// Fallback to the global javascript parse function
|
|
5337
|
+
if (typeof compilation.options.module.parser.javascript !== "undefined") {
|
|
5338
|
+
return compilation.options.module.parser.javascript.parse;
|
|
5339
|
+
}
|
|
5340
|
+
}
|
|
5341
|
+
|
|
4949
5342
|
/**
|
|
4950
5343
|
* @param {string} code source code
|
|
4951
|
-
* @param {
|
|
4952
|
-
* @
|
|
5344
|
+
* @param {InternalParseOptions} options parsing options
|
|
5345
|
+
* @param {ParseFunction=} customParse custom function to parse
|
|
5346
|
+
* @returns {ParseResult} parse result
|
|
4953
5347
|
*/
|
|
4954
|
-
static _parse(code, options) {
|
|
5348
|
+
static _parse(code, options, customParse) {
|
|
4955
5349
|
const type = options ? options.sourceType : "module";
|
|
4956
|
-
/** @type {
|
|
5350
|
+
/** @type {ParseOptions} */
|
|
4957
5351
|
const parserOptions = {
|
|
4958
5352
|
...defaultParserOptions,
|
|
4959
5353
|
allowReturnOutsideFunction: type === "script",
|
|
4960
5354
|
...options,
|
|
4961
5355
|
sourceType: type === "auto" ? "module" : type
|
|
4962
5356
|
};
|
|
5357
|
+
/**
|
|
5358
|
+
* @param {string} code source code
|
|
5359
|
+
* @param {ParseOptions} options parsing options
|
|
5360
|
+
* @returns {ParseResult} parse result
|
|
5361
|
+
*/
|
|
5362
|
+
const internalParse = (code, options) => {
|
|
5363
|
+
if (typeof customParse === "function") {
|
|
5364
|
+
return customParse(code, options);
|
|
5365
|
+
}
|
|
5366
|
+
|
|
5367
|
+
/** @type {Comment[]} */
|
|
5368
|
+
const comments = [];
|
|
5369
|
+
|
|
5370
|
+
if (options.comments) {
|
|
5371
|
+
/** @type {AcornOptions} */
|
|
5372
|
+
(options).onComment = comments;
|
|
5373
|
+
}
|
|
5374
|
+
|
|
5375
|
+
/** @type {Set<number>} */
|
|
5376
|
+
const semicolons = new Set();
|
|
5377
|
+
|
|
5378
|
+
if (options.semicolons) {
|
|
5379
|
+
/** @type {AcornOptions} */
|
|
5380
|
+
(options).onInsertedSemicolon = (pos) => semicolons.add(pos);
|
|
5381
|
+
}
|
|
5382
|
+
|
|
5383
|
+
const ast =
|
|
5384
|
+
/** @type {Program} */
|
|
5385
|
+
(parser.parse(code, /** @type {AcornOptions} */ (options)));
|
|
5386
|
+
|
|
5387
|
+
return { ast, comments, semicolons };
|
|
5388
|
+
};
|
|
4963
5389
|
|
|
4964
|
-
/** @type {
|
|
5390
|
+
/** @type {Program | undefined} */
|
|
4965
5391
|
let ast;
|
|
5392
|
+
/** @type {Comment[] | undefined} */
|
|
5393
|
+
let comments;
|
|
5394
|
+
/** @type {Set<number> | undefined} */
|
|
5395
|
+
let semicolons;
|
|
4966
5396
|
let error;
|
|
4967
5397
|
let threw = false;
|
|
4968
5398
|
try {
|
|
4969
|
-
ast =
|
|
5399
|
+
({ ast, comments, semicolons } = internalParse(code, parserOptions));
|
|
4970
5400
|
} catch (err) {
|
|
4971
5401
|
error = err;
|
|
4972
5402
|
threw = true;
|
|
@@ -4974,14 +5404,10 @@ class JavascriptParser extends Parser {
|
|
|
4974
5404
|
|
|
4975
5405
|
if (threw && type === "auto") {
|
|
4976
5406
|
parserOptions.sourceType = "script";
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
}
|
|
4980
|
-
if (Array.isArray(parserOptions.onComment)) {
|
|
4981
|
-
parserOptions.onComment.length = 0;
|
|
4982
|
-
}
|
|
5407
|
+
parserOptions.allowReturnOutsideFunction = true;
|
|
5408
|
+
|
|
4983
5409
|
try {
|
|
4984
|
-
ast =
|
|
5410
|
+
({ ast, comments, semicolons } = internalParse(code, parserOptions));
|
|
4985
5411
|
threw = false;
|
|
4986
5412
|
} catch (_err) {
|
|
4987
5413
|
// we use the error from first parse try
|
|
@@ -4993,15 +5419,25 @@ class JavascriptParser extends Parser {
|
|
|
4993
5419
|
throw error;
|
|
4994
5420
|
}
|
|
4995
5421
|
|
|
4996
|
-
return /** @type {
|
|
5422
|
+
return /** @type {ParseResult} */ ({ ast, comments, semicolons });
|
|
5423
|
+
}
|
|
5424
|
+
|
|
5425
|
+
/**
|
|
5426
|
+
* @param {((BaseParser: typeof AcornParser) => typeof AcornParser)[]} plugins parser plugin
|
|
5427
|
+
* @returns {typeof JavascriptParser} parser
|
|
5428
|
+
*/
|
|
5429
|
+
static extend(...plugins) {
|
|
5430
|
+
parser = parser.extend(...plugins);
|
|
5431
|
+
return JavascriptParser;
|
|
4997
5432
|
}
|
|
4998
5433
|
}
|
|
4999
5434
|
|
|
5000
5435
|
module.exports = JavascriptParser;
|
|
5001
5436
|
module.exports.ALLOWED_MEMBER_TYPES_ALL = ALLOWED_MEMBER_TYPES_ALL;
|
|
5002
|
-
module.exports.ALLOWED_MEMBER_TYPES_EXPRESSION =
|
|
5003
|
-
ALLOWED_MEMBER_TYPES_EXPRESSION;
|
|
5004
5437
|
module.exports.ALLOWED_MEMBER_TYPES_CALL_EXPRESSION =
|
|
5005
5438
|
ALLOWED_MEMBER_TYPES_CALL_EXPRESSION;
|
|
5006
|
-
module.exports.
|
|
5439
|
+
module.exports.ALLOWED_MEMBER_TYPES_EXPRESSION =
|
|
5440
|
+
ALLOWED_MEMBER_TYPES_EXPRESSION;
|
|
5007
5441
|
module.exports.VariableInfo = VariableInfo;
|
|
5442
|
+
module.exports.VariableInfoFlags = VariableInfoFlags;
|
|
5443
|
+
module.exports.getImportAttributes = getImportAttributes;
|