webpack 5.59.0 → 5.94.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.
Files changed (570) hide show
  1. package/README.md +48 -38
  2. package/bin/webpack.js +34 -10
  3. package/hot/dev-server.js +19 -5
  4. package/hot/lazy-compilation-node.js +13 -1
  5. package/hot/lazy-compilation-web.js +9 -0
  6. package/hot/log-apply-result.js +5 -0
  7. package/hot/log.js +23 -4
  8. package/hot/only-dev-server.js +3 -2
  9. package/hot/poll.js +5 -2
  10. package/hot/signal.js +6 -2
  11. package/lib/APIPlugin.js +226 -122
  12. package/lib/AbstractMethodError.js +10 -5
  13. package/lib/AsyncDependenciesBlock.js +13 -5
  14. package/lib/AutomaticPrefetchPlugin.js +2 -1
  15. package/lib/BannerPlugin.js +33 -12
  16. package/lib/Cache.js +16 -12
  17. package/lib/CacheFacade.js +13 -16
  18. package/lib/CaseSensitiveModulesWarning.js +8 -8
  19. package/lib/Chunk.js +60 -33
  20. package/lib/ChunkGraph.js +207 -72
  21. package/lib/ChunkGroup.js +40 -20
  22. package/lib/ChunkTemplate.js +43 -0
  23. package/lib/CleanPlugin.js +117 -32
  24. package/lib/CodeGenerationResults.js +8 -7
  25. package/lib/CommentCompilationWarning.js +0 -1
  26. package/lib/CompatibilityPlugin.js +85 -46
  27. package/lib/Compilation.js +712 -392
  28. package/lib/Compiler.js +393 -172
  29. package/lib/ConcatenationScope.js +10 -13
  30. package/lib/ConditionalInitFragment.js +22 -14
  31. package/lib/ConstPlugin.js +104 -64
  32. package/lib/ContextExclusionPlugin.js +3 -3
  33. package/lib/ContextModule.js +283 -108
  34. package/lib/ContextModuleFactory.js +151 -63
  35. package/lib/ContextReplacementPlugin.js +25 -10
  36. package/lib/CssModule.js +166 -0
  37. package/lib/DefinePlugin.js +254 -148
  38. package/lib/DelegatedModule.js +29 -6
  39. package/lib/DelegatedModuleFactoryPlugin.js +42 -22
  40. package/lib/DelegatedPlugin.js +4 -0
  41. package/lib/DependenciesBlock.js +17 -2
  42. package/lib/Dependency.js +58 -29
  43. package/lib/DependencyTemplate.js +24 -3
  44. package/lib/DependencyTemplates.js +2 -2
  45. package/lib/DllEntryPlugin.js +18 -1
  46. package/lib/DllModule.js +21 -4
  47. package/lib/DllModuleFactory.js +2 -1
  48. package/lib/DllPlugin.js +9 -7
  49. package/lib/DllReferencePlugin.js +50 -19
  50. package/lib/EntryOptionPlugin.js +6 -1
  51. package/lib/EntryPlugin.js +7 -4
  52. package/lib/Entrypoint.js +2 -2
  53. package/lib/EnvironmentNotSupportAsyncWarning.js +52 -0
  54. package/lib/EnvironmentPlugin.js +5 -2
  55. package/lib/ErrorHelpers.js +65 -26
  56. package/lib/EvalDevToolModulePlugin.js +37 -13
  57. package/lib/EvalSourceMapDevToolPlugin.js +50 -20
  58. package/lib/ExportsInfo.js +234 -133
  59. package/lib/ExportsInfoApiPlugin.js +31 -15
  60. package/lib/ExternalModule.js +391 -129
  61. package/lib/ExternalModuleFactoryPlugin.js +65 -17
  62. package/lib/FileSystemInfo.js +1038 -523
  63. package/lib/FlagAllModulesAsUsedPlugin.js +27 -27
  64. package/lib/FlagDependencyExportsPlugin.js +352 -349
  65. package/lib/FlagDependencyUsagePlugin.js +10 -10
  66. package/lib/FlagEntryExportAsUsedPlugin.js +26 -23
  67. package/lib/Generator.js +16 -8
  68. package/lib/GraphHelpers.js +3 -2
  69. package/lib/HookWebpackError.js +11 -13
  70. package/lib/HotModuleReplacementPlugin.js +221 -128
  71. package/lib/IgnoreErrorModuleFactory.js +4 -4
  72. package/lib/IgnorePlugin.js +5 -4
  73. package/lib/IgnoreWarningsPlugin.js +6 -9
  74. package/lib/InitFragment.js +39 -15
  75. package/lib/JavascriptMetaInfoPlugin.js +27 -15
  76. package/lib/LibManifestPlugin.js +45 -16
  77. package/lib/LoaderOptionsPlugin.js +13 -3
  78. package/lib/MainTemplate.js +74 -21
  79. package/lib/Module.js +155 -34
  80. package/lib/ModuleBuildError.js +13 -11
  81. package/lib/ModuleDependencyError.js +6 -4
  82. package/lib/ModuleDependencyWarning.js +6 -4
  83. package/lib/ModuleError.js +10 -5
  84. package/lib/ModuleFactory.js +4 -4
  85. package/lib/ModuleFilenameHelpers.js +164 -54
  86. package/lib/ModuleGraph.js +93 -53
  87. package/lib/ModuleGraphConnection.js +27 -13
  88. package/lib/ModuleHashingError.js +29 -0
  89. package/lib/ModuleInfoHeaderPlugin.js +92 -33
  90. package/lib/ModuleNotFoundError.js +5 -2
  91. package/lib/ModuleParseError.js +17 -9
  92. package/lib/ModuleProfile.js +1 -0
  93. package/lib/ModuleRestoreError.js +3 -1
  94. package/lib/ModuleStoreError.js +3 -2
  95. package/lib/ModuleTemplate.js +33 -1
  96. package/lib/ModuleTypeConstants.js +168 -0
  97. package/lib/ModuleWarning.js +10 -5
  98. package/lib/MultiCompiler.js +115 -38
  99. package/lib/MultiStats.js +75 -33
  100. package/lib/MultiWatching.js +6 -2
  101. package/lib/NodeStuffPlugin.js +136 -37
  102. package/lib/NormalModule.js +437 -194
  103. package/lib/NormalModuleFactory.js +313 -116
  104. package/lib/NormalModuleReplacementPlugin.js +10 -4
  105. package/lib/NullFactory.js +1 -1
  106. package/lib/OptimizationStages.js +3 -3
  107. package/lib/Parser.js +1 -1
  108. package/lib/PlatformPlugin.js +39 -0
  109. package/lib/PrefetchPlugin.js +4 -0
  110. package/lib/ProgressPlugin.js +83 -28
  111. package/lib/ProvidePlugin.js +37 -19
  112. package/lib/RawModule.js +18 -5
  113. package/lib/RecordIdsPlugin.js +8 -8
  114. package/lib/RequireJsStuffPlugin.js +22 -15
  115. package/lib/ResolverFactory.js +8 -4
  116. package/lib/RuntimeGlobals.js +99 -65
  117. package/lib/RuntimeModule.js +17 -15
  118. package/lib/RuntimePlugin.js +116 -13
  119. package/lib/RuntimeTemplate.js +304 -102
  120. package/lib/SelfModuleFactory.js +12 -0
  121. package/lib/SizeFormatHelpers.js +2 -4
  122. package/lib/SourceMapDevToolModuleOptionsPlugin.js +4 -0
  123. package/lib/SourceMapDevToolPlugin.js +89 -42
  124. package/lib/Stats.js +12 -7
  125. package/lib/Template.js +30 -33
  126. package/lib/TemplatedPathPlugin.js +102 -34
  127. package/lib/UseStrictPlugin.js +37 -12
  128. package/lib/WarnCaseSensitiveModulesPlugin.js +12 -0
  129. package/lib/WarnDeprecatedOptionPlugin.js +6 -0
  130. package/lib/WatchIgnorePlugin.js +46 -13
  131. package/lib/Watching.js +139 -76
  132. package/lib/WebpackError.js +14 -5
  133. package/lib/WebpackIsIncludedPlugin.js +22 -13
  134. package/lib/WebpackOptionsApply.js +162 -56
  135. package/lib/WebpackOptionsDefaulter.js +10 -3
  136. package/lib/asset/AssetGenerator.js +351 -99
  137. package/lib/asset/AssetModulesPlugin.js +57 -33
  138. package/lib/asset/AssetParser.js +15 -6
  139. package/lib/asset/AssetSourceGenerator.js +30 -10
  140. package/lib/asset/AssetSourceParser.js +8 -2
  141. package/lib/asset/RawDataUrlModule.js +162 -0
  142. package/lib/async-modules/AwaitDependenciesInitFragment.js +16 -13
  143. package/lib/async-modules/InferAsyncModulesPlugin.js +1 -1
  144. package/lib/buildChunkGraph.js +376 -420
  145. package/lib/cache/AddManagedPathsPlugin.js +6 -1
  146. package/lib/cache/IdleFileCachePlugin.js +26 -13
  147. package/lib/cache/MemoryCachePlugin.js +1 -1
  148. package/lib/cache/MemoryWithGcCachePlugin.js +13 -7
  149. package/lib/cache/PackFileCacheStrategy.js +172 -94
  150. package/lib/cache/ResolverCachePlugin.js +115 -43
  151. package/lib/cache/getLazyHashedEtag.js +2 -2
  152. package/lib/cache/mergeEtags.js +16 -21
  153. package/lib/cli.js +195 -110
  154. package/lib/config/browserslistTargetHandler.js +106 -41
  155. package/lib/config/defaults.js +572 -154
  156. package/lib/config/normalization.js +361 -322
  157. package/lib/config/target.js +105 -66
  158. package/lib/container/ContainerEntryDependency.js +2 -1
  159. package/lib/container/ContainerEntryModule.js +27 -11
  160. package/lib/container/ContainerEntryModuleFactory.js +1 -1
  161. package/lib/container/ContainerExposedDependency.js +9 -0
  162. package/lib/container/ContainerPlugin.js +18 -12
  163. package/lib/container/ContainerReferencePlugin.js +1 -1
  164. package/lib/container/FallbackDependency.js +13 -0
  165. package/lib/container/FallbackItemDependency.js +3 -0
  166. package/lib/container/FallbackModule.js +19 -8
  167. package/lib/container/FallbackModuleFactory.js +1 -1
  168. package/lib/container/ModuleFederationPlugin.js +2 -0
  169. package/lib/container/RemoteModule.js +17 -4
  170. package/lib/container/RemoteRuntimeModule.js +31 -17
  171. package/lib/container/RemoteToExternalDependency.js +3 -0
  172. package/lib/container/options.js +18 -4
  173. package/lib/css/CssExportsGenerator.js +203 -0
  174. package/lib/css/CssGenerator.js +151 -0
  175. package/lib/css/CssLoadingRuntimeModule.js +592 -0
  176. package/lib/css/CssModulesPlugin.js +888 -0
  177. package/lib/css/CssParser.js +1049 -0
  178. package/lib/css/walkCssTokens.js +775 -0
  179. package/lib/debug/ProfilingPlugin.js +102 -54
  180. package/lib/dependencies/AMDDefineDependency.js +54 -10
  181. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +204 -61
  182. package/lib/dependencies/AMDPlugin.js +44 -24
  183. package/lib/dependencies/AMDRequireArrayDependency.js +34 -10
  184. package/lib/dependencies/AMDRequireContextDependency.js +15 -0
  185. package/lib/dependencies/AMDRequireDependenciesBlock.js +6 -0
  186. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +185 -54
  187. package/lib/dependencies/AMDRequireDependency.js +21 -6
  188. package/lib/dependencies/AMDRequireItemDependency.js +6 -0
  189. package/lib/dependencies/AMDRuntimeModules.js +4 -4
  190. package/lib/dependencies/CachedConstDependency.js +22 -1
  191. package/lib/dependencies/CommonJsDependencyHelpers.js +16 -2
  192. package/lib/dependencies/CommonJsExportRequireDependency.js +77 -47
  193. package/lib/dependencies/CommonJsExportsDependency.js +28 -5
  194. package/lib/dependencies/CommonJsExportsParserPlugin.js +111 -39
  195. package/lib/dependencies/CommonJsFullRequireDependency.js +42 -8
  196. package/lib/dependencies/CommonJsImportsParserPlugin.js +530 -130
  197. package/lib/dependencies/CommonJsPlugin.js +51 -26
  198. package/lib/dependencies/CommonJsRequireContextDependency.js +23 -2
  199. package/lib/dependencies/CommonJsRequireDependency.js +9 -1
  200. package/lib/dependencies/CommonJsSelfReferenceDependency.js +22 -8
  201. package/lib/dependencies/ConstDependency.js +12 -3
  202. package/lib/dependencies/ContextDependency.js +32 -5
  203. package/lib/dependencies/ContextDependencyHelpers.js +92 -62
  204. package/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +4 -1
  205. package/lib/dependencies/ContextElementDependency.js +41 -4
  206. package/lib/dependencies/CreateScriptUrlDependency.js +22 -1
  207. package/lib/dependencies/CriticalDependencyWarning.js +4 -1
  208. package/lib/dependencies/CssExportDependency.js +156 -0
  209. package/lib/dependencies/CssImportDependency.js +125 -0
  210. package/lib/dependencies/CssLocalIdentifierDependency.js +245 -0
  211. package/lib/dependencies/CssSelfLocalIdentifierDependency.js +111 -0
  212. package/lib/dependencies/CssUrlDependency.js +164 -0
  213. package/lib/dependencies/DelegatedSourceDependency.js +3 -0
  214. package/lib/dependencies/DllEntryDependency.js +14 -0
  215. package/lib/dependencies/DynamicExports.js +15 -11
  216. package/lib/dependencies/ExportsInfoDependency.js +26 -5
  217. package/lib/dependencies/ExternalModuleDependency.js +109 -0
  218. package/lib/dependencies/ExternalModuleInitFragment.js +133 -0
  219. package/lib/dependencies/HarmonyAcceptDependency.js +11 -2
  220. package/lib/dependencies/HarmonyAcceptImportDependency.js +9 -4
  221. package/lib/dependencies/HarmonyCompatibilityDependency.js +6 -5
  222. package/lib/dependencies/HarmonyDetectionParserPlugin.js +29 -3
  223. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +152 -0
  224. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +96 -51
  225. package/lib/dependencies/HarmonyExportExpressionDependency.js +21 -4
  226. package/lib/dependencies/HarmonyExportHeaderDependency.js +13 -0
  227. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +216 -108
  228. package/lib/dependencies/HarmonyExportInitFragment.js +21 -9
  229. package/lib/dependencies/HarmonyExportSpecifierDependency.js +12 -0
  230. package/lib/dependencies/HarmonyExports.js +13 -7
  231. package/lib/dependencies/HarmonyImportDependency.js +65 -19
  232. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +268 -74
  233. package/lib/dependencies/HarmonyImportSideEffectDependency.js +11 -5
  234. package/lib/dependencies/HarmonyImportSpecifierDependency.js +180 -36
  235. package/lib/dependencies/HarmonyModulesPlugin.js +33 -5
  236. package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +15 -3
  237. package/lib/dependencies/ImportContextDependency.js +15 -2
  238. package/lib/dependencies/ImportDependency.js +50 -12
  239. package/lib/dependencies/ImportEagerDependency.js +11 -6
  240. package/lib/dependencies/ImportMetaContextDependency.js +42 -0
  241. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +301 -0
  242. package/lib/dependencies/ImportMetaContextPlugin.js +72 -0
  243. package/lib/dependencies/ImportMetaHotAcceptDependency.js +6 -0
  244. package/lib/dependencies/ImportMetaHotDeclineDependency.js +6 -0
  245. package/lib/dependencies/ImportMetaPlugin.js +128 -59
  246. package/lib/dependencies/ImportParserPlugin.js +153 -83
  247. package/lib/dependencies/ImportPlugin.js +21 -7
  248. package/lib/dependencies/ImportWeakDependency.js +11 -6
  249. package/lib/dependencies/JsonExportsDependency.js +38 -30
  250. package/lib/dependencies/LoaderDependency.js +14 -0
  251. package/lib/dependencies/LoaderImportDependency.js +14 -0
  252. package/lib/dependencies/LoaderPlugin.js +54 -40
  253. package/lib/dependencies/LocalModule.js +17 -1
  254. package/lib/dependencies/LocalModuleDependency.js +15 -0
  255. package/lib/dependencies/LocalModulesHelpers.js +22 -4
  256. package/lib/dependencies/ModuleDecoratorDependency.js +9 -1
  257. package/lib/dependencies/ModuleDependency.js +24 -7
  258. package/lib/dependencies/ModuleDependencyTemplateAsId.js +2 -1
  259. package/lib/dependencies/ModuleHotAcceptDependency.js +6 -0
  260. package/lib/dependencies/ModuleHotDeclineDependency.js +6 -0
  261. package/lib/dependencies/PrefetchDependency.js +3 -0
  262. package/lib/dependencies/ProvidedDependency.js +43 -8
  263. package/lib/dependencies/PureExpressionDependency.js +73 -39
  264. package/lib/dependencies/RequireContextDependency.js +6 -16
  265. package/lib/dependencies/RequireContextDependencyParserPlugin.js +14 -6
  266. package/lib/dependencies/RequireContextPlugin.js +20 -7
  267. package/lib/dependencies/RequireEnsureDependenciesBlock.js +7 -0
  268. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +29 -12
  269. package/lib/dependencies/RequireEnsureDependency.js +16 -2
  270. package/lib/dependencies/RequireEnsureItemDependency.js +3 -0
  271. package/lib/dependencies/RequireEnsurePlugin.js +27 -7
  272. package/lib/dependencies/RequireHeaderDependency.js +14 -1
  273. package/lib/dependencies/RequireIncludeDependency.js +6 -1
  274. package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +29 -5
  275. package/lib/dependencies/RequireIncludePlugin.js +25 -5
  276. package/lib/dependencies/RequireResolveContextDependency.js +19 -2
  277. package/lib/dependencies/RequireResolveDependency.js +8 -1
  278. package/lib/dependencies/RequireResolveHeaderDependency.js +18 -0
  279. package/lib/dependencies/RuntimeRequirementsDependency.js +9 -1
  280. package/lib/dependencies/StaticExportsDependency.js +8 -0
  281. package/lib/dependencies/SystemPlugin.js +49 -22
  282. package/lib/dependencies/SystemRuntimeModule.js +1 -1
  283. package/lib/dependencies/URLDependency.js +20 -13
  284. package/lib/dependencies/URLPlugin.js +115 -27
  285. package/lib/dependencies/UnsupportedDependency.js +13 -0
  286. package/lib/dependencies/WebAssemblyExportImportedDependency.js +14 -0
  287. package/lib/dependencies/WebAssemblyImportDependency.js +9 -1
  288. package/lib/dependencies/WebpackIsIncludedDependency.js +6 -1
  289. package/lib/dependencies/WorkerDependency.js +47 -3
  290. package/lib/dependencies/WorkerPlugin.js +143 -59
  291. package/lib/dependencies/getFunctionExpression.js +9 -0
  292. package/lib/dependencies/processExportInfo.js +3 -1
  293. package/lib/electron/ElectronTargetPlugin.js +1 -0
  294. package/lib/esm/ExportWebpackRequireRuntimeModule.js +3 -2
  295. package/lib/esm/ModuleChunkFormatPlugin.js +92 -55
  296. package/lib/esm/ModuleChunkLoadingPlugin.js +12 -1
  297. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +141 -25
  298. package/lib/formatLocation.js +1 -2
  299. package/lib/hmr/HotModuleReplacement.runtime.js +37 -25
  300. package/lib/hmr/HotModuleReplacementRuntimeModule.js +2 -1
  301. package/lib/hmr/JavascriptHotModuleReplacement.runtime.js +13 -15
  302. package/lib/hmr/LazyCompilationPlugin.js +94 -41
  303. package/lib/hmr/lazyCompilationBackend.js +107 -44
  304. package/lib/ids/ChunkModuleIdRangePlugin.js +12 -3
  305. package/lib/ids/DeterministicChunkIdsPlugin.js +13 -6
  306. package/lib/ids/DeterministicModuleIdsPlugin.js +59 -35
  307. package/lib/ids/HashedModuleIdsPlugin.js +24 -16
  308. package/lib/ids/IdHelpers.js +59 -49
  309. package/lib/ids/NamedChunkIdsPlugin.js +13 -1
  310. package/lib/ids/NamedModuleIdsPlugin.js +20 -12
  311. package/lib/ids/NaturalModuleIdsPlugin.js +10 -13
  312. package/lib/ids/OccurrenceChunkIdsPlugin.js +6 -2
  313. package/lib/ids/OccurrenceModuleIdsPlugin.js +14 -11
  314. package/lib/ids/SyncModuleIdsPlugin.js +146 -0
  315. package/lib/index.js +44 -5
  316. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +9 -7
  317. package/lib/javascript/BasicEvaluatedExpression.js +133 -19
  318. package/lib/javascript/ChunkHelpers.js +33 -0
  319. package/lib/javascript/CommonJsChunkFormatPlugin.js +18 -15
  320. package/lib/javascript/EnableChunkLoadingPlugin.js +11 -6
  321. package/lib/javascript/JavascriptGenerator.js +37 -6
  322. package/lib/javascript/JavascriptModulesPlugin.js +523 -295
  323. package/lib/javascript/JavascriptParser.js +1591 -574
  324. package/lib/javascript/JavascriptParserHelpers.js +58 -37
  325. package/lib/javascript/StartupHelpers.js +69 -47
  326. package/lib/json/JsonData.js +33 -0
  327. package/lib/json/JsonGenerator.js +29 -21
  328. package/lib/json/JsonModulesPlugin.js +13 -7
  329. package/lib/json/JsonParser.js +30 -16
  330. package/lib/library/AbstractLibraryPlugin.js +6 -2
  331. package/lib/library/AmdLibraryPlugin.js +34 -18
  332. package/lib/library/AssignLibraryPlugin.js +68 -32
  333. package/lib/library/EnableLibraryPlugin.js +39 -14
  334. package/lib/library/ExportPropertyLibraryPlugin.js +14 -5
  335. package/lib/library/JsonpLibraryPlugin.js +4 -3
  336. package/lib/library/ModernModuleLibraryPlugin.js +144 -0
  337. package/lib/library/ModuleLibraryPlugin.js +12 -7
  338. package/lib/library/SystemLibraryPlugin.js +6 -4
  339. package/lib/library/UmdLibraryPlugin.js +119 -100
  340. package/lib/logging/Logger.js +59 -6
  341. package/lib/logging/createConsoleLogger.js +25 -40
  342. package/lib/logging/runtime.js +8 -9
  343. package/lib/logging/truncateArgs.js +9 -8
  344. package/lib/node/CommonJsChunkLoadingPlugin.js +18 -2
  345. package/lib/node/NodeEnvironmentPlugin.js +14 -8
  346. package/lib/node/NodeTargetPlugin.js +7 -0
  347. package/lib/node/NodeTemplatePlugin.js +10 -2
  348. package/lib/node/NodeWatchFileSystem.js +100 -50
  349. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +51 -26
  350. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +13 -2
  351. package/lib/node/ReadFileCompileWasmPlugin.js +21 -3
  352. package/lib/node/RequireChunkLoadingRuntimeModule.js +49 -26
  353. package/lib/node/nodeConsole.js +48 -31
  354. package/lib/optimize/AggressiveMergingPlugin.js +10 -4
  355. package/lib/optimize/AggressiveSplittingPlugin.js +26 -21
  356. package/lib/optimize/ConcatenatedModule.js +353 -212
  357. package/lib/optimize/EnsureChunkConditionsPlugin.js +4 -1
  358. package/lib/optimize/FlagIncludedChunksPlugin.js +14 -8
  359. package/lib/optimize/InnerGraph.js +30 -25
  360. package/lib/optimize/InnerGraphPlugin.js +105 -64
  361. package/lib/optimize/LimitChunkCountPlugin.js +32 -9
  362. package/lib/optimize/MangleExportsPlugin.js +7 -2
  363. package/lib/optimize/MinMaxSizeWarning.js +6 -1
  364. package/lib/optimize/ModuleConcatenationPlugin.js +150 -83
  365. package/lib/optimize/RealContentHashPlugin.js +99 -43
  366. package/lib/optimize/RemoveParentModulesPlugin.js +131 -48
  367. package/lib/optimize/RuntimeChunkPlugin.js +15 -2
  368. package/lib/optimize/SideEffectsFlagPlugin.js +119 -63
  369. package/lib/optimize/SplitChunksPlugin.js +129 -78
  370. package/lib/performance/SizeLimitsPlugin.js +22 -8
  371. package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +4 -2
  372. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +4 -1
  373. package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +8 -5
  374. package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +5 -3
  375. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +5 -3
  376. package/lib/rules/BasicEffectRulePlugin.js +7 -1
  377. package/lib/rules/BasicMatcherRulePlugin.js +8 -1
  378. package/lib/rules/ObjectMatcherRulePlugin.js +19 -2
  379. package/lib/rules/RuleSetCompiler.js +53 -32
  380. package/lib/rules/UseEffectRulePlugin.js +42 -36
  381. package/lib/runtime/AsyncModuleRuntimeModule.js +56 -69
  382. package/lib/runtime/AutoPublicPathRuntimeModule.js +25 -9
  383. package/lib/runtime/BaseUriRuntimeModule.js +35 -0
  384. package/lib/runtime/ChunkNameRuntimeModule.js +1 -1
  385. package/lib/runtime/CompatGetDefaultExportRuntimeModule.js +5 -2
  386. package/lib/runtime/CompatRuntimeModule.js +7 -2
  387. package/lib/runtime/CreateFakeNamespaceObjectRuntimeModule.js +7 -4
  388. package/lib/runtime/CreateScriptRuntimeModule.js +38 -0
  389. package/lib/runtime/CreateScriptUrlRuntimeModule.js +13 -36
  390. package/lib/runtime/DefinePropertyGettersRuntimeModule.js +6 -3
  391. package/lib/runtime/EnsureChunkRuntimeModule.js +29 -15
  392. package/lib/runtime/GetChunkFilenameRuntimeModule.js +56 -43
  393. package/lib/runtime/GetFullHashRuntimeModule.js +4 -3
  394. package/lib/runtime/GetMainFilenameRuntimeModule.js +5 -2
  395. package/lib/runtime/GetTrustedTypesPolicyRuntimeModule.js +98 -0
  396. package/lib/runtime/GlobalRuntimeModule.js +1 -1
  397. package/lib/runtime/HasOwnPropertyRuntimeModule.js +5 -2
  398. package/lib/runtime/LoadScriptRuntimeModule.js +61 -45
  399. package/lib/runtime/MakeNamespaceObjectRuntimeModule.js +5 -2
  400. package/lib/runtime/NonceRuntimeModule.js +24 -0
  401. package/lib/runtime/OnChunksLoadedRuntimeModule.js +4 -2
  402. package/lib/runtime/PublicPathRuntimeModule.js +9 -2
  403. package/lib/runtime/RelativeUrlRuntimeModule.js +5 -2
  404. package/lib/runtime/RuntimeIdRuntimeModule.js +6 -2
  405. package/lib/runtime/StartupChunkDependenciesPlugin.js +15 -0
  406. package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +36 -28
  407. package/lib/runtime/StartupEntrypointRuntimeModule.js +13 -9
  408. package/lib/runtime/SystemContextRuntimeModule.js +1 -1
  409. package/lib/schemes/DataUriPlugin.js +16 -3
  410. package/lib/schemes/HttpUriPlugin.js +336 -120
  411. package/lib/serialization/ArraySerializer.js +22 -6
  412. package/lib/serialization/BinaryMiddleware.js +212 -33
  413. package/lib/serialization/DateObjectSerializer.js +16 -4
  414. package/lib/serialization/ErrorObjectSerializer.js +23 -6
  415. package/lib/serialization/FileMiddleware.js +187 -86
  416. package/lib/serialization/MapObjectSerializer.js +25 -8
  417. package/lib/serialization/NullPrototypeObjectSerializer.js +26 -8
  418. package/lib/serialization/ObjectMiddleware.js +96 -66
  419. package/lib/serialization/PlainObjectSerializer.js +51 -14
  420. package/lib/serialization/RegExpObjectSerializer.js +17 -5
  421. package/lib/serialization/Serializer.js +23 -5
  422. package/lib/serialization/SerializerMiddleware.js +8 -8
  423. package/lib/serialization/SetObjectSerializer.js +22 -6
  424. package/lib/serialization/SingleItemMiddleware.js +2 -2
  425. package/lib/serialization/types.js +2 -2
  426. package/lib/sharing/ConsumeSharedFallbackDependency.js +3 -0
  427. package/lib/sharing/ConsumeSharedModule.js +40 -17
  428. package/lib/sharing/ConsumeSharedPlugin.js +139 -102
  429. package/lib/sharing/ConsumeSharedRuntimeModule.js +144 -130
  430. package/lib/sharing/ProvideForSharedDependency.js +0 -1
  431. package/lib/sharing/ProvideSharedDependency.js +17 -0
  432. package/lib/sharing/ProvideSharedModule.js +19 -6
  433. package/lib/sharing/ProvideSharedModuleFactory.js +1 -1
  434. package/lib/sharing/ProvideSharedPlugin.js +37 -30
  435. package/lib/sharing/SharePlugin.js +2 -2
  436. package/lib/sharing/ShareRuntimeModule.js +20 -10
  437. package/lib/sharing/resolveMatchedConfigs.js +6 -5
  438. package/lib/sharing/utils.js +338 -34
  439. package/lib/stats/DefaultStatsFactoryPlugin.js +660 -396
  440. package/lib/stats/DefaultStatsPresetPlugin.js +85 -25
  441. package/lib/stats/DefaultStatsPrinterPlugin.js +525 -145
  442. package/lib/stats/StatsFactory.js +128 -57
  443. package/lib/stats/StatsPrinter.js +77 -46
  444. package/lib/util/ArrayHelpers.js +35 -1
  445. package/lib/util/ArrayQueue.js +15 -22
  446. package/lib/util/AsyncQueue.js +37 -16
  447. package/lib/util/IterableHelpers.js +3 -4
  448. package/lib/util/LazyBucketSortedSet.js +60 -44
  449. package/lib/util/LazySet.js +11 -2
  450. package/lib/util/MapHelpers.js +17 -5
  451. package/lib/util/ParallelismFactorCalculator.js +11 -1
  452. package/lib/util/Queue.js +9 -3
  453. package/lib/util/Semaphore.js +4 -7
  454. package/lib/util/SetHelpers.js +5 -5
  455. package/lib/util/SortableSet.js +19 -6
  456. package/lib/util/StackedCacheMap.js +33 -3
  457. package/lib/util/StackedMap.js +1 -3
  458. package/lib/util/StringXor.js +46 -0
  459. package/lib/util/TupleQueue.js +9 -3
  460. package/lib/util/TupleSet.js +15 -5
  461. package/lib/util/URLAbsoluteSpecifier.js +8 -8
  462. package/lib/util/WeakTupleMap.js +70 -28
  463. package/lib/util/binarySearchBounds.js +51 -9
  464. package/lib/util/chainedImports.js +97 -0
  465. package/lib/util/cleverMerge.js +51 -36
  466. package/lib/util/comparators.js +146 -83
  467. package/lib/util/compileBooleanMatcher.js +35 -7
  468. package/lib/util/conventions.js +126 -0
  469. package/lib/util/create-schema-validation.js +9 -2
  470. package/lib/util/createHash.js +49 -14
  471. package/lib/util/deprecation.js +48 -15
  472. package/lib/util/deterministicGrouping.js +71 -39
  473. package/lib/util/extractUrlAndGlobal.js +3 -0
  474. package/lib/util/findGraphRoots.js +7 -5
  475. package/lib/util/fs.js +419 -94
  476. package/lib/util/hash/BatchedHash.js +10 -4
  477. package/lib/util/hash/md4.js +20 -0
  478. package/lib/util/hash/wasm-hash.js +163 -0
  479. package/lib/util/hash/xxhash64.js +7 -141
  480. package/lib/util/identifier.js +140 -93
  481. package/lib/util/internalSerializables.js +22 -0
  482. package/lib/util/makeSerializable.js +7 -0
  483. package/lib/util/memoize.js +10 -10
  484. package/lib/util/mergeScope.js +76 -0
  485. package/lib/util/nonNumericOnlyHash.js +22 -0
  486. package/lib/util/numberHash.js +84 -34
  487. package/lib/util/objectToMap.js +0 -1
  488. package/lib/util/processAsyncTree.js +7 -1
  489. package/lib/util/propertyAccess.js +7 -55
  490. package/lib/util/propertyName.js +77 -0
  491. package/lib/util/registerExternalSerializer.js +2 -2
  492. package/lib/util/runtime.js +188 -133
  493. package/lib/util/semver.js +64 -56
  494. package/lib/util/serialization.js +26 -1
  495. package/lib/util/smartGrouping.js +10 -10
  496. package/lib/util/source.js +1 -1
  497. package/lib/validateSchema.js +6 -2
  498. package/lib/wasm/EnableWasmLoadingPlugin.js +9 -4
  499. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +70 -30
  500. package/lib/wasm-async/AsyncWebAssemblyGenerator.js +9 -1
  501. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +34 -16
  502. package/lib/wasm-async/AsyncWebAssemblyModulesPlugin.js +32 -12
  503. package/lib/wasm-async/AsyncWebAssemblyParser.js +17 -4
  504. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +72 -31
  505. package/lib/wasm-sync/WasmFinalizeExportsPlugin.js +17 -6
  506. package/lib/wasm-sync/WebAssemblyGenerator.js +72 -52
  507. package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +5 -4
  508. package/lib/wasm-sync/WebAssemblyModulesPlugin.js +53 -43
  509. package/lib/wasm-sync/WebAssemblyParser.js +23 -9
  510. package/lib/wasm-sync/WebAssemblyUtils.js +5 -4
  511. package/lib/web/FetchCompileAsyncWasmPlugin.js +11 -1
  512. package/lib/web/FetchCompileWasmPlugin.js +59 -42
  513. package/lib/web/JsonpChunkLoadingPlugin.js +9 -0
  514. package/lib/web/JsonpChunkLoadingRuntimeModule.js +71 -41
  515. package/lib/webpack.js +43 -12
  516. package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +15 -12
  517. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +55 -40
  518. package/module.d.ts +233 -0
  519. package/package.json +85 -139
  520. package/schemas/WebpackOptions.check.js +1 -1
  521. package/schemas/WebpackOptions.json +679 -47
  522. package/schemas/plugins/BannerPlugin.check.js +1 -1
  523. package/schemas/plugins/BannerPlugin.json +9 -1
  524. package/schemas/plugins/DllReferencePlugin.check.js +1 -1
  525. package/schemas/plugins/HashedModuleIdsPlugin.check.js +1 -1
  526. package/schemas/plugins/ProgressPlugin.check.js +1 -1
  527. package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
  528. package/schemas/plugins/SourceMapDevToolPlugin.json +4 -0
  529. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
  530. package/schemas/plugins/asset/AssetInlineGeneratorOptions.check.js +1 -1
  531. package/schemas/plugins/asset/AssetParserOptions.check.js +1 -1
  532. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
  533. package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
  534. package/schemas/plugins/container/ContainerPlugin.json +10 -1
  535. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  536. package/schemas/plugins/container/ContainerReferencePlugin.json +2 -0
  537. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  538. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  539. package/schemas/plugins/container/ModuleFederationPlugin.json +12 -1
  540. package/schemas/plugins/css/CssAutoGeneratorOptions.check.d.ts +7 -0
  541. package/schemas/plugins/css/CssAutoGeneratorOptions.check.js +6 -0
  542. package/schemas/plugins/css/CssAutoGeneratorOptions.json +3 -0
  543. package/schemas/plugins/css/CssAutoParserOptions.check.d.ts +7 -0
  544. package/schemas/plugins/css/CssAutoParserOptions.check.js +6 -0
  545. package/schemas/plugins/css/CssAutoParserOptions.json +3 -0
  546. package/schemas/plugins/css/CssGeneratorOptions.check.d.ts +7 -0
  547. package/schemas/plugins/css/CssGeneratorOptions.check.js +6 -0
  548. package/schemas/plugins/css/CssGeneratorOptions.json +3 -0
  549. package/schemas/plugins/css/CssGlobalGeneratorOptions.check.d.ts +7 -0
  550. package/schemas/plugins/css/CssGlobalGeneratorOptions.check.js +6 -0
  551. package/schemas/plugins/css/CssGlobalGeneratorOptions.json +3 -0
  552. package/schemas/plugins/css/CssGlobalParserOptions.check.d.ts +7 -0
  553. package/schemas/plugins/css/CssGlobalParserOptions.check.js +6 -0
  554. package/schemas/plugins/css/CssGlobalParserOptions.json +3 -0
  555. package/schemas/plugins/css/CssModuleGeneratorOptions.check.d.ts +7 -0
  556. package/schemas/plugins/css/CssModuleGeneratorOptions.check.js +6 -0
  557. package/schemas/plugins/css/CssModuleGeneratorOptions.json +3 -0
  558. package/schemas/plugins/css/CssModuleParserOptions.check.d.ts +7 -0
  559. package/schemas/plugins/css/CssModuleParserOptions.check.js +6 -0
  560. package/schemas/plugins/css/CssModuleParserOptions.json +3 -0
  561. package/schemas/plugins/css/CssParserOptions.check.d.ts +7 -0
  562. package/schemas/plugins/css/CssParserOptions.check.js +6 -0
  563. package/schemas/plugins/css/CssParserOptions.json +3 -0
  564. package/schemas/plugins/optimize/AggressiveSplittingPlugin.check.js +1 -1
  565. package/schemas/plugins/optimize/LimitChunkCountPlugin.check.js +1 -1
  566. package/schemas/plugins/optimize/MinChunkSizePlugin.check.js +1 -1
  567. package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
  568. package/schemas/plugins/schemes/HttpUriPlugin.json +4 -0
  569. package/schemas/plugins/sharing/SharePlugin.check.js +1 -1
  570. package/types.d.ts +5026 -1756
