webpack 5.76.1 → 5.88.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of webpack might be problematic. Click here for more details.

Files changed (436) hide show
  1. package/README.md +10 -4
  2. package/bin/webpack.js +26 -2
  3. package/hot/dev-server.js +2 -1
  4. package/hot/lazy-compilation-node.js +10 -0
  5. package/hot/lazy-compilation-web.js +9 -0
  6. package/hot/log-apply-result.js +5 -0
  7. package/hot/log.js +22 -0
  8. package/hot/only-dev-server.js +2 -1
  9. package/hot/poll.js +3 -0
  10. package/hot/signal.js +4 -0
  11. package/lib/APIPlugin.js +174 -116
  12. package/lib/AsyncDependenciesBlock.js +13 -5
  13. package/lib/AutomaticPrefetchPlugin.js +1 -0
  14. package/lib/BannerPlugin.js +4 -0
  15. package/lib/CacheFacade.js +4 -0
  16. package/lib/CaseSensitiveModulesWarning.js +3 -1
  17. package/lib/Chunk.js +36 -18
  18. package/lib/ChunkGraph.js +4 -4
  19. package/lib/ChunkGroup.js +25 -10
  20. package/lib/CleanPlugin.js +30 -7
  21. package/lib/CodeGenerationResults.js +2 -2
  22. package/lib/CompatibilityPlugin.js +85 -46
  23. package/lib/Compilation.js +17 -8
  24. package/lib/Compiler.js +12 -8
  25. package/lib/ConcatenationScope.js +2 -2
  26. package/lib/ConditionalInitFragment.js +11 -1
  27. package/lib/ConstPlugin.js +79 -44
  28. package/lib/ContextModule.js +20 -6
  29. package/lib/ContextModuleFactory.js +2 -1
  30. package/lib/ContextReplacementPlugin.js +13 -0
  31. package/lib/CssModule.js +169 -0
  32. package/lib/DefinePlugin.js +152 -86
  33. package/lib/DelegatedModule.js +22 -4
  34. package/lib/DelegatedModuleFactoryPlugin.js +6 -0
  35. package/lib/DependenciesBlock.js +17 -1
  36. package/lib/Dependency.js +19 -5
  37. package/lib/DllEntryPlugin.js +16 -1
  38. package/lib/DllModule.js +17 -2
  39. package/lib/DllModuleFactory.js +1 -1
  40. package/lib/DllReferencePlugin.js +13 -1
  41. package/lib/Entrypoint.js +1 -1
  42. package/lib/ErrorHelpers.js +62 -22
  43. package/lib/EvalSourceMapDevToolPlugin.js +9 -2
  44. package/lib/ExportsInfo.js +20 -3
  45. package/lib/ExportsInfoApiPlugin.js +30 -14
  46. package/lib/ExternalModule.js +30 -9
  47. package/lib/FileSystemInfo.js +9 -1
  48. package/lib/FlagAllModulesAsUsedPlugin.js +27 -27
  49. package/lib/FlagDependencyExportsPlugin.js +336 -348
  50. package/lib/FlagDependencyUsagePlugin.js +9 -9
  51. package/lib/FlagEntryExportAsUsedPlugin.js +26 -23
  52. package/lib/HookWebpackError.js +1 -1
  53. package/lib/HotModuleReplacementPlugin.js +60 -46
  54. package/lib/IgnoreErrorModuleFactory.js +1 -1
  55. package/lib/InitFragment.js +28 -5
  56. package/lib/JavascriptMetaInfoPlugin.js +27 -15
  57. package/lib/LibManifestPlugin.js +22 -5
  58. package/lib/LoaderOptionsPlugin.js +12 -2
  59. package/lib/MainTemplate.js +2 -2
  60. package/lib/Module.js +44 -12
  61. package/lib/ModuleBuildError.js +9 -0
  62. package/lib/ModuleDependencyError.js +4 -2
  63. package/lib/ModuleDependencyWarning.js +4 -2
  64. package/lib/ModuleError.js +9 -0
  65. package/lib/ModuleFactory.js +1 -1
  66. package/lib/ModuleFilenameHelpers.js +114 -4
  67. package/lib/ModuleGraph.js +33 -23
  68. package/lib/ModuleGraphConnection.js +19 -6
  69. package/lib/ModuleInfoHeaderPlugin.js +9 -2
  70. package/lib/ModuleNotFoundError.js +5 -2
  71. package/lib/ModuleParseError.js +9 -0
  72. package/lib/ModuleProfile.js +1 -0
  73. package/lib/ModuleRestoreError.js +2 -0
  74. package/lib/ModuleStoreError.js +2 -1
  75. package/lib/ModuleTypeConstants.js +169 -0
  76. package/lib/ModuleWarning.js +9 -0
  77. package/lib/MultiWatching.js +4 -0
  78. package/lib/NodeStuffPlugin.js +65 -35
  79. package/lib/NormalModule.js +12 -2
  80. package/lib/NormalModuleFactory.js +56 -8
  81. package/lib/NormalModuleReplacementPlugin.js +5 -3
  82. package/lib/NullFactory.js +1 -1
  83. package/lib/PrefetchPlugin.js +4 -0
  84. package/lib/ProgressPlugin.js +71 -15
  85. package/lib/ProvidePlugin.js +30 -14
  86. package/lib/RawModule.js +13 -2
  87. package/lib/RecordIdsPlugin.js +4 -4
  88. package/lib/RequireJsStuffPlugin.js +22 -15
  89. package/lib/RuntimeGlobals.js +5 -0
  90. package/lib/RuntimeModule.js +12 -11
  91. package/lib/RuntimePlugin.js +10 -3
  92. package/lib/RuntimeTemplate.js +29 -11
  93. package/lib/SelfModuleFactory.js +12 -0
  94. package/lib/SourceMapDevToolModuleOptionsPlugin.js +4 -0
  95. package/lib/SourceMapDevToolPlugin.js +47 -11
  96. package/lib/Template.js +5 -3
  97. package/lib/UseStrictPlugin.js +29 -11
  98. package/lib/WarnCaseSensitiveModulesPlugin.js +12 -0
  99. package/lib/WarnDeprecatedOptionPlugin.js +7 -0
  100. package/lib/WatchIgnorePlugin.js +4 -0
  101. package/lib/WebpackError.js +14 -5
  102. package/lib/WebpackIsIncludedPlugin.js +22 -13
  103. package/lib/WebpackOptionsApply.js +41 -44
  104. package/lib/WebpackOptionsDefaulter.js +10 -3
  105. package/lib/asset/AssetGenerator.js +24 -9
  106. package/lib/asset/AssetModulesPlugin.js +28 -12
  107. package/lib/asset/AssetParser.js +15 -7
  108. package/lib/asset/AssetSourceParser.js +8 -3
  109. package/lib/asset/RawDataUrlModule.js +15 -4
  110. package/lib/async-modules/AwaitDependenciesInitFragment.js +4 -0
  111. package/lib/async-modules/InferAsyncModulesPlugin.js +1 -1
  112. package/lib/cache/IdleFileCachePlugin.js +2 -1
  113. package/lib/cache/MemoryWithGcCachePlugin.js +2 -0
  114. package/lib/cache/PackFileCacheStrategy.js +42 -15
  115. package/lib/cache/ResolverCachePlugin.js +3 -0
  116. package/lib/config/browserslistTargetHandler.js +10 -10
  117. package/lib/config/defaults.js +306 -105
  118. package/lib/config/normalization.js +110 -71
  119. package/lib/config/target.js +37 -10
  120. package/lib/container/ContainerEntryModule.js +11 -1
  121. package/lib/container/ContainerEntryModuleFactory.js +1 -1
  122. package/lib/container/ContainerExposedDependency.js +9 -0
  123. package/lib/container/ContainerPlugin.js +3 -1
  124. package/lib/container/FallbackDependency.js +13 -0
  125. package/lib/container/FallbackItemDependency.js +3 -0
  126. package/lib/container/FallbackModule.js +12 -2
  127. package/lib/container/FallbackModuleFactory.js +1 -1
  128. package/lib/container/RemoteModule.js +11 -1
  129. package/lib/container/RemoteRuntimeModule.js +3 -2
  130. package/lib/container/RemoteToExternalDependency.js +3 -0
  131. package/lib/css/CssExportsGenerator.js +9 -0
  132. package/lib/css/CssGenerator.js +5 -1
  133. package/lib/css/CssLoadingRuntimeModule.js +53 -22
  134. package/lib/css/CssModulesPlugin.js +253 -74
  135. package/lib/css/CssParser.js +697 -282
  136. package/lib/css/walkCssTokens.js +269 -138
  137. package/lib/debug/ProfilingPlugin.js +33 -12
  138. package/lib/dependencies/AMDDefineDependency.js +54 -10
  139. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +13 -2
  140. package/lib/dependencies/AMDPlugin.js +33 -20
  141. package/lib/dependencies/AMDRequireArrayDependency.js +13 -0
  142. package/lib/dependencies/AMDRequireContextDependency.js +15 -0
  143. package/lib/dependencies/AMDRequireDependenciesBlock.js +6 -0
  144. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +8 -2
  145. package/lib/dependencies/AMDRequireDependency.js +16 -1
  146. package/lib/dependencies/AMDRequireItemDependency.js +6 -0
  147. package/lib/dependencies/AMDRuntimeModules.js +2 -2
  148. package/lib/dependencies/CachedConstDependency.js +14 -0
  149. package/lib/dependencies/CommonJsDependencyHelpers.js +9 -0
  150. package/lib/dependencies/CommonJsExportRequireDependency.js +19 -0
  151. package/lib/dependencies/CommonJsExportsDependency.js +16 -0
  152. package/lib/dependencies/CommonJsExportsParserPlugin.js +77 -5
  153. package/lib/dependencies/CommonJsFullRequireDependency.js +10 -1
  154. package/lib/dependencies/CommonJsImportsParserPlugin.js +174 -63
  155. package/lib/dependencies/CommonJsPlugin.js +51 -26
  156. package/lib/dependencies/CommonJsRequireContextDependency.js +17 -0
  157. package/lib/dependencies/CommonJsRequireDependency.js +7 -0
  158. package/lib/dependencies/CommonJsSelfReferenceDependency.js +16 -0
  159. package/lib/dependencies/ConstDependency.js +11 -2
  160. package/lib/dependencies/ContextDependency.js +15 -2
  161. package/lib/dependencies/ContextDependencyHelpers.js +3 -3
  162. package/lib/dependencies/ContextElementDependency.js +8 -0
  163. package/lib/dependencies/CreateScriptUrlDependency.js +10 -1
  164. package/lib/dependencies/CriticalDependencyWarning.js +3 -0
  165. package/lib/dependencies/CssExportDependency.js +8 -0
  166. package/lib/dependencies/CssImportDependency.js +55 -3
  167. package/lib/dependencies/CssLocalIdentifierDependency.js +15 -1
  168. package/lib/dependencies/CssSelfLocalIdentifierDependency.js +10 -1
  169. package/lib/dependencies/CssUrlDependency.js +46 -16
  170. package/lib/dependencies/DelegatedSourceDependency.js +3 -0
  171. package/lib/dependencies/DllEntryDependency.js +14 -0
  172. package/lib/dependencies/DynamicExports.js +10 -6
  173. package/lib/dependencies/ExportsInfoDependency.js +25 -4
  174. package/lib/dependencies/HarmonyAcceptDependency.js +10 -1
  175. package/lib/dependencies/HarmonyAcceptImportDependency.js +3 -0
  176. package/lib/dependencies/HarmonyCompatibilityDependency.js +2 -1
  177. package/lib/dependencies/HarmonyDetectionParserPlugin.js +22 -2
  178. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +32 -6
  179. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +5 -0
  180. package/lib/dependencies/HarmonyExportExpressionDependency.js +20 -3
  181. package/lib/dependencies/HarmonyExportHeaderDependency.js +13 -0
  182. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +22 -6
  183. package/lib/dependencies/HarmonyExportInitFragment.js +2 -1
  184. package/lib/dependencies/HarmonyExportSpecifierDependency.js +12 -0
  185. package/lib/dependencies/HarmonyExports.js +11 -5
  186. package/lib/dependencies/HarmonyImportDependency.js +10 -1
  187. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +53 -22
  188. package/lib/dependencies/HarmonyImportSideEffectDependency.js +7 -2
  189. package/lib/dependencies/HarmonyImportSpecifierDependency.js +139 -16
  190. package/lib/dependencies/HarmonyModulesPlugin.js +23 -5
  191. package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +15 -3
  192. package/lib/dependencies/ImportContextDependency.js +15 -0
  193. package/lib/dependencies/ImportDependency.js +15 -4
  194. package/lib/dependencies/ImportEagerDependency.js +7 -4
  195. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +51 -13
  196. package/lib/dependencies/ImportMetaContextPlugin.js +18 -5
  197. package/lib/dependencies/ImportMetaHotAcceptDependency.js +6 -0
  198. package/lib/dependencies/ImportMetaHotDeclineDependency.js +6 -0
  199. package/lib/dependencies/ImportMetaPlugin.js +103 -51
  200. package/lib/dependencies/ImportParserPlugin.js +83 -25
  201. package/lib/dependencies/ImportPlugin.js +21 -7
  202. package/lib/dependencies/ImportWeakDependency.js +7 -4
  203. package/lib/dependencies/JsonExportsDependency.js +9 -1
  204. package/lib/dependencies/LocalModule.js +16 -0
  205. package/lib/dependencies/LocalModuleDependency.js +15 -0
  206. package/lib/dependencies/LocalModulesHelpers.js +18 -0
  207. package/lib/dependencies/ModuleDecoratorDependency.js +8 -0
  208. package/lib/dependencies/ModuleDependency.js +9 -1
  209. package/lib/dependencies/ModuleDependencyTemplateAsId.js +2 -1
  210. package/lib/dependencies/ModuleHotAcceptDependency.js +6 -0
  211. package/lib/dependencies/ModuleHotDeclineDependency.js +6 -0
  212. package/lib/dependencies/PrefetchDependency.js +3 -0
  213. package/lib/dependencies/ProvidedDependency.js +14 -2
  214. package/lib/dependencies/PureExpressionDependency.js +10 -1
  215. package/lib/dependencies/RequireContextDependency.js +6 -0
  216. package/lib/dependencies/RequireContextDependencyParserPlugin.js +13 -5
  217. package/lib/dependencies/RequireContextPlugin.js +19 -6
  218. package/lib/dependencies/RequireEnsureDependenciesBlock.js +7 -0
  219. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +6 -1
  220. package/lib/dependencies/RequireEnsureDependency.js +16 -2
  221. package/lib/dependencies/RequireEnsureItemDependency.js +3 -0
  222. package/lib/dependencies/RequireEnsurePlugin.js +27 -7
  223. package/lib/dependencies/RequireHeaderDependency.js +14 -1
  224. package/lib/dependencies/RequireIncludeDependency.js +5 -0
  225. package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +29 -5
  226. package/lib/dependencies/RequireIncludePlugin.js +25 -5
  227. package/lib/dependencies/RequireResolveContextDependency.js +17 -0
  228. package/lib/dependencies/RequireResolveDependency.js +6 -0
  229. package/lib/dependencies/RequireResolveHeaderDependency.js +18 -0
  230. package/lib/dependencies/RuntimeRequirementsDependency.js +8 -0
  231. package/lib/dependencies/StaticExportsDependency.js +8 -0
  232. package/lib/dependencies/SystemPlugin.js +48 -21
  233. package/lib/dependencies/SystemRuntimeModule.js +1 -1
  234. package/lib/dependencies/URLDependency.js +13 -4
  235. package/lib/dependencies/URLPlugin.js +31 -18
  236. package/lib/dependencies/UnsupportedDependency.js +13 -0
  237. package/lib/dependencies/WebAssemblyExportImportedDependency.js +14 -0
  238. package/lib/dependencies/WebAssemblyImportDependency.js +9 -1
  239. package/lib/dependencies/WebpackIsIncludedDependency.js +5 -0
  240. package/lib/dependencies/WorkerDependency.js +47 -3
  241. package/lib/dependencies/WorkerPlugin.js +105 -32
  242. package/lib/dependencies/getFunctionExpression.js +7 -0
  243. package/lib/esm/ExportWebpackRequireRuntimeModule.js +3 -2
  244. package/lib/esm/ModuleChunkFormatPlugin.js +21 -8
  245. package/lib/esm/ModuleChunkLoadingPlugin.js +9 -0
  246. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +19 -12
  247. package/lib/hmr/HotModuleReplacementRuntimeModule.js +1 -1
  248. package/lib/hmr/LazyCompilationPlugin.js +14 -5
  249. package/lib/ids/ChunkModuleIdRangePlugin.js +11 -0
  250. package/lib/ids/DeterministicChunkIdsPlugin.js +11 -2
  251. package/lib/ids/DeterministicModuleIdsPlugin.js +11 -7
  252. package/lib/ids/HashedModuleIdsPlugin.js +9 -2
  253. package/lib/ids/IdHelpers.js +6 -0
  254. package/lib/ids/NamedChunkIdsPlugin.js +13 -1
  255. package/lib/ids/NamedModuleIdsPlugin.js +14 -3
  256. package/lib/ids/OccurrenceChunkIdsPlugin.js +6 -2
  257. package/lib/ids/OccurrenceModuleIdsPlugin.js +1 -1
  258. package/lib/ids/SyncModuleIdsPlugin.js +3 -2
  259. package/lib/index.js +8 -0
  260. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +3 -3
  261. package/lib/javascript/BasicEvaluatedExpression.js +137 -11
  262. package/lib/javascript/ChunkHelpers.js +2 -2
  263. package/lib/javascript/CommonJsChunkFormatPlugin.js +7 -3
  264. package/lib/javascript/EnableChunkLoadingPlugin.js +4 -0
  265. package/lib/javascript/JavascriptModulesPlugin.js +194 -194
  266. package/lib/javascript/JavascriptParser.js +941 -256
  267. package/lib/javascript/JavascriptParserHelpers.js +37 -15
  268. package/lib/javascript/StartupHelpers.js +2 -2
  269. package/lib/json/JsonData.js +26 -1
  270. package/lib/json/JsonGenerator.js +21 -7
  271. package/lib/json/JsonModulesPlugin.js +14 -5
  272. package/lib/json/JsonParser.js +27 -13
  273. package/lib/library/AbstractLibraryPlugin.js +4 -0
  274. package/lib/library/AmdLibraryPlugin.js +22 -6
  275. package/lib/library/AssignLibraryPlugin.js +6 -4
  276. package/lib/library/ExportPropertyLibraryPlugin.js +4 -1
  277. package/lib/library/ModuleLibraryPlugin.js +8 -4
  278. package/lib/library/SystemLibraryPlugin.js +1 -0
  279. package/lib/library/UmdLibraryPlugin.js +4 -0
  280. package/lib/logging/runtime.js +1 -1
  281. package/lib/logging/truncateArgs.js +4 -0
  282. package/lib/node/CommonJsChunkLoadingPlugin.js +17 -2
  283. package/lib/node/NodeTargetPlugin.js +3 -0
  284. package/lib/node/NodeTemplatePlugin.js +10 -2
  285. package/lib/node/NodeWatchFileSystem.js +1 -1
  286. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +18 -9
  287. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +12 -2
  288. package/lib/node/ReadFileCompileWasmPlugin.js +21 -3
  289. package/lib/node/RequireChunkLoadingRuntimeModule.js +15 -8
  290. package/lib/node/nodeConsole.js +2 -4
  291. package/lib/optimize/AggressiveMergingPlugin.js +8 -0
  292. package/lib/optimize/AggressiveSplittingPlugin.js +9 -2
  293. package/lib/optimize/ConcatenatedModule.js +8 -6
  294. package/lib/optimize/EnsureChunkConditionsPlugin.js +3 -0
  295. package/lib/optimize/FlagIncludedChunksPlugin.js +11 -5
  296. package/lib/optimize/InnerGraph.js +5 -5
  297. package/lib/optimize/InnerGraphPlugin.js +57 -48
  298. package/lib/optimize/LimitChunkCountPlugin.js +29 -4
  299. package/lib/optimize/MangleExportsPlugin.js +1 -1
  300. package/lib/optimize/MinMaxSizeWarning.js +5 -0
  301. package/lib/optimize/ModuleConcatenationPlugin.js +59 -2
  302. package/lib/optimize/RealContentHashPlugin.js +86 -30
  303. package/lib/optimize/RemoveParentModulesPlugin.js +6 -0
  304. package/lib/optimize/RuntimeChunkPlugin.js +9 -1
  305. package/lib/optimize/SideEffectsFlagPlugin.js +53 -44
  306. package/lib/optimize/SplitChunksPlugin.js +71 -31
  307. package/lib/performance/SizeLimitsPlugin.js +7 -4
  308. package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +4 -2
  309. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +3 -1
  310. package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +6 -3
  311. package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +4 -2
  312. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +4 -2
  313. package/lib/rules/BasicEffectRulePlugin.js +4 -0
  314. package/lib/rules/BasicMatcherRulePlugin.js +5 -0
  315. package/lib/rules/RuleSetCompiler.js +3 -3
  316. package/lib/rules/UseEffectRulePlugin.js +6 -4
  317. package/lib/runtime/AsyncModuleRuntimeModule.js +9 -6
  318. package/lib/runtime/AutoPublicPathRuntimeModule.js +16 -5
  319. package/lib/runtime/BaseUriRuntimeModule.js +8 -4
  320. package/lib/runtime/ChunkNameRuntimeModule.js +1 -1
  321. package/lib/runtime/CompatGetDefaultExportRuntimeModule.js +5 -2
  322. package/lib/runtime/CompatRuntimeModule.js +7 -2
  323. package/lib/runtime/CreateFakeNamespaceObjectRuntimeModule.js +5 -2
  324. package/lib/runtime/CreateScriptRuntimeModule.js +4 -2
  325. package/lib/runtime/CreateScriptUrlRuntimeModule.js +4 -2
  326. package/lib/runtime/DefinePropertyGettersRuntimeModule.js +5 -2
  327. package/lib/runtime/EnsureChunkRuntimeModule.js +18 -4
  328. package/lib/runtime/GetChunkFilenameRuntimeModule.js +45 -26
  329. package/lib/runtime/GetFullHashRuntimeModule.js +4 -3
  330. package/lib/runtime/GetMainFilenameRuntimeModule.js +5 -2
  331. package/lib/runtime/GetTrustedTypesPolicyRuntimeModule.js +27 -6
  332. package/lib/runtime/GlobalRuntimeModule.js +1 -1
  333. package/lib/runtime/HasOwnPropertyRuntimeModule.js +5 -2
  334. package/lib/runtime/LoadScriptRuntimeModule.js +65 -50
  335. package/lib/runtime/MakeNamespaceObjectRuntimeModule.js +5 -2
  336. package/lib/runtime/NonceRuntimeModule.js +1 -1
  337. package/lib/runtime/OnChunksLoadedRuntimeModule.js +4 -2
  338. package/lib/runtime/PublicPathRuntimeModule.js +9 -2
  339. package/lib/runtime/RelativeUrlRuntimeModule.js +5 -2
  340. package/lib/runtime/RuntimeIdRuntimeModule.js +6 -2
  341. package/lib/runtime/StartupChunkDependenciesPlugin.js +15 -0
  342. package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +13 -4
  343. package/lib/runtime/StartupEntrypointRuntimeModule.js +11 -7
  344. package/lib/runtime/SystemContextRuntimeModule.js +1 -1
  345. package/lib/schemes/DataUriPlugin.js +16 -3
  346. package/lib/schemes/HttpUriPlugin.js +38 -0
  347. package/lib/serialization/ArraySerializer.js +22 -6
  348. package/lib/serialization/BinaryMiddleware.js +164 -1
  349. package/lib/serialization/DateObjectSerializer.js +15 -4
  350. package/lib/serialization/ErrorObjectSerializer.js +23 -8
  351. package/lib/serialization/FileMiddleware.js +17 -0
  352. package/lib/serialization/MapObjectSerializer.js +24 -8
  353. package/lib/serialization/NullPrototypeObjectSerializer.js +25 -8
  354. package/lib/serialization/ObjectMiddleware.js +33 -2
  355. package/lib/serialization/PlainObjectSerializer.js +23 -12
  356. package/lib/serialization/RegExpObjectSerializer.js +16 -5
  357. package/lib/serialization/SetObjectSerializer.js +21 -6
  358. package/lib/serialization/types.js +1 -1
  359. package/lib/sharing/ConsumeSharedFallbackDependency.js +3 -0
  360. package/lib/sharing/ConsumeSharedModule.js +13 -2
  361. package/lib/sharing/ConsumeSharedPlugin.js +4 -0
  362. package/lib/sharing/ConsumeSharedRuntimeModule.js +22 -7
  363. package/lib/sharing/ProvideSharedDependency.js +17 -0
  364. package/lib/sharing/ProvideSharedModule.js +11 -1
  365. package/lib/sharing/ProvideSharedModuleFactory.js +1 -1
  366. package/lib/sharing/ProvideSharedPlugin.js +22 -21
  367. package/lib/sharing/ShareRuntimeModule.js +19 -9
  368. package/lib/sharing/resolveMatchedConfigs.js +1 -1
  369. package/lib/sharing/utils.js +320 -7
  370. package/lib/stats/DefaultStatsFactoryPlugin.js +105 -29
  371. package/lib/stats/DefaultStatsPresetPlugin.js +9 -0
  372. package/lib/stats/DefaultStatsPrinterPlugin.js +43 -0
  373. package/lib/util/AsyncQueue.js +4 -2
  374. package/lib/util/LazySet.js +10 -2
  375. package/lib/util/MapHelpers.js +19 -5
  376. package/lib/util/ParallelismFactorCalculator.js +10 -0
  377. package/lib/util/Semaphore.js +1 -1
  378. package/lib/util/StackedCacheMap.js +6 -0
  379. package/lib/util/StringXor.js +51 -0
  380. package/lib/util/binarySearchBounds.js +49 -0
  381. package/lib/util/compileBooleanMatcher.js +31 -0
  382. package/lib/util/createHash.js +35 -13
  383. package/lib/util/deprecation.js +18 -3
  384. package/lib/util/deterministicGrouping.js +50 -11
  385. package/lib/util/findGraphRoots.js +4 -2
  386. package/lib/util/hash/md4.js +2 -2
  387. package/lib/util/hash/xxhash64.js +1 -1
  388. package/lib/util/identifier.js +4 -0
  389. package/lib/util/internalSerializables.js +1 -0
  390. package/lib/util/makeSerializable.js +7 -0
  391. package/lib/util/memoize.js +3 -3
  392. package/lib/util/numberHash.js +75 -21
  393. package/lib/util/processAsyncTree.js +7 -1
  394. package/lib/util/propertyAccess.js +9 -54
  395. package/lib/util/propertyName.js +79 -0
  396. package/lib/util/registerExternalSerializer.js +1 -1
  397. package/lib/util/runtime.js +14 -1
  398. package/lib/util/semver.js +1 -1
  399. package/lib/util/serialization.js +10 -0
  400. package/lib/util/smartGrouping.js +1 -1
  401. package/lib/validateSchema.js +6 -2
  402. package/lib/wasm/EnableWasmLoadingPlugin.js +4 -0
  403. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +15 -2
  404. package/lib/wasm-async/AsyncWebAssemblyGenerator.js +9 -1
  405. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +14 -3
  406. package/lib/wasm-async/AsyncWebAssemblyModulesPlugin.js +28 -8
  407. package/lib/wasm-async/AsyncWebAssemblyParser.js +11 -4
  408. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +39 -8
  409. package/lib/wasm-sync/WasmFinalizeExportsPlugin.js +17 -6
  410. package/lib/wasm-sync/WebAssemblyGenerator.js +19 -5
  411. package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +1 -1
  412. package/lib/wasm-sync/WebAssemblyModulesPlugin.js +53 -43
  413. package/lib/wasm-sync/WebAssemblyParser.js +15 -4
  414. package/lib/wasm-sync/WebAssemblyUtils.js +1 -1
  415. package/lib/web/FetchCompileAsyncWasmPlugin.js +11 -1
  416. package/lib/web/FetchCompileWasmPlugin.js +59 -42
  417. package/lib/web/JsonpChunkLoadingPlugin.js +9 -0
  418. package/lib/web/JsonpChunkLoadingRuntimeModule.js +26 -9
  419. package/lib/webpack.js +12 -3
  420. package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +9 -0
  421. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +20 -17
  422. package/module.d.ts +55 -37
  423. package/package.json +59 -56
  424. package/schemas/WebpackOptions.check.js +1 -1
  425. package/schemas/WebpackOptions.json +132 -5
  426. package/schemas/plugins/ProgressPlugin.check.js +1 -1
  427. package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
  428. package/schemas/plugins/SourceMapDevToolPlugin.json +4 -0
  429. package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
  430. package/schemas/plugins/container/ContainerPlugin.json +8 -0
  431. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  432. package/schemas/plugins/container/ModuleFederationPlugin.json +8 -0
  433. package/schemas/plugins/css/CssGeneratorOptions.json +1 -1
  434. package/schemas/plugins/css/CssParserOptions.json +1 -1
  435. package/schemas/plugins/sharing/SharePlugin.check.js +1 -1
  436. package/types.d.ts +1608 -667
