@depup/webpack 5.106.0-depup.0 → 5.109.0-depup.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (667) hide show
  1. package/README.md +9 -11
  2. package/changes.json +16 -24
  3. package/hot/dev-server.js +2 -0
  4. package/lib/APIPlugin.js +60 -35
  5. package/lib/AsyncDependenciesBlock.js +3 -0
  6. package/lib/AutomaticPrefetchPlugin.js +6 -1
  7. package/lib/BannerPlugin.js +13 -5
  8. package/lib/Cache.js +27 -5
  9. package/lib/CacheFacade.js +41 -0
  10. package/lib/Chunk.js +71 -25
  11. package/lib/ChunkGraph.js +141 -9
  12. package/lib/ChunkGroup.js +115 -28
  13. package/lib/ChunkTemplate.js +9 -0
  14. package/lib/CircularModulesPlugin.js +190 -0
  15. package/lib/CleanPlugin.js +23 -26
  16. package/lib/CodeGenerationResults.js +19 -0
  17. package/lib/CompatibilityPlugin.js +54 -37
  18. package/lib/Compilation.js +635 -107
  19. package/lib/Compiler.js +93 -31
  20. package/lib/ConcatenationScope.js +34 -4
  21. package/lib/ConditionalInitFragment.js +6 -0
  22. package/lib/ConstPlugin.js +15 -12
  23. package/lib/ContextExclusionPlugin.js +3 -1
  24. package/lib/ContextModule.js +345 -55
  25. package/lib/ContextModuleFactory.js +193 -51
  26. package/lib/ContextReplacementPlugin.js +8 -1
  27. package/lib/DefinePlugin.js +498 -127
  28. package/lib/DependenciesBlock.js +6 -1
  29. package/lib/Dependency.js +159 -11
  30. package/lib/DependencyTemplate.js +7 -1
  31. package/lib/DependencyTemplates.js +4 -0
  32. package/lib/DotenvPlugin.js +3 -0
  33. package/lib/DynamicEntryPlugin.js +3 -1
  34. package/lib/EntryOptionPlugin.js +42 -2
  35. package/lib/EntryPlugin.js +4 -1
  36. package/lib/Entrypoint.js +5 -1
  37. package/lib/EnvironmentPlugin.js +3 -2
  38. package/lib/ErrorHelpers.js +7 -0
  39. package/lib/EvalDevToolModulePlugin.js +3 -1
  40. package/lib/EvalSourceMapDevToolPlugin.js +11 -11
  41. package/lib/ExportsInfo.js +399 -108
  42. package/lib/ExportsInfoApiPlugin.js +4 -3
  43. package/lib/ExternalModule.js +376 -78
  44. package/lib/ExternalModuleFactoryPlugin.js +75 -3
  45. package/lib/ExternalsPlugin.js +3 -1
  46. package/lib/FileSystemInfo.js +575 -149
  47. package/lib/FlagAllModulesAsUsedPlugin.js +3 -6
  48. package/lib/FlagDependencyExportsPlugin.js +82 -9
  49. package/lib/FlagDependencyUsagePlugin.js +92 -6
  50. package/lib/FlagEntryExportAsUsedPlugin.js +4 -1
  51. package/lib/Generator.js +24 -3
  52. package/lib/HotModuleReplacementPlugin.js +110 -44
  53. package/lib/IgnorePlugin.js +5 -2
  54. package/lib/IgnoreWarningsPlugin.js +2 -1
  55. package/lib/InitFragment.js +15 -0
  56. package/lib/JavascriptMetaInfoPlugin.js +9 -6
  57. package/lib/LazyBarrel.js +389 -0
  58. package/lib/LibraryTemplatePlugin.js +2 -1
  59. package/lib/LoaderOptionsPlugin.js +3 -1
  60. package/lib/LoaderTargetPlugin.js +3 -1
  61. package/lib/MainTemplate.js +15 -0
  62. package/lib/ManifestPlugin.js +9 -2
  63. package/lib/Module.js +121 -60
  64. package/lib/ModuleFactory.js +6 -1
  65. package/lib/ModuleFilenameHelpers.js +5 -2
  66. package/lib/ModuleGraph.js +69 -2
  67. package/lib/ModuleGraphConnection.js +9 -0
  68. package/lib/ModuleInfoHeaderPlugin.js +5 -0
  69. package/lib/ModuleNotFoundError.js +3 -83
  70. package/lib/ModuleProfile.js +27 -1
  71. package/lib/ModuleSourceTypeConstants.js +52 -19
  72. package/lib/ModuleTemplate.js +10 -0
  73. package/lib/ModuleTypeConstants.js +20 -4
  74. package/lib/MultiCompiler.js +59 -4
  75. package/lib/MultiStats.js +9 -0
  76. package/lib/MultiWatching.js +6 -0
  77. package/lib/NoEmitOnErrorsPlugin.js +1 -1
  78. package/lib/NodeStuffPlugin.js +78 -46
  79. package/lib/NormalModule.js +485 -181
  80. package/lib/NormalModuleFactory.js +148 -29
  81. package/lib/NormalModuleReplacementPlugin.js +3 -1
  82. package/lib/NullFactory.js +1 -0
  83. package/lib/OptionsApply.js +1 -0
  84. package/lib/Parser.js +3 -1
  85. package/lib/PlatformPlugin.js +2 -1
  86. package/lib/PrefetchPlugin.js +4 -1
  87. package/lib/ProgressPlugin.js +351 -161
  88. package/lib/ProvidePlugin.js +6 -3
  89. package/lib/RawModule.js +32 -16
  90. package/lib/RecordIdsPlugin.js +9 -0
  91. package/lib/RequestShortener.js +8 -0
  92. package/lib/ResolverFactory.js +5 -0
  93. package/lib/RuntimeGlobals.js +58 -5
  94. package/lib/RuntimeModule.js +22 -7
  95. package/lib/RuntimePlugin.js +104 -26
  96. package/lib/RuntimeTemplate.js +616 -37
  97. package/lib/SelfModuleFactory.js +3 -0
  98. package/lib/SourceMapDevToolModuleOptionsPlugin.js +2 -0
  99. package/lib/SourceMapDevToolPlugin.js +341 -63
  100. package/lib/Stats.js +6 -0
  101. package/lib/Template.js +29 -3
  102. package/lib/TemplatedPathPlugin.js +505 -138
  103. package/lib/UseStrictPlugin.js +3 -2
  104. package/lib/WarnCaseSensitiveModulesPlugin.js +72 -3
  105. package/lib/WarnDeprecatedOptionPlugin.js +6 -2
  106. package/lib/WarnNoModeSetPlugin.js +18 -2
  107. package/lib/WatchIgnorePlugin.js +5 -1
  108. package/lib/Watching.js +25 -3
  109. package/lib/WebpackError.js +3 -74
  110. package/lib/WebpackIsIncludedPlugin.js +4 -2
  111. package/lib/WebpackOptionsApply.js +88 -25
  112. package/lib/WebpackOptionsDefaulter.js +1 -0
  113. package/lib/asset/AssetBytesGenerator.js +28 -10
  114. package/lib/asset/AssetBytesParser.js +1 -0
  115. package/lib/asset/AssetGenerator.js +199 -60
  116. package/lib/asset/AssetModule.js +47 -0
  117. package/lib/asset/AssetModulesPlugin.js +115 -24
  118. package/lib/asset/AssetParser.js +4 -2
  119. package/lib/asset/AssetSourceGenerator.js +26 -8
  120. package/lib/asset/AssetSourceParser.js +1 -0
  121. package/lib/asset/RawDataUrlModule.js +23 -13
  122. package/lib/asset/WebManifestGenerator.js +164 -0
  123. package/lib/asset/WebManifestParser.js +130 -0
  124. package/lib/async-modules/AsyncModuleHelpers.js +1 -0
  125. package/lib/async-modules/AwaitDependenciesInitFragment.js +18 -4
  126. package/lib/async-modules/InferAsyncModulesPlugin.js +1 -1
  127. package/lib/async-modules/isGeneratorLowered.js +26 -0
  128. package/lib/buildChunkGraph.js +107 -15
  129. package/lib/bun/BunTargetPlugin.js +42 -0
  130. package/lib/cache/AddBuildDependenciesPlugin.js +3 -1
  131. package/lib/cache/AddManagedPathsPlugin.js +5 -1
  132. package/lib/cache/IdleFileCachePlugin.js +6 -1
  133. package/lib/cache/MemoryCachePlugin.js +1 -1
  134. package/lib/cache/MemoryWithGcCachePlugin.js +4 -1
  135. package/lib/cache/PackFileCacheStrategy.js +43 -7
  136. package/lib/cache/ResolverCachePlugin.js +12 -1
  137. package/lib/cache/getLazyHashedEtag.js +13 -2
  138. package/lib/cache/mergeEtags.js +4 -0
  139. package/lib/cli.js +142 -20
  140. package/lib/config/browserslistTargetHandler.js +141 -0
  141. package/lib/config/defaults.js +591 -41
  142. package/lib/config/defineConfig.js +31 -0
  143. package/lib/config/normalization.js +46 -1
  144. package/lib/config/target.js +200 -2
  145. package/lib/container/ContainerEntryDependency.js +2 -0
  146. package/lib/container/ContainerEntryModule.js +27 -14
  147. package/lib/container/ContainerEntryModuleFactory.js +1 -0
  148. package/lib/container/ContainerExposedDependency.js +6 -2
  149. package/lib/container/ContainerPlugin.js +2 -1
  150. package/lib/container/ContainerReferencePlugin.js +3 -2
  151. package/lib/container/FallbackDependency.js +9 -7
  152. package/lib/container/FallbackItemDependency.js +1 -0
  153. package/lib/container/FallbackModule.js +22 -9
  154. package/lib/container/FallbackModuleFactory.js +1 -0
  155. package/lib/container/ModuleFederationPlugin.js +12 -26
  156. package/lib/container/RemoteModule.js +33 -10
  157. package/lib/container/RemoteRuntimeModule.js +15 -12
  158. package/lib/container/RemoteToExternalDependency.js +1 -0
  159. package/lib/container/options.js +7 -0
  160. package/lib/css/CssGenerator.js +534 -272
  161. package/lib/css/CssInjectStyleRuntimeModule.js +86 -70
  162. package/lib/css/CssLoadingRuntimeModule.js +156 -77
  163. package/lib/{CssModule.js → css/CssModule.js} +72 -37
  164. package/lib/css/CssModulesPlugin.js +356 -204
  165. package/lib/css/CssParser.js +3452 -1950
  166. package/lib/css/syntax.js +4058 -0
  167. package/lib/debug/ProfilingPlugin.js +33 -2
  168. package/lib/deno/DenoTargetPlugin.js +41 -0
  169. package/lib/dependencies/AMDDefineDependency.js +29 -17
  170. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +19 -6
  171. package/lib/dependencies/AMDPlugin.js +6 -3
  172. package/lib/dependencies/AMDRequireArrayDependency.js +13 -11
  173. package/lib/dependencies/AMDRequireContextDependency.js +10 -11
  174. package/lib/dependencies/AMDRequireDependenciesBlock.js +1 -0
  175. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +28 -14
  176. package/lib/dependencies/AMDRequireDependency.js +28 -20
  177. package/lib/dependencies/AMDRequireItemDependency.js +1 -0
  178. package/lib/dependencies/AMDRuntimeModules.js +3 -0
  179. package/lib/dependencies/CachedConstDependency.js +9 -1
  180. package/lib/dependencies/CommonJsDependencyHelpers.js +104 -0
  181. package/lib/dependencies/CommonJsExportRequireDependency.js +138 -38
  182. package/lib/dependencies/CommonJsExportsDependency.js +74 -20
  183. package/lib/dependencies/CommonJsExportsParserPlugin.js +246 -15
  184. package/lib/dependencies/CommonJsFullRequireDependency.js +62 -27
  185. package/lib/dependencies/CommonJsImportsParserPlugin.js +187 -24
  186. package/lib/dependencies/CommonJsPlugin.js +7 -4
  187. package/lib/dependencies/CommonJsRequireContextDependency.js +13 -13
  188. package/lib/dependencies/CommonJsRequireDependency.js +135 -13
  189. package/lib/dependencies/CommonJsSelfReferenceDependency.js +60 -16
  190. package/lib/dependencies/ConstDependency.js +22 -12
  191. package/lib/dependencies/ContextDependency.js +13 -2
  192. package/lib/dependencies/ContextDependencyHelpers.js +7 -4
  193. package/lib/dependencies/ContextDependencyTemplateAsId.js +2 -1
  194. package/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +1 -0
  195. package/lib/dependencies/ContextElementDependency.js +27 -14
  196. package/lib/dependencies/CreateRequireParserPlugin.js +14 -7
  197. package/lib/dependencies/CreateScriptUrlDependency.js +9 -7
  198. package/lib/dependencies/CriticalDependencyWarning.js +3 -1
  199. package/lib/dependencies/CssIcssExportDependency.js +682 -368
  200. package/lib/dependencies/CssIcssImportDependency.js +62 -17
  201. package/lib/dependencies/CssIcssSymbolDependency.js +36 -17
  202. package/lib/dependencies/CssImportDependency.js +37 -1
  203. package/lib/dependencies/CssUrlDependency.js +87 -14
  204. package/lib/dependencies/DelegatedSourceDependency.js +1 -0
  205. package/lib/dependencies/DllEntryDependency.js +12 -13
  206. package/lib/dependencies/DynamicExports.js +5 -0
  207. package/lib/dependencies/EntryDependency.js +1 -0
  208. package/lib/dependencies/ExportBindingInitFragment.js +164 -0
  209. package/lib/dependencies/ExportsInfoDependency.js +18 -12
  210. package/lib/dependencies/ExternalModuleDependency.js +13 -5
  211. package/lib/dependencies/ExternalModuleInitFragment.js +10 -5
  212. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +19 -12
  213. package/lib/dependencies/HarmonyAcceptDependency.js +24 -26
  214. package/lib/dependencies/HarmonyAcceptImportDependency.js +2 -0
  215. package/lib/dependencies/HarmonyCompatibilityDependency.js +33 -14
  216. package/lib/dependencies/HarmonyDetectionParserPlugin.js +108 -30
  217. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +32 -2
  218. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +70 -33
  219. package/lib/dependencies/HarmonyExportExpressionDependency.js +140 -46
  220. package/lib/dependencies/HarmonyExportHeaderDependency.js +11 -9
  221. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +253 -37
  222. package/lib/dependencies/HarmonyExportInitFragment.js +28 -20
  223. package/lib/dependencies/HarmonyExportSpecifierDependency.js +88 -18
  224. package/lib/dependencies/HarmonyExports.js +6 -1
  225. package/lib/dependencies/HarmonyImportDependency.js +59 -3
  226. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +139 -146
  227. package/lib/dependencies/HarmonyImportGuard.js +426 -0
  228. package/lib/dependencies/HarmonyImportSideEffectDependency.js +22 -1
  229. package/lib/dependencies/HarmonyImportSpecifierDependency.js +136 -17
  230. package/lib/{HarmonyLinkingError.js → dependencies/HarmonyLinkingError.js} +6 -3
  231. package/lib/dependencies/HarmonyModulesPlugin.js +11 -1
  232. package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +2 -1
  233. package/lib/dependencies/HtmlEntryDependency.js +1295 -0
  234. package/lib/dependencies/HtmlInlineHtmlDependency.js +107 -0
  235. package/lib/dependencies/HtmlInlineScriptDependency.js +126 -0
  236. package/lib/dependencies/HtmlInlineStyleDependency.js +152 -0
  237. package/lib/dependencies/HtmlSourceDependency.js +172 -0
  238. package/lib/dependencies/ImportContextDependency.js +9 -9
  239. package/lib/dependencies/ImportDependency.js +92 -3
  240. package/lib/dependencies/ImportEagerDependency.js +2 -0
  241. package/lib/dependencies/ImportMetaContextDependency.js +1 -0
  242. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +35 -19
  243. package/lib/dependencies/ImportMetaContextPlugin.js +40 -8
  244. package/lib/dependencies/ImportMetaGlobDependency.js +81 -0
  245. package/lib/dependencies/ImportMetaGlobDependencyParserPlugin.js +78 -0
  246. package/lib/dependencies/ImportMetaGlobHelpers.js +660 -0
  247. package/lib/dependencies/ImportMetaHotAcceptDependency.js +2 -0
  248. package/lib/dependencies/ImportMetaHotDeclineDependency.js +2 -0
  249. package/lib/dependencies/ImportMetaPlugin.js +595 -209
  250. package/lib/dependencies/ImportMetaResolveDependency.js +90 -0
  251. package/lib/dependencies/ImportParserPlugin.js +114 -27
  252. package/lib/dependencies/ImportPhase.js +17 -11
  253. package/lib/dependencies/ImportPlugin.js +2 -1
  254. package/lib/dependencies/ImportWeakDependency.js +3 -0
  255. package/lib/dependencies/JsonExportsDependency.js +15 -10
  256. package/lib/dependencies/LoaderDependency.js +2 -0
  257. package/lib/dependencies/LoaderImportDependency.js +3 -0
  258. package/lib/dependencies/LoaderPlugin.js +9 -2
  259. package/lib/dependencies/LocalModule.js +15 -12
  260. package/lib/dependencies/LocalModuleDependency.js +15 -13
  261. package/lib/dependencies/LocalModulesHelpers.js +3 -0
  262. package/lib/dependencies/ModuleDecoratorDependency.js +16 -10
  263. package/lib/dependencies/ModuleDependency.js +14 -0
  264. package/lib/dependencies/ModuleDependencyTemplateAsId.js +1 -0
  265. package/lib/dependencies/ModuleDependencyTemplateAsRequireId.js +1 -0
  266. package/lib/dependencies/ModuleHotAcceptDependency.js +2 -0
  267. package/lib/dependencies/ModuleHotDeclineDependency.js +2 -0
  268. package/lib/dependencies/ModuleInitFragmentDependency.js +19 -11
  269. package/lib/dependencies/NullDependency.js +2 -0
  270. package/lib/dependencies/PrefetchDependency.js +1 -0
  271. package/lib/dependencies/ProvidedDependency.js +36 -27
  272. package/lib/dependencies/PureExpressionDependency.js +14 -10
  273. package/lib/dependencies/RequireContextDependency.js +1 -0
  274. package/lib/dependencies/RequireContextDependencyParserPlugin.js +2 -1
  275. package/lib/dependencies/RequireContextPlugin.js +2 -1
  276. package/lib/dependencies/RequireEnsureDependenciesBlock.js +1 -0
  277. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +4 -6
  278. package/lib/dependencies/RequireEnsureDependency.js +16 -13
  279. package/lib/dependencies/RequireEnsureItemDependency.js +1 -0
  280. package/lib/dependencies/RequireEnsurePlugin.js +2 -1
  281. package/lib/dependencies/RequireHeaderDependency.js +7 -4
  282. package/lib/dependencies/RequireIncludeDependency.js +2 -0
  283. package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +11 -12
  284. package/lib/dependencies/RequireIncludePlugin.js +2 -1
  285. package/lib/{RequireJsStuffPlugin.js → dependencies/RequireJsStuffPlugin.js} +9 -8
  286. package/lib/dependencies/RequireResolveContextDependency.js +10 -11
  287. package/lib/dependencies/RequireResolveDependency.js +2 -0
  288. package/lib/dependencies/RequireResolveHeaderDependency.js +8 -5
  289. package/lib/dependencies/RuntimeRequirementsDependency.js +11 -8
  290. package/lib/dependencies/StaticExportsDependency.js +13 -10
  291. package/lib/dependencies/SystemPlugin.js +9 -6
  292. package/lib/dependencies/SystemRuntimeModule.js +1 -0
  293. package/lib/dependencies/TopLevelAwaitDependency.js +93 -0
  294. package/lib/dependencies/URLContextDependency.js +8 -7
  295. package/lib/dependencies/URLDependency.js +157 -33
  296. package/lib/dependencies/URLPlugin.js +2 -0
  297. package/lib/dependencies/UnsupportedDependency.js +12 -13
  298. package/lib/dependencies/WebAssemblyExportImportedDependency.js +15 -16
  299. package/lib/dependencies/WebAssemblyImportDependency.js +19 -18
  300. package/lib/dependencies/WebpackIsIncludedDependency.js +3 -0
  301. package/lib/dependencies/{WorkerPlugin.js → WorkerAndWorkletPlugin.js} +364 -114
  302. package/lib/dependencies/WorkerDependency.js +111 -27
  303. package/lib/dependencies/WorkletDependency.js +278 -0
  304. package/lib/dependencies/getFunctionExpression.js +1 -0
  305. package/lib/dependencies/processExportInfo.js +14 -11
  306. package/lib/{DelegatedModule.js → dll/DelegatedModule.js} +71 -44
  307. package/lib/{DelegatedModuleFactoryPlugin.js → dll/DelegatedModuleFactoryPlugin.js} +27 -4
  308. package/lib/{DelegatedPlugin.js → dll/DelegatedPlugin.js} +5 -3
  309. package/lib/{DllEntryPlugin.js → dll/DllEntryPlugin.js} +9 -5
  310. package/lib/{DllModule.js → dll/DllModule.js} +36 -24
  311. package/lib/{DllModuleFactory.js → dll/DllModuleFactory.js} +5 -4
  312. package/lib/{DllPlugin.js → dll/DllPlugin.js} +24 -6
  313. package/lib/{DllReferencePlugin.js → dll/DllReferencePlugin.js} +26 -18
  314. package/lib/{LibManifestPlugin.js → dll/LibManifestPlugin.js} +14 -10
  315. package/lib/electron/ElectronTargetPlugin.js +24 -5
  316. package/lib/{AbstractMethodError.js → errors/AbstractMethodError.js} +10 -1
  317. package/lib/{AsyncDependencyToInitialChunkError.js → errors/AsyncDependencyToInitialChunkError.js} +8 -3
  318. package/lib/errors/BuildCycleError.js +1 -1
  319. package/lib/{ChunkRenderError.js → errors/ChunkRenderError.js} +1 -1
  320. package/lib/{CodeGenerationError.js → errors/CodeGenerationError.js} +1 -1
  321. package/lib/{CommentCompilationWarning.js → errors/CommentCompilationWarning.js} +9 -3
  322. package/lib/{ConcurrentCompilationError.js → errors/ConcurrentCompilationError.js} +5 -2
  323. package/lib/{EnvironmentNotSupportAsyncWarning.js → errors/EnvironmentNotSupportAsyncWarning.js} +5 -5
  324. package/lib/{HookWebpackError.js → errors/HookWebpackError.js} +20 -16
  325. package/lib/{IgnoreErrorModuleFactory.js → errors/IgnoreErrorModuleFactory.js} +7 -4
  326. package/lib/{InvalidDependenciesModuleWarning.js → errors/InvalidDependenciesModuleWarning.js} +6 -3
  327. package/lib/errors/JSONParseError.js +115 -0
  328. package/lib/errors/LoaderLoadingError.js +20 -0
  329. package/lib/{ModuleBuildError.js → errors/ModuleBuildError.js} +22 -16
  330. package/lib/{ModuleDependencyError.js → errors/ModuleDependencyError.js} +10 -3
  331. package/lib/{ModuleDependencyWarning.js → errors/ModuleDependencyWarning.js} +13 -5
  332. package/lib/{ModuleError.js → errors/ModuleError.js} +10 -14
  333. package/lib/{ModuleHashingError.js → errors/ModuleHashingError.js} +5 -1
  334. package/lib/errors/ModuleNotFoundError.js +94 -0
  335. package/lib/errors/ModuleParseError.js +141 -0
  336. package/lib/{ModuleRestoreError.js → errors/ModuleRestoreError.js} +4 -1
  337. package/lib/{ModuleStoreError.js → errors/ModuleStoreError.js} +5 -1
  338. package/lib/{ModuleWarning.js → errors/ModuleWarning.js} +13 -14
  339. package/lib/{NodeStuffInWebError.js → errors/NodeStuffInWebError.js} +7 -5
  340. package/lib/errors/NonErrorEmittedError.js +30 -0
  341. package/lib/{UnhandledSchemeError.js → errors/UnhandledSchemeError.js} +9 -2
  342. package/lib/{UnsupportedFeatureWarning.js → errors/UnsupportedFeatureWarning.js} +4 -3
  343. package/lib/errors/WebpackError.js +84 -0
  344. package/lib/esm/ExportWebpackRequireRuntimeModule.js +2 -0
  345. package/lib/esm/ModuleChunkFormatPlugin.js +52 -15
  346. package/lib/esm/ModuleChunkLoadingPlugin.js +11 -3
  347. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +71 -49
  348. package/lib/hmr/HotModuleReplacement.runtime.js +175 -30
  349. package/lib/hmr/HotModuleReplacementRuntimeModule.js +8 -0
  350. package/lib/hmr/JavascriptHotModuleReplacement.runtime.js +173 -26
  351. package/lib/hmr/JavascriptHotModuleReplacementHelper.js +1 -0
  352. package/lib/hmr/LazyCompilationPlugin.js +154 -7
  353. package/lib/hmr/lazyCompilationBackend.js +34 -8
  354. package/lib/html/HtmlGenerator.js +1470 -0
  355. package/lib/html/HtmlModule.js +41 -0
  356. package/lib/html/HtmlModulesPlugin.js +1111 -0
  357. package/lib/html/HtmlParser.js +1970 -0
  358. package/lib/html/favicon.svg +1 -0
  359. package/lib/html/syntax.js +9020 -0
  360. package/lib/ids/ChunkModuleIdRangePlugin.js +3 -1
  361. package/lib/ids/DeterministicChunkIdsPlugin.js +3 -1
  362. package/lib/ids/DeterministicModuleIdsPlugin.js +3 -1
  363. package/lib/ids/HashedModuleIdsPlugin.js +2 -1
  364. package/lib/ids/IdHelpers.js +25 -2
  365. package/lib/ids/NamedChunkIdsPlugin.js +3 -1
  366. package/lib/ids/NamedModuleIdsPlugin.js +3 -1
  367. package/lib/ids/NaturalChunkIdsPlugin.js +1 -1
  368. package/lib/ids/NaturalModuleIdsPlugin.js +1 -1
  369. package/lib/ids/OccurrenceChunkIdsPlugin.js +2 -1
  370. package/lib/ids/OccurrenceModuleIdsPlugin.js +4 -1
  371. package/lib/ids/SyncModuleIdsPlugin.js +3 -1
  372. package/lib/index.js +66 -15
  373. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +5 -6
  374. package/lib/javascript/BasicEvaluatedExpression.js +370 -49
  375. package/lib/javascript/ChunkFormatHelpers.js +2 -1
  376. package/lib/javascript/ChunkHelpers.js +1 -0
  377. package/lib/javascript/CommonJsChunkFormatPlugin.js +1 -1
  378. package/lib/javascript/EnableChunkLoadingPlugin.js +6 -1
  379. package/lib/javascript/JavascriptGenerator.js +213 -51
  380. package/lib/javascript/JavascriptModule.js +54 -0
  381. package/lib/javascript/JavascriptModulesPlugin.js +579 -183
  382. package/lib/javascript/JavascriptParser.js +1289 -462
  383. package/lib/javascript/JavascriptParserHelpers.js +10 -7
  384. package/lib/javascript/StartupHelpers.js +5 -0
  385. package/lib/javascript/syntax.js +4380 -0
  386. package/lib/json/JsonData.js +5 -0
  387. package/lib/json/JsonGenerator.js +21 -0
  388. package/lib/json/JsonModule.js +40 -0
  389. package/lib/json/JsonModulesPlugin.js +8 -1
  390. package/lib/json/JsonParser.js +18 -27
  391. package/lib/library/AbstractLibraryPlugin.js +17 -2
  392. package/lib/library/AmdLibraryPlugin.js +8 -0
  393. package/lib/library/AssignLibraryPlugin.js +21 -3
  394. package/lib/library/EnableLibraryPlugin.js +8 -2
  395. package/lib/library/ExportPropertyLibraryPlugin.js +10 -0
  396. package/lib/{FalseIIFEUmdWarning.js → library/FalseIIFEUmdWarning.js} +2 -1
  397. package/lib/library/JsonpLibraryPlugin.js +8 -0
  398. package/lib/library/ModuleLibraryPlugin.js +154 -7
  399. package/lib/library/SystemLibraryPlugin.js +11 -3
  400. package/lib/library/UmdLibraryPlugin.js +16 -0
  401. package/lib/loaders/LoaderRunner.js +714 -0
  402. package/lib/loaders/loadLoader.js +100 -0
  403. package/lib/logging/Logger.js +17 -0
  404. package/lib/logging/createConsoleLogger.js +7 -0
  405. package/lib/logging/runtime.js +2 -0
  406. package/lib/logging/truncateArgs.js +2 -0
  407. package/lib/node/CommonJsChunkLoadingPlugin.js +5 -1
  408. package/lib/node/NodeEnvironmentPlugin.js +7 -3
  409. package/lib/node/NodeSourcePlugin.js +1 -1
  410. package/lib/node/NodeTargetPlugin.js +4 -63
  411. package/lib/node/NodeTemplatePlugin.js +3 -1
  412. package/lib/node/NodeWatchFileSystem.js +40 -22
  413. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +13 -9
  414. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +23 -1
  415. package/lib/node/ReadFileCompileWasmPlugin.js +18 -1
  416. package/lib/node/RequireChunkLoadingRuntimeModule.js +21 -16
  417. package/lib/node/nodeBuiltins.js +80 -0
  418. package/lib/node/nodeConsole.js +116 -64
  419. package/lib/optimize/AggressiveMergingPlugin.js +3 -1
  420. package/lib/optimize/AggressiveSplittingPlugin.js +6 -1
  421. package/lib/optimize/ConcatenatedModule.js +585 -116
  422. package/lib/optimize/ConstExportsPlugin.js +211 -0
  423. package/lib/optimize/EnsureChunkConditionsPlugin.js +2 -1
  424. package/lib/optimize/FlagIncludedChunksPlugin.js +15 -4
  425. package/lib/optimize/InlineExports.js +178 -0
  426. package/lib/optimize/InnerGraph.js +374 -262
  427. package/lib/optimize/InnerGraphPlugin.js +246 -117
  428. package/lib/optimize/LimitChunkCountPlugin.js +9 -0
  429. package/lib/optimize/MangleExportsPlugin.js +5 -1
  430. package/lib/optimize/MergeDuplicateChunksPlugin.js +2 -0
  431. package/lib/optimize/MinChunkSizePlugin.js +2 -1
  432. package/lib/optimize/MinMaxSizeWarning.js +5 -4
  433. package/lib/optimize/ModuleConcatenationPlugin.js +159 -34
  434. package/lib/optimize/RealContentHashPlugin.js +125 -50
  435. package/lib/optimize/RemoveEmptyChunksPlugin.js +2 -1
  436. package/lib/optimize/RemoveParentModulesPlugin.js +3 -1
  437. package/lib/optimize/RuntimeChunkPlugin.js +2 -1
  438. package/lib/optimize/SideEffectsFlagPlugin.js +381 -55
  439. package/lib/optimize/SplitChunksPlugin.js +54 -6
  440. package/lib/performance/AssetsOverSizeLimitWarning.js +3 -2
  441. package/lib/performance/EntrypointsOverSizeLimitWarning.js +3 -2
  442. package/lib/performance/NoAsyncChunksWarning.js +5 -3
  443. package/lib/performance/SizeLimitsPlugin.js +8 -2
  444. package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +1 -0
  445. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +21 -0
  446. package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +1 -0
  447. package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +5 -1
  448. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +25 -13
  449. package/lib/prefetch/ResourceHintPlugin.js +663 -0
  450. package/lib/prefetch/ResourceHintRuntimeModule.js +149 -0
  451. package/lib/prefetch/StartupAssetHintRuntimeModule.js +210 -0
  452. package/lib/prefetch/parseResourceHintOptions.js +103 -0
  453. package/lib/rules/BasicEffectRulePlugin.js +3 -0
  454. package/lib/rules/BasicMatcherRulePlugin.js +3 -0
  455. package/lib/rules/ObjectMatcherRulePlugin.js +3 -0
  456. package/lib/rules/RuleSetCompiler.js +132 -0
  457. package/lib/rules/UseEffectRulePlugin.js +10 -3
  458. package/lib/runtime/AsyncModuleGeneratorRuntimeModule.js +56 -0
  459. package/lib/runtime/AsyncModuleRuntimeModule.js +52 -33
  460. package/lib/runtime/AutoPublicPathRuntimeModule.js +22 -9
  461. package/lib/runtime/BaseUriRuntimeModule.js +1 -0
  462. package/lib/runtime/ChunkNameRuntimeModule.js +1 -0
  463. package/lib/runtime/CommonJsWrapRuntimeModule.js +37 -0
  464. package/lib/runtime/CompatGetDefaultExportRuntimeModule.js +2 -1
  465. package/lib/runtime/CompatRuntimeModule.js +2 -0
  466. package/lib/runtime/CreateFakeNamespaceObjectRuntimeModule.js +7 -4
  467. package/lib/runtime/CreateScriptRuntimeModule.js +1 -0
  468. package/lib/runtime/CreateScriptUrlRuntimeModule.js +1 -0
  469. package/lib/runtime/DefinePropertyGettersRuntimeModule.js +34 -4
  470. package/lib/runtime/EnsureChunkRuntimeModule.js +1 -0
  471. package/lib/runtime/GetChunkFilenameRuntimeModule.js +88 -8
  472. package/lib/runtime/GetFullHashRuntimeModule.js +1 -0
  473. package/lib/runtime/GetMainFilenameRuntimeModule.js +1 -0
  474. package/lib/runtime/GetTrustedTypesPolicyRuntimeModule.js +2 -1
  475. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +59 -0
  476. package/lib/runtime/GlobalRuntimeModule.js +1 -0
  477. package/lib/runtime/HasOwnPropertyRuntimeModule.js +2 -1
  478. package/lib/runtime/HelperRuntimeModule.js +5 -0
  479. package/lib/runtime/LoadScriptRuntimeModule.js +28 -37
  480. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +354 -37
  481. package/lib/runtime/MakeNamespaceObjectRuntimeModule.js +2 -1
  482. package/lib/runtime/NonceRuntimeModule.js +1 -0
  483. package/lib/runtime/OnChunksLoadedRuntimeModule.js +5 -4
  484. package/lib/runtime/PublicPathRuntimeModule.js +1 -0
  485. package/lib/runtime/RelativeUrlRuntimeModule.js +4 -2
  486. package/lib/runtime/RuntimeIdRuntimeModule.js +1 -0
  487. package/lib/runtime/SetAnonymousDefaultNameRuntimeModule.js +38 -0
  488. package/lib/runtime/StartupChunkDependenciesPlugin.js +13 -1
  489. package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +2 -1
  490. package/lib/runtime/StartupEntrypointRuntimeModule.js +5 -3
  491. package/lib/runtime/SystemContextRuntimeModule.js +1 -0
  492. package/lib/runtime/ToBinaryRuntimeModule.js +1 -0
  493. package/lib/runtime/WorkerRuntimeModule.js +33 -0
  494. package/lib/schemes/DataUriPlugin.js +14 -2
  495. package/lib/schemes/FileUriPlugin.js +1 -1
  496. package/lib/schemes/HttpUriPlugin.js +86 -4
  497. package/lib/schemes/VirtualUrlPlugin.js +8 -4
  498. package/lib/serialization/AggregateErrorSerializer.js +9 -6
  499. package/lib/serialization/ArraySerializer.js +6 -8
  500. package/lib/serialization/BinaryMiddleware.js +552 -463
  501. package/lib/serialization/DateObjectSerializer.js +4 -2
  502. package/lib/serialization/ErrorObjectSerializer.js +10 -6
  503. package/lib/serialization/FileMiddleware.js +50 -3
  504. package/lib/serialization/MapObjectSerializer.js +7 -9
  505. package/lib/serialization/NullPrototypeObjectSerializer.js +9 -9
  506. package/lib/serialization/ObjectMiddleware.js +73 -13
  507. package/lib/serialization/PlainObjectSerializer.js +16 -8
  508. package/lib/serialization/RegExpObjectSerializer.js +4 -2
  509. package/lib/serialization/Serializer.js +6 -0
  510. package/lib/serialization/SerializerMiddleware.js +14 -2
  511. package/lib/serialization/SetObjectSerializer.js +6 -8
  512. package/lib/serialization/SingleItemMiddleware.js +3 -0
  513. package/lib/sharing/ConsumeSharedFallbackDependency.js +1 -0
  514. package/lib/sharing/ConsumeSharedModule.js +21 -7
  515. package/lib/sharing/ConsumeSharedPlugin.js +11 -11
  516. package/lib/sharing/ConsumeSharedRuntimeModule.js +55 -45
  517. package/lib/sharing/ProvideForSharedDependency.js +1 -0
  518. package/lib/sharing/ProvideSharedDependency.js +34 -15
  519. package/lib/sharing/ProvideSharedModule.js +42 -12
  520. package/lib/sharing/ProvideSharedModuleFactory.js +1 -0
  521. package/lib/sharing/ProvideSharedPlugin.js +13 -8
  522. package/lib/sharing/SharePlugin.js +5 -1
  523. package/lib/sharing/ShareRuntimeModule.js +19 -16
  524. package/lib/sharing/resolveMatchedConfigs.js +6 -2
  525. package/lib/sharing/utils.js +9 -1
  526. package/lib/stats/DefaultStatsFactoryPlugin.js +94 -12
  527. package/lib/stats/DefaultStatsPresetPlugin.js +14 -2
  528. package/lib/stats/DefaultStatsPrinterPlugin.js +64 -18
  529. package/lib/stats/StatsFactory.js +39 -18
  530. package/lib/stats/StatsPrinter.js +16 -2
  531. package/lib/typescript/TypeScriptPlugin.js +210 -0
  532. package/lib/url/URLParserPlugin.js +111 -23
  533. package/lib/util/ArrayHelpers.js +1 -0
  534. package/lib/util/ArrayQueue.js +10 -5
  535. package/lib/util/AsyncQueue.js +154 -74
  536. package/lib/util/Hash.js +2 -2
  537. package/lib/util/IterableHelpers.js +3 -0
  538. package/lib/util/LazyBucketSortedSet.js +26 -0
  539. package/lib/util/LazySet.js +45 -4
  540. package/lib/util/LocConverter.js +64 -0
  541. package/lib/util/ParallelismFactorCalculator.js +1 -0
  542. package/lib/util/Queue.js +6 -3
  543. package/lib/util/Semaphore.js +15 -1
  544. package/lib/util/SetHelpers.js +4 -1
  545. package/lib/util/SortableSet.js +7 -1
  546. package/lib/util/SourceProcessor.js +119 -0
  547. package/lib/util/StackedCacheMap.js +20 -3
  548. package/lib/util/StackedMap.js +162 -43
  549. package/lib/util/StringXor.js +1 -1
  550. package/lib/util/TupleQueue.js +7 -3
  551. package/lib/util/TupleSet.js +14 -0
  552. package/lib/util/URLAbsoluteSpecifier.js +1 -0
  553. package/lib/util/WeakTupleMap.js +60 -1
  554. package/lib/util/binarySearchBounds.js +3 -2
  555. package/lib/util/chainedImports.js +3 -3
  556. package/lib/util/cleverMerge.js +19 -2
  557. package/lib/util/comparators.js +35 -4
  558. package/lib/util/compileBooleanMatcher.js +9 -0
  559. package/lib/util/concatenate.js +80 -24
  560. package/lib/util/conventions.js +46 -1
  561. package/lib/util/createHash.js +0 -1
  562. package/lib/util/createHooksRegistry.js +43 -0
  563. package/lib/util/createMappings.js +118 -0
  564. package/lib/util/dataURL.js +3 -2
  565. package/lib/util/deprecation.js +19 -0
  566. package/lib/util/deterministicGrouping.js +46 -17
  567. package/lib/util/extractSourceMap.js +2 -1
  568. package/lib/util/extractUrlAndGlobal.js +1 -0
  569. package/lib/util/findGraphRoots.js +7 -0
  570. package/lib/{formatLocation.js → util/formatLocation.js} +4 -2
  571. package/lib/{SizeFormatHelpers.js → util/formatSize.js} +10 -3
  572. package/lib/util/fs.js +87 -14
  573. package/lib/util/generateDebugId.js +1 -0
  574. package/lib/util/globUtils.js +710 -0
  575. package/lib/util/hash/BatchedHash.js +1 -0
  576. package/lib/util/hash/BulkUpdateHash.js +1 -0
  577. package/lib/util/hash/DebugHash.js +1 -0
  578. package/lib/util/hash/hash-digest.js +32 -15
  579. package/lib/util/hash/md4.js +1 -1
  580. package/lib/util/hash/wasm-hash.js +5 -0
  581. package/lib/util/hash/xxhash64.js +1 -1
  582. package/lib/util/identifier.js +97 -6
  583. package/lib/util/implicitTypeLoaderFallback.js +62 -0
  584. package/lib/util/internalSerializables.js +102 -60
  585. package/lib/util/magicComment.js +149 -7
  586. package/lib/util/makeSerializable.js +7 -0
  587. package/lib/util/memoize.js +2 -0
  588. package/lib/util/mimeTypes.js +176 -0
  589. package/lib/util/nonNumericOnlyHash.js +31 -1
  590. package/lib/util/numberHash.js +2 -2
  591. package/lib/util/parseJson.js +41 -0
  592. package/lib/util/processAsyncTree.js +8 -0
  593. package/lib/util/property.js +9 -2
  594. package/lib/util/publicPathPlaceholder.js +64 -0
  595. package/lib/util/registerExternalSerializer.js +24 -4
  596. package/lib/util/removeBOM.js +1 -0
  597. package/lib/util/runtime.js +32 -0
  598. package/lib/util/semver.js +15 -0
  599. package/lib/util/serialization.js +2 -0
  600. package/lib/util/smartGrouping.js +8 -0
  601. package/lib/util/source.js +23 -0
  602. package/lib/util/topologicalSort.js +69 -0
  603. package/lib/validateSchema.js +1 -0
  604. package/lib/wasm/EnableWasmLoadingPlugin.js +15 -1
  605. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +25 -18
  606. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +34 -22
  607. package/lib/wasm-async/AsyncWasmModule.js +77 -0
  608. package/lib/wasm-async/AsyncWebAssemblyGenerator.js +6 -0
  609. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +6 -1
  610. package/lib/wasm-async/AsyncWebAssemblyModulesPlugin.js +22 -126
  611. package/lib/wasm-async/AsyncWebAssemblyParser.js +3 -2
  612. package/lib/wasm-async/UniversalCompileAsyncWasmPlugin.js +13 -2
  613. package/lib/wasm-sync/SyncWasmModule.js +39 -0
  614. package/lib/wasm-sync/UnsupportedWebAssemblyFeatureError.js +7 -3
  615. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +86 -19
  616. package/lib/wasm-sync/WasmFinalizeExportsPlugin.js +4 -3
  617. package/lib/wasm-sync/WebAssemblyGenerator.js +27 -1
  618. package/lib/wasm-sync/WebAssemblyInInitialChunkError.js +9 -3
  619. package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +4 -0
  620. package/lib/wasm-sync/WebAssemblyModulesPlugin.js +20 -1
  621. package/lib/wasm-sync/WebAssemblyParser.js +9 -3
  622. package/lib/wasm-sync/WebAssemblyUtils.js +2 -0
  623. package/lib/web/FetchCompileAsyncWasmPlugin.js +29 -1
  624. package/lib/web/FetchCompileWasmPlugin.js +27 -1
  625. package/lib/web/JsonpChunkLoadingPlugin.js +11 -1
  626. package/lib/web/JsonpChunkLoadingRuntimeModule.js +58 -64
  627. package/lib/web/JsonpTemplatePlugin.js +2 -1
  628. package/lib/webpack.js +78 -1
  629. package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +10 -1
  630. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +15 -10
  631. package/lib/webworker/WebWorkerTemplatePlugin.js +1 -1
  632. package/module.d.ts +21 -0
  633. package/package.json +79 -77
  634. package/schemas/WebpackOptions.check.js +1 -1
  635. package/schemas/WebpackOptions.json +1117 -79
  636. package/schemas/plugins/{DllPlugin.check.d.ts → HtmlGeneratorOptions.check.d.ts} +1 -1
  637. package/schemas/plugins/HtmlGeneratorOptions.check.js +6 -0
  638. package/schemas/plugins/HtmlGeneratorOptions.json +3 -0
  639. package/schemas/plugins/{DllReferencePlugin.check.d.ts → HtmlParserOptions.check.d.ts} +1 -1
  640. package/schemas/plugins/HtmlParserOptions.check.js +6 -0
  641. package/schemas/plugins/HtmlParserOptions.json +3 -0
  642. package/schemas/plugins/ProgressPlugin.check.js +1 -1
  643. package/schemas/plugins/ProgressPlugin.json +38 -0
  644. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  645. package/schemas/plugins/container/ContainerReferencePlugin.json +2 -0
  646. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  647. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  648. package/schemas/plugins/container/ModuleFederationPlugin.json +2 -0
  649. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.d.ts +7 -0
  650. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +6 -0
  651. package/schemas/plugins/css/CssAutoOrModuleParserOptions.json +3 -0
  652. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  653. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  654. package/schemas/plugins/dll/DllPlugin.check.d.ts +7 -0
  655. package/schemas/plugins/dll/DllReferencePlugin.check.d.ts +7 -0
  656. package/types.d.ts +8608 -1159
  657. package/lib/CaseSensitiveModulesWarning.js +0 -72
  658. package/lib/GraphHelpers.js +0 -46
  659. package/lib/ModuleParseError.js +0 -125
  660. package/lib/NoModeWarning.js +0 -23
  661. package/lib/css/CssMergeStyleSheetsRuntimeModule.js +0 -56
  662. package/lib/css/walkCssTokens.js +0 -1843
  663. package/lib/util/AppendOnlyStackedSet.js +0 -78
  664. /package/schemas/plugins/{DllPlugin.check.js → dll/DllPlugin.check.js} +0 -0
  665. /package/schemas/plugins/{DllPlugin.json → dll/DllPlugin.json} +0 -0
  666. /package/schemas/plugins/{DllReferencePlugin.check.js → dll/DllReferencePlugin.check.js} +0 -0
  667. /package/schemas/plugins/{DllReferencePlugin.json → dll/DllReferencePlugin.json} +0 -0