@@ -6,7 +6,7 @@
6
6
  "use strict";
7
7
 
8
8
  const { Parser: AcornParser } = require("acorn");
9
- const { importAssertions } = require("acorn-import-assertions");
9
+ const { importAttributesOrAssertions } = require("acorn-import-attributes");
10
10
  const { SyncBailHook, HookMap } = require("tapable");
11
11
  const vm = require("vm");
12
12
  const Parser = require("../Parser");
@@ -16,49 +16,92 @@ 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 */
56
- /** @template T @typedef {import("tapable").AsArray<T>} AsArray<T> */
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 {import("estree").AssignmentProperty} AssignmentProperty */
91
+ /**
92
+ * @template T
93
+ * @typedef {import("tapable").AsArray<T>} AsArray<T>
94
+ */
57
95
  /** @typedef {import("../Parser").ParserState} ParserState */
58
96
  /** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
59
97
  /** @typedef {{declaredScope: ScopeInfo, freeName: string | true, tagInfo: TagInfo | undefined}} VariableInfoInterface */
60
- /** @typedef {{ name: string | VariableInfo, rootInfo: string | VariableInfo, getMembers: () => string[] }} GetInfoResult */
98
+ /** @typedef {{ name: string | VariableInfo, rootInfo: string | VariableInfo, getMembers: () => string[], getMembersOptionals: () => boolean[], getMemberRanges: () => Range[] }} GetInfoResult */
99
+ /** @typedef {Statement | ModuleDeclaration | Expression} StatementPathItem */
100
+ /** @typedef {TODO} OnIdent */
61
101
 
102
+ /** @typedef {Record<string, string> & { _isLegacyAssert?: boolean }} ImportAttributes */
103
+
104
+ /** @type {string[]} */
62
105
  const EMPTY_ARRAY = [];
63
106
  const ALLOWED_MEMBER_TYPES_CALL_EXPRESSION = 0b01;
64
107
  const ALLOWED_MEMBER_TYPES_EXPRESSION = 0b10;
@@ -66,12 +109,12 @@ const ALLOWED_MEMBER_TYPES_ALL = 0b11;
66
109
 
67
110
  // Syntax: https://developer.mozilla.org/en/SpiderMonkey/Parser_API
68
111
 
69
- const parser = AcornParser.extend(importAssertions);
112
+ const parser = AcornParser.extend(importAttributesOrAssertions);
70
113
 