@@ -16,48 +16,83 @@ const memoize = require("../util/memoize");
16
16
  const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
17
17
 
18
18
  /** @typedef {import("acorn").Options} AcornOptions */
19
- /** @typedef {import("estree").ArrayExpression} ArrayExpressionNode */
20
- /** @typedef {import("estree").BinaryExpression} BinaryExpressionNode */
21
- /** @typedef {import("estree").BlockStatement} BlockStatementNode */
22
- /** @typedef {import("estree").SequenceExpression} SequenceExpressionNode */
23
- /** @typedef {import("estree").CallExpression} CallExpressionNode */
24
- /** @typedef {import("estree").ClassDeclaration} ClassDeclarationNode */
25
- /** @typedef {import("estree").ClassExpression} ClassExpressionNode */
26
- /** @typedef {import("estree").Comment} CommentNode */
27
- /** @typedef {import("estree").ConditionalExpression} ConditionalExpressionNode */
28
- /** @typedef {import("estree").Declaration} DeclarationNode */
29
- /** @typedef {import("estree").PrivateIdentifier} PrivateIdentifierNode */
30
- /** @typedef {import("estree").PropertyDefinition} PropertyDefinitionNode */
31
- /** @typedef {import("estree").Expression} ExpressionNode */
32
- /** @typedef {import("estree").Identifier} IdentifierNode */
33
- /** @typedef {import("estree").IfStatement} IfStatementNode */
34
- /** @typedef {import("estree").LabeledStatement} LabeledStatementNode */
35
- /** @typedef {import("estree").Literal} LiteralNode */
36
- /** @typedef {import("estree").LogicalExpression} LogicalExpressionNode */
37
- /** @typedef {import("estree").ChainExpression} ChainExpressionNode */
38
- /** @typedef {import("estree").MemberExpression} MemberExpressionNode */
39
- /** @typedef {import("estree").MetaProperty} MetaPropertyNode */
40
- /** @typedef {import("estree").MethodDefinition} MethodDefinitionNode */
41
- /** @typedef {import("estree").ModuleDeclaration} ModuleDeclarationNode */
42
- /** @typedef {import("estree").NewExpression} NewExpressionNode */
19
+ /** @typedef {import("estree").AssignmentExpression} AssignmentExpression */
20
+ /** @typedef {import("estree").BinaryExpression} BinaryExpression */
21
+ /** @typedef {import("estree").BlockStatement} BlockStatement */
22
+ /** @typedef {import("estree").SequenceExpression} SequenceExpression */
23
+ /** @typedef {import("estree").CallExpression} CallExpression */
24
+ /** @typedef {import("estree").BaseCallExpression} BaseCallExpression */
25
+ /** @typedef {import("estree").StaticBlock} StaticBlock */
26
+ /** @typedef {import("estree").ImportExpression} ImportExpression */
27
+ /** @typedef {import("estree").ClassDeclaration} ClassDeclaration */
28
+ /** @typedef {import("estree").ForStatement} ForStatement */
29
+ /** @typedef {import("estree").SwitchStatement} SwitchStatement */
30
+ /** @typedef {import("estree").ExportNamedDeclaration} ExportNamedDeclaration */
31
+ /** @typedef {import("estree").ClassExpression} ClassExpression */
32
+ /** @typedef {import("estree").Comment} Comment */
33
+ /** @typedef {import("estree").ConditionalExpression} ConditionalExpression */
34
+ /** @typedef {import("estree").Declaration} Declaration */
35
+ /** @typedef {import("estree").PrivateIdentifier} PrivateIdentifier */
36
+ /** @typedef {import("estree").PropertyDefinition} PropertyDefinition */
37
+ /** @typedef {import("estree").Expression} Expression */
38
+ /** @typedef {import("estree").Identifier} Identifier */
39
+ /** @typedef {import("estree").VariableDeclaration} VariableDeclaration */
40
+ /** @typedef {import("estree").IfStatement} IfStatement */
41
+ /** @typedef {import("estree").LabeledStatement} LabeledStatement */
42
+ /** @typedef {import("estree").Literal} Literal */
43
+ /** @typedef {import("estree").LogicalExpression} LogicalExpression */
44
+ /** @typedef {import("estree").ChainExpression} ChainExpression */
45
+ /** @typedef {import("estree").MemberExpression} MemberExpression */
46
+ /** @typedef {import("estree").YieldExpression} YieldExpression */
47
+ /** @typedef {import("estree").MetaProperty} MetaProperty */
48
+ /** @typedef {import("estree").Property} Property */
49
+ /** @typedef {import("estree").AssignmentPattern} AssignmentPattern */
50
+ /** @typedef {import("estree").ChainElement} ChainElement */
51
+ /** @typedef {import("estree").Pattern} Pattern */
52
+ /** @typedef {import("estree").UpdateExpression} UpdateExpression */
53
+ /** @typedef {import("estree").ObjectExpression} ObjectExpression */
54
+ /** @typedef {import("estree").UnaryExpression} UnaryExpression */
55
+ /** @typedef {import("estree").ArrayExpression} ArrayExpression */
56
+ /** @typedef {import("estree").ArrayPattern} ArrayPattern */
57
+ /** @typedef {import("estree").AwaitExpression} AwaitExpression */
58
+ /** @typedef {import("estree").ThisExpression} ThisExpression */
59
+ /** @typedef {import("estree").RestElement} RestElement */
60
+ /** @typedef {import("estree").ObjectPattern} ObjectPattern */
61
+ /** @typedef {import("estree").SwitchCase} SwitchCase */
62
+ /** @typedef {import("estree").CatchClause} CatchClause */
63
+ /** @typedef {import("estree").VariableDeclarator} VariableDeclarator */
64
+ /** @typedef {import("estree").ForInStatement} ForInStatement */
65
+ /** @typedef {import("estree").ForOfStatement} ForOfStatement */
66
+ /** @typedef {import("estree").ReturnStatement} ReturnStatement */
67
+ /** @typedef {import("estree").WithStatement} WithStatement */
68
+ /** @typedef {import("estree").ThrowStatement} ThrowStatement */
69
+ /** @typedef {import("estree").MethodDefinition} MethodDefinition */
70
+ /** @typedef {import("estree").ModuleDeclaration} ModuleDeclaration */
71
+ /** @typedef {import("estree").NewExpression} NewExpression */
72
+ /** @typedef {import("estree").SpreadElement} SpreadElement */
73
+ /** @typedef {import("estree").FunctionExpression} FunctionExpression */
74
+ /** @typedef {import("estree").WhileStatement} WhileStatement */
75
+ /** @typedef {import("estree").ArrowFunctionExpression} ArrowFunctionExpression */
76
+ /** @typedef {import("estree").ExpressionStatement} ExpressionStatement */
77
+ /** @typedef {import("estree").FunctionDeclaration} FunctionDeclaration */
78
+ /** @typedef {import("estree").DoWhileStatement} DoWhileStatement */
79
+ /** @typedef {import("estree").TryStatement} TryStatement */
43
80
  /** @typedef {import("estree").Node} AnyNode */
44
- /** @typedef {import("estree").Program} ProgramNode */
45
- /** @typedef {import("estree").Statement} StatementNode */
46
- /** @typedef {import("estree").ImportDeclaration} ImportDeclarationNode */
47
- /** @typedef {import("estree").ExportNamedDeclaration} ExportNamedDeclarationNode */
48
- /** @typedef {import("estree").ExportDefaultDeclaration} ExportDefaultDeclarationNode */
49
- /** @typedef {import("estree").ExportAllDeclaration} ExportAllDeclarationNode */
50
- /** @typedef {import("estree").Super} SuperNode */
51
- /** @typedef {import("estree").TaggedTemplateExpression} TaggedTemplateExpressionNode */
52
- /** @typedef {import("estree").TemplateLiteral} TemplateLiteralNode */
53
- /** @typedef {import("estree").ThisExpression} ThisExpressionNode */
54
- /** @typedef {import("estree").UnaryExpression} UnaryExpressionNode */
55
- /** @typedef {import("estree").VariableDeclarator} VariableDeclaratorNode */
81
+ /** @typedef {import("estree").Program} Program */
82
+ /** @typedef {import("estree").Directive} Directive */
83
+ /** @typedef {import("estree").Statement} Statement */
84
+ /** @typedef {import("estree").ImportDeclaration} ImportDeclaration */
85
+ /** @typedef {import("estree").ExportDefaultDeclaration} ExportDefaultDeclaration */
86
+ /** @typedef {import("estree").ExportAllDeclaration} ExportAllDeclaration */
87
+ /** @typedef {import("estree").Super} Super */
88
+ /** @typedef {import("estree").TaggedTemplateExpression} TaggedTemplateExpression */
89
+ /** @typedef {import("estree").TemplateLiteral} TemplateLiteral */
90
+ /** @typedef {Record<string, any>} Assertions */
56
91
  /** @template T @typedef {import("tapable").AsArray<T>} AsArray<T> */
57
92
  /** @typedef {import("../Parser").ParserState} ParserState */
58
93
  /** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
59
94
  /** @typedef {{declaredScope: ScopeInfo, freeName: string | true, tagInfo: TagInfo | undefined}} VariableInfoInterface */
60
- /** @typedef {{ name: string | VariableInfo, rootInfo: string | VariableInfo, getMembers: () => string[], getMembersOptionals: () => boolean[] }} GetInfoResult */
95
+ /** @typedef {{ name: string | VariableInfo, rootInfo: string | VariableInfo, getMembers: () => string[], getMembersOptionals: () => boolean[], getMemberRanges: () => Range[] }} GetInfoResult */
61
96
 