@@ -0,0 +1,4380 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Alexander Akait @alexander-akait
4
+ */
5
+
6
+ "use strict";
7
+
8
+ // cspell:ignore yuku binop prec Prec
9
+
10
+ const { Parser: BaseParser, tokTypes } = require("acorn");
11
+
12
+ // acorn exports its token-context table but leaves it out of its public types
13
+ const tokContexts =
14
+ /** @type {Record<string, unknown>} */
15
+ (
16
+ /** @type {{ tokContexts: Record<string, unknown> }} */
17
+ (/** @type {unknown} */ (require("acorn"))).tokContexts
18
+ );
19
+
20
+ /** @typedef {{ token: string, isExpr: boolean, preserveSpace?: boolean, override?: unknown }} TokContextShim acorn TokContext fields read by the owned tokenizer */
21
+
22
+ // acorn's token contexts used by the inlined finishToken context updates
23
+ const CTX_B_STAT = /** @type {TokContextShim} */ (tokContexts.b_stat);
24
+ const CTX_B_EXPR = /** @type {TokContextShim} */ (tokContexts.b_expr);
25
+ const CTX_P_STAT = /** @type {TokContextShim} */ (tokContexts.p_stat);
26
+ const CTX_P_EXPR = /** @type {TokContextShim} */ (tokContexts.p_expr);
27
+ const CTX_F_STAT = /** @type {TokContextShim} */ (tokContexts.f_stat);
28
+ const CTX_F_EXPR = /** @type {TokContextShim} */ (tokContexts.f_expr);
29
+
30
+ // acorn exports its keyword→TokenType map but leaves it out of its public
31
+ // types; used by the word-classification lookups below.
32
+ const keywordTypes =
33
+ /** @type {Record<string, TokenType>} */
34
+ (
35
+ /** @type {{ keywordTypes: Record<string, TokenType> }} */
36
+ (/** @type {unknown} */ (require("acorn"))).keywordTypes
37
+ );
38
+
39
+ /** @typedef {import("acorn").Options} Options */
40
+ /** @typedef {import("acorn").Position} Position */
41
+ /** @typedef {import("acorn").Node} Node */
42
+ /** @typedef {import("acorn").Identifier} Identifier */
43
+ /** @typedef {import("acorn").ImportAttribute} ImportAttribute */
44
+ /** @typedef {import("acorn").ImportDefaultSpecifier} ImportDefaultSpecifier */
45
+ /** @typedef {import("acorn").ImportExpression} ImportExpression */
46
+ /** @typedef {import("acorn").Expression} Expression */
47
+ /** @typedef {import("acorn").ImportSpecifier | import("acorn").ImportDefaultSpecifier | import("acorn").ImportNamespaceSpecifier} AnyImportSpecifier */
48
+ /** @typedef {import("acorn").TokenType} TokenType */
49
+ /** @typedef {TokenType & { beforeExpr: boolean, isAssign?: boolean, prefix?: boolean, postfix?: boolean, binop: number | null, updateContext?: (prevType: TokenType) => void }} TokenTypeInternal acorn's internal TokenType fields, absent from its public types */
50
+ /** @typedef {import("estree").SourceLocation} SourceLocation */
51
+ /** @typedef {[number, number]} Range */
52
+ /** @typedef {"defer" | "source"} ImportPhase */
53
+ /** @typedef {import("estree").Comment & { start: number, end: number }} CollectedComment comment as JavascriptParser exposes it */
54
+
55
+ // Symbol-keyed so they stay out of for-in, Object.keys and JSON.stringify
56
+ // over AST nodes.
57
+ const kSource = Symbol("source");
58
+ const kRange = Symbol("range");
59
+ const kText = Symbol("text");
60
+ const kTextStart = Symbol("text start");
61
+
62
+ // Marks import attributes parsed from the legacy `assert {...}` syntax.
63
+ const LEGACY_ASSERT_ATTRIBUTES = Symbol("assert");
64
+
65
+ // acorn's binding types and scope flags, stable across acorn 8
66
+ const BIND_VAR = 1;
67
+ const BIND_LEXICAL = 2;
68
+ const SCOPE_TOP = 1;
69
+ const SCOPE_SIMPLE_CATCH = 32;
70
+ // SCOPE_TOP | SCOPE_FUNCTION | SCOPE_CLASS_STATIC_BLOCK
71
+ const SCOPE_VAR = 0b100000011;
72
+
73
+ // ASCII identifier-continuation chars ($ 0-9 A-Z _ a-z); css/html-style
74
+ // Uint8Array table so the tokenizer fast path is one load per char
75
+ const IDENT_CHAR = new Uint8Array(128);
76
+ IDENT_CHAR[36] = 1;
77
+ IDENT_CHAR[95] = 1;
78
+ for (let i = 48; i <= 57; i++) IDENT_CHAR[i] = 1;
79
+ for (let i = 65; i <= 90; i++) IDENT_CHAR[i] = 1;
80
+ for (let i = 97; i <= 122; i++) IDENT_CHAR[i] = 1;
81
+
82
+ // ASCII identifier-start chars (IDENT_CHAR minus 0-9), for token dispatch in
83
+ // the owned `nextToken` loop.
84
+ const IDENT_START = new Uint8Array(128);
85
+ IDENT_START[36] = 1;
86
+ IDENT_START[95] = 1;
87
+ for (let i = 65; i <= 90; i++) IDENT_START[i] = 1;
88
+ for (let i = 97; i <= 122; i++) IDENT_START[i] = 1;
89
+
90
+ // Single-char punctuators that acorn's `getTokenFromCode` reads as just
91
+ // `++pos; finishToken(type)` (no value, no operator state machine). Dispatching
92
+ // them from `nextToken`'s char table skips the extra `getTokenFromCode` call and
93
+ // its switch for the commonest tokens in JS ( ) { } [ ] ; , : — `0` is "not a
94
+ // simple punctuator" since token types are truthy objects.
95
+ const SIMPLE_PUNCT = Array.from({ length: 128 });
96
+ SIMPLE_PUNCT[40] = tokTypes.parenL;
97
+ SIMPLE_PUNCT[41] = tokTypes.parenR;
98
+ SIMPLE_PUNCT[59] = tokTypes.semi;
99
+ SIMPLE_PUNCT[44] = tokTypes.comma;
100
+ SIMPLE_PUNCT[91] = tokTypes.bracketL;
101
+ SIMPLE_PUNCT[93] = tokTypes.bracketR;
102
+ SIMPLE_PUNCT[123] = tokTypes.braceL;
103
+ SIMPLE_PUNCT[125] = tokTypes.braceR;
104
+ SIMPLE_PUNCT[58] = tokTypes.colon;
105
+
106
+ // Char classification for the owned `nextToken` (yuku's ws_class): one table
107
+ // load steers both the whitespace skip loop and the token dispatch. Token
108
+ // classes sort below CLS_SPACE so the skip loop exits on a single compare.
109
+ const CLS_OTHER = 0;
110
+ const CLS_IDENT = 1;
111
+ const CLS_PUNCT = 2;
112
+ const CLS_DOT = 3;
113
+ const CLS_EQ = 4;
114
+ const CLS_UNICODE = 5;
115
+ const CLS_SPACE = 6;
116
+ const CLS_NEWLINE = 7;
117
+ const CLS_SLASH = 8;
118
+ // Full `charCodeAt` range so the scan loop needs no `code > 127` branch per
119
+ // character: every non-ASCII code unit classifies as CLS_UNICODE (which sorts
120
+ // below CLS_SPACE, so the loop exits on the same single compare) and the
121
+ // dispatch delegates it to acorn's unicode-aware paths.
122
+ const CHAR_CLASS = new Uint8Array(0x10000).fill(CLS_UNICODE, 128);
123
+ for (let i = 0; i < 128; i++) {
124
+ if (IDENT_START[i] === 1 || i === 92) CHAR_CLASS[i] = CLS_IDENT;
125
+ else if (SIMPLE_PUNCT[i] !== undefined) CHAR_CLASS[i] = CLS_PUNCT;
126
+ }
127
+ CHAR_CLASS[46] = CLS_DOT;
128
+ CHAR_CLASS[61] = CLS_EQ;
129
+ CHAR_CLASS[32] = CLS_SPACE;
130
+ CHAR_CLASS[9] = CLS_SPACE;
131
+ CHAR_CLASS[11] = CLS_SPACE;
132
+ CHAR_CLASS[12] = CLS_SPACE;
133
+ CHAR_CLASS[10] = CLS_NEWLINE;
134
+ CHAR_CLASS[13] = CLS_NEWLINE;
135
+ CHAR_CLASS[47] = CLS_SLASH;
136
+
137
+ /**
138
+ * Drop-in replacement for acorn's `Node` that materializes `loc` and `range`
139
+ * on first access instead of allocating them during parsing. Most nodes never
140
+ * get either read, which saves three objects and an array per node.
141
+ */
142
+ class LazyLocNode {
143
+ /**
144
+ * @param {number} pos start offset
145
+ */
146
+ constructor(pos) {
147
+ this.type = "";
148
+ this.start = pos;
149
+ this.end = 0;
150
+ }
151
+
152
+ /**
153
+ * Memoized in a symbol slot — a plain store is far cheaper than making the
154
+ * property own via defineProperty, and the slot stays invisible to for-in,
155
+ * Object.keys and JSON.stringify. No `loc` is served at all — locations
156
+ * are derived from offsets via `JavascriptParser#getLocation`.
157
+ * @returns {Range} source range
158
+ */
159
+ get range() {
160
+ const cached = this[kRange];
161
+ if (cached !== undefined) return cached;
162
+ /** @type {Range} */
163
+ const range = [this.start, this.end];
164
+ if (this.end > 0) this[kRange] = range;
165
+ return range;
166
+ }
167
+
168
+ /**
169
+ * @param {Range} value source range
170
+ */
171
+ set range(value) {
172
+ this[kRange] = value;
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Single-shape `Identifier`, the most common node: all fields are assigned in
178
+ * one constructor, so every instance is born on its final hidden class instead
179
+ * of transitioning through acorn's start-empty-then-mutate construction.
180
+ */
181
+ class IdentifierNode {
182
+ /**
183
+ * @param {number} start start offset
184
+ * @param {number} end end offset
185
+ * @param {string} name identifier name
186
+ */
187
+ constructor(start, end, name) {
188
+ this.type = "Identifier";
189
+ this.start = start;
190
+ this.end = end;
191
+ this.name = name;
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Single-shape `Literal`; `bigint` and `regex` stay post-construction
197
+ * additions since both are rare.
198
+ */
199
+ class LiteralNode {
200
+ /**
201
+ * @param {number} start start offset
202
+ * @param {number} end end offset
203
+ * @param {unknown} value literal value
204
+ * @param {string} raw literal source text
205
+ */
206
+ constructor(start, end, value, raw) {
207
+ this.type = "Literal";
208
+ this.start = start;
209
+ this.end = end;
210
+ this.value = value;
211
+ this.raw = raw;
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Single-shape `MemberExpression`. `optional` is a real field on every
217
+ * instance since webpack always parses with `ecmaVersion >= 11`.
218
+ */
219
+ class MemberExpressionNode {
220
+ /**
221
+ * @param {number} start start offset
222
+ * @param {number} end end offset
223
+ * @param {Expression} object object expression
224
+ * @param {Node} property property node
225
+ * @param {boolean} computed whether the access is computed (`a[b]`)
226
+ * @param {boolean} optional whether the access is optional (`a?.b`)
227
+ */
228
+ constructor(start, end, object, property, computed, optional) {
229
+ this.type = "MemberExpression";
230
+ this.start = start;
231
+ this.end = end;
232
+ this.object = object;
233
+ this.property = property;
234
+ this.computed = computed;
235
+ this.optional = optional;
236
+ }
237
+ }
238
+
239
+ /**
240
+ * Single-shape `CallExpression`; `optional` as in `MemberExpressionNode`.
241
+ */
242
+ class CallExpressionNode {
243
+ /**
244
+ * @param {number} start start offset
245
+ * @param {number} end end offset
246
+ * @param {Expression} callee callee expression
247
+ * @param {Node[]} args call arguments
248
+ * @param {boolean} optional whether the call is optional (`a?.()`)
249
+ */
250
+ constructor(start, end, callee, args, optional) {
251
+ this.type = "CallExpression";
252
+ this.start = start;
253
+ this.end = end;
254
+ this.callee = callee;
255
+ this.arguments = args;
256
+ this.optional = optional;
257
+ }
258
+ }
259
+
260
+ /**
261
+ * Single-shape `ThisExpression`.
262
+ */
263
+ class ThisNode {
264
+ /**
265
+ * @param {number} start start offset
266
+ * @param {number} end end offset
267
+ */
268
+ constructor(start, end) {
269
+ this.type = "ThisExpression";
270
+ this.start = start;
271
+ this.end = end;
272
+ }
273
+ }
274
+
275
+ /**
276
+ * Single-shape `BinaryExpression`/`LogicalExpression` — identical field sets,
277
+ * so both node types share one hidden class.
278
+ */
279
+ class BinaryNode {
280
+ /**
281
+ * @param {number} start start offset
282
+ * @param {number} end end offset
283
+ * @param {"BinaryExpression" | "LogicalExpression"} type node type
284
+ * @param {Expression} left left operand
285
+ * @param {string} operator operator text
286
+ * @param {Expression} right right operand
287
+ */
288
+ constructor(start, end, type, left, operator, right) {
289
+ this.type = type;
290
+ this.start = start;
291
+ this.end = end;
292
+ this.left = left;
293
+ this.operator = operator;
294
+ this.right = right;
295
+ }
296
+ }
297
+
298
+ /**
299
+ * Single-shape `AssignmentExpression`.
300
+ */
301
+ class AssignmentNode {
302
+ /**
303
+ * @param {number} start start offset
304
+ * @param {number} end end offset
305
+ * @param {string} operator assignment operator text
306
+ * @param {Node} left assignment target
307
+ * @param {Expression} right assigned value
308
+ */
309
+ constructor(start, end, operator, left, right) {
310
+ this.type = "AssignmentExpression";
311
+ this.start = start;
312
+ this.end = end;
313
+ this.operator = operator;
314
+ this.left = left;
315
+ this.right = right;
316
+ }
317
+ }
318
+
319
+ /**
320
+ * Single-shape `UnaryExpression`/`UpdateExpression` — identical field sets,
321
+ * so both node types share one hidden class.
322
+ */
323
+ class UnaryNode {
324
+ /**
325
+ * @param {number} start start offset
326
+ * @param {number} end end offset
327
+ * @param {"UnaryExpression" | "UpdateExpression"} type node type
328
+ * @param {string} operator operator text
329
+ * @param {boolean} prefix whether the operator is prefixed
330
+ * @param {Expression} argument operand
331
+ */
332
+ constructor(start, end, type, operator, prefix, argument) {
333
+ this.type = type;
334
+ this.start = start;
335
+ this.end = end;
336
+ this.operator = operator;
337
+ this.prefix = prefix;
338
+ this.argument = argument;
339
+ }
340
+ }
341
+
342
+ /**
343
+ * Single-shape `VariableDeclaration` (statement position; `for` heads keep the
344
+ * generic node since their caller finishes them).
345
+ */
346
+ class VariableDeclarationNode {
347
+ /**
348
+ * @param {number} start start offset
349
+ * @param {number} end end offset
350
+ * @param {Node[]} declarations declarators
351
+ * @param {string} kind declaration kind (`var`/`let`/`const`/`using`)
352
+ */
353
+ constructor(start, end, declarations, kind) {
354
+ this.type = "VariableDeclaration";
355
+ this.start = start;
356
+ this.end = end;
357
+ this.declarations = declarations;
358
+ this.kind = kind;
359
+ }
360
+ }
361
+
362
+ /**
363
+ * Single-shape `VariableDeclarator`.
364
+ */
365
+ class VariableDeclaratorNode {
366
+ /**
367
+ * @param {number} start start offset
368
+ * @param {number} end end offset
369
+ * @param {Node} id binding target
370
+ * @param {Expression | null} init initializer
371
+ */
372
+ constructor(start, end, id, init) {
373
+ this.type = "VariableDeclarator";
374
+ this.start = start;
375
+ this.end = end;
376
+ this.id = id;
377
+ this.init = init;
378
+ }
379
+ }
380
+
381
+ /**
382
+ * Single-shape `ExpressionStatement`.
383
+ */
384
+ class ExpressionStatementNode {
385
+ /**
386
+ * @param {number} start start offset
387
+ * @param {number} end end offset
388
+ * @param {Expression} expression the statement's expression
389
+ */
390
+ constructor(start, end, expression) {
391
+ this.type = "ExpressionStatement";
392
+ this.start = start;
393
+ this.end = end;
394
+ this.expression = expression;
395
+ }
396
+ }
397
+
398
+ /**
399
+ * Single-shape `BlockStatement`.
400
+ */
401
+ class BlockStatementNode {
402
+ /**
403
+ * @param {number} start start offset
404
+ * @param {number} end end offset
405
+ * @param {Node[]} body statements
406
+ */
407
+ constructor(start, end, body) {
408
+ this.type = "BlockStatement";
409
+ this.start = start;
410
+ this.end = end;
411
+ this.body = body;
412
+ }
413
+ }
414
+
415
+ /**
416
+ * Single-shape `IfStatement`.
417
+ */
418
+ class IfStatementNode {
419
+ /**
420
+ * @param {number} start start offset
421
+ * @param {number} end end offset
422
+ * @param {Expression} test condition
423
+ * @param {Node} consequent then-branch
424
+ * @param {Node | null} alternate else-branch
425
+ */
426
+ constructor(start, end, test, consequent, alternate) {
427
+ this.type = "IfStatement";
428
+ this.start = start;
429
+ this.end = end;
430
+ this.test = test;
431
+ this.consequent = consequent;
432
+ this.alternate = alternate;
433
+ }
434
+ }
435
+
436
+ /**
437
+ * Single-shape `ReturnStatement`.
438
+ */
439
+ class ReturnStatementNode {
440
+ /**
441
+ * @param {number} start start offset
442
+ * @param {number} end end offset
443
+ * @param {Expression | null} argument returned expression
444
+ */
445
+ constructor(start, end, argument) {
446
+ this.type = "ReturnStatement";
447
+ this.start = start;
448
+ this.end = end;
449
+ this.argument = argument;
450
+ }
451
+ }
452
+
453
+ /**
454
+ * Single-shape `ConditionalExpression`.
455
+ */
456
+ class ConditionalExpressionNode {
457
+ /**
458
+ * @param {number} start start offset
459
+ * @param {number} end end offset
460
+ * @param {Expression} test condition
461
+ * @param {Expression} consequent then-value
462
+ * @param {Expression} alternate else-value
463
+ */
464
+ constructor(start, end, test, consequent, alternate) {
465
+ this.type = "ConditionalExpression";
466
+ this.start = start;
467
+ this.end = end;
468
+ this.test = test;
469
+ this.consequent = consequent;
470
+ this.alternate = alternate;
471
+ }
472
+ }
473
+
474
+ /**
475
+ * Single-shape `NewExpression`.
476
+ */
477
+ class NewExpressionNode {
478
+ /**
479
+ * @param {number} start start offset
480
+ * @param {number} end end offset
481
+ * @param {Expression} callee constructed expression
482
+ * @param {Expression[]} args constructor arguments
483
+ */
484
+ constructor(start, end, callee, args) {
485
+ this.type = "NewExpression";
486
+ this.start = start;
487
+ this.end = end;
488
+ this.callee = callee;
489
+ this.arguments = args;
490
+ }
491
+ }
492
+
493
+ /**
494
+ * Single-shape `ArrayExpression`.
495
+ */
496
+ class ArrayExpressionNode {
497
+ /**
498
+ * @param {number} start start offset
499
+ * @param {number} end end offset
500
+ * @param {(Expression | null)[]} elements array elements (`null` for holes)
501
+ */
502
+ constructor(start, end, elements) {
503
+ this.type = "ArrayExpression";
504
+ this.start = start;
505
+ this.end = end;
506
+ this.elements = elements;
507
+ }
508
+ }
509
+
510
+ /**
511
+ * Single-shape `TemplateLiteral`.
512
+ */
513
+ class TemplateLiteralNode {
514
+ /**
515
+ * @param {number} start start offset
516
+ * @param {number} end end offset
517
+ * @param {Expression[]} expressions substitution expressions
518
+ * @param {Node[]} quasis template chunks
519
+ */
520
+ constructor(start, end, expressions, quasis) {
521
+ this.type = "TemplateLiteral";
522
+ this.start = start;
523
+ this.end = end;
524
+ this.expressions = expressions;
525
+ this.quasis = quasis;
526
+ }
527
+ }
528
+
529
+ /**
530
+ * Single-shape `TemplateElement`.
531
+ */
532
+ class TemplateElementNode {
533
+ /**
534
+ * @param {number} start start offset
535
+ * @param {number} end end offset
536
+ * @param {{ raw: string, cooked: string | null }} value chunk text
537
+ * @param {boolean} tail whether this is the closing chunk
538
+ */
539
+ constructor(start, end, value, tail) {
540
+ this.type = "TemplateElement";
541
+ this.start = start;
542
+ this.end = end;
543
+ this.value = value;
544
+ this.tail = tail;
545
+ }
546
+ }
547
+
548
+ /**
549
+ * Single-shape `ObjectExpression`/`ObjectPattern` — identical field sets, so
550
+ * both node types share one hidden class.
551
+ */
552
+ class ObjectNode {
553
+ /**
554
+ * @param {number} start start offset
555
+ * @param {number} end end offset
556
+ * @param {"ObjectExpression" | "ObjectPattern"} type node type
557
+ * @param {Node[]} properties properties
558
+ */
559
+ constructor(start, end, type, properties) {
560
+ this.type = type;
561
+ this.start = start;
562
+ this.end = end;
563
+ this.properties = properties;
564
+ }
565
+ }
566
+
567
+ /**
568
+ * Pre-shaped `Property`: acorn fills property nodes through shared
569
+ * subroutines (`parsePropertyName`/`parsePropertyValue`), so instead of
570
+ * rebuilding that flow the fields are all declared up-front and acorn's
571
+ * writes land in existing slots — one hidden class, no transitions (yuku's
572
+ * decoder emits `Property` with this fixed shape). Every non-throwing acorn
573
+ * branch assigns `computed`, `key`, `value` and `kind`; `finishNode` sets
574
+ * `type` and `end`.
575
+ */
576
+ class PropertyNode {
577
+ /**
578
+ * @param {number} start start offset
579
+ */
580
+ constructor(start) {
581
+ this.type = "";
582
+ this.start = start;
583
+ this.end = 0;
584
+ this.method = false;
585
+ this.shorthand = false;
586
+ this.computed = false;
587
+ /** @type {Node | null} */
588
+ this.key = null;
589
+ /** @type {Node | null} */
590
+ this.value = null;
591
+ this.kind = "";
592
+ }
593
+ }
594
+
595
+ /**
596
+ * Single-shape `SpreadElement`/`RestElement` — identical field sets, so both
597
+ * node types share one hidden class.
598
+ */
599
+ class RestSpreadNode {
600
+ /**
601
+ * @param {number} start start offset
602
+ * @param {number} end end offset
603
+ * @param {"SpreadElement" | "RestElement"} type node type
604
+ * @param {Node} argument spread/rest argument
605
+ */
606
+ constructor(start, end, type, argument) {
607
+ this.type = type;
608
+ this.start = start;
609
+ this.end = end;
610
+ this.argument = argument;
611
+ }
612
+ }
613
+
614
+ // Shared zero-length arguments array for `new X` without parens, mirroring
615
+ // acorn's module-level `empty`.
616
+ /** @type {Expression[]} */
617
+ const EMPTY_NEW_ARGS = [];
618
+
619
+ /**
620
+ * Mirror of acorn's module-level `isLocalVariableAccess`.
621
+ * @param {Node} node checked node
622
+ * @returns {boolean} whether the node reads a local variable
623
+ */
624
+ const isLocalVariableAccess = (node) =>
625
+ node.type === "Identifier" ||
626
+ (node.type === "ParenthesizedExpression" &&
627
+ isLocalVariableAccess(
628
+ /** @type {Node} */ (
629
+ /** @type {Node & { expression?: Node }} */ (node).expression
630
+ )
631
+ ));
632
+
633
+ /**
634
+ * Mirror of acorn's module-level `isPrivateFieldAccess`.
635
+ * @param {Node} node checked node
636
+ * @returns {boolean} whether the node accesses a private field
637
+ */
638
+ const isPrivateFieldAccess = (node) =>
639
+ (node.type === "MemberExpression" &&
640
+ /** @type {Node} */ (
641
+ /** @type {Node & { property?: Node }} */ (node).property
642
+ ).type === "PrivateIdentifier") ||
643
+ (node.type === "ChainExpression" &&
644
+ isPrivateFieldAccess(
645
+ /** @type {Node} */ (
646
+ /** @type {Node & { expression?: Node }} */ (node).expression
647
+ )
648
+ )) ||
649
+ (node.type === "ParenthesizedExpression" &&
650
+ isPrivateFieldAccess(
651
+ /** @type {Node} */ (
652
+ /** @type {Node & { expression?: Node }} */ (node).expression
653
+ )
654
+ ));
655
+
656
+ // the dedicated node classes serve `range` exactly like LazyLocNode
657
+ for (const NodeClass of [
658
+ IdentifierNode,
659
+ LiteralNode,
660
+ MemberExpressionNode,
661
+ CallExpressionNode,
662
+ ThisNode,
663
+ BinaryNode,
664
+ AssignmentNode,
665
+ UnaryNode,
666
+ VariableDeclarationNode,
667
+ VariableDeclaratorNode,
668
+ ExpressionStatementNode,
669
+ BlockStatementNode,
670
+ IfStatementNode,
671
+ ReturnStatementNode,
672
+ ConditionalExpressionNode,
673
+ NewExpressionNode,
674
+ ArrayExpressionNode,
675
+ TemplateLiteralNode,
676
+ TemplateElementNode,
677
+ ObjectNode,
678
+ PropertyNode,
679
+ RestSpreadNode
680
+ ]) {
681
+ for (const key of ["range"]) {
682
+ Object.defineProperty(
683
+ NodeClass.prototype,
684
+ key,
685
+ /** @type {PropertyDescriptor} */
686
+ (Object.getOwnPropertyDescriptor(LazyLocNode.prototype, key))
687
+ );
688
+ }
689
+ }
690
+
691
+ /**
692
+ * Comment collected without slicing its text out of the source: only magic
693
+ * comments and pure annotations ever get their text read, so the slice is
694
+ * deferred to the first `value` access and memoized like `loc`.
695
+ */
696
+ class LazyComment {
697
+ /**
698
+ * @param {boolean} block whether this is a block comment
699
+ * @param {number} textStart offset right after the comment opener
700
+ * @param {number} start start offset
701
+ * @param {number} end end offset
702
+ * @param {string} source full source text for the lazy `value` slice
703
+ */
704
+ constructor(block, textStart, start, end, source) {
705
+ /** @type {"Block" | "Line"} */
706
+ this.type = block ? "Block" : "Line";
707
+ this.start = start;
708
+ this.end = end;
709
+ /** @type {Range} */
710
+ this.range = [start, end];
711
+ this[kSource] = source;
712
+ this[kTextStart] = textStart;
713
+ }
714
+
715
+ /**
716
+ * @returns {string} comment text without the delimiters
717
+ */
718
+ get value() {
719
+ const cached = this[kText];
720
+ if (cached !== undefined) return cached;
721
+ return (this[kText] = this[kSource].slice(
722
+ this[kTextStart],
723
+ this.type === "Block" ? this.end - 2 : this.end
724
+ ));
725
+ }
726
+
727
+ /**
728
+ * @param {string} value comment text
729
+ */
730
+ set value(value) {
731
+ this[kText] = value;
732
+ }
733
+ }
734
+
735
+ /**
736
+ * Replaces acorn's array-backed `Scope`: membership checks in `declareName`
737
+ * are `indexOf` there, which goes quadratic on files with thousands of
738
+ * bindings per scope (bundled or minified inputs). The three Sets are
739
+ * allocated lazily — most scopes declare into only one (module `functions` is
740
+ * always empty), so ~⅔ of the Sets are never needed.
741
+ */
742
+ class Scope {
743
+ /**
744
+ * @param {number} flags scope flags
745
+ */
746
+ constructor(flags) {
747
+ this.flags = flags;
748
+ /** @type {Set<string> | undefined} */
749
+ this.var = undefined;
750
+ /** @type {Set<string> | undefined} */
751
+ this.lexical = undefined;
752
+ /** @type {Set<string> | undefined} */
753
+ this.functions = undefined;
754
+ // first lexically-declared name; stands in for acorn's `lexical[0]`
755
+ // (the catch parameter of a simple catch scope)
756
+ /** @type {string | undefined} */
757
+ this.firstLexical = undefined;
758
+ }
759
+ }
760
+
761
+ /**
762
+ * Acorn's methods and state used by `WebpackParser` but missing from its
763
+ * public types, plus `WebpackParser`'s own fields, so overridden methods can
764
+ * declare `this` precisely.
765
+ * @typedef {import("acorn").Parser & {
766
+ * type: TokenType,
767
+ * value: unknown,
768
+ * start: number,
769
+ * startLoc?: Position,
770
+ * containsEsc: boolean,
771
+ * exprAllowed: boolean,
772
+ * options: Options,
773
+ * end: number,
774
+ * lastTokEnd: number,
775
+ * canInsertSemicolon: () => boolean,
776
+ * nextToken: () => void,
777
+ * next: (ignoreEscapeSequenceInKeyword?: boolean) => void,
778
+ * eat: (type: TokenType) => boolean,
779
+ * expect: (type: TokenType) => void,
780
+ * afterTrailingComma: (type: TokenType, notNext?: boolean) => boolean,
781
+ * unexpected: (pos?: number) => never,
782
+ * raise: (pos: number, message: string) => never,
783
+ * raiseRecoverable: (pos: number, message: string) => void,
784
+ * isContextual: (name: string) => boolean,
785
+ * parseIdent: (liberal?: boolean) => Identifier,
786
+ * parseLiteral: (value: unknown) => Node,
787
+ * awaitIdentPos: number,
788
+ * lastTokStart: number,
789
+ * yieldPos: number,
790
+ * awaitPos: number,
791
+ * parseExpression: () => Expression,
792
+ * parseSpread: (refDestructuringErrors?: DestructuringErrorsShim | null) => Node,
793
+ * braceIsBlock: (prevType: TokenType) => boolean,
794
+ * _gapHasNewline: () => boolean,
795
+ * parseExprList: (close: TokenType, allowTrailingComma: boolean, allowEmpty: boolean, refDestructuringErrors?: DestructuringErrorsShim | null) => Expression[],
796
+ * parsePrivateIdent: () => Node,
797
+ * parseTemplate: (opts: { isTagged: boolean }) => Node,
798
+ * shouldParseAsyncArrow: () => boolean,
799
+ * parseSubscriptAsyncArrow: (startPos: number, startLoc: Position | undefined, exprList: Expression[], forInit: boolean | string) => Expression,
800
+ * checkPatternErrors: (refDestructuringErrors: DestructuringErrorsShim, isAssign: boolean) => void,
801
+ * checkYieldAwaitInDefaultParams: () => void,
802
+ * checkExpressionErrors: (refDestructuringErrors?: DestructuringErrorsShim | null, andThrow?: boolean) => boolean,
803
+ * parseSubscript: (base: Expression, startPos: number, startLoc: Position | undefined, noCalls: boolean | undefined, maybeAsyncArrow: boolean, optionalChained: boolean, forInit: boolean | string) => Expression,
804
+ * parseExprAtom: (refDestructuringErrors?: DestructuringErrorsShim | null, forInit?: boolean | string, forNew?: boolean) => Expression,
805
+ * buildBinary: (startPos: number, startLoc: Position | undefined, left: Expression, right: Expression, op: string, logical: boolean) => Expression,
806
+ * parseMaybeAssign: (forInit?: boolean | string, refDestructuringErrors?: DestructuringErrorsShim | null, afterLeftParse?: (this: unknown, left: Expression, startPos: number, startLoc?: Position) => Expression) => Expression,
807
+ * parseMaybeConditional: (forInit?: boolean | string, refDestructuringErrors?: DestructuringErrorsShim | null) => Expression,
808
+ * parseMaybeUnary: (refDestructuringErrors: DestructuringErrorsShim | null, sawUnary: boolean, incDec: boolean, forInit?: boolean | string) => Expression,
809
+ * parseExprSubscripts: (refDestructuringErrors?: DestructuringErrorsShim | null, forInit?: boolean | string) => Expression,
810
+ * parseAwait: (forInit?: boolean | string) => Expression,
811
+ * canAwait: boolean,
812
+ * privateNameStack: unknown[],
813
+ * semicolon: () => void,
814
+ * exitScope: () => void,
815
+ * parseStatement: (context: string | null, topLevel?: boolean, exports?: unknown) => Node,
816
+ * parseBindingAtom: () => Node,
817
+ * parseVarStatement: (node: Node, kind: string, allowMissingInitializer?: boolean) => Node,
818
+ * parseVar: (node: Node, isFor: boolean, kind: string, allowMissingInitializer?: boolean) => Node,
819
+ * parseExpressionStatement: (node: Node, expr: Expression) => Node,
820
+ * parseParenExpression: () => Expression,
821
+ * parseIfStatement: (node: Node) => Node,
822
+ * parseReturnStatement: (node: Node) => Node,
823
+ * insertSemicolon: () => boolean,
824
+ * allowReturn: boolean,
825
+ * allowNewDotTarget: boolean,
826
+ * parseExprOps: (forInit?: boolean | string, refDestructuringErrors?: DestructuringErrorsShim | null) => Expression,
827
+ * parseExprOp: (left: Expression, leftStartPos: number, leftStartLoc: Position | undefined, minPrec: number, forInit?: boolean | string) => Expression,
828
+ * _deStack: DestructuringErrorsShim[],
829
+ * _deDepth: number,
830
+ * _ecmaVersion: number,
831
+ * _noLocations: boolean,
832
+ * _validRegexpFlags: string,
833
+ * _propHashFastPath: boolean,
834
+ * _propHashStack: { proto: boolean }[],
835
+ * _propHashDepth: number,
836
+ * _acquireDestructuringErrors: () => DestructuringErrorsShim,
837
+ * _releaseDestructuringErrors: () => void,
838
+ * parseSubscripts: (base: Expression, startPos: number, startLoc: Position | undefined, noCalls?: boolean, forInit?: boolean | string) => Expression,
839
+ * parseNew: () => Expression,
840
+ * parseTemplateElement: (opts: { isTagged: boolean }) => Node,
841
+ * parseBlock: (createNewLexicalScope?: boolean, node?: Node, exitStrict?: boolean) => Node,
842
+ * parseYield: (forInit?: boolean | string) => Expression,
843
+ * toAssignable: (node: Node, isBinding?: boolean, refDestructuringErrors?: DestructuringErrorsShim | null) => Node,
844
+ * checkLValPattern: (expr: Node, bindingType?: number, checkClashes?: unknown) => void,
845
+ * checkUnreserved: (ref: Identifier) => void,
846
+ * enterScope: (flags: number) => void,
847
+ * readRegexp: () => void,
848
+ * potentialArrowAt: number,
849
+ * potentialArrowInForAwait: boolean,
850
+ * overrideContext: (tokenCtx: unknown) => void,
851
+ * parseFunction: (node: Node, statement: number, allowExpressionBody?: boolean, isAsync?: boolean, forInit?: boolean | string) => Expression,
852
+ * parseArrowExpression: (node: Node, params: Node[], isAsync: boolean, forInit?: boolean | string) => Expression,
853
+ * _subscriptFastPath: boolean,
854
+ * checkLValSimple: (expr: Node, bindingType?: number) => void,
855
+ * startNode: () => Node,
856
+ * startNodeAt: (pos: number, loc?: Position) => Node,
857
+ * finishNode: (node: Node, type: string) => Node,
858
+ * readWord1: () => string,
859
+ * readWord: () => void,
860
+ * readToken: (code: number) => void,
861
+ * getTokenFromCode: (code: number) => void,
862
+ * fullCharCodeAtPos: () => number,
863
+ * skipSpace: () => void,
864
+ * skipLineComment: (startSkip: number) => void,
865
+ * skipBlockComment: () => void,
866
+ * readString: (quote: number) => void,
867
+ * readNumber: (startsWithDot: boolean) => void,
868
+ * readRadixNumber: (radix: number) => void,
869
+ * readTmplToken: () => void,
870
+ * finishToken: (type: TokenType, value?: unknown) => void,
871
+ * context: TokContextShim[],
872
+ * pos: number,
873
+ * input: string,
874
+ * scopeStack: Scope[],
875
+ * currentScope: () => Scope,
876
+ * currentThisScope: () => Scope,
877
+ * currentVarScope: () => Scope,
878
+ * keywords: RegExp,
879
+ * reservedWords: RegExp,
880
+ * reservedWordsStrict: RegExp,
881
+ * reservedWordsStrictBind: RegExp,
882
+ * strict: boolean,
883
+ * inGenerator: boolean,
884
+ * inGeneratorContext: () => boolean,
885
+ * inAsync: boolean,
886
+ * inClassStaticBlock: boolean,
887
+ * _wordLookups: WordLookups,
888
+ * treatFunctionsAsVar: boolean,
889
+ * treatFunctionsAsVarInScope: (scope: Scope) => boolean,
890
+ * inModule: boolean,
891
+ * undefinedExports: Record<string, Node>,
892
+ * parseObj: (isPattern: boolean, refDestructuringErrors?: DestructuringErrorsShim | null) => Node,
893
+ * parseProperty: (isPattern: boolean, refDestructuringErrors?: DestructuringErrorsShim | null) => Node,
894
+ * parsePropertyName: (prop: Node) => Node,
895
+ * parsePropertyValue: (prop: Node, isPattern: boolean, isGenerator: boolean, isAsync: boolean, startPos: number | undefined, startLoc: Position | undefined, refDestructuringErrors: DestructuringErrorsShim | null | undefined, containsEsc: boolean) => void,
896
+ * isAsyncProp: (prop: Node) => boolean,
897
+ * checkPropClash: (prop: Node, propHash: Record<string, unknown>, refDestructuringErrors?: DestructuringErrorsShim | null) => void,
898
+ * parseImport: (node: Node) => Node,
899
+ * parseExport: (node: Node, exports: unknown) => Node,
900
+ * parseImportSpecifiers: () => AnyImportSpecifier[],
901
+ * parseImportAttribute: () => ImportAttribute,
902
+ * parseExprImport: (forNew: boolean) => Expression,
903
+ * parseImportMeta: (node: Node) => Expression,
904
+ * parseDynamicImport: (node: Node) => Expression,
905
+ * _lazy: boolean,
906
+ * _importPhase: ImportPhase | null,
907
+ * _importPhasesEnabled: boolean,
908
+ * _lazyComments: CollectedComment[] | undefined,
909
+ * _newlineBefore: 0 | 1 | 2,
910
+ * _fullTokenFastPath: boolean,
911
+ * _stmtFastPath: boolean,
912
+ * isLet: (context?: string | null) => boolean,
913
+ * parseLabeledStatement: (node: Node, maybeName: string, expr: Identifier, context: string | null) => Node,
914
+ * _parseVarInto: (declarations: Node[], isFor: boolean, kind: string, allowMissingInitializer?: boolean) => void,
915
+ * _parseVarStatementAt: (start: number, kind: string, allowMissingInitializer?: boolean) => Node,
916
+ * _parseIfStatementAt: (start: number) => Node,
917
+ * _parseReturnStatementAt: (start: number) => Node,
918
+ * _parseExpressionStatementAt: (start: number, expr: Expression) => Node,
919
+ * _moduleFallback: boolean,
920
+ * _moduleSyntaxSeen: boolean,
921
+ * _tryModuleFallback: () => boolean,
922
+ * }} ParserInternals
923
+ */
924
+
925
+ // internal methods are absent from acorn's types, so super calls do not
926
+ // type-check; call through a typed view of the base prototype instead
927
+ const base = /** @type {ParserInternals} */ (
928
+ /** @type {unknown} */ (BaseParser.prototype)
929
+ );
930
+
931
+ /**
932
+ * Acorn's internal destructuring-errors record; the class itself is not
933
+ * exported. Owned methods must create records with the same hidden class the
934
+ * rest of the expression parser reads, or every record field access there
935
+ * turns polymorphic.
936
+ * @typedef {{ shorthandAssign: number, trailingComma: number, parenthesizedAssign: number, parenthesizedBind: number, doubleProto: number }} DestructuringErrorsShim
937
+ */
938
+
939
+ // Capture the class at module load: parse one expression through a probe
940
+ // whose `checkExpressionErrors` sees the record the base parser created.
941
+ /** @type {{ new (): DestructuringErrorsShim } | null} */
942
+ const DestructuringErrorsClass = (() => {
943
+ /** @type {{ new (): DestructuringErrorsShim } | null} */
944
+ let captured = null;
945
+ class Probe extends BaseParser {
946
+ /**
947
+ * @param {DestructuringErrorsShim | null} refDestructuringErrors record to inspect
948
+ * @param {boolean=} andThrow whether to throw on error
949
+ * @returns {boolean} whether an error position was set
950
+ */
951
+ checkExpressionErrors(refDestructuringErrors, andThrow) {
952
+ if (refDestructuringErrors) {
953
+ captured =
954
+ /** @type {{ new (): DestructuringErrorsShim }} */
955
+ (refDestructuringErrors.constructor);
956
+ }
957
+ return /** @type {ParserInternals} */ (
958
+ /** @type {unknown} */ (base)
959
+ ).checkExpressionErrors.call(this, refDestructuringErrors, andThrow);
960
+ }
961
+ }
962
+ Probe.parse("a", { ecmaVersion: 2020 });
963
+ // cast: the closure assignment above is invisible to control-flow analysis
964
+ return /** @type {{ new (): DestructuringErrorsShim } | null} */ (captured);
965
+ })();
966
+
967
+ /**
968
+ * @returns {DestructuringErrorsShim} fresh destructuring-errors record on acorn's own class (plain-object fallback if the capture ever fails)
969
+ */
970
+ const createDestructuringErrors = () => {
971
+ const DestructuringErrors = DestructuringErrorsClass;
972
+ return DestructuringErrors !== null
973
+ ? new DestructuringErrors()
974
+ : {
975
+ shorthandAssign: -1,
976
+ trailingComma: -1,
977
+ parenthesizedAssign: -1,
978
+ parenthesizedBind: -1,
979
+ doubleProto: -1
980
+ };
981
+ };
982
+
983
+ /**
984
+ * Reserved-word classification for `checkUnreserved`'s single lookup:
985
+ * `1` keyword, `2` reserved in sloppy and strict mode, `3` reserved in strict
986
+ * mode only.
987
+ * @typedef {1 | 2 | 3} ReservedKind
988
+ */
989
+
990
+ /**
991
+ * @typedef {object} WordLookups
992
+ * @property {Map<string, TokenType>} keywords keyword name → token type
993
+ * @property {Map<string, ReservedKind>} reservedKinds identifier name → reserved kind
994
+ * @property {number} reservedMaxLen longest key in `reservedKinds`
995
+ * @property {{ test: (name: string) => boolean }} reservedBindTest strict-mode binding check, a Set-backed stand-in for acorn's `reservedWordsStrictBind` regexp
996
+ */
997
+
998
+ // One entry per distinct keyword/reserved-word set; webpack parses with a
999
+ // single option set, making this effectively a one-time build shared across
1000
+ // every parse.
1001
+ /** @type {Map<string, WordLookups>} */
1002
+ const wordLookupsCache = new Map();
1003
+
1004
+ /**
1005
+ * @param {string} word interned candidate
1006
+ * @param {string} input source code
1007
+ * @param {number} start word start offset
1008
+ * @param {number} len word length (already known equal to `word.length`)
1009
+ * @returns {boolean} whether the source span spells `word`
1010
+ */
1011
+ const sameWord = (word, input, start, len) => {
1012
+ for (let i = 0; i < len; i++) {
1013
+ if (word.charCodeAt(i) !== input.charCodeAt(start + i)) return false;
1014
+ }
1015
+ return true;
1016
+ };
1017
+
1018
+ // Direct-mapped identifier cache for `readWord1`: one slot per hash, verified
1019
+ // by char compare, overwritten on collision. Shared across parses — hits are
1020
+ // content-checked, so a stale entry is merely a miss. Only words short enough
1021
+ // to be flat V8 strings (never slices retaining their whole source) are stored.
1022
+ const WORD_CACHE_MASK = 0x1fff;
1023
+ /** @type {(string | null)[]} */
1024
+ const WORD_CACHE = Array.from({ length: WORD_CACHE_MASK + 1 }, () => null);
1025
+ const WORD_CACHE_MAX_LEN = 12;
1026
+
1027
+ // Multi-char operator strings for `finishOp` (`=>`, `===`, `&&=`, …), keyed by
1028
+ // their char codes packed 7 bits apart — collision-free for ASCII operators up
1029
+ // to acorn's maximum of 4 chars (`>>>=`), so the set stays ~40 entries.
1030
+ /** @type {Map<number, string>} */
1031
+ const OP_CACHE = new Map();
1032
+
1033
+ // Sticky mirrors of acorn's `skipWhiteSpace` / string-literal / `lineBreak`
1034
+ // regexes for the owned `strictDirective` (they scan at an offset, no slice).
1035
+ const STRICT_SKIP_WS = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;
1036
+ const STRICT_LITERAL = /(?:'((?:\\[^]|[^'\\])*?)'|"((?:\\[^]|[^"\\])*?)")/y;
1037
+ const STRICT_LINE_BREAK = /\r\n?|\n|\u2028|\u2029/;
1038
+
1039
+ /**
1040
+ * @param {RegExp} re acorn `wordsRegexp` output (`^(?:a|b|c)$`)
1041
+ * @returns {Set<string>} the alternation's words
1042
+ */
1043
+ const wordsRegexpToSet = (re) => {
1044
+ const match = /^\^\(\?:(.*)\)\$$/.exec(re.source);
1045
+ const body = match ? match[1] : "";
1046
+ return new Set(body ? body.split("|") : []);
1047
+ };
1048
+
1049
+ // One-entry identity memo in front of the string-keyed cache: acorn's
1050
+ // `wordsRegexp` interns its regexps, so identity captures the whole word set,
1051
+ // and builds construct thousands of parsers with one option set — this makes
1052
+ // the per-construction lookup three compares instead of a long key concat.
1053
+ /** @type {RegExp | undefined} */
1054
+ let lastKeywordsRe;
1055
+ /** @type {RegExp | undefined} */
1056
+ let lastReservedRe;
1057
+ /** @type {RegExp | undefined} */
1058
+ let lastReservedStrictRe;
1059
+ /** @type {WordLookups | undefined} */
1060
+ let lastWordLookups;
1061
+
1062
+ /**
1063
+ * Mirrors acorn's `keywords` / `reservedWords` / `reservedWordsStrict` regexps
1064
+ * as Map/Set lookups. Membership is the hot per-word test in `readWord` and
1065
+ * `checkUnreserved`, and a hash lookup beats an anchored alternation regexp.
1066
+ * @param {ParserInternals} parser parser instance
1067
+ * @returns {WordLookups} lookups for this parser's keyword set
1068
+ */
1069
+ const getWordLookups = (parser) => {
1070
+ if (
1071
+ parser.keywords === lastKeywordsRe &&
1072
+ parser.reservedWords === lastReservedRe &&
1073
+ parser.reservedWordsStrict === lastReservedStrictRe
1074
+ ) {
1075
+ return /** @type {WordLookups} */ (lastWordLookups);
1076
+ }
1077
+ // module vs script share a keyword set but differ in reserved words, so the
1078
+ // key must cover all three regexps
1079
+ const key = `${parser.keywords.source}\n${parser.reservedWords.source}\n${parser.reservedWordsStrict.source}`;
1080
+ lastKeywordsRe = parser.keywords;
1081
+ lastReservedRe = parser.reservedWords;
1082
+ lastReservedStrictRe = parser.reservedWordsStrict;
1083
+ const cached = wordLookupsCache.get(key);
1084
+ if (cached !== undefined) {
1085
+ lastWordLookups = cached;
1086
+ return cached;
1087
+ }
1088
+ /** @type {Map<string, TokenType>} */
1089
+ const keywords = new Map();
1090
+ // acorn's keyword regexp is a subset of keywordTypes for the ecmaVersion
1091
+ for (const name of Object.keys(keywordTypes)) {
1092
+ if (parser.keywords.test(name)) keywords.set(name, keywordTypes[name]);
1093
+ }
1094
+ const reserved = wordsRegexpToSet(parser.reservedWords);
1095
+ /** @type {Map<string, ReservedKind>} */
1096
+ const reservedKinds = new Map();
1097
+ for (const name of reserved) reservedKinds.set(name, 2);
1098
+ for (const name of wordsRegexpToSet(parser.reservedWordsStrict)) {
1099
+ if (!reserved.has(name)) reservedKinds.set(name, 3);
1100
+ }
1101
+ // keyword classification wins, matching acorn's keyword-first check
1102
+ for (const name of keywords.keys()) reservedKinds.set(name, 1);
1103
+ const reservedBind = wordsRegexpToSet(parser.reservedWordsStrictBind);
1104
+ let reservedMaxLen = 0;
1105
+ for (const name of reservedKinds.keys()) {
1106
+ if (name.length > reservedMaxLen) reservedMaxLen = name.length;
1107
+ }
1108
+ /** @type {WordLookups} */
1109
+ const lookups = {
1110
+ keywords,
1111
+ reservedKinds,
1112
+ reservedMaxLen,
1113
+ reservedBindTest: { test: (name) => reservedBind.has(name) }
1114
+ };
1115
+ wordLookupsCache.set(key, lookups);
1116
+ lastWordLookups = lookups;
1117
+ return lookups;
1118
+ };
1119
+
1120
+ /**
1121
+ * webpack's parser: acorn plus lazy `range` (no `loc` at all), Set-based scopes,
1122
+ * tokenizer fast paths, import attributes and import phases (with acorn's
1123
+ * `!forNew` guard, unlike the former `acorn-import-phases` package).
1124
+ */
1125
+ class WebpackParser extends BaseParser {
1126
+ /**
1127
+ * @param {Options & { lazyNodes?: boolean, lazyComments?: CollectedComment[], importPhases?: boolean, moduleFallback?: boolean }} options options
1128
+ * @param {string} input source code
1129
+ * @param {number=} startPos start position
1130
+ */
1131
+ constructor(options, input, startPos) {
1132
+ const lazy = options.lazyNodes === true;
1133
+ // JavascriptParser._parse pre-disables acorn's tracking, so the
1134
+ // defensive copy only runs for direct callers
1135
+ if (lazy && (options.locations || options.ranges)) {
1136
+ options = { ...options, locations: false, ranges: false };
1137
+ }
1138
+ super(options, input, startPos);
1139
+ // acorn sets this.keywords/reservedWords in its constructor; parsing
1140
+ // (and thus readWord) only starts later in parse(), so this is ready
1141
+ this._wordLookups = getWordLookups(
1142
+ /** @type {ParserInternals} */ (/** @type {unknown} */ (this))
1143
+ );
1144
+ // acorn only calls `.test()` on reservedWordsStrictBind (in
1145
+ // checkLValSimple); swap its regexp for the Set-backed check
1146
+ /** @type {{ reservedWordsStrictBind: { test: (name: string) => boolean } }} */
1147
+ (/** @type {unknown} */ (this)).reservedWordsStrictBind =
1148
+ this._wordLookups.reservedBindTest;
1149
+ // per-token option probes cached once: acorn normalizes options in
1150
+ // `getOptions` before the constructor body runs and never mutates them
1151
+ const normalizedOptions = /** @type {ParserInternals} */ (
1152
+ /** @type {unknown} */ (this)
1153
+ ).options;
1154
+ this._ecmaVersion = /** @type {number} */ (normalizedOptions.ecmaVersion);
1155
+ this._noLocations = !normalizedOptions.locations;
1156
+ // lazy mode: nodes get only offsets, gating the owned tokenizer and
1157
+ // statement fast paths
1158
+ this._lazy = lazy;
1159
+ // lazy comment collection must not race a user-provided onComment
1160
+ /** @type {CollectedComment[] | undefined} */
1161
+ this._lazyComments =
1162
+ lazy && !options.onComment ? options.lazyComments : undefined;
1163
+ // acorn skips a hashbang inside its constructor, before `_lazyComments`
1164
+ // above exists — reconstruct the comment the override missed
1165
+ if (
1166
+ this._lazyComments !== undefined &&
1167
+ !startPos &&
1168
+ this.options.allowHashBang &&
1169
+ input.startsWith("#!")
1170
+ ) {
1171
+ this._lazyComments.push(
1172
+ new LazyComment(
1173
+ false,
1174
+ 2,
1175
+ 0,
1176
+ /** @type {ParserInternals} */ (/** @type {unknown} */ (this)).pos,
1177
+ input
1178
+ )
1179
+ );
1180
+ }
1181
+ /** @type {ImportPhase | null} */
1182
+ this._importPhase = null;
1183
+ this._importPhasesEnabled = options.importPhases === true;
1184
+ // auto source type: parse as module first, downgrade to script in place
1185
+ // (instead of a second full parse) when script-only syntax is hit
1186
+ this._moduleFallback = options.moduleFallback === true;
1187
+ // set once a module-only construct is parsed; blocks the downgrade
1188
+ this._moduleSyntaxSeen = false;
1189
+ // the owned parseSubscript assumes optional chaining exists (it bakes
1190
+ // `optional` into the node shape), so gate it on the normalized version
1191
+ this._subscriptFastPath = lazy && this._ecmaVersion >= 11;
1192
+ // the owned getTokenFromCode bakes in every ES2021 operator (?., ??=,
1193
+ // &&=, ...), so it needs at least that version
1194
+ this._fullTokenFastPath = lazy && this._ecmaVersion >= 12;
1195
+ // whether the gap before the current token holds a line terminator:
1196
+ // 0 no, 1 yes, 2 unknown (canInsertSemicolon then scans the gap)
1197
+ /** @type {0 | 1 | 2} */
1198
+ this._newlineBefore = 2;
1199
+ // LIFO pool for call-scoped destructuring-errors records; depth resets
1200
+ // implicitly since a raise aborts the whole parse
1201
+ /** @type {DestructuringErrorsShim[]} */
1202
+ this._deStack = [];
1203
+ this._deDepth = 0;
1204
+ // LIFO pool for `parseObj`'s prop-clash records: acorn's ES6+
1205
+ // `checkPropClash` only ever touches `.proto`, so one record per nesting
1206
+ // depth suffices; an overriding subclass gets the fresh `{}` acorn expects
1207
+ this._propHashFastPath =
1208
+ /** @type {ParserInternals} */ (/** @type {unknown} */ (this))
1209
+ .checkPropClash === base.checkPropClash;
1210
+ /** @type {{ proto: boolean }[]} */
1211
+ this._propHashStack = [];
1212
+ this._propHashDepth = 0;
1213
+ // `readRegexp`'s flag whitelist depends only on the ecmaVersion
1214
+ this._validRegexpFlags = `gim${this._ecmaVersion >= 6 ? "uy" : ""}${
1215
+ this._ecmaVersion >= 9 ? "s" : ""
1216
+ }${this._ecmaVersion >= 13 ? "d" : ""}${this._ecmaVersion >= 15 ? "v" : ""}`;
1217
+ // the owned parseStatement inlines these methods, so a parser plugin
1218
+ // overriding any of them turns the statement fast path off
1219
+ const proto = WebpackParser.prototype;
1220
+ this._stmtFastPath =
1221
+ lazy &&
1222
+ this.parseVarStatement === proto.parseVarStatement &&
1223
+ this.parseVar === proto.parseVar &&
1224
+ this.parseIfStatement === proto.parseIfStatement &&
1225
+ this.parseReturnStatement === proto.parseReturnStatement &&
1226
+ this.parseExpressionStatement === proto.parseExpressionStatement;
1227
+ }
1228
+
1229
+ /**
1230
+ * Fetches a destructuring-errors record from the pool: acorn allocates one
1231
+ * per expression parse and drops it at the end of the call, so strictly
1232
+ * call-scoped users can reuse records instead. Pair every acquire with a
1233
+ * `_releaseDestructuringErrors` on each non-throwing exit.
1234
+ * @returns {DestructuringErrorsShim} reset record
1235
+ * @this {ParserInternals}
1236
+ */
1237
+ _acquireDestructuringErrors() {
1238
+ const stack = this._deStack;
1239
+ const depth = this._deDepth++;
1240
+ const cached = stack[depth];
1241
+ if (cached !== undefined) {
1242
+ cached.shorthandAssign =
1243
+ cached.trailingComma =
1244
+ cached.parenthesizedAssign =
1245
+ cached.parenthesizedBind =
1246
+ cached.doubleProto =
1247
+ -1;
1248
+ return cached;
1249
+ }
1250
+ return (stack[depth] = createDestructuringErrors());
1251
+ }
1252
+
1253
+ /**
1254
+ * @returns {void}
1255
+ * @this {ParserInternals}
1256
+ */
1257
+ _releaseDestructuringErrors() {
1258
+ this._deDepth--;
1259
+ }
1260
+
1261
+ // ----- tokenizer fast paths -----
1262
+
1263
+ /**
1264
+ * Owned per-token loop: acorn's `nextToken` chains `skipSpace` →
1265
+ * `fullCharCodeAtPos` → `readToken` → `isIdentifierStart` with a dead
1266
+ * `locations` check at each step. For the common lazy, non-template context
1267
+ * this folds whitespace and comment skipping and the ASCII token dispatch
1268
+ * into one function so nothing re-enters acorn's per-step option checks.
1269
+ * Template/`preserveSpace` contexts and non-lazy mode use acorn's tokenizer.
1270
+ * @returns {void}
1271
+ * @this {ParserInternals}
1272
+ */
1273
+ nextToken() {
1274
+ const context = this.context;
1275
+ const curContext = context[context.length - 1];
1276
+ if (
1277
+ !this._lazy ||
1278
+ !curContext ||
1279
+ curContext.preserveSpace ||
1280
+ curContext.override
1281
+ ) {
1282
+ this._newlineBefore = 2;
1283
+ return base.nextToken.call(this);
1284
+ }
1285
+ const input = this.input;
1286
+ const len = input.length;
1287
+ let pos = this.pos;
1288
+ // line terminators are flagged while skipping (yuku's
1289
+ // `line_terminator_before`), so ASI checks need no gap re-scan. A
1290
+ // delegated path (acorn's html-comment handling) may have consumed part
1291
+ // of the gap before re-entering — start at "unknown" then.
1292
+ /** @type {0 | 1 | 2} */
1293
+ let newline = pos === this.lastTokEnd ? 0 : 2;
1294
+ // one CHAR_CLASS load classifies each char for both the skip loop and
1295
+ // the token dispatch below (yuku's ws_class/ident/punct tables in one)
1296
+ let code = 0;
1297
+ let cls = CLS_OTHER;
1298
+ while (pos < len) {
1299
+ code = input.charCodeAt(pos);
1300
+ cls = CHAR_CLASS[code];
1301
+ if (cls < CLS_SPACE) {
1302
+ if (cls === CLS_UNICODE) {
1303
+ // unicode whitespace / line terminators: acorn consumes the rest
1304
+ this.pos = pos;
1305
+ base.skipSpace.call(this);
1306
+ pos = this.pos;
1307
+ if (newline === 0) newline = 2;
1308
+ code = pos < len ? input.charCodeAt(pos) : 0;
1309
+ cls = CHAR_CLASS[code];
1310
+ }
1311
+ break;
1312
+ }
1313
+ if (cls === CLS_SPACE) {
1314
+ // space, tab, VT, FF (no CRLF/line bookkeeping in lazy mode)
1315
+ pos++;
1316
+ } else if (cls === CLS_NEWLINE) {
1317
+ newline = 1;
1318
+ pos++;
1319
+ } else {
1320
+ const next = input.charCodeAt(pos + 1);
1321
+ if (next === 42) {
1322
+ this.pos = pos;
1323
+ this.skipBlockComment();
1324
+ pos = this.pos;
1325
+ // the comment body may hold a line terminator
1326
+ if (newline === 0) newline = 2;
1327
+ } else if (next === 47) {
1328
+ this.pos = pos;
1329
+ this.skipLineComment(2);
1330
+ pos = this.pos;
1331
+ } else {
1332
+ // a division/regexp token, not a comment
1333
+ cls = CLS_OTHER;
1334
+ break;
1335
+ }
1336
+ }
1337
+ }
1338
+ this._newlineBefore = newline;
1339
+ this.pos = pos;
1340
+ this.start = pos;
1341
+ if (pos >= len) return this.finishToken(tokTypes.eof);
1342
+ switch (cls) {
1343
+ case CLS_IDENT:
1344
+ return this.readWord();
1345
+ case CLS_PUNCT:
1346
+ this.pos = pos + 1;
1347
+ return this.finishToken(/** @type {TokenType} */ (SIMPLE_PUNCT[code]));
1348
+ case CLS_DOT: {
1349
+ // `.` not starting `.5` or `...`: skip readToken_dot's re-dispatch
1350
+ const next = input.charCodeAt(pos + 1);
1351
+ if ((next < 48 || next > 57) && next !== 46) {
1352
+ this.pos = pos + 1;
1353
+ return this.finishToken(tokTypes.dot);
1354
+ }
1355
+ return this.getTokenFromCode(code);
1356
+ }
1357
+ case CLS_EQ: {
1358
+ // `=` not starting `==` or `=>`: skip readToken_eq_excl + finishOp slice
1359
+ const next = input.charCodeAt(pos + 1);
1360
+ if (next !== 61 && next !== 62) {
1361
+ this.pos = pos + 1;
1362
+ return this.finishToken(tokTypes.eq, "=");
1363
+ }
1364
+ return this.getTokenFromCode(code);
1365
+ }
1366
+ case CLS_UNICODE:
1367
+ return this.readToken(this.fullCharCodeAtPos());
1368
+ default:
1369
+ return this.getTokenFromCode(code);
1370
+ }
1371
+ }
1372
+
1373
+ /**
1374
+ * Lazy-mode `finishToken`: acorn probes `options.locations` for a dead
1375
+ * `endLoc` write on every token and reaches `updateContext` through an extra
1376
+ * method call. Skip the probe and inline acorn's `updateContext` body — this
1377
+ * runs once per token. Other modes use acorn's.
1378
+ * @param {TokenType} type token type
1379
+ * @param {unknown=} value token value
1380
+ * @returns {void}
1381
+ * @this {ParserInternals}
1382
+ */
1383
+ finishToken(type, value) {
1384
+ if (!this._lazy) {
1385
+ return base.finishToken.call(this, type, value);
1386
+ }
1387
+ this.end = this.pos;
1388
+ const prevType = this.type;
1389
+ this.type = type;
1390
+ this.value = value;
1391
+ const internal = /** @type {TokenTypeInternal} */ (type);
1392
+ // acorn's updateContext, inlined: keyword-after-dot forbids an expression,
1393
+ // else the token type's own context hook runs, else `exprAllowed` follows
1394
+ // the type's `beforeExpr` (the branch that makes `/` after a value divide)
1395
+ if (type === tokTypes.name) {
1396
+ // name.updateContext, inlined for the commonest token: only `of` /
1397
+ // `yield` (outside a `.` access, ES6+) can re-allow an expression
1398
+ this.exprAllowed =
1399
+ ((value === "of" && !this.exprAllowed) ||
1400
+ (value === "yield" && this.inGeneratorContext())) &&
1401
+ prevType !== tokTypes.dot &&
1402
+ this._ecmaVersion >= 6;
1403
+ } else if (type.keyword && prevType === tokTypes.dot) {
1404
+ this.exprAllowed = false;
1405
+ } else if (type === tokTypes.parenR || type === tokTypes.braceR) {
1406
+ // parenR/braceR.updateContext, inlined
1407
+ const context = this.context;
1408
+ if (context.length === 1) {
1409
+ this.exprAllowed = true;
1410
+ } else {
1411
+ let out = /** @type {TokContextShim} */ (context.pop());
1412
+ if (
1413
+ out === CTX_B_STAT &&
1414
+ /** @type {TokContextShim} */ (context[context.length - 1]).token ===
1415
+ "function"
1416
+ ) {
1417
+ out = /** @type {TokContextShim} */ (context.pop());
1418
+ }
1419
+ this.exprAllowed = !out.isExpr;
1420
+ }
1421
+ } else if (type === tokTypes.braceL) {
1422
+ // braceL.updateContext, inlined
1423
+ this.context.push(this.braceIsBlock(prevType) ? CTX_B_STAT : CTX_B_EXPR);
1424
+ this.exprAllowed = true;
1425
+ } else if (type === tokTypes.parenL) {
1426
+ // parenL.updateContext, inlined
1427
+ const statementParens =
1428
+ prevType === tokTypes._if ||
1429
+ prevType === tokTypes._for ||
1430
+ prevType === tokTypes._with ||
1431
+ prevType === tokTypes._while;
1432
+ this.context.push(statementParens ? CTX_P_STAT : CTX_P_EXPR);
1433
+ this.exprAllowed = true;
1434
+ } else if (internal.updateContext) {
1435
+ internal.updateContext.call(this, prevType);
1436
+ } else {
1437
+ this.exprAllowed = internal.beforeExpr;
1438
+ }
1439
+ }
1440
+
1441
+ /**
1442
+ * Owned `braceIsBlock`, acorn's verbatim except the line-terminator probe:
1443
+ * acorn slices the inter-token gap and runs a regexp; `_gapHasNewline`
1444
+ * answers from the tokenizer's newline flag (scanning only when unknown).
1445
+ * @param {TokenType} prevType type of the previous token
1446
+ * @returns {boolean} whether a `{` opens a block in this context
1447
+ * @this {ParserInternals}
1448
+ */
1449
+ braceIsBlock(prevType) {
1450
+ const context = this.context;
1451
+ const parent = /** @type {TokContextShim} */ (context[context.length - 1]);
1452
+ if (parent === CTX_F_EXPR || parent === CTX_F_STAT) return true;
1453
+ if (
1454
+ prevType === tokTypes.colon &&
1455
+ (parent === CTX_B_STAT || parent === CTX_B_EXPR)
1456
+ ) {
1457
+ return !parent.isExpr;
1458
+ }
1459
+ // after `return`, or after `yield`/`of` (name with exprAllowed), a line
1460
+ // terminator decides between block and expression
1461
+ if (
1462
+ prevType === tokTypes._return ||
1463
+ (prevType === tokTypes.name && this.exprAllowed)
1464
+ ) {
1465
+ return this._gapHasNewline();
1466
+ }
1467
+ if (
1468
+ prevType === tokTypes._else ||
1469
+ prevType === tokTypes.semi ||
1470
+ prevType === tokTypes.eof ||
1471
+ prevType === tokTypes.parenR ||
1472
+ prevType === tokTypes.arrow
1473
+ ) {
1474
+ return true;
1475
+ }
1476
+ if (prevType === tokTypes.braceL) return parent === CTX_B_STAT;
1477
+ if (
1478
+ prevType === tokTypes._var ||
1479
+ prevType === tokTypes._const ||
1480
+ prevType === tokTypes.name
1481
+ ) {
1482
+ return false;
1483
+ }
1484
+ return !this.exprAllowed;
1485
+ }
1486
+
1487
+ /**
1488
+ * Whether the gap before the current token holds a line terminator, served
1489
+ * from the owned tokenizer's flag when known.
1490
+ * @returns {boolean} whether a line terminator precedes the current token
1491
+ * @this {ParserInternals}
1492
+ */
1493
+ _gapHasNewline() {
1494
+ const newlineBefore = this._newlineBefore;
1495
+ if (newlineBefore !== 2) return newlineBefore === 1;
1496
+ const input = this.input;
1497
+ const end = this.start;
1498
+ for (let i = this.lastTokEnd; i < end; i++) {
1499
+ const ch = input.charCodeAt(i);
1500
+ // LF, CR, LS, PS — acorn's `lineBreak` alternation
1501
+ if (ch === 10 || ch === 13 || ch === 0x2028 || ch === 0x2029) {
1502
+ // memoize: the gap is fixed until the next token is read, and
1503
+ // `nextToken` rewrites the flag — ASI probes often repeat per token
1504
+ // (e.g. name atoms behind a /*#__PURE__*/ comment)
1505
+ this._newlineBefore = 1;
1506
+ return true;
1507
+ }
1508
+ }
1509
+ this._newlineBefore = 0;
1510
+ return false;
1511
+ }
1512
+
1513
+ /**
1514
+ * Owned per-token advance: acorn's `next` writes `lastTokEndLoc`/
1515
+ * `lastTokStartLoc` and probes `options.onToken` on every token, both dead in
1516
+ * lazy mode (locations off, no token stream), leaving only the two offset
1517
+ * writes and the keyword-escape guard. Other modes use acorn's.
1518
+ * @param {boolean=} ignoreEscapeSequenceInKeyword whether an escape in a keyword is allowed here
1519
+ * @returns {void}
1520
+ * @this {ParserInternals}
1521
+ */
1522
+ next(ignoreEscapeSequenceInKeyword) {
1523
+ if (!this._lazy) {
1524
+ return base.next.call(this, ignoreEscapeSequenceInKeyword);
1525
+ }
1526
+ const type = this.type;
1527
+ if (!ignoreEscapeSequenceInKeyword && type.keyword && this.containsEsc) {
1528
+ this.raiseRecoverable(
1529
+ this.start,
1530
+ `Escape sequence in keyword ${type.keyword}`
1531
+ );
1532
+ }
1533
+ this.lastTokEnd = this.end;
1534
+ this.lastTokStart = this.start;
1535
+ this.nextToken();
1536
+ }
1537
+
1538
+ /**
1539
+ * Owned `finishOp`: acorn slices the operator text out of the source for
1540
+ * every operator token, allocating a fresh 2-4 char string per `=>`, `===`,
1541
+ * `&&` etc. Serve those from `OP_CACHE` instead; single-char operators keep
1542
+ * the direct slice, which V8 serves from its single-character table.
1543
+ * @param {TokenType} type token type
1544
+ * @param {number} size operator length
1545
+ * @returns {void}
1546
+ * @this {ParserInternals}
1547
+ */
1548
+ finishOp(type, size) {
1549
+ const pos = this.pos;
1550
+ const input = this.input;
1551
+ if (size === 1) {
1552
+ this.pos = pos + 1;
1553
+ return this.finishToken(type, input.slice(pos, pos + 1));
1554
+ }
1555
+ let key = input.charCodeAt(pos) | (input.charCodeAt(pos + 1) << 7);
1556
+ if (size > 2) {
1557
+ key |= input.charCodeAt(pos + 2) << 14;
1558
+ if (size > 3) key |= input.charCodeAt(pos + 3) << 21;
1559
+ }
1560
+ let str = OP_CACHE.get(key);
1561
+ if (str === undefined) {
1562
+ str = input.slice(pos, pos + size);
1563
+ OP_CACHE.set(key, str);
1564
+ }
1565
+ this.pos = pos + size;
1566
+ return this.finishToken(type, str);
1567
+ }
1568
+
1569
+ /**
1570
+ * Owned `getTokenFromCode`: acorn dispatches operators through per-family
1571
+ * `readToken_*` methods that each end in `finishOp`'s source slice. Resolve
1572
+ * every operator by direct char peeks to a static string instead (yuku's
1573
+ * `scanPunctuation`) — no method chain, no slice, no `OP_CACHE` probe. The
1574
+ * HTML-comment forms (`<!--`, `-->`), `#`, and unknown chars delegate.
1575
+ * @param {number} code current char code
1576
+ * @returns {void}
1577
+ * @this {ParserInternals}
1578
+ */
1579
+ getTokenFromCode(code) {
1580
+ if (!this._fullTokenFastPath) {
1581
+ return base.getTokenFromCode.call(this, code);
1582
+ }
1583
+ const input = this.input;
1584
+ const pos = this.pos;
1585
+ switch (code) {
1586
+ case 46: {
1587
+ // '.': number, ellipsis or plain dot
1588
+ const next = input.charCodeAt(pos + 1);
1589
+ if (next >= 48 && next <= 57) return this.readNumber(true);
1590
+ if (next === 46 && input.charCodeAt(pos + 2) === 46) {
1591
+ this.pos = pos + 3;
1592
+ return this.finishToken(tokTypes.ellipsis);
1593
+ }
1594
+ this.pos = pos + 1;
1595
+ return this.finishToken(tokTypes.dot);
1596
+ }
1597
+ case 47: {
1598
+ // '/': regexp in expression position, otherwise /= or /
1599
+ if (this.exprAllowed) {
1600
+ this.pos = pos + 1;
1601
+ return this.readRegexp();
1602
+ }
1603
+ if (input.charCodeAt(pos + 1) === 61) {
1604
+ this.pos = pos + 2;
1605
+ return this.finishToken(tokTypes.assign, "/=");
1606
+ }
1607
+ this.pos = pos + 1;
1608
+ return this.finishToken(tokTypes.slash, "/");
1609
+ }
1610
+ case 37: {
1611
+ // '%': %= or %
1612
+ if (input.charCodeAt(pos + 1) === 61) {
1613
+ this.pos = pos + 2;
1614
+ return this.finishToken(tokTypes.assign, "%=");
1615
+ }
1616
+ this.pos = pos + 1;
1617
+ return this.finishToken(tokTypes.modulo, "%");
1618
+ }
1619
+ case 42: {
1620
+ // '*': **=, **, *= or *
1621
+ const next = input.charCodeAt(pos + 1);
1622
+ if (next === 42) {
1623
+ if (input.charCodeAt(pos + 2) === 61) {
1624
+ this.pos = pos + 3;
1625
+ return this.finishToken(tokTypes.assign, "**=");
1626
+ }
1627
+ this.pos = pos + 2;
1628
+ return this.finishToken(tokTypes.starstar, "**");
1629
+ }
1630
+ if (next === 61) {
1631
+ this.pos = pos + 2;
1632
+ return this.finishToken(tokTypes.assign, "*=");
1633
+ }
1634
+ this.pos = pos + 1;
1635
+ return this.finishToken(tokTypes.star, "*");
1636
+ }
1637
+ case 124: {
1638
+ // '|': ||=, ||, |= or |
1639
+ const next = input.charCodeAt(pos + 1);
1640
+ if (next === 124) {
1641
+ if (input.charCodeAt(pos + 2) === 61) {
1642
+ this.pos = pos + 3;
1643
+ return this.finishToken(tokTypes.assign, "||=");
1644
+ }
1645
+ this.pos = pos + 2;
1646
+ return this.finishToken(tokTypes.logicalOR, "||");
1647
+ }
1648
+ if (next === 61) {
1649
+ this.pos = pos + 2;
1650
+ return this.finishToken(tokTypes.assign, "|=");
1651
+ }
1652
+ this.pos = pos + 1;
1653
+ return this.finishToken(tokTypes.bitwiseOR, "|");
1654
+ }
1655
+ case 38: {
1656
+ // '&': &&=, &&, &= or &
1657
+ const next = input.charCodeAt(pos + 1);
1658
+ if (next === 38) {
1659
+ if (input.charCodeAt(pos + 2) === 61) {
1660
+ this.pos = pos + 3;
1661
+ return this.finishToken(tokTypes.assign, "&&=");
1662
+ }
1663
+ this.pos = pos + 2;
1664
+ return this.finishToken(tokTypes.logicalAND, "&&");
1665
+ }
1666
+ if (next === 61) {
1667
+ this.pos = pos + 2;
1668
+ return this.finishToken(tokTypes.assign, "&=");
1669
+ }
1670
+ this.pos = pos + 1;
1671
+ return this.finishToken(tokTypes.bitwiseAND, "&");
1672
+ }
1673
+ case 94: {
1674
+ // '^': ^= or ^
1675
+ if (input.charCodeAt(pos + 1) === 61) {
1676
+ this.pos = pos + 2;
1677
+ return this.finishToken(tokTypes.assign, "^=");
1678
+ }
1679
+ this.pos = pos + 1;
1680
+ return this.finishToken(tokTypes.bitwiseXOR, "^");
1681
+ }
1682
+ case 43: {
1683
+ // '+': ++, += or +
1684
+ const next = input.charCodeAt(pos + 1);
1685
+ if (next === 43) {
1686
+ this.pos = pos + 2;
1687
+ return this.finishToken(tokTypes.incDec, "++");
1688
+ }
1689
+ if (next === 61) {
1690
+ this.pos = pos + 2;
1691
+ return this.finishToken(tokTypes.assign, "+=");
1692
+ }
1693
+ this.pos = pos + 1;
1694
+ return this.finishToken(tokTypes.plusMin, "+");
1695
+ }
1696
+ case 45: {
1697
+ // '-': --, -= or -; `-->` may open an HTML line comment
1698
+ const next = input.charCodeAt(pos + 1);
1699
+ if (next === 45) {
1700
+ if (input.charCodeAt(pos + 2) === 62 && !this.inModule) {
1701
+ return base.getTokenFromCode.call(this, code);
1702
+ }
1703
+ this.pos = pos + 2;
1704
+ return this.finishToken(tokTypes.incDec, "--");
1705
+ }
1706
+ if (next === 61) {
1707
+ this.pos = pos + 2;
1708
+ return this.finishToken(tokTypes.assign, "-=");
1709
+ }
1710
+ this.pos = pos + 1;
1711
+ return this.finishToken(tokTypes.plusMin, "-");
1712
+ }
1713
+ case 60: {
1714
+ // '<': <<=, <<, <= or <; `<!--` opens an HTML line comment
1715
+ const next = input.charCodeAt(pos + 1);
1716
+ if (next === 60) {
1717
+ if (input.charCodeAt(pos + 2) === 61) {
1718
+ this.pos = pos + 3;
1719
+ return this.finishToken(tokTypes.assign, "<<=");
1720
+ }
1721
+ this.pos = pos + 2;
1722
+ return this.finishToken(tokTypes.bitShift, "<<");
1723
+ }
1724
+ if (
1725
+ next === 33 &&
1726
+ !this.inModule &&
1727
+ input.charCodeAt(pos + 2) === 45 &&
1728
+ input.charCodeAt(pos + 3) === 45
1729
+ ) {
1730
+ return base.getTokenFromCode.call(this, code);
1731
+ }
1732
+ if (next === 61) {
1733
+ this.pos = pos + 2;
1734
+ return this.finishToken(tokTypes.relational, "<=");
1735
+ }
1736
+ this.pos = pos + 1;
1737
+ return this.finishToken(tokTypes.relational, "<");
1738
+ }
1739
+ case 62: {
1740
+ // '>': >>>=, >>>, >>=, >>, >= or >
1741
+ const next = input.charCodeAt(pos + 1);
1742
+ if (next === 62) {
1743
+ if (input.charCodeAt(pos + 2) === 62) {
1744
+ if (input.charCodeAt(pos + 3) === 61) {
1745
+ this.pos = pos + 4;
1746
+ return this.finishToken(tokTypes.assign, ">>>=");
1747
+ }
1748
+ this.pos = pos + 3;
1749
+ return this.finishToken(tokTypes.bitShift, ">>>");
1750
+ }
1751
+ if (input.charCodeAt(pos + 2) === 61) {
1752
+ this.pos = pos + 3;
1753
+ return this.finishToken(tokTypes.assign, ">>=");
1754
+ }
1755
+ this.pos = pos + 2;
1756
+ return this.finishToken(tokTypes.bitShift, ">>");
1757
+ }
1758
+ if (next === 61) {
1759
+ this.pos = pos + 2;
1760
+ return this.finishToken(tokTypes.relational, ">=");
1761
+ }
1762
+ this.pos = pos + 1;
1763
+ return this.finishToken(tokTypes.relational, ">");
1764
+ }
1765
+ case 61: {
1766
+ // '=': ===, ==, => or =
1767
+ const next = input.charCodeAt(pos + 1);
1768
+ if (next === 61) {
1769
+ if (input.charCodeAt(pos + 2) === 61) {
1770
+ this.pos = pos + 3;
1771
+ return this.finishToken(tokTypes.equality, "===");
1772
+ }
1773
+ this.pos = pos + 2;
1774
+ return this.finishToken(tokTypes.equality, "==");
1775
+ }
1776
+ if (next === 62) {
1777
+ this.pos = pos + 2;
1778
+ return this.finishToken(tokTypes.arrow);
1779
+ }
1780
+ this.pos = pos + 1;
1781
+ return this.finishToken(tokTypes.eq, "=");
1782
+ }
1783
+ case 33: {
1784
+ // '!': !==, != or !
1785
+ const next = input.charCodeAt(pos + 1);
1786
+ if (next === 61) {
1787
+ if (input.charCodeAt(pos + 2) === 61) {
1788
+ this.pos = pos + 3;
1789
+ return this.finishToken(tokTypes.equality, "!==");
1790
+ }
1791
+ this.pos = pos + 2;
1792
+ return this.finishToken(tokTypes.equality, "!=");
1793
+ }
1794
+ this.pos = pos + 1;
1795
+ return this.finishToken(tokTypes.prefix, "!");
1796
+ }
1797
+ case 63: {
1798
+ // '?': ?. (not before a digit), ??=, ?? or ?
1799
+ const next = input.charCodeAt(pos + 1);
1800
+ if (next === 46) {
1801
+ const next2 = input.charCodeAt(pos + 2);
1802
+ if (next2 < 48 || next2 > 57) {
1803
+ this.pos = pos + 2;
1804
+ return this.finishToken(tokTypes.questionDot, "?.");
1805
+ }
1806
+ }
1807
+ if (next === 63) {
1808
+ if (input.charCodeAt(pos + 2) === 61) {
1809
+ this.pos = pos + 3;
1810
+ return this.finishToken(tokTypes.assign, "??=");
1811
+ }
1812
+ this.pos = pos + 2;
1813
+ return this.finishToken(tokTypes.coalesce, "??");
1814
+ }
1815
+ this.pos = pos + 1;
1816
+ return this.finishToken(tokTypes.question, "?");
1817
+ }
1818
+ case 126: {
1819
+ // '~'
1820
+ this.pos = pos + 1;
1821
+ return this.finishToken(tokTypes.prefix, "~");
1822
+ }
1823
+ case 96: {
1824
+ // '`'
1825
+ this.pos = pos + 1;
1826
+ return this.finishToken(tokTypes.backQuote);
1827
+ }
1828
+ case 48: {
1829
+ // '0': radix literals split off before the decimal reader
1830
+ const next = input.charCodeAt(pos + 1);
1831
+ if (next === 120 || next === 88) return this.readRadixNumber(16);
1832
+ if (next === 111 || next === 79) return this.readRadixNumber(8);
1833
+ if (next === 98 || next === 66) return this.readRadixNumber(2);
1834
+ return this.readNumber(false);
1835
+ }
1836
+ case 49:
1837
+ case 50:
1838
+ case 51:
1839
+ case 52:
1840
+ case 53:
1841
+ case 54:
1842
+ case 55:
1843
+ case 56:
1844
+ case 57:
1845
+ return this.readNumber(false);
1846
+ case 34:
1847
+ case 39:
1848
+ return this.readString(code);
1849
+ default:
1850
+ return base.getTokenFromCode.call(this, code);
1851
+ }
1852
+ }
1853
+
1854
+ /**
1855
+ * ASCII fast path for acorn's `readWord1`, which pays a surrogate-aware
1856
+ * method call and a range-check helper per character. Escapes, non-ASCII
1857
+ * and astral input restart the base implementation from the word start.
1858
+ * Words are deduplicated through `WORD_CACHE` so repeated identifiers —
1859
+ * which dominate real code — reuse one string instead of slicing a fresh
1860
+ * one per occurrence; sharing also keeps their cached string hashes warm
1861
+ * for the keyword/scope Map lookups downstream.
1862
+ * @this {ParserInternals}
1863
+ * @returns {string} the word
1864
+ */
1865
+ readWord1() {
1866
+ const input = this.input;
1867
+ const start = this.pos;
1868
+ const len = input.length;
1869
+ // djb2-style hash folded into the scan loop (yuku scans each lexeme in
1870
+ // one pass); computing it for the rare over-long words is cheaper than
1871
+ // re-walking every word in a second pass
1872
+ let hash = 0;
1873
+ let pos = start;
1874
+ while (pos < len) {
1875
+ const ch = input.charCodeAt(pos);
1876
+ if (ch < 128) {
1877
+ if (IDENT_CHAR[ch] === 0) {
1878
+ // backslash escape: restart cold so escape rules see the word
1879
+ if (ch === 92) return base.readWord1.call(this);
1880
+ break;
1881
+ }
1882
+ hash = (Math.imul(hash, 33) + ch) | 0;
1883
+ pos++;
1884
+ } else {
1885
+ return base.readWord1.call(this);
1886
+ }
1887
+ }
1888
+ this.containsEsc = false;
1889
+ this.pos = pos;
1890
+ const wordLen = pos - start;
1891
+ // Single-char words skip the cache (V8 serves those slices from its
1892
+ // single-character table without allocating); long words skip it too.
1893
+ if (wordLen >= 2 && wordLen <= WORD_CACHE_MAX_LEN) {
1894
+ const slot = hash & WORD_CACHE_MASK;
1895
+ const cached = WORD_CACHE[slot];
1896
+ if (
1897
+ cached !== null &&
1898
+ cached.length === wordLen &&
1899
+ sameWord(cached, input, start, wordLen)
1900
+ ) {
1901
+ return cached;
1902
+ }
1903
+ const word = input.slice(start, pos);
1904
+ WORD_CACHE[slot] = word;
1905
+ return word;
1906
+ }
1907
+ return input.slice(start, pos);
1908
+ }
1909
+
1910
+ /**
1911
+ * String fast path: one scan that both finds the closing quote and vets the
1912
+ * span (the former `indexOf` + verify-loop pair read every string twice).
1913
+ * Escapes, newlines in the span, old ecmaVersions (LS/PS terminate strings
1914
+ * there) and location tracking restart acorn's implementation, which also
1915
+ * produces its exact errors.
1916
+ * @this {ParserInternals}
1917
+ * @param {number} quote quote char code
1918
+ * @returns {void}
1919
+ */
1920
+ readString(quote) {
1921
+ if (!this._noLocations || this._ecmaVersion < 10) {
1922
+ return base.readString.call(this, quote);
1923
+ }
1924
+ const input = this.input;
1925
+ const len = input.length;
1926
+ const start = this.pos + 1;
1927
+ let pos = start;
1928
+ for (;;) {
1929
+ if (pos >= len) this.raise(this.start, "Unterminated string constant");
1930
+ const ch = input.charCodeAt(pos);
1931
+ if (ch === quote) break;
1932
+ // backslash, LF, CR
1933
+ if (ch === 92 || ch === 10 || ch === 13) {
1934
+ return base.readString.call(this, quote);
1935
+ }
1936
+ pos++;
1937
+ }
1938
+ this.pos = pos + 1;
1939
+ this.finishToken(tokTypes.string, input.slice(start, pos));
1940
+ }
1941
+
1942
+ /**
1943
+ * Number fast path: plain integer literals (no leading zero, up to 15
1944
+ * digits so the float is exact) are accumulated numerically — no slice,
1945
+ * no parseFloat, no separator handling. Everything else (dots, exponents,
1946
+ * bigints, separators, octal forms) restarts acorn's implementation.
1947
+ * @this {ParserInternals}
1948
+ * @param {boolean} startsWithDot whether the number started with a dot
1949
+ * @returns {void}
1950
+ */
1951
+ readNumber(startsWithDot) {
1952
+ if (startsWithDot) return base.readNumber.call(this, startsWithDot);
1953
+ const input = this.input;
1954
+ const start = this.pos;
1955
+ const len = input.length;
1956
+ const first = input.charCodeAt(start);
1957
+ let pos;
1958
+ if (first === 48) {
1959
+ const c1 = start + 1 < len ? input.charCodeAt(start + 1) : 0;
1960
+ if (c1 === 46) {
1961
+ // `0.<digits>`
1962
+ pos = start + 1;
1963
+ } else if (c1 > 127 || IDENT_CHAR[c1] === 1) {
1964
+ // 0x/0o/0b, 0e…, 0n, 0_, legacy `0NN`, or `0`+identifier: acorn
1965
+ return base.readNumber.call(this, startsWithDot);
1966
+ } else {
1967
+ // bare `0` before punctuation/operator/whitespace/EOF
1968
+ this.pos = start + 1;
1969
+ return this.finishToken(tokTypes.num, 0);
1970
+ }
1971
+ } else if (first > 48 && first <= 57) {
1972
+ // integer digits, accumulated numerically for the integer-only case
1973
+ let value = first - 48;
1974
+ pos = start + 1;
1975
+ while (pos < len) {
1976
+ const ch = input.charCodeAt(pos);
1977
+ if (ch >= 48 && ch <= 57) {
1978
+ value = value * 10 + (ch - 48);
1979
+ pos++;
1980
+ } else {
1981
+ break;
1982
+ }
1983
+ }
1984
+ const after = pos < len ? input.charCodeAt(pos) : 0;
1985
+ if (after !== 46) {
1986
+ // no fraction: exponent, separator, bigint suffix or a trailing
1987
+ // identifier char all need acorn's full handling and exact errors
1988
+ if (
1989
+ after === 101 ||
1990
+ after === 69 ||
1991
+ after === 95 ||
1992
+ after === 110 ||
1993
+ after > 127 ||
1994
+ IDENT_CHAR[after] === 1
1995
+ ) {
1996
+ return base.readNumber.call(this, startsWithDot);
1997
+ }
1998
+ // 15 digits always fit exactly into a double
1999
+ if (pos - start > 15) {
2000
+ return base.readNumber.call(this, startsWithDot);
2001
+ }
2002
+ this.pos = pos;
2003
+ return this.finishToken(tokTypes.num, value);
2004
+ }
2005
+ // a fraction follows the integer part
2006
+ } else {
2007
+ return base.readNumber.call(this, startsWithDot);
2008
+ }
2009
+ // decimal fraction: `pos` is at the '.'
2010
+ pos++;
2011
+ while (pos < len) {
2012
+ const ch = input.charCodeAt(pos);
2013
+ if (ch >= 48 && ch <= 57) pos++;
2014
+ else break;
2015
+ }
2016
+ const after = pos < len ? input.charCodeAt(pos) : 0;
2017
+ // exponent, a second dot, separator, bigint suffix or trailing identifier
2018
+ if (
2019
+ after === 46 ||
2020
+ after === 101 ||
2021
+ after === 69 ||
2022
+ after === 95 ||
2023
+ after === 110 ||
2024
+ after > 127 ||
2025
+ IDENT_CHAR[after] === 1
2026
+ ) {
2027
+ return base.readNumber.call(this, startsWithDot);
2028
+ }
2029
+ this.pos = pos;
2030
+ this.finishToken(tokTypes.num, Number.parseFloat(input.slice(start, pos)));
2031
+ }
2032
+
2033
+ /**
2034
+ * Owned `strictDirective`: acorn's runs an anchored literal regex over
2035
+ * `this.input.slice(start)` — a fresh sliced string per (sloppy-mode)
2036
+ * function body. Sticky regexes at the offset scan the same grammar with no
2037
+ * slice. Same directive-prologue semantics, including the ASI tail checks.
2038
+ * @param {number} start offset of the function body's first statement
2039
+ * @returns {boolean} true when a 'use strict' directive leads the prologue
2040
+ * @this {ParserInternals & { input: string, options: { ecmaVersion: number } }}
2041
+ */
2042
+ strictDirective(start) {
2043
+ if (/** @type {number} */ (this.options.ecmaVersion) < 5) return false;
2044
+ const input = this.input;
2045
+ for (;;) {
2046
+ // Skip whitespace and comments (acorn's `skipWhiteSpace`, sticky).
2047
+ STRICT_SKIP_WS.lastIndex = start;
2048
+ start += /** @type {RegExpExecArray} */ (STRICT_SKIP_WS.exec(input))[0]
2049
+ .length;
2050
+ STRICT_LITERAL.lastIndex = start;
2051
+ const match = STRICT_LITERAL.exec(input);
2052
+ if (!match) return false;
2053
+ if ((match[1] || match[2]) === "use strict") {
2054
+ STRICT_SKIP_WS.lastIndex = start + match[0].length;
2055
+ const spaceAfter = /** @type {RegExpExecArray} */ (
2056
+ STRICT_SKIP_WS.exec(input)
2057
+ );
2058
+ const end = spaceAfter.index + spaceAfter[0].length;
2059
+ const next = input.charAt(end);
2060
+ return (
2061
+ next === ";" ||
2062
+ next === "}" ||
2063
+ (STRICT_LINE_BREAK.test(spaceAfter[0]) &&
2064
+ !(
2065
+ /[(`.[+\-/*%<>=,?^&]/.test(next) ||
2066
+ (next === "!" && input.charAt(end + 1) === "=")
2067
+ ))
2068
+ );
2069
+ }
2070
+ start += match[0].length;
2071
+
2072
+ // Skip semicolon, if any.
2073
+ STRICT_SKIP_WS.lastIndex = start;
2074
+ start += /** @type {RegExpExecArray} */ (STRICT_SKIP_WS.exec(input))[0]
2075
+ .length;
2076
+ if (input[start] === ";") start++;
2077
+ }
2078
+ }
2079
+
2080
+ /**
2081
+ * Template fast path: when the chunk contains no backslash and no CR, the
2082
+ * cooked value is one slice (LF/LS/PS cook to themselves). Escapes, CR
2083
+ * normalization and location tracking restart acorn's implementation,
2084
+ * which also produces its exact errors.
2085
+ * @this {ParserInternals}
2086
+ * @returns {void}
2087
+ */
2088
+ readTmplToken() {
2089
+ if (!this._noLocations) return base.readTmplToken.call(this);
2090
+ const input = this.input;
2091
+ const start = this.pos;
2092
+ const len = input.length;
2093
+ let pos = start;
2094
+ while (pos < len) {
2095
+ const ch = input.charCodeAt(pos);
2096
+ if (ch === 96 || (ch === 36 && input.charCodeAt(pos + 1) === 123)) {
2097
+ if (
2098
+ pos === this.start &&
2099
+ (this.type === tokTypes.template ||
2100
+ this.type === tokTypes.invalidTemplate)
2101
+ ) {
2102
+ if (ch === 36) {
2103
+ this.pos = pos + 2;
2104
+ return this.finishToken(tokTypes.dollarBraceL);
2105
+ }
2106
+ this.pos = pos + 1;
2107
+ return this.finishToken(tokTypes.backQuote);
2108
+ }
2109
+ this.pos = pos;
2110
+ return this.finishToken(tokTypes.template, input.slice(start, pos));
2111
+ }
2112
+ // backslash and CR need acorn's cooked-string building
2113
+ if (ch === 92 || ch === 13) {
2114
+ return base.readTmplToken.call(this);
2115
+ }
2116
+ pos++;
2117
+ }
2118
+ this.raise(this.start, "Unterminated template");
2119
+ }
2120
+
2121
+ /**
2122
+ * Fast path for the common run of plain ASCII whitespace; comments,
2123
+ * unicode whitespace and location tracking delegate to acorn.
2124
+ * @this {ParserInternals & { pos: number }}
2125
+ * @returns {void}
2126
+ */
2127
+ skipSpace() {
2128
+ if (!this._noLocations) return base.skipSpace.call(this);
2129
+ const input = this.input;
2130
+ const len = input.length;
2131
+ let pos = this.pos;
2132
+ while (pos < len) {
2133
+ const ch = input.charCodeAt(pos);
2134
+ // 9-13 and 32 cover tab, LF, VT, FF, CR and space
2135
+ if (ch === 32 || (ch > 8 && ch < 14)) {
2136
+ pos++;
2137
+ } else if (ch === 47 || ch > 127) {
2138
+ // comments or unicode whitespace: let acorn handle the rest
2139
+ this.pos = pos;
2140
+ return base.skipSpace.call(this);
2141
+ } else {
2142
+ break;
2143
+ }
2144
+ }
2145
+ this.pos = pos;
2146
+ }
2147
+
2148
+ // ----- word classification (Map/Set lookups, replaces acorn's regexps) -----
2149
+
2150
+ /**
2151
+ * Replaces acorn's `readWord`, whose `this.keywords.test(word)` runs an
2152
+ * anchored alternation regexp for every identifier and keyword token; a
2153
+ * Map lookup on the same keyword set is cheaper.
2154
+ * @this {ParserInternals}
2155
+ * @returns {void}
2156
+ */
2157
+ readWord() {
2158
+ const word = this.readWord1();
2159
+ let type = tokTypes.name;
2160
+ const len = word.length;
2161
+ // every acorn keyword is 2-10 lowercase ASCII chars (`do`…`instanceof`),
2162
+ // so most identifiers skip the Map probe entirely (yuku gates its keyword
2163
+ // switch the same way)
2164
+ if (len >= 2 && len <= 10) {
2165
+ const first = word.charCodeAt(0);
2166
+ if (first >= 97 && first <= 122) {
2167
+ type = this._wordLookups.keywords.get(word) || tokTypes.name;
2168
+ }
2169
+ }
2170
+ this.finishToken(type, word);
2171
+ }
2172
+
2173
+ /**
2174
+ * Mirror of acorn's `checkUnreserved` with its two per-identifier regexp
2175
+ * tests (`keywords` and `reservedWords`/`reservedWordsStrict`) folded into a
2176
+ * single `reservedKinds` lookup — one hash probe instead of two, and the
2177
+ * common plain identifier misses it and returns. Branches and error
2178
+ * messages match acorn exactly.
2179
+ * @param {Identifier} ref identifier node
2180
+ * @this {ParserInternals}
2181
+ */
2182
+ checkUnreserved(ref) {
2183
+ const { start, end, name } = ref;
2184
+ // every reserved word and special name below is short lowercase ASCII, so
2185
+ // most identifiers exit on this shape gate before any string compare
2186
+ // (`yield`/`await`/`arguments` all pass it: lengths 5/5/9 ≤ reservedMaxLen,
2187
+ // which keywords like `instanceof` keep at ≥ 10)
2188
+ const lookups = this._wordLookups;
2189
+ const nameLen = name.length;
2190
+ if (nameLen < 2 || nameLen > lookups.reservedMaxLen) return;
2191
+ const firstCC = name.charCodeAt(0);
2192
+ if (firstCC < 97 || firstCC > 122) return;
2193
+ // name-first ordering: acorn's `inGenerator`/`inAsync` are getters that
2194
+ // walk the scope stack, so gate them behind the cheap string compare —
2195
+ // a plain identifier never triggers them
2196
+ if (name === "yield" && this.inGenerator) {
2197
+ this.raiseRecoverable(
2198
+ start,
2199
+ "Cannot use 'yield' as identifier inside a generator"
2200
+ );
2201
+ } else if (name === "await" && this.inAsync) {
2202
+ this.raiseRecoverable(
2203
+ start,
2204
+ "Cannot use 'await' as identifier inside an async function"
2205
+ );
2206
+ }
2207
+ if (name === "arguments" && !(this.currentThisScope().flags & SCOPE_VAR)) {
2208
+ this.raiseRecoverable(
2209
+ start,
2210
+ "Cannot use 'arguments' in class field initializer"
2211
+ );
2212
+ }
2213
+ if ((name === "arguments" || name === "await") && this.inClassStaticBlock) {
2214
+ this.raise(
2215
+ start,
2216
+ `Cannot use ${name} in class static initialization block`
2217
+ );
2218
+ }
2219
+ const kind = lookups.reservedKinds.get(name);
2220
+ if (kind === undefined) return;
2221
+ if (kind === 1) {
2222
+ this.raise(start, `Unexpected keyword '${name}'`);
2223
+ }
2224
+ if (
2225
+ /** @type {number} */ (this.options.ecmaVersion) < 6 &&
2226
+ this.input.slice(start, end).includes("\\")
2227
+ ) {
2228
+ return;
2229
+ }
2230
+ if (kind === 2 || (kind === 3 && this.strict)) {
2231
+ if (name === "await" && !this.inAsync) {
2232
+ this.raiseRecoverable(
2233
+ start,
2234
+ "Cannot use keyword 'await' outside an async function"
2235
+ );
2236
+ }
2237
+ this.raiseRecoverable(start, `The keyword '${name}' is reserved`);
2238
+ }
2239
+ }
2240
+
2241
+ /**
2242
+ * Replaces acorn's `canInsertSemicolon`, whose line-break check slices the
2243
+ * inter-token gap and runs a regexp on it for every ASI decision (hundreds
2244
+ * of thousands per file). Scan the gap for a line terminator instead — no
2245
+ * slice, no regexp.
2246
+ * @returns {boolean} whether a semicolon may be inserted here
2247
+ * @this {ParserInternals}
2248
+ */
2249
+ canInsertSemicolon() {
2250
+ if (this.type === tokTypes.eof || this.type === tokTypes.braceR) {
2251
+ return true;
2252
+ }
2253
+ // the owned nextToken already classified the gap; 2 (comment/unicode in
2254
+ // the gap, or a token from acorn's tokenizer) falls back to the scan
2255
+ return this._gapHasNewline();
2256
+ }
2257
+
2258
+ // ----- comment collection without eager text slicing -----
2259
+
2260
+ /**
2261
+ * Replaces acorn's `skipLineComment` when comments are collected lazily:
2262
+ * the same scan, but no text slice and no position objects. Acorn calls
2263
+ * this for `//`, hashbangs and HTML-style comments (varying `startSkip`).
2264
+ * @this {ParserInternals}
2265
+ * @param {number} startSkip length of the comment opener
2266
+ * @returns {void}
2267
+ */
2268
+ skipLineComment(startSkip) {
2269
+ const comments = this._lazyComments;
2270
+ if (comments === undefined) {
2271
+ return base.skipLineComment.call(this, startSkip);
2272
+ }
2273
+ const input = this.input;
2274
+ const start = this.pos;
2275
+ const len = input.length;
2276
+ let pos = start + startSkip;
2277
+ while (pos < len) {
2278
+ const ch = input.charCodeAt(pos);
2279
+ // LF, CR, LS, PS terminate the comment but are not part of it
2280
+ if (ch === 10 || ch === 13 || ch === 0x2028 || ch === 0x2029) break;
2281
+ pos++;
2282
+ }
2283
+ this.pos = pos;
2284
+ comments.push(new LazyComment(false, start + startSkip, start, pos, input));
2285
+ }
2286
+
2287
+ /**
2288
+ * Replaces acorn's `skipBlockComment` when comments are collected lazily.
2289
+ * Locations are always off in lazy mode, so line breaks need no handling.
2290
+ * @this {ParserInternals}
2291
+ * @returns {void}
2292
+ */
2293
+ skipBlockComment() {
2294
+ const comments = this._lazyComments;
2295
+ if (comments === undefined) {
2296
+ return base.skipBlockComment.call(this);
2297
+ }
2298
+ const start = this.pos;
2299
+ const end = this.input.indexOf("*/", (this.pos += 2));
2300
+ if (end === -1) this.raise(this.pos - 2, "Unterminated comment");
2301
+ this.pos = end + 2;
2302
+ comments.push(
2303
+ new LazyComment(true, start + 2, start, this.pos, this.input)
2304
+ );
2305
+ }
2306
+
2307
+ // ----- lazy range -----
2308
+
2309
+ /**
2310
+ * @returns {Node} new node
2311
+ * @this {ParserInternals}
2312
+ */
2313
+ startNode() {
2314
+ if (!this._lazy) return base.startNode.call(this);
2315
+ return new LazyLocNode(this.start);
2316
+ }
2317
+
2318
+ /**
2319
+ * @param {number} pos start offset
2320
+ * @param {Position=} loc start position when acorn tracks locations
2321
+ * @returns {Node} new node
2322
+ * @this {ParserInternals}
2323
+ */
2324
+ startNodeAt(pos, loc) {
2325
+ if (!this._lazy) return base.startNodeAt.call(this, pos, loc);
2326
+ return new LazyLocNode(pos);
2327
+ }
2328
+
2329
+ /**
2330
+ * Lazy-mode `finishNode`: acorn's `locations`/`ranges` writes are dead when
2331
+ * `range` is served lazily and `loc` not at all, so skip them and the `finishNodeAt`
2332
+ * indirection. Runs once per node.
2333
+ * @param {Node} node node to finish
2334
+ * @param {string} type node type
2335
+ * @returns {Node} the finished node
2336
+ * @this {ParserInternals}
2337
+ */
2338
+ finishNode(node, type) {
2339
+ if (!this._lazy) return base.finishNode.call(this, node, type);
2340
+ node.type = type;
2341
+ node.end = this.lastTokEnd;
2342
+ return node;
2343
+ }
2344
+
2345
+ /**
2346
+ * Mirror of acorn's `copyNode`, which bypasses `startNodeAt` via
2347
+ * `new Node(...)` and would otherwise produce non-lazy nodes.
2348
+ * @param {Node} node node to copy
2349
+ * @returns {Node} copied node
2350
+ * @this {ParserInternals}
2351
+ */
2352
+ copyNode(node) {
2353
+ const newNode = this.startNodeAt(node.start, this.startLoc);
2354
+ const from = /** @type {Record<string, unknown>} */ (
2355
+ /** @type {unknown} */ (node)
2356
+ );
2357
+ const to = /** @type {Record<string, unknown>} */ (
2358
+ /** @type {unknown} */ (newNode)
2359
+ );
2360
+ for (const prop in from) to[prop] = from[prop];
2361
+ return newNode;
2362
+ }
2363
+
2364
+ // ----- owned node construction (single-shape nodes, replaces acorn's
2365
+ // start-empty-then-mutate flow one node type at a time) -----
2366
+
2367
+ /**
2368
+ * Owned `parseIdent` for the common name-token case: builds the finished
2369
+ * `IdentifierNode` directly, skipping acorn's `parseIdentNode`/`startNode`/
2370
+ * `finishNode` chain and its keyword branches. Keyword-as-identifier
2371
+ * (`obj.class`) and non-lazy mode delegate to acorn.
2372
+ * @param {boolean=} liberal whether reserved words are allowed
2373
+ * @returns {Identifier} identifier node
2374
+ * @this {ParserInternals}
2375
+ */
2376
+ parseIdent(liberal) {
2377
+ if (this.type !== tokTypes.name || !this._lazy) {
2378
+ return base.parseIdent.call(this, liberal);
2379
+ }
2380
+ const node = /** @type {Identifier} */ (
2381
+ /** @type {unknown} */ (
2382
+ new IdentifierNode(
2383
+ this.start,
2384
+ this.end,
2385
+ /** @type {string} */ (this.value)
2386
+ )
2387
+ )
2388
+ );
2389
+ this.next(Boolean(liberal));
2390
+ if (!liberal) {
2391
+ this.checkUnreserved(node);
2392
+ if (node.name === "await" && !this.awaitIdentPos) {
2393
+ this.awaitIdentPos = node.start;
2394
+ }
2395
+ }
2396
+ return node;
2397
+ }
2398
+
2399
+ /**
2400
+ * Owned `parseSubscript`, an exact-semantics copy of acorn 8's with the
2401
+ * node construction replaced: member and call nodes are built fully-formed
2402
+ * after their property/arguments parse (the half-built node was never
2403
+ * reachable during it), landing on `MemberExpressionNode`/
2404
+ * `CallExpressionNode`'s single shapes. Pre-optional-chaining ecmaVersions
2405
+ * and non-lazy mode delegate to acorn.
2406
+ * @param {Expression} baseExpr subscript base
2407
+ * @param {number} startPos expression start offset
2408
+ * @param {Position | undefined} startLoc expression start position
2409
+ * @param {boolean | undefined} noCalls whether calls are forbidden (`new` callee)
2410
+ * @param {boolean} maybeAsyncArrow whether this may be an async arrow head
2411
+ * @param {boolean} optionalChained whether the chain is already optional
2412
+ * @param {boolean | string} forInit for-init context flag
2413
+ * @returns {Expression} subscript element or `baseExpr` when done
2414
+ * @this {ParserInternals}
2415
+ */
2416
+ parseSubscript(
2417
+ baseExpr,
2418
+ startPos,
2419
+ startLoc,
2420
+ noCalls,
2421
+ maybeAsyncArrow,
2422
+ optionalChained,
2423
+ forInit
2424
+ ) {
2425
+ if (!this._subscriptFastPath) {
2426
+ return base.parseSubscript.call(
2427
+ this,
2428
+ baseExpr,
2429
+ startPos,
2430
+ startLoc,
2431
+ noCalls,
2432
+ maybeAsyncArrow,
2433
+ optionalChained,
2434
+ forInit
2435
+ );
2436
+ }
2437
+ const optional = this.eat(tokTypes.questionDot);
2438
+ if (noCalls && optional) {
2439
+ this.raise(
2440
+ this.lastTokStart,
2441
+ "Optional chaining cannot appear in the callee of new expressions"
2442
+ );
2443
+ }
2444
+
2445
+ const computed = this.eat(tokTypes.bracketL);
2446
+ if (
2447
+ computed ||
2448
+ (optional &&
2449
+ this.type !== tokTypes.parenL &&
2450
+ this.type !== tokTypes.backQuote) ||
2451
+ this.eat(tokTypes.dot)
2452
+ ) {
2453
+ /** @type {Node} */
2454
+ let property;
2455
+ if (computed) {
2456
+ property = this.parseExpression();
2457
+ this.expect(tokTypes.bracketR);
2458
+ } else if (
2459
+ this.type === tokTypes.privateId &&
2460
+ /** @type {string} */ (baseExpr.type) !== "Super"
2461
+ ) {
2462
+ property = this.parsePrivateIdent();
2463
+ } else {
2464
+ property = this.parseIdent(this.options.allowReserved !== "never");
2465
+ }
2466
+ return /** @type {Expression} */ (
2467
+ /** @type {unknown} */ (
2468
+ new MemberExpressionNode(
2469
+ startPos,
2470
+ this.lastTokEnd,
2471
+ baseExpr,
2472
+ property,
2473
+ computed,
2474
+ optional
2475
+ )
2476
+ )
2477
+ );
2478
+ } else if (!noCalls && this.eat(tokTypes.parenL)) {
2479
+ const refDestructuringErrors = this._acquireDestructuringErrors();
2480
+ const oldYieldPos = this.yieldPos;
2481
+ const oldAwaitPos = this.awaitPos;
2482
+ const oldAwaitIdentPos = this.awaitIdentPos;
2483
+ this.yieldPos = 0;
2484
+ this.awaitPos = 0;
2485
+ this.awaitIdentPos = 0;
2486
+ const exprList = this.parseExprList(
2487
+ tokTypes.parenR,
2488
+ true,
2489
+ false,
2490
+ refDestructuringErrors
2491
+ );
2492
+ if (maybeAsyncArrow && !optional && this.shouldParseAsyncArrow()) {
2493
+ this.checkPatternErrors(refDestructuringErrors, false);
2494
+ this._releaseDestructuringErrors();
2495
+ this.checkYieldAwaitInDefaultParams();
2496
+ if (this.awaitIdentPos > 0) {
2497
+ this.raise(
2498
+ this.awaitIdentPos,
2499
+ "Cannot use 'await' as identifier inside an async function"
2500
+ );
2501
+ }
2502
+ this.yieldPos = oldYieldPos;
2503
+ this.awaitPos = oldAwaitPos;
2504
+ this.awaitIdentPos = oldAwaitIdentPos;
2505
+ return this.parseSubscriptAsyncArrow(
2506
+ startPos,
2507
+ startLoc,
2508
+ exprList,
2509
+ forInit
2510
+ );
2511
+ }
2512
+ this.checkExpressionErrors(refDestructuringErrors, true);
2513
+ this._releaseDestructuringErrors();
2514
+ this.yieldPos = oldYieldPos || this.yieldPos;
2515
+ this.awaitPos = oldAwaitPos || this.awaitPos;
2516
+ this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos;
2517
+ return /** @type {Expression} */ (
2518
+ /** @type {unknown} */ (
2519
+ new CallExpressionNode(
2520
+ startPos,
2521
+ this.lastTokEnd,
2522
+ baseExpr,
2523
+ exprList,
2524
+ optional
2525
+ )
2526
+ )
2527
+ );
2528
+ } else if (this.type === tokTypes.backQuote) {
2529
+ if (optional || optionalChained) {
2530
+ this.raise(
2531
+ this.start,
2532
+ "Optional chaining cannot appear in the tag of tagged template expressions"
2533
+ );
2534
+ }
2535
+ const node = this.startNodeAt(startPos, startLoc);
2536
+ /** @type {Node & { tag?: Expression, quasi?: Node }} */
2537
+ (node).tag = baseExpr;
2538
+ /** @type {Node & { tag?: Expression, quasi?: Node }} */
2539
+ (node).quasi = this.parseTemplate({ isTagged: true });
2540
+ return /** @type {Expression} */ (
2541
+ /** @type {unknown} */ (
2542
+ this.finishNode(node, "TaggedTemplateExpression")
2543
+ )
2544
+ );
2545
+ }
2546
+ return baseExpr;
2547
+ }
2548
+
2549
+ /**
2550
+ * Owned `parseStatement` for the hot statement heads: acorn starts a node
2551
+ * before dispatching, but the owned statement parsers build their own
2552
+ * single-shape nodes, so that started node was one discarded allocation per
2553
+ * statement. Dispatch the common heads (`var`/`let`/`const`, `if`, `return`,
2554
+ * blocks and plain expression statements) without it; everything rarer, the
2555
+ * `name`-token ambiguities (`let`/`async`/`using`/`await` heads) and
2556
+ * plugin-overridden parsers delegate to acorn.
2557
+ * @param {string | null} context statement context
2558
+ * @param {boolean=} topLevel whether parsing top-level statements
2559
+ * @param {unknown=} exports export tracking object
2560
+ * @returns {Node} statement
2561
+ * @this {ParserInternals}
2562
+ */
2563
+ parseStatement(context, topLevel, exports) {
2564
+ if (!this._stmtFastPath) {
2565
+ return base.parseStatement.call(this, context, topLevel, exports);
2566
+ }
2567
+ const startType = this.type;
2568
+ switch (startType) {
2569
+ case tokTypes._var:
2570
+ case tokTypes._const: {
2571
+ const kind = /** @type {string} */ (this.value);
2572
+ if (context && kind !== "var") this.unexpected();
2573
+ return this._parseVarStatementAt(this.start, kind);
2574
+ }
2575
+ case tokTypes._if:
2576
+ return this._parseIfStatementAt(this.start);
2577
+ case tokTypes._return:
2578
+ return this._parseReturnStatementAt(this.start);
2579
+ case tokTypes.braceL:
2580
+ // the owned parseBlock never reads the started node
2581
+ return this.parseBlock(true);
2582
+ case tokTypes._break:
2583
+ case tokTypes._continue:
2584
+ case tokTypes._debugger:
2585
+ case tokTypes._do:
2586
+ case tokTypes._for:
2587
+ case tokTypes._function:
2588
+ case tokTypes._class:
2589
+ case tokTypes._switch:
2590
+ case tokTypes._throw:
2591
+ case tokTypes._try:
2592
+ case tokTypes._while:
2593
+ case tokTypes._with:
2594
+ case tokTypes.semi:
2595
+ case tokTypes._export:
2596
+ case tokTypes._import:
2597
+ return base.parseStatement.call(this, context, topLevel, exports);
2598
+ default: {
2599
+ if (startType === tokTypes.name) {
2600
+ const value = this.value;
2601
+ if (value === "let") {
2602
+ if (this.isLet(context)) {
2603
+ // mirrors acorn's `context && kind !== "var"` rejection
2604
+ if (context) this.unexpected();
2605
+ return this._parseVarStatementAt(this.start, "let");
2606
+ }
2607
+ // `let` as a plain identifier: expression/label tail below
2608
+ } else if (
2609
+ value === "async" ||
2610
+ value === "using" ||
2611
+ value === "await"
2612
+ ) {
2613
+ // async functions and using declarations keep acorn's
2614
+ // lookahead-heavy classification
2615
+ return base.parseStatement.call(this, context, topLevel, exports);
2616
+ }
2617
+ }
2618
+ // unambiguous expression statement, with acorn's label tail
2619
+ const start = this.start;
2620
+ const maybeName = this.value;
2621
+ const expr = this.parseExpression();
2622
+ if (
2623
+ startType === tokTypes.name &&
2624
+ expr.type === "Identifier" &&
2625
+ this.eat(tokTypes.colon)
2626
+ ) {
2627
+ // labels are rare enough to pay for the started node
2628
+ return this.parseLabeledStatement(
2629
+ this.startNodeAt(start),
2630
+ /** @type {string} */ (maybeName),
2631
+ /** @type {Identifier} */ (expr),
2632
+ context
2633
+ );
2634
+ }
2635
+ return this._parseExpressionStatementAt(start, expr);
2636
+ }
2637
+ }
2638
+ }
2639
+
2640
+ /**
2641
+ * Owned `parseVarStatement`: the passed started node is filled by
2642
+ * `parseVar` as acorn expects, then the finished statement lands on
2643
+ * `VariableDeclarationNode`'s single shape. Non-lazy mode delegates.
2644
+ * @param {Node} node started statement node from `parseStatement`
2645
+ * @param {string} kind declaration kind
2646
+ * @param {boolean=} allowMissingInitializer whether `const x;` is allowed
2647
+ * @returns {Node} variable declaration
2648
+ * @this {ParserInternals}
2649
+ */
2650
+ parseVarStatement(node, kind, allowMissingInitializer) {
2651
+ if (!this._lazy) {
2652
+ return base.parseVarStatement.call(
2653
+ this,
2654
+ node,
2655
+ kind,
2656
+ allowMissingInitializer
2657
+ );
2658
+ }
2659
+ return this._parseVarStatementAt(node.start, kind, allowMissingInitializer);
2660
+ }
2661
+
2662
+ /**
2663
+ * Statement-position `var`/`let`/`const` without a started node: the
2664
+ * declaration lands directly on `VariableDeclarationNode`'s single shape.
2665
+ * @param {number} start statement start offset
2666
+ * @param {string} kind declaration kind
2667
+ * @param {boolean=} allowMissingInitializer whether `const x;` is allowed
2668
+ * @returns {Node} variable declaration
2669
+ * @this {ParserInternals}
2670
+ */
2671
+ _parseVarStatementAt(start, kind, allowMissingInitializer) {
2672
+ this.next();
2673
+ /** @type {Node[]} */
2674
+ const declarations = [];
2675
+ this._parseVarInto(declarations, false, kind, allowMissingInitializer);
2676
+ this.semicolon();
2677
+ return /** @type {Node} */ (
2678
+ /** @type {unknown} */ (
2679
+ new VariableDeclarationNode(start, this.lastTokEnd, declarations, kind)
2680
+ )
2681
+ );
2682
+ }
2683
+
2684
+ /**
2685
+ * Owned `parseVar`, an exact-semantics copy of acorn 8's that builds each
2686
+ * declarator fully-formed on `VariableDeclaratorNode`'s single shape. The
2687
+ * passed node keeps receiving `declarations`/`kind` because
2688
+ * `parseForStatement` finishes it itself. Non-lazy mode delegates.
2689
+ * @param {Node} node declaration node to fill
2690
+ * @param {boolean} isFor whether parsing a `for` head
2691
+ * @param {string} kind declaration kind
2692
+ * @param {boolean=} allowMissingInitializer whether `const x;` is allowed
2693
+ * @returns {Node} the filled node
2694
+ * @this {ParserInternals}
2695
+ */
2696
+ parseVar(node, isFor, kind, allowMissingInitializer) {
2697
+ if (!this._lazy) {
2698
+ return base.parseVar.call(
2699
+ this,
2700
+ node,
2701
+ isFor,
2702
+ kind,
2703
+ allowMissingInitializer
2704
+ );
2705
+ }
2706
+ /** @type {Node[]} */
2707
+ const declarations = [];
2708
+ const target =
2709
+ /** @type {Node & { declarations: Node[], kind: string }} */ (node);
2710
+ target.declarations = declarations;
2711
+ target.kind = kind;
2712
+ this._parseVarInto(declarations, isFor, kind, allowMissingInitializer);
2713
+ return node;
2714
+ }
2715
+
2716
+ /**
2717
+ * The declarator loop of the owned `parseVar`, shared with the owned
2718
+ * `parseStatement`'s node-free statement path.
2719
+ * @param {Node[]} declarations output array for the declarators
2720
+ * @param {boolean} isFor whether parsing a `for` head
2721
+ * @param {string} kind declaration kind
2722
+ * @param {boolean=} allowMissingInitializer whether `const x;` is allowed
2723
+ * @returns {void}
2724
+ * @this {ParserInternals}
2725
+ */
2726
+ _parseVarInto(declarations, isFor, kind, allowMissingInitializer) {
2727
+ const ecmaVersion = this._ecmaVersion;
2728
+ const usingKind = kind === "using" || kind === "await using";
2729
+ for (;;) {
2730
+ const declStart = this.start;
2731
+ const id = usingKind ? this.parseIdent() : this.parseBindingAtom();
2732
+ this.checkLValPattern(
2733
+ id,
2734
+ kind === "var" ? BIND_VAR : BIND_LEXICAL,
2735
+ false
2736
+ );
2737
+ /** @type {Expression | null} */
2738
+ let init = null;
2739
+ if (this.eat(tokTypes.eq)) {
2740
+ init = this.parseMaybeAssign(isFor);
2741
+ } else if (
2742
+ !allowMissingInitializer &&
2743
+ kind === "const" &&
2744
+ !(
2745
+ this.type === tokTypes._in ||
2746
+ (ecmaVersion >= 6 && this.isContextual("of"))
2747
+ )
2748
+ ) {
2749
+ this.unexpected();
2750
+ } else if (
2751
+ !allowMissingInitializer &&
2752
+ usingKind &&
2753
+ ecmaVersion >= 17 &&
2754
+ this.type !== tokTypes._in &&
2755
+ !this.isContextual("of")
2756
+ ) {
2757
+ this.raise(
2758
+ this.lastTokEnd,
2759
+ `Missing initializer in ${kind} declaration`
2760
+ );
2761
+ } else if (
2762
+ !allowMissingInitializer &&
2763
+ id.type !== "Identifier" &&
2764
+ !(isFor && (this.type === tokTypes._in || this.isContextual("of")))
2765
+ ) {
2766
+ this.raise(
2767
+ this.lastTokEnd,
2768
+ "Complex binding patterns require an initialization value"
2769
+ );
2770
+ }
2771
+ declarations.push(
2772
+ /** @type {Node} */ (
2773
+ /** @type {unknown} */ (
2774
+ new VariableDeclaratorNode(declStart, this.lastTokEnd, id, init)
2775
+ )
2776
+ )
2777
+ );
2778
+ if (!this.eat(tokTypes.comma)) break;
2779
+ }
2780
+ }
2781
+
2782
+ /**
2783
+ * Owned `parseExpressionStatement`: the statement lands on
2784
+ * `ExpressionStatementNode`'s single shape (the passed started node is
2785
+ * discarded, matching acorn's observable output). Non-lazy mode delegates.
2786
+ * @param {Node} node started statement node from `parseStatement`
2787
+ * @param {Expression} expr the parsed expression
2788
+ * @returns {Node} expression statement
2789
+ * @this {ParserInternals}
2790
+ */
2791
+ parseExpressionStatement(node, expr) {
2792
+ if (!this._lazy) {
2793
+ return base.parseExpressionStatement.call(this, node, expr);
2794
+ }
2795
+ return this._parseExpressionStatementAt(node.start, expr);
2796
+ }
2797
+
2798
+ /**
2799
+ * `parseExpressionStatement` without a started node.
2800
+ * @param {number} start statement start offset
2801
+ * @param {Expression} expr the parsed expression
2802
+ * @returns {Node} expression statement
2803
+ * @this {ParserInternals}
2804
+ */
2805
+ _parseExpressionStatementAt(start, expr) {
2806
+ this.semicolon();
2807
+ return /** @type {Node} */ (
2808
+ /** @type {unknown} */ (
2809
+ new ExpressionStatementNode(start, this.lastTokEnd, expr)
2810
+ )
2811
+ );
2812
+ }
2813
+
2814
+ /**
2815
+ * Owned `parseBlock`, an exact-semantics copy of acorn 8's landing on
2816
+ * `BlockStatementNode`'s single shape. Non-lazy mode delegates.
2817
+ * @param {boolean=} createNewLexicalScope whether the block opens a scope
2818
+ * @param {Node=} node started statement node, when called from `parseStatement`
2819
+ * @param {boolean=} exitStrict whether to restore sloppy mode at the end
2820
+ * @returns {Node} block statement
2821
+ * @this {ParserInternals}
2822
+ */
2823
+ parseBlock(createNewLexicalScope, node, exitStrict) {
2824
+ if (!this._lazy) {
2825
+ return base.parseBlock.call(
2826
+ this,
2827
+ createNewLexicalScope,
2828
+ node,
2829
+ exitStrict
2830
+ );
2831
+ }
2832
+ if (createNewLexicalScope === undefined) createNewLexicalScope = true;
2833
+ const start = this.start;
2834
+ /** @type {Node[]} */
2835
+ const body = [];
2836
+ this.expect(tokTypes.braceL);
2837
+ if (createNewLexicalScope) this.enterScope(0);
2838
+ while (this.type !== tokTypes.braceR) {
2839
+ body.push(this.parseStatement(null));
2840
+ }
2841
+ if (exitStrict) this.strict = false;
2842
+ this.next();
2843
+ if (createNewLexicalScope) this.exitScope();
2844
+ return /** @type {Node} */ (
2845
+ /** @type {unknown} */ (
2846
+ new BlockStatementNode(start, this.lastTokEnd, body)
2847
+ )
2848
+ );
2849
+ }
2850
+
2851
+ /**
2852
+ * Owned `parseIfStatement` landing on `IfStatementNode`'s single shape.
2853
+ * Non-lazy mode delegates to acorn.
2854
+ * @param {Node} node started statement node from `parseStatement`
2855
+ * @returns {Node} if statement
2856
+ * @this {ParserInternals}
2857
+ */
2858
+ parseIfStatement(node) {
2859
+ if (!this._lazy) return base.parseIfStatement.call(this, node);
2860
+ return this._parseIfStatementAt(node.start);
2861
+ }
2862
+
2863
+ /**
2864
+ * `parseIfStatement` without a started node.
2865
+ * @param {number} start statement start offset
2866
+ * @returns {Node} if statement
2867
+ * @this {ParserInternals}
2868
+ */
2869
+ _parseIfStatementAt(start) {
2870
+ this.next();
2871
+ const test = this.parseParenExpression();
2872
+ // function declarations are allowed in branches outside strict mode
2873
+ const consequent = this.parseStatement("if");
2874
+ const alternate = this.eat(tokTypes._else)
2875
+ ? this.parseStatement("if")
2876
+ : null;
2877
+ return /** @type {Node} */ (
2878
+ /** @type {unknown} */ (
2879
+ new IfStatementNode(start, this.lastTokEnd, test, consequent, alternate)
2880
+ )
2881
+ );
2882
+ }
2883
+
2884
+ /**
2885
+ * Owned `parseReturnStatement` landing on `ReturnStatementNode`'s single
2886
+ * shape. Non-lazy mode delegates to acorn.
2887
+ * @param {Node} node started statement node from `parseStatement`
2888
+ * @returns {Node} return statement
2889
+ * @this {ParserInternals}
2890
+ */
2891
+ parseReturnStatement(node) {
2892
+ if (!this._lazy) {
2893
+ if (!this.allowReturn) this._tryModuleFallback();
2894
+ return base.parseReturnStatement.call(this, node);
2895
+ }
2896
+ return this._parseReturnStatementAt(node.start);
2897
+ }
2898
+
2899
+ /**
2900
+ * In `auto` source type a top-level `return` is script-only syntax. When the
2901
+ * strict module parse reaches it with no module construct seen yet, downgrade
2902
+ * to a sloppy script in place: the prefix parsed under stricter rules stays a
2903
+ * valid sloppy prefix, so the second full parse is avoided.
2904
+ * @returns {boolean} true when the parse was downgraded to script
2905
+ * @this {ParserInternals}
2906
+ */
2907
+ _tryModuleFallback() {
2908
+ if (
2909
+ !this._moduleFallback ||
2910
+ this._moduleSyntaxSeen ||
2911
+ !(this.currentVarScope().flags & SCOPE_TOP)
2912
+ ) {
2913
+ return false;
2914
+ }
2915
+ this.options.allowReturnOutsideFunction = true;
2916
+ // acorn stamps Program.sourceType from this at parseTopLevel's end
2917
+ this.options.sourceType = "script";
2918
+ this.strict = false;
2919
+ this.inModule = false;
2920
+ this._moduleFallback = false;
2921
+ return true;
2922
+ }
2923
+
2924
+ /**
2925
+ * `parseReturnStatement` without a started node.
2926
+ * @param {number} start statement start offset
2927
+ * @returns {Node} return statement
2928
+ * @this {ParserInternals}
2929
+ */
2930
+ _parseReturnStatementAt(start) {
2931
+ if (!this.allowReturn && !this._tryModuleFallback()) {
2932
+ this.raise(this.start, "'return' outside of function");
2933
+ }
2934
+ this.next();
2935
+ /** @type {Expression | null} */
2936
+ let argument = null;
2937
+ // `return` takes an optional argument, so eagerly look for a semicolon
2938
+ if (!(this.eat(tokTypes.semi) || this.insertSemicolon())) {
2939
+ argument = this.parseExpression();
2940
+ this.semicolon();
2941
+ }
2942
+ return /** @type {Node} */ (
2943
+ /** @type {unknown} */ (
2944
+ new ReturnStatementNode(start, this.lastTokEnd, argument)
2945
+ )
2946
+ );
2947
+ }
2948
+
2949
+ /**
2950
+ * Owned `parseSpread` landing on `RestSpreadNode`'s single shape.
2951
+ * Non-lazy mode delegates.
2952
+ * @param {DestructuringErrorsShim | null=} refDestructuringErrors destructuring errors to fill
2953
+ * @returns {Node} spread element
2954
+ * @this {ParserInternals}
2955
+ */
2956
+ parseSpread(refDestructuringErrors) {
2957
+ if (!this._lazy) {
2958
+ return base.parseSpread.call(this, refDestructuringErrors);
2959
+ }
2960
+ const start = this.start;
2961
+ this.next();
2962
+ const argument = this.parseMaybeAssign(false, refDestructuringErrors);
2963
+ return /** @type {Node} */ (
2964
+ /** @type {unknown} */ (
2965
+ new RestSpreadNode(start, this.lastTokEnd, "SpreadElement", argument)
2966
+ )
2967
+ );
2968
+ }
2969
+
2970
+ /**
2971
+ * Owned `parseMaybeConditional` landing on
2972
+ * `ConditionalExpressionNode`'s single shape. Non-lazy mode delegates.
2973
+ * @param {boolean | string=} forInit for-init context flag
2974
+ * @param {DestructuringErrorsShim | null=} refDestructuringErrors destructuring errors to fill
2975
+ * @returns {Expression} expression node
2976
+ * @this {ParserInternals}
2977
+ */
2978
+ parseMaybeConditional(forInit, refDestructuringErrors) {
2979
+ if (!this._lazy) {
2980
+ return base.parseMaybeConditional.call(
2981
+ this,
2982
+ forInit,
2983
+ refDestructuringErrors
2984
+ );
2985
+ }
2986
+ const startPos = this.start;
2987
+ const expr = this.parseExprOps(forInit, refDestructuringErrors);
2988
+ if (this.checkExpressionErrors(refDestructuringErrors)) return expr;
2989
+ if (
2990
+ !(expr.type === "ArrowFunctionExpression" && expr.start === startPos) &&
2991
+ this.eat(tokTypes.question)
2992
+ ) {
2993
+ const consequent = this.parseMaybeAssign();
2994
+ this.expect(tokTypes.colon);
2995
+ const alternate = this.parseMaybeAssign(forInit);
2996
+ return /** @type {Expression} */ (
2997
+ /** @type {unknown} */ (
2998
+ new ConditionalExpressionNode(
2999
+ startPos,
3000
+ this.lastTokEnd,
3001
+ expr,
3002
+ consequent,
3003
+ alternate
3004
+ )
3005
+ )
3006
+ );
3007
+ }
3008
+ return expr;
3009
+ }
3010
+
3011
+ /**
3012
+ * Owned `parseNew`, an exact-semantics copy of acorn 8's: `NewExpression`
3013
+ * lands on `NewExpressionNode`'s single shape (zero-argument calls share
3014
+ * one empty array like acorn's `empty`); the rare `new.target` path keeps
3015
+ * the generic node. Non-lazy mode delegates.
3016
+ * @returns {Expression} new expression or meta property
3017
+ * @this {ParserInternals}
3018
+ */
3019
+ parseNew() {
3020
+ if (!this._lazy) return base.parseNew.call(this);
3021
+ if (this.containsEsc) {
3022
+ this.raiseRecoverable(this.start, "Escape sequence in keyword new");
3023
+ }
3024
+ const nodeStart = this.start;
3025
+ this.next();
3026
+ if (this._ecmaVersion >= 6 && this.type === tokTypes.dot) {
3027
+ const node =
3028
+ /** @type {Node & { meta?: Node, property?: Identifier }} */
3029
+ (this.startNodeAt(nodeStart, undefined));
3030
+ const meta =
3031
+ /** @type {Node & { name?: string }} */
3032
+ (this.startNodeAt(nodeStart, undefined));
3033
+ meta.name = "new";
3034
+ node.meta = this.finishNode(/** @type {Node} */ (meta), "Identifier");
3035
+ this.next();
3036
+ const containsEsc = this.containsEsc;
3037
+ node.property = this.parseIdent(true);
3038
+ if (node.property.name !== "target") {
3039
+ this.raiseRecoverable(
3040
+ node.property.start,
3041
+ "The only valid meta property for new is 'new.target'"
3042
+ );
3043
+ }
3044
+ if (containsEsc) {
3045
+ this.raiseRecoverable(
3046
+ nodeStart,
3047
+ "'new.target' must not contain escaped characters"
3048
+ );
3049
+ }
3050
+ if (!this.allowNewDotTarget) {
3051
+ this.raiseRecoverable(
3052
+ nodeStart,
3053
+ "'new.target' can only be used in functions and class static block"
3054
+ );
3055
+ }
3056
+ return /** @type {Expression} */ (
3057
+ /** @type {unknown} */ (this.finishNode(node, "MetaProperty"))
3058
+ );
3059
+ }
3060
+ const startPos = this.start;
3061
+ const startLoc = this.startLoc;
3062
+ const callee = this.parseSubscripts(
3063
+ this.parseExprAtom(null, false, true),
3064
+ startPos,
3065
+ startLoc,
3066
+ true,
3067
+ false
3068
+ );
3069
+ if (/** @type {string} */ (callee.type) === "Super") {
3070
+ this.raiseRecoverable(startPos, "Invalid use of 'super'");
3071
+ }
3072
+ /** @type {Expression[]} */
3073
+ const args = this.eat(tokTypes.parenL)
3074
+ ? this.parseExprList(tokTypes.parenR, true, false)
3075
+ : EMPTY_NEW_ARGS;
3076
+ return /** @type {Expression} */ (
3077
+ /** @type {unknown} */ (
3078
+ new NewExpressionNode(nodeStart, this.lastTokEnd, callee, args)
3079
+ )
3080
+ );
3081
+ }
3082
+
3083
+ /**
3084
+ * Owned `parseTemplateElement` landing on `TemplateElementNode`'s single
3085
+ * shape; matches acorn's CRLF normalization and invalid-escape handling.
3086
+ * Non-lazy mode delegates.
3087
+ * @param {{ isTagged: boolean }} opts whether the template is tagged
3088
+ * @returns {Node} template element
3089
+ * @this {ParserInternals}
3090
+ */
3091
+ parseTemplateElement(opts) {
3092
+ if (!this._lazy) return base.parseTemplateElement.call(this, opts);
3093
+ const start = this.start;
3094
+ /** @type {{ raw: string, cooked: string | null }} */
3095
+ let value;
3096
+ if (this.type === tokTypes.invalidTemplate) {
3097
+ if (!opts.isTagged) {
3098
+ this.raiseRecoverable(
3099
+ this.start,
3100
+ "Bad escape sequence in untagged template literal"
3101
+ );
3102
+ }
3103
+ value = {
3104
+ raw: /** @type {string} */ (this.value).replace(/\r\n?/g, "\n"),
3105
+ cooked: null
3106
+ };
3107
+ } else {
3108
+ const cooked = /** @type {string} */ (this.value);
3109
+ // Every escape cooks strictly shorter and CRLF shortens, while a lone CR
3110
+ // cooks to the LF the raw normalization would produce — so an
3111
+ // equal-length cooked string IS the normalized raw. That covers every
3112
+ // fast-path chunk (no backslash, no CR): raw and cooked share one string.
3113
+ value = {
3114
+ raw:
3115
+ cooked.length === this.end - this.start
3116
+ ? cooked
3117
+ : this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"),
3118
+ cooked
3119
+ };
3120
+ }
3121
+ this.next();
3122
+ return /** @type {Node} */ (
3123
+ /** @type {unknown} */ (
3124
+ new TemplateElementNode(
3125
+ start,
3126
+ this.lastTokEnd,
3127
+ value,
3128
+ this.type === tokTypes.backQuote
3129
+ )
3130
+ )
3131
+ );
3132
+ }
3133
+
3134
+ /**
3135
+ * Owned `parseTemplate` landing on `TemplateLiteralNode`'s single shape.
3136
+ * Non-lazy mode delegates.
3137
+ * @param {{ isTagged?: boolean }=} opts whether the template is tagged
3138
+ * @returns {Node} template literal
3139
+ * @this {ParserInternals}
3140
+ */
3141
+ parseTemplate(opts) {
3142
+ if (!this._lazy) {
3143
+ return base.parseTemplate.call(
3144
+ this,
3145
+ /** @type {{ isTagged: boolean }} */ (opts)
3146
+ );
3147
+ }
3148
+ const isTagged = (opts !== undefined && opts.isTagged) === true;
3149
+ const start = this.start;
3150
+ this.next();
3151
+ /** @type {Expression[]} */
3152
+ const expressions = [];
3153
+ // one options object for all chunks (only `isTagged` is ever read)
3154
+ const eltOpts = { isTagged };
3155
+ let curElt = /** @type {Node & { tail?: boolean }} */ (
3156
+ this.parseTemplateElement(eltOpts)
3157
+ );
3158
+ const quasis = [/** @type {Node} */ (curElt)];
3159
+ while (!curElt.tail) {
3160
+ if (this.type === tokTypes.eof) {
3161
+ this.raise(this.pos, "Unterminated template literal");
3162
+ }
3163
+ this.expect(tokTypes.dollarBraceL);
3164
+ expressions.push(this.parseExpression());
3165
+ this.expect(tokTypes.braceR);
3166
+ curElt = /** @type {Node & { tail?: boolean }} */ (
3167
+ this.parseTemplateElement(eltOpts)
3168
+ );
3169
+ quasis.push(/** @type {Node} */ (curElt));
3170
+ }
3171
+ this.next();
3172
+ return /** @type {Node} */ (
3173
+ /** @type {unknown} */ (
3174
+ new TemplateLiteralNode(start, this.lastTokEnd, expressions, quasis)
3175
+ )
3176
+ );
3177
+ }
3178
+
3179
+ /**
3180
+ * Owned `parseMaybeUnary`, an exact-semantics copy of acorn 8's: prefix
3181
+ * unary/update and postfix update nodes are built fully-formed on
3182
+ * `UnaryNode`'s shared single shape. Non-lazy mode delegates to acorn.
3183
+ * @param {DestructuringErrorsShim | null} refDestructuringErrors destructuring errors to fill
3184
+ * @param {boolean} sawUnary whether a unary operator was already consumed
3185
+ * @param {boolean} incDec whether the caller was an update operator
3186
+ * @param {boolean | string=} forInit for-init context flag
3187
+ * @returns {Expression} expression node
3188
+ * @this {ParserInternals}
3189
+ */
3190
+ parseMaybeUnary(refDestructuringErrors, sawUnary, incDec, forInit) {
3191
+ if (!this._lazy) {
3192
+ return base.parseMaybeUnary.call(
3193
+ this,
3194
+ refDestructuringErrors,
3195
+ sawUnary,
3196
+ incDec,
3197
+ forInit
3198
+ );
3199
+ }
3200
+ const startPos = this.start;
3201
+ const startLoc = this.startLoc;
3202
+ /** @type {Expression} */
3203
+ let expr;
3204
+ if (this.isContextual("await") && this.canAwait) {
3205
+ expr = this.parseAwait(forInit);
3206
+ sawUnary = true;
3207
+ } else if (/** @type {TokenTypeInternal} */ (this.type).prefix) {
3208
+ const update = this.type === tokTypes.incDec;
3209
+ const operator = /** @type {string} */ (this.value);
3210
+ this.next();
3211
+ const argument = this.parseMaybeUnary(null, true, update, forInit);
3212
+ this.checkExpressionErrors(refDestructuringErrors, true);
3213
+ if (update) {
3214
+ this.checkLValSimple(argument);
3215
+ } else if (
3216
+ this.strict &&
3217
+ operator === "delete" &&
3218
+ isLocalVariableAccess(argument)
3219
+ ) {
3220
+ this.raiseRecoverable(
3221
+ startPos,
3222
+ "Deleting local variable in strict mode"
3223
+ );
3224
+ } else if (operator === "delete" && isPrivateFieldAccess(argument)) {
3225
+ this.raiseRecoverable(startPos, "Private fields can not be deleted");
3226
+ } else {
3227
+ sawUnary = true;
3228
+ }
3229
+ expr = /** @type {Expression} */ (
3230
+ /** @type {unknown} */ (
3231
+ new UnaryNode(
3232
+ startPos,
3233
+ this.lastTokEnd,
3234
+ update ? "UpdateExpression" : "UnaryExpression",
3235
+ operator,
3236
+ true,
3237
+ argument
3238
+ )
3239
+ )
3240
+ );
3241
+ } else if (!sawUnary && this.type === tokTypes.privateId) {
3242
+ if (
3243
+ (forInit || this.privateNameStack.length === 0) &&
3244
+ this.options.checkPrivateFields
3245
+ ) {
3246
+ this.unexpected();
3247
+ }
3248
+ expr = /** @type {Expression} */ (
3249
+ /** @type {unknown} */ (this.parsePrivateIdent())
3250
+ );
3251
+ // a private name is only valid as `#x in obj`
3252
+ if (this.type !== tokTypes._in) this.unexpected();
3253
+ } else {
3254
+ expr = this.parseExprSubscripts(refDestructuringErrors, forInit);
3255
+ if (this.checkExpressionErrors(refDestructuringErrors)) return expr;
3256
+ while (
3257
+ /** @type {TokenTypeInternal} */ (this.type).postfix &&
3258
+ !this.canInsertSemicolon()
3259
+ ) {
3260
+ const operator = /** @type {string} */ (this.value);
3261
+ this.checkLValSimple(expr);
3262
+ this.next();
3263
+ expr = /** @type {Expression} */ (
3264
+ /** @type {unknown} */ (
3265
+ new UnaryNode(
3266
+ startPos,
3267
+ this.lastTokEnd,
3268
+ "UpdateExpression",
3269
+ operator,
3270
+ false,
3271
+ expr
3272
+ )
3273
+ )
3274
+ );
3275
+ }
3276
+ }
3277
+
3278
+ if (!incDec && this.eat(tokTypes.starstar)) {
3279
+ if (sawUnary) {
3280
+ this.unexpected(this.lastTokStart);
3281
+ } else {
3282
+ return this.buildBinary(
3283
+ startPos,
3284
+ startLoc,
3285
+ expr,
3286
+ this.parseMaybeUnary(null, false, false, forInit),
3287
+ "**",
3288
+ false
3289
+ );
3290
+ }
3291
+ }
3292
+ return expr;
3293
+ }
3294
+
3295
+ /**
3296
+ * Owned `parseMaybeAssign`, an exact-semantics copy of acorn 8's: the
3297
+ * operator is captured before `next()` and the `AssignmentExpression` is
3298
+ * built fully-formed on `AssignmentNode`'s single shape after the
3299
+ * right-hand parse. Yield and non-lazy mode delegate to acorn.
3300
+ * @param {boolean | string=} forInit for-init context flag
3301
+ * @param {DestructuringErrorsShim | null=} refDestructuringErrors destructuring errors to fill
3302
+ * @param {((this: unknown, left: Expression, startPos: number, startLoc?: Position) => Expression)=} afterLeftParse hook applied to the parsed left side
3303
+ * @returns {Expression} expression node
3304
+ * @this {ParserInternals}
3305
+ */
3306
+ parseMaybeAssign(forInit, refDestructuringErrors, afterLeftParse) {
3307
+ if (!this._lazy) {
3308
+ return base.parseMaybeAssign.call(
3309
+ this,
3310
+ forInit,
3311
+ refDestructuringErrors,
3312
+ afterLeftParse
3313
+ );
3314
+ }
3315
+ if (this.isContextual("yield")) {
3316
+ if (this.inGenerator) return this.parseYield(forInit);
3317
+ // the tokenizer assumed an expression follows `yield`, but this
3318
+ // isn't that kind of yield
3319
+ this.exprAllowed = false;
3320
+ }
3321
+
3322
+ let ownDestructuringErrors = false;
3323
+ let oldParenAssign = -1;
3324
+ let oldTrailingComma = -1;
3325
+ let oldDoubleProto = -1;
3326
+ if (refDestructuringErrors) {
3327
+ oldParenAssign = refDestructuringErrors.parenthesizedAssign;
3328
+ oldTrailingComma = refDestructuringErrors.trailingComma;
3329
+ oldDoubleProto = refDestructuringErrors.doubleProto;
3330
+ refDestructuringErrors.parenthesizedAssign =
3331
+ refDestructuringErrors.trailingComma = -1;
3332
+ } else {
3333
+ refDestructuringErrors = this._acquireDestructuringErrors();
3334
+ ownDestructuringErrors = true;
3335
+ }
3336
+
3337
+ const startPos = this.start;
3338
+ const startLoc = this.startLoc;
3339
+ if (this.type === tokTypes.parenL || this.type === tokTypes.name) {
3340
+ this.potentialArrowAt = this.start;
3341
+ this.potentialArrowInForAwait = forInit === "await";
3342
+ }
3343
+ let left = this.parseMaybeConditional(forInit, refDestructuringErrors);
3344
+ if (afterLeftParse) {
3345
+ left = afterLeftParse.call(this, left, startPos, startLoc);
3346
+ }
3347
+ if (/** @type {TokenTypeInternal} */ (this.type).isAssign) {
3348
+ const operator = /** @type {string} */ (this.value);
3349
+ if (this.type === tokTypes.eq) {
3350
+ left = /** @type {Expression} */ (
3351
+ this.toAssignable(left, false, refDestructuringErrors)
3352
+ );
3353
+ }
3354
+ if (!ownDestructuringErrors) {
3355
+ refDestructuringErrors.parenthesizedAssign =
3356
+ refDestructuringErrors.trailingComma =
3357
+ refDestructuringErrors.doubleProto =
3358
+ -1;
3359
+ }
3360
+ if (refDestructuringErrors.shorthandAssign >= left.start) {
3361
+ // shorthand default was used correctly
3362
+ refDestructuringErrors.shorthandAssign = -1;
3363
+ }
3364
+ if (this.type === tokTypes.eq) this.checkLValPattern(left);
3365
+ else this.checkLValSimple(left);
3366
+ // the own record's last read was above, so the nested right-side
3367
+ // parse below can already reuse its pool slot
3368
+ if (ownDestructuringErrors) this._releaseDestructuringErrors();
3369
+ this.next();
3370
+ const right = this.parseMaybeAssign(forInit);
3371
+ if (oldDoubleProto > -1) {
3372
+ refDestructuringErrors.doubleProto = oldDoubleProto;
3373
+ }
3374
+ return /** @type {Expression} */ (
3375
+ /** @type {unknown} */ (
3376
+ new AssignmentNode(startPos, this.lastTokEnd, operator, left, right)
3377
+ )
3378
+ );
3379
+ } else if (ownDestructuringErrors) {
3380
+ this.checkExpressionErrors(refDestructuringErrors, true);
3381
+ this._releaseDestructuringErrors();
3382
+ }
3383
+ if (oldParenAssign > -1) {
3384
+ refDestructuringErrors.parenthesizedAssign = oldParenAssign;
3385
+ }
3386
+ if (oldTrailingComma > -1) {
3387
+ refDestructuringErrors.trailingComma = oldTrailingComma;
3388
+ }
3389
+ return left;
3390
+ }
3391
+
3392
+ /**
3393
+ * Owned `parseExprOps`, an exact copy of acorn 8's, so the hot expression
3394
+ * spine (`parseMaybeAssign` → here → `parseMaybeUnary`) stays monomorphic
3395
+ * on owned code. Non-lazy mode delegates.
3396
+ * @param {boolean | string=} forInit for-init context flag
3397
+ * @param {DestructuringErrorsShim | null=} refDestructuringErrors destructuring errors to fill
3398
+ * @returns {Expression} expression node
3399
+ * @this {ParserInternals}
3400
+ */
3401
+ parseExprOps(forInit, refDestructuringErrors) {
3402
+ if (!this._lazy) {
3403
+ return base.parseExprOps.call(this, forInit, refDestructuringErrors);
3404
+ }
3405
+ const startPos = this.start;
3406
+ const startLoc = this.startLoc;
3407
+ const expr = this.parseMaybeUnary(
3408
+ refDestructuringErrors || null,
3409
+ false,
3410
+ false,
3411
+ forInit
3412
+ );
3413
+ if (this.checkExpressionErrors(refDestructuringErrors)) return expr;
3414
+ return expr.start === startPos && expr.type === "ArrowFunctionExpression"
3415
+ ? expr
3416
+ : this.parseExprOp(expr, startPos, startLoc, -1, forInit);
3417
+ }
3418
+
3419
+ /**
3420
+ * Owned `parseExprOp`, an exact-semantics copy of acorn 8's with the
3421
+ * same-precedence continuation turned from tail recursion into a loop —
3422
+ * `a + b + c + d` runs one frame instead of one per operator. Non-lazy mode
3423
+ * delegates.
3424
+ * @param {Expression} left left operand
3425
+ * @param {number} leftStartPos expression start offset
3426
+ * @param {Position | undefined} leftStartLoc expression start position
3427
+ * @param {number} minPrec minimal binding precedence to continue
3428
+ * @param {boolean | string=} forInit for-init context flag (excludes `in`)
3429
+ * @returns {Expression} expression node
3430
+ * @this {ParserInternals}
3431
+ */
3432
+ parseExprOp(left, leftStartPos, leftStartLoc, minPrec, forInit) {
3433
+ if (!this._lazy) {
3434
+ return base.parseExprOp.call(
3435
+ this,
3436
+ left,
3437
+ leftStartPos,
3438
+ leftStartLoc,
3439
+ minPrec,
3440
+ forInit
3441
+ );
3442
+ }
3443
+ for (;;) {
3444
+ const type = /** @type {TokenTypeInternal} */ (this.type);
3445
+ let prec = type.binop;
3446
+ // acorn's TokenType sets binop to null (never undefined) when absent
3447
+ if (
3448
+ prec === null ||
3449
+ prec <= minPrec ||
3450
+ (forInit && type === tokTypes._in)
3451
+ ) {
3452
+ return left;
3453
+ }
3454
+ const logical =
3455
+ type === tokTypes.logicalOR || type === tokTypes.logicalAND;
3456
+ const coalesce = type === tokTypes.coalesce;
3457
+ if (coalesce) {
3458
+ // acorn parses `??`'s right at logical precedence so the mixing
3459
+ // check below sees any unparenthesized `&&`/`||` as a sibling
3460
+ prec = /** @type {number} */ (
3461
+ /** @type {TokenTypeInternal} */ (tokTypes.logicalAND).binop
3462
+ );
3463
+ }
3464
+ const op = /** @type {string} */ (this.value);
3465
+ this.next();
3466
+ const startPos = this.start;
3467
+ const right = this.parseExprOp(
3468
+ this.parseMaybeUnary(null, false, false, forInit),
3469
+ startPos,
3470
+ this.startLoc,
3471
+ prec,
3472
+ forInit
3473
+ );
3474
+ left = this.buildBinary(
3475
+ leftStartPos,
3476
+ leftStartLoc,
3477
+ left,
3478
+ right,
3479
+ op,
3480
+ logical || coalesce
3481
+ );
3482
+ if (
3483
+ (logical && this.type === tokTypes.coalesce) ||
3484
+ (coalesce &&
3485
+ (this.type === tokTypes.logicalOR ||
3486
+ this.type === tokTypes.logicalAND))
3487
+ ) {
3488
+ this.raiseRecoverable(
3489
+ this.start,
3490
+ "Logical expressions and coalesce expressions cannot be mixed. Wrap either by parentheses"
3491
+ );
3492
+ }
3493
+ }
3494
+ }
3495
+
3496
+ /**
3497
+ * Owned `buildBinary` (acorn calls it only from `parseExprOp`): binary and
3498
+ * logical nodes are built fully-formed on `BinaryNode`'s single shape.
3499
+ * Non-lazy mode delegates to acorn.
3500
+ * @param {number} startPos expression start offset
3501
+ * @param {Position | undefined} startLoc expression start position
3502
+ * @param {Expression} left left operand
3503
+ * @param {Expression} right right operand
3504
+ * @param {string} op operator text
3505
+ * @param {boolean} logical whether this is a logical/coalesce expression
3506
+ * @returns {Expression} binary or logical expression node
3507
+ * @this {ParserInternals}
3508
+ */
3509
+ buildBinary(startPos, startLoc, left, right, op, logical) {
3510
+ if (!this._lazy) {
3511
+ return base.buildBinary.call(
3512
+ this,
3513
+ startPos,
3514
+ startLoc,
3515
+ left,
3516
+ right,
3517
+ op,
3518
+ logical
3519
+ );
3520
+ }
3521
+ const rightNode = /** @type {Node} */ (/** @type {unknown} */ (right));
3522
+ if (rightNode.type === "PrivateIdentifier") {
3523
+ this.raise(
3524
+ rightNode.start,
3525
+ "Private identifier can only be left side of binary expression"
3526
+ );
3527
+ }
3528
+ return /** @type {Expression} */ (
3529
+ /** @type {unknown} */ (
3530
+ new BinaryNode(
3531
+ startPos,
3532
+ this.lastTokEnd,
3533
+ logical ? "LogicalExpression" : "BinaryExpression",
3534
+ left,
3535
+ op,
3536
+ right
3537
+ )
3538
+ )
3539
+ );
3540
+ }
3541
+
3542
+ /**
3543
+ * Owned `parseExprAtom` for the hot atoms: identifiers (with acorn's exact
3544
+ * async-function/async-arrow detection), number/string literals, keyword
3545
+ * literals (`true`/`false`/`null` — on the same `LiteralNode` shape as the
3546
+ * rest) and `this`. Everything else, and non-lazy mode, delegates to acorn.
3547
+ * @param {DestructuringErrorsShim | null=} refDestructuringErrors destructuring errors to fill
3548
+ * @param {boolean | string=} forInit for-init context flag
3549
+ * @param {boolean=} forNew whether parsed as a `new` callee
3550
+ * @returns {Expression} expression atom
3551
+ * @this {ParserInternals}
3552
+ */
3553
+ parseExprAtom(refDestructuringErrors, forInit, forNew) {
3554
+ if (!this._lazy) {
3555
+ return base.parseExprAtom.call(
3556
+ this,
3557
+ refDestructuringErrors,
3558
+ forInit,
3559
+ forNew
3560
+ );
3561
+ }
3562
+ // division in expression position: the tokenizer got confused, force a
3563
+ // regexp re-read (mirrors the top of acorn's parseExprAtom)
3564
+ if (this.type === tokTypes.slash) this.readRegexp();
3565
+ const type = this.type;
3566
+ if (type === tokTypes.name) {
3567
+ const canBeArrow = this.potentialArrowAt === this.start;
3568
+ const startPos = this.start;
3569
+ const startLoc = this.startLoc;
3570
+ const containsEsc = this.containsEsc;
3571
+ let id = this.parseIdent(false);
3572
+ // `async` compare first — almost every identifier fails it, skipping
3573
+ // the version probe (all operands are pure)
3574
+ if (
3575
+ id.name === "async" &&
3576
+ !containsEsc &&
3577
+ this._ecmaVersion >= 8 &&
3578
+ !this.canInsertSemicolon() &&
3579
+ this.eat(tokTypes._function)
3580
+ ) {
3581
+ this.overrideContext(tokContexts.f_expr);
3582
+ return this.parseFunction(
3583
+ this.startNodeAt(startPos, startLoc),
3584
+ 0,
3585
+ false,
3586
+ true,
3587
+ forInit
3588
+ );
3589
+ }
3590
+ if (canBeArrow && !this.canInsertSemicolon()) {
3591
+ if (this.eat(tokTypes.arrow)) {
3592
+ return this.parseArrowExpression(
3593
+ this.startNodeAt(startPos, startLoc),
3594
+ [id],
3595
+ false,
3596
+ forInit
3597
+ );
3598
+ }
3599
+ if (
3600
+ id.name === "async" &&
3601
+ !containsEsc &&
3602
+ this._ecmaVersion >= 8 &&
3603
+ this.type === tokTypes.name &&
3604
+ (!this.potentialArrowInForAwait ||
3605
+ this.value !== "of" ||
3606
+ this.containsEsc)
3607
+ ) {
3608
+ id = this.parseIdent(false);
3609
+ if (this.canInsertSemicolon() || !this.eat(tokTypes.arrow)) {
3610
+ this.unexpected();
3611
+ }
3612
+ return this.parseArrowExpression(
3613
+ this.startNodeAt(startPos, startLoc),
3614
+ [id],
3615
+ true,
3616
+ forInit
3617
+ );
3618
+ }
3619
+ }
3620
+ return id;
3621
+ }
3622
+ if (type === tokTypes.num || type === tokTypes.string) {
3623
+ return /** @type {Expression} */ (
3624
+ /** @type {unknown} */ (this.parseLiteral(this.value))
3625
+ );
3626
+ }
3627
+ if (
3628
+ type === tokTypes._null ||
3629
+ type === tokTypes._true ||
3630
+ type === tokTypes._false
3631
+ ) {
3632
+ const node = new LiteralNode(
3633
+ this.start,
3634
+ this.end,
3635
+ type === tokTypes._null ? null : type === tokTypes._true,
3636
+ /** @type {string} */ (type.keyword)
3637
+ );
3638
+ this.next();
3639
+ return /** @type {Expression} */ (/** @type {unknown} */ (node));
3640
+ }
3641
+ if (type === tokTypes._this) {
3642
+ const node = new ThisNode(this.start, this.end);
3643
+ this.next();
3644
+ return /** @type {Expression} */ (/** @type {unknown} */ (node));
3645
+ }
3646
+ if (type === tokTypes.bracketL) {
3647
+ const start = this.start;
3648
+ this.next();
3649
+ const elements = this.parseExprList(
3650
+ tokTypes.bracketR,
3651
+ true,
3652
+ true,
3653
+ refDestructuringErrors
3654
+ );
3655
+ return /** @type {Expression} */ (
3656
+ /** @type {unknown} */ (
3657
+ new ArrayExpressionNode(start, this.lastTokEnd, elements)
3658
+ )
3659
+ );
3660
+ }
3661
+ return base.parseExprAtom.call(
3662
+ this,
3663
+ refDestructuringErrors,
3664
+ forInit,
3665
+ forNew
3666
+ );
3667
+ }
3668
+
3669
+ /**
3670
+ * Owned `parseObj`, an exact-semantics copy of acorn 8's landing on
3671
+ * `ObjectNode`'s single shape (the ES5 trailing-comma gate is dropped —
3672
+ * the fast path requires ES11+). Non-lazy mode delegates.
3673
+ * @param {boolean} isPattern whether parsing a binding pattern
3674
+ * @param {DestructuringErrorsShim | null=} refDestructuringErrors destructuring errors to fill
3675
+ * @returns {Node} object expression or pattern
3676
+ * @this {ParserInternals}
3677
+ */
3678
+ parseObj(isPattern, refDestructuringErrors) {
3679
+ if (!this._subscriptFastPath) {
3680
+ return base.parseObj.call(this, isPattern, refDestructuringErrors);
3681
+ }
3682
+ const start = this.start;
3683
+ let first = true;
3684
+ // acorn's ES6+ `checkPropClash` only ever reads/writes `.proto`, so the
3685
+ // record is pooled by nesting depth (like `_deStack`); a subclass override
3686
+ // might write arbitrary keys and gets a fresh `{}` instead. Depth resets
3687
+ // implicitly since a raise aborts the whole parse.
3688
+ const pooled = this._propHashFastPath;
3689
+ /** @type {Record<string, unknown>} */
3690
+ let propHash;
3691
+ if (pooled) {
3692
+ const stack = this._propHashStack;
3693
+ const depth = this._propHashDepth++;
3694
+ const cached = stack[depth];
3695
+ if (cached !== undefined) {
3696
+ cached.proto = false;
3697
+ propHash = cached;
3698
+ } else {
3699
+ propHash = stack[depth] = { proto: false };
3700
+ }
3701
+ } else {
3702
+ propHash = {};
3703
+ }
3704
+ /** @type {Node[]} */
3705
+ const properties = [];
3706
+ this.next();
3707
+ while (!this.eat(tokTypes.braceR)) {
3708
+ if (!first) {
3709
+ this.expect(tokTypes.comma);
3710
+ if (this.afterTrailingComma(tokTypes.braceR)) break;
3711
+ } else {
3712
+ first = false;
3713
+ }
3714
+ const prop = this.parseProperty(isPattern, refDestructuringErrors);
3715
+ if (!isPattern) {
3716
+ this.checkPropClash(prop, propHash, refDestructuringErrors);
3717
+ }
3718
+ properties.push(prop);
3719
+ }
3720
+ if (pooled) this._propHashDepth--;
3721
+ return /** @type {Node} */ (
3722
+ /** @type {unknown} */ (
3723
+ new ObjectNode(
3724
+ start,
3725
+ this.lastTokEnd,
3726
+ isPattern ? "ObjectPattern" : "ObjectExpression",
3727
+ properties
3728
+ )
3729
+ )
3730
+ );
3731
+ }
3732
+
3733
+ /**
3734
+ * Owned `parseProperty`, an exact-semantics copy of acorn 8's: spread/rest
3735
+ * land fully-formed on `RestSpreadNode` and properties start pre-shaped on
3736
+ * `PropertyNode`, which acorn's shared `parsePropertyName`/
3737
+ * `parsePropertyValue` then fill in place (ES9+ semantics assumed via the
3738
+ * ES11 fast-path gate). Non-lazy mode delegates.
3739
+ * @param {boolean} isPattern whether parsing a binding pattern
3740
+ * @param {DestructuringErrorsShim | null=} refDestructuringErrors destructuring errors to fill
3741
+ * @returns {Node} property, spread element or rest element
3742
+ * @this {ParserInternals}
3743
+ */
3744
+ parseProperty(isPattern, refDestructuringErrors) {
3745
+ if (!this._subscriptFastPath) {
3746
+ return base.parseProperty.call(this, isPattern, refDestructuringErrors);
3747
+ }
3748
+ const nodeStart = this.start;
3749
+ if (this.eat(tokTypes.ellipsis)) {
3750
+ if (isPattern) {
3751
+ const argument = /** @type {Node} */ (
3752
+ /** @type {unknown} */ (this.parseIdent(false))
3753
+ );
3754
+ if (this.type === tokTypes.comma) {
3755
+ this.raiseRecoverable(
3756
+ this.start,
3757
+ "Comma is not permitted after the rest element"
3758
+ );
3759
+ }
3760
+ return /** @type {Node} */ (
3761
+ /** @type {unknown} */ (
3762
+ new RestSpreadNode(
3763
+ nodeStart,
3764
+ this.lastTokEnd,
3765
+ "RestElement",
3766
+ argument
3767
+ )
3768
+ )
3769
+ );
3770
+ }
3771
+ const argument = /** @type {Node} */ (
3772
+ /** @type {unknown} */ (
3773
+ this.parseMaybeAssign(false, refDestructuringErrors)
3774
+ )
3775
+ );
3776
+ // disallow trailing comma via `this.toAssignable()`
3777
+ if (
3778
+ this.type === tokTypes.comma &&
3779
+ refDestructuringErrors &&
3780
+ refDestructuringErrors.trailingComma < 0
3781
+ ) {
3782
+ refDestructuringErrors.trailingComma = this.start;
3783
+ }
3784
+ return /** @type {Node} */ (
3785
+ /** @type {unknown} */ (
3786
+ new RestSpreadNode(
3787
+ nodeStart,
3788
+ this.lastTokEnd,
3789
+ "SpreadElement",
3790
+ argument
3791
+ )
3792
+ )
3793
+ );
3794
+ }
3795
+ const prop = /** @type {Node} */ (
3796
+ /** @type {unknown} */ (new PropertyNode(nodeStart))
3797
+ );
3798
+ let isGenerator = false;
3799
+ /** @type {number | undefined} */
3800
+ let startPos;
3801
+ /** @type {Position | undefined} */
3802
+ let startLoc;
3803
+ if (isPattern || refDestructuringErrors) {
3804
+ startPos = this.start;
3805
+ startLoc = this.startLoc;
3806
+ }
3807
+ if (!isPattern) isGenerator = this.eat(tokTypes.star);
3808
+ const containsEsc = this.containsEsc;
3809
+ this.parsePropertyName(prop);
3810
+ let isAsync = false;
3811
+ if (!isPattern && !containsEsc && !isGenerator && this.isAsyncProp(prop)) {
3812
+ isAsync = true;
3813
+ isGenerator = this.eat(tokTypes.star);
3814
+ this.parsePropertyName(prop);
3815
+ }
3816
+ this.parsePropertyValue(
3817
+ prop,
3818
+ isPattern,
3819
+ isGenerator,
3820
+ isAsync,
3821
+ startPos,
3822
+ startLoc,
3823
+ refDestructuringErrors,
3824
+ containsEsc
3825
+ );
3826
+ return this.finishNode(prop, "Property");
3827
+ }
3828
+
3829
+ /**
3830
+ * Owned `parseLiteral`: builds the finished `LiteralNode` directly; the
3831
+ * `bigint` branch matches acorn's. Non-lazy mode delegates to acorn.
3832
+ * @param {unknown} value literal value
3833
+ * @returns {Node} literal node
3834
+ * @this {ParserInternals}
3835
+ */
3836
+ parseLiteral(value) {
3837
+ if (!this._lazy) return base.parseLiteral.call(this, value);
3838
+ const start = this.start;
3839
+ const end = this.end;
3840
+ const raw = this.input.slice(start, end);
3841
+ const node = new LiteralNode(start, end, value, raw);
3842
+ if (raw.charCodeAt(raw.length - 1) === 110) {
3843
+ // acorn falls back to normalizing `raw` when `BigInt` is missing;
3844
+ // every Node version webpack supports has it, so `value` is set
3845
+ /** @type {LiteralNode & { bigint?: string }} */ (node).bigint =
3846
+ /** @type {bigint} */ (value).toString();
3847
+ }
3848
+ this.next();
3849
+ return /** @type {Node} */ (/** @type {unknown} */ (node));
3850
+ }
3851
+
3852
+ /**
3853
+ * Single-construction regexp literals: acorn validates the pattern and
3854
+ * then builds the value with a second `new RegExp`. This override scans
3855
+ * like acorn, keeps acorn's flag validation (for its exact messages) and
3856
+ * lets one `new RegExp` be both the V8-backed validation and the value.
3857
+ * @this {ParserInternals & { regexpState: unknown }}
3858
+ * @returns {void}
3859
+ */
3860
+ readRegexp() {
3861
+ const input = this.input;
3862
+ const start = this.pos;
3863
+ const len = input.length;
3864
+ let escaped = false;
3865
+ let inClass = false;
3866
+ let pos = start;
3867
+ for (;;) {
3868
+ if (pos >= len) this.raise(start, "Unterminated regular expression");
3869
+ const ch = input.charCodeAt(pos);
3870
+ // LF, CR, LS, PS
3871
+ if (ch === 10 || ch === 13 || ch === 0x2028 || ch === 0x2029) {
3872
+ this.raise(start, "Unterminated regular expression");
3873
+ }
3874
+ if (escaped) {
3875
+ escaped = false;
3876
+ } else {
3877
+ if (ch === 91) inClass = true;
3878
+ else if (ch === 93 && inClass) inClass = false;
3879
+ else if (ch === 47 && !inClass) break;
3880
+ escaped = ch === 92;
3881
+ }
3882
+ pos++;
3883
+ }
3884
+ const pattern = input.slice(start, pos);
3885
+ this.pos = pos + 1;
3886
+ const flagsStart = this.pos;
3887
+ const flags = this.readWord1();
3888
+ if (this.containsEsc) this.unexpected(flagsStart);
3889
+
3890
+ // acorn's per-ecmaVersion flag validation, kept for its exact errors;
3891
+ // the whitelist is precomputed in the constructor
3892
+ const ecmaVersion = this._ecmaVersion;
3893
+ const validFlags = this._validRegexpFlags;
3894
+ let hasU = false;
3895
+ let hasV = false;
3896
+ for (let i = 0; i < flags.length; i++) {
3897
+ const flag = flags.charAt(i);
3898
+ if (!validFlags.includes(flag)) {
3899
+ this.raise(start, "Invalid regular expression flag");
3900
+ }
3901
+ if (flags.includes(flag, i + 1)) {
3902
+ this.raise(start, "Duplicate regular expression flag");
3903
+ }
3904
+ if (flag === "u") hasU = true;
3905
+ if (flag === "v") hasV = true;
3906
+ }
3907
+ if (ecmaVersion >= 15 && hasU && hasV) {
3908
+ this.raise(start, "Invalid regular expression flag");
3909
+ }
3910
+
3911
+ let value = null;
3912
+ try {
3913
+ value = new RegExp(pattern, flags);
3914
+ } catch (err) {
3915
+ // V8's verdict on the pattern, like validateRegExpPattern below
3916
+ this.raiseRecoverable(start, /** @type {Error} */ (err).message);
3917
+ }
3918
+ return this.finishToken(tokTypes.regexp, { pattern, flags, value });
3919
+ }
3920
+
3921
+ // ----- regexp validation (V8-backed, replaces acorn's JS revalidation) -----
3922
+
3923
+ /**
3924
+ * Acorn constructs the literal's `RegExp` value right after this hook, so
3925
+ * V8 validates every pattern anyway; acorn's own JS copy of
3926
+ * that validation costs several percent of parse time. Raise from V8's
3927
+ * verdict instead — invalid patterns still fail the module build, only
3928
+ * exotic engine-specific message texts may differ.
3929
+ * @param {{ start: number, source: string, flags: string }} state acorn regexp validation state
3930
+ * @this {ParserInternals}
3931
+ */
3932
+ validateRegExpPattern(state) {
3933
+ try {
3934
+ // eslint-disable-next-line no-new
3935
+ new RegExp(state.source, state.flags);
3936
+ } catch (err) {
3937
+ this.raiseRecoverable(state.start, /** @type {Error} */ (err).message);
3938
+ }
3939
+ }
3940
+
3941
+ // ----- scope tracking (Set-based, replaces acorn's array + indexOf) -----
3942
+
3943
+ /**
3944
+ * @param {number} flags scope flags
3945
+ * @this {ParserInternals}
3946
+ */
3947
+ enterScope(flags) {
3948
+ this.scopeStack.push(new Scope(flags));
3949
+ }
3950
+
3951
+ /**
3952
+ * Set-backed replacement for acorn's `declareName` on Set-backed scopes.
3953
+ * @param {string} name declared name
3954
+ * @param {number} bindingType acorn BIND_* binding type
3955
+ * @param {number} pos source offset for redeclaration errors
3956
+ * @this {ParserInternals}
3957
+ */
3958
+ declareName(name, bindingType, pos) {
3959
+ let redeclared = false;
3960
+ if (bindingType === BIND_LEXICAL) {
3961
+ const scope = this.currentScope();
3962
+ redeclared =
3963
+ (scope.lexical !== undefined && scope.lexical.has(name)) ||
3964
+ (scope.functions !== undefined && scope.functions.has(name)) ||
3965
+ (scope.var !== undefined && scope.var.has(name));
3966
+ if (scope.lexical === undefined) {
3967
+ scope.firstLexical = name;
3968
+ scope.lexical = new Set();
3969
+ }
3970
+ scope.lexical.add(name);
3971
+ if (this.inModule && scope.flags & SCOPE_TOP) {
3972
+ delete this.undefinedExports[name];
3973
+ }
3974
+ } else if (bindingType === /* BIND_SIMPLE_CATCH */ 4) {
3975
+ const scope = this.currentScope();
3976
+ if (scope.lexical === undefined) {
3977
+ scope.firstLexical = name;
3978
+ scope.lexical = new Set();
3979
+ }
3980
+ scope.lexical.add(name);
3981
+ } else if (bindingType === /* BIND_FUNCTION */ 3) {
3982
+ const scope = this.currentScope();
3983
+ redeclared = this.treatFunctionsAsVar
3984
+ ? scope.lexical !== undefined && scope.lexical.has(name)
3985
+ : (scope.lexical !== undefined && scope.lexical.has(name)) ||
3986
+ (scope.var !== undefined && scope.var.has(name));
3987
+ (scope.functions || (scope.functions = new Set())).add(name);
3988
+ } else {
3989
+ for (let i = this.scopeStack.length - 1; i >= 0; --i) {
3990
+ const scope = this.scopeStack[i];
3991
+ if (
3992
+ (scope.lexical !== undefined &&
3993
+ scope.lexical.has(name) &&
3994
+ !(
3995
+ scope.flags & SCOPE_SIMPLE_CATCH && scope.firstLexical === name
3996
+ )) ||
3997
+ // lazy-Set check first: `functions` is undefined for almost all
3998
+ // scopes, and the method call walks no state worth paying for then
3999
+ (scope.functions !== undefined &&
4000
+ !this.treatFunctionsAsVarInScope(scope) &&
4001
+ scope.functions.has(name))
4002
+ ) {
4003
+ redeclared = true;
4004
+ break;
4005
+ }
4006
+ (scope.var || (scope.var = new Set())).add(name);
4007
+ if (this.inModule && scope.flags & SCOPE_TOP) {
4008
+ delete this.undefinedExports[name];
4009
+ }
4010
+ if (scope.flags & SCOPE_VAR) break;
4011
+ }
4012
+ }
4013
+ if (redeclared) {
4014
+ this.raiseRecoverable(
4015
+ pos,
4016
+ `Identifier '${name}' has already been declared`
4017
+ );
4018
+ }
4019
+ }
4020
+
4021
+ /**
4022
+ * Set-backed replacement for acorn's `checkLocalExport` on Set-backed scopes.
4023
+ * @param {Identifier} id exported identifier
4024
+ * @this {ParserInternals}
4025
+ */
4026
+ checkLocalExport(id) {
4027
+ const topScope = this.scopeStack[0];
4028
+ if (
4029
+ !(topScope.lexical !== undefined && topScope.lexical.has(id.name)) &&
4030
+ !(topScope.var !== undefined && topScope.var.has(id.name))
4031
+ ) {
4032
+ this.undefinedExports[id.name] = id;
4033
+ }
4034
+ }
4035
+
4036
+ // ----- import attributes (`with { ... }` / legacy `assert { ... }`) -----
4037
+
4038
+ /**
4039
+ * @returns {ImportAttribute[]} import attributes
4040
+ * @this {ParserInternals}
4041
+ */
4042
+ parseWithClause() {
4043
+ /** @type {ImportAttribute[] & { [LEGACY_ASSERT_ATTRIBUTES]?: boolean }} */
4044
+ const nodes = [];
4045
+
4046
+ const isAssertLegacy = this.value === "assert";
4047
+
4048
+ if (isAssertLegacy) {
4049
+ if (!this.eat(tokTypes.name)) {
4050
+ return nodes;
4051
+ }
4052
+ } else if (!this.eat(tokTypes._with)) {
4053
+ return nodes;
4054
+ }
4055
+
4056
+ this.expect(tokTypes.braceL);
4057
+
4058
+ /** @type {Record<string, boolean>} */
4059
+ const attributeKeys = {};
4060
+ let first = true;
4061
+
4062
+ while (!this.eat(tokTypes.braceR)) {
4063
+ if (!first) {
4064
+ this.expect(tokTypes.comma);
4065
+ if (this.afterTrailingComma(tokTypes.braceR)) {
4066
+ break;
4067
+ }
4068
+ } else {
4069
+ first = false;
4070
+ }
4071
+
4072
+ const attr = this.parseImportAttribute();
4073
+ const keyName =
4074
+ /** @type {string} */
4075
+ (attr.key.type === "Identifier" ? attr.key.name : attr.key.value);
4076
+
4077
+ if (Object.prototype.hasOwnProperty.call(attributeKeys, keyName)) {
4078
+ this.raiseRecoverable(
4079
+ attr.key.start,
4080
+ `Duplicate attribute key '${keyName}'`
4081
+ );
4082
+ }
4083
+
4084
+ attributeKeys[keyName] = true;
4085
+ nodes.push(attr);
4086
+ }
4087
+
4088
+ if (isAssertLegacy) {
4089
+ nodes[LEGACY_ASSERT_ATTRIBUTES] = true;
4090
+ }
4091
+
4092
+ return nodes;
4093
+ }
4094
+
4095
+ // ----- import phases (`import defer/source`, `import.defer/source()`) -----
4096
+
4097
+ /**
4098
+ * @param {Node & { phase?: ImportPhase }} node import declaration node
4099
+ * @returns {Node} finished node
4100
+ * @this {ParserInternals}
4101
+ */
4102
+ parseImport(node) {
4103
+ this._moduleSyntaxSeen = true;
4104
+ this._importPhase = null;
4105
+ const result = base.parseImport.call(this, node);
4106
+ if (this._importPhase) node.phase = this._importPhase;
4107
+ return result;
4108
+ }
4109
+
4110
+ /**
4111
+ * Owned `parseExport` only to flag module syntax for the auto-fallback guard;
4112
+ * parsing itself delegates to acorn.
4113
+ * @param {Node} node started export node
4114
+ * @param {unknown} exports export-name tracking object
4115
+ * @returns {Node} export declaration
4116
+ * @this {ParserInternals}
4117
+ */
4118
+ parseExport(node, exports) {
4119
+ this._moduleSyntaxSeen = true;
4120
+ return base.parseExport.call(this, node, exports);
4121
+ }
4122
+
4123
+ /**
4124
+ * Owned `parseAwait` only to flag top-level await (module-only) for the
4125
+ * auto-fallback guard; await inside a function is not module syntax.
4126
+ * @param {boolean | string=} forInit for-loop init context flag
4127
+ * @returns {Expression} await expression
4128
+ * @this {ParserInternals}
4129
+ */
4130
+ parseAwait(forInit) {
4131
+ if (this.inModule && this.currentVarScope().flags & SCOPE_TOP) {
4132
+ this._moduleSyntaxSeen = true;
4133
+ }
4134
+ return base.parseAwait.call(this, forInit);
4135
+ }
4136
+
4137
+ /**
4138
+ * @returns {AnyImportSpecifier[]} import specifiers
4139
+ * @this {ParserInternals}
4140
+ */
4141
+ parseImportSpecifiers() {
4142
+ if (!this._importPhasesEnabled) {
4143
+ return base.parseImportSpecifiers.call(this);
4144
+ }
4145
+
4146
+ /** @type {ImportPhase | null} */
4147
+ const phase = this.isContextual("defer")
4148
+ ? "defer"
4149
+ : this.isContextual("source")
4150
+ ? "source"
4151
+ : null;
4152
+ if (!phase) return base.parseImportSpecifiers.call(this);
4153
+
4154
+ const phaseId = this.parseIdent();
4155
+ if (this.isContextual("from") || this.type === tokTypes.comma) {
4156
+ // `defer`/`source` was the default import name, not a phase modifier
4157
+ const defaultSpecifier =
4158
+ /** @type {ImportDefaultSpecifier} */
4159
+ (
4160
+ this.startNodeAt(
4161
+ phaseId.start,
4162
+ phaseId.loc ? phaseId.loc.start : undefined
4163
+ )
4164
+ );
4165
+ defaultSpecifier.local = phaseId;
4166
+ this.checkLValSimple(phaseId, BIND_LEXICAL);
4167
+
4168
+ /** @type {AnyImportSpecifier[]} */
4169
+ const nodes = [
4170
+ /** @type {ImportDefaultSpecifier} */
4171
+ (this.finishNode(defaultSpecifier, "ImportDefaultSpecifier"))
4172
+ ];
4173
+ if (this.eat(tokTypes.comma)) {
4174
+ if (this.type !== tokTypes.star && this.type !== tokTypes.braceL) {
4175
+ this.unexpected();
4176
+ }
4177
+ nodes.push(...base.parseImportSpecifiers.call(this));
4178
+ }
4179
+ return nodes;
4180
+ }
4181
+
4182
+ this._importPhase = phase;
4183
+
4184
+ if (phase === "defer") {
4185
+ if (this.type !== tokTypes.star) {
4186
+ this.raiseRecoverable(
4187
+ phaseId.start,
4188
+ "'import defer' can only be used with namespace imports ('import defer * as identifierName from ...')."
4189
+ );
4190
+ }
4191
+ } else if (this.type !== tokTypes.name) {
4192
+ this.raiseRecoverable(
4193
+ phaseId.start,
4194
+ "'import source' can only be used with direct identifier specifier imports."
4195
+ );
4196
+ }
4197
+
4198
+ const specifiers = base.parseImportSpecifiers.call(this);
4199
+
4200
+ if (
4201
+ phase === "source" &&
4202
+ specifiers.some((s) => s.type !== "ImportDefaultSpecifier")
4203
+ ) {
4204
+ this.raiseRecoverable(
4205
+ phaseId.start,
4206
+ "'import source' can only be used with direct identifier specifier imports ('import source identifierName from ...')."
4207
+ );
4208
+ }
4209
+
4210
+ return specifiers;
4211
+ }
4212
+
4213
+ /**
4214
+ * @param {boolean} forNew whether parsed as the operand of `new`
4215
+ * @returns {Expression} expression node
4216
+ * @this {ParserInternals}
4217
+ */
4218
+ parseExprImport(forNew) {
4219
+ const node = base.parseExprImport.call(this, forNew);
4220
+
4221
+ if (
4222
+ this._importPhasesEnabled &&
4223
+ node.type === "MetaProperty" &&
4224
+ (node.property.name === "defer" || node.property.name === "source")
4225
+ ) {
4226
+ if (this.type === tokTypes.parenL) {
4227
+ if (forNew) {
4228
+ // same guard acorn applies to `new import(...)`
4229
+ this.raise(node.start, "import call cannot be the target of `new`");
4230
+ }
4231
+ const dynImport =
4232
+ /** @type {ImportExpression & { phase?: ImportPhase }} */
4233
+ (
4234
+ this.parseDynamicImport(
4235
+ this.startNodeAt(
4236
+ node.start,
4237
+ node.loc ? node.loc.start : undefined
4238
+ )
4239
+ )
4240
+ );
4241
+ dynImport.phase = node.property.name;
4242
+ return dynImport;
4243
+ }
4244
+ this.raiseRecoverable(
4245
+ node.start,
4246
+ `'import.${node.property.name}' can only be used in a dynamic import.`
4247
+ );
4248
+ }
4249
+
4250
+ return node;
4251
+ }
4252
+
4253
+ /**
4254
+ * @param {Node & { property?: Identifier }} node started node with `meta` set to `import`
4255
+ * @returns {Expression} MetaProperty node
4256
+ * @this {ParserInternals}
4257
+ */
4258
+ parseImportMeta(node) {
4259
+ if (!this._importPhasesEnabled) {
4260
+ // base only accepts `import.meta` here, which is module-only
4261
+ this._moduleSyntaxSeen = true;
4262
+ return base.parseImportMeta.call(this, node);
4263
+ }
4264
+
4265
+ this.next();
4266
+
4267
+ const containsEsc = this.containsEsc;
4268
+ const property = this.parseIdent(true);
4269
+ node.property = property;
4270
+ const { name } = property;
4271
+
4272
+ // only `import.meta` is module-only; `import.defer`/`.source` are dynamic
4273
+ if (name === "meta") this._moduleSyntaxSeen = true;
4274
+
4275
+ if (name !== "meta" && name !== "defer" && name !== "source") {
4276
+ this.raiseRecoverable(
4277
+ property.start,
4278
+ "The only valid meta property for import is 'import.meta'"
4279
+ );
4280
+ }
4281
+ if (containsEsc) {
4282
+ this.raiseRecoverable(
4283
+ node.start,
4284
+ `'import.${name}' must not contain escaped characters`
4285
+ );
4286
+ }
4287
+ if (
4288
+ name === "meta" &&
4289
+ this.options.sourceType !== "module" &&
4290
+ !this.options.allowImportExportEverywhere
4291
+ ) {
4292
+ this.raiseRecoverable(
4293
+ node.start,
4294
+ "Cannot use 'import.meta' outside a module"
4295
+ );
4296
+ }
4297
+
4298
+ return /** @type {Expression} */ (this.finishNode(node, "MetaProperty"));
4299
+ }
4300
+ }
4301
+
4302
+ /** @typedef {import("../Dependency").SourcePosition} SourcePosition */
4303
+
4304
+ /**
4305
+ * Whether a raw string literal contains a legacy octal (`\47`, `\0` followed by
4306
+ * a digit) or non-octal decimal (`\8`, `\9`) escape — all SyntaxErrors in
4307
+ * strict mode. Escaped backslashes (`\\`) and `\x` / `\u` escapes are skipped.
4308
+ * @param {string} raw raw string literal text, including quotes
4309
+ * @returns {boolean} true when a strict-forbidden escape is present
4310
+ */
4311
+ const hasOctalEscape = (raw) => {
4312
+ for (let i = 0; i < raw.length; i++) {
4313
+ if (raw.charCodeAt(i) !== 92) continue;
4314
+ const next = raw.charCodeAt(i + 1);
4315
+ if (next === 92) {
4316
+ i++;
4317
+ continue;
4318
+ }
4319
+ // `\0` is a valid NUL escape unless a digit follows it.
4320
+ if (next === 48) {
4321
+ const after = raw.charCodeAt(i + 2);
4322
+ if (after >= 48 && after <= 57) return true;
4323
+ i++;
4324
+ continue;
4325
+ }
4326
+ if (next >= 49 && next <= 57) return true;
4327
+ }
4328
+ return false;
4329
+ };
4330
+
4331
+ // Location decoding for lazy-mode output: nodes carry only offsets (the parser
4332
+ // skips acorn's location tracking), so line/column are derived on demand from
4333
+ // these two helpers.
4334
+
4335
+ /**
4336
+ * Offset of each line's first character. Char-code scan matching acorn's
4337
+ * `lineBreak` semantics (CRLF is one break): a regex `exec` loop here
4338
+ * allocates a match array per line.
4339
+ * @param {string} source source code
4340
+ * @returns {number[]} line start offsets
4341
+ */
4342
+ const buildLineStarts = (source) => {
4343
+ const len = source.length;
4344
+ const lineStarts = [0];
4345
+ for (let i = 0; i < len; i++) {
4346
+ const ch = source.charCodeAt(i);
4347
+ if (ch === 10) {
4348
+ lineStarts.push(i + 1);
4349
+ } else if (ch === 13) {
4350
+ if (source.charCodeAt(i + 1) === 10) i++;
4351
+ lineStarts.push(i + 1);
4352
+ } else if (ch === 0x2028 || ch === 0x2029) {
4353
+ lineStarts.push(i + 1);
4354
+ }
4355
+ }
4356
+ return lineStarts;
4357
+ };
4358
+
4359
+ /**
4360
+ * Binary search for the line containing the offset.
4361
+ * @param {number[]} lineStarts line start offsets
4362
+ * @param {number} offset source offset
4363
+ * @returns {SourcePosition} position (1-based line, 0-based column)
4364
+ */
4365
+ const positionAt = (lineStarts, offset) => {
4366
+ let lo = 0;
4367
+ let hi = lineStarts.length - 1;
4368
+ while (lo < hi) {
4369
+ const mid = (lo + hi + 1) >>> 1;
4370
+ if (lineStarts[mid] <= offset) lo = mid;
4371
+ else hi = mid - 1;
4372
+ }
4373
+ return { line: lo + 1, column: offset - lineStarts[lo] };
4374
+ };
4375
+
4376
+ module.exports.LEGACY_ASSERT_ATTRIBUTES = LEGACY_ASSERT_ATTRIBUTES;
4377
+ module.exports.WebpackParser = WebpackParser;
4378
+ module.exports.buildLineStarts = buildLineStarts;
4379
+ module.exports.hasOctalEscape = hasOctalEscape;
4380
+ module.exports.positionAt = positionAt;