71
114
  class VariableInfo {
72
115
  /**
73
116
  * @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
117
+ * @param {string | true | undefined} freeName which free name the variable aliases, or true when none
75
118
  * @param {TagInfo | undefined} tagInfo info about tags
76
119
  */
77
120
  constructor(declaredScope, freeName, tagInfo) {
@@ -82,40 +125,88 @@ class VariableInfo {
82
125
  }
83
126
 
84
127
  /** @typedef {string | ScopeInfo | VariableInfo} ExportedVariableInfo */
85
- /** @typedef {LiteralNode | string | null | undefined} ImportSource */
128
+ /** @typedef {Literal | string | null | undefined} ImportSource */
86
129
  /** @typedef {Omit<AcornOptions, "sourceType" | "ecmaVersion"> & { sourceType: "module" | "script" | "auto", ecmaVersion?: AcornOptions["ecmaVersion"] }} ParseOptions */
87
130
 
88
131
  /**
89
- * @typedef {Object} TagInfo
132
+ * @typedef {object} TagInfo
90
133
  * @property {any} tag
91
134
  * @property {any} data
92
135
  * @property {TagInfo | undefined} next
93
136
  */
94
137
 
95
138
  /**
96
- * @typedef {Object} ScopeInfo
139
+ * @typedef {object} ScopeInfo
97
140
  * @property {StackedMap<string, VariableInfo | ScopeInfo>} definitions
98
141
  * @property {boolean | "arrow"} topLevelScope
99
- * @property {boolean} inShorthand
142
+ * @property {boolean | string} inShorthand
143
+ * @property {boolean} inTaggedTemplateTag
144
+ * @property {boolean} inTry
100
145
  * @property {boolean} isStrict
101
146
  * @property {boolean} isAsmJs
102
- * @property {boolean} inTry
103
147
  */
104
148
 
149
+ /** @typedef {[number, number]} Range */
150
+
151
+ /**
152
+ * @typedef {object} DestructuringAssignmentProperty
153
+ * @property {string} id
154
+ * @property {Range | undefined=} range
155
+ * @property {boolean | string} shorthand
156
+ */
157
+
158
+ /**
159
+ * Helper function for joining two ranges into a single range. This is useful
160
+ * when working with AST nodes, as it allows you to combine the ranges of child nodes
161
+ * to create the range of the _parent node_.
162
+ * @param {[number, number]} startRange start range to join
163
+ * @param {[number, number]} endRange end range to join
164
+ * @returns {[number, number]} joined range
165
+ * @example
166
+ * ```js
167
+ * const startRange = [0, 5];
168
+ * const endRange = [10, 15];
169
+ * const joinedRange = joinRanges(startRange, endRange);
170
+ * console.log(joinedRange); // [0, 15]
171
+ * ```
172
+ */
105
173
  const joinRanges = (startRange, endRange) => {
106
174
  if (!endRange) return startRange;
107
175
  if (!startRange) return endRange;
108
176
  return [startRange[0], endRange[1]];
109
177
  };
110
178
 
179
+ /**
180
+ * Helper function used to generate a string representation of a
181
+ * [member expression](https://github.com/estree/estree/blob/master/es5.md#memberexpression).
182
+ * @param {string} object object to name
183
+ * @param {string[]} membersReversed reversed list of members
184
+ * @returns {string} member expression as a string
185
+ * @example
186
+ * ```js
187
+ * const membersReversed = ["property1", "property2", "property3"]; // Members parsed from the AST
188
+ * const name = objectAndMembersToName("myObject", membersReversed);
189
+ *
190
+ * console.log(name); // "myObject.property1.property2.property3"
191
+ * ```
192
+ */
111
193
  const objectAndMembersToName = (object, membersReversed) => {
112
194
  let name = object;
113
195
  for (let i = membersReversed.length - 1; i >= 0; i--) {
114
- name = name + "." + membersReversed[i];
196
+ name = `${name}.${membersReversed[i]}`;
115
197
  }
116
198
  return name;
117
199
  };
118
200
 
201
+ /**
202
+ * Grabs the name of a given expression and returns it as a string or undefined. Has particular
203
+ * handling for [Identifiers](https://github.com/estree/estree/blob/master/es5.md#identifier),
204
+ * [ThisExpressions](https://github.com/estree/estree/blob/master/es5.md#identifier), and
205
+ * [MetaProperties](https://github.com/estree/estree/blob/master/es2015.md#metaproperty) which is
206
+ * specifically for handling the `new.target` meta property.
207
+ * @param {Expression | SpreadElement | Super} expression expression
208
+ * @returns {string | "this" | undefined} name or variable info
209
+ */
119
210
  const getRootName = expression => {
120
211
  switch (expression.type) {
121
212
  case "Identifier":
@@ -155,73 +246,81 @@ class JavascriptParser extends Parser {
155
246
  constructor(sourceType = "auto") {
156
247
  super();
157
248
  this.hooks = Object.freeze({
158
- /** @type {HookMap<SyncBailHook<[UnaryExpressionNode], BasicEvaluatedExpression | undefined | null>>} */
249
+ /** @type {HookMap<SyncBailHook<[UnaryExpression], BasicEvaluatedExpression | undefined | null>>} */
159
250
  evaluateTypeof: new HookMap(() => new SyncBailHook(["expression"])),
160
- /** @type {HookMap<SyncBailHook<[ExpressionNode], BasicEvaluatedExpression | undefined | null>>} */
251
+ /** @type {HookMap<SyncBailHook<[Expression | SpreadElement], BasicEvaluatedExpression | undefined | null>>} */
161
252
  evaluate: new HookMap(() => new SyncBailHook(["expression"])),
162
- /** @type {HookMap<SyncBailHook<[IdentifierNode | ThisExpressionNode | MemberExpressionNode | MetaPropertyNode], BasicEvaluatedExpression | undefined | null>>} */
253
+ /** @type {HookMap<SyncBailHook<[Identifier | ThisExpression | MemberExpression | MetaProperty], BasicEvaluatedExpression | undefined | null>>} */
163
254
  evaluateIdentifier: new HookMap(() => new SyncBailHook(["expression"])),
164
- /** @type {HookMap<SyncBailHook<[IdentifierNode | ThisExpressionNode | MemberExpressionNode], BasicEvaluatedExpression | undefined | null>>} */
255
+ /** @type {HookMap<SyncBailHook<[Identifier | ThisExpression | MemberExpression], BasicEvaluatedExpression | undefined | null>>} */
165
256
  evaluateDefinedIdentifier: new HookMap(
166
257
  () => new SyncBailHook(["expression"])
167
258
  ),
168
- /** @type {HookMap<SyncBailHook<[CallExpressionNode, BasicEvaluatedExpression | undefined], BasicEvaluatedExpression | undefined | null>>} */
259
+ /** @type {HookMap<SyncBailHook<[NewExpression], BasicEvaluatedExpression | undefined | null>>} */
260
+ evaluateNewExpression: new HookMap(
261
+ () => new SyncBailHook(["expression"])
262
+ ),
263
+ /** @type {HookMap<SyncBailHook<[CallExpression], BasicEvaluatedExpression | undefined | null>>} */
264
+ evaluateCallExpression: new HookMap(
265
+ () => new SyncBailHook(["expression"])
266
+ ),
267
+ /** @type {HookMap<SyncBailHook<[CallExpression, BasicEvaluatedExpression], BasicEvaluatedExpression | undefined | null>>} */
169
268
  evaluateCallExpressionMember: new HookMap(
170
269
  () => new SyncBailHook(["expression", "param"])
171
270
  ),
172
- /** @type {HookMap<SyncBailHook<[ExpressionNode | DeclarationNode | PrivateIdentifierNode, number], boolean | void>>} */
271
+ /** @type {HookMap<SyncBailHook<[Expression | Declaration | PrivateIdentifier, number], boolean | void>>} */
173
272
  isPure: new HookMap(
174
273
  () => new SyncBailHook(["expression", "commentsStartPosition"])
175
274
  ),
176
- /** @type {SyncBailHook<[StatementNode | ModuleDeclarationNode], boolean | void>} */
275
+ /** @type {SyncBailHook<[Statement | ModuleDeclaration], boolean | void>} */
177
276
  preStatement: new SyncBailHook(["statement"]),
178
277
 
179
- /** @type {SyncBailHook<[StatementNode | ModuleDeclarationNode], boolean | void>} */
278
+ /** @type {SyncBailHook<[Statement | ModuleDeclaration], boolean | void>} */
180
279
  blockPreStatement: new SyncBailHook(["declaration"]),
181
- /** @type {SyncBailHook<[StatementNode | ModuleDeclarationNode], boolean | void>} */
280
+ /** @type {SyncBailHook<[Statement | ModuleDeclaration], boolean | void>} */
182
281
  statement: new SyncBailHook(["statement"]),
183
- /** @type {SyncBailHook<[IfStatementNode], boolean | void>} */
282
+ /** @type {SyncBailHook<[IfStatement], boolean | void>} */
184
283
  statementIf: new SyncBailHook(["statement"]),
185
- /** @type {SyncBailHook<[ExpressionNode, ClassExpressionNode | ClassDeclarationNode], boolean | void>} */
284
+ /** @type {SyncBailHook<[Expression, ClassExpression | ClassDeclaration], boolean | void>} */
186
285
  classExtendsExpression: new SyncBailHook([
187
286
  "expression",
188
287
  "classDefinition"
189
288
  ]),
190
- /** @type {SyncBailHook<[MethodDefinitionNode | PropertyDefinitionNode, ClassExpressionNode | ClassDeclarationNode], boolean | void>} */
289
+ /** @type {SyncBailHook<[MethodDefinition | PropertyDefinition | StaticBlock, ClassExpression | ClassDeclaration], boolean | void>} */
191
290
  classBodyElement: new SyncBailHook(["element", "classDefinition"]),
192
- /** @type {SyncBailHook<[ExpressionNode, MethodDefinitionNode | PropertyDefinitionNode, ClassExpressionNode | ClassDeclarationNode], boolean | void>} */
291
+ /** @type {SyncBailHook<[Expression, MethodDefinition | PropertyDefinition, ClassExpression | ClassDeclaration], boolean | void>} */
193
292
  classBodyValue: new SyncBailHook([
194
293
  "expression",
195
294
  "element",
196
295
  "classDefinition"
197
296
  ]),
198
- /** @type {HookMap<SyncBailHook<[LabeledStatementNode], boolean | void>>} */
297
+ /** @type {HookMap<SyncBailHook<[LabeledStatement], boolean | void>>} */
199
298
  label: new HookMap(() => new SyncBailHook(["statement"])),
200
- /** @type {SyncBailHook<[ImportDeclarationNode, ImportSource], boolean | void>} */
299
+ /** @type {SyncBailHook<[ImportDeclaration, ImportSource], boolean | void>} */
201
300
  import: new SyncBailHook(["statement", "source"]),
202
- /** @type {SyncBailHook<[ImportDeclarationNode, ImportSource, string, string], boolean | void>} */
301
+ /** @type {SyncBailHook<[ImportDeclaration, ImportSource, string, string], boolean | void>} */
203
302
  importSpecifier: new SyncBailHook([
204
303
  "statement",
205
304
  "source",
206
305
  "exportName",
207
306
  "identifierName"
208
307
  ]),
209
- /** @type {SyncBailHook<[ExportNamedDeclarationNode | ExportAllDeclarationNode], boolean | void>} */
308
+ /** @type {SyncBailHook<[ExportDefaultDeclaration | ExportNamedDeclaration], boolean | void>} */
210
309
  export: new SyncBailHook(["statement"]),
211
- /** @type {SyncBailHook<[ExportNamedDeclarationNode | ExportAllDeclarationNode, ImportSource], boolean | void>} */
310
+ /** @type {SyncBailHook<[ExportNamedDeclaration | ExportAllDeclaration, ImportSource], boolean | void>} */
212
311
  exportImport: new SyncBailHook(["statement", "source"]),
213
- /** @type {SyncBailHook<[ExportNamedDeclarationNode | ExportAllDeclarationNode, DeclarationNode], boolean | void>} */
312
+ /** @type {SyncBailHook<[ExportDefaultDeclaration | ExportNamedDeclaration | ExportAllDeclaration, Declaration], boolean | void>} */
214
313
  exportDeclaration: new SyncBailHook(["statement", "declaration"]),
215
- /** @type {SyncBailHook<[ExportDefaultDeclarationNode, DeclarationNode], boolean | void>} */
314
+ /** @type {SyncBailHook<[ExportDefaultDeclaration, FunctionDeclaration | ClassDeclaration], boolean | void>} */
216
315
  exportExpression: new SyncBailHook(["statement", "declaration"]),
217
- /** @type {SyncBailHook<[ExportNamedDeclarationNode | ExportAllDeclarationNode, string, string, number | undefined], boolean | void>} */
316
+ /** @type {SyncBailHook<[ExportDefaultDeclaration | ExportNamedDeclaration | ExportAllDeclaration, string, string, number | undefined], boolean | void>} */
218
317
  exportSpecifier: new SyncBailHook([
219
318
  "statement",
220
319
  "identifierName",
221
320
  "exportName",
222
321
  "index"
223
322
  ]),
224
- /** @type {SyncBailHook<[ExportNamedDeclarationNode | ExportAllDeclarationNode, ImportSource, string, string, number | undefined], boolean | void>} */
323
+ /** @type {SyncBailHook<[ExportNamedDeclaration | ExportAllDeclaration, ImportSource, string, string, number | undefined], boolean | void>} */
225
324
  exportImportSpecifier: new SyncBailHook([
226
325
  "statement",
227
326
  "source",
@@ -229,86 +328,102 @@ class JavascriptParser extends Parser {
229
328
  "exportName",
230
329
  "index"
231
330
  ]),
232
- /** @type {SyncBailHook<[VariableDeclaratorNode, StatementNode], boolean | void>} */
331
+ /** @type {SyncBailHook<[VariableDeclarator, Statement], boolean | void>} */
233
332
  preDeclarator: new SyncBailHook(["declarator", "statement"]),
234
- /** @type {SyncBailHook<[VariableDeclaratorNode, StatementNode], boolean | void>} */
333
+ /** @type {SyncBailHook<[VariableDeclarator, Statement], boolean | void>} */
235
334
  declarator: new SyncBailHook(["declarator", "statement"]),
236
- /** @type {HookMap<SyncBailHook<[DeclarationNode], boolean | void>>} */
335
+ /** @type {HookMap<SyncBailHook<[Declaration], boolean | void>>} */
237
336
  varDeclaration: new HookMap(() => new SyncBailHook(["declaration"])),
238
- /** @type {HookMap<SyncBailHook<[DeclarationNode], boolean | void>>} */
337
+ /** @type {HookMap<SyncBailHook<[Declaration], boolean | void>>} */
239
338
  varDeclarationLet: new HookMap(() => new SyncBailHook(["declaration"])),
240
- /** @type {HookMap<SyncBailHook<[DeclarationNode], boolean | void>>} */
339
+ /** @type {HookMap<SyncBailHook<[Declaration], boolean | void>>} */
241
340
  varDeclarationConst: new HookMap(() => new SyncBailHook(["declaration"])),
242
- /** @type {HookMap<SyncBailHook<[DeclarationNode], boolean | void>>} */
341
+ /** @type {HookMap<SyncBailHook<[Declaration], boolean | void>>} */
243
342
  varDeclarationVar: new HookMap(() => new SyncBailHook(["declaration"])),
244
- /** @type {HookMap<SyncBailHook<[IdentifierNode], boolean | void>>} */
343
+ /** @type {HookMap<SyncBailHook<[Identifier], boolean | void>>} */
245
344
  pattern: new HookMap(() => new SyncBailHook(["pattern"])),
246
- /** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
345
+ /** @type {HookMap<SyncBailHook<[Expression], boolean | void>>} */
247
346
  canRename: new HookMap(() => new SyncBailHook(["initExpression"])),
248
- /** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
347
+ /** @type {HookMap<SyncBailHook<[Expression], boolean | void>>} */
249
348
  rename: new HookMap(() => new SyncBailHook(["initExpression"])),
250
- /** @type {HookMap<SyncBailHook<[import("estree").AssignmentExpression], boolean | void>>} */
349
+ /** @type {HookMap<SyncBailHook<[AssignmentExpression], boolean | void>>} */
251
350
  assign: new HookMap(() => new SyncBailHook(["expression"])),
252
- /** @type {HookMap<SyncBailHook<[import("estree").AssignmentExpression, string[]], boolean | void>>} */
351
+ /** @type {HookMap<SyncBailHook<[AssignmentExpression, string[]], boolean | void>>} */
253
352
  assignMemberChain: new HookMap(
254
353
  () => new SyncBailHook(["expression", "members"])
255
354
  ),
256
- /** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
355
+ /** @type {HookMap<SyncBailHook<[Expression], boolean | void>>} */
257
356
  typeof: new HookMap(() => new SyncBailHook(["expression"])),
258
- /** @type {SyncBailHook<[ExpressionNode], boolean | void>} */
357
+ /** @type {SyncBailHook<[ImportExpression], boolean | void>} */
259
358
  importCall: new SyncBailHook(["expression"]),
260
- /** @type {SyncBailHook<[ExpressionNode], boolean | void>} */
359
+ /** @type {SyncBailHook<[Expression | ForOfStatement], boolean | void>} */
261
360
  topLevelAwait: new SyncBailHook(["expression"]),
262
- /** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
361
+ /** @type {HookMap<SyncBailHook<[CallExpression], boolean | void>>} */
263
362
  call: new HookMap(() => new SyncBailHook(["expression"])),
264
363
  /** Something like "a.b()" */
265
- /** @type {HookMap<SyncBailHook<[CallExpressionNode, string[]], boolean | void>>} */
364
+ /** @type {HookMap<SyncBailHook<[CallExpression, string[], boolean[], Range[]], boolean | void>>} */
266
365
  callMemberChain: new HookMap(
267
- () => new SyncBailHook(["expression", "members"])
366
+ () =>
367
+ new SyncBailHook([
368
+ "expression",
369
+ "members",
370
+ "membersOptionals",
371
+ "memberRanges"
372
+ ])
268
373
  ),
269
374
  /** Something like "a.b().c.d" */
270
- /** @type {HookMap<SyncBailHook<[ExpressionNode, string[], CallExpressionNode, string[]], boolean | void>>} */
375
+ /** @type {HookMap<SyncBailHook<[Expression, string[], CallExpression, string[], Range[]], boolean | void>>} */
271
376
  memberChainOfCallMemberChain: new HookMap(
272
377
  () =>
273
378
  new SyncBailHook([
274
379
  "expression",
275
380
  "calleeMembers",
276
381
  "callExpression",
277
- "members"
382
+ "members",
383
+ "memberRanges"
278
384
  ])
279
385
  ),
280
386
  /** Something like "a.b().c.d()"" */
281
- /** @type {HookMap<SyncBailHook<[ExpressionNode, string[], CallExpressionNode, string[]], boolean | void>>} */
387
+ /** @type {HookMap<SyncBailHook<[CallExpression, string[], CallExpression, string[], Range[]], boolean | void>>} */
282
388
  callMemberChainOfCallMemberChain: new HookMap(
283
389
  () =>
284
390
  new SyncBailHook([
285
391
  "expression",
286
392
  "calleeMembers",
287
393
  "innerCallExpression",
288
- "members"
394
+ "members",
395
+ "memberRanges"
289
396
  ])
290
397
  ),
291
- /** @type {SyncBailHook<[ChainExpressionNode], boolean | void>} */
398
+ /** @type {SyncBailHook<[ChainExpression], boolean | void>} */
292
399
  optionalChaining: new SyncBailHook(["optionalChaining"]),
293
- /** @type {HookMap<SyncBailHook<[NewExpressionNode], boolean | void>>} */
400
+ /** @type {HookMap<SyncBailHook<[NewExpression], boolean | void>>} */
294
401
  new: new HookMap(() => new SyncBailHook(["expression"])),
295
- /** @type {HookMap<SyncBailHook<[ExpressionNode], boolean | void>>} */
402
+ /** @type {SyncBailHook<[BinaryExpression], boolean | void>} */
403
+ binaryExpression: new SyncBailHook(["binaryExpression"]),
404
+ /** @type {HookMap<SyncBailHook<[Expression], boolean | void>>} */
296
405
  expression: new HookMap(() => new SyncBailHook(["expression"])),
297
- /** @type {HookMap<SyncBailHook<[ExpressionNode, string[]], boolean | void>>} */
406
+ /** @type {HookMap<SyncBailHook<[MemberExpression, string[], boolean[], Range[]], boolean | void>>} */
298
407
  expressionMemberChain: new HookMap(
299
- () => new SyncBailHook(["expression", "members"])
408
+ () =>
409
+ new SyncBailHook([
410
+ "expression",
411
+ "members",
412
+ "membersOptionals",
413
+ "memberRanges"
414
+ ])
300
415
  ),
301
- /** @type {HookMap<SyncBailHook<[ExpressionNode, string[]], boolean | void>>} */
416
+ /** @type {HookMap<SyncBailHook<[MemberExpression, string[]], boolean | void>>} */
302
417
  unhandledExpressionMemberChain: new HookMap(
303
418
  () => new SyncBailHook(["expression", "members"])
304
419
  ),
305
- /** @type {SyncBailHook<[ExpressionNode], boolean | void>} */
420
+ /** @type {SyncBailHook<[ConditionalExpression], boolean | void>} */
306
421
  expressionConditionalOperator: new SyncBailHook(["expression"]),
307
- /** @type {SyncBailHook<[ExpressionNode], boolean | void>} */
422
+ /** @type {SyncBailHook<[LogicalExpression], boolean | void>} */
308
423
  expressionLogicalOperator: new SyncBailHook(["expression"]),
309
- /** @type {SyncBailHook<[ProgramNode, CommentNode[]], boolean | void>} */
424
+ /** @type {SyncBailHook<[Program, Comment[]], boolean | void>} */
310
425
  program: new SyncBailHook(["ast", "comments"]),
311
- /** @type {SyncBailHook<[ProgramNode, CommentNode[]], boolean | void>} */
426
+ /** @type {SyncBailHook<[Program, Comment[]], boolean | void>} */
312
427
  finish: new SyncBailHook(["ast", "comments"])
313
428
  });
314
429
  this.sourceType = sourceType;
@@ -316,58 +431,74 @@ class JavascriptParser extends Parser {
316
431
  this.scope = undefined;
317
432
  /** @type {ParserState} */
318
433
  this.state = undefined;
434
+ /** @type {Comment[] | undefined} */
319
435
  this.comments = undefined;
436
+ /** @type {Set<number> | undefined} */
320
437
  this.semicolons = undefined;
321
- /** @type {(StatementNode|ExpressionNode)[]} */
438
+ /** @type {StatementPathItem[]} */
322
439
  this.statementPath = undefined;
440
+ /** @type {Statement | ModuleDeclaration | Expression | undefined} */
323
441
  this.prevStatement = undefined;
442
+ /** @type {WeakMap<Expression, Set<DestructuringAssignmentProperty>> | undefined} */
443
+ this.destructuringAssignmentProperties = undefined;
324
444
  this.currentTagData = undefined;
445
+ this.magicCommentContext = vm.createContext(undefined, {
446
+ name: "Webpack Magic Comment Parser",
447
+ codeGeneration: { strings: false, wasm: false }
448
+ });
325
449
  this._initializeEvaluating();
326
450
  }
327
451
 
328
452
  _initializeEvaluating() {
329
453
  this.hooks.evaluate.for("Literal").tap("JavascriptParser", _expr => {
330
- const expr = /** @type {LiteralNode} */ (_expr);
454
+ const expr = /** @type {Literal} */ (_expr);
331
455
 
332
456
  switch (typeof expr.value) {
333
457
  case "number":
334
458
  return new BasicEvaluatedExpression()
335
459
  .setNumber(expr.value)
336
- .setRange(expr.range);
460
+ .setRange(/** @type {Range} */ (expr.range));
337
461
  case "bigint":
338
462
  return new BasicEvaluatedExpression()
339
463
  .setBigInt(expr.value)
340
- .setRange(expr.range);
464
+ .setRange(/** @type {Range} */ (expr.range));
341
465
  case "string":
342
466
  return new BasicEvaluatedExpression()
343
467
  .setString(expr.value)
344
- .setRange(expr.range);
468
+ .setRange(/** @type {Range} */ (expr.range));
345
469
  case "boolean":
346
470
  return new BasicEvaluatedExpression()
347
471
  .setBoolean(expr.value)
348
- .setRange(expr.range);
472
+ .setRange(/** @type {Range} */ (expr.range));
349
473
  }
350
474
  if (expr.value === null) {
351
- return new BasicEvaluatedExpression().setNull().setRange(expr.range);
475
+ return new BasicEvaluatedExpression()
476
+ .setNull()
477
+ .setRange(/** @type {Range} */ (expr.range));
352
478
  }
353
479
  if (expr.value instanceof RegExp) {
354
480
  return new BasicEvaluatedExpression()
355
481
  .setRegExp(expr.value)
356
- .setRange(expr.range);
482
+ .setRange(/** @type {Range} */ (expr.range));
357
483
  }
358
484
  });
359
485
  this.hooks.evaluate.for("NewExpression").tap("JavascriptParser", _expr => {
360
- const expr = /** @type {NewExpressionNode} */ (_expr);
486
+ const expr = /** @type {NewExpression} */ (_expr);
361
487
  const callee = expr.callee;
362
- if (
363
- callee.type !== "Identifier" ||
364
- callee.name !== "RegExp" ||
488
+ if (callee.type !== "Identifier") return;
489
+ if (callee.name !== "RegExp") {
490
+ return this.callHooksForName(
491
+ this.hooks.evaluateNewExpression,
492
+ callee.name,
493
+ expr
494
+ );
495
+ } else if (
365
496
  expr.arguments.length > 2 ||
366
497
  this.getVariableInfo("RegExp") !== "RegExp"
367
498
  )
368
499
  return;
369
500
 
370
- let regExp, flags;
501
+ let regExp;
371
502
  const arg1 = expr.arguments[0];
372
503
 
373
504
  if (arg1) {
@@ -381,11 +512,15 @@ class JavascriptParser extends Parser {
381
512
 
382
513
  if (!regExp) return;
383
514
  } else {
384
- return new BasicEvaluatedExpression()
385
- .setRegExp(new RegExp(""))
386
- .setRange(expr.range);
515
+ return (
516
+ new BasicEvaluatedExpression()
517
+ // eslint-disable-next-line prefer-regex-literals
518
+ .setRegExp(new RegExp(""))
519
+ .setRange(/** @type {Range} */ (expr.range))
520
+ );
387
521
  }
388
522
 
523
+ let flags;
389
524
  const arg2 = expr.arguments[1];
390
525
 
391
526
  if (arg2) {
@@ -408,90 +543,142 @@ class JavascriptParser extends Parser {
408
543
 
409
544
  return new BasicEvaluatedExpression()
410
545
  .setRegExp(flags ? new RegExp(regExp, flags) : new RegExp(regExp))
411
- .setRange(expr.range);
546
+ .setRange(/** @type {Range} */ (expr.range));
412
547
  });
413
548
  this.hooks.evaluate
414
549
  .for("LogicalExpression")
415
550
  .tap("JavascriptParser", _expr => {
416
- const expr = /** @type {LogicalExpressionNode} */ (_expr);
551
+ const expr = /** @type {LogicalExpression} */ (_expr);
417
552
 
418
553
  const left = this.evaluateExpression(expr.left);
419
- if (!left) return;
420
554
  let returnRight = false;
421
555
  /** @type {boolean|undefined} */
422
556
  let allowedRight;
423
557
  if (expr.operator === "&&") {
424
558
  const leftAsBool = left.asBool();
425
- if (leftAsBool === false) return left.setRange(expr.range);
559
+ if (leftAsBool === false)
560
+ return left.setRange(/** @type {Range} */ (expr.range));
426
561
  returnRight = leftAsBool === true;
427
562
  allowedRight = false;
428
563
  } else if (expr.operator === "||") {
429
564
  const leftAsBool = left.asBool();
430
- if (leftAsBool === true) return left.setRange(expr.range);
565
+ if (leftAsBool === true)
566
+ return left.setRange(/** @type {Range} */ (expr.range));
431
567
  returnRight = leftAsBool === false;
432
568
  allowedRight = true;
433
569
  } else if (expr.operator === "??") {
434
570
  const leftAsNullish = left.asNullish();
435
- if (leftAsNullish === false) return left.setRange(expr.range);
571
+ if (leftAsNullish === false)
572
+ return left.setRange(/** @type {Range} */ (expr.range));
436
573
  if (leftAsNullish !== true) return;
437
574
  returnRight = true;
438
575
  } else return;
439
576
  const right = this.evaluateExpression(expr.right);
440
- if (!right) return;
441
577
  if (returnRight) {
442
578
  if (left.couldHaveSideEffects()) right.setSideEffects();
443
- return right.setRange(expr.range);
579
+ return right.setRange(/** @type {Range} */ (expr.range));
444
580
  }
445
581
 
446
582
  const asBool = right.asBool();
447
583
 
448
584
  if (allowedRight === true && asBool === true) {
449
585
  return new BasicEvaluatedExpression()
450
- .setRange(expr.range)
586
+ .setRange(/** @type {Range} */ (expr.range))
451
587
  .setTruthy();
452
588
  } else if (allowedRight === false && asBool === false) {
453
- return new BasicEvaluatedExpression().setRange(expr.range).setFalsy();
589
+ return new BasicEvaluatedExpression()
590
+ .setRange(/** @type {Range} */ (expr.range))
591
+ .setFalsy();
454
592
  }
455
593
  });
456
594
 
595
+ /**
596
+ * In simple logical cases, we can use valueAsExpression to assist us in evaluating the expression on
597
+ * either side of a [BinaryExpression](https://github.com/estree/estree/blob/master/es5.md#binaryexpression).
598
+ * This supports scenarios in webpack like conditionally `import()`'ing modules based on some simple evaluation:
599
+ *
600
+ * ```js
601
+ * if (1 === 3) {
602
+ * import("./moduleA"); // webpack will auto evaluate this and not import the modules
603
+ * }
604
+ * ```
605
+ *
606
+ * Additional scenarios include evaluation of strings inside of dynamic import statements:
607
+ *
608
+ * ```js
609
+ * const foo = "foo";
610
+ * const bar = "bar";
611
+ *
612
+ * import("./" + foo + bar); // webpack will auto evaluate this into import("./foobar")
613
+ * ```
614
+ * @param {boolean | number | bigint | string} value the value to convert to an expression
615
+ * @param {BinaryExpression | UnaryExpression} expr the expression being evaluated
616
+ * @param {boolean} sideEffects whether the expression has side effects
617
+ * @returns {BasicEvaluatedExpression | undefined} the evaluated expression
618
+ * @example
619
+ *
620
+ * ```js
621
+ * const binaryExpr = new BinaryExpression("+",
622
+ * { type: "Literal", value: 2 },
623
+ * { type: "Literal", value: 3 }
624
+ * );
625
+ *
626
+ * const leftValue = 2;
627
+ * const rightValue = 3;
628
+ *
629
+ * const leftExpr = valueAsExpression(leftValue, binaryExpr.left, false);
630
+ * const rightExpr = valueAsExpression(rightValue, binaryExpr.right, false);
631
+ * const result = new BasicEvaluatedExpression()
632
+ * .setNumber(leftExpr.number + rightExpr.number)
633
+ * .setRange(binaryExpr.range);
634
+ *
635
+ * console.log(result.number); // Output: 5
636
+ * ```
637
+ */
457
638
  const valueAsExpression = (value, expr, sideEffects) => {
458
639
  switch (typeof value) {
459
640
  case "boolean":
460
641
  return new BasicEvaluatedExpression()
461
642
  .setBoolean(value)
462
643
  .setSideEffects(sideEffects)
463
- .setRange(expr.range);
644
+ .setRange(/** @type {Range} */ (expr.range));
464
645
  case "number":
465
646
  return new BasicEvaluatedExpression()
466
647
  .setNumber(value)
467
648
  .setSideEffects(sideEffects)
468
- .setRange(expr.range);
649
+ .setRange(/** @type {Range} */ (expr.range));
469
650
  case "bigint":
470
651
  return new BasicEvaluatedExpression()
471
652
  .setBigInt(value)
472
653
  .setSideEffects(sideEffects)
473
- .setRange(expr.range);
654
+ .setRange(/** @type {Range} */ (expr.range));
474
655
  case "string":
475
656
  return new BasicEvaluatedExpression()
476
657
  .setString(value)
477
658
  .setSideEffects(sideEffects)
478
- .setRange(expr.range);
659
+ .setRange(/** @type {Range} */ (expr.range));
479
660
  }
480
661
  };
481
662
 
482
663
  this.hooks.evaluate
483
664
  .for("BinaryExpression")
484
665
  .tap("JavascriptParser", _expr => {
485
- const expr = /** @type {BinaryExpressionNode} */ (_expr);
486
-
487
- const handleConstOperation = fn => {
666
+ const expr = /** @type {BinaryExpression} */ (_expr);
667
+
668
+ /**
669
+ * Evaluates a binary expression if and only if it is a const operation (e.g. 1 + 2, "a" + "b", etc.).
670
+ * @template T
671
+ * @param {(leftOperand: T, rightOperand: T) => boolean | number | bigint | string} operandHandler the handler for the operation (e.g. (a, b) => a + b)
672
+ * @returns {BasicEvaluatedExpression | undefined} the evaluated expression
673
+ */
674
+ const handleConstOperation = operandHandler => {
488
675
  const left = this.evaluateExpression(expr.left);
489
- if (!left || !left.isCompileTimeValue()) return;
676
+ if (!left.isCompileTimeValue()) return;
490
677
 
491
678
  const right = this.evaluateExpression(expr.right);
492
- if (!right || !right.isCompileTimeValue()) return;
679
+ if (!right.isCompileTimeValue()) return;
493
680
 
494
- const result = fn(
681
+ const result = operandHandler(
495
682
  left.asCompileTimeValue(),
496
683
  right.asCompileTimeValue()
497
684
  );
@@ -502,10 +689,28 @@ class JavascriptParser extends Parser {
502
689
  );
503
690
  };
504
691
 
692
+ /**
693
+ * Helper function to determine if two booleans are always different. This is used in `handleStrictEqualityComparison`
694
+ * to determine if an expressions boolean or nullish conversion is equal or not.
695
+ * @param {boolean} a first boolean to compare
696
+ * @param {boolean} b second boolean to compare
697
+ * @returns {boolean} true if the two booleans are always different, false otherwise
698
+ */
505
699
  const isAlwaysDifferent = (a, b) =>
506
700
  (a === true && b === false) || (a === false && b === true);
507
701
 
702
+ /**
703
+ * @param {BasicEvaluatedExpression} left left
704
+ * @param {BasicEvaluatedExpression} right right
705
+ * @param {BasicEvaluatedExpression} res res
706
+ * @param {boolean} eql true for "===" and false for "!=="
707
+ * @returns {BasicEvaluatedExpression | undefined} result
708
+ */
508
709
  const handleTemplateStringCompare = (left, right, res, eql) => {
710
+ /**
711
+ * @param {BasicEvaluatedExpression[]} parts parts
712
+ * @returns {string} value
713
+ */
509
714
  const getPrefix = parts => {
510
715
  let value = "";
511
716
  for (const p of parts) {
@@ -515,6 +720,10 @@ class JavascriptParser extends Parser {
515
720
  }
516
721
  return value;
517
722
  };
723
+ /**
724
+ * @param {BasicEvaluatedExpression[]} parts parts
725
+ * @returns {string} value
726
+ */
518
727
  const getSuffix = parts => {
519
728
  let value = "";
520
729
  for (let i = parts.length - 1; i >= 0; i--) {
@@ -524,17 +733,27 @@ class JavascriptParser extends Parser {
524
733
  }
525
734
  return value;
526
735
  };
527
- const leftPrefix = getPrefix(left.parts);
528
- const rightPrefix = getPrefix(right.parts);
529
- const leftSuffix = getSuffix(left.parts);
530
- const rightSuffix = getSuffix(right.parts);
736
+ const leftPrefix = getPrefix(
737
+ /** @type {BasicEvaluatedExpression[]} */ (left.parts)
738
+ );
739
+ const rightPrefix = getPrefix(
740
+ /** @type {BasicEvaluatedExpression[]} */ (right.parts)
741
+ );
742
+ const leftSuffix = getSuffix(
743
+ /** @type {BasicEvaluatedExpression[]} */ (left.parts)
744
+ );
745
+ const rightSuffix = getSuffix(
746
+ /** @type {BasicEvaluatedExpression[]} */ (right.parts)
747
+ );
531
748
  const lenPrefix = Math.min(leftPrefix.length, rightPrefix.length);
532
749
  const lenSuffix = Math.min(leftSuffix.length, rightSuffix.length);
533
- if (
534
- leftPrefix.slice(0, lenPrefix) !==
535
- rightPrefix.slice(0, lenPrefix) ||
536
- leftSuffix.slice(-lenSuffix) !== rightSuffix.slice(-lenSuffix)
537
- ) {
750
+ const prefixMismatch =
751
+ lenPrefix > 0 &&
752
+ leftPrefix.slice(0, lenPrefix) !== rightPrefix.slice(0, lenPrefix);
753
+ const suffixMismatch =
754
+ lenSuffix > 0 &&
755
+ leftSuffix.slice(-lenSuffix) !== rightSuffix.slice(-lenSuffix);
756
+ if (prefixMismatch || suffixMismatch) {
538
757
  return res
539
758
  .setBoolean(!eql)
540
759
  .setSideEffects(
@@ -543,13 +762,16 @@ class JavascriptParser extends Parser {
543
762
  }
544
763
  };
545
764
 
765
+ /**
766
+ * Helper function to handle BinaryExpressions using strict equality comparisons (e.g. "===" and "!==").
767
+ * @param {boolean} eql true for "===" and false for "!=="
768
+ * @returns {BasicEvaluatedExpression | undefined} the evaluated expression
769
+ */
546
770
  const handleStrictEqualityComparison = eql => {
547
771
  const left = this.evaluateExpression(expr.left);
548
- if (!left) return;
549
772
  const right = this.evaluateExpression(expr.right);
550
- if (!right) return;
551
773
  const res = new BasicEvaluatedExpression();
552
- res.setRange(expr.range);
774
+ res.setRange(/** @type {Range} */ (expr.range));
553
775
 
554
776
  const leftConst = left.isCompileTimeValue();
555
777
  const rightConst = right.isCompileTimeValue();
@@ -587,8 +809,14 @@ class JavascriptParser extends Parser {
587
809
  (rightPrimitive === false &&
588
810
  (rightConst || leftPrimitive === true)) ||
589
811
  // Different nullish or boolish status also means not equal
590
- isAlwaysDifferent(left.asBool(), right.asBool()) ||
591
- isAlwaysDifferent(left.asNullish(), right.asNullish())
812
+ isAlwaysDifferent(
813
+ /** @type {boolean} */ (left.asBool()),
814
+ /** @type {boolean} */ (right.asBool())
815
+ ) ||
816
+ isAlwaysDifferent(
817
+ /** @type {boolean} */ (left.asNullish()),
818
+ /** @type {boolean} */ (right.asNullish())
819
+ )
592
820
  ) {
593
821
  return res
594
822
  .setBoolean(!eql)
@@ -598,13 +826,16 @@ class JavascriptParser extends Parser {
598
826
  }
599
827
  };
600
828
 
829
+ /**
830
+ * Helper function to handle BinaryExpressions using abstract equality comparisons (e.g. "==" and "!=").
831
+ * @param {boolean} eql true for "==" and false for "!="
832
+ * @returns {BasicEvaluatedExpression | undefined} the evaluated expression
833
+ */
601
834
  const handleAbstractEqualityComparison = eql => {
602
835
  const left = this.evaluateExpression(expr.left);
603
- if (!left) return;
604
836
  const right = this.evaluateExpression(expr.right);
605
- if (!right) return;
606
837
  const res = new BasicEvaluatedExpression();
607
- res.setRange(expr.range);
838
+ res.setRange(/** @type {Range} */ (expr.range));
608
839
 
609
840
  const leftConst = left.isCompileTimeValue();
610
841
  const rightConst = right.isCompileTimeValue();
@@ -635,15 +866,16 @@ class JavascriptParser extends Parser {
635
866
 
636
867
  if (expr.operator === "+") {
637
868
  const left = this.evaluateExpression(expr.left);
638
- if (!left) return;
639
869
  const right = this.evaluateExpression(expr.right);
640
- if (!right) return;
641
870
  const res = new BasicEvaluatedExpression();
642
871
  if (left.isString()) {
643
872
  if (right.isString()) {
644
- res.setString(left.string + right.string);
873
+ res.setString(
874
+ /** @type {string} */ (left.string) +
875
+ /** @type {string} */ (right.string)
876
+ );
645
877
  } else if (right.isNumber()) {
646
- res.setString(left.string + right.number);
878
+ res.setString(/** @type {string} */ (left.string) + right.number);
647
879
  } else if (
648
880
  right.isWrapped() &&
649
881
  right.prefix &&
@@ -653,8 +885,16 @@ class JavascriptParser extends Parser {
653
885
  // => ("leftPrefix" + inner + "postfix")
654
886
  res.setWrapped(
655
887
  new BasicEvaluatedExpression()
656
- .setString(left.string + right.prefix.string)
657
- .setRange(joinRanges(left.range, right.prefix.range)),
888
+ .setString(
889
+ /** @type {string} */ (left.string) +
890
+ /** @type {string} */ (right.prefix.string)
891
+ )
892
+ .setRange(
893
+ joinRanges(
894
+ /** @type {Range} */ (left.range),
895
+ /** @type {Range} */ (right.prefix.range)
896
+ )
897
+ ),
658
898
  right.postfix,
659
899
  right.wrappedInnerExpressions
660
900
  );
@@ -673,15 +913,21 @@ class JavascriptParser extends Parser {
673
913
  }
674
914
  } else if (left.isNumber()) {
675
915
  if (right.isString()) {
676
- res.setString(left.number + right.string);
916
+ res.setString(left.number + /** @type {string} */ (right.string));
677
917
  } else if (right.isNumber()) {
678
- res.setNumber(left.number + right.number);
918
+ res.setNumber(
919
+ /** @type {number} */ (left.number) +
920
+ /** @type {number} */ (right.number)
921
+ );
679
922
  } else {
680
923
  return;
681
924
  }
682
925
  } else if (left.isBigInt()) {
683
926
  if (right.isBigInt()) {
684
- res.setBigInt(left.bigint + right.bigint);
927
+ res.setBigInt(
928
+ /** @type {bigint} */ (left.bigint) +
929
+ /** @type {bigint} */ (right.bigint)
930
+ );
685
931
  }
686
932
  } else if (left.isWrapped()) {
687
933
  if (left.postfix && left.postfix.isString() && right.isString()) {
@@ -690,8 +936,16 @@ class JavascriptParser extends Parser {
690
936
  res.setWrapped(
691
937
  left.prefix,
692
938
  new BasicEvaluatedExpression()
693
- .setString(left.postfix.string + right.string)
694
- .setRange(joinRanges(left.postfix.range, right.range)),
939
+ .setString(
940
+ /** @type {string} */ (left.postfix.string) +
941
+ /** @type {string} */ (right.string)
942
+ )
943
+ .setRange(
944
+ joinRanges(
945
+ /** @type {Range} */ (left.postfix.range),
946
+ /** @type {Range} */ (right.range)
947
+ )
948
+ ),
695
949
  left.wrappedInnerExpressions
696
950
  );
697
951
  } else if (
@@ -704,8 +958,16 @@ class JavascriptParser extends Parser {
704
958
  res.setWrapped(
705
959
  left.prefix,
706
960
  new BasicEvaluatedExpression()
707
- .setString(left.postfix.string + right.number)
708
- .setRange(joinRanges(left.postfix.range, right.range)),
961
+ .setString(
962
+ /** @type {string} */ (left.postfix.string) +
963
+ /** @type {number} */ (right.number)
964
+ )
965
+ .setRange(
966
+ joinRanges(
967
+ /** @type {Range} */ (left.postfix.range),
968
+ /** @type {Range} */ (right.range)
969
+ )
970
+ ),
709
971
  left.wrappedInnerExpressions
710
972
  );
711
973
  } else if (right.isString()) {
@@ -718,8 +980,8 @@ class JavascriptParser extends Parser {
718
980
  res.setWrapped(
719
981
  left.prefix,
720
982
  new BasicEvaluatedExpression()
721
- .setString(right.number + "")
722
- .setRange(right.range),
983
+ .setString(String(right.number))
984
+ .setRange(/** @type {Range} */ (right.range)),
723
985
  left.wrappedInnerExpressions
724
986
  );
725
987
  } else if (right.isWrapped()) {
@@ -747,29 +1009,27 @@ class JavascriptParser extends Parser {
747
1009
  )
748
1010
  );
749
1011
  }
1012
+ } else if (right.isString()) {
1013
+ // left + "right"
1014
+ // => ([null] + left + "right")
1015
+ res.setWrapped(null, right, [left]);
1016
+ } else if (right.isWrapped()) {
1017
+ // left + (prefix + inner + "postfix")
1018
+ // => ([null] + left + prefix + inner + "postfix")
1019
+ res.setWrapped(
1020
+ null,
1021
+ right.postfix,
1022
+ right.wrappedInnerExpressions &&
1023
+ (right.prefix ? [left, right.prefix] : [left]).concat(
1024
+ right.wrappedInnerExpressions
1025
+ )
1026
+ );
750
1027
  } else {
751
- if (right.isString()) {
752
- // left + "right"
753
- // => ([null] + left + "right")
754
- res.setWrapped(null, right, [left]);
755
- } else if (right.isWrapped()) {
756
- // left + (prefix + inner + "postfix")
757
- // => ([null] + left + prefix + inner + "postfix")
758
- res.setWrapped(
759
- null,
760
- right.postfix,
761
- right.wrappedInnerExpressions &&
762
- (right.prefix ? [left, right.prefix] : [left]).concat(
763
- right.wrappedInnerExpressions
764
- )
765
- );
766
- } else {
767
- return;
768
- }
1028
+ return;
769
1029
  }
770
1030
  if (left.couldHaveSideEffects() || right.couldHaveSideEffects())
771
1031
  res.setSideEffects();
772
- res.setRange(expr.range);
1032
+ res.setRange(/** @type {Range} */ (expr.range));
773
1033
  return res;
774
1034
  } else if (expr.operator === "-") {
775
1035
  return handleConstOperation((l, r) => l - r);
@@ -812,12 +1072,18 @@ class JavascriptParser extends Parser {
812
1072
  this.hooks.evaluate
813
1073
  .for("UnaryExpression")
814
1074
  .tap("JavascriptParser", _expr => {
815
- const expr = /** @type {UnaryExpressionNode} */ (_expr);
816
-
817
- const handleConstOperation = fn => {
1075
+ const expr = /** @type {UnaryExpression} */ (_expr);
1076
+
1077
+ /**
1078
+ * Evaluates a UnaryExpression if and only if it is a basic const operator (e.g. +a, -a, ~a).
1079
+ * @template T
1080
+ * @param {(operand: T) => boolean | number | bigint | string} operandHandler handler for the operand
1081
+ * @returns {BasicEvaluatedExpression | undefined} evaluated expression
1082
+ */
1083
+ const handleConstOperation = operandHandler => {
818
1084
  const argument = this.evaluateExpression(expr.argument);
819
- if (!argument || !argument.isCompileTimeValue()) return;
820
- const result = fn(argument.asCompileTimeValue());
1085
+ if (!argument.isCompileTimeValue()) return;
1086
+ const result = operandHandler(argument.asCompileTimeValue());
821
1087
  return valueAsExpression(
822
1088
  result,
823
1089
  expr,
@@ -866,7 +1132,7 @@ class JavascriptParser extends Parser {
866
1132
  case "FunctionExpression": {
867
1133
  return new BasicEvaluatedExpression()
868
1134
  .setString("function")
869
- .setRange(expr.range);
1135
+ .setRange(/** @type {Range} */ (expr.range));
870
1136
  }
871
1137
  }
872
1138
  const arg = this.evaluateExpression(expr.argument);
@@ -874,79 +1140,88 @@ class JavascriptParser extends Parser {
874
1140
  if (arg.isString()) {
875
1141
  return new BasicEvaluatedExpression()
876
1142
  .setString("string")
877
- .setRange(expr.range);
1143
+ .setRange(/** @type {Range} */ (expr.range));
878
1144
  }
879
1145
  if (arg.isWrapped()) {
880
1146
  return new BasicEvaluatedExpression()
881
1147
  .setString("string")
882
1148
  .setSideEffects()
883
- .setRange(expr.range);
1149
+ .setRange(/** @type {Range} */ (expr.range));
884
1150
  }
885
1151
  if (arg.isUndefined()) {
886
1152
  return new BasicEvaluatedExpression()
887
1153
  .setString("undefined")
888
- .setRange(expr.range);
1154
+ .setRange(/** @type {Range} */ (expr.range));
889
1155
  }
890
1156
  if (arg.isNumber()) {
891
1157
  return new BasicEvaluatedExpression()
892
1158
  .setString("number")
893
- .setRange(expr.range);
1159
+ .setRange(/** @type {Range} */ (expr.range));
894
1160
  }
895
1161
  if (arg.isBigInt()) {
896
1162
  return new BasicEvaluatedExpression()
897
1163
  .setString("bigint")
898
- .setRange(expr.range);
1164
+ .setRange(/** @type {Range} */ (expr.range));
899
1165
  }
900
1166
  if (arg.isBoolean()) {
901
1167
  return new BasicEvaluatedExpression()
902
1168
  .setString("boolean")
903
- .setRange(expr.range);
1169
+ .setRange(/** @type {Range} */ (expr.range));
904
1170
  }
905
1171
  if (arg.isConstArray() || arg.isRegExp() || arg.isNull()) {
906
1172
  return new BasicEvaluatedExpression()
907
1173
  .setString("object")
908
- .setRange(expr.range);
1174
+ .setRange(/** @type {Range} */ (expr.range));
909
1175
  }
910
1176
  if (arg.isArray()) {
911
1177
  return new BasicEvaluatedExpression()
912
1178
  .setString("object")
913
1179
  .setSideEffects(arg.couldHaveSideEffects())
914
- .setRange(expr.range);
1180
+ .setRange(/** @type {Range} */ (expr.range));
915
1181
  }
916
1182
  } else if (expr.operator === "!") {
917
1183
  const argument = this.evaluateExpression(expr.argument);
918
- if (!argument) return;
919
1184
  const bool = argument.asBool();
920
1185
  if (typeof bool !== "boolean") return;
921
1186
  return new BasicEvaluatedExpression()
922
1187
  .setBoolean(!bool)
923
1188
  .setSideEffects(argument.couldHaveSideEffects())
924
- .setRange(expr.range);
1189
+ .setRange(/** @type {Range} */ (expr.range));
925
1190
  } else if (expr.operator === "~") {
926
1191
  return handleConstOperation(v => ~v);
927
1192
  } else if (expr.operator === "+") {
1193
+ // eslint-disable-next-line no-implicit-coercion
928
1194
  return handleConstOperation(v => +v);
929
1195
  } else if (expr.operator === "-") {
930
1196
  return handleConstOperation(v => -v);
931
1197
  }
932
1198
  });
933
- this.hooks.evaluateTypeof.for("undefined").tap("JavascriptParser", expr => {
934
- return new BasicEvaluatedExpression()
935
- .setString("undefined")
936
- .setRange(expr.range);
1199
+ this.hooks.evaluateTypeof
1200
+ .for("undefined")
1201
+ .tap("JavascriptParser", expr =>
1202
+ new BasicEvaluatedExpression()
1203
+ .setString("undefined")
1204
+ .setRange(/** @type {Range} */ (expr.range))
1205
+ );
1206
+ this.hooks.evaluate.for("Identifier").tap("JavascriptParser", expr => {
1207
+ if (/** @type {Identifier} */ (expr).name === "undefined") {
1208
+ return new BasicEvaluatedExpression()
1209
+ .setUndefined()
1210
+ .setRange(/** @type {Range} */ (expr.range));
1211
+ }
937
1212
  });
938
1213
  /**
939
1214
  * @param {string} exprType expression type name
940
- * @param {function(ExpressionNode): GetInfoResult | undefined} getInfo get info
1215
+ * @param {function(Expression | SpreadElement): GetInfoResult | undefined} getInfo get info
941
1216
  * @returns {void}
942
1217
  */
943
1218
  const tapEvaluateWithVariableInfo = (exprType, getInfo) => {
944
- /** @type {ExpressionNode | undefined} */
945
- let cachedExpression = undefined;
1219
+ /** @type {Expression | undefined} */
1220
+ let cachedExpression;
946
1221
  /** @type {GetInfoResult | undefined} */
947
- let cachedInfo = undefined;
1222
+ let cachedInfo;
948
1223
  this.hooks.evaluate.for(exprType).tap("JavascriptParser", expr => {
949
- const expression = /** @type {MemberExpressionNode} */ (expr);
1224
+ const expression = /** @type {MemberExpression} */ (expr);
950
1225
 
951
1226
  const info = getInfo(expr);
952
1227
  if (info !== undefined) {
@@ -973,8 +1248,14 @@ class JavascriptParser extends Parser {
973
1248
  const info = cachedExpression === expr ? cachedInfo : getInfo(expr);
974
1249
  if (info !== undefined) {
975
1250
  return new BasicEvaluatedExpression()
976
- .setIdentifier(info.name, info.rootInfo, info.getMembers)
977
- .setRange(expr.range);
1251
+ .setIdentifier(
1252
+ info.name,
1253
+ info.rootInfo,
1254
+ info.getMembers,
1255
+ info.getMembersOptionals,
1256
+ info.getMemberRanges
1257
+ )
1258
+ .setRange(/** @type {Range} */ (expr.range));
978
1259
  }
979
1260
  });
980
1261
  this.hooks.finish.tap("JavascriptParser", () => {
@@ -983,14 +1264,18 @@ class JavascriptParser extends Parser {
983
1264
  });
984
1265
  };
985
1266
  tapEvaluateWithVariableInfo("Identifier", expr => {
986
- const info = this.getVariableInfo(
987
- /** @type {IdentifierNode} */ (expr).name
988
- );
1267
+ const info = this.getVariableInfo(/** @type {Identifier} */ (expr).name);
989
1268
  if (
990
1269
  typeof info === "string" ||
991
1270
  (info instanceof VariableInfo && typeof info.freeName === "string")
992
1271
  ) {
993
- return { name: info, rootInfo: info, getMembers: () => [] };
1272
+ return {
1273
+ name: info,
1274
+ rootInfo: info,
1275
+ getMembers: () => [],
1276
+ getMembersOptionals: () => [],
1277
+ getMemberRanges: () => []
1278
+ };
994
1279
  }
995
1280
  });
996
1281
  tapEvaluateWithVariableInfo("ThisExpression", expr => {
@@ -999,11 +1284,17 @@ class JavascriptParser extends Parser {
999
1284
  typeof info === "string" ||
1000
1285
  (info instanceof VariableInfo && typeof info.freeName === "string")
1001
1286
  ) {
1002
- return { name: info, rootInfo: info, getMembers: () => [] };
1287
+ return {
1288
+ name: info,
1289
+ rootInfo: info,
1290
+ getMembers: () => [],
1291
+ getMembersOptionals: () => [],
1292
+ getMemberRanges: () => []
1293
+ };
1003
1294
  }
1004
1295
  });
1005
1296
  this.hooks.evaluate.for("MetaProperty").tap("JavascriptParser", expr => {
1006
- const metaProperty = /** @type {MetaPropertyNode} */ (expr);
1297
+ const metaProperty = /** @type {MetaProperty} */ (expr);
1007
1298
 
1008
1299
  return this.callHooksForName(
1009
1300
  this.hooks.evaluateIdentifier,
@@ -1013,33 +1304,36 @@ class JavascriptParser extends Parser {
1013
1304
  });
1014
1305
  tapEvaluateWithVariableInfo("MemberExpression", expr =>
1015
1306
  this.getMemberExpressionInfo(
1016
- /** @type {MemberExpressionNode} */ (expr),
1307
+ /** @type {MemberExpression} */ (expr),
1017
1308
  ALLOWED_MEMBER_TYPES_EXPRESSION
1018
1309
  )
1019
1310
  );
1020
1311
 
1021
1312
  this.hooks.evaluate.for("CallExpression").tap("JavascriptParser", _expr => {
1022
- const expr = /** @type {CallExpressionNode} */ (_expr);
1313
+ const expr = /** @type {CallExpression} */ (_expr);
1023
1314
  if (
1024
- expr.callee.type !== "MemberExpression" ||
1025
- expr.callee.property.type !==
1315
+ expr.callee.type === "MemberExpression" &&
1316
+ expr.callee.property.type ===
1026
1317
  (expr.callee.computed ? "Literal" : "Identifier")
1027
1318
  ) {
1028
- return;
1029
- }
1030
-
1031
- // type Super also possible here
1032
- const param = this.evaluateExpression(
1033
- /** @type {ExpressionNode} */ (expr.callee.object)
1034
- );
1035
- if (!param) return;
1036
- const property =
1037
- expr.callee.property.type === "Literal"
1038
- ? `${expr.callee.property.value}`
1039
- : expr.callee.property.name;
1040
- const hook = this.hooks.evaluateCallExpressionMember.get(property);
1041
- if (hook !== undefined) {
1042
- return hook.call(expr, param);
1319
+ // type Super also possible here
1320
+ const param = this.evaluateExpression(
1321
+ /** @type {Expression} */ (expr.callee.object)
1322
+ );
1323
+ const property =
1324
+ expr.callee.property.type === "Literal"
1325
+ ? `${expr.callee.property.value}`
1326
+ : expr.callee.property.name;
1327
+ const hook = this.hooks.evaluateCallExpressionMember.get(property);
1328
+ if (hook !== undefined) {
1329
+ return hook.call(expr, param);
1330
+ }
1331
+ } else if (expr.callee.type === "Identifier") {
1332
+ return this.callHooksForName(
1333
+ this.hooks.evaluateCallExpression,
1334
+ expr.callee.name,
1335
+ expr
1336
+ );
1043
1337
  }
1044
1338
  });
1045
1339
  this.hooks.evaluateCallExpressionMember
@@ -1051,21 +1345,24 @@ class JavascriptParser extends Parser {
1051
1345
  if (arg1.type === "SpreadElement") return;
1052
1346
  const arg1Eval = this.evaluateExpression(arg1);
1053
1347
  if (!arg1Eval.isString()) return;
1054
- const arg1Value = arg1Eval.string;
1348
+ const arg1Value = /** @type {string} */ (arg1Eval.string);
1055
1349
 
1056
1350
  let result;
1057
1351
  if (arg2) {
1058
1352
  if (arg2.type === "SpreadElement") return;
1059
1353
  const arg2Eval = this.evaluateExpression(arg2);
1060
1354
  if (!arg2Eval.isNumber()) return;
1061
- result = param.string.indexOf(arg1Value, arg2Eval.number);
1355
+ result = /** @type {string} */ (param.string).indexOf(
1356
+ arg1Value,
1357
+ arg2Eval.number
1358
+ );
1062
1359
  } else {
1063
- result = param.string.indexOf(arg1Value);
1360
+ result = /** @type {string} */ (param.string).indexOf(arg1Value);
1064
1361
  }
1065
1362
  return new BasicEvaluatedExpression()
1066
1363
  .setNumber(result)
1067
1364
  .setSideEffects(param.couldHaveSideEffects())
1068
- .setRange(expr.range);
1365
+ .setRange(/** @type {Range} */ (expr.range));
1069
1366
  });
1070
1367
  this.hooks.evaluateCallExpressionMember
1071
1368
  .for("replace")
@@ -1074,31 +1371,37 @@ class JavascriptParser extends Parser {
1074
1371
  if (expr.arguments.length !== 2) return;
1075
1372
  if (expr.arguments[0].type === "SpreadElement") return;
1076
1373
  if (expr.arguments[1].type === "SpreadElement") return;
1077
- let arg1 = this.evaluateExpression(expr.arguments[0]);
1078
- let arg2 = this.evaluateExpression(expr.arguments[1]);
1374
+ const arg1 = this.evaluateExpression(expr.arguments[0]);
1375
+ const arg2 = this.evaluateExpression(expr.arguments[1]);
1079
1376
  if (!arg1.isString() && !arg1.isRegExp()) return;
1080
- const arg1Value = arg1.regExp || arg1.string;
1377
+ const arg1Value = /** @type {string | RegExp} */ (
1378
+ arg1.regExp || arg1.string
1379
+ );
1081
1380
  if (!arg2.isString()) return;
1082
- const arg2Value = arg2.string;
1381
+ const arg2Value = /** @type {string} */ (arg2.string);
1083
1382
  return new BasicEvaluatedExpression()
1084
- .setString(param.string.replace(arg1Value, arg2Value))
1383
+ .setString(
1384
+ /** @type {string} */ (param.string).replace(arg1Value, arg2Value)
1385
+ )
1085
1386
  .setSideEffects(param.couldHaveSideEffects())
1086
- .setRange(expr.range);
1387
+ .setRange(/** @type {Range} */ (expr.range));
1087
1388
  });
1088
- ["substr", "substring", "slice"].forEach(fn => {
1389
+ for (const fn of ["substr", "substring", "slice"]) {
1089
1390
  this.hooks.evaluateCallExpressionMember
1090
1391
  .for(fn)
1091
1392
  .tap("JavascriptParser", (expr, param) => {
1092
1393
  if (!param.isString()) return;
1093
1394
  let arg1;
1094
- let result,
1095
- str = param.string;
1395
+ let result;
1396
+ const str = /** @type {string} */ (param.string);
1096
1397
  switch (expr.arguments.length) {
1097
1398
  case 1:
1098
1399
  if (expr.arguments[0].type === "SpreadElement") return;
1099
1400
  arg1 = this.evaluateExpression(expr.arguments[0]);
1100
1401
  if (!arg1.isNumber()) return;
1101
- result = str[fn](arg1.number);
1402
+ result = str[
1403
+ /** @type {"substr" | "substring" | "slice"} */ (fn)
1404
+ ](/** @type {number} */ (arg1.number));
1102
1405
  break;
1103
1406
  case 2: {
1104
1407
  if (expr.arguments[0].type === "SpreadElement") return;
@@ -1107,7 +1410,12 @@ class JavascriptParser extends Parser {
1107
1410
  const arg2 = this.evaluateExpression(expr.arguments[1]);
1108
1411
  if (!arg1.isNumber()) return;
1109
1412
  if (!arg2.isNumber()) return;
1110
- result = str[fn](arg1.number, arg2.number);
1413
+ result = str[
1414
+ /** @type {"substr" | "substring" | "slice"} */ (fn)
1415
+ ](
1416
+ /** @type {number} */ (arg1.number),
1417
+ /** @type {number} */ (arg2.number)
1418
+ );
1111
1419
  break;
1112
1420
  }
1113
1421
  default:
@@ -1116,13 +1424,13 @@ class JavascriptParser extends Parser {
1116
1424
  return new BasicEvaluatedExpression()
1117
1425
  .setString(result)
1118
1426
  .setSideEffects(param.couldHaveSideEffects())
1119
- .setRange(expr.range);
1427
+ .setRange(/** @type {Range} */ (expr.range));
1120
1428
  });
1121
- });
1429
+ }
1122
1430
 
1123
1431
  /**
1124
1432
  * @param {"cooked" | "raw"} kind kind of values to get
1125
- * @param {TemplateLiteralNode} templateLiteralExpr TemplateLiteral expr
1433
+ * @param {TemplateLiteral} templateLiteralExpr TemplateLiteral expr
1126
1434
  * @returns {{quasis: BasicEvaluatedExpression[], parts: BasicEvaluatedExpression[]}} Simplified template
1127
1435
  */
1128
1436
  const getSimplifiedTemplateResult = (kind, templateLiteralExpr) => {
@@ -1149,7 +1457,10 @@ class JavascriptParser extends Parser {
1149
1457
  // is a const string
1150
1458
 
1151
1459
  prevExpr.setString(prevExpr.string + exprAsString + quasi);
1152
- prevExpr.setRange([prevExpr.range[0], quasiExpr.range[1]]);
1460
+ prevExpr.setRange([
1461
+ /** @type {Range} */ (prevExpr.range)[0],
1462
+ /** @type {Range} */ (quasiExpr.range)[1]
1463
+ ]);
1153
1464
  // We unset the expression as it doesn't match to a single expression
1154
1465
  prevExpr.setExpression(undefined);
1155
1466
  continue;
@@ -1158,8 +1469,8 @@ class JavascriptParser extends Parser {
1158
1469
  }
1159
1470
 
1160
1471
  const part = new BasicEvaluatedExpression()
1161
- .setString(quasi)
1162
- .setRange(quasiExpr.range)
1472
+ .setString(/** @type {string} */ (quasi))
1473
+ .setRange(/** @type {Range} */ (quasiExpr.range))
1163
1474
  .setExpression(quasiExpr);
1164
1475
  quasis.push(part);
1165
1476
  parts.push(part);
@@ -1173,37 +1484,37 @@ class JavascriptParser extends Parser {
1173
1484
  this.hooks.evaluate
1174
1485
  .for("TemplateLiteral")
1175
1486
  .tap("JavascriptParser", _node => {
1176
- const node = /** @type {TemplateLiteralNode} */ (_node);
1487
+ const node = /** @type {TemplateLiteral} */ (_node);
1177
1488
 
1178
1489
  const { quasis, parts } = getSimplifiedTemplateResult("cooked", node);
1179
1490
  if (parts.length === 1) {
1180
- return parts[0].setRange(node.range);
1491
+ return parts[0].setRange(/** @type {Range} */ (node.range));
1181
1492
  }
1182
1493
  return new BasicEvaluatedExpression()
1183
1494
  .setTemplateString(quasis, parts, "cooked")
1184
- .setRange(node.range);
1495
+ .setRange(/** @type {Range} */ (node.range));
1185
1496
  });
1186
1497
  this.hooks.evaluate
1187
1498
  .for("TaggedTemplateExpression")
1188
1499
  .tap("JavascriptParser", _node => {
1189
- const node = /** @type {TaggedTemplateExpressionNode} */ (_node);
1500
+ const node = /** @type {TaggedTemplateExpression} */ (_node);
1190
1501
  const tag = this.evaluateExpression(node.tag);
1191
1502
 
1192
- if (tag.isIdentifier() && tag.identifier !== "String.raw") return;
1193
- const { quasis, parts } = getSimplifiedTemplateResult(
1194
- "raw",
1195
- node.quasi
1196
- );
1197
- return new BasicEvaluatedExpression()
1198
- .setTemplateString(quasis, parts, "raw")
1199
- .setRange(node.range);
1503
+ if (tag.isIdentifier() && tag.identifier === "String.raw") {
1504
+ const { quasis, parts } = getSimplifiedTemplateResult(
1505
+ "raw",
1506
+ node.quasi
1507
+ );
1508
+ return new BasicEvaluatedExpression()
1509
+ .setTemplateString(quasis, parts, "raw")
1510
+ .setRange(/** @type {Range} */ (node.range));
1511
+ }
1200
1512
  });
1201
1513
 
1202
1514
  this.hooks.evaluateCallExpressionMember
1203
1515
  .for("concat")
1204
1516
  .tap("JavascriptParser", (expr, param) => {
1205
1517
  if (!param.isString() && !param.isWrapped()) return;
1206
-
1207
1518
  let stringSuffix = null;
1208
1519
  let hasUnknownParams = false;
1209
1520
  const innerExpressions = [];
@@ -1220,15 +1531,17 @@ class JavascriptParser extends Parser {
1220
1531
  continue;
1221
1532
  }
1222
1533
 
1534
+ /** @type {string} */
1223
1535
  const value = argExpr.isString()
1224
- ? argExpr.string
1225
- : "" + argExpr.number;
1536
+ ? /** @type {string} */ (argExpr.string)
1537
+ : String(/** @type {number} */ (argExpr.number));
1226
1538
 
1539
+ /** @type {string} */
1227
1540
  const newString = value + (stringSuffix ? stringSuffix.string : "");
1228
- const newRange = [
1229
- argExpr.range[0],
1230
- (stringSuffix || argExpr).range[1]
1231
- ];
1541
+ const newRange = /** @type {Range} */ ([
1542
+ /** @type {Range} */ (argExpr.range)[0],
1543
+ /** @type {Range} */ ((stringSuffix || argExpr).range)[1]
1544
+ ]);
1232
1545
  stringSuffix = new BasicEvaluatedExpression()
1233
1546
  .setString(newString)
1234
1547
  .setSideEffects(
@@ -1246,7 +1559,7 @@ class JavascriptParser extends Parser {
1246
1559
  : innerExpressions.reverse();
1247
1560
  return new BasicEvaluatedExpression()
1248
1561
  .setWrapped(prefix, stringSuffix, inner)
1249
- .setRange(expr.range);
1562
+ .setRange(/** @type {Range} */ (expr.range));
1250
1563
  } else if (param.isWrapped()) {
1251
1564
  const postfix = stringSuffix || param.postfix;
1252
1565
  const inner = param.wrappedInnerExpressions
@@ -1254,18 +1567,18 @@ class JavascriptParser extends Parser {
1254
1567
  : innerExpressions.reverse();
1255
1568
  return new BasicEvaluatedExpression()
1256
1569
  .setWrapped(param.prefix, postfix, inner)
1257
- .setRange(expr.range);
1258
- } else {
1259
- const newString =
1260
- param.string + (stringSuffix ? stringSuffix.string : "");
1261
- return new BasicEvaluatedExpression()
1262
- .setString(newString)
1263
- .setSideEffects(
1264
- (stringSuffix && stringSuffix.couldHaveSideEffects()) ||
1265
- param.couldHaveSideEffects()
1266
- )
1267
- .setRange(expr.range);
1570
+ .setRange(/** @type {Range} */ (expr.range));
1268
1571
  }
1572
+ const newString =
1573
+ /** @type {string} */ (param.string) +
1574
+ (stringSuffix ? stringSuffix.string : "");
1575
+ return new BasicEvaluatedExpression()
1576
+ .setString(newString)
1577
+ .setSideEffects(
1578
+ (stringSuffix && stringSuffix.couldHaveSideEffects()) ||
1579
+ param.couldHaveSideEffects()
1580
+ )
1581
+ .setRange(/** @type {Range} */ (expr.range));
1269
1582
  });
1270
1583
  this.hooks.evaluateCallExpressionMember
1271
1584
  .for("split")
@@ -1276,21 +1589,25 @@ class JavascriptParser extends Parser {
1276
1589
  let result;
1277
1590
  const arg = this.evaluateExpression(expr.arguments[0]);
1278
1591
  if (arg.isString()) {
1279
- result = param.string.split(arg.string);
1592
+ result =
1593
+ /** @type {string} */
1594
+ (param.string).split(/** @type {string} */ (arg.string));
1280
1595
  } else if (arg.isRegExp()) {
1281
- result = param.string.split(arg.regExp);
1596
+ result = /** @type {string} */ (param.string).split(
1597
+ /** @type {RegExp} */ (arg.regExp)
1598
+ );
1282
1599
  } else {
1283
1600
  return;
1284
1601
  }
1285
1602
  return new BasicEvaluatedExpression()
1286
1603
  .setArray(result)
1287
1604
  .setSideEffects(param.couldHaveSideEffects())
1288
- .setRange(expr.range);
1605
+ .setRange(/** @type {Range} */ (expr.range));
1289
1606
  });
1290
1607
  this.hooks.evaluate
1291
1608
  .for("ConditionalExpression")
1292
1609
  .tap("JavascriptParser", _expr => {
1293
- const expr = /** @type {ConditionalExpressionNode} */ (_expr);
1610
+ const expr = /** @type {ConditionalExpression} */ (_expr);
1294
1611
 
1295
1612
  const condition = this.evaluateExpression(expr.test);
1296
1613
  const conditionValue = condition.asBool();
@@ -1298,15 +1615,18 @@ class JavascriptParser extends Parser {
1298
1615
  if (conditionValue === undefined) {
1299
1616
  const consequent = this.evaluateExpression(expr.consequent);
1300
1617
  const alternate = this.evaluateExpression(expr.alternate);
1301
- if (!consequent || !alternate) return;
1302
1618
  res = new BasicEvaluatedExpression();
1303
1619
  if (consequent.isConditional()) {
1304
- res.setOptions(consequent.options);
1620
+ res.setOptions(
1621
+ /** @type {BasicEvaluatedExpression[]} */ (consequent.options)
1622
+ );
1305
1623
  } else {
1306
1624
  res.setOptions([consequent]);
1307
1625
  }
1308
1626
  if (alternate.isConditional()) {
1309
- res.addOptions(alternate.options);
1627
+ res.addOptions(
1628
+ /** @type {BasicEvaluatedExpression[]} */ (alternate.options)
1629
+ );
1310
1630
  } else {
1311
1631
  res.addOptions([alternate]);
1312
1632
  }
@@ -1316,33 +1636,32 @@ class JavascriptParser extends Parser {
1316
1636
  );
1317
1637
  if (condition.couldHaveSideEffects()) res.setSideEffects();
1318
1638
  }
1319
- res.setRange(expr.range);
1639
+ res.setRange(/** @type {Range} */ (expr.range));
1320
1640
  return res;
1321
1641
  });
1322
1642
  this.hooks.evaluate
1323
1643
  .for("ArrayExpression")
1324
1644
  .tap("JavascriptParser", _expr => {
1325
- const expr = /** @type {ArrayExpressionNode} */ (_expr);
1645
+ const expr = /** @type {ArrayExpression} */ (_expr);
1326
1646
 
1327
- const items = expr.elements.map(element => {
1328
- return (
1647
+ const items = expr.elements.map(
1648
+ element =>
1329
1649
  element !== null &&
1330
1650
  element.type !== "SpreadElement" &&
1331
1651
  this.evaluateExpression(element)
1332
- );
1333
- });
1652
+ );
1334
1653
  if (!items.every(Boolean)) return;
1335
1654
  return new BasicEvaluatedExpression()
1336
- .setItems(items)
1337
- .setRange(expr.range);
1655
+ .setItems(/** @type {BasicEvaluatedExpression[]} */ (items))
1656
+ .setRange(/** @type {Range} */ (expr.range));
1338
1657
  });
1339
1658
  this.hooks.evaluate
1340
1659
  .for("ChainExpression")
1341
1660
  .tap("JavascriptParser", _expr => {
1342
- const expr = /** @type {ChainExpressionNode} */ (_expr);
1343
- /** @type {ExpressionNode[]} */
1661
+ const expr = /** @type {ChainExpression} */ (_expr);
1662
+ /** @type {Expression[]} */
1344
1663
  const optionalExpressionsStack = [];
1345
- /** @type {ExpressionNode|SuperNode} */
1664
+ /** @type {Expression|Super} */
1346
1665
  let next = expr.expression;
1347
1666
 
1348
1667
  while (
@@ -1353,7 +1672,7 @@ class JavascriptParser extends Parser {
1353
1672
  if (next.optional) {
1354
1673
  // SuperNode can not be optional
1355
1674
  optionalExpressionsStack.push(
1356
- /** @type {ExpressionNode} */ (next.object)
1675
+ /** @type {Expression} */ (next.object)
1357
1676
  );
1358
1677
  }
1359
1678
  next = next.object;
@@ -1361,7 +1680,7 @@ class JavascriptParser extends Parser {
1361
1680
  if (next.optional) {
1362
1681
  // SuperNode can not be optional
1363
1682
  optionalExpressionsStack.push(
1364
- /** @type {ExpressionNode} */ (next.callee)
1683
+ /** @type {Expression} */ (next.callee)
1365
1684
  );
1366
1685
  }
1367
1686
  next = next.callee;
@@ -1369,60 +1688,91 @@ class JavascriptParser extends Parser {
1369
1688
  }
1370
1689
 
1371
1690
  while (optionalExpressionsStack.length > 0) {
1372
- const expression = optionalExpressionsStack.pop();
1691
+ const expression =
1692
+ /** @type {Expression} */
1693
+ (optionalExpressionsStack.pop());
1373
1694
  const evaluated = this.evaluateExpression(expression);
1374
1695
 
1375
- if (evaluated && evaluated.asNullish()) {
1376
- return evaluated.setRange(_expr.range);
1696
+ if (evaluated.asNullish()) {
1697
+ return evaluated.setRange(/** @type {Range} */ (_expr.range));
1377
1698
  }
1378
1699
  }
1379
1700
  return this.evaluateExpression(expr.expression);
1380
1701
  });
1381
1702
  }
1382
1703
 
1704
+ /**
1705
+ * @param {Expression} node node
1706
+ * @returns {Set<DestructuringAssignmentProperty> | undefined} destructured identifiers
1707
+ */
1708
+ destructuringAssignmentPropertiesFor(node) {
1709
+ if (!this.destructuringAssignmentProperties) return;
1710
+ return this.destructuringAssignmentProperties.get(node);
1711
+ }
1712
+
1713
+ /**
1714
+ * @param {Expression} expr expression
1715
+ * @returns {string | VariableInfoInterface | undefined} identifier
1716
+ */
1383
1717
  getRenameIdentifier(expr) {
1384
1718
  const result = this.evaluateExpression(expr);
1385
- if (result && result.isIdentifier()) {
1719
+ if (result.isIdentifier()) {
1386
1720
  return result.identifier;
1387
1721
  }
1388
1722
  }
1389
1723
 
1390
1724
  /**
1391
- * @param {ClassExpressionNode | ClassDeclarationNode} classy a class node
1725
+ * @param {ClassExpression | ClassDeclaration} classy a class node
1392
1726
  * @returns {void}
1393
1727
  */
1394
1728
  walkClass(classy) {
1395
- if (classy.superClass) {
1396
- if (!this.hooks.classExtendsExpression.call(classy.superClass, classy)) {
1397
- this.walkExpression(classy.superClass);
1398
- }
1729
+ if (
1730
+ classy.superClass &&
1731
+ !this.hooks.classExtendsExpression.call(classy.superClass, classy)
1732
+ ) {
1733
+ this.walkExpression(classy.superClass);
1399
1734
  }
1400
1735
  if (classy.body && classy.body.type === "ClassBody") {
1401
- for (const classElement of /** @type {TODO} */ (classy.body.body)) {
1402
- if (!this.hooks.classBodyElement.call(classElement, classy)) {
1403
- if (classElement.computed && classElement.key) {
1404
- this.walkExpression(classElement.key);
1405
- }
1406
- if (classElement.value) {
1407
- if (
1408
- !this.hooks.classBodyValue.call(
1409
- classElement.value,
1410
- classElement,
1411
- classy
1412
- )
1413
- ) {
1736
+ const scopeParams = [];
1737
+ // Add class name in scope for recursive calls
1738
+ if (classy.id) {
1739
+ scopeParams.push(classy.id);
1740
+ }
1741
+ this.inClassScope(true, scopeParams, () => {
1742
+ for (const classElement of /** @type {TODO} */ (classy.body.body)) {
1743
+ if (!this.hooks.classBodyElement.call(classElement, classy)) {
1744
+ if (classElement.computed && classElement.key) {
1745
+ this.walkExpression(classElement.key);
1746
+ }
1747
+ if (classElement.value) {
1748
+ if (
1749
+ !this.hooks.classBodyValue.call(
1750
+ classElement.value,
1751
+ classElement,
1752
+ classy
1753
+ )
1754
+ ) {
1755
+ const wasTopLevel = this.scope.topLevelScope;
1756
+ this.scope.topLevelScope = false;
1757
+ this.walkExpression(classElement.value);
1758
+ this.scope.topLevelScope = wasTopLevel;
1759
+ }
1760
+ } else if (classElement.type === "StaticBlock") {
1414
1761
  const wasTopLevel = this.scope.topLevelScope;
1415
1762
  this.scope.topLevelScope = false;
1416
- this.walkExpression(classElement.value);
1763
+ this.walkBlockStatement(classElement);
1417
1764
  this.scope.topLevelScope = wasTopLevel;
1418
1765
  }
1419
1766
  }
1420
1767
  }
1421
- }
1768
+ });
1422
1769
  }
1423
1770
  }
1424
1771
 
1425
- // Pre walking iterates the scope for variable declarations
1772
+ /**
1773
+ * Pre walking iterates the scope for variable declarations
1774
+ * @param {(Statement | ModuleDeclaration)[]} statements statements
1775
+ */
1426
1776
  preWalkStatements(statements) {
1427
1777
  for (let index = 0, len = statements.length; index < len; index++) {
1428
1778
  const statement = statements[index];
@@ -1430,7 +1780,10 @@ class JavascriptParser extends Parser {
1430
1780
  }
1431
1781
  }
1432
1782
 
1433
- // Block pre walking iterates the scope for block variable declarations
1783
+ /**
1784
+ * Block pre walking iterates the scope for block variable declarations
1785
+ * @param {(Statement | ModuleDeclaration)[]} statements statements
1786
+ */
1434
1787
  blockPreWalkStatements(statements) {
1435
1788
  for (let index = 0, len = statements.length; index < len; index++) {
1436
1789
  const statement = statements[index];
@@ -1438,7 +1791,10 @@ class JavascriptParser extends Parser {
1438
1791
  }
1439
1792
  }
1440
1793
 
1441
- // Walking iterates the statements and expressions and processes them
1794
+ /**
1795
+ * Walking iterates the statements and expressions and processes them
1796
+ * @param {(Statement | ModuleDeclaration)[]} statements statements
1797
+ */
1442
1798
  walkStatements(statements) {
1443
1799
  for (let index = 0, len = statements.length; index < len; index++) {
1444
1800
  const statement = statements[index];
@@ -1446,6 +1802,10 @@ class JavascriptParser extends Parser {
1446
1802
  }
1447
1803
  }
1448
1804
 
1805
+ /**
1806
+ * Walking iterates the statements and expressions and processes them
1807
+ * @param {Statement | ModuleDeclaration} statement statement
1808
+ */
1449
1809
  preWalkStatement(statement) {
1450
1810
  this.statementPath.push(statement);
1451
1811
  if (this.hooks.preStatement.call(statement)) {
@@ -1496,6 +1856,9 @@ class JavascriptParser extends Parser {
1496
1856
  this.prevStatement = this.statementPath.pop();
1497
1857
  }
1498
1858
 
1859
+ /**
1860
+ * @param {Statement | ModuleDeclaration} statement statement
1861
+ */
1499
1862
  blockPreWalkStatement(statement) {
1500
1863
  this.statementPath.push(statement);
1501
1864
  if (this.hooks.blockPreStatement.call(statement)) {
@@ -1521,10 +1884,15 @@ class JavascriptParser extends Parser {
1521
1884
  case "ClassDeclaration":
1522
1885
  this.blockPreWalkClassDeclaration(statement);
1523
1886
  break;
1887
+ case "ExpressionStatement":
1888
+ this.blockPreWalkExpressionStatement(statement);
1524
1889
  }
1525
1890
  this.prevStatement = this.statementPath.pop();
1526
1891
  }
1527
1892
 
1893
+ /**
1894
+ * @param {Statement | ModuleDeclaration} statement statement
1895
+ */
1528
1896
  walkStatement(statement) {
1529
1897
  this.statementPath.push(statement);
1530
1898
  if (this.hooks.statement.call(statement) !== undefined) {
@@ -1597,8 +1965,7 @@ class JavascriptParser extends Parser {
1597
1965
  * Walks a statements that is nested within a parent statement
1598
1966
  * and can potentially be a non-block statement.
1599
1967
  * This enforces the nested statement to never be in ASI position.
1600
- * @param {StatementNode} statement the nested statement
1601
- * @returns {void}
1968
+ * @param {Statement} statement the nested statement
1602
1969
  */
1603
1970
  walkNestedStatement(statement) {
1604
1971
  this.prevStatement = undefined;
@@ -1606,10 +1973,16 @@ class JavascriptParser extends Parser {
1606
1973
  }
1607
1974
 
1608
1975
  // Real Statements
1976
+ /**
1977
+ * @param {BlockStatement} statement block statement
1978
+ */
1609
1979
  preWalkBlockStatement(statement) {
1610
1980
  this.preWalkStatements(statement.body);
1611
1981
  }
1612
1982
 
1983
+ /**
1984
+ * @param {BlockStatement} statement block statement
1985
+ */
1613
1986
  walkBlockStatement(statement) {
1614
1987
  this.inBlockScope(() => {
1615
1988
  const body = statement.body;
@@ -1620,10 +1993,16 @@ class JavascriptParser extends Parser {
1620
1993
  });
1621
1994
  }
1622
1995
 
1996
+ /**
1997
+ * @param {ExpressionStatement} statement expression statement
1998
+ */
1623
1999
  walkExpressionStatement(statement) {
1624
2000
  this.walkExpression(statement.expression);
1625
2001
  }
1626
2002
 
2003
+ /**
2004
+ * @param {IfStatement} statement if statement
2005
+ */
1627
2006
  preWalkIfStatement(statement) {
1628
2007
  this.preWalkStatement(statement.consequent);
1629
2008
  if (statement.alternate) {
@@ -1631,6 +2010,9 @@ class JavascriptParser extends Parser {
1631
2010
  }
1632
2011
  }
1633
2012
 
2013
+ /**
2014
+ * @param {IfStatement} statement if statement
2015
+ */
1634
2016
  walkIfStatement(statement) {
1635
2017
  const result = this.hooks.statementIf.call(statement);
1636
2018
  if (result === undefined) {
@@ -1639,19 +2021,23 @@ class JavascriptParser extends Parser {
1639
2021
  if (statement.alternate) {
1640
2022
  this.walkNestedStatement(statement.alternate);
1641
2023
  }
1642
- } else {
1643
- if (result) {
1644
- this.walkNestedStatement(statement.consequent);
1645
- } else if (statement.alternate) {
1646
- this.walkNestedStatement(statement.alternate);
1647
- }
2024
+ } else if (result) {
2025
+ this.walkNestedStatement(statement.consequent);
2026
+ } else if (statement.alternate) {
2027
+ this.walkNestedStatement(statement.alternate);
1648
2028
  }
1649
2029
  }
1650
2030
 
2031
+ /**
2032
+ * @param {LabeledStatement} statement with statement
2033
+ */
1651
2034
  preWalkLabeledStatement(statement) {
1652
2035
  this.preWalkStatement(statement.body);
1653
2036
  }
1654
2037
 
2038
+ /**
2039
+ * @param {LabeledStatement} statement with statement
2040
+ */
1655
2041
  walkLabeledStatement(statement) {
1656
2042
  const hook = this.hooks.label.get(statement.label.name);
1657
2043
  if (hook !== undefined) {
@@ -1661,42 +2047,69 @@ class JavascriptParser extends Parser {
1661
2047
  this.walkNestedStatement(statement.body);
1662
2048
  }
1663
2049
 
2050
+ /**
2051
+ * @param {WithStatement} statement with statement
2052
+ */
1664
2053
  preWalkWithStatement(statement) {
1665
2054
  this.preWalkStatement(statement.body);
1666
2055
  }
1667
2056
 
2057
+ /**
2058
+ * @param {WithStatement} statement with statement
2059
+ */
1668
2060
  walkWithStatement(statement) {
1669
2061
  this.walkExpression(statement.object);
1670
2062
  this.walkNestedStatement(statement.body);
1671
2063
  }
1672
2064
 
2065
+ /**
2066
+ * @param {SwitchStatement} statement switch statement
2067
+ */
1673
2068
  preWalkSwitchStatement(statement) {
1674
2069
  this.preWalkSwitchCases(statement.cases);
1675
2070
  }
1676
2071
 
2072
+ /**
2073
+ * @param {SwitchStatement} statement switch statement
2074
+ */
1677
2075
  walkSwitchStatement(statement) {
1678
2076
  this.walkExpression(statement.discriminant);
1679
2077
  this.walkSwitchCases(statement.cases);
1680
2078
  }
1681
2079
 
2080
+ /**
2081
+ * @param {ReturnStatement | ThrowStatement} statement return or throw statement
2082
+ */
1682
2083
  walkTerminatingStatement(statement) {
1683
2084
  if (statement.argument) this.walkExpression(statement.argument);
1684
2085
  }
1685
2086
 
2087
+ /**
2088
+ * @param {ReturnStatement} statement return statement
2089
+ */
1686
2090
  walkReturnStatement(statement) {
1687
2091
  this.walkTerminatingStatement(statement);
1688
2092
  }
1689
2093
 
2094
+ /**
2095
+ * @param {ThrowStatement} statement return statement
2096
+ */
1690
2097
  walkThrowStatement(statement) {
1691
2098
  this.walkTerminatingStatement(statement);
1692
2099
  }
1693
2100
 
2101
+ /**
2102
+ * @param {TryStatement} statement try statement
2103
+ */
1694
2104
  preWalkTryStatement(statement) {
1695
2105
  this.preWalkStatement(statement.block);
1696
2106
  if (statement.handler) this.preWalkCatchClause(statement.handler);
1697
- if (statement.finializer) this.preWalkStatement(statement.finializer);
2107
+ if (statement.finalizer) this.preWalkStatement(statement.finalizer);
1698
2108
  }
1699
2109
 
2110
+ /**
2111
+ * @param {TryStatement} statement try statement
2112
+ */
1700
2113
  walkTryStatement(statement) {
1701
2114
  if (this.scope.inTry) {
1702
2115
  this.walkStatement(statement.block);
@@ -1709,33 +2122,49 @@ class JavascriptParser extends Parser {
1709
2122
  if (statement.finalizer) this.walkStatement(statement.finalizer);
1710
2123
  }
1711
2124
 
2125
+ /**
2126
+ * @param {WhileStatement} statement while statement
2127
+ */
1712
2128
  preWalkWhileStatement(statement) {
1713
2129
  this.preWalkStatement(statement.body);
1714
2130
  }
1715
2131
 
2132
+ /**
2133
+ * @param {WhileStatement} statement while statement
2134
+ */
1716
2135
  walkWhileStatement(statement) {
1717
2136
  this.walkExpression(statement.test);
1718
2137
  this.walkNestedStatement(statement.body);
1719
2138
  }
1720
2139
 
2140
+ /**
2141
+ * @param {DoWhileStatement} statement do while statement
2142
+ */
1721
2143
  preWalkDoWhileStatement(statement) {
1722
2144
  this.preWalkStatement(statement.body);
1723
2145
  }
1724
2146
 
2147
+ /**
2148
+ * @param {DoWhileStatement} statement do while statement
2149
+ */
1725
2150
  walkDoWhileStatement(statement) {
1726
2151
  this.walkNestedStatement(statement.body);
1727
2152
  this.walkExpression(statement.test);
1728
2153
  }
1729
2154
 
2155
+ /**
2156
+ * @param {ForStatement} statement for statement
2157
+ */
1730
2158
  preWalkForStatement(statement) {
1731
- if (statement.init) {
1732
- if (statement.init.type === "VariableDeclaration") {
1733
- this.preWalkStatement(statement.init);
1734
- }
2159
+ if (statement.init && statement.init.type === "VariableDeclaration") {
2160
+ this.preWalkStatement(statement.init);
1735
2161
  }
1736
2162
  this.preWalkStatement(statement.body);
1737
2163
  }
1738
2164
 
2165
+ /**
2166
+ * @param {ForStatement} statement for statement
2167
+ */
1739
2168
  walkForStatement(statement) {
1740
2169
  this.inBlockScope(() => {
1741
2170
  if (statement.init) {
@@ -1766,6 +2195,9 @@ class JavascriptParser extends Parser {
1766
2195
  });
1767
2196
  }
1768
2197
 
2198
+ /**
2199
+ * @param {ForInStatement} statement for statement
2200
+ */
1769
2201
  preWalkForInStatement(statement) {
1770
2202
  if (statement.left.type === "VariableDeclaration") {
1771
2203
  this.preWalkVariableDeclaration(statement.left);
@@ -1773,6 +2205,9 @@ class JavascriptParser extends Parser {
1773
2205
  this.preWalkStatement(statement.body);
1774
2206
  }
1775
2207
 
2208
+ /**
2209
+ * @param {ForInStatement} statement for statement
2210
+ */
1776
2211
  walkForInStatement(statement) {
1777
2212
  this.inBlockScope(() => {
1778
2213
  if (statement.left.type === "VariableDeclaration") {
@@ -1795,6 +2230,9 @@ class JavascriptParser extends Parser {
1795
2230
  });
1796
2231
  }
1797
2232
 
2233
+ /**
2234
+ * @param {ForOfStatement} statement statement
2235
+ */
1798
2236
  preWalkForOfStatement(statement) {
1799
2237
  if (statement.await && this.scope.topLevelScope === true) {
1800
2238
  this.hooks.topLevelAwait.call(statement);
@@ -1805,6 +2243,9 @@ class JavascriptParser extends Parser {
1805
2243
  this.preWalkStatement(statement.body);
1806
2244
  }
1807
2245
 
2246
+ /**
2247
+ * @param {ForOfStatement} statement for statement
2248
+ */
1808
2249
  walkForOfStatement(statement) {
1809
2250
  this.inBlockScope(() => {
1810
2251
  if (statement.left.type === "VariableDeclaration") {
@@ -1827,13 +2268,18 @@ class JavascriptParser extends Parser {
1827
2268
  });
1828
2269
  }
1829
2270
 
1830
- // Declarations
2271
+ /**
2272
+ * @param {FunctionDeclaration} statement function declaration
2273
+ */
1831
2274
  preWalkFunctionDeclaration(statement) {
1832
2275
  if (statement.id) {
1833
2276
  this.defineVariable(statement.id.name);
1834
2277
  }
1835
2278
  }
1836
2279
 
2280
+ /**
2281
+ * @param {FunctionDeclaration} statement function declaration
2282
+ */
1837
2283
  walkFunctionDeclaration(statement) {
1838
2284
  const wasTopLevel = this.scope.topLevelScope;
1839
2285
  this.scope.topLevelScope = false;
@@ -1854,8 +2300,55 @@ class JavascriptParser extends Parser {
1854
2300
  this.scope.topLevelScope = wasTopLevel;
1855
2301
  }
1856
2302
 
2303
+ /**
2304
+ * @param {ExpressionStatement} statement expression statement
2305
+ */
2306
+ blockPreWalkExpressionStatement(statement) {
2307
+ const expression = statement.expression;
2308
+ switch (expression.type) {
2309
+ case "AssignmentExpression":
2310
+ this.preWalkAssignmentExpression(expression);
2311
+ }
2312
+ }
2313
+
2314
+ /**
2315
+ * @param {AssignmentExpression} expression assignment expression
2316
+ */
2317
+ preWalkAssignmentExpression(expression) {
2318
+ if (
2319
+ expression.left.type !== "ObjectPattern" ||
2320
+ !this.destructuringAssignmentProperties
2321
+ )
2322
+ return;
2323
+ const keys = this._preWalkObjectPattern(expression.left);
2324
+ if (!keys) return;
2325
+
2326
+ // check multiple assignments
2327
+ if (this.destructuringAssignmentProperties.has(expression)) {
2328
+ const set =
2329
+ /** @type {Set<DestructuringAssignmentProperty>} */
2330
+ (this.destructuringAssignmentProperties.get(expression));
2331
+ this.destructuringAssignmentProperties.delete(expression);
2332
+ for (const id of set) keys.add(id);
2333
+ }
2334
+
2335
+ this.destructuringAssignmentProperties.set(
2336
+ expression.right.type === "AwaitExpression"
2337
+ ? expression.right.argument
2338
+ : expression.right,
2339
+ keys
2340
+ );
2341
+
2342
+ if (expression.right.type === "AssignmentExpression") {
2343
+ this.preWalkAssignmentExpression(expression.right);
2344
+ }
2345
+ }
2346
+
2347
+ /**
2348
+ * @param {ImportDeclaration} statement statement
2349
+ */
1857
2350
  blockPreWalkImportDeclaration(statement) {
1858
- const source = statement.source.value;
2351
+ const source = /** @type {ImportSource} */ (statement.source.value);
1859
2352
  this.hooks.import.call(statement, source);
1860
2353
  for (const specifier of statement.specifiers) {
1861
2354
  const name = specifier.local.name;
@@ -1872,7 +2365,12 @@ class JavascriptParser extends Parser {
1872
2365
  !this.hooks.importSpecifier.call(
1873
2366
  statement,
1874
2367
  source,
1875
- specifier.imported.name,
2368
+ specifier.imported.name ||
2369
+ // eslint-disable-next-line no-warning-comments
2370
+ // @ts-ignore
2371
+ // Old version of acorn used it
2372
+ // TODO drop it in webpack@6
2373
+ specifier.imported.value,
1876
2374
  name
1877
2375
  )
1878
2376
  ) {
@@ -1890,6 +2388,10 @@ class JavascriptParser extends Parser {
1890
2388
  }
1891
2389
  }
1892
2390
 
2391
+ /**
2392
+ * @param {Declaration} declaration declaration
2393
+ * @param {OnIdent} onIdent on ident callback
2394
+ */
1893
2395
  enterDeclaration(declaration, onIdent) {
1894
2396
  switch (declaration.type) {
1895
2397
  case "VariableDeclaration":
@@ -1911,27 +2413,29 @@ class JavascriptParser extends Parser {
1911
2413
  }
1912
2414
  }
1913
2415
 
2416
+ /**
2417
+ * @param {ExportNamedDeclaration} statement statement
2418
+ */
1914
2419
  blockPreWalkExportNamedDeclaration(statement) {
1915
2420
  let source;
1916
2421
  if (statement.source) {
1917
- source = statement.source.value;
2422
+ source = /** @type {ImportSource} */ (statement.source.value);
1918
2423
  this.hooks.exportImport.call(statement, source);
1919
2424
  } else {
1920
2425
  this.hooks.export.call(statement);
1921
2426
  }
1922
- if (statement.declaration) {
1923
- if (
1924
- !this.hooks.exportDeclaration.call(statement, statement.declaration)
1925
- ) {
1926
- const prev = this.prevStatement;
1927
- this.preWalkStatement(statement.declaration);
1928
- this.prevStatement = prev;
1929
- this.blockPreWalkStatement(statement.declaration);
1930
- let index = 0;
1931
- this.enterDeclaration(statement.declaration, def => {
1932
- this.hooks.exportSpecifier.call(statement, def, def, index++);
1933
- });
1934
- }
2427
+ if (
2428
+ statement.declaration &&
2429
+ !this.hooks.exportDeclaration.call(statement, statement.declaration)
2430
+ ) {
2431
+ const prev = this.prevStatement;
2432
+ this.preWalkStatement(statement.declaration);
2433
+ this.prevStatement = prev;
2434
+ this.blockPreWalkStatement(statement.declaration);
2435
+ let index = 0;
2436
+ this.enterDeclaration(statement.declaration, def => {
2437
+ this.hooks.exportSpecifier.call(statement, def, def, index++);
2438
+ });
1935
2439
  }
1936
2440
  if (statement.specifiers) {
1937
2441
  for (
@@ -1942,7 +2446,13 @@ class JavascriptParser extends Parser {
1942
2446
  const specifier = statement.specifiers[specifierIndex];
1943
2447
  switch (specifier.type) {
1944
2448
  case "ExportSpecifier": {
1945
- const name = specifier.exported.name;
2449
+ const name =
2450
+ specifier.exported.name ||
2451
+ // eslint-disable-next-line no-warning-comments
2452
+ // @ts-ignore
2453
+ // Old version of acorn used it
2454
+ // TODO drop it in webpack@6
2455
+ specifier.exported.value;
1946
2456
  if (source) {
1947
2457
  this.hooks.exportImportSpecifier.call(
1948
2458
  statement,
@@ -1966,42 +2476,59 @@ class JavascriptParser extends Parser {
1966
2476
  }
1967
2477
  }
1968
2478
 
2479
+ /**
2480
+ * @param {ExportNamedDeclaration} statement the statement
2481
+ */
1969
2482
  walkExportNamedDeclaration(statement) {
1970
2483
  if (statement.declaration) {
1971
2484
  this.walkStatement(statement.declaration);
1972
2485
  }
1973
2486
  }
1974
2487
 
2488
+ /**
2489
+ * @param {TODO} statement statement
2490
+ */
1975
2491
  blockPreWalkExportDefaultDeclaration(statement) {
1976
2492
  const prev = this.prevStatement;
1977
2493
  this.preWalkStatement(statement.declaration);
1978
2494
  this.prevStatement = prev;
1979
2495
  this.blockPreWalkStatement(statement.declaration);
1980
2496
  if (
1981
- statement.declaration.id &&
2497
+ /** @type {FunctionDeclaration | ClassDeclaration} */ (
2498
+ statement.declaration
2499
+ ).id &&
1982
2500
  statement.declaration.type !== "FunctionExpression" &&
1983
2501
  statement.declaration.type !== "ClassExpression"
1984
2502
  ) {
2503
+ const declaration =
2504
+ /** @type {FunctionDeclaration | ClassDeclaration} */
2505
+ (statement.declaration);
1985
2506
  this.hooks.exportSpecifier.call(
1986
2507
  statement,
1987
- statement.declaration.id.name,
2508
+ declaration.id.name,
1988
2509
  "default",
1989
2510
  undefined
1990
2511
  );
1991
2512
  }
1992
2513
  }
1993
2514
 
2515
+ /**
2516
+ * @param {ExportDefaultDeclaration} statement statement
2517
+ */
1994
2518
  walkExportDefaultDeclaration(statement) {
1995
2519
  this.hooks.export.call(statement);
1996
2520
  if (
1997
- statement.declaration.id &&
2521
+ /** @type {FunctionDeclaration | ClassDeclaration} */ (
2522
+ statement.declaration
2523
+ ).id &&
1998
2524
  statement.declaration.type !== "FunctionExpression" &&
1999
2525
  statement.declaration.type !== "ClassExpression"
2000
2526
  ) {
2001
- if (
2002
- !this.hooks.exportDeclaration.call(statement, statement.declaration)
2003
- ) {
2004
- this.walkStatement(statement.declaration);
2527
+ const declaration =
2528
+ /** @type {FunctionDeclaration | ClassDeclaration} */
2529
+ (statement.declaration);
2530
+ if (!this.hooks.exportDeclaration.call(statement, declaration)) {
2531
+ this.walkStatement(declaration);
2005
2532
  }
2006
2533
  } else {
2007
2534
  // Acorn parses `export default function() {}` as `FunctionDeclaration` and
@@ -2011,14 +2538,23 @@ class JavascriptParser extends Parser {
2011
2538
  statement.declaration.type === "FunctionDeclaration" ||
2012
2539
  statement.declaration.type === "ClassDeclaration"
2013
2540
  ) {
2014
- this.walkStatement(statement.declaration);
2541
+ this.walkStatement(
2542
+ /** @type {FunctionDeclaration | ClassDeclaration} */
2543
+ (statement.declaration)
2544
+ );
2015
2545
  } else {
2016
2546
  this.walkExpression(statement.declaration);
2017
2547
  }
2018
- if (!this.hooks.exportExpression.call(statement, statement.declaration)) {
2548
+
2549
+ if (
2550
+ !this.hooks.exportExpression.call(
2551
+ statement,
2552
+ /** @type {TODO} */ (statement).declaration
2553
+ )
2554
+ ) {
2019
2555
  this.hooks.exportSpecifier.call(
2020
2556
  statement,
2021
- statement.declaration,
2557
+ /** @type {TODO} */ (statement.declaration),
2022
2558
  "default",
2023
2559
  undefined
2024
2560
  );
@@ -2026,18 +2562,27 @@ class JavascriptParser extends Parser {
2026
2562
  }
2027
2563
  }
2028
2564
 
2029
- blockPreWalkExportAllDeclaration(statement) {
2030
- const source = statement.source.value;
2565
+ /**
2566
+ * @param {ExportAllDeclaration} statement statement
2567
+ */
2568
+ blockPreWalkExportAllDeclaration(statement) {
2569
+ const source = /** @type {ImportSource} */ (statement.source.value);
2031
2570
  const name = statement.exported ? statement.exported.name : null;
2032
2571
  this.hooks.exportImport.call(statement, source);
2033
2572
  this.hooks.exportImportSpecifier.call(statement, source, null, name, 0);
2034
2573
  }
2035
2574
 
2575
+ /**
2576
+ * @param {VariableDeclaration} statement variable declaration
2577
+ */
2036
2578
  preWalkVariableDeclaration(statement) {
2037
2579
  if (statement.kind !== "var") return;
2038
2580
  this._preWalkVariableDeclaration(statement, this.hooks.varDeclarationVar);
2039
2581
  }
2040
2582
 
2583
+ /**
2584
+ * @param {VariableDeclaration} statement variable declaration
2585
+ */
2041
2586
  blockPreWalkVariableDeclaration(statement) {
2042
2587
  if (statement.kind === "var") return;
2043
2588
  const hookMap =
@@ -2047,10 +2592,15 @@ class JavascriptParser extends Parser {
2047
2592
  this._preWalkVariableDeclaration(statement, hookMap);
2048
2593
  }
2049
2594
 
2595
+ /**
2596
+ * @param {VariableDeclaration} statement variable declaration
2597
+ * @param {TODO} hookMap map of hooks
2598
+ */
2050
2599
  _preWalkVariableDeclaration(statement, hookMap) {
2051
2600
  for (const declarator of statement.declarations) {
2052
2601
  switch (declarator.type) {
2053
2602
  case "VariableDeclarator": {
2603
+ this.preWalkVariableDeclarator(declarator);
2054
2604
  if (!this.hooks.preDeclarator.call(declarator, statement)) {
2055
2605
  this.enterPattern(declarator.id, (name, decl) => {
2056
2606
  let hook = hookMap.get(name);
@@ -2068,6 +2618,75 @@ class JavascriptParser extends Parser {
2068
2618
  }
2069
2619
  }
2070
2620
 
2621
+ /**
2622
+ * @param {ObjectPattern} objectPattern object pattern
2623
+ * @returns {Set<DestructuringAssignmentProperty> | undefined} set of names or undefined if not all keys are identifiers
2624
+ */
2625
+ _preWalkObjectPattern(objectPattern) {
2626
+ /** @type {Set<DestructuringAssignmentProperty>} */
2627
+ const props = new Set();
2628
+ const properties = objectPattern.properties;
2629
+ for (let i = 0; i < properties.length; i++) {
2630
+ const property = properties[i];
2631
+ if (property.type !== "Property") return;
2632
+ if (property.shorthand && property.value.type === "Identifier") {
2633
+ this.scope.inShorthand = property.value.name;
2634
+ }
2635
+ const key = property.key;
2636
+ if (key.type === "Identifier") {
2637
+ props.add({
2638
+ id: key.name,
2639
+ range: key.range,
2640
+ shorthand: this.scope.inShorthand
2641
+ });
2642
+ } else {
2643
+ const id = this.evaluateExpression(/** @type {TODO} */ (key));
2644
+ const str = id.asString();
2645
+ if (str) {
2646
+ props.add({
2647
+ id: str,
2648
+ range: key.range,
2649
+ shorthand: this.scope.inShorthand
2650
+ });
2651
+ } else {
2652
+ // could not evaluate key
2653
+ return;
2654
+ }
2655
+ }
2656
+ this.scope.inShorthand = false;
2657
+ }
2658
+
2659
+ return props;
2660
+ }
2661
+
2662
+ /**
2663
+ * @param {VariableDeclarator} declarator variable declarator
2664
+ */
2665
+ preWalkVariableDeclarator(declarator) {
2666
+ if (
2667
+ !declarator.init ||
2668
+ declarator.id.type !== "ObjectPattern" ||
2669
+ !this.destructuringAssignmentProperties
2670
+ )
2671
+ return;
2672
+ const keys = this._preWalkObjectPattern(declarator.id);
2673
+
2674
+ if (!keys) return;
2675
+ this.destructuringAssignmentProperties.set(
2676
+ declarator.init.type === "AwaitExpression"
2677
+ ? declarator.init.argument
2678
+ : declarator.init,
2679
+ keys
2680
+ );
2681
+
2682
+ if (declarator.init.type === "AssignmentExpression") {
2683
+ this.preWalkAssignmentExpression(declarator.init);
2684
+ }
2685
+ }
2686
+
2687
+ /**
2688
+ * @param {VariableDeclaration} statement variable declaration
2689
+ */
2071
2690
  walkVariableDeclaration(statement) {
2072
2691
  for (const declarator of statement.declarations) {
2073
2692
  switch (declarator.type) {
@@ -2076,10 +2695,16 @@ class JavascriptParser extends Parser {
2076
2695
  declarator.init && this.getRenameIdentifier(declarator.init);
2077
2696
  if (renameIdentifier && declarator.id.type === "Identifier") {
2078
2697
  const hook = this.hooks.canRename.get(renameIdentifier);
2079
- if (hook !== undefined && hook.call(declarator.init)) {
2698
+ if (
2699
+ hook !== undefined &&
2700
+ hook.call(/** @type {Expression} */ (declarator.init))
2701
+ ) {
2080
2702
  // renaming with "var a = b;"
2081
2703
  const hook = this.hooks.rename.get(renameIdentifier);
2082
- if (hook === undefined || !hook.call(declarator.init)) {
2704
+ if (
2705
+ hook === undefined ||
2706
+ !hook.call(/** @type {Expression} */ (declarator.init))
2707
+ ) {
2083
2708
  this.setVariable(declarator.id.name, renameIdentifier);
2084
2709
  }
2085
2710
  break;
@@ -2095,16 +2720,25 @@ class JavascriptParser extends Parser {
2095
2720
  }
2096
2721
  }
2097
2722
 
2723
+ /**
2724
+ * @param {ClassDeclaration} statement class declaration
2725
+ */
2098
2726
  blockPreWalkClassDeclaration(statement) {
2099
2727
  if (statement.id) {
2100
2728
  this.defineVariable(statement.id.name);
2101
2729
  }
2102
2730
  }
2103
2731
 
2732
+ /**
2733
+ * @param {ClassDeclaration} statement class declaration
2734
+ */
2104
2735
  walkClassDeclaration(statement) {
2105
2736
  this.walkClass(statement);
2106
2737
  }
2107
2738
 
2739
+ /**
2740
+ * @param {SwitchCase[]} switchCases switch statement
2741
+ */
2108
2742
  preWalkSwitchCases(switchCases) {
2109
2743
  for (let index = 0, len = switchCases.length; index < len; index++) {
2110
2744
  const switchCase = switchCases[index];
@@ -2112,6 +2746,9 @@ class JavascriptParser extends Parser {
2112
2746
  }
2113
2747
  }
2114
2748
 
2749
+ /**
2750
+ * @param {SwitchCase[]} switchCases switch statement
2751
+ */
2115
2752
  walkSwitchCases(switchCases) {
2116
2753
  this.inBlockScope(() => {
2117
2754
  const len = switchCases.length;
@@ -2147,10 +2784,16 @@ class JavascriptParser extends Parser {
2147
2784
  });
2148
2785
  }
2149
2786
 
2787
+ /**
2788
+ * @param {CatchClause} catchClause catch clause
2789
+ */
2150
2790
  preWalkCatchClause(catchClause) {
2151
2791
  this.preWalkStatement(catchClause.body);
2152
2792
  }
2153
2793
 
2794
+ /**
2795
+ * @param {CatchClause} catchClause catch clause
2796
+ */
2154
2797
  walkCatchClause(catchClause) {
2155
2798
  this.inBlockScope(() => {
2156
2799
  // Error binding is optional in catch clause since ECMAScript 2019
@@ -2167,6 +2810,9 @@ class JavascriptParser extends Parser {
2167
2810
  });
2168
2811
  }
2169
2812
 
2813
+ /**
2814
+ * @param {Pattern} pattern pattern
2815
+ */
2170
2816
  walkPattern(pattern) {
2171
2817
  switch (pattern.type) {
2172
2818
  case "ArrayPattern":
@@ -2187,21 +2833,33 @@ class JavascriptParser extends Parser {
2187
2833
  }
2188
2834
  }
2189
2835
 
2836
+ /**
2837
+ * @param {AssignmentPattern} pattern assignment pattern
2838
+ */
2190
2839
  walkAssignmentPattern(pattern) {
2191
2840
  this.walkExpression(pattern.right);
2192
2841
  this.walkPattern(pattern.left);
2193
2842
  }
2194
2843
 
2844
+ /**
2845
+ * @param {ObjectPattern} pattern pattern
2846
+ */
2195
2847
  walkObjectPattern(pattern) {
2196
2848
  for (let i = 0, len = pattern.properties.length; i < len; i++) {
2197
2849
  const prop = pattern.properties[i];
2198
2850
  if (prop) {
2851
+ if (prop.type === "RestElement") {
2852
+ continue;
2853
+ }
2199
2854
  if (prop.computed) this.walkExpression(prop.key);
2200
2855
  if (prop.value) this.walkPattern(prop.value);
2201
2856
  }
2202
2857
  }
2203
2858
  }
2204
2859
 
2860
+ /**
2861
+ * @param {ArrayPattern} pattern array pattern
2862
+ */
2205
2863
  walkArrayPattern(pattern) {
2206
2864
  for (let i = 0, len = pattern.elements.length; i < len; i++) {
2207
2865
  const element = pattern.elements[i];
@@ -2209,10 +2867,16 @@ class JavascriptParser extends Parser {
2209
2867
  }
2210
2868
  }
2211
2869
 
2870
+ /**
2871
+ * @param {RestElement} pattern rest element
2872
+ */
2212
2873
  walkRestElement(pattern) {
2213
2874
  this.walkPattern(pattern.argument);
2214
2875
  }
2215
2876
 
2877
+ /**
2878
+ * @param {(Expression | SpreadElement | null)[]} expressions expressions
2879
+ */
2216
2880
  walkExpressions(expressions) {
2217
2881
  for (const expression of expressions) {
2218
2882
  if (expression) {
@@ -2221,6 +2885,9 @@ class JavascriptParser extends Parser {
2221
2885
  }
2222
2886
  }
2223
2887
 
2888
+ /**
2889
+ * @param {TODO} expression expression
2890
+ */
2224
2891
  walkExpression(expression) {
2225
2892
  switch (expression.type) {
2226
2893
  case "ArrayExpression":
@@ -2301,24 +2968,36 @@ class JavascriptParser extends Parser {
2301
2968
  }
2302
2969
  }
2303
2970
 
2971
+ /**
2972
+ * @param {AwaitExpression} expression await expression
2973
+ */
2304
2974
  walkAwaitExpression(expression) {
2305
2975
  if (this.scope.topLevelScope === true)
2306
2976
  this.hooks.topLevelAwait.call(expression);
2307
2977
  this.walkExpression(expression.argument);
2308
2978
  }
2309
2979
 
2980
+ /**
2981
+ * @param {ArrayExpression} expression array expression
2982
+ */
2310
2983
  walkArrayExpression(expression) {
2311
2984
  if (expression.elements) {
2312
2985
  this.walkExpressions(expression.elements);
2313
2986
  }
2314
2987
  }
2315
2988
 
2989
+ /**
2990
+ * @param {SpreadElement} expression spread element
2991
+ */
2316
2992
  walkSpreadElement(expression) {
2317
2993
  if (expression.argument) {
2318
2994
  this.walkExpression(expression.argument);
2319
2995
  }
2320
2996
  }
2321
2997
 
2998
+ /**
2999
+ * @param {ObjectExpression} expression object expression
3000
+ */
2322
3001
  walkObjectExpression(expression) {
2323
3002
  for (
2324
3003
  let propIndex = 0, len = expression.properties.length;
@@ -2330,6 +3009,9 @@ class JavascriptParser extends Parser {
2330
3009
  }
2331
3010
  }
2332
3011
 
3012
+ /**
3013
+ * @param {Property | SpreadElement} prop property or spread element
3014
+ */
2333
3015
  walkProperty(prop) {
2334
3016
  if (prop.type === "SpreadElement") {
2335
3017
  this.walkExpression(prop.argument);
@@ -2347,14 +3029,17 @@ class JavascriptParser extends Parser {
2347
3029
  }
2348
3030
  }
2349
3031
 
3032
+ /**
3033
+ * @param {FunctionExpression} expression arrow function expression
3034
+ */
2350
3035
  walkFunctionExpression(expression) {
2351
3036
  const wasTopLevel = this.scope.topLevelScope;
2352
3037
  this.scope.topLevelScope = false;
2353
- const scopeParams = expression.params;
3038
+ const scopeParams = [...expression.params];
2354
3039
 
2355
3040
  // Add function name in scope for recursive calls
2356
3041
  if (expression.id) {
2357
- scopeParams.push(expression.id.name);
3042
+ scopeParams.push(expression.id);
2358
3043
  }
2359
3044
 
2360
3045
  this.inFunctionScope(true, scopeParams, () => {
@@ -2374,6 +3059,9 @@ class JavascriptParser extends Parser {
2374
3059
  this.scope.topLevelScope = wasTopLevel;
2375
3060
  }
2376
3061
 
3062
+ /**
3063
+ * @param {ArrowFunctionExpression} expression arrow function expression
3064
+ */
2377
3065
  walkArrowFunctionExpression(expression) {
2378
3066
  const wasTopLevel = this.scope.topLevelScope;
2379
3067
  this.scope.topLevelScope = wasTopLevel ? "arrow" : false;
@@ -2395,7 +3083,7 @@ class JavascriptParser extends Parser {
2395
3083
  }
2396
3084
 
2397
3085
  /**
2398
- * @param {SequenceExpressionNode} expression the sequence
3086
+ * @param {SequenceExpression} expression the sequence
2399
3087
  */
2400
3088
  walkSequenceExpression(expression) {
2401
3089
  if (!expression.expressions) return;
@@ -2407,22 +3095,30 @@ class JavascriptParser extends Parser {
2407
3095
  (currentStatement.type === "ExpressionStatement" &&
2408
3096
  currentStatement.expression === expression)
2409
3097
  ) {
2410
- const old = this.statementPath.pop();
3098
+ const old = /** @type {StatementPathItem} */ (this.statementPath.pop());
3099
+ const prev = this.prevStatement;
2411
3100
  for (const expr of expression.expressions) {
2412
3101
  this.statementPath.push(expr);
2413
3102
  this.walkExpression(expr);
2414
- this.statementPath.pop();
3103
+ this.prevStatement = this.statementPath.pop();
2415
3104
  }
3105
+ this.prevStatement = prev;
2416
3106
  this.statementPath.push(old);
2417
3107
  } else {
2418
3108
  this.walkExpressions(expression.expressions);
2419
3109
  }
2420
3110
  }
2421
3111
 
3112
+ /**
3113
+ * @param {UpdateExpression} expression the update expression
3114
+ */
2422
3115
  walkUpdateExpression(expression) {
2423
3116
  this.walkExpression(expression.argument);
2424
3117
  }
2425
3118
 
3119
+ /**
3120
+ * @param {UnaryExpression} expression the unary expression
3121
+ */
2426
3122
  walkUnaryExpression(expression) {
2427
3123
  if (expression.operator === "typeof") {
2428
3124
  const result = this.callHooksForExpression(
@@ -2443,52 +3139,65 @@ class JavascriptParser extends Parser {
2443
3139
  this.walkExpression(expression.argument);
2444
3140
  }
2445
3141
 
3142
+ /**
3143
+ * @param {LogicalExpression | BinaryExpression} expression the expression
3144
+ */
2446
3145
  walkLeftRightExpression(expression) {
2447
3146
  this.walkExpression(expression.left);
2448
3147
  this.walkExpression(expression.right);
2449
3148
  }
2450
3149
 
3150
+ /**
3151
+ * @param {BinaryExpression} expression the binary expression
3152
+ */
2451
3153
  walkBinaryExpression(expression) {
2452
- this.walkLeftRightExpression(expression);
3154
+ if (this.hooks.binaryExpression.call(expression) === undefined) {
3155
+ this.walkLeftRightExpression(expression);
3156
+ }
2453
3157
  }
2454
3158
 
3159
+ /**
3160
+ * @param {LogicalExpression} expression the logical expression
3161
+ */
2455
3162
  walkLogicalExpression(expression) {
2456
3163
  const result = this.hooks.expressionLogicalOperator.call(expression);
2457
3164
  if (result === undefined) {
2458
3165
  this.walkLeftRightExpression(expression);
2459
- } else {
2460
- if (result) {
2461
- this.walkExpression(expression.right);
2462
- }
3166
+ } else if (result) {
3167
+ this.walkExpression(expression.right);
2463
3168
  }
2464
3169
  }
2465
3170
 
3171
+ /**
3172
+ * @param {AssignmentExpression} expression assignment expression
3173
+ */
2466
3174
  walkAssignmentExpression(expression) {
2467
3175
  if (expression.left.type === "Identifier") {
2468
3176
  const renameIdentifier = this.getRenameIdentifier(expression.right);
2469
- if (renameIdentifier) {
3177
+ if (
3178
+ renameIdentifier &&
3179
+ this.callHooksForInfo(
3180
+ this.hooks.canRename,
3181
+ renameIdentifier,
3182
+ expression.right
3183
+ )
3184
+ ) {
3185
+ // renaming "a = b;"
2470
3186
  if (
2471
- this.callHooksForInfo(
2472
- this.hooks.canRename,
3187
+ !this.callHooksForInfo(
3188
+ this.hooks.rename,
2473
3189
  renameIdentifier,
2474
3190
  expression.right
2475
3191
  )
2476
3192
  ) {
2477
- // renaming "a = b;"
2478
- if (
2479
- !this.callHooksForInfo(
2480
- this.hooks.rename,
2481
- renameIdentifier,
2482
- expression.right
2483
- )
2484
- ) {
2485
- this.setVariable(
2486
- expression.left.name,
2487
- this.getVariableInfo(renameIdentifier)
2488
- );
2489
- }
2490
- return;
3193
+ this.setVariable(
3194
+ expression.left.name,
3195
+ typeof renameIdentifier === "string"
3196
+ ? this.getVariableInfo(renameIdentifier)
3197
+ : renameIdentifier
3198
+ );
2491
3199
  }
3200
+ return;
2492
3201
  }
2493
3202
  this.walkExpression(expression.right);
2494
3203
  this.enterPattern(expression.left, (name, decl) => {
@@ -2511,17 +3220,16 @@ class JavascriptParser extends Parser {
2511
3220
  expression.left,
2512
3221
  ALLOWED_MEMBER_TYPES_EXPRESSION
2513
3222
  );
2514
- if (exprName) {
2515
- if (
2516
- this.callHooksForInfo(
2517
- this.hooks.assignMemberChain,
2518
- exprName.rootInfo,
2519
- expression,
2520
- exprName.getMembers()
2521
- )
2522
- ) {
2523
- return;
2524
- }
3223
+ if (
3224
+ exprName &&
3225
+ this.callHooksForInfo(
3226
+ this.hooks.assignMemberChain,
3227
+ exprName.rootInfo,
3228
+ expression,
3229
+ exprName.getMembers()
3230
+ )
3231
+ ) {
3232
+ return;
2525
3233
  }
2526
3234
  this.walkExpression(expression.right);
2527
3235
  this.walkExpression(expression.left);
@@ -2531,6 +3239,9 @@ class JavascriptParser extends Parser {
2531
3239
  }
2532
3240
  }
2533
3241
 
3242
+ /**
3243
+ * @param {ConditionalExpression} expression conditional expression
3244
+ */
2534
3245
  walkConditionalExpression(expression) {
2535
3246
  const result = this.hooks.expressionConditionalOperator.call(expression);
2536
3247
  if (result === undefined) {
@@ -2539,15 +3250,16 @@ class JavascriptParser extends Parser {
2539
3250
  if (expression.alternate) {
2540
3251
  this.walkExpression(expression.alternate);
2541
3252
  }
2542
- } else {
2543
- if (result) {
2544
- this.walkExpression(expression.consequent);
2545
- } else if (expression.alternate) {
2546
- this.walkExpression(expression.alternate);
2547
- }
3253
+ } else if (result) {
3254
+ this.walkExpression(expression.consequent);
3255
+ } else if (expression.alternate) {
3256
+ this.walkExpression(expression.alternate);
2548
3257
  }
2549
3258
  }
2550
3259
 
3260
+ /**
3261
+ * @param {NewExpression} expression new expression
3262
+ */
2551
3263
  walkNewExpression(expression) {
2552
3264
  const result = this.callHooksForExpression(
2553
3265
  this.hooks.new,
@@ -2561,33 +3273,47 @@ class JavascriptParser extends Parser {
2561
3273
  }
2562
3274
  }
2563
3275
 
3276
+ /**
3277
+ * @param {YieldExpression} expression yield expression
3278
+ */
2564
3279
  walkYieldExpression(expression) {
2565
3280
  if (expression.argument) {
2566
3281
  this.walkExpression(expression.argument);
2567
3282
  }
2568
3283
  }
2569
3284
 
3285
+ /**
3286
+ * @param {TemplateLiteral} expression template literal
3287
+ */
2570
3288
  walkTemplateLiteral(expression) {
2571
3289
  if (expression.expressions) {
2572
3290
  this.walkExpressions(expression.expressions);
2573
3291
  }
2574
3292
  }
2575
3293
 
3294
+ /**
3295
+ * @param {TaggedTemplateExpression} expression tagged template expression
3296
+ */
2576
3297
  walkTaggedTemplateExpression(expression) {
2577
3298
  if (expression.tag) {
3299
+ this.scope.inTaggedTemplateTag = true;
2578
3300
  this.walkExpression(expression.tag);
3301
+ this.scope.inTaggedTemplateTag = false;
2579
3302
  }
2580
3303
  if (expression.quasi && expression.quasi.expressions) {
2581
3304
  this.walkExpressions(expression.quasi.expressions);
2582
3305
  }
2583
3306
  }
2584
3307
 
3308
+ /**
3309
+ * @param {ClassExpression} expression the class expression
3310
+ */
2585
3311
  walkClassExpression(expression) {
2586
3312
  this.walkClass(expression);
2587
3313
  }
2588
3314
 
2589
3315
  /**
2590
- * @param {ChainExpressionNode} expression expression
3316
+ * @param {ChainExpression} expression expression
2591
3317
  */
2592
3318
  walkChainExpression(expression) {
2593
3319
  const result = this.hooks.optionalChaining.call(expression);
@@ -2601,27 +3327,33 @@ class JavascriptParser extends Parser {
2601
3327
  }
2602
3328
  }
2603
3329
 
3330
+ /**
3331
+ * @private
3332
+ * @param {FunctionExpression | ArrowFunctionExpression} functionExpression function expression
3333
+ * @param {(Expression | SpreadElement)[]} options options
3334
+ * @param {Expression | SpreadElement | null} currentThis current this
3335
+ */
2604
3336
  _walkIIFE(functionExpression, options, currentThis) {
3337
+ /**
3338
+ * @param {Expression | SpreadElement} argOrThis arg or this
3339
+ * @returns {string | VariableInfoInterface | undefined} var info
3340
+ */
2605
3341
  const getVarInfo = argOrThis => {
2606
- const renameIdentifier = this.getRenameIdentifier(argOrThis);
2607
- if (renameIdentifier) {
2608
- if (
2609
- this.callHooksForInfo(
2610
- this.hooks.canRename,
2611
- renameIdentifier,
2612
- argOrThis
2613
- )
2614
- ) {
2615
- if (
2616
- !this.callHooksForInfo(
2617
- this.hooks.rename,
2618
- renameIdentifier,
2619
- argOrThis
2620
- )
2621
- ) {
2622
- return this.getVariableInfo(renameIdentifier);
2623
- }
2624
- }
3342
+ const renameIdentifier = this.getRenameIdentifier(
3343
+ /** @type {Expression} */ (argOrThis)
3344
+ );
3345
+ if (
3346
+ renameIdentifier &&
3347
+ this.callHooksForInfo(
3348
+ this.hooks.canRename,
3349
+ renameIdentifier,
3350
+ argOrThis
3351
+ ) &&
3352
+ !this.callHooksForInfo(this.hooks.rename, renameIdentifier, argOrThis)
3353
+ ) {
3354
+ return typeof renameIdentifier === "string"
3355
+ ? /** @type {string} */ (this.getVariableInfo(renameIdentifier))
3356
+ : renameIdentifier;
2625
3357
  }
2626
3358
  this.walkExpression(argOrThis);
2627
3359
  };
@@ -2631,12 +3363,15 @@ class JavascriptParser extends Parser {
2631
3363
  const varInfoForArgs = options.map(getVarInfo);
2632
3364
  const wasTopLevel = this.scope.topLevelScope;
2633
3365
  this.scope.topLevelScope = wasTopLevel && arrow ? "arrow" : false;
2634
- const scopeParams = params.filter(
2635
- (identifier, idx) => !varInfoForArgs[idx]
2636
- );
3366
+ const scopeParams =
3367
+ /** @type {(Identifier | string)[]} */
3368
+ (params.filter((identifier, idx) => !varInfoForArgs[idx]));
2637
3369
 
2638
3370
  // Add function name in scope for recursive calls
2639
- if (functionExpression.id) {
3371
+ if (
3372
+ functionExpression.type === "FunctionExpression" &&
3373
+ functionExpression.id
3374
+ ) {
2640
3375
  scopeParams.push(functionExpression.id.name);
2641
3376
  }
2642
3377
 
@@ -2648,7 +3383,7 @@ class JavascriptParser extends Parser {
2648
3383
  const varInfo = varInfoForArgs[i];
2649
3384
  if (!varInfo) continue;
2650
3385
  if (!params[i] || params[i].type !== "Identifier") continue;
2651
- this.setVariable(params[i].name, varInfo);
3386
+ this.setVariable(/** @type {Identifier} */ (params[i]).name, varInfo);
2652
3387
  }
2653
3388
  if (functionExpression.body.type === "BlockStatement") {
2654
3389
  this.detectMode(functionExpression.body.body);
@@ -2663,29 +3398,40 @@ class JavascriptParser extends Parser {
2663
3398
  this.scope.topLevelScope = wasTopLevel;
2664
3399
  }
2665
3400
 
3401
+ /**
3402
+ * @param {ImportExpression} expression import expression
3403
+ */
2666
3404
  walkImportExpression(expression) {
2667
- let result = this.hooks.importCall.call(expression);
3405
+ const result = this.hooks.importCall.call(expression);
2668
3406
  if (result === true) return;
2669
3407
 
2670
3408
  this.walkExpression(expression.source);
2671
3409
  }
2672
3410
 
3411
+ /**
3412
+ * @param {CallExpression} expression expression
3413
+ */
2673
3414
  walkCallExpression(expression) {
2674
- const isSimpleFunction = fn => {
2675
- return fn.params.every(p => p.type === "Identifier");
2676
- };
3415
+ const isSimpleFunction = fn =>
3416
+ fn.params.every(p => p.type === "Identifier");
2677
3417
  if (
2678
3418
  expression.callee.type === "MemberExpression" &&
2679
3419
  expression.callee.object.type.endsWith("FunctionExpression") &&
2680
3420
  !expression.callee.computed &&
3421
+ // eslint-disable-next-line no-warning-comments
3422
+ // @ts-ignore
3423
+ // TODO check me and handle more cases
2681
3424
  (expression.callee.property.name === "call" ||
3425
+ // eslint-disable-next-line no-warning-comments
3426
+ // @ts-ignore
2682
3427
  expression.callee.property.name === "bind") &&
2683
3428
  expression.arguments.length > 0 &&
2684
3429
  isSimpleFunction(expression.callee.object)
2685
3430
  ) {
2686
3431
  // (function(…) { }.call/bind(?, …))
2687
3432
  this._walkIIFE(
2688
- expression.callee.object,
3433
+ /** @type {FunctionExpression | ArrowFunctionExpression} */
3434
+ (expression.callee.object),
2689
3435
  expression.arguments.slice(1),
2690
3436
  expression.arguments[0]
2691
3437
  );
@@ -2694,7 +3440,12 @@ class JavascriptParser extends Parser {
2694
3440
  isSimpleFunction(expression.callee)
2695
3441
  ) {
2696
3442
  // (function(…) { }(…))
2697
- this._walkIIFE(expression.callee, expression.arguments, null);
3443
+ this._walkIIFE(
3444
+ /** @type {FunctionExpression | ArrowFunctionExpression} */
3445
+ (expression.callee),
3446
+ expression.arguments,
3447
+ null
3448
+ );
2698
3449
  } else {
2699
3450
  if (expression.callee.type === "MemberExpression") {
2700
3451
  const exprInfo = this.getMemberExpressionInfo(
@@ -2708,18 +3459,25 @@ class JavascriptParser extends Parser {
2708
3459
  expression,
2709
3460
  exprInfo.getCalleeMembers(),
2710
3461
  exprInfo.call,
2711
- exprInfo.getMembers()
3462
+ exprInfo.getMembers(),
3463
+ exprInfo.getMemberRanges()
2712
3464
  );
2713
3465
  if (result === true) return;
2714
3466
  }
2715
3467
  }
2716
- const callee = this.evaluateExpression(expression.callee);
3468
+ const callee = this.evaluateExpression(
3469
+ /** @type {TODO} */ (expression.callee)
3470
+ );
2717
3471
  if (callee.isIdentifier()) {
2718
3472
  const result1 = this.callHooksForInfo(
2719
3473
  this.hooks.callMemberChain,
2720
3474
  callee.rootInfo,
2721
3475
  expression,
2722
- callee.getMembers()
3476
+ callee.getMembers(),
3477
+ callee.getMembersOptionals
3478
+ ? callee.getMembersOptionals()
3479
+ : callee.getMembers().map(() => false),
3480
+ callee.getMemberRanges ? callee.getMemberRanges() : []
2723
3481
  );
2724
3482
  if (result1 === true) return;
2725
3483
  const result2 = this.callHooksForInfo(
@@ -2744,6 +3502,9 @@ class JavascriptParser extends Parser {
2744
3502
  }
2745
3503
  }
2746
3504
 
3505
+ /**
3506
+ * @param {MemberExpression} expression member expression
3507
+ */
2747
3508
  walkMemberExpression(expression) {
2748
3509
  const exprInfo = this.getMemberExpressionInfo(
2749
3510
  expression,
@@ -2759,11 +3520,15 @@ class JavascriptParser extends Parser {
2759
3520
  );
2760
3521
  if (result1 === true) return;
2761
3522
  const members = exprInfo.getMembers();
3523
+ const membersOptionals = exprInfo.getMembersOptionals();
3524
+ const memberRanges = exprInfo.getMemberRanges();
2762
3525
  const result2 = this.callHooksForInfo(
2763
3526
  this.hooks.expressionMemberChain,
2764
3527
  exprInfo.rootInfo,
2765
3528
  expression,
2766
- members
3529
+ members,
3530
+ membersOptionals,
3531
+ memberRanges
2767
3532
  );
2768
3533
  if (result2 === true) return;
2769
3534
  this.walkMemberExpressionWithExpressionName(
@@ -2788,7 +3553,8 @@ class JavascriptParser extends Parser {
2788
3553
  expression,
2789
3554
  exprInfo.getCalleeMembers(),
2790
3555
  exprInfo.call,
2791
- exprInfo.getMembers()
3556
+ exprInfo.getMembers(),
3557
+ exprInfo.getMemberRanges()
2792
3558
  );
2793
3559
  if (result === true) return;
2794
3560
  // Fast skip over the member chain as we already called memberChainOfCallMemberChain
@@ -2802,6 +3568,13 @@ class JavascriptParser extends Parser {
2802
3568
  if (expression.computed === true) this.walkExpression(expression.property);
2803
3569
  }
2804
3570
 
3571
+ /**
3572
+ * @param {TODO} expression member expression
3573
+ * @param {string} name name
3574
+ * @param {string | VariableInfo} rootInfo root info
3575
+ * @param {string[]} members members
3576
+ * @param {TODO} onUnhandled on unhandled callback
3577
+ */
2805
3578
  walkMemberExpressionWithExpressionName(
2806
3579
  expression,
2807
3580
  name,
@@ -2835,21 +3608,35 @@ class JavascriptParser extends Parser {
2835
3608
  if (expression.computed === true) this.walkExpression(expression.property);
2836
3609
  }
2837
3610
 
3611
+ /**
3612
+ * @param {ThisExpression} expression this expression
3613
+ */
2838
3614
  walkThisExpression(expression) {
2839
3615
  this.callHooksForName(this.hooks.expression, "this", expression);
2840
3616
  }
2841
3617
 
3618
+ /**
3619
+ * @param {Identifier} expression identifier
3620
+ */
2842
3621
  walkIdentifier(expression) {
2843
3622
  this.callHooksForName(this.hooks.expression, expression.name, expression);
2844
3623
  }
2845
3624
 
2846
3625
  /**
2847
- * @param {MetaPropertyNode} metaProperty meta property
3626
+ * @param {MetaProperty} metaProperty meta property
2848
3627
  */
2849
3628
  walkMetaProperty(metaProperty) {
2850
3629
  this.hooks.expression.for(getRootName(metaProperty)).call(metaProperty);
2851
3630
  }
2852
3631
 
3632
+ /**
3633
+ * @template T
3634
+ * @template R
3635
+ * @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
3636
+ * @param {TODO} expr expression
3637
+ * @param {AsArray<T>} args args for the hook
3638
+ * @returns {R | undefined} result of hook
3639
+ */
2853
3640
  callHooksForExpression(hookMap, expr, ...args) {
2854
3641
  return this.callHooksForExpressionWithFallback(
2855
3642
  hookMap,
@@ -2864,11 +3651,11 @@ class JavascriptParser extends Parser {
2864
3651
  * @template T
2865
3652
  * @template R
2866
3653
  * @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
2867
- * @param {MemberExpressionNode} expr expression info
2868
- * @param {function(string, string | ScopeInfo | VariableInfo, function(): string[]): any} fallback callback when variable in not handled by hooks
2869
- * @param {function(string): any} defined callback when variable is defined
3654
+ * @param {MemberExpression} expr expression info
3655
+ * @param {(function(string, string | ScopeInfo | VariableInfo, function(): string[]): any) | undefined} fallback callback when variable in not handled by hooks
3656
+ * @param {(function(string): any) | undefined} defined callback when variable is defined
2870
3657
  * @param {AsArray<T>} args args for the hook
2871
- * @returns {R} result of hook
3658
+ * @returns {R | undefined} result of hook
2872
3659
  */
2873
3660
  callHooksForExpressionWithFallback(
2874
3661
  hookMap,
@@ -2900,7 +3687,7 @@ class JavascriptParser extends Parser {
2900
3687
  * @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
2901
3688
  * @param {string} name key in map
2902
3689
  * @param {AsArray<T>} args args for the hook
2903
- * @returns {R} result of hook
3690
+ * @returns {R | undefined} result of hook
2904
3691
  */
2905
3692
  callHooksForName(hookMap, name, ...args) {
2906
3693
  return this.callHooksForNameWithFallback(
@@ -2918,7 +3705,7 @@ class JavascriptParser extends Parser {
2918
3705
  * @param {HookMap<SyncBailHook<T, R>>} hookMap hooks that should be called
2919
3706
  * @param {ExportedVariableInfo} info variable info
2920
3707
  * @param {AsArray<T>} args args for the hook
2921
- * @returns {R} result of hook
3708
+ * @returns {R | undefined} result of hook
2922
3709
  */
2923
3710
  callHooksForInfo(hookMap, info, ...args) {
2924
3711
  return this.callHooksForInfoWithFallback(
@@ -2935,10 +3722,10 @@ class JavascriptParser extends Parser {
2935
3722
  * @template R
2936
3723
  * @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
2937
3724
  * @param {ExportedVariableInfo} info variable info
2938
- * @param {function(string): any} fallback callback when variable in not handled by hooks
2939
- * @param {function(): any} defined callback when variable is defined
3725
+ * @param {(function(string): any) | undefined} fallback callback when variable in not handled by hooks
3726
+ * @param {(function(): any) | undefined} defined callback when variable is defined
2940
3727
  * @param {AsArray<T>} args args for the hook
2941
- * @returns {R} result of hook
3728
+ * @returns {R | undefined} result of hook
2942
3729
  */
2943
3730
  callHooksForInfoWithFallback(hookMap, info, fallback, defined, ...args) {
2944
3731
  let name;
@@ -2985,10 +3772,10 @@ class JavascriptParser extends Parser {
2985
3772
  * @template R
2986
3773
  * @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
2987
3774
  * @param {string} name key in map
2988
- * @param {function(string): any} fallback callback when variable in not handled by hooks
2989
- * @param {function(): any} defined callback when variable is defined
3775
+ * @param {(function(string): any) | undefined} fallback callback when variable in not handled by hooks
3776
+ * @param {(function(): any) | undefined} defined callback when variable is defined
2990
3777
  * @param {AsArray<T>} args args for the hook
2991
- * @returns {R} result of hook
3778
+ * @returns {R | undefined} result of hook
2992
3779
  */
2993
3780
  callHooksForNameWithFallback(hookMap, name, fallback, defined, ...args) {
2994
3781
  return this.callHooksForInfoWithFallback(
@@ -3012,6 +3799,7 @@ class JavascriptParser extends Parser {
3012
3799
  topLevelScope: oldScope.topLevelScope,
3013
3800
  inTry: false,
3014
3801
  inShorthand: false,
3802
+ inTaggedTemplateTag: false,
3015
3803
  isStrict: oldScope.isStrict,
3016
3804
  isAsmJs: oldScope.isAsmJs,
3017
3805
  definitions: oldScope.definitions.createChild()
@@ -3028,12 +3816,50 @@ class JavascriptParser extends Parser {
3028
3816
  this.scope = oldScope;
3029
3817
  }
3030
3818
 
3819
+ /**
3820
+ * @param {boolean} hasThis true, when this is defined
3821
+ * @param {any} params scope params
3822
+ * @param {function(): void} fn inner function
3823
+ * @returns {void}
3824
+ */
3825
+ inClassScope(hasThis, params, fn) {
3826
+ const oldScope = this.scope;
3827
+ this.scope = {
3828
+ topLevelScope: oldScope.topLevelScope,
3829
+ inTry: false,
3830
+ inShorthand: false,
3831
+ inTaggedTemplateTag: false,
3832
+ isStrict: oldScope.isStrict,
3833
+ isAsmJs: oldScope.isAsmJs,
3834
+ definitions: oldScope.definitions.createChild()
3835
+ };
3836
+
3837
+ if (hasThis) {
3838
+ this.undefineVariable("this");
3839
+ }
3840
+
3841
+ this.enterPatterns(params, (ident, pattern) => {
3842
+ this.defineVariable(ident);
3843
+ });
3844
+
3845
+ fn();
3846
+
3847
+ this.scope = oldScope;
3848
+ }
3849
+
3850
+ /**
3851
+ * @param {boolean} hasThis true, when this is defined
3852
+ * @param {any} params scope params
3853
+ * @param {function(): void} fn inner function
3854
+ * @returns {void}
3855
+ */
3031
3856
  inFunctionScope(hasThis, params, fn) {
3032
3857
  const oldScope = this.scope;
3033
3858
  this.scope = {
3034
3859
  topLevelScope: oldScope.topLevelScope,
3035
3860
  inTry: false,
3036
3861
  inShorthand: false,
3862
+ inTaggedTemplateTag: false,
3037
3863
  isStrict: oldScope.isStrict,
3038
3864
  isAsmJs: oldScope.isAsmJs,
3039
3865
  definitions: oldScope.definitions.createChild()
@@ -3052,12 +3878,17 @@ class JavascriptParser extends Parser {
3052
3878
  this.scope = oldScope;
3053
3879
  }
3054
3880
 
3881
+ /**
3882
+ * @param {function(): void} fn inner function
3883
+ * @returns {void}
3884
+ */
3055
3885
  inBlockScope(fn) {
3056
3886
  const oldScope = this.scope;
3057
3887
  this.scope = {
3058
3888
  topLevelScope: oldScope.topLevelScope,
3059
3889
  inTry: oldScope.inTry,
3060
3890
  inShorthand: false,
3891
+ inTaggedTemplateTag: false,
3061
3892
  isStrict: oldScope.isStrict,
3062
3893
  isAsmJs: oldScope.isAsmJs,
3063
3894
  definitions: oldScope.definitions.createChild()
@@ -3068,19 +3899,36 @@ class JavascriptParser extends Parser {
3068
3899
  this.scope = oldScope;
3069
3900
  }
3070
3901
 
3902
+ /**
3903
+ * @param {Array<Directive | Statement | ModuleDeclaration>} statements statements
3904
+ */
3071
3905
  detectMode(statements) {
3072
3906
  const isLiteral =
3073
3907
  statements.length >= 1 &&
3074
3908
  statements[0].type === "ExpressionStatement" &&
3075
3909
  statements[0].expression.type === "Literal";
3076
- if (isLiteral && statements[0].expression.value === "use strict") {
3910
+ if (
3911
+ isLiteral &&
3912
+ /** @type {Literal} */
3913
+ (/** @type {ExpressionStatement} */ (statements[0]).expression).value ===
3914
+ "use strict"
3915
+ ) {
3077
3916
  this.scope.isStrict = true;
3078
3917
  }
3079
- if (isLiteral && statements[0].expression.value === "use asm") {
3918
+ if (
3919
+ isLiteral &&
3920
+ /** @type {Literal} */
3921
+ (/** @type {ExpressionStatement} */ (statements[0]).expression).value ===
3922
+ "use asm"
3923
+ ) {
3080
3924
  this.scope.isAsmJs = true;
3081
3925
  }
3082
3926
  }
3083
3927
 
3928
+ /**
3929
+ * @param {(string | Pattern | Property)[]} patterns patterns
3930
+ * @param {OnIdent} onIdent on ident callback
3931
+ */
3084
3932
  enterPatterns(patterns, onIdent) {
3085
3933
  for (const pattern of patterns) {
3086
3934
  if (typeof pattern !== "string") {
@@ -3091,6 +3939,10 @@ class JavascriptParser extends Parser {
3091
3939
  }
3092
3940
  }
3093
3941
 
3942
+ /**
3943
+ * @param {Pattern | Property} pattern pattern
3944
+ * @param {OnIdent} onIdent on ident callback
3945
+ */
3094
3946
  enterPattern(pattern, onIdent) {
3095
3947
  if (!pattern) return;
3096
3948
  switch (pattern.type) {
@@ -3115,18 +3967,26 @@ class JavascriptParser extends Parser {
3115
3967
  this.enterIdentifier(pattern.value, onIdent);
3116
3968
  this.scope.inShorthand = false;
3117
3969
  } else {
3118
- this.enterPattern(pattern.value, onIdent);
3970
+ this.enterPattern(/** @type {Identifier} */ (pattern.value), onIdent);
3119
3971
  }
3120
3972
  break;
3121
3973
  }
3122
3974
  }
3123
3975
 
3976
+ /**
3977
+ * @param {Identifier} pattern identifier pattern
3978
+ * @param {OnIdent} onIdent callback
3979
+ */
3124
3980
  enterIdentifier(pattern, onIdent) {
3125
3981
  if (!this.callHooksForName(this.hooks.pattern, pattern.name, pattern)) {
3126
3982
  onIdent(pattern.name, pattern);
3127
3983
  }
3128
3984
  }
3129
3985
 
3986
+ /**
3987
+ * @param {ObjectPattern} pattern object pattern
3988
+ * @param {OnIdent} onIdent callback
3989
+ */
3130
3990
  enterObjectPattern(pattern, onIdent) {
3131
3991
  for (
3132
3992
  let propIndex = 0, len = pattern.properties.length;
@@ -3138,6 +3998,10 @@ class JavascriptParser extends Parser {
3138
3998
  }
3139
3999
  }
3140
4000
 
4001
+ /**
4002
+ * @param {ArrayPattern} pattern object pattern
4003
+ * @param {OnIdent} onIdent callback
4004
+ */
3141
4005
  enterArrayPattern(pattern, onIdent) {
3142
4006
  for (
3143
4007
  let elementIndex = 0, len = pattern.elements.length;
@@ -3145,43 +4009,56 @@ class JavascriptParser extends Parser {
3145
4009
  elementIndex++
3146
4010
  ) {
3147
4011
  const element = pattern.elements[elementIndex];
3148
- this.enterPattern(element, onIdent);
4012
+
4013
+ if (element) {
4014
+ this.enterPattern(element, onIdent);
4015
+ }
3149
4016
  }
3150
4017
  }
3151
4018
 
4019
+ /**
4020
+ * @param {RestElement} pattern object pattern
4021
+ * @param {OnIdent} onIdent callback
4022
+ */
3152
4023
  enterRestElement(pattern, onIdent) {
3153
4024
  this.enterPattern(pattern.argument, onIdent);
3154
4025
  }
3155
4026
 
4027
+ /**
4028
+ * @param {AssignmentPattern} pattern object pattern
4029
+ * @param {OnIdent} onIdent callback
4030
+ */
3156
4031
  enterAssignmentPattern(pattern, onIdent) {
3157
4032
  this.enterPattern(pattern.left, onIdent);
3158
4033
  }
3159
4034
 
3160
4035
  /**
3161
- * @param {ExpressionNode} expression expression node
3162
- * @returns {BasicEvaluatedExpression | undefined} evaluation result
4036
+ * @param {Expression | SpreadElement} expression expression node
4037
+ * @returns {BasicEvaluatedExpression} evaluation result
3163
4038
  */
3164
4039
  evaluateExpression(expression) {
3165
4040
  try {
3166
4041
  const hook = this.hooks.evaluate.get(expression.type);
3167
4042
  if (hook !== undefined) {
3168
4043
  const result = hook.call(expression);
3169
- if (result !== undefined) {
3170
- if (result) {
3171
- result.setExpression(expression);
3172
- }
4044
+ if (result !== undefined && result !== null) {
4045
+ result.setExpression(expression);
3173
4046
  return result;
3174
4047
  }
3175
4048
  }
3176
- } catch (e) {
3177
- console.warn(e);
4049
+ } catch (err) {
4050
+ console.warn(err);
3178
4051
  // ignore error
3179
4052
  }
3180
4053
  return new BasicEvaluatedExpression()
3181
- .setRange(expression.range)
4054
+ .setRange(/** @type {Range} */ (expression.range))
3182
4055
  .setExpression(expression);
3183
4056
  }
3184
4057
 
4058
+ /**
4059
+ * @param {Expression} expression expression
4060
+ * @returns {string} parsed string
4061
+ */
3185
4062
  parseString(expression) {
3186
4063
  switch (expression.type) {
3187
4064
  case "BinaryExpression":
@@ -3193,13 +4070,17 @@ class JavascriptParser extends Parser {
3193
4070
  }
3194
4071
  break;
3195
4072
  case "Literal":
3196
- return expression.value + "";
4073
+ return String(expression.value);
3197
4074
  }
3198
4075
  throw new Error(
3199
- expression.type + " is not supported as parameter for require"
4076
+ `${expression.type} is not supported as parameter for require`
3200
4077
  );
3201
4078
  }
3202
4079
 
4080
+ /**
4081
+ * @param {Expression} expression expression
4082
+ * @returns {TODO} result
4083
+ */
3203
4084
  parseCalculatedString(expression) {
3204
4085
  switch (expression.type) {
3205
4086
  case "BinaryExpression":
@@ -3223,14 +4104,13 @@ class JavascriptParser extends Parser {
3223
4104
  code: true,
3224
4105
  conditional: false
3225
4106
  };
3226
- } else {
3227
- return {
3228
- range: [left.range[0], right.range[1]],
3229
- value: left.value + right.value,
3230
- code: false,
3231
- conditional: false
3232
- };
3233
4107
  }
4108
+ return {
4109
+ range: [left.range[0], right.range[1]],
4110
+ value: left.value + right.value,
4111
+ code: false,
4112
+ conditional: false
4113
+ };
3234
4114
  }
3235
4115
  break;
3236
4116
  case "ConditionalExpression": {
@@ -3261,7 +4141,7 @@ class JavascriptParser extends Parser {
3261
4141
  case "Literal":
3262
4142
  return {
3263
4143
  range: expression.range,
3264
- value: expression.value + "",
4144
+ value: String(expression.value),
3265
4145
  code: false,
3266
4146
  conditional: false
3267
4147
  };
@@ -3290,7 +4170,7 @@ class JavascriptParser extends Parser {
3290
4170
  source = source.toString("utf-8");
3291
4171
  }
3292
4172
  if (typeof source === "object") {
3293
- ast = /** @type {ProgramNode} */ (source);
4173
+ ast = /** @type {Program} */ (source);
3294
4174
  comments = source.comments;
3295
4175
  } else {
3296
4176
  comments = [];
@@ -3311,6 +4191,7 @@ class JavascriptParser extends Parser {
3311
4191
  topLevelScope: true,
3312
4192
  inTry: false,
3313
4193
  inShorthand: false,
4194
+ inTaggedTemplateTag: false,
3314
4195
  isStrict: false,
3315
4196
  isAsmJs: false,
3316
4197
  definitions: new StackedMap()
@@ -3322,12 +4203,14 @@ class JavascriptParser extends Parser {
3322
4203
  this.statementPath = [];
3323
4204
  this.prevStatement = undefined;
3324
4205
  if (this.hooks.program.call(ast, comments) === undefined) {
4206
+ this.destructuringAssignmentProperties = new WeakMap();
3325
4207
  this.detectMode(ast.body);
3326
4208
  this.preWalkStatements(ast.body);
3327
4209
  this.prevStatement = undefined;
3328
4210
  this.blockPreWalkStatements(ast.body);
3329
4211
  this.prevStatement = undefined;
3330
4212
  this.walkStatements(ast.body);
4213
+ this.destructuringAssignmentProperties = undefined;
3331
4214
  }
3332
4215
  this.hooks.finish.call(ast, comments);
3333
4216
  this.scope = oldScope;
@@ -3340,8 +4223,12 @@ class JavascriptParser extends Parser {
3340
4223
  return state;
3341
4224
  }
3342
4225
 
4226
+ /**
4227
+ * @param {string} source source code
4228
+ * @returns {BasicEvaluatedExpression} evaluation result
4229
+ */
3343
4230
  evaluate(source) {
3344
- const ast = JavascriptParser._parse("(" + source + ")", {
4231
+ const ast = JavascriptParser._parse(`(${source})`, {
3345
4232
  sourceType: this.sourceType,
3346
4233
  locations: false
3347
4234
  });
@@ -3352,7 +4239,7 @@ class JavascriptParser extends Parser {
3352
4239
  }
3353
4240
 
3354
4241
  /**
3355
- * @param {ExpressionNode | DeclarationNode | PrivateIdentifierNode | null | undefined} expr an expression
4242
+ * @param {Expression | Declaration | PrivateIdentifier | null | undefined} expr an expression
3356
4243
  * @param {number} commentsStartPos source position from which annotation comments are checked
3357
4244
  * @returns {boolean} true, when the expression is pure
3358
4245
  */
@@ -3363,70 +4250,113 @@ class JavascriptParser extends Parser {
3363
4250
  .call(expr, commentsStartPos);
3364
4251
  if (typeof result === "boolean") return result;
3365
4252
  switch (expr.type) {
4253
+ // TODO handle more cases
3366
4254
  case "ClassDeclaration":
3367
4255
  case "ClassExpression": {
3368
4256
  if (expr.body.type !== "ClassBody") return false;
3369
- if (expr.superClass && !this.isPure(expr.superClass, expr.range[0])) {
4257
+ if (
4258
+ expr.superClass &&
4259
+ !this.isPure(expr.superClass, /** @type {Range} */ (expr.range)[0])
4260
+ ) {
3370
4261
  return false;
3371
4262
  }
3372
4263
  const items =
3373
- /** @type {(MethodDefinitionNode | PropertyDefinitionNode)[]} */ (
3374
- expr.body.body
3375
- );
3376
- return items.every(
3377
- item =>
3378
- (!item.computed ||
3379
- !item.key ||
3380
- this.isPure(item.key, item.range[0])) &&
3381
- (!item.static ||
3382
- !item.value ||
3383
- this.isPure(
3384
- item.value,
3385
- item.key ? item.key.range[1] : item.range[0]
3386
- ))
3387
- );
4264
+ /** @type {TODO[]} */
4265
+ (expr.body.body);
4266
+ return items.every(item => {
4267
+ if (
4268
+ item.computed &&
4269
+ item.key &&
4270
+ !this.isPure(item.key, item.range[0])
4271
+ ) {
4272
+ return false;
4273
+ }
4274
+
4275
+ if (
4276
+ item.static &&
4277
+ item.value &&
4278
+ !this.isPure(
4279
+ item.value,
4280
+ item.key ? item.key.range[1] : item.range[0]
4281
+ )
4282
+ ) {
4283
+ return false;
4284
+ }
4285
+
4286
+ if (item.type === "StaticBlock") {
4287
+ return false;
4288
+ }
4289
+
4290
+ if (
4291
+ expr.superClass &&
4292
+ item.type === "MethodDefinition" &&
4293
+ item.kind === "constructor"
4294
+ ) {
4295
+ return false;
4296
+ }
4297
+
4298
+ return true;
4299
+ });
3388
4300
  }
3389
4301
 
3390
4302
  case "FunctionDeclaration":
3391
4303
  case "FunctionExpression":
3392
4304
  case "ArrowFunctionExpression":
4305
+ case "ThisExpression":
3393
4306
  case "Literal":
4307
+ case "TemplateLiteral":
4308
+ case "Identifier":
3394
4309
  case "PrivateIdentifier":
3395
4310
  return true;
3396
4311
 
3397
4312
  case "VariableDeclaration":
3398
4313
  return expr.declarations.every(decl =>
3399
- this.isPure(decl.init, decl.range[0])
4314
+ this.isPure(decl.init, /** @type {Range} */ (decl.range)[0])
3400
4315
  );
3401
4316
 
3402
4317
  case "ConditionalExpression":
3403
4318
  return (
3404
4319
  this.isPure(expr.test, commentsStartPos) &&
3405
- this.isPure(expr.consequent, expr.test.range[1]) &&
3406
- this.isPure(expr.alternate, expr.consequent.range[1])
4320
+ this.isPure(
4321
+ expr.consequent,
4322
+ /** @type {Range} */ (expr.test.range)[1]
4323
+ ) &&
4324
+ this.isPure(
4325
+ expr.alternate,
4326
+ /** @type {Range} */ (expr.consequent.range)[1]
4327
+ )
4328
+ );
4329
+
4330
+ case "LogicalExpression":
4331
+ return (
4332
+ this.isPure(expr.left, commentsStartPos) &&
4333
+ this.isPure(expr.right, /** @type {Range} */ (expr.left.range)[1])
3407
4334
  );
3408
4335
 
3409
4336
  case "SequenceExpression":
3410
4337
  return expr.expressions.every(expr => {
3411
4338
  const pureFlag = this.isPure(expr, commentsStartPos);
3412
- commentsStartPos = expr.range[1];
4339
+ commentsStartPos = /** @type {Range} */ (expr.range)[1];
3413
4340
  return pureFlag;
3414
4341
  });
3415
4342
 
3416
4343
  case "CallExpression": {
3417
4344
  const pureFlag =
3418
- expr.range[0] - commentsStartPos > 12 &&
3419
- this.getComments([commentsStartPos, expr.range[0]]).some(
4345
+ /** @type {Range} */ (expr.range)[0] - commentsStartPos > 12 &&
4346
+ this.getComments([
4347
+ commentsStartPos,
4348
+ /** @type {Range} */ (expr.range)[0]
4349
+ ]).some(
3420
4350
  comment =>
3421
4351
  comment.type === "Block" &&
3422
4352
  /^\s*(#|@)__PURE__\s*$/.test(comment.value)
3423
4353
  );
3424
4354
  if (!pureFlag) return false;
3425
- commentsStartPos = expr.callee.range[1];
4355
+ commentsStartPos = /** @type {Range} */ (expr.callee.range)[1];
3426
4356
  return expr.arguments.every(arg => {
3427
4357
  if (arg.type === "SpreadElement") return false;
3428
4358
  const pureFlag = this.isPure(arg, commentsStartPos);
3429
- commentsStartPos = arg.range[1];
4359
+ commentsStartPos = /** @type {Range} */ (arg.range)[1];
3430
4360
  return pureFlag;
3431
4361
  });
3432
4362
  }
@@ -3435,13 +4365,28 @@ class JavascriptParser extends Parser {
3435
4365
  return !evaluated.couldHaveSideEffects();
3436
4366
  }
3437
4367
 
4368
+ /**
4369
+ * @param {Range} range range
4370
+ * @returns {Comment[]} comments in the range
4371
+ */
3438
4372
  getComments(range) {
3439
4373
  const [rangeStart, rangeEnd] = range;
3440
- const compare = (comment, needle) => comment.range[0] - needle;
3441
- let idx = binarySearchBounds.ge(this.comments, rangeStart, compare);
3442
- let commentsInRange = [];
3443
- while (this.comments[idx] && this.comments[idx].range[1] <= rangeEnd) {
3444
- commentsInRange.push(this.comments[idx]);
4374
+ /**
4375
+ * @param {Comment} comment comment
4376
+ * @param {number} needle needle
4377
+ * @returns {number} compared
4378
+ */
4379
+ const compare = (comment, needle) =>
4380
+ /** @type {Range} */ (comment.range)[0] - needle;
4381
+ const comments = /** @type {Comment[]} */ (this.comments);
4382
+ let idx = binarySearchBounds.ge(comments, rangeStart, compare);
4383
+ /** @type {Comment[]} */
4384
+ const commentsInRange = [];
4385
+ while (
4386
+ comments[idx] &&
4387
+ /** @type {Range} */ (comments[idx].range)[1] <= rangeEnd
4388
+ ) {
4389
+ commentsInRange.push(comments[idx]);
3445
4390
  idx++;
3446
4391
  }
3447
4392
 
@@ -3457,25 +4402,40 @@ class JavascriptParser extends Parser {
3457
4402
  if (currentStatement === undefined) throw new Error("Not in statement");
3458
4403
  return (
3459
4404
  // Either asking directly for the end position of the current statement
3460
- (currentStatement.range[1] === pos && this.semicolons.has(pos)) ||
4405
+ (currentStatement.range[1] === pos &&
4406
+ /** @type {Set<number>} */ (this.semicolons).has(pos)) ||
3461
4407
  // Or asking for the start position of the current statement,
3462
4408
  // here we have to check multiple things
3463
4409
  (currentStatement.range[0] === pos &&
3464
4410
  // is there a previous statement which might be relevant?
3465
4411
  this.prevStatement !== undefined &&
3466
4412
  // is the end position of the previous statement an ASI position?
3467
- this.semicolons.has(this.prevStatement.range[1]))
4413
+ /** @type {Set<number>} */ (this.semicolons).has(
4414
+ this.prevStatement.range[1]
4415
+ ))
3468
4416
  );
3469
4417
  }
3470
4418
 
4419
+ /**
4420
+ * @param {number} pos source code position
4421
+ * @returns {void}
4422
+ */
4423
+ setAsiPosition(pos) {
4424
+ /** @type {Set<number>} */ (this.semicolons).add(pos);
4425
+ }
4426
+
3471
4427
  /**
3472
4428
  * @param {number} pos source code position
3473
4429
  * @returns {void}
3474
4430
  */
3475
4431
  unsetAsiPosition(pos) {
3476
- this.semicolons.delete(pos);
4432
+ /** @type {Set<number>} */ (this.semicolons).delete(pos);
3477
4433
  }
3478
4434
 
4435
+ /**
4436
+ * @param {Expression} expr expression
4437
+ * @returns {boolean} true, when the expression is a statement level expression
4438
+ */
3479
4439
  isStatementLevelExpression(expr) {
3480
4440
  const currentStatement = this.statementPath[this.statementPath.length - 1];
3481
4441
  return (
@@ -3485,6 +4445,11 @@ class JavascriptParser extends Parser {
3485
4445
  );
3486
4446
  }
3487
4447
 
4448
+ /**
4449
+ * @param {string} name name
4450
+ * @param {TODO} tag tag info
4451
+ * @returns {TODO} tag data
4452
+ */
3488
4453
  getTagData(name, tag) {
3489
4454
  const info = this.scope.definitions.get(name);
3490
4455
  if (info instanceof VariableInfo) {
@@ -3496,6 +4461,11 @@ class JavascriptParser extends Parser {
3496
4461
  }
3497
4462
  }
3498
4463
 
4464
+ /**
4465
+ * @param {string} name name
4466
+ * @param {TODO} tag tag info
4467
+ * @param {TODO=} data data
4468
+ */
3499
4469
  tagVariable(name, tag, data) {
3500
4470
  const oldInfo = this.scope.definitions.get(name);
3501
4471
  /** @type {VariableInfo} */
@@ -3522,6 +4492,9 @@ class JavascriptParser extends Parser {
3522
4492
  this.scope.definitions.set(name, newInfo);
3523
4493
  }
3524
4494
 
4495
+ /**
4496
+ * @param {string} name variable name
4497
+ */
3525
4498
  defineVariable(name) {
3526
4499
  const oldInfo = this.scope.definitions.get(name);
3527
4500
  // Don't redefine variable in same scope to keep existing tags
@@ -3530,10 +4503,17 @@ class JavascriptParser extends Parser {
3530
4503
  this.scope.definitions.set(name, this.scope);
3531
4504
  }
3532
4505
 
4506
+ /**
4507
+ * @param {string} name variable name
4508
+ */
3533
4509
  undefineVariable(name) {
3534
4510
  this.scope.definitions.delete(name);
3535
4511
  }
3536
4512
 
4513
+ /**
4514
+ * @param {string} name variable name
4515
+ * @returns {boolean} true, when variable is defined
4516
+ */
3537
4517
  isVariableDefined(name) {
3538
4518
  const info = this.scope.definitions.get(name);
3539
4519
  if (info === undefined) return false;
@@ -3545,20 +4525,19 @@ class JavascriptParser extends Parser {
3545
4525
 
3546
4526
  /**
3547
4527
  * @param {string} name variable name
3548
- * @returns {ExportedVariableInfo} info for this variable
4528
+ * @returns {string | ExportedVariableInfo} info for this variable
3549
4529
  */
3550
4530
  getVariableInfo(name) {
3551
4531
  const value = this.scope.definitions.get(name);
3552
4532
  if (value === undefined) {
3553
4533
  return name;
3554
- } else {
3555
- return value;
3556
4534
  }
4535
+ return value;
3557
4536
  }
3558
4537
 
3559
4538
  /**
3560
4539
  * @param {string} name variable name
3561
- * @param {ExportedVariableInfo} variableInfo new info for this variable
4540
+ * @param {string | ExportedVariableInfo} variableInfo new info for this variable
3562
4541
  * @returns {void}
3563
4542
  */
3564
4543
  setVariable(name, variableInfo) {
@@ -3576,23 +4555,50 @@ class JavascriptParser extends Parser {
3576
4555
  }
3577
4556
  }
3578
4557
 
4558
+ /**
4559
+ * @param {TagInfo} tagInfo tag info
4560
+ * @returns {VariableInfo} variable info
4561
+ */
4562
+ evaluatedVariable(tagInfo) {
4563
+ return new VariableInfo(this.scope, undefined, tagInfo);
4564
+ }
4565
+
4566
+ /**
4567
+ * @param {Range} range range of the comment
4568
+ * @returns {TODO} TODO
4569
+ */
3579
4570
  parseCommentOptions(range) {
3580
4571
  const comments = this.getComments(range);
3581
4572
  if (comments.length === 0) {
3582
4573
  return EMPTY_COMMENT_OPTIONS;
3583
4574
  }
3584
- let options = {};
3585
- let errors = [];
4575
+ const options = {};
4576
+ /** @type {unknown[]} */
4577
+ const errors = [];
3586
4578
  for (const comment of comments) {
3587
4579
  const { value } = comment;
3588
4580
  if (value && webpackCommentRegExp.test(value)) {
3589
4581
  // try compile only if webpack options comment is present
3590
4582
  try {
3591
- const val = vm.runInNewContext(`(function(){return {${value}};})()`);
3592
- Object.assign(options, val);
3593
- } catch (e) {
3594
- e.comment = comment;
3595
- errors.push(e);
4583
+ for (let [key, val] of Object.entries(
4584
+ vm.runInContext(
4585
+ `(function(){return {${value}};})()`,
4586
+ this.magicCommentContext
4587
+ )
4588
+ )) {
4589
+ if (typeof val === "object" && val !== null) {
4590
+ val =
4591
+ val.constructor.name === "RegExp"
4592
+ ? new RegExp(val)
4593
+ : JSON.parse(JSON.stringify(val));
4594
+ }
4595
+ options[key] = val;
4596
+ }
4597
+ } catch (err) {
4598
+ const newErr = new Error(String(err.message));
4599
+ newErr.stack = String(err.stack);
4600
+ Object.assign(newErr, { comment });
4601
+ errors.push(newErr);
3596
4602
  }
3597
4603
  }
3598
4604
  }
@@ -3600,61 +4606,69 @@ class JavascriptParser extends Parser {
3600
4606
  }
3601
4607
 
3602
4608
  /**
3603
- * @param {MemberExpressionNode} expression a member expression
3604
- * @returns {{ members: string[], object: ExpressionNode | SuperNode }} member names (reverse order) and remaining object
4609
+ * @param {MemberExpression} expression a member expression
4610
+ * @returns {{ members: string[], object: Expression | Super, membersOptionals: boolean[], memberRanges: Range[] }} member names (reverse order) and remaining object
3605
4611
  */
3606
4612
  extractMemberExpressionChain(expression) {
3607
4613
  /** @type {AnyNode} */
3608
4614
  let expr = expression;
3609
4615
  const members = [];
4616
+ const membersOptionals = [];
4617
+ const memberRanges = [];
3610
4618
  while (expr.type === "MemberExpression") {
3611
4619
  if (expr.computed) {
3612
4620
  if (expr.property.type !== "Literal") break;
3613
- members.push(`${expr.property.value}`);
4621
+ members.push(`${expr.property.value}`); // the literal
4622
+ memberRanges.push(/** @type {Range} */ (expr.object.range)); // the range of the expression fragment before the literal
3614
4623
  } else {
3615
4624
  if (expr.property.type !== "Identifier") break;
3616
- members.push(expr.property.name);
4625
+ members.push(expr.property.name); // the identifier
4626
+ memberRanges.push(/** @type {Range} */ (expr.object.range)); // the range of the expression fragment before the identifier
3617
4627
  }
4628
+ membersOptionals.push(expr.optional);
3618
4629
  expr = expr.object;
3619
4630
  }
4631
+
3620
4632
  return {
3621
4633
  members,
4634
+ membersOptionals,
4635
+ memberRanges,
3622
4636
  object: expr
3623
4637
  };
3624
4638
  }
3625
4639
 
3626
4640
  /**
3627
4641
  * @param {string} varName variable name
3628
- * @returns {{name: string, info: VariableInfo | string}} name of the free variable and variable info for that
4642
+ * @returns {{name: string, info: VariableInfo | string} | undefined} name of the free variable and variable info for that
3629
4643
  */
3630
4644
  getFreeInfoFromVariable(varName) {
3631
4645
  const info = this.getVariableInfo(varName);
3632
4646
  let name;
3633
4647
  if (info instanceof VariableInfo) {
3634
4648
  name = info.freeName;
3635
- if (typeof name !== "string") return undefined;
4649
+ if (typeof name !== "string") return;
3636
4650
  } else if (typeof info !== "string") {
3637
- return undefined;
4651
+ return;
3638
4652
  } else {
3639
4653
  name = info;
3640
4654
  }
3641
4655
  return { info, name };
3642
4656
  }
3643
4657
 
3644
- /** @typedef {{ type: "call", call: CallExpressionNode, calleeName: string, rootInfo: string | VariableInfo, getCalleeMembers: () => string[], name: string, getMembers: () => string[]}} CallExpressionInfo */
3645
- /** @typedef {{ type: "expression", rootInfo: string | VariableInfo, name: string, getMembers: () => string[]}} ExpressionExpressionInfo */
4658
+ /** @typedef {{ type: "call", call: CallExpression, calleeName: string, rootInfo: string | VariableInfo, getCalleeMembers: () => string[], name: string, getMembers: () => string[], getMembersOptionals: () => boolean[], getMemberRanges: () => Range[]}} CallExpressionInfo */
4659
+ /** @typedef {{ type: "expression", rootInfo: string | VariableInfo, name: string, getMembers: () => string[], getMembersOptionals: () => boolean[], getMemberRanges: () => Range[]}} ExpressionExpressionInfo */
3646
4660
 
3647
4661
  /**
3648
- * @param {MemberExpressionNode} expression a member expression
4662
+ * @param {MemberExpression} expression a member expression
3649
4663
  * @param {number} allowedTypes which types should be returned, presented in bit mask
3650
4664
  * @returns {CallExpressionInfo | ExpressionExpressionInfo | undefined} expression info
3651
4665
  */
3652
4666
  getMemberExpressionInfo(expression, allowedTypes) {
3653
- const { object, members } = this.extractMemberExpressionChain(expression);
4667
+ const { object, members, membersOptionals, memberRanges } =
4668
+ this.extractMemberExpressionChain(expression);
3654
4669
  switch (object.type) {
3655
4670
  case "CallExpression": {
3656
- if ((allowedTypes & ALLOWED_MEMBER_TYPES_CALL_EXPRESSION) === 0)
3657
- return undefined;
4671
+ if ((allowedTypes & ALLOWED_MEMBER_TYPES_CALL_EXPRESSION) === 0) return;
3658
4672
  let callee = object.callee;
3659
4673
  let rootMembers = EMPTY_ARRAY;
3660
4674
  if (callee.type === "MemberExpression") {
@@ -3662,9 +4676,9 @@ class JavascriptParser extends Parser {
3662
4676
  this.extractMemberExpressionChain(callee));
3663
4677
  }
3664
4678
  const rootName = getRootName(callee);
3665
- if (!rootName) return undefined;
4679
+ if (!rootName) return;
3666
4680
  const result = this.getFreeInfoFromVariable(rootName);
3667
- if (!result) return undefined;
4681
+ if (!result) return;
3668
4682
  const { info: rootInfo, name: resolvedRoot } = result;
3669
4683
  const calleeName = objectAndMembersToName(resolvedRoot, rootMembers);
3670
4684
  return {
@@ -3674,33 +4688,36 @@ class JavascriptParser extends Parser {
3674
4688
  rootInfo,
3675
4689
  getCalleeMembers: memoize(() => rootMembers.reverse()),
3676
4690
  name: objectAndMembersToName(`${calleeName}()`, members),
3677
- getMembers: memoize(() => members.reverse())
4691
+ getMembers: memoize(() => members.reverse()),
4692
+ getMembersOptionals: memoize(() => membersOptionals.reverse()),
4693
+ getMemberRanges: memoize(() => memberRanges.reverse())
3678
4694
  };
3679
4695
  }
3680
4696
  case "Identifier":
3681
4697
  case "MetaProperty":
3682
4698
  case "ThisExpression": {
3683
- if ((allowedTypes & ALLOWED_MEMBER_TYPES_EXPRESSION) === 0)
3684
- return undefined;
4699
+ if ((allowedTypes & ALLOWED_MEMBER_TYPES_EXPRESSION) === 0) return;
3685
4700
  const rootName = getRootName(object);
3686
- if (!rootName) return undefined;
4701
+ if (!rootName) return;
3687
4702
 
3688
4703
  const result = this.getFreeInfoFromVariable(rootName);
3689
- if (!result) return undefined;
4704
+ if (!result) return;
3690
4705
  const { info: rootInfo, name: resolvedRoot } = result;
3691
4706
  return {
3692
4707
  type: "expression",
3693
4708
  name: objectAndMembersToName(resolvedRoot, members),
3694
4709
  rootInfo,
3695
- getMembers: memoize(() => members.reverse())
4710
+ getMembers: memoize(() => members.reverse()),
4711
+ getMembersOptionals: memoize(() => membersOptionals.reverse()),
4712
+ getMemberRanges: memoize(() => memberRanges.reverse())
3696
4713
  };
3697
4714
  }
3698
4715
  }
3699
4716
  }
3700
4717
 
3701
4718
  /**
3702
- * @param {MemberExpressionNode} expression an expression
3703
- * @returns {{ name: string, rootInfo: ExportedVariableInfo, getMembers: () => string[]}} name info
4719
+ * @param {MemberExpression} expression an expression
4720
+ * @returns {{ name: string, rootInfo: ExportedVariableInfo, getMembers: () => string[]} | undefined} name info
3704
4721
  */
3705
4722
  getNameForExpression(expression) {
3706
4723
  return this.getMemberExpressionInfo(
@@ -3712,7 +4729,7 @@ class JavascriptParser extends Parser {
3712
4729
  /**
3713
4730
  * @param {string} code source code
3714
4731
  * @param {ParseOptions} options parsing options
3715
- * @returns {ProgramNode} parsed ast
4732
+ * @returns {Program} parsed ast
3716
4733
  */
3717
4734
  static _parse(code, options) {
3718
4735
  const type = options ? options.sourceType : "module";
@@ -3724,14 +4741,14 @@ class JavascriptParser extends Parser {
3724
4741
  sourceType: type === "auto" ? "module" : type
3725
4742
  };
3726
4743
 
3727
- /** @type {AnyNode} */
4744
+ /** @type {AnyNode | undefined} */
3728
4745
  let ast;
3729
4746
  let error;
3730
4747
  let threw = false;
3731
4748
  try {
3732
4749
  ast = /** @type {AnyNode} */ (parser.parse(code, parserOptions));
3733
- } catch (e) {
3734
- error = e;
4750
+ } catch (err) {
4751
+ error = err;
3735
4752
  threw = true;
3736
4753
  }
3737
4754
 
@@ -3746,7 +4763,7 @@ class JavascriptParser extends Parser {
3746
4763
  try {
3747
4764
  ast = /** @type {AnyNode} */ (parser.parse(code, parserOptions));
3748
4765
  threw = false;
3749
- } catch (e) {
4766
+ } catch (_err) {
3750
4767
  // we use the error from first parse try
3751
4768
  // so nothing to do here
3752
4769
  }
@@ -3756,7 +4773,7 @@ class JavascriptParser extends Parser {
3756
4773
  throw error;
3757
4774
  }
3758
4775
 
3759
- return /** @type {ProgramNode} */ (ast);
4776
+ return /** @type {Program} */ (ast);
3760
4777
  }
3761
4778
  }
3762
4779