62
97
  const EMPTY_ARRAY = [];
63
98
  const ALLOWED_MEMBER_TYPES_CALL_EXPRESSION = 0b01;
@@ -71,7 +106,7 @@ const parser = AcornParser.extend(importAssertions);
71
106
  class VariableInfo {
72
107
  /**
73
108
  * @param {ScopeInfo} declaredScope scope in which the variable is declared
74
- * @param {string | true} freeName which free name the variable aliases, or true when none
109
+ * @param {string | true | undefined} freeName which free name the variable aliases, or true when none
75
110
  * @param {TagInfo | undefined} tagInfo info about tags
76
111
  */
77
112
  constructor(declaredScope, freeName, tagInfo) {
@@ -82,7 +117,7 @@ class VariableInfo {
82
117
  }
83
118
 
84
119
  /** @typedef {string | ScopeInfo | VariableInfo} ExportedVariableInfo */
85
- /** @typedef {LiteralNode | string | null | undefined} ImportSource */
120
+ /** @typedef {Literal | string | null | undefined} ImportSource */
86
121
  /** @typedef {Omit<AcornOptions, "sourceType" | "ecmaVersion"> & { sourceType: "module" | "script" | "auto", ecmaVersion?: AcornOptions["ecmaVersion"] }} ParseOptions */
87
122
 
88
123
  /**
@@ -96,18 +131,55 @@ class VariableInfo {
96
131
  * @typedef {Object} ScopeInfo
97
132
  * @property {StackedMap<string, VariableInfo | ScopeInfo>} definitions
98
133
  * @property {boolean | "arrow"} topLevelScope
99
- * @property {boolean} inShorthand
134
+ * @property {boolean | string} inShorthand
135
+ * @property {boolean} inTaggedTemplateTag
136
+ * @property {boolean} inTry
100
137
  * @property {boolean} isStrict
101
138
  * @property {boolean} isAsmJs
102
- * @property {boolean} inTry
103
139
  */
104
140
 
141
+ /** @typedef {[number, number]} Range */
142
+
143
+ /**
144
+ * Helper function for joining two ranges into a single range. This is useful
145
+ * when working with AST nodes, as it allows you to combine the ranges of child nodes
146
+ * to create the range of the _parent node_.
147
+ *
148
+ * @param {[number, number]} startRange start range to join
149
+ * @param {[number, number]} endRange end range to join
150
+ * @returns {[number, number]} joined range
151
+ *
152
+ * @example
153
+ * ```js
154
+ * const startRange = [0, 5];
155
+ * const endRange = [10, 15];
156
+ * const joinedRange = joinRanges(startRange, endRange);
157
+ * console.log(joinedRange); // [0, 15]
158
+ * ```
159
+ *
160
+ */
105
161
  const joinRanges = (startRange, endRange) => {
106
162
  if (!endRange) return startRange;
107
163
  if (!startRange) return endRange;
108
164
  return [startRange[0], endRange[1]];
109
165
  };
110
166
 
167
+ /**
168
+ * Helper function used to generate a string representation of a
169
+ * [member expression](https://github.com/estree/estree/blob/master/es5.md#memberexpression).
170
+ *
171
+ * @param {string} object object to name
172
+ * @param {string[]} membersReversed reversed list of members
173
+ * @returns {string} member expression as a string
174
+ * @example
175
+ * ```js
176
+ * const membersReversed = ["property1", "property2", "property3"]; // Members parsed from the AST
177
+ * const name = objectAndMembersToName("myObject", membersReversed);
178
+ *
179
+ * console.log(name); // "myObject.property1.property2.property3"
180
+ * ```
181
+ *
182
+ */
111
183
  const objectAndMembersToName = (object, membersReversed) => {
112
184
  let name = object;
113
185
  for (let i = membersReversed.length - 1; i >= 0; i--) {
@@ -116,6 +188,16 @@ const objectAndMembersToName = (object, membersReversed) => {
116
188
  return name;
117
189
  };
118
190
 
191
+ /**
192
+ * Grabs the name of a given expression and returns it as a string or undefined. Has particular
193
+ * handling for [Identifiers](https://github.com/estree/estree/blob/master/es5.md#identifier),
194
+ * [ThisExpressions](https://github.com/estree/estree/blob/master/es5.md#identifier), and
195
+ * [MetaProperties](https://github.com/estree/estree/blob/master/es2015.md#metaproperty) which is
196
+ * specifically for handling the `new.target` meta property.
197
+ *
198
+ * @param {Expression | Super} expression expression
199
+ * @returns {string | "this" | undefined} name or variable info
200
+ */
119
201
  const getRootName = expression => {
120
202
  switch (expression.type) {
121
203
  case "Identifier":
@@ -155,81 +237,81 @@ class JavascriptParser extends Parser {
155
237
  constructor(sourceType = "auto") {
156
238
  super();
157
239
  this.hooks = Object.freeze({
158
- /** @type {HookMap<SyncBailHook<[UnaryExpressionNode], BasicEvaluatedExpression | undefined | null>>} */
240
+ /** @type {HookMap<SyncBailHook<[UnaryExpression], BasicEvaluatedExpression | undefined | null>>} */
159
241
  evaluateTypeof: new HookMap(() => new SyncBailHook(["expression"])),
160
- /** @type {HookMap<SyncBailHook<[ExpressionNode], BasicEvaluatedExpression | undefined | null>>} */
242
+ /** @type {HookMap<SyncBailHook<[Expression], BasicEvaluatedExpression | undefined | null>>} */
161
243
  evaluate: new HookMap(() => new SyncBailHook(["expression"])),
162
- /** @type {HookMap<SyncBailHook<[IdentifierNode | ThisExpressionNode | MemberExpressionNode | MetaPropertyNode], BasicEvaluatedExpression | undefined | null>>} */
244
+ /** @type {HookMap<SyncBailHook<[Identifier | ThisExpression | MemberExpression | MetaProperty], BasicEvaluatedExpression | undefined | null>>} */
163
245
  evaluateIdentifier: new HookMap(() => new SyncBailHook(["expression"])),
164
- /** @type {HookMap<SyncBailHook<[IdentifierNode | ThisExpressionNode | MemberExpressionNode], BasicEvaluatedExpression | undefined | null>>} */
246
+ /** @type {HookMap<SyncBailHook<[Identifier | ThisExpression | MemberExpression], BasicEvaluatedExpression | undefined | null>>} */
165
247
  evaluateDefinedIdentifier: new HookMap(
166
248
  () => new SyncBailHook(["expression"])
167
249
  ),
168
- /** @type {HookMap<SyncBailHook<[NewExpressionNode], BasicEvaluatedExpression | undefined | null>>} */
250
+ /** @type {HookMap<SyncBailHook<[NewExpression], BasicEvaluatedExpression | undefined | null>>} */
169
251
  evaluateNewExpression: new HookMap(
170
252
  () => new SyncBailHook(["expression"])
171
253
  ),
172
- /** @type {HookMap<SyncBailHook<[CallExpressionNode], BasicEvaluatedExpression | undefined | null>>} */
254
+ /** @type {HookMap<SyncBailHook<[CallExpression], BasicEvaluatedExpression | undefined | null>>} */
173
255
  evaluateCallExpression: new HookMap(
174
256
  () => new SyncBailHook(["expression"])
175
257
  ),
176
- /** @type {HookMap<SyncBailHook<[CallExpressionNode, BasicEvaluatedExpression | undefined], BasicEvaluatedExpression | undefined | null>>} */
258
+ /** @type {HookMap<SyncBailHook<[CallExpression, BasicEvaluatedExpression | undefined], BasicEvaluatedExpression | undefined | null>>} */
177
259
  evaluateCallExpressionMember: new HookMap(
178
260
  () => new SyncBailHook(["expression", "param"])
179
261
  ),
180
- /** @type {HookMap<SyncBailHook<[ExpressionNode | DeclarationNode | PrivateIdentifierNode, number], boolean | void>>} */
262
+ /** @type {HookMap<SyncBailHook<[Expression | Declaration | PrivateIdentifier, number], boolean | void>>} */
181
263
  isPure: new HookMap(
182
264
  () => new SyncBailHook(["expression", "commentsStartPosition"])
183
265
  ),
184
- /** @type {SyncBailHook<[StatementNode | ModuleDeclarationNode], boolean | void>} */
266
+ /** @type {SyncBailHook<[Statement | ModuleDeclaration], boolean | void>} */
185
267
  preStatement: new SyncBailHook(["statement"]),
186
268
 
187
- /** @type {SyncBailHook<[StatementNode | ModuleDeclarationNode], boolean | void>} */
269
+ /** @type {SyncBailHook<[Statement | ModuleDeclaration], boolean | void>} */
188
270
  blockPreStatement: new SyncBailHook(["declaration"]),
189
- /** @type {SyncBailHook<[StatementNode | ModuleDeclarationNode], boolean | void>} */
271
+ /** @type {SyncBailHook<[Statement | ModuleDeclaration], boolean | void>} */
190
272
  statement: new SyncBailHook(["statement"]),
191
- /** @type {SyncBailHook<[IfStatementNode], boolean | void>} */
273
+ /** @type {SyncBailHook<[IfStatement], boolean | void>} */
192
274
  statementIf: new SyncBailHook(["statement"]),
193
- /** @type {SyncBailHook<[ExpressionNode, ClassExpressionNode | ClassDeclarationNode], boolean | void>} */
275
+ /** @type {SyncBailHook<[Expression, ClassExpression | ClassDeclaration], boolean | void>} */
194
276
  classExtendsExpression: new SyncBailHook([
195
277
  "expression",
196
278
  "classDefinition"
197
279
  ]),
198
- /** @type {SyncBailHook<[MethodDefinitionNode | PropertyDefinitionNode, ClassExpressionNode | ClassDeclarationNode], boolean | void>} */
280
+ /** @type {SyncBailHook<[MethodDefinition | PropertyDefinition | StaticBlock, ClassExpression | ClassDeclaration], boolean | void>} */
199
281
  classBodyElement: new SyncBailHook(["element", "classDefinition"]),
200
- /** @type {SyncBailHook<[ExpressionNode, MethodDefinitionNode | PropertyDefinitionNode, ClassExpressionNode | ClassDeclarationNode], boolean | void>} */
282
+ /** @type {SyncBailHook<[Expression, MethodDefinition | PropertyDefinition, ClassExpression | ClassDeclaration], boolean | void>} */
201
283
  classBodyValue: new SyncBailHook([
202
284
  "expression",
203
285
  "element",
204
286
  "classDefinition"
205
287
  ]),
206
- /** @type {HookMap<SyncBailHook<[LabeledStatementNode], boolean | void>>} */
288
+ /** @type {HookMap<SyncBailHook<[LabeledStatement], boolean | void>>} */
207
289
  label: new HookMap(() => new SyncBailHook(["statement"])),
208
- /** @type {SyncBailHook<[ImportDeclarationNode, ImportSource], boolean | void>} */
290
+ /** @type {SyncBailHook<[ImportDeclaration, ImportSource], boolean | void>} */
209
291
  import: new SyncBailHook(["statement", "source"]),
210
- /** @type {SyncBailHook<[ImportDeclarationNode, ImportSource, string, string], boolean | void>} */
292
+ /** @type {SyncBailHook<[ImportDeclaration, ImportSource, string, string], boolean | void>} */
211
293
  importSpecifier: new SyncBailHook([
212
294
  "statement",
213
295
  "source",
214
296
  "exportName",
215
297
  "identifierName"
216
298
  ]),
217
- /** @type {SyncBailHook<[ExportNamedDeclarationNode | ExportAllDeclarationNode], boolean | void>} */
299
+ /** @type {SyncBailHook<[ExportNamedDeclaration | ExportAllDeclaration], boolean | void>} */
218
300
  export: new SyncBailHook(["statement"]),
219
- /** @type {SyncBailHook<[ExportNamedDeclarationNode | ExportAllDeclarationNode, ImportSource], boolean | void>} */
301
+ /** @type {SyncBailHook<[ExportNamedDeclaration | ExportAllDeclaration, ImportSource], boolean | void>} */
220
302
  exportImport: new SyncBailHook(["statement", "source"]),
221
- /** @type {SyncBailHook<[ExportNamedDeclarationNode | ExportAllDeclarationNode, DeclarationNode], boolean | void>} */
303
+ /** @type {SyncBailHook<[ExportNamedDeclaration | ExportAllDeclaration, Declaration], boolean | void>} */
222
304
  exportDeclaration: new SyncBailHook(["statement", "declaration"]),
223
- /** @type {SyncBailHook<[ExportDefaultDeclarationNode, DeclarationNode], boolean | void>} */
305
+ /** @type {SyncBailHook<[ExportDefaultDeclaration, Declaration], boolean | void>} */
224
306
  exportExpression: new SyncBailHook(["statement", "declaration"]),
225
- /** @type {SyncBailHook<[ExportNamedDeclarationNode | ExportAllDeclarationNode, string, string, number | undefined], boolean | void>} */
307
+ /** @type {SyncBailHook<[ExportNamedDeclaration | ExportAllDeclaration, string, string, number | undefined], boolean | void>} */
226
308
  exportSpecifier: new SyncBailHook([
227
309
  "statement",
228
310
  "identifierName",
229
311
  "exportName",
230
312
  "index"
231
313
  ]),
232
- /** @type {SyncBailHook<[ExportNamedDeclarationNode | ExportAllDeclarationNode, ImportSource, string, string, number | undefined], boolean | void>} */
314
+ /** @type {SyncBailHook<[ExportNamedDeclaration | ExportAllDeclaration, ImportSource, string, string, number | undefined], boolean | void>} */
233
315
  exportImportSpecifier: new SyncBailHook([
234
316
  "statement",
235
317
  "source",
@@ -237,45 +319,51 @@ class JavascriptParser extends Parser {
237
319
  "exportName",
238
320
  "index"
239
321
  ]),
240
- /** @type {SyncBailHook<[VariableDeclaratorNode, StatementNode], boolean | void>} */
322
+ /** @type {SyncBailHook<[VariableDeclarator, Statement], boolean | void>} */
241
323
  preDeclarator: new SyncBailHook(["declarator", "statement"]),
242
- /** @type {SyncBailHook<[VariableDeclaratorNode, StatementNode], boolean | void>} */
324
+ /** @type {SyncBailHook<[VariableDeclarator, Statement], boolean | void>} */
243
325
  declarator: new SyncBailHook(["declarator", "statement"]),
244
- /** @type {HookMap<SyncBailHook<[DeclarationNode], boolean | void>>} */
326
+ /** @type {HookMap<SyncBailHook<[Declaration], boolean | void>>} */
245
327
  varDeclaration: new HookMap(() => new SyncBailHook(["declaration"])),
246
- /** @type {HookMap<SyncBailHook<[DeclarationNode], boolean | void>>} */
328
+ /** @type {HookMap<SyncBailHook<[Declaration], boolean | void>>} */
247
329
  varDeclarationLet: new HookMap(() => new SyncBailHook(["declaration"])),
248
- /** @type {HookMap<SyncBailHook<[DeclarationNode], boolean | void>>} */
330
+ /** @type {HookMap<SyncBailHook<[Declaration], boolean | void>>} */
249
331
  varDeclarationConst: new HookMap(() => new SyncBailHook(["declaration"])),
250
- /** @type {HookMap<SyncBailHook<[DeclarationNode], boolean | void>>} */
332
+ /** @type {HookMap<SyncBailHook<[Declaration], boolean | void>>} */
251
333
  varDeclarationVar: new HookMap(() => new SyncBailHook(["declaration"])),
252
- /** @type {HookMap<SyncBailHook<[IdentifierNode], boolean | void>>} */
334
+ /** @type {HookMap<SyncBailHook<[Identifier], boolean | void>>} */
253
335
  pattern: new HookMap(() => new SyncBailHook(["pattern"])),
254
- /** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
336
+ /** @type {HookMap<SyncBailHook<[Expression], boolean | void>>} */
255
337
  canRename: new HookMap(() => new SyncBailHook(["initExpression"])),
256
- /** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
338
+ /** @type {HookMap<SyncBailHook<[Expression], boolean | void>>} */
257
339
  rename: new HookMap(() => new SyncBailHook(["initExpression"])),
258
- /** @type {HookMap<SyncBailHook<[import("estree").AssignmentExpression], boolean | void>>} */
340
+ /** @type {HookMap<SyncBailHook<[AssignmentExpression], boolean | void>>} */
259
341
  assign: new HookMap(() => new SyncBailHook(["expression"])),
260
- /** @type {HookMap<SyncBailHook<[import("estree").AssignmentExpression, string[]], boolean | void>>} */
342
+ /** @type {HookMap<SyncBailHook<[AssignmentExpression, string[]], boolean | void>>} */
261
343
  assignMemberChain: new HookMap(
262
344
  () => new SyncBailHook(["expression", "members"])
263
345
  ),
264
- /** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
346
+ /** @type {HookMap<SyncBailHook<[Expression], boolean | void>>} */
265
347
  typeof: new HookMap(() => new SyncBailHook(["expression"])),
266
- /** @type {SyncBailHook<[ExpressionNode], boolean | void>} */
348
+ /** @type {SyncBailHook<[ImportExpression], boolean | void>} */
267
349
  importCall: new SyncBailHook(["expression"]),
268
- /** @type {SyncBailHook<[ExpressionNode], boolean | void>} */
350
+ /** @type {SyncBailHook<[Expression], boolean | void>} */
269
351
  topLevelAwait: new SyncBailHook(["expression"]),
270
- /** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
352
+ /** @type {HookMap<SyncBailHook<[CallExpression], boolean | void>>} */
271
353
  call: new HookMap(() => new SyncBailHook(["expression"])),
272
354
  /** Something like "a.b()" */
273
- /** @type {HookMap<SyncBailHook<[CallExpressionNode, string[], boolean[]], boolean | void>>} */
355
+ /** @type {HookMap<SyncBailHook<[CallExpression, string[], boolean[], Range[]], boolean | void>>} */
274
356
  callMemberChain: new HookMap(
275
- () => new SyncBailHook(["expression", "members", "membersOptionals"])
357
+ () =>
358
+ new SyncBailHook([
359
+ "expression",
360
+ "members",
361
+ "membersOptionals",
362
+ "memberRanges"
363
+ ])
276
364
  ),
277
365
  /** Something like "a.b().c.d" */
278
- /** @type {HookMap<SyncBailHook<[ExpressionNode, string[], CallExpressionNode, string[]], boolean | void>>} */
366
+ /** @type {HookMap<SyncBailHook<[Expression, string[], CallExpression, string[]], boolean | void>>} */
279
367
  memberChainOfCallMemberChain: new HookMap(
280
368
  () =>
281
369
  new SyncBailHook([
@@ -286,7 +374,7 @@ class JavascriptParser extends Parser {
286
374
  ])
287
375
  ),
288
376
  /** Something like "a.b().c.d()"" */
289
- /** @type {HookMap<SyncBailHook<[ExpressionNode, string[], CallExpressionNode, string[]], boolean | void>>} */
377
+ /** @type {HookMap<SyncBailHook<[CallExpression, string[], CallExpression, string[]], boolean | void>>} */
290
378
  callMemberChainOfCallMemberChain: new HookMap(
291
379
  () =>
292
380
  new SyncBailHook([
@@ -296,29 +384,35 @@ class JavascriptParser extends Parser {
296
384
  "members"
297
385
  ])
298
386
  ),
299
- /** @type {SyncBailHook<[ChainExpressionNode], boolean | void>} */
387
+ /** @type {SyncBailHook<[ChainExpression], boolean | void>} */
300
388
  optionalChaining: new SyncBailHook(["optionalChaining"]),
301
- /** @type {HookMap<SyncBailHook<[NewExpressionNode], boolean | void>>} */
389
+ /** @type {HookMap<SyncBailHook<[NewExpression], boolean | void>>} */
302
390
  new: new HookMap(() => new SyncBailHook(["expression"])),
303
- /** @type {SyncBailHook<[BinaryExpressionNode], boolean | void>} */
391
+ /** @type {SyncBailHook<[BinaryExpression], boolean | void>} */
304
392
  binaryExpression: new SyncBailHook(["binaryExpression"]),
305
- /** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
393
+ /** @type {HookMap<SyncBailHook<[Expression], boolean | void>>} */
306
394
  expression: new HookMap(() => new SyncBailHook(["expression"])),
307
- /** @type {HookMap<SyncBailHook<[ExpressionNode, string[], boolean[]], boolean | void>>} */
395
+ /** @type {HookMap<SyncBailHook<[MemberExpression, string[], boolean[], Range[]], boolean | void>>} */
308
396
  expressionMemberChain: new HookMap(
309
- () => new SyncBailHook(["expression", "members", "membersOptionals"])
397
+ () =>
398
+ new SyncBailHook([
399
+ "expression",
400
+ "members",
401
+ "membersOptionals",
402
+ "memberRanges"
403
+ ])
310
404
  ),
311
- /** @type {HookMap<SyncBailHook<[ExpressionNode, string[]], boolean | void>>} */
405
+ /** @type {HookMap<SyncBailHook<[MemberExpression, string[]], boolean | void>>} */
312
406
  unhandledExpressionMemberChain: new HookMap(
313
407
  () => new SyncBailHook(["expression", "members"])
314
408
  ),
315
- /** @type {SyncBailHook<[ExpressionNode], boolean | void>} */
409
+ /** @type {SyncBailHook<[ConditionalExpression], boolean | void>} */
316
410
  expressionConditionalOperator: new SyncBailHook(["expression"]),
317
- /** @type {SyncBailHook<[ExpressionNode], boolean | void>} */
411
+ /** @type {SyncBailHook<[LogicalExpression], boolean | void>} */
318
412
  expressionLogicalOperator: new SyncBailHook(["expression"]),
319
- /** @type {SyncBailHook<[ProgramNode, CommentNode[]], boolean | void>} */
413
+ /** @type {SyncBailHook<[Program, Comment[]], boolean | void>} */
320
414
  program: new SyncBailHook(["ast", "comments"]),
321
- /** @type {SyncBailHook<[ProgramNode, CommentNode[]], boolean | void>} */
415
+ /** @type {SyncBailHook<[Program, Comment[]], boolean | void>} */
322
416
  finish: new SyncBailHook(["ast", "comments"])
323
417
  });
324
418
  this.sourceType = sourceType;
@@ -328,46 +422,51 @@ class JavascriptParser extends Parser {
328
422
  this.state = undefined;
329
423
  this.comments = undefined;
330
424
  this.semicolons = undefined;
331
- /** @type {(StatementNode|ExpressionNode)[]} */
425
+ /** @type {(Statement | ModuleDeclaration | Expression)[]} */
332
426
  this.statementPath = undefined;
427
+ /** @type {Statement | ModuleDeclaration | Expression | undefined} */
333
428
  this.prevStatement = undefined;
429
+ /** @type {WeakMap<Expression, Set<string>>} */
430
+ this.destructuringAssignmentProperties = undefined;
334
431
  this.currentTagData = undefined;
335
432
  this._initializeEvaluating();
336
433
  }
337
434
 
338
435
  _initializeEvaluating() {
339
436
  this.hooks.evaluate.for("Literal").tap("JavascriptParser", _expr => {
340
- const expr = /** @type {LiteralNode} */ (_expr);
437
+ const expr = /** @type {Literal} */ (_expr);
341
438
 
342
439
  switch (typeof expr.value) {
343
440
  case "number":
344
441
  return new BasicEvaluatedExpression()
345
442
  .setNumber(expr.value)
346
- .setRange(expr.range);
443
+ .setRange(/** @type {Range} */ (expr.range));
347
444
  case "bigint":
348
445
  return new BasicEvaluatedExpression()
349
446
  .setBigInt(expr.value)
350
- .setRange(expr.range);
447
+ .setRange(/** @type {Range} */ (expr.range));
351
448
  case "string":
352
449
  return new BasicEvaluatedExpression()
353
450
  .setString(expr.value)
354
- .setRange(expr.range);
451
+ .setRange(/** @type {Range} */ (expr.range));
355
452
  case "boolean":
356
453
  return new BasicEvaluatedExpression()
357
454
  .setBoolean(expr.value)
358
- .setRange(expr.range);
455
+ .setRange(/** @type {Range} */ (expr.range));
359
456
  }
360
457
  if (expr.value === null) {
361
- return new BasicEvaluatedExpression().setNull().setRange(expr.range);
458
+ return new BasicEvaluatedExpression()
459
+ .setNull()
460
+ .setRange(/** @type {Range} */ (expr.range));
362
461
  }
363
462
  if (expr.value instanceof RegExp) {
364
463
  return new BasicEvaluatedExpression()
365
464
  .setRegExp(expr.value)
366
- .setRange(expr.range);
465
+ .setRange(/** @type {Range} */ (expr.range));
367
466
  }
368
467
  });
369
468
  this.hooks.evaluate.for("NewExpression").tap("JavascriptParser", _expr => {
370
- const expr = /** @type {NewExpressionNode} */ (_expr);
469
+ const expr = /** @type {NewExpression} */ (_expr);
371
470
  const callee = expr.callee;
372
471
  if (callee.type !== "Identifier") return;
373
472
  if (callee.name !== "RegExp") {
@@ -398,7 +497,7 @@ class JavascriptParser extends Parser {
398
497
  } else {
399
498
  return new BasicEvaluatedExpression()
400
499
  .setRegExp(new RegExp(""))
401
- .setRange(expr.range);
500
+ .setRange(/** @type {Range} */ (expr.range));
402
501
  }
403
502
 
404
503
  const arg2 = expr.arguments[1];
@@ -423,12 +522,12 @@ class JavascriptParser extends Parser {
423
522
 
424
523
  return new BasicEvaluatedExpression()
425
524
  .setRegExp(flags ? new RegExp(regExp, flags) : new RegExp(regExp))
426
- .setRange(expr.range);
525
+ .setRange(/** @type {Range} */ (expr.range));
427
526
  });
428
527
  this.hooks.evaluate
429
528
  .for("LogicalExpression")
430
529
  .tap("JavascriptParser", _expr => {
431
- const expr = /** @type {LogicalExpressionNode} */ (_expr);
530
+ const expr = /** @type {LogicalExpression} */ (_expr);
432
531
 
433
532
  const left = this.evaluateExpression(expr.left);
434
533
  let returnRight = false;
@@ -467,44 +566,94 @@ class JavascriptParser extends Parser {
467
566
  }
468
567
  });
469
568
 
569
+ /**
570
+ * In simple logical cases, we can use valueAsExpression to assist us in evaluating the expression on
571
+ * either side of a [BinaryExpression](https://github.com/estree/estree/blob/master/es5.md#binaryexpression).
572
+ * This supports scenarios in webpack like conditionally `import()`'ing modules based on some simple evaluation:
573
+ *
574
+ * ```js
575
+ * if (1 === 3) {
576
+ * import("./moduleA"); // webpack will auto evaluate this and not import the modules
577
+ * }
578
+ * ```
579
+ *
580
+ * Additional scenarios include evaluation of strings inside of dynamic import statements:
581
+ *
582
+ * ```js
583
+ * const foo = "foo";
584
+ * const bar = "bar";
585
+ *
586
+ * import("./" + foo + bar); // webpack will auto evaluate this into import("./foobar")
587
+ * ```
588
+ * @param {boolean | number | BigInt | string} value the value to convert to an expression
589
+ * @param {BinaryExpression | UnaryExpression} expr the expression being evaluated
590
+ * @param {boolean} sideEffects whether the expression has side effects
591
+ * @returns {BasicEvaluatedExpression | undefined} the evaluated expression
592
+ * @example
593
+ *
594
+ * ```js
595
+ * const binaryExpr = new BinaryExpression("+",
596
+ * { type: "Literal", value: 2 },
597
+ * { type: "Literal", value: 3 }
598
+ * );
599
+ *
600
+ * const leftValue = 2;
601
+ * const rightValue = 3;
602
+ *
603
+ * const leftExpr = valueAsExpression(leftValue, binaryExpr.left, false);
604
+ * const rightExpr = valueAsExpression(rightValue, binaryExpr.right, false);
605
+ * const result = new BasicEvaluatedExpression()
606
+ * .setNumber(leftExpr.number + rightExpr.number)
607
+ * .setRange(binaryExpr.range);
608
+ *
609
+ * console.log(result.number); // Output: 5
610
+ * ```
611
+ */
470
612
  const valueAsExpression = (value, expr, sideEffects) => {
471
613
  switch (typeof value) {
472
614
  case "boolean":
473
615
  return new BasicEvaluatedExpression()
474
616
  .setBoolean(value)
475
617
  .setSideEffects(sideEffects)
476
- .setRange(expr.range);
618
+ .setRange(/** @type {Range} */ (expr.range));
477
619
  case "number":
478
620
  return new BasicEvaluatedExpression()
479
621
  .setNumber(value)
480
622
  .setSideEffects(sideEffects)
481
- .setRange(expr.range);
623
+ .setRange(/** @type {Range} */ (expr.range));
482
624
  case "bigint":
483
625
  return new BasicEvaluatedExpression()
484
626
  .setBigInt(value)
485
627
  .setSideEffects(sideEffects)
486
- .setRange(expr.range);
628
+ .setRange(/** @type {Range} */ (expr.range));
487
629
  case "string":
488
630
  return new BasicEvaluatedExpression()
489
631
  .setString(value)
490
632
  .setSideEffects(sideEffects)
491
- .setRange(expr.range);
633
+ .setRange(/** @type {Range} */ (expr.range));
492
634
  }
493
635
  };
494
636
 
495
637
  this.hooks.evaluate
496
638
  .for("BinaryExpression")
497
639
  .tap("JavascriptParser", _expr => {
498
- const expr = /** @type {BinaryExpressionNode} */ (_expr);
499
-
500
- const handleConstOperation = fn => {
640
+ const expr = /** @type {BinaryExpression} */ (_expr);
641
+
642
+ /**
643
+ * Evaluates a binary expression if and only if it is a const operation (e.g. 1 + 2, "a" + "b", etc.).
644
+ *
645
+ * @template T
646
+ * @param {(leftOperand: T, rightOperand: T) => boolean | number | BigInt | string} operandHandler the handler for the operation (e.g. (a, b) => a + b)
647
+ * @returns {BasicEvaluatedExpression | undefined} the evaluated expression
648
+ */
649
+ const handleConstOperation = operandHandler => {
501
650
  const left = this.evaluateExpression(expr.left);
502
651
  if (!left.isCompileTimeValue()) return;
503
652
 
504
653
  const right = this.evaluateExpression(expr.right);
505
654
  if (!right.isCompileTimeValue()) return;
506
655
 
507
- const result = fn(
656
+ const result = operandHandler(
508
657
  left.asCompileTimeValue(),
509
658
  right.asCompileTimeValue()
510
659
  );
@@ -515,6 +664,14 @@ class JavascriptParser extends Parser {
515
664
  );
516
665
  };
517
666
 
667
+ /**
668
+ * Helper function to determine if two booleans are always different. This is used in `handleStrictEqualityComparison`
669
+ * to determine if an expressions boolean or nullish conversion is equal or not.
670
+ *
671
+ * @param {boolean} a first boolean to compare
672
+ * @param {boolean} b second boolean to compare
673
+ * @returns {boolean} true if the two booleans are always different, false otherwise
674
+ */
518
675
  const isAlwaysDifferent = (a, b) =>
519
676
  (a === true && b === false) || (a === false && b === true);
520
677
 
@@ -543,11 +700,13 @@ class JavascriptParser extends Parser {
543
700
  const rightSuffix = getSuffix(right.parts);
544
701
  const lenPrefix = Math.min(leftPrefix.length, rightPrefix.length);
545
702
  const lenSuffix = Math.min(leftSuffix.length, rightSuffix.length);
546
- if (
547
- leftPrefix.slice(0, lenPrefix) !==
548
- rightPrefix.slice(0, lenPrefix) ||
549
- leftSuffix.slice(-lenSuffix) !== rightSuffix.slice(-lenSuffix)
550
- ) {
703
+ const prefixMismatch =
704
+ lenPrefix > 0 &&
705
+ leftPrefix.slice(0, lenPrefix) !== rightPrefix.slice(0, lenPrefix);
706
+ const suffixMismatch =
707
+ lenSuffix > 0 &&
708
+ leftSuffix.slice(-lenSuffix) !== rightSuffix.slice(-lenSuffix);
709
+ if (prefixMismatch || suffixMismatch) {
551
710
  return res
552
711
  .setBoolean(!eql)
553
712
  .setSideEffects(
@@ -556,11 +715,16 @@ class JavascriptParser extends Parser {
556
715
  }
557
716
  };
558
717
 
718
+ /**
719
+ * Helper function to handle BinaryExpressions using strict equality comparisons (e.g. "===" and "!==").
720
+ * @param {boolean} eql true for "===" and false for "!=="
721
+ * @returns {BasicEvaluatedExpression | undefined} the evaluated expression
722
+ */
559
723
  const handleStrictEqualityComparison = eql => {
560
724
  const left = this.evaluateExpression(expr.left);
561
725
  const right = this.evaluateExpression(expr.right);
562
726
  const res = new BasicEvaluatedExpression();
563
- res.setRange(expr.range);
727
+ res.setRange(/** @type {Range} */ (expr.range));
564
728
 
565
729
  const leftConst = left.isCompileTimeValue();
566
730
  const rightConst = right.isCompileTimeValue();
@@ -598,8 +762,14 @@ class JavascriptParser extends Parser {
598
762
  (rightPrimitive === false &&
599
763
  (rightConst || leftPrimitive === true)) ||
600
764
  // Different nullish or boolish status also means not equal
601
- isAlwaysDifferent(left.asBool(), right.asBool()) ||
602
- isAlwaysDifferent(left.asNullish(), right.asNullish())
765
+ isAlwaysDifferent(
766
+ /** @type {boolean} */ (left.asBool()),
767
+ /** @type {boolean} */ (right.asBool())
768
+ ) ||
769
+ isAlwaysDifferent(
770
+ /** @type {boolean} */ (left.asNullish()),
771
+ /** @type {boolean} */ (right.asNullish())
772
+ )
603
773
  ) {
604
774
  return res
605
775
  .setBoolean(!eql)
@@ -609,6 +779,11 @@ class JavascriptParser extends Parser {
609
779
  }
610
780
  };
611
781
 
782
+ /**
783
+ * Helper function to handle BinaryExpressions using abstract equality comparisons (e.g. "==" and "!=").
784
+ * @param {boolean} eql true for "==" and false for "!="
785
+ * @returns {BasicEvaluatedExpression | undefined} the evaluated expression
786
+ */
612
787
  const handleAbstractEqualityComparison = eql => {
613
788
  const left = this.evaluateExpression(expr.left);
614
789
  const right = this.evaluateExpression(expr.right);
@@ -819,12 +994,19 @@ class JavascriptParser extends Parser {
819
994
  this.hooks.evaluate
820
995
  .for("UnaryExpression")
821
996
  .tap("JavascriptParser", _expr => {
822
- const expr = /** @type {UnaryExpressionNode} */ (_expr);
823
-
824
- const handleConstOperation = fn => {
997
+ const expr = /** @type {UnaryExpression} */ (_expr);
998
+
999
+ /**
1000
+ * Evaluates a UnaryExpression if and only if it is a basic const operator (e.g. +a, -a, ~a).
1001
+ *
1002
+ * @template T
1003
+ * @param {(operand: T) => boolean | number | BigInt | string} operandHandler handler for the operand
1004
+ * @returns {BasicEvaluatedExpression | undefined} evaluated expression
1005
+ */
1006
+ const handleConstOperation = operandHandler => {
825
1007
  const argument = this.evaluateExpression(expr.argument);
826
1008
  if (!argument.isCompileTimeValue()) return;
827
- const result = fn(argument.asCompileTimeValue());
1009
+ const result = operandHandler(argument.asCompileTimeValue());
828
1010
  return valueAsExpression(
829
1011
  result,
830
1012
  expr,
@@ -942,7 +1124,7 @@ class JavascriptParser extends Parser {
942
1124
  .setRange(expr.range);
943
1125
  });
944
1126
  this.hooks.evaluate.for("Identifier").tap("JavascriptParser", expr => {
945
- if (/** @type {IdentifierNode} */ (expr).name === "undefined") {
1127
+ if (/** @type {Identifier} */ (expr).name === "undefined") {
946
1128
  return new BasicEvaluatedExpression()
947
1129
  .setUndefined()
948
1130
  .setRange(expr.range);
@@ -950,16 +1132,16 @@ class JavascriptParser extends Parser {
950
1132
  });
951
1133
  /**
952
1134
  * @param {string} exprType expression type name
953
- * @param {function(ExpressionNode): GetInfoResult | undefined} getInfo get info
1135
+ * @param {function(Expression): GetInfoResult | undefined} getInfo get info
954
1136
  * @returns {void}
955
1137
  */
956
1138
  const tapEvaluateWithVariableInfo = (exprType, getInfo) => {
957
- /** @type {ExpressionNode | undefined} */
1139
+ /** @type {Expression | undefined} */
958
1140
  let cachedExpression = undefined;
959
1141
  /** @type {GetInfoResult | undefined} */
960
1142
  let cachedInfo = undefined;
961
1143
  this.hooks.evaluate.for(exprType).tap("JavascriptParser", expr => {
962
- const expression = /** @type {MemberExpressionNode} */ (expr);
1144
+ const expression = /** @type {MemberExpression} */ (expr);
963
1145
 
964
1146
  const info = getInfo(expr);
965
1147
  if (info !== undefined) {
@@ -990,7 +1172,8 @@ class JavascriptParser extends Parser {
990
1172
  info.name,
991
1173
  info.rootInfo,
992
1174
  info.getMembers,
993
- info.getMembersOptionals
1175
+ info.getMembersOptionals,
1176
+ info.getMemberRanges
994
1177
  )
995
1178
  .setRange(expr.range);
996
1179
  }
@@ -1001,9 +1184,7 @@ class JavascriptParser extends Parser {
1001
1184
  });
1002
1185
  };
1003
1186
  tapEvaluateWithVariableInfo("Identifier", expr => {
1004
- const info = this.getVariableInfo(
1005
- /** @type {IdentifierNode} */ (expr).name
1006
- );
1187
+ const info = this.getVariableInfo(/** @type {Identifier} */ (expr).name);
1007
1188
  if (
1008
1189
  typeof info === "string" ||
1009
1190
  (info instanceof VariableInfo && typeof info.freeName === "string")
@@ -1012,7 +1193,8 @@ class JavascriptParser extends Parser {
1012
1193
  name: info,
1013
1194
  rootInfo: info,
1014
1195
  getMembers: () => [],
1015
- getMembersOptionals: () => []
1196
+ getMembersOptionals: () => [],
1197
+ getMemberRanges: () => []
1016
1198
  };
1017
1199
  }
1018
1200
  });
@@ -1026,12 +1208,13 @@ class JavascriptParser extends Parser {
1026
1208
  name: info,
1027
1209
  rootInfo: info,
1028
1210
  getMembers: () => [],
1029
- getMembersOptionals: () => []
1211
+ getMembersOptionals: () => [],
1212
+ getMemberRanges: () => []
1030
1213
  };
1031
1214
  }
1032
1215
  });
1033
1216
  this.hooks.evaluate.for("MetaProperty").tap("JavascriptParser", expr => {
1034
- const metaProperty = /** @type {MetaPropertyNode} */ (expr);
1217
+ const metaProperty = /** @type {MetaProperty} */ (expr);
1035
1218
 
1036
1219
  return this.callHooksForName(
1037
1220
  this.hooks.evaluateIdentifier,
@@ -1041,13 +1224,13 @@ class JavascriptParser extends Parser {
1041
1224
  });
1042
1225
  tapEvaluateWithVariableInfo("MemberExpression", expr =>
1043
1226
  this.getMemberExpressionInfo(
1044
- /** @type {MemberExpressionNode} */ (expr),
1227
+ /** @type {MemberExpression} */ (expr),
1045
1228
  ALLOWED_MEMBER_TYPES_EXPRESSION
1046
1229
  )
1047
1230
  );
1048
1231
 
1049
1232
  this.hooks.evaluate.for("CallExpression").tap("JavascriptParser", _expr => {
1050
- const expr = /** @type {CallExpressionNode} */ (_expr);
1233
+ const expr = /** @type {CallExpression} */ (_expr);
1051
1234
  if (
1052
1235
  expr.callee.type === "MemberExpression" &&
1053
1236
  expr.callee.property.type ===
@@ -1055,7 +1238,7 @@ class JavascriptParser extends Parser {
1055
1238
  ) {
1056
1239
  // type Super also possible here
1057
1240
  const param = this.evaluateExpression(
1058
- /** @type {ExpressionNode} */ (expr.callee.object)
1241
+ /** @type {Expression} */ (expr.callee.object)
1059
1242
  );
1060
1243
  const property =
1061
1244
  expr.callee.property.type === "Literal"
@@ -1153,7 +1336,7 @@ class JavascriptParser extends Parser {
1153
1336
 
1154
1337
  /**
1155
1338
  * @param {"cooked" | "raw"} kind kind of values to get
1156
- * @param {TemplateLiteralNode} templateLiteralExpr TemplateLiteral expr
1339
+ * @param {TemplateLiteral} templateLiteralExpr TemplateLiteral expr
1157
1340
  * @returns {{quasis: BasicEvaluatedExpression[], parts: BasicEvaluatedExpression[]}} Simplified template
1158
1341
  */
1159
1342
  const getSimplifiedTemplateResult = (kind, templateLiteralExpr) => {
@@ -1190,7 +1373,7 @@ class JavascriptParser extends Parser {
1190
1373
 
1191
1374
  const part = new BasicEvaluatedExpression()
1192
1375
  .setString(quasi)
1193
- .setRange(quasiExpr.range)
1376
+ .setRange(/** @type {Range} */ (quasiExpr.range))
1194
1377
  .setExpression(quasiExpr);
1195
1378
  quasis.push(part);
1196
1379
  parts.push(part);
@@ -1204,20 +1387,20 @@ class JavascriptParser extends Parser {
1204
1387
  this.hooks.evaluate
1205
1388
  .for("TemplateLiteral")
1206
1389
  .tap("JavascriptParser", _node => {
1207
- const node = /** @type {TemplateLiteralNode} */ (_node);
1390
+ const node = /** @type {TemplateLiteral} */ (_node);
1208
1391
 
1209
1392
  const { quasis, parts } = getSimplifiedTemplateResult("cooked", node);
1210
1393
  if (parts.length === 1) {
1211
- return parts[0].setRange(node.range);
1394
+ return parts[0].setRange(/** @type {Range} */ (node.range));
1212
1395
  }
1213
1396
  return new BasicEvaluatedExpression()
1214
1397
  .setTemplateString(quasis, parts, "cooked")
1215
- .setRange(node.range);
1398
+ .setRange(/** @type {Range} */ (node.range));
1216
1399
  });
1217
1400
  this.hooks.evaluate
1218
1401
  .for("TaggedTemplateExpression")
1219
1402
  .tap("JavascriptParser", _node => {
1220
- const node = /** @type {TaggedTemplateExpressionNode} */ (_node);
1403
+ const node = /** @type {TaggedTemplateExpression} */ (_node);
1221
1404
  const tag = this.evaluateExpression(node.tag);
1222
1405
 
1223
1406
  if (tag.isIdentifier() && tag.identifier === "String.raw") {
@@ -1227,7 +1410,7 @@ class JavascriptParser extends Parser {
1227
1410
  );
1228
1411
  return new BasicEvaluatedExpression()
1229
1412
  .setTemplateString(quasis, parts, "raw")
1230
- .setRange(node.range);
1413
+ .setRange(/** @type {Range} */ (node.range));
1231
1414
  }
1232
1415
  });
1233
1416
 
@@ -1257,10 +1440,10 @@ class JavascriptParser extends Parser {
1257
1440
  : "" + argExpr.number;
1258
1441
 
1259
1442
  const newString = value + (stringSuffix ? stringSuffix.string : "");
1260
- const newRange = [
1443
+ const newRange = /** @type {Range} */ ([
1261
1444
  argExpr.range[0],
1262
1445
  (stringSuffix || argExpr).range[1]
1263
- ];
1446
+ ]);
1264
1447
  stringSuffix = new BasicEvaluatedExpression()
1265
1448
  .setString(newString)
1266
1449
  .setSideEffects(
@@ -1317,12 +1500,12 @@ class JavascriptParser extends Parser {
1317
1500
  return new BasicEvaluatedExpression()
1318
1501
  .setArray(result)
1319
1502
  .setSideEffects(param.couldHaveSideEffects())
1320
- .setRange(expr.range);
1503
+ .setRange(/** @type {Range} */ (expr.range));
1321
1504
  });
1322
1505
  this.hooks.evaluate
1323
1506
  .for("ConditionalExpression")
1324
1507
  .tap("JavascriptParser", _expr => {
1325
- const expr = /** @type {ConditionalExpressionNode} */ (_expr);
1508
+ const expr = /** @type {ConditionalExpression} */ (_expr);
1326
1509
 
1327
1510
  const condition = this.evaluateExpression(expr.test);
1328
1511
  const conditionValue = condition.asBool();
@@ -1332,12 +1515,16 @@ class JavascriptParser extends Parser {
1332
1515
  const alternate = this.evaluateExpression(expr.alternate);
1333
1516
  res = new BasicEvaluatedExpression();
1334
1517
  if (consequent.isConditional()) {
1335
- res.setOptions(consequent.options);
1518
+ res.setOptions(
1519
+ /** @type {BasicEvaluatedExpression[]} */ (consequent.options)
1520
+ );
1336
1521
  } else {
1337
1522
  res.setOptions([consequent]);
1338
1523
  }
1339
1524
  if (alternate.isConditional()) {
1340
- res.addOptions(alternate.options);
1525
+ res.addOptions(
1526
+ /** @type {BasicEvaluatedExpression[]} */ (alternate.options)
1527
+ );
1341
1528
  } else {
1342
1529
  res.addOptions([alternate]);
1343
1530
  }
@@ -1347,13 +1534,13 @@ class JavascriptParser extends Parser {
1347
1534
  );
1348
1535
  if (condition.couldHaveSideEffects()) res.setSideEffects();
1349
1536
  }
1350
- res.setRange(expr.range);
1537
+ res.setRange(/** @type {Range} */ (expr.range));
1351
1538
  return res;
1352
1539
  });
1353
1540
  this.hooks.evaluate
1354
1541
  .for("ArrayExpression")
1355
1542
  .tap("JavascriptParser", _expr => {
1356
- const expr = /** @type {ArrayExpressionNode} */ (_expr);
1543
+ const expr = /** @type {ArrayExpression} */ (_expr);
1357
1544
 
1358
1545
  const items = expr.elements.map(element => {
1359
1546
  return (
@@ -1365,15 +1552,15 @@ class JavascriptParser extends Parser {
1365
1552
  if (!items.every(Boolean)) return;
1366
1553
  return new BasicEvaluatedExpression()
1367
1554
  .setItems(items)
1368
- .setRange(expr.range);
1555
+ .setRange(/** @type {Range} */ (expr.range));
1369
1556
  });
1370
1557
  this.hooks.evaluate
1371
1558
  .for("ChainExpression")
1372
1559
  .tap("JavascriptParser", _expr => {
1373
- const expr = /** @type {ChainExpressionNode} */ (_expr);
1374
- /** @type {ExpressionNode[]} */
1560
+ const expr = /** @type {ChainExpression} */ (_expr);
1561
+ /** @type {Expression[]} */
1375
1562
  const optionalExpressionsStack = [];
1376
- /** @type {ExpressionNode|SuperNode} */
1563
+ /** @type {Expression|Super} */
1377
1564
  let next = expr.expression;
1378
1565
 
1379
1566
  while (
@@ -1384,7 +1571,7 @@ class JavascriptParser extends Parser {
1384
1571
  if (next.optional) {
1385
1572
  // SuperNode can not be optional
1386
1573
  optionalExpressionsStack.push(
1387
- /** @type {ExpressionNode} */ (next.object)
1574
+ /** @type {Expression} */ (next.object)
1388
1575
  );
1389
1576
  }
1390
1577
  next = next.object;
@@ -1392,7 +1579,7 @@ class JavascriptParser extends Parser {
1392
1579
  if (next.optional) {
1393
1580
  // SuperNode can not be optional
1394
1581
  optionalExpressionsStack.push(
1395
- /** @type {ExpressionNode} */ (next.callee)
1582
+ /** @type {Expression} */ (next.callee)
1396
1583
  );
1397
1584
  }
1398
1585
  next = next.callee;
@@ -1400,17 +1587,32 @@ class JavascriptParser extends Parser {
1400
1587
  }
1401
1588
 
1402
1589
  while (optionalExpressionsStack.length > 0) {
1403
- const expression = optionalExpressionsStack.pop();
1590
+ const expression =
1591
+ /** @type {Expression} */
1592
+ (optionalExpressionsStack.pop());
1404
1593
  const evaluated = this.evaluateExpression(expression);
1405
1594
 
1406
1595
  if (evaluated.asNullish()) {
1407
- return evaluated.setRange(_expr.range);
1596
+ return evaluated.setRange(/** @type {Range} */ (_expr.range));
1408
1597
  }
1409
1598
  }
1410
1599
  return this.evaluateExpression(expr.expression);
1411
1600
  });
1412
1601
  }
1413
1602
 
1603
+ /**
1604
+ * @param {Expression} node node
1605
+ * @returns {Set<string>|undefined} destructured identifiers
1606
+ */
1607
+ destructuringAssignmentPropertiesFor(node) {
1608
+ if (!this.destructuringAssignmentProperties) return undefined;
1609
+ return this.destructuringAssignmentProperties.get(node);
1610
+ }
1611
+
1612
+ /**
1613
+ * @param {Expression} expr expression
1614
+ * @returns {string | VariableInfoInterface | undefined} identifier
1615
+ */
1414
1616
  getRenameIdentifier(expr) {
1415
1617
  const result = this.evaluateExpression(expr);
1416
1618
  if (result.isIdentifier()) {
@@ -1419,7 +1621,7 @@ class JavascriptParser extends Parser {
1419
1621
  }
1420
1622
 
1421
1623
  /**
1422
- * @param {ClassExpressionNode | ClassDeclarationNode} classy a class node
1624
+ * @param {ClassExpression | ClassDeclaration} classy a class node
1423
1625
  * @returns {void}
1424
1626
  */
1425
1627
  walkClass(classy) {
@@ -1429,36 +1631,47 @@ class JavascriptParser extends Parser {
1429
1631
  }
1430
1632
  }
1431
1633
  if (classy.body && classy.body.type === "ClassBody") {
1432
- for (const classElement of /** @type {TODO} */ (classy.body.body)) {
1433
- if (!this.hooks.classBodyElement.call(classElement, classy)) {
1434
- if (classElement.computed && classElement.key) {
1435
- this.walkExpression(classElement.key);
1436
- }
1437
- if (classElement.value) {
1438
- if (
1439
- !this.hooks.classBodyValue.call(
1440
- classElement.value,
1441
- classElement,
1442
- classy
1443
- )
1444
- ) {
1634
+ const scopeParams = [];
1635
+ // Add class name in scope for recursive calls
1636
+ if (classy.id) {
1637
+ scopeParams.push(classy.id);
1638
+ }
1639
+ this.inClassScope(true, scopeParams, () => {
1640
+ for (const classElement of /** @type {TODO} */ (classy.body.body)) {
1641
+ if (!this.hooks.classBodyElement.call(classElement, classy)) {
1642
+ if (classElement.computed && classElement.key) {
1643
+ this.walkExpression(classElement.key);
1644
+ }
1645
+ if (classElement.value) {
1646
+ if (
1647
+ !this.hooks.classBodyValue.call(
1648
+ classElement.value,
1649
+ classElement,
1650
+ classy
1651
+ )
1652
+ ) {
1653
+ const wasTopLevel = this.scope.topLevelScope;
1654
+ this.scope.topLevelScope = false;
1655
+ this.walkExpression(classElement.value);
1656
+ this.scope.topLevelScope = wasTopLevel;
1657
+ }
1658
+ } else if (classElement.type === "StaticBlock") {
1445
1659
  const wasTopLevel = this.scope.topLevelScope;
1446
1660
  this.scope.topLevelScope = false;
1447
- this.walkExpression(classElement.value);
1661
+ this.walkBlockStatement(classElement);
1448
1662
  this.scope.topLevelScope = wasTopLevel;
1449
1663
  }
1450
- } else if (classElement.type === "StaticBlock") {
1451
- const wasTopLevel = this.scope.topLevelScope;
1452
- this.scope.topLevelScope = false;
1453
- this.walkBlockStatement(classElement);
1454
- this.scope.topLevelScope = wasTopLevel;
1455
1664
  }
1456
1665
  }
1457
- }
1666
+ });
1458
1667
  }
1459
1668
  }
1460
1669
 
1461
- // Pre walking iterates the scope for variable declarations
1670
+ /**
1671
+ * Pre walking iterates the scope for variable declarations
1672
+ *
1673
+ * @param {(Statement | ModuleDeclaration)[]} statements statements
1674
+ */
1462
1675
  preWalkStatements(statements) {
1463
1676
  for (let index = 0, len = statements.length; index < len; index++) {
1464
1677
  const statement = statements[index];
@@ -1466,7 +1679,11 @@ class JavascriptParser extends Parser {
1466
1679
  }
1467
1680
  }
1468
1681
 
1469
- // Block pre walking iterates the scope for block variable declarations
1682
+ /**
1683
+ * Block pre walking iterates the scope for block variable declarations
1684
+ *
1685
+ * @param {(Statement | ModuleDeclaration)[]} statements statements
1686
+ */
1470
1687
  blockPreWalkStatements(statements) {
1471
1688
  for (let index = 0, len = statements.length; index < len; index++) {
1472
1689
  const statement = statements[index];
@@ -1474,7 +1691,11 @@ class JavascriptParser extends Parser {
1474
1691
  }
1475
1692
  }
1476
1693
 
1477
- // Walking iterates the statements and expressions and processes them
1694
+ /**
1695
+ * Walking iterates the statements and expressions and processes them
1696
+ *
1697
+ * @param {(Statement | ModuleDeclaration)[]} statements statements
1698
+ */
1478
1699
  walkStatements(statements) {
1479
1700
  for (let index = 0, len = statements.length; index < len; index++) {
1480
1701
  const statement = statements[index];
@@ -1482,6 +1703,11 @@ class JavascriptParser extends Parser {
1482
1703
  }
1483
1704
  }
1484
1705
 
1706
+ /**
1707
+ * Walking iterates the statements and expressions and processes them
1708
+ *
1709
+ * @param {Statement | ModuleDeclaration} statement statement
1710
+ */
1485
1711
  preWalkStatement(statement) {
1486
1712
  this.statementPath.push(statement);
1487
1713
  if (this.hooks.preStatement.call(statement)) {
@@ -1532,6 +1758,9 @@ class JavascriptParser extends Parser {
1532
1758
  this.prevStatement = this.statementPath.pop();
1533
1759
  }
1534
1760
 
1761
+ /**
1762
+ * @param {Statement | ModuleDeclaration} statement statement
1763
+ */
1535
1764
  blockPreWalkStatement(statement) {
1536
1765
  this.statementPath.push(statement);
1537
1766
  if (this.hooks.blockPreStatement.call(statement)) {
@@ -1557,10 +1786,15 @@ class JavascriptParser extends Parser {
1557
1786
  case "ClassDeclaration":
1558
1787
  this.blockPreWalkClassDeclaration(statement);
1559
1788
  break;
1789
+ case "ExpressionStatement":
1790
+ this.blockPreWalkExpressionStatement(statement);
1560
1791
  }
1561
1792
  this.prevStatement = this.statementPath.pop();
1562
1793
  }
1563
1794
 
1795
+ /**
1796
+ * @param {Statement | ModuleDeclaration} statement statement
1797
+ */
1564
1798
  walkStatement(statement) {
1565
1799
  this.statementPath.push(statement);
1566
1800
  if (this.hooks.statement.call(statement) !== undefined) {
@@ -1633,8 +1867,8 @@ class JavascriptParser extends Parser {
1633
1867
  * Walks a statements that is nested within a parent statement
1634
1868
  * and can potentially be a non-block statement.
1635
1869
  * This enforces the nested statement to never be in ASI position.
1636
- * @param {StatementNode} statement the nested statement
1637
- * @returns {void}
1870
+ *
1871
+ * @param {Statement} statement the nested statement
1638
1872
  */
1639
1873
  walkNestedStatement(statement) {
1640
1874
  this.prevStatement = undefined;
@@ -1642,10 +1876,16 @@ class JavascriptParser extends Parser {
1642
1876
  }
1643
1877
 
1644
1878
  // Real Statements
1879
+ /**
1880
+ * @param {BlockStatement} statement block statement
1881
+ */
1645
1882
  preWalkBlockStatement(statement) {
1646
1883
  this.preWalkStatements(statement.body);
1647
1884
  }
1648
1885
 
1886
+ /**
1887
+ * @param {BlockStatement} statement block statement
1888
+ */
1649
1889
  walkBlockStatement(statement) {
1650
1890
  this.inBlockScope(() => {
1651
1891
  const body = statement.body;
@@ -1656,10 +1896,16 @@ class JavascriptParser extends Parser {
1656
1896
  });
1657
1897
  }
1658
1898
 
1899
+ /**
1900
+ * @param {ExpressionStatement} statement expression statement
1901
+ */
1659
1902
  walkExpressionStatement(statement) {
1660
1903
  this.walkExpression(statement.expression);
1661
1904
  }
1662
1905
 
1906
+ /**
1907
+ * @param {IfStatement} statement if statement
1908
+ */
1663
1909
  preWalkIfStatement(statement) {
1664
1910
  this.preWalkStatement(statement.consequent);
1665
1911
  if (statement.alternate) {
@@ -1667,6 +1913,9 @@ class JavascriptParser extends Parser {
1667
1913
  }
1668
1914
  }
1669
1915
 
1916
+ /**
1917
+ * @param {IfStatement} statement if statement
1918
+ */
1670
1919
  walkIfStatement(statement) {
1671
1920
  const result = this.hooks.statementIf.call(statement);
1672
1921
  if (result === undefined) {
@@ -1684,10 +1933,16 @@ class JavascriptParser extends Parser {
1684
1933
  }
1685
1934
  }
1686
1935
 
1936
+ /**
1937
+ * @param {LabeledStatement} statement with statement
1938
+ */
1687
1939
  preWalkLabeledStatement(statement) {
1688
1940
  this.preWalkStatement(statement.body);
1689
1941
  }
1690
1942
 
1943
+ /**
1944
+ * @param {LabeledStatement} statement with statement
1945
+ */
1691
1946
  walkLabeledStatement(statement) {
1692
1947
  const hook = this.hooks.label.get(statement.label.name);
1693
1948
  if (hook !== undefined) {
@@ -1697,42 +1952,69 @@ class JavascriptParser extends Parser {
1697
1952
  this.walkNestedStatement(statement.body);
1698
1953
  }
1699
1954
 
1955
+ /**
1956
+ * @param {WithStatement} statement with statement
1957
+ */
1700
1958
  preWalkWithStatement(statement) {
1701
1959
  this.preWalkStatement(statement.body);
1702
1960
  }
1703
1961
 
1962
+ /**
1963
+ * @param {WithStatement} statement with statement
1964
+ */
1704
1965
  walkWithStatement(statement) {
1705
1966
  this.walkExpression(statement.object);
1706
1967
  this.walkNestedStatement(statement.body);
1707
1968
  }
1708
1969
 
1970
+ /**
1971
+ * @param {SwitchStatement} statement switch statement
1972
+ */
1709
1973
  preWalkSwitchStatement(statement) {
1710
1974
  this.preWalkSwitchCases(statement.cases);
1711
1975
  }
1712
1976
 
1977
+ /**
1978
+ * @param {SwitchStatement} statement switch statement
1979
+ */
1713
1980
  walkSwitchStatement(statement) {
1714
1981
  this.walkExpression(statement.discriminant);
1715
1982
  this.walkSwitchCases(statement.cases);
1716
1983
  }
1717
1984
 
1985
+ /**
1986
+ * @param {ReturnStatement | ThrowStatement} statement return or throw statement
1987
+ */
1718
1988
  walkTerminatingStatement(statement) {
1719
1989
  if (statement.argument) this.walkExpression(statement.argument);
1720
1990
  }
1721
1991
 
1992
+ /**
1993
+ * @param {ReturnStatement} statement return statement
1994
+ */
1722
1995
  walkReturnStatement(statement) {
1723
1996
  this.walkTerminatingStatement(statement);
1724
1997
  }
1725
1998
 
1999
+ /**
2000
+ * @param {ThrowStatement} statement return statement
2001
+ */
1726
2002
  walkThrowStatement(statement) {
1727
2003
  this.walkTerminatingStatement(statement);
1728
2004
  }
1729
2005
 
2006
+ /**
2007
+ * @param {TryStatement} statement try statement
2008
+ */
1730
2009
  preWalkTryStatement(statement) {
1731
2010
  this.preWalkStatement(statement.block);
1732
2011
  if (statement.handler) this.preWalkCatchClause(statement.handler);
1733
- if (statement.finializer) this.preWalkStatement(statement.finializer);
2012
+ if (statement.finalizer) this.preWalkStatement(statement.finalizer);
1734
2013
  }
1735
2014
 
2015
+ /**
2016
+ * @param {TryStatement} statement try statement
2017
+ */
1736
2018
  walkTryStatement(statement) {
1737
2019
  if (this.scope.inTry) {
1738
2020
  this.walkStatement(statement.block);
@@ -1745,24 +2027,39 @@ class JavascriptParser extends Parser {
1745
2027
  if (statement.finalizer) this.walkStatement(statement.finalizer);
1746
2028
  }
1747
2029
 
2030
+ /**
2031
+ * @param {WhileStatement} statement while statement
2032
+ */
1748
2033
  preWalkWhileStatement(statement) {
1749
2034
  this.preWalkStatement(statement.body);
1750
2035
  }
1751
2036
 
2037
+ /**
2038
+ * @param {WhileStatement} statement while statement
2039
+ */
1752
2040
  walkWhileStatement(statement) {
1753
2041
  this.walkExpression(statement.test);
1754
2042
  this.walkNestedStatement(statement.body);
1755
2043
  }
1756
2044
 
2045
+ /**
2046
+ * @param {DoWhileStatement} statement do while statement
2047
+ */
1757
2048
  preWalkDoWhileStatement(statement) {
1758
2049
  this.preWalkStatement(statement.body);
1759
2050
  }
1760
2051
 
2052
+ /**
2053
+ * @param {DoWhileStatement} statement do while statement
2054
+ */
1761
2055
  walkDoWhileStatement(statement) {
1762
2056
  this.walkNestedStatement(statement.body);
1763
2057
  this.walkExpression(statement.test);
1764
2058
  }
1765
2059
 
2060
+ /**
2061
+ * @param {ForStatement} statement for statement
2062
+ */
1766
2063
  preWalkForStatement(statement) {
1767
2064
  if (statement.init) {
1768
2065
  if (statement.init.type === "VariableDeclaration") {
@@ -1772,6 +2069,9 @@ class JavascriptParser extends Parser {
1772
2069
  this.preWalkStatement(statement.body);
1773
2070
  }
1774
2071
 
2072
+ /**
2073
+ * @param {ForStatement} statement for statement
2074
+ */
1775
2075
  walkForStatement(statement) {
1776
2076
  this.inBlockScope(() => {
1777
2077
  if (statement.init) {
@@ -1802,6 +2102,9 @@ class JavascriptParser extends Parser {
1802
2102
  });
1803
2103
  }
1804
2104
 
2105
+ /**
2106
+ * @param {ForInStatement} statement for statement
2107
+ */
1805
2108
  preWalkForInStatement(statement) {
1806
2109
  if (statement.left.type === "VariableDeclaration") {
1807
2110
  this.preWalkVariableDeclaration(statement.left);
@@ -1809,6 +2112,9 @@ class JavascriptParser extends Parser {
1809
2112
  this.preWalkStatement(statement.body);
1810
2113
  }
1811
2114
 
2115
+ /**
2116
+ * @param {ForInStatement} statement for statement
2117
+ */
1812
2118
  walkForInStatement(statement) {
1813
2119
  this.inBlockScope(() => {
1814
2120
  if (statement.left.type === "VariableDeclaration") {
@@ -1841,6 +2147,9 @@ class JavascriptParser extends Parser {
1841
2147
  this.preWalkStatement(statement.body);
1842
2148
  }
1843
2149
 
2150
+ /**
2151
+ * @param {ForOfStatement} statement for statement
2152
+ */
1844
2153
  walkForOfStatement(statement) {
1845
2154
  this.inBlockScope(() => {
1846
2155
  if (statement.left.type === "VariableDeclaration") {
@@ -1863,13 +2172,18 @@ class JavascriptParser extends Parser {
1863
2172
  });
1864
2173
  }
1865
2174
 
1866
- // Declarations
2175
+ /**
2176
+ * @param {FunctionDeclaration} statement function declaration
2177
+ */
1867
2178
  preWalkFunctionDeclaration(statement) {
1868
2179
  if (statement.id) {
1869
2180
  this.defineVariable(statement.id.name);
1870
2181
  }
1871
2182
  }
1872
2183
 
2184
+ /**
2185
+ * @param {FunctionDeclaration} statement function declaration
2186
+ */
1873
2187
  walkFunctionDeclaration(statement) {
1874
2188
  const wasTopLevel = this.scope.topLevelScope;
1875
2189
  this.scope.topLevelScope = false;
@@ -1890,6 +2204,48 @@ class JavascriptParser extends Parser {
1890
2204
  this.scope.topLevelScope = wasTopLevel;
1891
2205
  }
1892
2206
 
2207
+ /**
2208
+ * @param {ExpressionStatement} statement expression statement
2209
+ */
2210
+ blockPreWalkExpressionStatement(statement) {
2211
+ const expression = statement.expression;
2212
+ switch (expression.type) {
2213
+ case "AssignmentExpression":
2214
+ this.preWalkAssignmentExpression(expression);
2215
+ }
2216
+ }
2217
+
2218
+ /**
2219
+ * @param {AssignmentExpression} expression assignment expression
2220
+ */
2221
+ preWalkAssignmentExpression(expression) {
2222
+ if (
2223
+ expression.left.type !== "ObjectPattern" ||
2224
+ !this.destructuringAssignmentProperties
2225
+ )
2226
+ return;
2227
+ const keys = this._preWalkObjectPattern(expression.left);
2228
+ if (!keys) return;
2229
+
2230
+ // check multiple assignments
2231
+ if (this.destructuringAssignmentProperties.has(expression)) {
2232
+ const set = this.destructuringAssignmentProperties.get(expression);
2233
+ this.destructuringAssignmentProperties.delete(expression);
2234
+ for (const id of set) keys.add(id);
2235
+ }
2236
+
2237
+ this.destructuringAssignmentProperties.set(
2238
+ expression.right.type === "AwaitExpression"
2239
+ ? expression.right.argument
2240
+ : expression.right,
2241
+ keys
2242
+ );
2243
+
2244
+ if (expression.right.type === "AssignmentExpression") {
2245
+ this.preWalkAssignmentExpression(expression.right);
2246
+ }
2247
+ }
2248
+
1893
2249
  blockPreWalkImportDeclaration(statement) {
1894
2250
  const source = statement.source.value;
1895
2251
  this.hooks.import.call(statement, source);
@@ -2002,6 +2358,9 @@ class JavascriptParser extends Parser {
2002
2358
  }
2003
2359
  }
2004
2360
 
2361
+ /**
2362
+ * @param {ExportNamedDeclaration} statement the statement
2363
+ */
2005
2364
  walkExportNamedDeclaration(statement) {
2006
2365
  if (statement.declaration) {
2007
2366
  this.walkStatement(statement.declaration);
@@ -2069,11 +2428,17 @@ class JavascriptParser extends Parser {
2069
2428
  this.hooks.exportImportSpecifier.call(statement, source, null, name, 0);
2070
2429
  }
2071
2430
 
2431
+ /**
2432
+ * @param {VariableDeclaration} statement variable declaration
2433
+ */
2072
2434
  preWalkVariableDeclaration(statement) {
2073
2435
  if (statement.kind !== "var") return;
2074
2436
  this._preWalkVariableDeclaration(statement, this.hooks.varDeclarationVar);
2075
2437
  }
2076
2438
 
2439
+ /**
2440
+ * @param {VariableDeclaration} statement variable declaration
2441
+ */
2077
2442
  blockPreWalkVariableDeclaration(statement) {
2078
2443
  if (statement.kind === "var") return;
2079
2444
  const hookMap =
@@ -2083,10 +2448,15 @@ class JavascriptParser extends Parser {
2083
2448
  this._preWalkVariableDeclaration(statement, hookMap);
2084
2449
  }
2085
2450
 
2451
+ /**
2452
+ * @param {VariableDeclaration} statement variable declaration
2453
+ * @param {TODO} hookMap map of hooks
2454
+ */
2086
2455
  _preWalkVariableDeclaration(statement, hookMap) {
2087
2456
  for (const declarator of statement.declarations) {
2088
2457
  switch (declarator.type) {
2089
2458
  case "VariableDeclarator": {
2459
+ this.preWalkVariableDeclarator(declarator);
2090
2460
  if (!this.hooks.preDeclarator.call(declarator, statement)) {
2091
2461
  this.enterPattern(declarator.id, (name, decl) => {
2092
2462
  let hook = hookMap.get(name);
@@ -2104,6 +2474,62 @@ class JavascriptParser extends Parser {
2104
2474
  }
2105
2475
  }
2106
2476
 
2477
+ /**
2478
+ * @param {ObjectPattern} objectPattern object pattern
2479
+ * @returns {Set<string> | undefined} set of names or undefined if not all keys are identifiers
2480
+ */
2481
+ _preWalkObjectPattern(objectPattern) {
2482
+ const ids = new Set();
2483
+ const properties = objectPattern.properties;
2484
+ for (let i = 0; i < properties.length; i++) {
2485
+ const property = properties[i];
2486
+ if (property.type !== "Property") return;
2487
+ const key = property.key;
2488
+ if (key.type === "Identifier") {
2489
+ ids.add(key.name);
2490
+ } else {
2491
+ const id = this.evaluateExpression(key);
2492
+ const str = id.asString();
2493
+ if (str) {
2494
+ ids.add(str);
2495
+ } else {
2496
+ // could not evaluate key
2497
+ return;
2498
+ }
2499
+ }
2500
+ }
2501
+
2502
+ return ids;
2503
+ }
2504
+
2505
+ /**
2506
+ * @param {VariableDeclarator} declarator variable declarator
2507
+ */
2508
+ preWalkVariableDeclarator(declarator) {
2509
+ if (
2510
+ !declarator.init ||
2511
+ declarator.id.type !== "ObjectPattern" ||
2512
+ !this.destructuringAssignmentProperties
2513
+ )
2514
+ return;
2515
+ const keys = this._preWalkObjectPattern(declarator.id);
2516
+
2517
+ if (!keys) return;
2518
+ this.destructuringAssignmentProperties.set(
2519
+ declarator.init.type === "AwaitExpression"
2520
+ ? declarator.init.argument
2521
+ : declarator.init,
2522
+ keys
2523
+ );
2524
+
2525
+ if (declarator.init.type === "AssignmentExpression") {
2526
+ this.preWalkAssignmentExpression(declarator.init);
2527
+ }
2528
+ }
2529
+
2530
+ /**
2531
+ * @param {VariableDeclaration} statement variable declaration
2532
+ */
2107
2533
  walkVariableDeclaration(statement) {
2108
2534
  for (const declarator of statement.declarations) {
2109
2535
  switch (declarator.type) {
@@ -2131,16 +2557,25 @@ class JavascriptParser extends Parser {
2131
2557
  }
2132
2558
  }
2133
2559
 
2560
+ /**
2561
+ * @param {ClassDeclaration} statement class declaration
2562
+ */
2134
2563
  blockPreWalkClassDeclaration(statement) {
2135
2564
  if (statement.id) {
2136
2565
  this.defineVariable(statement.id.name);
2137
2566
  }
2138
2567
  }
2139
2568
 
2569
+ /**
2570
+ * @param {ClassDeclaration} statement class declaration
2571
+ */
2140
2572
  walkClassDeclaration(statement) {
2141
2573
  this.walkClass(statement);
2142
2574
  }
2143
2575
 
2576
+ /**
2577
+ * @param {SwitchCase[]} switchCases switch statement
2578
+ */
2144
2579
  preWalkSwitchCases(switchCases) {
2145
2580
  for (let index = 0, len = switchCases.length; index < len; index++) {
2146
2581
  const switchCase = switchCases[index];
@@ -2148,6 +2583,9 @@ class JavascriptParser extends Parser {
2148
2583
  }
2149
2584
  }
2150
2585
 
2586
+ /**
2587
+ * @param {SwitchCase[]} switchCases switch statement
2588
+ */
2151
2589
  walkSwitchCases(switchCases) {
2152
2590
  this.inBlockScope(() => {
2153
2591
  const len = switchCases.length;
@@ -2183,10 +2621,16 @@ class JavascriptParser extends Parser {
2183
2621
  });
2184
2622
  }
2185
2623
 
2624
+ /**
2625
+ * @param {CatchClause} catchClause catch clause
2626
+ */
2186
2627
  preWalkCatchClause(catchClause) {
2187
2628
  this.preWalkStatement(catchClause.body);
2188
2629
  }
2189
2630
 
2631
+ /**
2632
+ * @param {CatchClause} catchClause catch clause
2633
+ */
2190
2634
  walkCatchClause(catchClause) {
2191
2635
  this.inBlockScope(() => {
2192
2636
  // Error binding is optional in catch clause since ECMAScript 2019
@@ -2203,6 +2647,9 @@ class JavascriptParser extends Parser {
2203
2647
  });
2204
2648
  }
2205
2649
 
2650
+ /**
2651
+ * @param {Pattern} pattern pattern
2652
+ */
2206
2653
  walkPattern(pattern) {
2207
2654
  switch (pattern.type) {
2208
2655
  case "ArrayPattern":
@@ -2223,6 +2670,9 @@ class JavascriptParser extends Parser {
2223
2670
  }
2224
2671
  }
2225
2672
 
2673
+ /**
2674
+ * @param {AssignmentPattern} pattern assignment pattern
2675
+ */
2226
2676
  walkAssignmentPattern(pattern) {
2227
2677
  this.walkExpression(pattern.right);
2228
2678
  this.walkPattern(pattern.left);
@@ -2238,6 +2688,9 @@ class JavascriptParser extends Parser {
2238
2688
  }
2239
2689
  }
2240
2690
 
2691
+ /**
2692
+ * @param {ArrayPattern} pattern array pattern
2693
+ */
2241
2694
  walkArrayPattern(pattern) {
2242
2695
  for (let i = 0, len = pattern.elements.length; i < len; i++) {
2243
2696
  const element = pattern.elements[i];
@@ -2245,10 +2698,16 @@ class JavascriptParser extends Parser {
2245
2698
  }
2246
2699
  }
2247
2700
 
2701
+ /**
2702
+ * @param {RestElement} pattern rest element
2703
+ */
2248
2704
  walkRestElement(pattern) {
2249
2705
  this.walkPattern(pattern.argument);
2250
2706
  }
2251
2707
 
2708
+ /**
2709
+ * @param {(Expression | SpreadElement | null)[]} expressions expressions
2710
+ */
2252
2711
  walkExpressions(expressions) {
2253
2712
  for (const expression of expressions) {
2254
2713
  if (expression) {
@@ -2257,6 +2716,9 @@ class JavascriptParser extends Parser {
2257
2716
  }
2258
2717
  }
2259
2718
 
2719
+ /**
2720
+ * @param {TODO} expression expression
2721
+ */
2260
2722
  walkExpression(expression) {
2261
2723
  switch (expression.type) {
2262
2724
  case "ArrayExpression":
@@ -2337,24 +2799,36 @@ class JavascriptParser extends Parser {
2337
2799
  }
2338
2800
  }
2339
2801
 
2802
+ /**
2803
+ * @param {AwaitExpression} expression await expression
2804
+ */
2340
2805
  walkAwaitExpression(expression) {
2341
2806
  if (this.scope.topLevelScope === true)
2342
2807
  this.hooks.topLevelAwait.call(expression);
2343
2808
  this.walkExpression(expression.argument);
2344
2809
  }
2345
2810
 
2811
+ /**
2812
+ * @param {ArrayExpression} expression array expression
2813
+ */
2346
2814
  walkArrayExpression(expression) {
2347
2815
  if (expression.elements) {
2348
2816
  this.walkExpressions(expression.elements);
2349
2817
  }
2350
2818
  }
2351
2819
 
2820
+ /**
2821
+ * @param {SpreadElement} expression spread element
2822
+ */
2352
2823
  walkSpreadElement(expression) {
2353
2824
  if (expression.argument) {
2354
2825
  this.walkExpression(expression.argument);
2355
2826
  }
2356
2827
  }
2357
2828
 
2829
+ /**
2830
+ * @param {ObjectExpression} expression object expression
2831
+ */
2358
2832
  walkObjectExpression(expression) {
2359
2833
  for (
2360
2834
  let propIndex = 0, len = expression.properties.length;
@@ -2366,6 +2840,9 @@ class JavascriptParser extends Parser {
2366
2840
  }
2367
2841
  }
2368
2842
 
2843
+ /**
2844
+ * @param {Property | SpreadElement} prop property or spread element
2845
+ */
2369
2846
  walkProperty(prop) {
2370
2847
  if (prop.type === "SpreadElement") {
2371
2848
  this.walkExpression(prop.argument);
@@ -2383,14 +2860,17 @@ class JavascriptParser extends Parser {
2383
2860
  }
2384
2861
  }
2385
2862
 
2863
+ /**
2864
+ * @param {FunctionExpression} expression arrow function expression
2865
+ */
2386
2866
  walkFunctionExpression(expression) {
2387
2867
  const wasTopLevel = this.scope.topLevelScope;
2388
2868
  this.scope.topLevelScope = false;
2389
- const scopeParams = expression.params;
2869
+ const scopeParams = [...expression.params];
2390
2870
 
2391
2871
  // Add function name in scope for recursive calls
2392
2872
  if (expression.id) {
2393
- scopeParams.push(expression.id.name);
2873
+ scopeParams.push(expression.id);
2394
2874
  }
2395
2875
 
2396
2876
  this.inFunctionScope(true, scopeParams, () => {
@@ -2410,6 +2890,9 @@ class JavascriptParser extends Parser {
2410
2890
  this.scope.topLevelScope = wasTopLevel;
2411
2891
  }
2412
2892
 
2893
+ /**
2894
+ * @param {ArrowFunctionExpression} expression arrow function expression
2895
+ */
2413
2896
  walkArrowFunctionExpression(expression) {
2414
2897
  const wasTopLevel = this.scope.topLevelScope;
2415
2898
  this.scope.topLevelScope = wasTopLevel ? "arrow" : false;
@@ -2431,7 +2914,7 @@ class JavascriptParser extends Parser {
2431
2914
  }
2432
2915
 
2433
2916
  /**
2434
- * @param {SequenceExpressionNode} expression the sequence
2917
+ * @param {SequenceExpression} expression the sequence
2435
2918
  */
2436
2919
  walkSequenceExpression(expression) {
2437
2920
  if (!expression.expressions) return;
@@ -2455,10 +2938,16 @@ class JavascriptParser extends Parser {
2455
2938
  }
2456
2939
  }
2457
2940
 
2941
+ /**
2942
+ * @param {UpdateExpression} expression the update expression
2943
+ */
2458
2944
  walkUpdateExpression(expression) {
2459
2945
  this.walkExpression(expression.argument);
2460
2946
  }
2461
2947
 
2948
+ /**
2949
+ * @param {UnaryExpression} expression the unary expression
2950
+ */
2462
2951
  walkUnaryExpression(expression) {
2463
2952
  if (expression.operator === "typeof") {
2464
2953
  const result = this.callHooksForExpression(
@@ -2479,17 +2968,26 @@ class JavascriptParser extends Parser {
2479
2968
  this.walkExpression(expression.argument);
2480
2969
  }
2481
2970
 
2971
+ /**
2972
+ * @param {LogicalExpression | BinaryExpression} expression the expression
2973
+ */
2482
2974
  walkLeftRightExpression(expression) {
2483
2975
  this.walkExpression(expression.left);
2484
2976
  this.walkExpression(expression.right);
2485
2977
  }
2486
2978
 
2979
+ /**
2980
+ * @param {BinaryExpression} expression the binary expression
2981
+ */
2487
2982
  walkBinaryExpression(expression) {
2488
2983
  if (this.hooks.binaryExpression.call(expression) === undefined) {
2489
2984
  this.walkLeftRightExpression(expression);
2490
2985
  }
2491
2986
  }
2492
2987
 
2988
+ /**
2989
+ * @param {LogicalExpression} expression the logical expression
2990
+ */
2493
2991
  walkLogicalExpression(expression) {
2494
2992
  const result = this.hooks.expressionLogicalOperator.call(expression);
2495
2993
  if (result === undefined) {
@@ -2501,6 +2999,9 @@ class JavascriptParser extends Parser {
2501
2999
  }
2502
3000
  }
2503
3001
 
3002
+ /**
3003
+ * @param {AssignmentExpression} expression assignment expression
3004
+ */
2504
3005
  walkAssignmentExpression(expression) {
2505
3006
  if (expression.left.type === "Identifier") {
2506
3007
  const renameIdentifier = this.getRenameIdentifier(expression.right);
@@ -2571,6 +3072,9 @@ class JavascriptParser extends Parser {
2571
3072
  }
2572
3073
  }
2573
3074
 
3075
+ /**
3076
+ * @param {ConditionalExpression} expression conditional expression
3077
+ */
2574
3078
  walkConditionalExpression(expression) {
2575
3079
  const result = this.hooks.expressionConditionalOperator.call(expression);
2576
3080
  if (result === undefined) {
@@ -2588,6 +3092,9 @@ class JavascriptParser extends Parser {
2588
3092
  }
2589
3093
  }
2590
3094
 
3095
+ /**
3096
+ * @param {NewExpression} expression new expression
3097
+ */
2591
3098
  walkNewExpression(expression) {
2592
3099
  const result = this.callHooksForExpression(
2593
3100
  this.hooks.new,
@@ -2601,33 +3108,47 @@ class JavascriptParser extends Parser {
2601
3108
  }
2602
3109
  }
2603
3110
 
3111
+ /**
3112
+ * @param {YieldExpression} expression yield expression
3113
+ */
2604
3114
  walkYieldExpression(expression) {
2605
3115
  if (expression.argument) {
2606
3116
  this.walkExpression(expression.argument);
2607
3117
  }
2608
3118
  }
2609
3119
 
3120
+ /**
3121
+ * @param {TemplateLiteral} expression template literal
3122
+ */
2610
3123
  walkTemplateLiteral(expression) {
2611
3124
  if (expression.expressions) {
2612
3125
  this.walkExpressions(expression.expressions);
2613
3126
  }
2614
3127
  }
2615
3128
 
3129
+ /**
3130
+ * @param {TaggedTemplateExpression} expression tagged template expression
3131
+ */
2616
3132
  walkTaggedTemplateExpression(expression) {
2617
3133
  if (expression.tag) {
3134
+ this.scope.inTaggedTemplateTag = true;
2618
3135
  this.walkExpression(expression.tag);
3136
+ this.scope.inTaggedTemplateTag = false;
2619
3137
  }
2620
3138
  if (expression.quasi && expression.quasi.expressions) {
2621
3139
  this.walkExpressions(expression.quasi.expressions);
2622
3140
  }
2623
3141
  }
2624
3142
 
3143
+ /**
3144
+ * @param {ClassExpression} expression the class expression
3145
+ */
2625
3146
  walkClassExpression(expression) {
2626
3147
  this.walkClass(expression);
2627
3148
  }
2628
3149
 
2629
3150
  /**
2630
- * @param {ChainExpressionNode} expression expression
3151
+ * @param {ChainExpression} expression expression
2631
3152
  */
2632
3153
  walkChainExpression(expression) {
2633
3154
  const result = this.hooks.optionalChaining.call(expression);
@@ -2705,6 +3226,9 @@ class JavascriptParser extends Parser {
2705
3226
  this.scope.topLevelScope = wasTopLevel;
2706
3227
  }
2707
3228
 
3229
+ /**
3230
+ * @param {ImportExpression} expression import expression
3231
+ */
2708
3232
  walkImportExpression(expression) {
2709
3233
  let result = this.hooks.importCall.call(expression);
2710
3234
  if (result === true) return;
@@ -2764,7 +3288,8 @@ class JavascriptParser extends Parser {
2764
3288
  callee.getMembers(),
2765
3289
  callee.getMembersOptionals
2766
3290
  ? callee.getMembersOptionals()
2767
- : callee.getMembers().map(() => false)
3291
+ : callee.getMembers().map(() => false),
3292
+ callee.getMemberRanges ? callee.getMemberRanges() : []
2768
3293
  );
2769
3294
  if (result1 === true) return;
2770
3295
  const result2 = this.callHooksForInfo(
@@ -2789,6 +3314,9 @@ class JavascriptParser extends Parser {
2789
3314
  }
2790
3315
  }
2791
3316
 
3317
+ /**
3318
+ * @param {MemberExpression} expression member expression
3319
+ */
2792
3320
  walkMemberExpression(expression) {
2793
3321
  const exprInfo = this.getMemberExpressionInfo(
2794
3322
  expression,
@@ -2805,12 +3333,14 @@ class JavascriptParser extends Parser {
2805
3333
  if (result1 === true) return;
2806
3334
  const members = exprInfo.getMembers();
2807
3335
  const membersOptionals = exprInfo.getMembersOptionals();
3336
+ const memberRanges = exprInfo.getMemberRanges();
2808
3337
  const result2 = this.callHooksForInfo(
2809
3338
  this.hooks.expressionMemberChain,
2810
3339
  exprInfo.rootInfo,
2811
3340
  expression,
2812
3341
  members,
2813
- membersOptionals
3342
+ membersOptionals,
3343
+ memberRanges
2814
3344
  );
2815
3345
  if (result2 === true) return;
2816
3346
  this.walkMemberExpressionWithExpressionName(
@@ -2882,16 +3412,22 @@ class JavascriptParser extends Parser {
2882
3412
  if (expression.computed === true) this.walkExpression(expression.property);
2883
3413
  }
2884
3414
 
3415
+ /**
3416
+ * @param {ThisExpression} expression this expression
3417
+ */
2885
3418
  walkThisExpression(expression) {
2886
3419
  this.callHooksForName(this.hooks.expression, "this", expression);
2887
3420
  }
2888
3421
 
3422
+ /**
3423
+ * @param {Identifier} expression identifier
3424
+ */
2889
3425
  walkIdentifier(expression) {
2890
3426
  this.callHooksForName(this.hooks.expression, expression.name, expression);
2891
3427
  }
2892
3428
 
2893
3429
  /**
2894
- * @param {MetaPropertyNode} metaProperty meta property
3430
+ * @param {MetaProperty} metaProperty meta property
2895
3431
  */
2896
3432
  walkMetaProperty(metaProperty) {
2897
3433
  this.hooks.expression.for(getRootName(metaProperty)).call(metaProperty);
@@ -2911,11 +3447,11 @@ class JavascriptParser extends Parser {
2911
3447
  * @template T
2912
3448
  * @template R
2913
3449
  * @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
2914
- * @param {MemberExpressionNode} expr expression info
2915
- * @param {function(string, string | ScopeInfo | VariableInfo, function(): string[]): any} fallback callback when variable in not handled by hooks
2916
- * @param {function(string): any} defined callback when variable is defined
3450
+ * @param {MemberExpression} expr expression info
3451
+ * @param {(function(string, string | ScopeInfo | VariableInfo, function(): string[]): any) | undefined} fallback callback when variable in not handled by hooks
3452
+ * @param {(function(string): any) | undefined} defined callback when variable is defined
2917
3453
  * @param {AsArray<T>} args args for the hook
2918
- * @returns {R} result of hook
3454
+ * @returns {R | undefined} result of hook
2919
3455
  */
2920
3456
  callHooksForExpressionWithFallback(
2921
3457
  hookMap,
@@ -2947,7 +3483,7 @@ class JavascriptParser extends Parser {
2947
3483
  * @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
2948
3484
  * @param {string} name key in map
2949
3485
  * @param {AsArray<T>} args args for the hook
2950
- * @returns {R} result of hook
3486
+ * @returns {R | undefined} result of hook
2951
3487
  */
2952
3488
  callHooksForName(hookMap, name, ...args) {
2953
3489
  return this.callHooksForNameWithFallback(
@@ -2965,7 +3501,7 @@ class JavascriptParser extends Parser {
2965
3501
  * @param {HookMap<SyncBailHook<T, R>>} hookMap hooks that should be called
2966
3502
  * @param {ExportedVariableInfo} info variable info
2967
3503
  * @param {AsArray<T>} args args for the hook
2968
- * @returns {R} result of hook
3504
+ * @returns {R | undefined} result of hook
2969
3505
  */
2970
3506
  callHooksForInfo(hookMap, info, ...args) {
2971
3507
  return this.callHooksForInfoWithFallback(
@@ -2982,10 +3518,10 @@ class JavascriptParser extends Parser {
2982
3518
  * @template R
2983
3519
  * @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
2984
3520
  * @param {ExportedVariableInfo} info variable info
2985
- * @param {function(string): any} fallback callback when variable in not handled by hooks
2986
- * @param {function(): any} defined callback when variable is defined
3521
+ * @param {(function(string): any) | undefined} fallback callback when variable in not handled by hooks
3522
+ * @param {(function(): any) | undefined} defined callback when variable is defined
2987
3523
  * @param {AsArray<T>} args args for the hook
2988
- * @returns {R} result of hook
3524
+ * @returns {R | undefined} result of hook
2989
3525
  */
2990
3526
  callHooksForInfoWithFallback(hookMap, info, fallback, defined, ...args) {
2991
3527
  let name;
@@ -3032,10 +3568,10 @@ class JavascriptParser extends Parser {
3032
3568
  * @template R
3033
3569
  * @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
3034
3570
  * @param {string} name key in map
3035
- * @param {function(string): any} fallback callback when variable in not handled by hooks
3036
- * @param {function(): any} defined callback when variable is defined
3571
+ * @param {(function(string): any) | undefined} fallback callback when variable in not handled by hooks
3572
+ * @param {(function(): any) | undefined} defined callback when variable is defined
3037
3573
  * @param {AsArray<T>} args args for the hook
3038
- * @returns {R} result of hook
3574
+ * @returns {R | undefined} result of hook
3039
3575
  */
3040
3576
  callHooksForNameWithFallback(hookMap, name, fallback, defined, ...args) {
3041
3577
  return this.callHooksForInfoWithFallback(
@@ -3059,6 +3595,7 @@ class JavascriptParser extends Parser {
3059
3595
  topLevelScope: oldScope.topLevelScope,
3060
3596
  inTry: false,
3061
3597
  inShorthand: false,
3598
+ inTaggedTemplateTag: false,
3062
3599
  isStrict: oldScope.isStrict,
3063
3600
  isAsmJs: oldScope.isAsmJs,
3064
3601
  definitions: oldScope.definitions.createChild()
@@ -3075,12 +3612,50 @@ class JavascriptParser extends Parser {
3075
3612
  this.scope = oldScope;
3076
3613
  }
3077
3614
 
3615
+ /**
3616
+ * @param {boolean} hasThis true, when this is defined
3617
+ * @param {any} params scope params
3618
+ * @param {function(): void} fn inner function
3619
+ * @returns {void}
3620
+ */
3621
+ inClassScope(hasThis, params, fn) {
3622
+ const oldScope = this.scope;
3623
+ this.scope = {
3624
+ topLevelScope: oldScope.topLevelScope,
3625
+ inTry: false,
3626
+ inShorthand: false,
3627
+ inTaggedTemplateTag: false,
3628
+ isStrict: oldScope.isStrict,
3629
+ isAsmJs: oldScope.isAsmJs,
3630
+ definitions: oldScope.definitions.createChild()
3631
+ };
3632
+
3633
+ if (hasThis) {
3634
+ this.undefineVariable("this");
3635
+ }
3636
+
3637
+ this.enterPatterns(params, (ident, pattern) => {
3638
+ this.defineVariable(ident);
3639
+ });
3640
+
3641
+ fn();
3642
+
3643
+ this.scope = oldScope;
3644
+ }
3645
+
3646
+ /**
3647
+ * @param {boolean} hasThis true, when this is defined
3648
+ * @param {any} params scope params
3649
+ * @param {function(): void} fn inner function
3650
+ * @returns {void}
3651
+ */
3078
3652
  inFunctionScope(hasThis, params, fn) {
3079
3653
  const oldScope = this.scope;
3080
3654
  this.scope = {
3081
3655
  topLevelScope: oldScope.topLevelScope,
3082
3656
  inTry: false,
3083
3657
  inShorthand: false,
3658
+ inTaggedTemplateTag: false,
3084
3659
  isStrict: oldScope.isStrict,
3085
3660
  isAsmJs: oldScope.isAsmJs,
3086
3661
  definitions: oldScope.definitions.createChild()
@@ -3099,12 +3674,17 @@ class JavascriptParser extends Parser {
3099
3674
  this.scope = oldScope;
3100
3675
  }
3101
3676
 
3677
+ /**
3678
+ * @param {function(): void} fn inner function
3679
+ * @returns {void}
3680
+ */
3102
3681
  inBlockScope(fn) {
3103
3682
  const oldScope = this.scope;
3104
3683
  this.scope = {
3105
3684
  topLevelScope: oldScope.topLevelScope,
3106
3685
  inTry: oldScope.inTry,
3107
3686
  inShorthand: false,
3687
+ inTaggedTemplateTag: false,
3108
3688
  isStrict: oldScope.isStrict,
3109
3689
  isAsmJs: oldScope.isAsmJs,
3110
3690
  definitions: oldScope.definitions.createChild()
@@ -3115,15 +3695,28 @@ class JavascriptParser extends Parser {
3115
3695
  this.scope = oldScope;
3116
3696
  }
3117
3697
 
3698
+ /**
3699
+ * @param {Array<Directive | Statement | ModuleDeclaration>} statements statements
3700
+ */
3118
3701
  detectMode(statements) {
3119
3702
  const isLiteral =
3120
3703
  statements.length >= 1 &&
3121
3704
  statements[0].type === "ExpressionStatement" &&
3122
3705
  statements[0].expression.type === "Literal";
3123
- if (isLiteral && statements[0].expression.value === "use strict") {
3706
+ if (
3707
+ isLiteral &&
3708
+ /** @type {Literal} */
3709
+ (/** @type {ExpressionStatement} */ (statements[0]).expression).value ===
3710
+ "use strict"
3711
+ ) {
3124
3712
  this.scope.isStrict = true;
3125
3713
  }
3126
- if (isLiteral && statements[0].expression.value === "use asm") {
3714
+ if (
3715
+ isLiteral &&
3716
+ /** @type {Literal} */
3717
+ (/** @type {ExpressionStatement} */ (statements[0]).expression).value ===
3718
+ "use asm"
3719
+ ) {
3127
3720
  this.scope.isAsmJs = true;
3128
3721
  }
3129
3722
  }
@@ -3168,12 +3761,20 @@ class JavascriptParser extends Parser {
3168
3761
  }
3169
3762
  }
3170
3763
 
3764
+ /**
3765
+ * @param {Identifier} pattern identifier pattern
3766
+ * @param {TODO} onIdent callback
3767
+ */
3171
3768
  enterIdentifier(pattern, onIdent) {
3172
3769
  if (!this.callHooksForName(this.hooks.pattern, pattern.name, pattern)) {
3173
3770
  onIdent(pattern.name, pattern);
3174
3771
  }
3175
3772
  }
3176
3773
 
3774
+ /**
3775
+ * @param {ObjectPattern} pattern object pattern
3776
+ * @param {TODO} onIdent callback
3777
+ */
3177
3778
  enterObjectPattern(pattern, onIdent) {
3178
3779
  for (
3179
3780
  let propIndex = 0, len = pattern.properties.length;
@@ -3185,6 +3786,10 @@ class JavascriptParser extends Parser {
3185
3786
  }
3186
3787
  }
3187
3788
 
3789
+ /**
3790
+ * @param {ArrayPattern} pattern object pattern
3791
+ * @param {TODO} onIdent callback
3792
+ */
3188
3793
  enterArrayPattern(pattern, onIdent) {
3189
3794
  for (
3190
3795
  let elementIndex = 0, len = pattern.elements.length;
@@ -3192,20 +3797,29 @@ class JavascriptParser extends Parser {
3192
3797
  elementIndex++
3193
3798
  ) {
3194
3799
  const element = pattern.elements[elementIndex];
3800
+ // TODO check on `null`?
3195
3801
  this.enterPattern(element, onIdent);
3196
3802
  }
3197
3803
  }
3198
3804
 
3805
+ /**
3806
+ * @param {RestElement} pattern object pattern
3807
+ * @param {TODO} onIdent callback
3808
+ */
3199
3809
  enterRestElement(pattern, onIdent) {
3200
3810
  this.enterPattern(pattern.argument, onIdent);
3201
3811
  }
3202
3812
 
3813
+ /**
3814
+ * @param {AssignmentPattern} pattern object pattern
3815
+ * @param {TODO} onIdent callback
3816
+ */
3203
3817
  enterAssignmentPattern(pattern, onIdent) {
3204
3818
  this.enterPattern(pattern.left, onIdent);
3205
3819
  }
3206
3820
 
3207
3821
  /**
3208
- * @param {ExpressionNode} expression expression node
3822
+ * @param {TODO} expression expression node
3209
3823
  * @returns {BasicEvaluatedExpression} evaluation result
3210
3824
  */
3211
3825
  evaluateExpression(expression) {
@@ -3223,10 +3837,14 @@ class JavascriptParser extends Parser {
3223
3837
  // ignore error
3224
3838
  }
3225
3839
  return new BasicEvaluatedExpression()
3226
- .setRange(expression.range)
3840
+ .setRange(/** @type {Range} */ (expression.range))
3227
3841
  .setExpression(expression);
3228
3842
  }
3229
3843
 
3844
+ /**
3845
+ * @param {Expression} expression expression
3846
+ * @returns {string} parsed string
3847
+ */
3230
3848
  parseString(expression) {
3231
3849
  switch (expression.type) {
3232
3850
  case "BinaryExpression":
@@ -3335,7 +3953,7 @@ class JavascriptParser extends Parser {
3335
3953
  source = source.toString("utf-8");
3336
3954
  }
3337
3955
  if (typeof source === "object") {
3338
- ast = /** @type {ProgramNode} */ (source);
3956
+ ast = /** @type {Program} */ (source);
3339
3957
  comments = source.comments;
3340
3958
  } else {
3341
3959
  comments = [];
@@ -3356,6 +3974,7 @@ class JavascriptParser extends Parser {
3356
3974
  topLevelScope: true,
3357
3975
  inTry: false,
3358
3976
  inShorthand: false,
3977
+ inTaggedTemplateTag: false,
3359
3978
  isStrict: false,
3360
3979
  isAsmJs: false,
3361
3980
  definitions: new StackedMap()
@@ -3367,12 +3986,14 @@ class JavascriptParser extends Parser {
3367
3986
  this.statementPath = [];
3368
3987
  this.prevStatement = undefined;
3369
3988
  if (this.hooks.program.call(ast, comments) === undefined) {
3989
+ this.destructuringAssignmentProperties = new WeakMap();
3370
3990
  this.detectMode(ast.body);
3371
3991
  this.preWalkStatements(ast.body);
3372
3992
  this.prevStatement = undefined;
3373
3993
  this.blockPreWalkStatements(ast.body);
3374
3994
  this.prevStatement = undefined;
3375
3995
  this.walkStatements(ast.body);
3996
+ this.destructuringAssignmentProperties = undefined;
3376
3997
  }
3377
3998
  this.hooks.finish.call(ast, comments);
3378
3999
  this.scope = oldScope;
@@ -3401,7 +4022,7 @@ class JavascriptParser extends Parser {
3401
4022
  }
3402
4023
 
3403
4024
  /**
3404
- * @param {ExpressionNode | DeclarationNode | PrivateIdentifierNode | null | undefined} expr an expression
4025
+ * @param {Expression | Declaration | PrivateIdentifier | null | undefined} expr an expression
3405
4026
  * @param {number} commentsStartPos source position from which annotation comments are checked
3406
4027
  * @returns {boolean} true, when the expression is pure
3407
4028
  */
@@ -3412,6 +4033,7 @@ class JavascriptParser extends Parser {
3412
4033
  .call(expr, commentsStartPos);
3413
4034
  if (typeof result === "boolean") return result;
3414
4035
  switch (expr.type) {
4036
+ // TODO handle more cases
3415
4037
  case "ClassDeclaration":
3416
4038
  case "ClassExpression": {
3417
4039
  if (expr.body.type !== "ClassBody") return false;
@@ -3419,63 +4041,94 @@ class JavascriptParser extends Parser {
3419
4041
  return false;
3420
4042
  }
3421
4043
  const items =
3422
- /** @type {(MethodDefinitionNode | PropertyDefinitionNode)[]} */ (
3423
- expr.body.body
3424
- );
3425
- return items.every(
3426
- item =>
3427
- (!item.computed ||
3428
- !item.key ||
3429
- this.isPure(item.key, item.range[0])) &&
3430
- (!item.static ||
3431
- !item.value ||
3432
- this.isPure(
3433
- item.value,
3434
- item.key ? item.key.range[1] : item.range[0]
3435
- ))
3436
- );
4044
+ /** @type {TODO[]} */
4045
+ (expr.body.body);
4046
+ return items.every(item => {
4047
+ if (
4048
+ item.computed &&
4049
+ item.key &&
4050
+ !this.isPure(item.key, item.range[0])
4051
+ ) {
4052
+ return false;
4053
+ }
4054
+
4055
+ if (
4056
+ item.static &&
4057
+ item.value &&
4058
+ !this.isPure(
4059
+ item.value,
4060
+ item.key ? item.key.range[1] : item.range[0]
4061
+ )
4062
+ ) {
4063
+ return false;
4064
+ }
4065
+
4066
+ if (item.type === "StaticBlock") {
4067
+ return false;
4068
+ }
4069
+
4070
+ return true;
4071
+ });
3437
4072
  }
3438
4073
 
3439
4074
  case "FunctionDeclaration":
3440
4075
  case "FunctionExpression":
3441
4076
  case "ArrowFunctionExpression":
4077
+ case "ThisExpression":
3442
4078
  case "Literal":
4079
+ case "TemplateLiteral":
4080
+ case "Identifier":
3443
4081
  case "PrivateIdentifier":
3444
4082
  return true;
3445
4083
 
3446
4084
  case "VariableDeclaration":
3447
4085
  return expr.declarations.every(decl =>
3448
- this.isPure(decl.init, decl.range[0])
4086
+ this.isPure(decl.init, /** @type {Range} */ (decl.range)[0])
3449
4087
  );
3450
4088
 
3451
4089
  case "ConditionalExpression":
3452
4090
  return (
3453
4091
  this.isPure(expr.test, commentsStartPos) &&
3454
- this.isPure(expr.consequent, expr.test.range[1]) &&
3455
- this.isPure(expr.alternate, expr.consequent.range[1])
4092
+ this.isPure(
4093
+ expr.consequent,
4094
+ /** @type {Range} */ (expr.test.range)[1]
4095
+ ) &&
4096
+ this.isPure(
4097
+ expr.alternate,
4098
+ /** @type {Range} */ (expr.consequent.range)[1]
4099
+ )
4100
+ );
4101
+
4102
+ case "LogicalExpression":
4103
+ return (
4104
+ this.isPure(expr.left, commentsStartPos) &&
4105
+ this.isPure(expr.right, /** @type {Range} */ (expr.left.range)[1])
3456
4106
  );
3457
4107
 
3458
4108
  case "SequenceExpression":
3459
4109
  return expr.expressions.every(expr => {
3460
4110
  const pureFlag = this.isPure(expr, commentsStartPos);
3461
- commentsStartPos = expr.range[1];
4111
+ commentsStartPos = /** @type {Range} */ (expr.range)[1];
3462
4112
  return pureFlag;
3463
4113
  });
3464
4114
 
3465
4115
  case "CallExpression": {
3466
4116
  const pureFlag =
3467
- expr.range[0] - commentsStartPos > 12 &&
3468
- this.getComments([commentsStartPos, expr.range[0]]).some(
4117
+ /** @type {Range} */ (expr.range)[0] - commentsStartPos > 12 &&
4118
+ this.getComments([
4119
+ commentsStartPos,
4120
+ /** @type {Range} */ (expr.range)[0]
4121
+ ]).some(
3469
4122
  comment =>
3470
4123
  comment.type === "Block" &&
3471
4124
  /^\s*(#|@)__PURE__\s*$/.test(comment.value)
3472
4125
  );
3473
4126
  if (!pureFlag) return false;
3474
- commentsStartPos = expr.callee.range[1];
4127
+ commentsStartPos = /** @type {Range} */ (expr.callee.range)[1];
3475
4128
  return expr.arguments.every(arg => {
3476
4129
  if (arg.type === "SpreadElement") return false;
3477
4130
  const pureFlag = this.isPure(arg, commentsStartPos);
3478
- commentsStartPos = arg.range[1];
4131
+ commentsStartPos = /** @type {Range} */ (arg.range)[1];
3479
4132
  return pureFlag;
3480
4133
  });
3481
4134
  }
@@ -3484,6 +4137,10 @@ class JavascriptParser extends Parser {
3484
4137
  return !evaluated.couldHaveSideEffects();
3485
4138
  }
3486
4139
 
4140
+ /**
4141
+ * @param {Range} range range
4142
+ * @returns {TODO[]} comments in the range
4143
+ */
3487
4144
  getComments(range) {
3488
4145
  const [rangeStart, rangeEnd] = range;
3489
4146
  const compare = (comment, needle) => comment.range[0] - needle;
@@ -3525,6 +4182,10 @@ class JavascriptParser extends Parser {
3525
4182
  this.semicolons.delete(pos);
3526
4183
  }
3527
4184
 
4185
+ /**
4186
+ * @param {Expression} expr expression
4187
+ * @returns {boolean} true, when the expression is a statement level expression
4188
+ */
3528
4189
  isStatementLevelExpression(expr) {
3529
4190
  const currentStatement = this.statementPath[this.statementPath.length - 1];
3530
4191
  return (
@@ -3571,6 +4232,9 @@ class JavascriptParser extends Parser {
3571
4232
  this.scope.definitions.set(name, newInfo);
3572
4233
  }
3573
4234
 
4235
+ /**
4236
+ * @param {string} name variable name
4237
+ */
3574
4238
  defineVariable(name) {
3575
4239
  const oldInfo = this.scope.definitions.get(name);
3576
4240
  // Don't redefine variable in same scope to keep existing tags
@@ -3579,10 +4243,17 @@ class JavascriptParser extends Parser {
3579
4243
  this.scope.definitions.set(name, this.scope);
3580
4244
  }
3581
4245
 
4246
+ /**
4247
+ * @param {string} name variable name
4248
+ */
3582
4249
  undefineVariable(name) {
3583
4250
  this.scope.definitions.delete(name);
3584
4251
  }
3585
4252
 
4253
+ /**
4254
+ * @param {string} name variable name
4255
+ * @returns {boolean} true, when variable is defined
4256
+ */
3586
4257
  isVariableDefined(name) {
3587
4258
  const info = this.scope.definitions.get(name);
3588
4259
  if (info === undefined) return false;
@@ -3625,10 +4296,18 @@ class JavascriptParser extends Parser {
3625
4296
  }
3626
4297
  }
3627
4298
 
4299
+ /**
4300
+ * @param {TagInfo} tagInfo tag info
4301
+ * @returns {VariableInfo} variable info
4302
+ */
3628
4303
  evaluatedVariable(tagInfo) {
3629
4304
  return new VariableInfo(this.scope, undefined, tagInfo);
3630
4305
  }
3631
4306
 
4307
+ /**
4308
+ * @param {Range} range range of the comment
4309
+ * @returns {TODO} TODO
4310
+ */
3632
4311
  parseCommentOptions(range) {
3633
4312
  const comments = this.getComments(range);
3634
4313
  if (comments.length === 0) {
@@ -3663,21 +4342,24 @@ class JavascriptParser extends Parser {
3663
4342
  }
3664
4343
 
3665
4344
  /**
3666
- * @param {MemberExpressionNode} expression a member expression
3667
- * @returns {{ members: string[], object: ExpressionNode | SuperNode, membersOptionals: boolean[] }} member names (reverse order) and remaining object
4345
+ * @param {MemberExpression} expression a member expression
4346
+ * @returns {{ members: string[], object: Expression | Super, membersOptionals: boolean[], memberRanges: Range[] }} member names (reverse order) and remaining object
3668
4347
  */
3669
4348
  extractMemberExpressionChain(expression) {
3670
4349
  /** @type {AnyNode} */
3671
4350
  let expr = expression;
3672
4351
  const members = [];
3673
4352
  const membersOptionals = [];
4353
+ const memberRanges = [];
3674
4354
  while (expr.type === "MemberExpression") {
3675
4355
  if (expr.computed) {
3676
4356
  if (expr.property.type !== "Literal") break;
3677
- members.push(`${expr.property.value}`);
4357
+ members.push(`${expr.property.value}`); // the literal
4358
+ memberRanges.push(expr.object.range); // the range of the expression fragment before the literal
3678
4359
  } else {
3679
4360
  if (expr.property.type !== "Identifier") break;
3680
- members.push(expr.property.name);
4361
+ members.push(expr.property.name); // the identifier
4362
+ memberRanges.push(expr.object.range); // the range of the expression fragment before the identifier
3681
4363
  }
3682
4364
  membersOptionals.push(expr.optional);
3683
4365
  expr = expr.object;
@@ -3686,13 +4368,14 @@ class JavascriptParser extends Parser {
3686
4368
  return {
3687
4369
  members,
3688
4370
  membersOptionals,
4371
+ memberRanges,
3689
4372
  object: expr
3690
4373
  };
3691
4374
  }
3692
4375
 
3693
4376
  /**
3694
4377
  * @param {string} varName variable name
3695
- * @returns {{name: string, info: VariableInfo | string}} name of the free variable and variable info for that
4378
+ * @returns {{name: string, info: VariableInfo | string} | undefined} name of the free variable and variable info for that
3696
4379
  */
3697
4380
  getFreeInfoFromVariable(varName) {
3698
4381
  const info = this.getVariableInfo(varName);
@@ -3708,16 +4391,16 @@ class JavascriptParser extends Parser {
3708
4391
  return { info, name };
3709
4392
  }
3710
4393
 
3711
- /** @typedef {{ type: "call", call: CallExpressionNode, calleeName: string, rootInfo: string | VariableInfo, getCalleeMembers: () => string[], name: string, getMembers: () => string[], getMembersOptionals: () => boolean[]}} CallExpressionInfo */
3712
- /** @typedef {{ type: "expression", rootInfo: string | VariableInfo, name: string, getMembers: () => string[], getMembersOptionals: () => boolean[]}} ExpressionExpressionInfo */
4394
+ /** @typedef {{ type: "call", call: CallExpression, calleeName: string, rootInfo: string | VariableInfo, getCalleeMembers: () => string[], name: string, getMembers: () => string[], getMembersOptionals: () => boolean[], getMemberRanges: () => Range[]}} CallExpressionInfo */
4395
+ /** @typedef {{ type: "expression", rootInfo: string | VariableInfo, name: string, getMembers: () => string[], getMembersOptionals: () => boolean[], getMemberRanges: () => Range[]}} ExpressionExpressionInfo */
3713
4396
 
3714
4397
  /**
3715
- * @param {MemberExpressionNode} expression a member expression
4398
+ * @param {MemberExpression} expression a member expression
3716
4399
  * @param {number} allowedTypes which types should be returned, presented in bit mask
3717
4400
  * @returns {CallExpressionInfo | ExpressionExpressionInfo | undefined} expression info
3718
4401
  */
3719
4402
  getMemberExpressionInfo(expression, allowedTypes) {
3720
- const { object, members, membersOptionals } =
4403
+ const { object, members, membersOptionals, memberRanges } =
3721
4404
  this.extractMemberExpressionChain(expression);
3722
4405
  switch (object.type) {
3723
4406
  case "CallExpression": {
@@ -3743,7 +4426,8 @@ class JavascriptParser extends Parser {
3743
4426
  getCalleeMembers: memoize(() => rootMembers.reverse()),
3744
4427
  name: objectAndMembersToName(`${calleeName}()`, members),
3745
4428
  getMembers: memoize(() => members.reverse()),
3746
- getMembersOptionals: memoize(() => membersOptionals.reverse())
4429
+ getMembersOptionals: memoize(() => membersOptionals.reverse()),
4430
+ getMemberRanges: memoize(() => memberRanges.reverse())
3747
4431
  };
3748
4432
  }
3749
4433
  case "Identifier":
@@ -3762,15 +4446,16 @@ class JavascriptParser extends Parser {
3762
4446
  name: objectAndMembersToName(resolvedRoot, members),
3763
4447
  rootInfo,
3764
4448
  getMembers: memoize(() => members.reverse()),
3765
- getMembersOptionals: memoize(() => membersOptionals.reverse())
4449
+ getMembersOptionals: memoize(() => membersOptionals.reverse()),
4450
+ getMemberRanges: memoize(() => memberRanges.reverse())
3766
4451
  };
3767
4452
  }
3768
4453
  }
3769
4454
  }
3770
4455
 
3771
4456
  /**
3772
- * @param {MemberExpressionNode} expression an expression
3773
- * @returns {{ name: string, rootInfo: ExportedVariableInfo, getMembers: () => string[]}} name info
4457
+ * @param {MemberExpression} expression an expression
4458
+ * @returns {{ name: string, rootInfo: ExportedVariableInfo, getMembers: () => string[]} | undefined} name info
3774
4459
  */
3775
4460
  getNameForExpression(expression) {
3776
4461
  return this.getMemberExpressionInfo(
@@ -3782,7 +4467,7 @@ class JavascriptParser extends Parser {
3782
4467
  /**
3783
4468
  * @param {string} code source code
3784
4469
  * @param {ParseOptions} options parsing options
3785
- * @returns {ProgramNode} parsed ast
4470
+ * @returns {Program} parsed ast
3786
4471
  */
3787
4472
  static _parse(code, options) {
3788
4473
  const type = options ? options.sourceType : "module";
@@ -3794,7 +4479,7 @@ class JavascriptParser extends Parser {
3794
4479
  sourceType: type === "auto" ? "module" : type
3795
4480
  };
3796
4481
 
3797
- /** @type {AnyNode} */
4482
+ /** @type {AnyNode | undefined} */
3798
4483
  let ast;
3799
4484
  let error;
3800
4485
  let threw = false;
@@ -3826,7 +4511,7 @@ class JavascriptParser extends Parser {
3826
4511
  throw error;
3827
4512
  }
3828
4513
 
3829
- return /** @type {ProgramNode} */ (ast);
4514
+ return /** @type {Program} */ (ast);
3830
4515
  }
3831
4516
  }
3832
4517