@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
@@ -5,20 +5,27 @@
5
5
 
6
6
  "use strict";
7
7
 
8
- const vm = require("vm");
9
- const { Parser: AcornParser, tokTypes } = require("acorn");
10
8
  const { HookMap, SyncBailHook } = require("tapable");
11
9
  const NormalModule = require("../NormalModule");
12
10
  const Parser = require("../Parser");
11
+ const WebpackError = require("../WebpackError");
13
12
  const StackedMap = require("../util/StackedMap");
14
- const binarySearchBounds = require("../util/binarySearchBounds");
15
13
  const {
14
+ CompilerHintNotationRegExp,
16
15
  createMagicCommentContext,
17
- webpackCommentRegExp
16
+ getCommentsInRange,
17
+ parseCommentOptionsInRange
18
18
  } = require("../util/magicComment");
19
- const memoize = require("../util/memoize");
20
19
  const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
21
-
20
+ const {
21
+ LEGACY_ASSERT_ATTRIBUTES,
22
+ WebpackParser,
23
+ buildLineStarts,
24
+ hasOctalEscape,
25
+ positionAt
26
+ } = require("./syntax");
27
+
28
+ /** @typedef {typeof import("acorn").Parser} AcornParser */
22
29
  /** @typedef {import("acorn").Options} AcornOptions */
23
30
  /** @typedef {import("acorn").ecmaVersion} EcmaVersion */
24
31
  /** @typedef {import("estree").AssignmentExpression} AssignmentExpression */
@@ -32,7 +39,9 @@ const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
32
39
  /** @typedef {import("estree").SwitchStatement} SwitchStatement */
33
40
  /** @typedef {import("estree").ClassExpression} ClassExpression */
34
41
  /** @typedef {import("estree").SourceLocation} SourceLocation */
35
- /** @typedef {import("estree").Comment & { start: number, end: number, loc: SourceLocation }} Comment */
42
+ /** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
43
+ /** @typedef {import("../Dependency").SourcePosition} SourcePosition */
44
+ /** @typedef {import("estree").Comment & { start: number, end: number, loc?: SourceLocation | null }} Comment */
36
45
  /** @typedef {import("estree").ConditionalExpression} ConditionalExpression */
37
46
  /** @typedef {import("estree").Declaration} Declaration */
38
47
  /** @typedef {import("estree").PrivateIdentifier} PrivateIdentifier */
@@ -94,6 +103,7 @@ const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
94
103
  /** @typedef {import("estree").MaybeNamedFunctionDeclaration} MaybeNamedFunctionDeclaration */
95
104
  /** @typedef {import("estree").MaybeNamedClassDeclaration} MaybeNamedClassDeclaration */
96
105
  /**
106
+ * Defines the shared type used by this module.
97
107
  * @template T
98
108
  * @typedef {import("tapable").AsArray<T>} AsArray<T>
99
109
  */
@@ -104,6 +114,7 @@ const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
104
114
  /** @typedef {import("../dependencies/HarmonyExportImportedSpecifierDependency").HarmonyStarExportsList} HarmonyStarExportsList */
105
115
 
106
116
  /**
117
+ * Defines the known javascript parser state type used by this module.
107
118
  * @typedef {object} KnownJavascriptParserState
108
119
  * @property {Set<string>=} harmonyNamedExports
109
120
  * @property {HarmonyStarExportsList=} harmonyStarExports
@@ -117,6 +128,7 @@ const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
117
128
  /** @typedef {import("../Module")} Module */
118
129
 
119
130
  /** @typedef {{ name: string | VariableInfo, rootInfo: string | VariableInfo, getMembers: () => Members, getMembersOptionals: () => MembersOptionals, getMemberRanges: () => MemberRanges }} GetInfoResult */
131
+ /** @typedef {{ consequent?: EXPECTED_OBJECT, alternate?: EXPECTED_OBJECT }} GuardCollection per-branch guard frames pushed onto the parser state guard stack */
120
132
  /** @typedef {Statement | ModuleDeclaration | Expression | MaybeNamedFunctionDeclaration | MaybeNamedClassDeclaration} StatementPathItem */
121
133
  /** @typedef {(ident: string) => void} OnIdentString */
122
134
  /** @typedef {(ident: string, identifier: Identifier) => void} OnIdent */
@@ -124,86 +136,52 @@ const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
124
136
 
125
137
  /** @typedef {Set<DestructuringAssignmentProperty>} DestructuringAssignmentProperties */
126
138
 
127
- // TODO remove cast when @types/estree has been updated to import assertions
139
+ // TODO remove cast when @types/estree has been updated to import phases
128
140
  /** @typedef {import("estree").ImportExpression & { phase?: "defer" | "source" }} ImportExpression */
129
141
 
130
142
  /** @type {string[]} */
131
143
  const EMPTY_ARRAY = [];
144
+
145
+ /**
146
+ * Getter that reverses `arr` in place on first access and caches it. Lighter
147
+ * than `memoize(() => arr.reverse())` (one closure instead of two) and called
148
+ * per member expression on hot parse paths.
149
+ * @template T
150
+ * @param {T[]} arr array reversed lazily on first access
151
+ * @returns {() => T[]} getter returning the reversed array
152
+ */
153
+ const lazyReverse = (arr) => {
154
+ let reversed = false;
155
+ return () => {
156
+ if (!reversed) {
157
+ arr.reverse();
158
+ reversed = true;
159
+ }
160
+ return arr;
161
+ };
162
+ };
163
+
132
164
  const ALLOWED_MEMBER_TYPES_CALL_EXPRESSION = 0b01;
133
165
  const ALLOWED_MEMBER_TYPES_EXPRESSION = 0b10;
134
166
  const ALLOWED_MEMBER_TYPES_ALL = 0b11;
135
167
 
136
- const LEGACY_ASSERT_ATTRIBUTES = Symbol("assert");
137
-
138
- /** @type {(BaseParser: typeof AcornParser) => typeof AcornParser} */
139
- const importAssertions = (Parser) =>
140
- class extends Parser {
141
- /**
142
- * @this {InstanceType<AcornParser>}
143
- * @returns {ImportAttribute[]} import attributes
144
- */
145
- parseWithClause() {
146
- /** @type {ImportAttribute[]} */
147
- const nodes = [];
148
-
149
- const isAssertLegacy = this.value === "assert";
150
-
151
- if (isAssertLegacy) {
152
- if (!this.eat(tokTypes.name)) {
153
- return nodes;
154
- }
155
- } else if (!this.eat(tokTypes._with)) {
156
- return nodes;
157
- }
158
-
159
- this.expect(tokTypes.braceL);
160
-
161
- /** @type {Record<string, boolean>} */
162
- const attributeKeys = {};
163
- let first = true;
164
-
165
- while (!this.eat(tokTypes.braceR)) {
166
- if (!first) {
167
- this.expect(tokTypes.comma);
168
- if (this.afterTrailingComma(tokTypes.braceR)) {
169
- break;
170
- }
171
- } else {
172
- first = false;
173
- }
174
-
175
- const attr =
176
- /** @type {ImportAttribute} */
177
- this.parseImportAttribute();
178
- const keyName =
179
- attr.key.type === "Identifier" ? attr.key.name : attr.key.value;
180
-
181
- if (Object.prototype.hasOwnProperty.call(attributeKeys, keyName)) {
182
- this.raiseRecoverable(
183
- attr.key.start,
184
- `Duplicate attribute key '${keyName}'`
185
- );
186
- }
187
-
188
- attributeKeys[keyName] = true;
189
- nodes.push(attr);
190
- }
191
-
192
- if (isAssertLegacy) {
193
- /** @type {EXPECTED_ANY} */
194
- (nodes)[LEGACY_ASSERT_ATTRIBUTES] = true;
195
- }
168
+ // Shared `() => false` so the members-optionals fallback in walkCallExpression
169
+ // doesn't allocate a fresh closure per identifier-rooted call.
170
+ const RETURN_FALSE = () => false;
196
171
 
197
- return nodes;
198
- }
199
- };
172
+ // Shared `() => []` for the member-less identifier/this evaluation results,
173
+ // replacing three fresh closures per evaluated free variable.
174
+ const RETURN_EMPTY_ARRAY = () => [];
200
175
 
201
176
  // Syntax: https://developer.mozilla.org/en/SpiderMonkey/Parser_API
202
- let parser = AcornParser.extend(importAssertions);
177
+ let parser = /** @type {AcornParser} */ (WebpackParser);
203
178
 
204
179
  /** @typedef {Record<string, string> & { _isLegacyAssert?: boolean }} ImportAttributes */
205
180
 
181
+ // Conceptually pairs with ./syntax's LEGACY_ASSERT_ATTRIBUTES marker, but is
182
+ // pinned here by its public `JavascriptParser.getImportAttributes` typing.
206
183
  /**
184
+ * Gets import attributes.
207
185
  * @param {ImportDeclaration | ExportNamedDeclaration | ExportAllDeclaration | ImportExpression} node node with assertions
208
186
  * @returns {ImportAttributes | undefined} import attributes
209
187
  */
@@ -287,19 +265,25 @@ const VariableInfoFlags = Object.freeze({
287
265
 
288
266
  class VariableInfo {
289
267
  /**
268
+ * Creates an instance of VariableInfo.
290
269
  * @param {ScopeInfo} declaredScope scope in which the variable is declared
291
270
  * @param {string | undefined} name which name the variable use, defined name or free name or tagged name
292
271
  * @param {VariableInfoFlagsType} flags how the variable is created
293
272
  * @param {TagInfo | undefined} tagInfo info about tags
294
273
  */
295
274
  constructor(declaredScope, name, flags, tagInfo) {
275
+ /** @type {ScopeInfo} */
296
276
  this.declaredScope = declaredScope;
277
+ /** @type {string | undefined} */
297
278
  this.name = name;
279
+ /** @type {VariableInfoFlagsType} */
298
280
  this.flags = flags;
281
+ /** @type {TagInfo | undefined} */
299
282
  this.tagInfo = tagInfo;
300
283
  }
301
284
 
302
285
  /**
286
+ * Checks whether this variable info is free.
303
287
  * @returns {boolean} the variable is free or not
304
288
  */
305
289
  isFree() {
@@ -307,6 +291,7 @@ class VariableInfo {
307
291
  }
308
292
 
309
293
  /**
294
+ * Checks whether this variable info is tagged.
310
295
  * @returns {boolean} the variable is tagged by tagVariable or not
311
296
  */
312
297
  isTagged() {
@@ -318,45 +303,51 @@ class VariableInfo {
318
303
  /** @typedef {Literal | string | null | undefined} ImportSource */
319
304
 
320
305
  /**
306
+ * Defines the internal parse options type used by this module.
321
307
  * @typedef {Omit<ParseOptions, "sourceType" | "ecmaVersion"> & { sourceType: "module" | "script" | "auto" }} InternalParseOptions
322
308
  */
323
309
 
324
310
  /**
311
+ * Defines the parse options type used by this module.
325
312
  * @typedef {object} ParseOptions
326
313
  * @property {"module" | "script"} sourceType
327
314
  * @property {EcmaVersion} ecmaVersion
328
315
  * @property {boolean=} locations
329
316
  * @property {boolean=} comments
330
317
  * @property {boolean=} ranges
331
- * @property {boolean=} semicolons
332
318
  * @property {boolean=} allowHashBang
333
319
  * @property {boolean=} allowReturnOutsideFunction
320
+ * @property {boolean=} lazyNodes internal: serve `range` lazily and skip acorn's location/range tracking
321
+ * @property {Comment[]=} lazyComments internal: collect comments here without slicing their text eagerly
322
+ * @property {boolean=} importPhases enable parsing of the import phase proposals (import defer / import source)
323
+ * @property {boolean=} moduleFallback internal: for `auto`, let the parser downgrade module->script in place instead of re-parsing
334
324
  */
335
325
 
336
326
  /**
327
+ * Defines the parse result type used by this module.
337
328
  * @typedef {object} ParseResult
338
329
  * @property {Program} ast
339
330
  * @property {Comment[]} comments
340
- * @property {Set<number>} semicolons
341
331
  */
342
332
 
343
333
  /**
334
+ * Defines the parse function type used by this module.
344
335
  * @typedef {(code: string, options: ParseOptions) => ParseResult} ParseFunction
345
336
  */
346
337
 
347
338
  /** @typedef {symbol} Tag */
348
339
 
349
340
  /** @typedef {import("../dependencies/HarmonyImportDependencyParserPlugin").HarmonySettings} HarmonySettings */
350
- /** @typedef {import("../dependencies/HarmonyImportDependencyParserPlugin").HarmonySpecifierGuards} HarmonySpecifierGuards */
351
341
  /** @typedef {import("../dependencies/ImportParserPlugin").ImportSettings} ImportSettings */
352
342
  /** @typedef {import("../dependencies/CommonJsImportsParserPlugin").CommonJsImportSettings} CommonJsImportSettings */
353
343
  /** @typedef {import("../CompatibilityPlugin").CompatibilitySettings} CompatibilitySettings */
354
344
  /** @typedef {import("../optimize/InnerGraph").TopLevelSymbol} TopLevelSymbol */
355
345
 
356
- /** @typedef {HarmonySettings | ImportSettings | CommonJsImportSettings | TopLevelSymbol | CompatibilitySettings | HarmonySpecifierGuards} KnownTagData */
346
+ /** @typedef {HarmonySettings | ImportSettings | CommonJsImportSettings | TopLevelSymbol | CompatibilitySettings} KnownTagData */
357
347
  /** @typedef {KnownTagData | Record<string, EXPECTED_ANY>} TagData */
358
348
 
359
349
  /**
350
+ * Defines the tag info type used by this module.
360
351
  * @typedef {object} TagInfo
361
352
  * @property {Tag} tag
362
353
  * @property {TagData=} data
@@ -372,6 +363,7 @@ const SCOPE_INFO_TERMINATED_RETURN = 1;
372
363
  const SCOPE_INFO_TERMINATED_THROW = 2;
373
364
 
374
365
  /**
366
+ * Defines the scope info type used by this module.
375
367
  * @typedef {object} ScopeInfo
376
368
  * @property {StackedMap<string, VariableInfo | ScopeInfo>} definitions
377
369
  * @property {boolean | "arrow"} topLevelScope
@@ -386,10 +378,11 @@ const SCOPE_INFO_TERMINATED_THROW = 2;
386
378
  /** @typedef {[number, number]} Range */
387
379
 
388
380
  /**
381
+ * Defines the destructuring assignment property type used by this module.
382
+ * Carries only the range — consumers derive line/column via `getLocation`.
389
383
  * @typedef {object} DestructuringAssignmentProperty
390
384
  * @property {string} id
391
385
  * @property {Range} range
392
- * @property {SourceLocation} loc
393
386
  * @property {Set<DestructuringAssignmentProperty> | undefined=} pattern
394
387
  * @property {boolean | string} shorthand
395
388
  */
@@ -459,6 +452,25 @@ const getRootName = (expression) => {
459
452
  }
460
453
  };
461
454
 
455
+ /**
456
+ * @param {string} type AST node type
457
+ * @returns {boolean} true for FunctionExpression or ArrowFunctionExpression
458
+ */
459
+ const isFunctionExpression = (type) =>
460
+ type === "FunctionExpression" || type === "ArrowFunctionExpression";
461
+
462
+ /**
463
+ * @param {FunctionExpression | ArrowFunctionExpression} fn function
464
+ * @returns {boolean} true when all params are plain identifiers
465
+ */
466
+ const isSimpleFunction = (fn) => {
467
+ const params = fn.params;
468
+ for (let i = 0; i < params.length; i++) {
469
+ if (params[i].type !== "Identifier") return false;
470
+ }
471
+ return true;
472
+ };
473
+
462
474
  /** @type {ParseOptions} */
463
475
  const defaultParserOptions = {
464
476
  sourceType: "module",
@@ -470,17 +482,24 @@ const defaultParserOptions = {
470
482
  allowHashBang: true
471
483
  };
472
484
 
473
- const EMPTY_COMMENT_OPTIONS = {
474
- options: null,
475
- errors: null
476
- };
485
+ // reused by _parse for every non-custom parse — all fields are reset per parse
486
+ /** @type {ParseOptions} */
487
+ const REUSED_PARSER_OPTIONS = { ...defaultParserOptions };
488
+
489
+ // Read-only snippet ASTs for `evaluate()`, released with the compilation;
490
+ // DefinePlugin evaluates the same strings once per usage per module.
491
+ /** @type {WeakMap<Compilation, Map<string, Program>>} */
492
+ const evaluateAstCaches = new WeakMap();
493
+ // The inner map is strong while the compilation lives, so cap it
494
+ const EVALUATE_AST_CACHE_LIMIT = 4096;
477
495
 
478
496
  const CLASS_NAME = "JavascriptParser";
479
497
 
480
498
  class JavascriptParser extends Parser {
481
499
  /**
500
+ * Creates an instance of JavascriptParser.
482
501
  * @param {"module" | "script" | "auto"=} sourceType default source type
483
- * @param {{ parse?: ParseFunction }=} options parser options
502
+ * @param {{ parse?: ParseFunction, typescript?: boolean, importPhases?: boolean, strictModeViolations?: "error" | "warn" | false }=} options parser options
484
503
  */
485
504
  constructor(sourceType = "auto", options = {}) {
486
505
  super();
@@ -513,14 +532,20 @@ class JavascriptParser extends Parser {
513
532
  ),
514
533
  /** @type {SyncBailHook<[Statement | ModuleDeclaration | MaybeNamedClassDeclaration | MaybeNamedFunctionDeclaration], boolean | void>} */
515
534
  preStatement: new SyncBailHook(["statement"]),
535
+ /** @type {HookMap<SyncBailHook<[Statement | ModuleDeclaration | MaybeNamedClassDeclaration | MaybeNamedFunctionDeclaration], boolean | void>>} */
536
+ preStatementByType: new HookMap(() => new SyncBailHook(["statement"])),
516
537
 
517
538
  /** @type {SyncBailHook<[Statement | ModuleDeclaration | MaybeNamedClassDeclaration | MaybeNamedFunctionDeclaration], boolean | void>} */
518
539
  blockPreStatement: new SyncBailHook(["declaration"]),
540
+ /** @type {HookMap<SyncBailHook<[Statement | ModuleDeclaration | MaybeNamedClassDeclaration | MaybeNamedFunctionDeclaration], boolean | void>>} */
541
+ blockPreStatementByType: new HookMap(
542
+ () => new SyncBailHook(["declaration"])
543
+ ),
519
544
  /** @type {SyncBailHook<[Statement | ModuleDeclaration | MaybeNamedFunctionDeclaration | MaybeNamedClassDeclaration], boolean | void>} */
520
545
  statement: new SyncBailHook(["statement"]),
521
546
  /** @type {SyncBailHook<[IfStatement], boolean | void>} */
522
547
  statementIf: new SyncBailHook(["statement"]),
523
- /** @type {SyncBailHook<[Expression], ((walk: () => void) => void) | void>} */
548
+ /** @type {SyncBailHook<[Expression], GuardCollection | void>} */
524
549
  collectGuards: new SyncBailHook(["expression"]),
525
550
  /** @type {SyncBailHook<[Expression, ClassExpression | ClassDeclaration | MaybeNamedClassDeclaration], boolean | void>} */
526
551
  classExtendsExpression: new SyncBailHook([
@@ -569,7 +594,7 @@ class JavascriptParser extends Parser {
569
594
  "exportName",
570
595
  "index"
571
596
  ]),
572
- /** @type {SyncBailHook<[VariableDeclarator, Statement], boolean | void>} */
597
+ /** @type {SyncBailHook<[VariableDeclarator, VariableDeclaration], boolean | void>} */
573
598
  preDeclarator: new SyncBailHook(["declarator", "statement"]),
574
599
  /** @type {SyncBailHook<[VariableDeclarator, Statement], boolean | void>} */
575
600
  declarator: new SyncBailHook(["declarator", "statement"]),
@@ -686,7 +711,10 @@ class JavascriptParser extends Parser {
686
711
  this.state = /** @type {EXPECTED_ANY} */ (undefined);
687
712
  /** @type {Comment[] | undefined} */
688
713
  this.comments = undefined;
689
- /** @type {Set<number> | undefined} */
714
+ // ASI overrides keyed by statement-end offset: true forces an ASI
715
+ // position, false forces a real semicolon. Absent offsets are derived
716
+ // from the source text. Allocated lazily by set/unsetAsiPosition.
717
+ /** @type {Map<number, boolean> | undefined} */
690
718
  this.semicolons = undefined;
691
719
  /** @type {StatementPath | undefined} */
692
720
  this.statementPath = undefined;
@@ -696,8 +724,39 @@ class JavascriptParser extends Parser {
696
724
  this.destructuringAssignmentProperties = undefined;
697
725
  /** @type {TagData | undefined} */
698
726
  this.currentTagData = undefined;
727
+ // True while parsing a loose module whose code is emitted as strict ESM.
728
+ this._strictInModuleOutput = false;
729
+ // Source text of the current parse, for offset → line/column mapping.
730
+ /** @type {string | undefined} */
731
+ this._source = undefined;
732
+ // Offset of each line's first character, built on first getLocation use.
733
+ /** @type {number[] | undefined} */
734
+ this._lineStarts = undefined;
735
+ // True while only the parser's own taps sit on evaluate.for("Identifier");
736
+ // recomputed per parse, gates the defined-identifier fast paths.
737
+ this._evalIdentOwnTaps = false;
699
738
  this.magicCommentContext = createMagicCommentContext();
739
+ // Reused for enterPatterns on every scope entry to avoid per-scope closures.
740
+ /** @type {OnIdentString} */
741
+ this._defineVariable = (ident) => this.defineVariable(ident);
700
742
  this._initializeEvaluating();
743
+ // keyed taps are free for every other member chain, and a shadowed
744
+ // `arguments` binding never dispatches the free-variable hooks
745
+ this.hooks.expressionMemberChain
746
+ .for("arguments")
747
+ .tap(CLASS_NAME, (expression, members) => {
748
+ if (this._strictInModuleOutput) {
749
+ this._checkStrictModeArgumentsMember(members[0], expression);
750
+ }
751
+ });
752
+ this.hooks.callMemberChain
753
+ .for("arguments")
754
+ .tap(CLASS_NAME, (expression, members) => {
755
+ // longer chains re-enter the member walk, which reports them
756
+ if (this._strictInModuleOutput && members.length === 1) {
757
+ this._checkStrictModeArgumentsMember(members[0], expression);
758
+ }
759
+ });
701
760
  }
702
761
 
703
762
  _initializeEvaluating() {
@@ -956,6 +1015,7 @@ class JavascriptParser extends Parser {
956
1015
  (a === true && b === false) || (a === false && b === true);
957
1016
 
958
1017
  /**
1018
+ * Handle template string compare.
959
1019
  * @param {BasicEvaluatedExpression} left left
960
1020
  * @param {BasicEvaluatedExpression} right right
961
1021
  * @param {BasicEvaluatedExpression} res res
@@ -964,6 +1024,7 @@ class JavascriptParser extends Parser {
964
1024
  */
965
1025
  const handleTemplateStringCompare = (left, right, res, eql) => {
966
1026
  /**
1027
+ * Returns value.
967
1028
  * @param {BasicEvaluatedExpression[]} parts parts
968
1029
  * @returns {string} value
969
1030
  */
@@ -977,6 +1038,7 @@ class JavascriptParser extends Parser {
977
1038
  return value;
978
1039
  };
979
1040
  /**
1041
+ * Returns value.
980
1042
  * @param {BasicEvaluatedExpression[]} parts parts
981
1043
  * @returns {string} value
982
1044
  */
@@ -1319,6 +1381,16 @@ class JavascriptParser extends Parser {
1319
1381
  return handleConstOperation((l, r) => l <= r);
1320
1382
  } else if (expr.operator === ">=") {
1321
1383
  return handleConstOperation((l, r) => l >= r);
1384
+ } else if (expr.operator === "in") {
1385
+ // `x in y` always evaluates to a boolean, so it is never nullish
1386
+ const left = this.evaluateExpression(expr.left);
1387
+ const right = this.evaluateExpression(expr.right);
1388
+ return new BasicEvaluatedExpression()
1389
+ .setNullish(false)
1390
+ .setSideEffects(
1391
+ left.couldHaveSideEffects() || right.couldHaveSideEffects()
1392
+ )
1393
+ .setRange(/** @type {Range} */ (expr.range));
1322
1394
  }
1323
1395
  });
1324
1396
  this.hooks.evaluate.for("UnaryExpression").tap(CLASS_NAME, (_expr) => {
@@ -1460,6 +1532,7 @@ class JavascriptParser extends Parser {
1460
1532
  }
1461
1533
  });
1462
1534
  /**
1535
+ * Tap evaluate with variable info.
1463
1536
  * @param {"Identifier" | "ThisExpression" | "MemberExpression"} exprType expression type name
1464
1537
  * @param {(node: Expression | SpreadElement) => GetInfoResult | undefined} getInfo get info
1465
1538
  * @returns {void}
@@ -1474,15 +1547,16 @@ class JavascriptParser extends Parser {
1474
1547
  /** @type {Identifier | ThisExpression | MemberExpression} */ (expr);
1475
1548
 
1476
1549
  const info = getInfo(expression);
1550
+ // Cache the result (even when undefined) so the stage-100 tap below
1551
+ // reuses it instead of recomputing getInfo — getMemberExpressionInfo
1552
+ // is expensive and previously ran twice for every rejected member.
1553
+ cachedExpression = expression;
1554
+ cachedInfo = info;
1477
1555
  if (info !== undefined) {
1478
1556
  return this.callHooksForInfoWithFallback(
1479
1557
  this.hooks.evaluateIdentifier,
1480
1558
  info.name,
1481
- (_name) => {
1482
- cachedExpression = expression;
1483
- cachedInfo = info;
1484
- return undefined;
1485
- },
1559
+ (_name) => undefined,
1486
1560
  (name) => {
1487
1561
  const hook = this.hooks.evaluateDefinedIdentifier.get(name);
1488
1562
  if (hook !== undefined) {
@@ -1522,14 +1596,18 @@ class JavascriptParser extends Parser {
1522
1596
  const info = this.getVariableInfo(/** @type {Identifier} */ (expr).name);
1523
1597
  if (
1524
1598
  typeof info === "string" ||
1525
- (info instanceof VariableInfo && (info.isFree() || info.isTagged()))
1599
+ (info instanceof VariableInfo &&
1600
+ (info.isFree() ||
1601
+ info.isTagged() ||
1602
+ // Walk `tagInfo` in `callHooksForInfo` if tagInfo is present.
1603
+ info.tagInfo !== undefined))
1526
1604
  ) {
1527
1605
  return {
1528
1606
  name: info,
1529
1607
  rootInfo: info,
1530
- getMembers: () => [],
1531
- getMembersOptionals: () => [],
1532
- getMemberRanges: () => []
1608
+ getMembers: RETURN_EMPTY_ARRAY,
1609
+ getMembersOptionals: RETURN_EMPTY_ARRAY,
1610
+ getMemberRanges: RETURN_EMPTY_ARRAY
1533
1611
  };
1534
1612
  }
1535
1613
  });
@@ -1542,9 +1620,9 @@ class JavascriptParser extends Parser {
1542
1620
  return {
1543
1621
  name: info,
1544
1622
  rootInfo: info,
1545
- getMembers: () => [],
1546
- getMembersOptionals: () => [],
1547
- getMemberRanges: () => []
1623
+ getMembers: RETURN_EMPTY_ARRAY,
1624
+ getMembersOptionals: RETURN_EMPTY_ARRAY,
1625
+ getMemberRanges: RETURN_EMPTY_ARRAY
1548
1626
  };
1549
1627
  }
1550
1628
  });
@@ -1565,8 +1643,8 @@ class JavascriptParser extends Parser {
1565
1643
  )
1566
1644
  );
1567
1645
 
1568
- this.hooks.evaluate.for("CallExpression").tap(CLASS_NAME, (_expr) => {
1569
- const expr = /** @type {CallExpression} */ (_expr);
1646
+ this.hooks.evaluate.for("CallExpression").tap(CLASS_NAME, (expression) => {
1647
+ const expr = /** @type {CallExpression} */ (expression);
1570
1648
  if (
1571
1649
  expr.callee.type === "MemberExpression" &&
1572
1650
  expr.callee.property.type ===
@@ -1687,6 +1765,7 @@ class JavascriptParser extends Parser {
1687
1765
  }
1688
1766
 
1689
1767
  /**
1768
+ * Gets simplified template result.
1690
1769
  * @param {"cooked" | "raw"} kind kind of values to get
1691
1770
  * @param {TemplateLiteral} templateLiteralExpr TemplateLiteral expr
1692
1771
  * @returns {{ quasis: BasicEvaluatedExpression[], parts: BasicEvaluatedExpression[] }} Simplified template
@@ -1959,9 +2038,25 @@ class JavascriptParser extends Parser {
1959
2038
  }
1960
2039
  return this.evaluateExpression(expr.expression);
1961
2040
  });
2041
+ this.hooks.evaluate.for("SequenceExpression").tap(CLASS_NAME, (_expr) => {
2042
+ const expr = /** @type {SequenceExpression} */ (_expr);
2043
+ if (!expr.range) return;
2044
+ let commentsStartPos = /** @type {Range} */ (expr.range)[0];
2045
+ for (let i = 0; i < expr.expressions.length - 1; i++) {
2046
+ const item = expr.expressions[i];
2047
+ if (!item.range) return;
2048
+ if (!this.isPure(item, commentsStartPos)) return;
2049
+ commentsStartPos = /** @type {Range} */ (item.range)[1];
2050
+ }
2051
+ const last = expr.expressions[expr.expressions.length - 1];
2052
+ const evaluated = this.evaluateExpression(last);
2053
+ if (!evaluated.isCompileTimeValue()) return;
2054
+ return evaluated.setRange(/** @type {Range} */ (expr.range));
2055
+ });
1962
2056
  }
1963
2057
 
1964
2058
  /**
2059
+ * Destructuring assignment properties for.
1965
2060
  * @param {Expression} node node
1966
2061
  * @returns {DestructuringAssignmentProperties | undefined} destructured identifiers
1967
2062
  */
@@ -1971,10 +2066,20 @@ class JavascriptParser extends Parser {
1971
2066
  }
1972
2067
 
1973
2068
  /**
2069
+ * Gets rename identifier.
1974
2070
  * @param {Expression | SpreadElement} expr expression
1975
2071
  * @returns {string | VariableInfo | undefined} identifier
1976
2072
  */
1977
2073
  getRenameIdentifier(expr) {
2074
+ if (
2075
+ expr.type === "Identifier" &&
2076
+ this._evalIdentOwnTaps &&
2077
+ expr.name !== "undefined" &&
2078
+ this._isDefinedPlainVariable(expr.name)
2079
+ ) {
2080
+ // the evaluation could only fall through — never an identifier result
2081
+ return;
2082
+ }
1978
2083
  const result = this.evaluateExpression(expr);
1979
2084
  if (result.isIdentifier()) {
1980
2085
  return result.identifier;
@@ -1982,6 +2087,7 @@ class JavascriptParser extends Parser {
1982
2087
  }
1983
2088
 
1984
2089
  /**
2090
+ * Processes the provided classy.
1985
2091
  * @param {ClassExpression | ClassDeclaration | MaybeNamedClassDeclaration} classy a class node
1986
2092
  * @returns {void}
1987
2093
  */
@@ -2113,49 +2219,60 @@ class JavascriptParser extends Parser {
2113
2219
  preWalkStatement(statement) {
2114
2220
  /** @type {StatementPath} */
2115
2221
  (this.statementPath).push(statement);
2116
- if (this.hooks.preStatement.call(statement)) {
2222
+ const { preStatement, preStatementByType } = this.hooks;
2223
+ // skip the broadcast entirely when nothing taps it; type-keyed taps
2224
+ // only run for their statement type
2225
+ let bail =
2226
+ preStatement.taps.length !== 0 ? preStatement.call(statement) : undefined;
2227
+ if (!bail) {
2228
+ const typed = preStatementByType.get(statement.type);
2229
+ if (typed !== undefined) bail = typed.call(statement);
2230
+ }
2231
+ if (bail) {
2117
2232
  this.prevStatement =
2118
2233
  /** @type {StatementPath} */
2119
2234
  (this.statementPath).pop();
2120
2235
  return;
2121
2236
  }
2237
+ // cases ordered by measured statement frequency; the commonest statements
2238
+ // (expressions, returns) intentionally match nothing here
2122
2239
  switch (statement.type) {
2123
- case "BlockStatement":
2124
- this.preWalkBlockStatement(statement);
2125
- break;
2126
- case "DoWhileStatement":
2127
- this.preWalkDoWhileStatement(statement);
2128
- break;
2129
- case "ForInStatement":
2130
- this.preWalkForInStatement(statement);
2240
+ case "VariableDeclaration":
2241
+ this.preWalkVariableDeclaration(statement);
2131
2242
  break;
2132
- case "ForOfStatement":
2133
- this.preWalkForOfStatement(statement);
2243
+ case "IfStatement":
2244
+ this.preWalkIfStatement(statement);
2134
2245
  break;
2135
- case "ForStatement":
2136
- this.preWalkForStatement(statement);
2246
+ case "BlockStatement":
2247
+ this.preWalkBlockStatement(statement);
2137
2248
  break;
2138
2249
  case "FunctionDeclaration":
2139
2250
  this.preWalkFunctionDeclaration(statement);
2140
2251
  break;
2141
- case "IfStatement":
2142
- this.preWalkIfStatement(statement);
2143
- break;
2144
- case "LabeledStatement":
2145
- this.preWalkLabeledStatement(statement);
2146
- break;
2147
- case "SwitchStatement":
2148
- this.preWalkSwitchStatement(statement);
2252
+ case "ForStatement":
2253
+ this.preWalkForStatement(statement);
2149
2254
  break;
2150
2255
  case "TryStatement":
2151
2256
  this.preWalkTryStatement(statement);
2152
2257
  break;
2153
- case "VariableDeclaration":
2154
- this.preWalkVariableDeclaration(statement);
2258
+ case "SwitchStatement":
2259
+ this.preWalkSwitchStatement(statement);
2155
2260
  break;
2156
2261
  case "WhileStatement":
2157
2262
  this.preWalkWhileStatement(statement);
2158
2263
  break;
2264
+ case "ForInStatement":
2265
+ this.preWalkForInStatement(statement);
2266
+ break;
2267
+ case "ForOfStatement":
2268
+ this.preWalkForOfStatement(statement);
2269
+ break;
2270
+ case "DoWhileStatement":
2271
+ this.preWalkDoWhileStatement(statement);
2272
+ break;
2273
+ case "LabeledStatement":
2274
+ this.preWalkLabeledStatement(statement);
2275
+ break;
2159
2276
  case "WithStatement":
2160
2277
  this.preWalkWithStatement(statement);
2161
2278
  break;
@@ -2166,32 +2283,43 @@ class JavascriptParser extends Parser {
2166
2283
  }
2167
2284
 
2168
2285
  /**
2286
+ * Block pre walk statement.
2169
2287
  * @param {Statement | ModuleDeclaration | MaybeNamedClassDeclaration | MaybeNamedFunctionDeclaration} statement statement
2170
2288
  */
2171
2289
  blockPreWalkStatement(statement) {
2172
2290
  /** @type {StatementPath} */
2173
2291
  (this.statementPath).push(statement);
2174
- if (this.hooks.blockPreStatement.call(statement)) {
2292
+ const { blockPreStatement, blockPreStatementByType } = this.hooks;
2293
+ let bail =
2294
+ blockPreStatement.taps.length !== 0
2295
+ ? blockPreStatement.call(statement)
2296
+ : undefined;
2297
+ if (!bail) {
2298
+ const typed = blockPreStatementByType.get(statement.type);
2299
+ if (typed !== undefined) bail = typed.call(statement);
2300
+ }
2301
+ if (bail) {
2175
2302
  this.prevStatement =
2176
2303
  /** @type {StatementPath} */
2177
2304
  (this.statementPath).pop();
2178
2305
  return;
2179
2306
  }
2307
+ // cases ordered by measured statement frequency
2180
2308
  switch (statement.type) {
2181
- case "ExportDefaultDeclaration":
2182
- this.blockPreWalkExportDefaultDeclaration(statement);
2183
- break;
2184
- case "ExportNamedDeclaration":
2185
- this.blockPreWalkExportNamedDeclaration(statement);
2186
- break;
2187
2309
  case "VariableDeclaration":
2188
2310
  this.blockPreWalkVariableDeclaration(statement);
2189
2311
  break;
2312
+ case "ExpressionStatement":
2313
+ this.blockPreWalkExpressionStatement(statement);
2314
+ break;
2190
2315
  case "ClassDeclaration":
2191
2316
  this.blockPreWalkClassDeclaration(statement);
2192
2317
  break;
2193
- case "ExpressionStatement":
2194
- this.blockPreWalkExpressionStatement(statement);
2318
+ case "ExportNamedDeclaration":
2319
+ this.blockPreWalkExportNamedDeclaration(statement);
2320
+ break;
2321
+ case "ExportDefaultDeclaration":
2322
+ this.blockPreWalkExportDefaultDeclaration(statement);
2195
2323
  }
2196
2324
  this.prevStatement =
2197
2325
  /** @type {StatementPath} */
@@ -2199,56 +2327,48 @@ class JavascriptParser extends Parser {
2199
2327
  }
2200
2328
 
2201
2329
  /**
2330
+ * Processes the provided statement.
2202
2331
  * @param {Statement | ModuleDeclaration | MaybeNamedFunctionDeclaration | MaybeNamedClassDeclaration} statement statement
2203
2332
  */
2204
2333
  walkStatement(statement) {
2205
2334
  /** @type {StatementPath} */
2206
2335
  (this.statementPath).push(statement);
2207
- if (this.hooks.statement.call(statement) !== undefined) {
2336
+ const { statement: statementHook } = this.hooks;
2337
+ if (
2338
+ statementHook.taps.length !== 0 &&
2339
+ statementHook.call(statement) !== undefined
2340
+ ) {
2208
2341
  this.prevStatement =
2209
2342
  /** @type {StatementPath} */
2210
2343
  (this.statementPath).pop();
2211
2344
  return;
2212
2345
  }
2346
+ // cases ordered by measured statement frequency; V8 compiles this to
2347
+ // sequential compares, so hot types must come first
2213
2348
  switch (statement.type) {
2214
- case "BlockStatement":
2215
- this.walkBlockStatement(statement);
2216
- break;
2217
- case "ClassDeclaration":
2218
- this.walkClassDeclaration(statement);
2219
- break;
2220
- case "DoWhileStatement":
2221
- this.walkDoWhileStatement(statement);
2222
- break;
2223
- case "ExportDefaultDeclaration":
2224
- this.walkExportDefaultDeclaration(statement);
2225
- break;
2226
- case "ExportNamedDeclaration":
2227
- this.walkExportNamedDeclaration(statement);
2228
- break;
2229
2349
  case "ExpressionStatement":
2230
2350
  this.walkExpressionStatement(statement);
2231
2351
  break;
2232
- case "ForInStatement":
2233
- this.walkForInStatement(statement);
2352
+ case "VariableDeclaration":
2353
+ this.walkVariableDeclaration(statement);
2234
2354
  break;
2235
- case "ForOfStatement":
2236
- this.walkForOfStatement(statement);
2355
+ case "ReturnStatement":
2356
+ this.walkReturnStatement(statement);
2237
2357
  break;
2238
- case "ForStatement":
2239
- this.walkForStatement(statement);
2358
+ case "IfStatement":
2359
+ this.walkIfStatement(statement);
2360
+ break;
2361
+ case "BlockStatement":
2362
+ this.walkBlockStatement(statement);
2240
2363
  break;
2241
2364
  case "FunctionDeclaration":
2242
2365
  this.walkFunctionDeclaration(statement);
2243
2366
  break;
2244
- case "IfStatement":
2245
- this.walkIfStatement(statement);
2246
- break;
2247
- case "LabeledStatement":
2248
- this.walkLabeledStatement(statement);
2367
+ case "ForStatement":
2368
+ this.walkForStatement(statement);
2249
2369
  break;
2250
- case "ReturnStatement":
2251
- this.walkReturnStatement(statement);
2370
+ case "TryStatement":
2371
+ this.walkTryStatement(statement);
2252
2372
  break;
2253
2373
  case "SwitchStatement":
2254
2374
  this.walkSwitchStatement(statement);
@@ -2256,15 +2376,30 @@ class JavascriptParser extends Parser {
2256
2376
  case "ThrowStatement":
2257
2377
  this.walkThrowStatement(statement);
2258
2378
  break;
2259
- case "TryStatement":
2260
- this.walkTryStatement(statement);
2261
- break;
2262
- case "VariableDeclaration":
2263
- this.walkVariableDeclaration(statement);
2264
- break;
2265
2379
  case "WhileStatement":
2266
2380
  this.walkWhileStatement(statement);
2267
2381
  break;
2382
+ case "ClassDeclaration":
2383
+ this.walkClassDeclaration(statement);
2384
+ break;
2385
+ case "ForInStatement":
2386
+ this.walkForInStatement(statement);
2387
+ break;
2388
+ case "ForOfStatement":
2389
+ this.walkForOfStatement(statement);
2390
+ break;
2391
+ case "DoWhileStatement":
2392
+ this.walkDoWhileStatement(statement);
2393
+ break;
2394
+ case "ExportNamedDeclaration":
2395
+ this.walkExportNamedDeclaration(statement);
2396
+ break;
2397
+ case "ExportDefaultDeclaration":
2398
+ this.walkExportDefaultDeclaration(statement);
2399
+ break;
2400
+ case "LabeledStatement":
2401
+ this.walkLabeledStatement(statement);
2402
+ break;
2268
2403
  case "WithStatement":
2269
2404
  this.walkWithStatement(statement);
2270
2405
  break;
@@ -2287,6 +2422,7 @@ class JavascriptParser extends Parser {
2287
2422
 
2288
2423
  // Real Statements
2289
2424
  /**
2425
+ * Pre walk block statement.
2290
2426
  * @param {BlockStatement} statement block statement
2291
2427
  */
2292
2428
  preWalkBlockStatement(statement) {
@@ -2294,6 +2430,7 @@ class JavascriptParser extends Parser {
2294
2430
  }
2295
2431
 
2296
2432
  /**
2433
+ * Walk block statement.
2297
2434
  * @param {BlockStatement | StaticBlock} statement block statement
2298
2435
  */
2299
2436
  walkBlockStatement(statement) {
@@ -2307,6 +2444,7 @@ class JavascriptParser extends Parser {
2307
2444
  }
2308
2445
 
2309
2446
  /**
2447
+ * Walk expression statement.
2310
2448
  * @param {ExpressionStatement} statement expression statement
2311
2449
  */
2312
2450
  walkExpressionStatement(statement) {
@@ -2314,6 +2452,7 @@ class JavascriptParser extends Parser {
2314
2452
  }
2315
2453
 
2316
2454
  /**
2455
+ * Pre walk if statement.
2317
2456
  * @param {IfStatement} statement if statement
2318
2457
  */
2319
2458
  preWalkIfStatement(statement) {
@@ -2324,27 +2463,47 @@ class JavascriptParser extends Parser {
2324
2463
  }
2325
2464
 
2326
2465
  /**
2466
+ * Walks a conditional branch with its guard frame (if any) pushed onto the
2467
+ * parser-state guard stack for the duration of the branch body.
2468
+ * @param {EXPECTED_OBJECT | undefined | null} frame guard frame, or falsy when the branch is unguarded
2469
+ * @param {() => void} walk branch walk
2470
+ * @returns {void}
2471
+ */
2472
+ walkGuardedBranch(frame, walk) {
2473
+ if (!frame) {
2474
+ walk();
2475
+ return;
2476
+ }
2477
+ const stack = this.state.guardStack || (this.state.guardStack = []);
2478
+ stack.push(frame);
2479
+ try {
2480
+ walk();
2481
+ } finally {
2482
+ stack.pop();
2483
+ }
2484
+ }
2485
+
2486
+ /**
2487
+ * Processes the provided statement.
2327
2488
  * @param {IfStatement} statement if statement
2328
2489
  */
2329
2490
  walkIfStatement(statement) {
2330
2491
  const result = this.hooks.statementIf.call(statement);
2331
2492
  if (result === undefined) {
2332
- const inGuard = this.hooks.collectGuards.call(statement.test);
2333
- if (inGuard) {
2334
- inGuard(() => {
2335
- this.walkExpression(statement.test);
2336
- this.walkNestedStatement(statement.consequent);
2337
- });
2338
- } else {
2339
- this.walkExpression(statement.test);
2340
- this.walkNestedStatement(statement.consequent);
2341
- }
2493
+ const guard = this.hooks.collectGuards.call(statement.test);
2494
+ this.walkExpression(statement.test);
2495
+ this.walkGuardedBranch(guard ? guard.consequent : undefined, () =>
2496
+ this.walkNestedStatement(statement.consequent)
2497
+ );
2342
2498
 
2343
2499
  const consequentTerminated = this.scope.terminated;
2344
2500
  this.scope.terminated = undefined;
2345
2501
 
2346
2502
  if (statement.alternate) {
2347
- this.walkNestedStatement(statement.alternate);
2503
+ const alternate = statement.alternate;
2504
+ this.walkGuardedBranch(guard ? guard.alternate : undefined, () =>
2505
+ this.walkNestedStatement(alternate)
2506
+ );
2348
2507
  }
2349
2508
 
2350
2509
  const alternateTerminated = this.scope.terminated;
@@ -2361,6 +2520,7 @@ class JavascriptParser extends Parser {
2361
2520
  }
2362
2521
 
2363
2522
  /**
2523
+ * Pre walk labeled statement.
2364
2524
  * @param {LabeledStatement} statement with statement
2365
2525
  */
2366
2526
  preWalkLabeledStatement(statement) {
@@ -2368,6 +2528,7 @@ class JavascriptParser extends Parser {
2368
2528
  }
2369
2529
 
2370
2530
  /**
2531
+ * Walk labeled statement.
2371
2532
  * @param {LabeledStatement} statement with statement
2372
2533
  */
2373
2534
  walkLabeledStatement(statement) {
@@ -2382,6 +2543,7 @@ class JavascriptParser extends Parser {
2382
2543
  }
2383
2544
 
2384
2545
  /**
2546
+ * Pre walk with statement.
2385
2547
  * @param {WithStatement} statement with statement
2386
2548
  */
2387
2549
  preWalkWithStatement(statement) {
@@ -2389,9 +2551,16 @@ class JavascriptParser extends Parser {
2389
2551
  }
2390
2552
 
2391
2553
  /**
2554
+ * Walk with statement.
2392
2555
  * @param {WithStatement} statement with statement
2393
2556
  */
2394
2557
  walkWithStatement(statement) {
2558
+ if (this._strictInModuleOutput) {
2559
+ this._reportStrictModeViolation(
2560
+ "`with` statements are not allowed",
2561
+ statement
2562
+ );
2563
+ }
2395
2564
  this.inBlockScope(() => {
2396
2565
  this.walkExpression(statement.object);
2397
2566
  this.walkNestedStatement(statement.body);
@@ -2399,6 +2568,7 @@ class JavascriptParser extends Parser {
2399
2568
  }
2400
2569
 
2401
2570
  /**
2571
+ * Pre walk switch statement.
2402
2572
  * @param {SwitchStatement} statement switch statement
2403
2573
  */
2404
2574
  preWalkSwitchStatement(statement) {
@@ -2406,6 +2576,7 @@ class JavascriptParser extends Parser {
2406
2576
  }
2407
2577
 
2408
2578
  /**
2579
+ * Walk switch statement.
2409
2580
  * @param {SwitchStatement} statement switch statement
2410
2581
  */
2411
2582
  walkSwitchStatement(statement) {
@@ -2414,6 +2585,7 @@ class JavascriptParser extends Parser {
2414
2585
  }
2415
2586
 
2416
2587
  /**
2588
+ * Walk terminating statement.
2417
2589
  * @param {ReturnStatement | ThrowStatement} statement return or throw statement
2418
2590
  */
2419
2591
  walkTerminatingStatement(statement) {
@@ -2429,6 +2601,7 @@ class JavascriptParser extends Parser {
2429
2601
  }
2430
2602
 
2431
2603
  /**
2604
+ * Walk return statement.
2432
2605
  * @param {ReturnStatement} statement return statement
2433
2606
  */
2434
2607
  walkReturnStatement(statement) {
@@ -2436,6 +2609,7 @@ class JavascriptParser extends Parser {
2436
2609
  }
2437
2610
 
2438
2611
  /**
2612
+ * Walk throw statement.
2439
2613
  * @param {ThrowStatement} statement return statement
2440
2614
  */
2441
2615
  walkThrowStatement(statement) {
@@ -2443,6 +2617,7 @@ class JavascriptParser extends Parser {
2443
2617
  }
2444
2618
 
2445
2619
  /**
2620
+ * Pre walk try statement.
2446
2621
  * @param {TryStatement} statement try statement
2447
2622
  */
2448
2623
  preWalkTryStatement(statement) {
@@ -2452,6 +2627,7 @@ class JavascriptParser extends Parser {
2452
2627
  }
2453
2628
 
2454
2629
  /**
2630
+ * Walk try statement.
2455
2631
  * @param {TryStatement} statement try statement
2456
2632
  */
2457
2633
  walkTryStatement(statement) {
@@ -2489,6 +2665,7 @@ class JavascriptParser extends Parser {
2489
2665
  }
2490
2666
 
2491
2667
  /**
2668
+ * Pre walk while statement.
2492
2669
  * @param {WhileStatement} statement while statement
2493
2670
  */
2494
2671
  preWalkWhileStatement(statement) {
@@ -2496,6 +2673,7 @@ class JavascriptParser extends Parser {
2496
2673
  }
2497
2674
 
2498
2675
  /**
2676
+ * Walk while statement.
2499
2677
  * @param {WhileStatement} statement while statement
2500
2678
  */
2501
2679
  walkWhileStatement(statement) {
@@ -2506,6 +2684,7 @@ class JavascriptParser extends Parser {
2506
2684
  }
2507
2685
 
2508
2686
  /**
2687
+ * Pre walk do while statement.
2509
2688
  * @param {DoWhileStatement} statement do while statement
2510
2689
  */
2511
2690
  preWalkDoWhileStatement(statement) {
@@ -2513,6 +2692,7 @@ class JavascriptParser extends Parser {
2513
2692
  }
2514
2693
 
2515
2694
  /**
2695
+ * Walk do while statement.
2516
2696
  * @param {DoWhileStatement} statement do while statement
2517
2697
  */
2518
2698
  walkDoWhileStatement(statement) {
@@ -2523,6 +2703,7 @@ class JavascriptParser extends Parser {
2523
2703
  }
2524
2704
 
2525
2705
  /**
2706
+ * Pre walk for statement.
2526
2707
  * @param {ForStatement} statement for statement
2527
2708
  */
2528
2709
  preWalkForStatement(statement) {
@@ -2533,6 +2714,7 @@ class JavascriptParser extends Parser {
2533
2714
  }
2534
2715
 
2535
2716
  /**
2717
+ * Walk for statement.
2536
2718
  * @param {ForStatement} statement for statement
2537
2719
  */
2538
2720
  walkForStatement(statement) {
@@ -2568,6 +2750,7 @@ class JavascriptParser extends Parser {
2568
2750
  }
2569
2751
 
2570
2752
  /**
2753
+ * Pre walk for in statement.
2571
2754
  * @param {ForInStatement} statement for statement
2572
2755
  */
2573
2756
  preWalkForInStatement(statement) {
@@ -2578,6 +2761,7 @@ class JavascriptParser extends Parser {
2578
2761
  }
2579
2762
 
2580
2763
  /**
2764
+ * Walk for in statement.
2581
2765
  * @param {ForInStatement} statement for statement
2582
2766
  */
2583
2767
  walkForInStatement(statement) {
@@ -2606,6 +2790,7 @@ class JavascriptParser extends Parser {
2606
2790
  }
2607
2791
 
2608
2792
  /**
2793
+ * Pre walk for of statement.
2609
2794
  * @param {ForOfStatement} statement statement
2610
2795
  */
2611
2796
  preWalkForOfStatement(statement) {
@@ -2619,6 +2804,7 @@ class JavascriptParser extends Parser {
2619
2804
  }
2620
2805
 
2621
2806
  /**
2807
+ * Walk for of statement.
2622
2808
  * @param {ForOfStatement} statement for statement
2623
2809
  */
2624
2810
  walkForOfStatement(statement) {
@@ -2647,6 +2833,7 @@ class JavascriptParser extends Parser {
2647
2833
  }
2648
2834
 
2649
2835
  /**
2836
+ * Pre walk function declaration.
2650
2837
  * @param {FunctionDeclaration | MaybeNamedFunctionDeclaration} statement function declaration
2651
2838
  */
2652
2839
  preWalkFunctionDeclaration(statement) {
@@ -2656,11 +2843,15 @@ class JavascriptParser extends Parser {
2656
2843
  }
2657
2844
 
2658
2845
  /**
2846
+ * Walk function declaration.
2659
2847
  * @param {FunctionDeclaration | MaybeNamedFunctionDeclaration} statement function declaration
2660
2848
  */
2661
2849
  walkFunctionDeclaration(statement) {
2662
2850
  const wasTopLevel = this.scope.topLevelScope;
2663
2851
  this.scope.topLevelScope = false;
2852
+ if (this._strictInModuleOutput) {
2853
+ this._checkStrictModeParams(statement.params);
2854
+ }
2664
2855
  this.inFunctionScope(true, statement.params, () => {
2665
2856
  for (const param of statement.params) {
2666
2857
  this.walkPattern(param);
@@ -2678,6 +2869,7 @@ class JavascriptParser extends Parser {
2678
2869
  }
2679
2870
 
2680
2871
  /**
2872
+ * Block pre walk expression statement.
2681
2873
  * @param {ExpressionStatement} statement expression statement
2682
2874
  */
2683
2875
  blockPreWalkExpressionStatement(statement) {
@@ -2689,6 +2881,7 @@ class JavascriptParser extends Parser {
2689
2881
  }
2690
2882
 
2691
2883
  /**
2884
+ * Pre walk assignment expression.
2692
2885
  * @param {AssignmentExpression} expression assignment expression
2693
2886
  */
2694
2887
  preWalkAssignmentExpression(expression) {
@@ -2696,6 +2889,7 @@ class JavascriptParser extends Parser {
2696
2889
  }
2697
2890
 
2698
2891
  /**
2892
+ * Enter destructuring assignment.
2699
2893
  * @param {Pattern} pattern pattern
2700
2894
  * @param {Expression} expression assignment expression
2701
2895
  * @returns {Expression | undefined} destructuring expression
@@ -2737,6 +2931,7 @@ class JavascriptParser extends Parser {
2737
2931
  }
2738
2932
 
2739
2933
  /**
2934
+ * Module pre walk import declaration.
2740
2935
  * @param {ImportDeclaration} statement statement
2741
2936
  */
2742
2937
  modulePreWalkImportDeclaration(statement) {
@@ -2782,6 +2977,7 @@ class JavascriptParser extends Parser {
2782
2977
  }
2783
2978
 
2784
2979
  /**
2980
+ * Processes the provided declaration.
2785
2981
  * @param {Declaration} declaration declaration
2786
2982
  * @param {OnIdent} onIdent on ident callback
2787
2983
  */
@@ -2807,6 +3003,7 @@ class JavascriptParser extends Parser {
2807
3003
  }
2808
3004
 
2809
3005
  /**
3006
+ * Module pre walk export named declaration.
2810
3007
  * @param {ExportNamedDeclaration} statement statement
2811
3008
  */
2812
3009
  modulePreWalkExportNamedDeclaration(statement) {
@@ -2847,6 +3044,7 @@ class JavascriptParser extends Parser {
2847
3044
  }
2848
3045
 
2849
3046
  /**
3047
+ * Block pre walk export named declaration.
2850
3048
  * @param {ExportNamedDeclaration} statement statement
2851
3049
  */
2852
3050
  blockPreWalkExportNamedDeclaration(statement) {
@@ -2898,6 +3096,7 @@ class JavascriptParser extends Parser {
2898
3096
  }
2899
3097
 
2900
3098
  /**
3099
+ * Walk export named declaration.
2901
3100
  * @param {ExportNamedDeclaration} statement the statement
2902
3101
  */
2903
3102
  walkExportNamedDeclaration(statement) {
@@ -2907,6 +3106,7 @@ class JavascriptParser extends Parser {
2907
3106
  }
2908
3107
 
2909
3108
  /**
3109
+ * Block pre walk export default declaration.
2910
3110
  * @param {ExportDefaultDeclaration} statement statement
2911
3111
  */
2912
3112
  blockPreWalkExportDefaultDeclaration(statement) {
@@ -2942,6 +3142,7 @@ class JavascriptParser extends Parser {
2942
3142
  }
2943
3143
 
2944
3144
  /**
3145
+ * Walk export default declaration.
2945
3146
  * @param {ExportDefaultDeclaration} statement statement
2946
3147
  */
2947
3148
  walkExportDefaultDeclaration(statement) {
@@ -2976,6 +3177,7 @@ class JavascriptParser extends Parser {
2976
3177
  }
2977
3178
 
2978
3179
  /**
3180
+ * Module pre walk export all declaration.
2979
3181
  * @param {ExportAllDeclaration} statement statement
2980
3182
  */
2981
3183
  modulePreWalkExportAllDeclaration(statement) {
@@ -2991,6 +3193,7 @@ class JavascriptParser extends Parser {
2991
3193
  }
2992
3194
 
2993
3195
  /**
3196
+ * Pre walk variable declaration.
2994
3197
  * @param {VariableDeclaration} statement variable declaration
2995
3198
  */
2996
3199
  preWalkVariableDeclaration(statement) {
@@ -2999,6 +3202,7 @@ class JavascriptParser extends Parser {
2999
3202
  }
3000
3203
 
3001
3204
  /**
3205
+ * Block pre walk variable declaration.
3002
3206
  * @param {VariableDeclaration} statement variable declaration
3003
3207
  */
3004
3208
  blockPreWalkVariableDeclaration(statement) {
@@ -3014,32 +3218,53 @@ class JavascriptParser extends Parser {
3014
3218
  }
3015
3219
 
3016
3220
  /**
3221
+ * Pre walk variable declaration.
3017
3222
  * @param {VariableDeclaration} statement variable declaration
3018
3223
  * @param {HookMap<SyncBailHook<[Identifier], boolean | void>>} hookMap map of hooks
3019
3224
  */
3020
3225
  _preWalkVariableDeclaration(statement, hookMap) {
3226
+ /** @type {OnIdent | undefined} */
3227
+ let onIdent;
3021
3228
  for (const declarator of statement.declarations) {
3022
- switch (declarator.type) {
3023
- case "VariableDeclarator": {
3024
- this.preWalkVariableDeclarator(declarator);
3025
- if (!this.hooks.preDeclarator.call(declarator, statement)) {
3026
- this.enterPattern(declarator.id, (name, ident) => {
3027
- let hook = hookMap.get(name);
3028
- if (hook === undefined || !hook.call(ident)) {
3029
- hook = this.hooks.varDeclaration.get(name);
3030
- if (hook === undefined || !hook.call(ident)) {
3031
- this.defineVariable(name);
3032
- }
3033
- }
3034
- });
3035
- }
3036
- break;
3229
+ if (declarator.type !== "VariableDeclarator") continue;
3230
+ this.preWalkVariableDeclarator(declarator);
3231
+ if (this.hooks.preDeclarator.call(declarator, statement)) continue;
3232
+ const id = declarator.id;
3233
+ if (id.type === "Identifier") {
3234
+ // fast path: plain `const x =` skips the enterPattern dispatch and
3235
+ // the per-declaration onIdent closure (only patterns need it)
3236
+ if (!this.callHooksForName(this.hooks.pattern, id.name, id)) {
3237
+ this._defineVariableForDeclaration(id.name, id, hookMap);
3238
+ }
3239
+ } else {
3240
+ if (onIdent === undefined) {
3241
+ onIdent = (name, ident) =>
3242
+ this._defineVariableForDeclaration(name, ident, hookMap);
3037
3243
  }
3244
+ this.enterPattern(id, onIdent);
3038
3245
  }
3039
3246
  }
3040
3247
  }
3041
3248
 
3042
3249
  /**
3250
+ * Defines a declared variable unless a declaration hook handles it.
3251
+ * @param {string} name variable name
3252
+ * @param {Identifier} ident identifier node
3253
+ * @param {HookMap<SyncBailHook<[Identifier], boolean | void>>} hookMap kind-specific declaration hooks
3254
+ * @returns {void}
3255
+ */
3256
+ _defineVariableForDeclaration(name, ident, hookMap) {
3257
+ let hook = hookMap.get(name);
3258
+ if (hook === undefined || !hook.call(ident)) {
3259
+ hook = this.hooks.varDeclaration.get(name);
3260
+ if (hook === undefined || !hook.call(ident)) {
3261
+ this.defineVariable(name);
3262
+ }
3263
+ }
3264
+ }
3265
+
3266
+ /**
3267
+ * Pre walk object pattern.
3043
3268
  * @param {ObjectPattern} objectPattern object pattern
3044
3269
  * @returns {DestructuringAssignmentProperties | undefined} set of names or undefined if not all keys are identifiers
3045
3270
  */
@@ -3071,7 +3296,6 @@ class JavascriptParser extends Parser {
3071
3296
  props.add({
3072
3297
  id: key.name,
3073
3298
  range: /** @type {Range} */ (key.range),
3074
- loc: /** @type {SourceLocation} */ (key.loc),
3075
3299
  pattern,
3076
3300
  shorthand: this.scope.inShorthand
3077
3301
  });
@@ -3088,7 +3312,6 @@ class JavascriptParser extends Parser {
3088
3312
  props.add({
3089
3313
  id: str,
3090
3314
  range: /** @type {Range} */ (key.range),
3091
- loc: /** @type {SourceLocation} */ (key.loc),
3092
3315
  pattern,
3093
3316
  shorthand: this.scope.inShorthand
3094
3317
  });
@@ -3104,6 +3327,7 @@ class JavascriptParser extends Parser {
3104
3327
  }
3105
3328
 
3106
3329
  /**
3330
+ * Pre walk array pattern.
3107
3331
  * @param {ArrayPattern} arrayPattern array pattern
3108
3332
  * @returns {Set<DestructuringAssignmentProperty> | undefined} set of names or undefined if not all keys are identifiers
3109
3333
  */
@@ -3124,7 +3348,6 @@ class JavascriptParser extends Parser {
3124
3348
  props.add({
3125
3349
  id: `${i}`,
3126
3350
  range: /** @type {Range} */ (element.range),
3127
- loc: /** @type {SourceLocation} */ (element.loc),
3128
3351
  pattern,
3129
3352
  shorthand: false
3130
3353
  });
@@ -3134,6 +3357,7 @@ class JavascriptParser extends Parser {
3134
3357
  }
3135
3358
 
3136
3359
  /**
3360
+ * Pre walk variable declarator.
3137
3361
  * @param {VariableDeclarator} declarator variable declarator
3138
3362
  */
3139
3363
  preWalkVariableDeclarator(declarator) {
@@ -3143,6 +3367,7 @@ class JavascriptParser extends Parser {
3143
3367
  }
3144
3368
 
3145
3369
  /**
3370
+ * Walk variable declaration.
3146
3371
  * @param {VariableDeclaration} statement variable declaration
3147
3372
  */
3148
3373
  walkVariableDeclaration(statement) {
@@ -3179,6 +3404,7 @@ class JavascriptParser extends Parser {
3179
3404
  }
3180
3405
 
3181
3406
  /**
3407
+ * Block pre walk class declaration.
3182
3408
  * @param {ClassDeclaration | MaybeNamedClassDeclaration} statement class declaration
3183
3409
  */
3184
3410
  blockPreWalkClassDeclaration(statement) {
@@ -3188,6 +3414,7 @@ class JavascriptParser extends Parser {
3188
3414
  }
3189
3415
 
3190
3416
  /**
3417
+ * Walk class declaration.
3191
3418
  * @param {ClassDeclaration | MaybeNamedClassDeclaration} statement class declaration
3192
3419
  */
3193
3420
  walkClassDeclaration(statement) {
@@ -3195,6 +3422,7 @@ class JavascriptParser extends Parser {
3195
3422
  }
3196
3423
 
3197
3424
  /**
3425
+ * Pre walk switch cases.
3198
3426
  * @param {SwitchCase[]} switchCases switch statement
3199
3427
  */
3200
3428
  preWalkSwitchCases(switchCases) {
@@ -3205,6 +3433,7 @@ class JavascriptParser extends Parser {
3205
3433
  }
3206
3434
 
3207
3435
  /**
3436
+ * Processes the provided switch case.
3208
3437
  * @param {SwitchCase[]} switchCases switch statement
3209
3438
  */
3210
3439
  walkSwitchCases(switchCases) {
@@ -3245,6 +3474,7 @@ class JavascriptParser extends Parser {
3245
3474
  }
3246
3475
 
3247
3476
  /**
3477
+ * Pre walk catch clause.
3248
3478
  * @param {CatchClause} catchClause catch clause
3249
3479
  */
3250
3480
  preWalkCatchClause(catchClause) {
@@ -3252,6 +3482,7 @@ class JavascriptParser extends Parser {
3252
3482
  }
3253
3483
 
3254
3484
  /**
3485
+ * Processes the provided catch clause.
3255
3486
  * @param {CatchClause} catchClause catch clause
3256
3487
  */
3257
3488
  walkCatchClause(catchClause) {
@@ -3271,10 +3502,17 @@ class JavascriptParser extends Parser {
3271
3502
  }
3272
3503
 
3273
3504
  /**
3505
+ * Processes the provided pattern.
3274
3506
  * @param {Pattern} pattern pattern
3275
3507
  */
3276
3508
  walkPattern(pattern) {
3277
3509
  switch (pattern.type) {
3510
+ // plain identifier bindings are the common case and walk nothing
3511
+ case "Identifier":
3512
+ break;
3513
+ case "ObjectPattern":
3514
+ this.walkObjectPattern(pattern);
3515
+ break;
3278
3516
  case "ArrayPattern":
3279
3517
  this.walkArrayPattern(pattern);
3280
3518
  break;
@@ -3284,9 +3522,6 @@ class JavascriptParser extends Parser {
3284
3522
  case "MemberExpression":
3285
3523
  this.walkMemberExpression(pattern);
3286
3524
  break;
3287
- case "ObjectPattern":
3288
- this.walkObjectPattern(pattern);
3289
- break;
3290
3525
  case "RestElement":
3291
3526
  this.walkRestElement(pattern);
3292
3527
  break;
@@ -3294,6 +3529,7 @@ class JavascriptParser extends Parser {
3294
3529
  }
3295
3530
 
3296
3531
  /**
3532
+ * Walk assignment pattern.
3297
3533
  * @param {AssignmentPattern} pattern assignment pattern
3298
3534
  */
3299
3535
  walkAssignmentPattern(pattern) {
@@ -3302,6 +3538,7 @@ class JavascriptParser extends Parser {
3302
3538
  }
3303
3539
 
3304
3540
  /**
3541
+ * Walk object pattern.
3305
3542
  * @param {ObjectPattern} pattern pattern
3306
3543
  */
3307
3544
  walkObjectPattern(pattern) {
@@ -3318,6 +3555,7 @@ class JavascriptParser extends Parser {
3318
3555
  }
3319
3556
 
3320
3557
  /**
3558
+ * Walk array pattern.
3321
3559
  * @param {ArrayPattern} pattern array pattern
3322
3560
  */
3323
3561
  walkArrayPattern(pattern) {
@@ -3328,6 +3566,7 @@ class JavascriptParser extends Parser {
3328
3566
  }
3329
3567
 
3330
3568
  /**
3569
+ * Processes the provided pattern.
3331
3570
  * @param {RestElement} pattern rest element
3332
3571
  */
3333
3572
  walkRestElement(pattern) {
@@ -3335,10 +3574,12 @@ class JavascriptParser extends Parser {
3335
3574
  }
3336
3575
 
3337
3576
  /**
3577
+ * Processes the provided expression.
3338
3578
  * @param {(Expression | SpreadElement | null)[]} expressions expressions
3339
3579
  */
3340
3580
  walkExpressions(expressions) {
3341
- for (const expression of expressions) {
3581
+ for (let i = 0, len = expressions.length; i < len; i++) {
3582
+ const expression = expressions[i];
3342
3583
  if (expression) {
3343
3584
  this.walkExpression(expression);
3344
3585
  }
@@ -3346,81 +3587,90 @@ class JavascriptParser extends Parser {
3346
3587
  }
3347
3588
 
3348
3589
  /**
3590
+ * Processes the provided expression.
3349
3591
  * @param {Expression | SpreadElement | PrivateIdentifier | Super} expression expression
3350
3592
  */
3351
3593
  walkExpression(expression) {
3594
+ // cases ordered by measured node frequency (identifiers are ~40% of all
3595
+ // expressions) — V8 compiles this to sequential compares, so hot types
3596
+ // must come first
3352
3597
  switch (expression.type) {
3353
- case "ArrayExpression":
3354
- this.walkArrayExpression(expression);
3598
+ case "Identifier":
3599
+ this.walkIdentifier(expression);
3355
3600
  break;
3356
- case "ArrowFunctionExpression":
3357
- this.walkArrowFunctionExpression(expression);
3601
+ case "MemberExpression":
3602
+ this.walkMemberExpression(expression);
3358
3603
  break;
3359
- case "AssignmentExpression":
3360
- this.walkAssignmentExpression(expression);
3604
+ case "Literal":
3605
+ if (this._strictInModuleOutput) {
3606
+ this._checkStrictModeLiteral(expression);
3607
+ }
3361
3608
  break;
3362
- case "AwaitExpression":
3363
- this.walkAwaitExpression(expression);
3609
+ case "CallExpression":
3610
+ this.walkCallExpression(expression);
3364
3611
  break;
3365
3612
  case "BinaryExpression":
3366
3613
  this.walkBinaryExpression(expression);
3367
3614
  break;
3368
- case "CallExpression":
3369
- this.walkCallExpression(expression);
3370
- break;
3371
- case "ChainExpression":
3372
- this.walkChainExpression(expression);
3615
+ case "AssignmentExpression":
3616
+ this.walkAssignmentExpression(expression);
3373
3617
  break;
3374
- case "ClassExpression":
3375
- this.walkClassExpression(expression);
3618
+ case "UnaryExpression":
3619
+ this.walkUnaryExpression(expression);
3376
3620
  break;
3377
- case "ConditionalExpression":
3378
- this.walkConditionalExpression(expression);
3621
+ case "LogicalExpression":
3622
+ this.walkLogicalExpression(expression);
3379
3623
  break;
3380
- case "FunctionExpression":
3381
- this.walkFunctionExpression(expression);
3624
+ case "ArrowFunctionExpression":
3625
+ this.walkArrowFunctionExpression(expression);
3382
3626
  break;
3383
- case "Identifier":
3384
- this.walkIdentifier(expression);
3627
+ case "ThisExpression":
3628
+ this.walkThisExpression(expression);
3385
3629
  break;
3386
- case "ImportExpression":
3387
- this.walkImportExpression(expression);
3630
+ case "ConditionalExpression":
3631
+ this.walkConditionalExpression(expression);
3388
3632
  break;
3389
- case "LogicalExpression":
3390
- this.walkLogicalExpression(expression);
3633
+ case "ArrayExpression":
3634
+ this.walkArrayExpression(expression);
3391
3635
  break;
3392
- case "MetaProperty":
3393
- this.walkMetaProperty(expression);
3636
+ case "ObjectExpression":
3637
+ this.walkObjectExpression(expression);
3394
3638
  break;
3395
- case "MemberExpression":
3396
- this.walkMemberExpression(expression);
3639
+ case "FunctionExpression":
3640
+ this.walkFunctionExpression(expression);
3397
3641
  break;
3398
3642
  case "NewExpression":
3399
3643
  this.walkNewExpression(expression);
3400
3644
  break;
3401
- case "ObjectExpression":
3402
- this.walkObjectExpression(expression);
3645
+ case "TemplateLiteral":
3646
+ this.walkTemplateLiteral(expression);
3647
+ break;
3648
+ case "SpreadElement":
3649
+ this.walkSpreadElement(expression);
3403
3650
  break;
3404
3651
  case "SequenceExpression":
3405
3652
  this.walkSequenceExpression(expression);
3406
3653
  break;
3407
- case "SpreadElement":
3408
- this.walkSpreadElement(expression);
3654
+ case "UpdateExpression":
3655
+ this.walkUpdateExpression(expression);
3409
3656
  break;
3410
- case "TaggedTemplateExpression":
3411
- this.walkTaggedTemplateExpression(expression);
3657
+ case "AwaitExpression":
3658
+ this.walkAwaitExpression(expression);
3412
3659
  break;
3413
- case "TemplateLiteral":
3414
- this.walkTemplateLiteral(expression);
3660
+ case "ChainExpression":
3661
+ this.walkChainExpression(expression);
3415
3662
  break;
3416
- case "ThisExpression":
3417
- this.walkThisExpression(expression);
3663
+ case "ClassExpression":
3664
+ this.walkClassExpression(expression);
3418
3665
  break;
3419
- case "UnaryExpression":
3420
- this.walkUnaryExpression(expression);
3666
+ case "ImportExpression":
3667
+ this.walkImportExpression(expression);
3421
3668
  break;
3422
- case "UpdateExpression":
3423
- this.walkUpdateExpression(expression);
3669
+ case "MetaProperty":
3670
+ this.walkMetaProperty(expression);
3671
+ break;
3672
+ case "TaggedTemplateExpression":
3673
+ this.walkTaggedTemplateExpression(expression);
3424
3674
  break;
3425
3675
  case "YieldExpression":
3426
3676
  this.walkYieldExpression(expression);
@@ -3429,6 +3679,36 @@ class JavascriptParser extends Parser {
3429
3679
  }
3430
3680
 
3431
3681
  /**
3682
+ * Reports octal number literals (`0777`) and octal string escapes (`"\47"`),
3683
+ * both SyntaxErrors in strict-mode ESM output.
3684
+ * @param {Literal} expression literal
3685
+ */
3686
+ _checkStrictModeLiteral(expression) {
3687
+ const raw = /** @type {string | undefined} */ (expression.raw);
3688
+ if (raw === undefined) return;
3689
+ if (typeof expression.value === "number") {
3690
+ // Legacy octal (`0777`) or non-octal decimal (`08`) integer literal.
3691
+ if (
3692
+ raw.length > 1 &&
3693
+ raw.charCodeAt(0) === 48 &&
3694
+ raw.charCodeAt(1) >= 48 &&
3695
+ raw.charCodeAt(1) <= 57
3696
+ ) {
3697
+ this._reportStrictModeViolation(
3698
+ "Octal literals are not allowed",
3699
+ expression
3700
+ );
3701
+ }
3702
+ } else if (typeof expression.value === "string" && hasOctalEscape(raw)) {
3703
+ this._reportStrictModeViolation(
3704
+ "Octal escape sequences are not allowed",
3705
+ expression
3706
+ );
3707
+ }
3708
+ }
3709
+
3710
+ /**
3711
+ * Walk await expression.
3432
3712
  * @param {AwaitExpression} expression await expression
3433
3713
  */
3434
3714
  walkAwaitExpression(expression) {
@@ -3439,6 +3719,7 @@ class JavascriptParser extends Parser {
3439
3719
  }
3440
3720
 
3441
3721
  /**
3722
+ * Walk array expression.
3442
3723
  * @param {ArrayExpression} expression array expression
3443
3724
  */
3444
3725
  walkArrayExpression(expression) {
@@ -3448,6 +3729,7 @@ class JavascriptParser extends Parser {
3448
3729
  }
3449
3730
 
3450
3731
  /**
3732
+ * Walk spread element.
3451
3733
  * @param {SpreadElement} expression spread element
3452
3734
  */
3453
3735
  walkSpreadElement(expression) {
@@ -3457,6 +3739,7 @@ class JavascriptParser extends Parser {
3457
3739
  }
3458
3740
 
3459
3741
  /**
3742
+ * Walk object expression.
3460
3743
  * @param {ObjectExpression} expression object expression
3461
3744
  */
3462
3745
  walkObjectExpression(expression) {
@@ -3471,6 +3754,7 @@ class JavascriptParser extends Parser {
3471
3754
  }
3472
3755
 
3473
3756
  /**
3757
+ * Processes the provided prop.
3474
3758
  * @param {Property | SpreadElement} prop property or spread element
3475
3759
  */
3476
3760
  walkProperty(prop) {
@@ -3494,18 +3778,21 @@ class JavascriptParser extends Parser {
3494
3778
  }
3495
3779
 
3496
3780
  /**
3781
+ * Walk function expression.
3497
3782
  * @param {FunctionExpression} expression arrow function expression
3498
3783
  */
3499
3784
  walkFunctionExpression(expression) {
3500
3785
  const wasTopLevel = this.scope.topLevelScope;
3501
3786
  this.scope.topLevelScope = false;
3502
- const scopeParams = [...expression.params];
3503
-
3504
- // Add function name in scope for recursive calls
3505
- if (expression.id) {
3506
- scopeParams.push(expression.id);
3787
+ // Only copy params when the function name must be added (recursive calls);
3788
+ // inFunctionScope reads params without mutating, like arrow functions.
3789
+ const scopeParams = expression.id
3790
+ ? [...expression.params, expression.id]
3791
+ : expression.params;
3792
+
3793
+ if (this._strictInModuleOutput) {
3794
+ this._checkStrictModeParams(expression.params);
3507
3795
  }
3508
-
3509
3796
  this.inFunctionScope(true, scopeParams, () => {
3510
3797
  for (const param of expression.params) {
3511
3798
  this.walkPattern(param);
@@ -3523,11 +3810,15 @@ class JavascriptParser extends Parser {
3523
3810
  }
3524
3811
 
3525
3812
  /**
3813
+ * Walk arrow function expression.
3526
3814
  * @param {ArrowFunctionExpression} expression arrow function expression
3527
3815
  */
3528
3816
  walkArrowFunctionExpression(expression) {
3529
3817
  const wasTopLevel = this.scope.topLevelScope;
3530
3818
  this.scope.topLevelScope = wasTopLevel ? "arrow" : false;
3819
+ if (this._strictInModuleOutput) {
3820
+ this._checkStrictModeParams(expression.params);
3821
+ }
3531
3822
  this.inFunctionScope(false, expression.params, () => {
3532
3823
  for (const param of expression.params) {
3533
3824
  this.walkPattern(param);
@@ -3546,6 +3837,7 @@ class JavascriptParser extends Parser {
3546
3837
  }
3547
3838
 
3548
3839
  /**
3840
+ * Walk sequence expression.
3549
3841
  * @param {SequenceExpression} expression the sequence
3550
3842
  */
3551
3843
  walkSequenceExpression(expression) {
@@ -3584,13 +3876,90 @@ class JavascriptParser extends Parser {
3584
3876
  }
3585
3877
 
3586
3878
  /**
3879
+ * Walk update expression.
3587
3880
  * @param {UpdateExpression} expression the update expression
3588
3881
  */
3589
3882
  walkUpdateExpression(expression) {
3883
+ if (
3884
+ this._strictInModuleOutput &&
3885
+ expression.argument.type === "Identifier"
3886
+ ) {
3887
+ this._checkStrictModeAssignTarget(expression.argument.name, expression);
3888
+ }
3590
3889
  this.walkExpression(expression.argument);
3591
3890
  }
3592
3891
 
3593
3892
  /**
3893
+ * Reports `arguments.callee` / `arguments.caller` — both throw a TypeError
3894
+ * once the module runs in strict-mode ESM output.
3895
+ * @param {string} name accessed member name
3896
+ * @param {Expression} node node to report the violation at
3897
+ */
3898
+ _checkStrictModeArgumentsMember(name, node) {
3899
+ if ((name === "callee" || name === "caller") && !this.scope.isStrict) {
3900
+ this._reportStrictModeViolation(
3901
+ `Accessing "arguments.${name}" is not allowed`,
3902
+ node
3903
+ );
3904
+ }
3905
+ }
3906
+
3907
+ /**
3908
+ * Reports an assignment or update target that breaks in strict-mode ESM
3909
+ * output: `eval` / `arguments` are a SyntaxError, the read-only globals
3910
+ * (`undefined`, `NaN`, `Infinity`) a TypeError instead of a silent no-op.
3911
+ * @param {string} name target identifier name
3912
+ * @param {AssignmentExpression | UpdateExpression} node node to report the violation at
3913
+ */
3914
+ _checkStrictModeAssignTarget(name, node) {
3915
+ if (name === "eval" || name === "arguments") {
3916
+ this._reportStrictModeViolation(
3917
+ `Assigning to "${name}" is not allowed`,
3918
+ node
3919
+ );
3920
+ } else if (
3921
+ (name === "undefined" || name === "NaN" || name === "Infinity") &&
3922
+ !this.scope.isStrict &&
3923
+ !this.isVariableDefined(name)
3924
+ ) {
3925
+ this._reportStrictModeViolation(
3926
+ `Assigning to the read-only global "${name}" is not allowed`,
3927
+ node
3928
+ );
3929
+ }
3930
+ }
3931
+
3932
+ /**
3933
+ * Reports strict-mode-only errors in a function's parameter list: a duplicate
3934
+ * simple parameter, or a parameter named `eval` / `arguments`.
3935
+ * @param {(import("estree").Pattern)[]} params function parameters
3936
+ */
3937
+ _checkStrictModeParams(params) {
3938
+ /** @type {Set<string> | undefined} */
3939
+ let seen;
3940
+ for (const param of params) {
3941
+ if (param.type !== "Identifier") continue;
3942
+ const name = param.name;
3943
+ if (name === "eval" || name === "arguments") {
3944
+ this._reportStrictModeViolation(
3945
+ `"${name}" is not allowed as a parameter name`,
3946
+ param
3947
+ );
3948
+ }
3949
+ if (seen === undefined) seen = new Set();
3950
+ if (seen.has(name)) {
3951
+ this._reportStrictModeViolation(
3952
+ `Duplicate parameter name "${name}" is not allowed`,
3953
+ param
3954
+ );
3955
+ } else {
3956
+ seen.add(name);
3957
+ }
3958
+ }
3959
+ }
3960
+
3961
+ /**
3962
+ * Walk unary expression.
3594
3963
  * @param {UnaryExpression} expression the unary expression
3595
3964
  */
3596
3965
  walkUnaryExpression(expression) {
@@ -3609,11 +3978,41 @@ class JavascriptParser extends Parser {
3609
3978
  );
3610
3979
  if (result === true) return;
3611
3980
  }
3981
+ } else if (
3982
+ this._strictInModuleOutput &&
3983
+ expression.operator === "delete" &&
3984
+ expression.argument.type === "Identifier"
3985
+ ) {
3986
+ this._reportStrictModeViolation(
3987
+ `Deleting the unqualified identifier "${expression.argument.name}" is not allowed`,
3988
+ expression
3989
+ );
3612
3990
  }
3613
3991
  this.walkExpression(expression.argument);
3614
3992
  }
3615
3993
 
3616
3994
  /**
3995
+ * Reports a construct that a loose script allows but that breaks once the
3996
+ * module is emitted as strict-mode ESM output. Severity comes from the
3997
+ * `strictModeViolations` parser option (`false` disables the checks upfront).
3998
+ * The location is computed here, on the rare violation path only.
3999
+ * @param {string} reason what is not allowed
4000
+ * @param {Statement | Expression | Identifier} node node to report the violation at
4001
+ */
4002
+ _reportStrictModeViolation(reason, node) {
4003
+ const diagnostic = new WebpackError(
4004
+ `${reason}. The output is an ES module, which runs in strict mode.`
4005
+ );
4006
+ diagnostic.loc = this.getLocation(node);
4007
+ if (this.options.strictModeViolations === "error") {
4008
+ this.state.module.addError(diagnostic);
4009
+ } else {
4010
+ this.state.module.addWarning(diagnostic);
4011
+ }
4012
+ }
4013
+
4014
+ /**
4015
+ * Walk left right expression.
3617
4016
  * @param {LogicalExpression | BinaryExpression} expression the expression
3618
4017
  */
3619
4018
  walkLeftRightExpression(expression) {
@@ -3622,6 +4021,7 @@ class JavascriptParser extends Parser {
3622
4021
  }
3623
4022
 
3624
4023
  /**
4024
+ * Walk binary expression.
3625
4025
  * @param {BinaryExpression} expression the binary expression
3626
4026
  */
3627
4027
  walkBinaryExpression(expression) {
@@ -3631,6 +4031,7 @@ class JavascriptParser extends Parser {
3631
4031
  }
3632
4032
 
3633
4033
  /**
4034
+ * Walk logical expression.
3634
4035
  * @param {LogicalExpression} expression the logical expression
3635
4036
  */
3636
4037
  walkLogicalExpression(expression) {
@@ -3643,10 +4044,14 @@ class JavascriptParser extends Parser {
3643
4044
  }
3644
4045
 
3645
4046
  /**
4047
+ * Walk assignment expression.
3646
4048
  * @param {AssignmentExpression} expression assignment expression
3647
4049
  */
3648
4050
  walkAssignmentExpression(expression) {
3649
4051
  if (expression.left.type === "Identifier") {
4052
+ if (this._strictInModuleOutput) {
4053
+ this._checkStrictModeAssignTarget(expression.left.name, expression);
4054
+ }
3650
4055
  const renameIdentifier = this.getRenameIdentifier(expression.right);
3651
4056
  if (
3652
4057
  renameIdentifier &&
@@ -3718,24 +4123,23 @@ class JavascriptParser extends Parser {
3718
4123
  }
3719
4124
 
3720
4125
  /**
4126
+ * Walk conditional expression.
3721
4127
  * @param {ConditionalExpression} expression conditional expression
3722
4128
  */
3723
4129
  walkConditionalExpression(expression) {
3724
4130
  const result = this.hooks.expressionConditionalOperator.call(expression);
3725
4131
  if (result === undefined) {
3726
- const inGuard = this.hooks.collectGuards.call(expression.test);
3727
- if (inGuard) {
3728
- inGuard(() => {
3729
- this.walkExpression(expression.test);
3730
- this.walkExpression(expression.consequent);
3731
- });
3732
- } else {
3733
- this.walkExpression(expression.test);
3734
- this.walkExpression(expression.consequent);
3735
- }
4132
+ const guard = this.hooks.collectGuards.call(expression.test);
4133
+ this.walkExpression(expression.test);
4134
+ this.walkGuardedBranch(guard ? guard.consequent : undefined, () =>
4135
+ this.walkExpression(expression.consequent)
4136
+ );
3736
4137
 
3737
4138
  if (expression.alternate) {
3738
- this.walkExpression(expression.alternate);
4139
+ const alternate = expression.alternate;
4140
+ this.walkGuardedBranch(guard ? guard.alternate : undefined, () =>
4141
+ this.walkExpression(alternate)
4142
+ );
3739
4143
  }
3740
4144
  } else if (result) {
3741
4145
  this.walkExpression(expression.consequent);
@@ -3745,6 +4149,7 @@ class JavascriptParser extends Parser {
3745
4149
  }
3746
4150
 
3747
4151
  /**
4152
+ * Walk new expression.
3748
4153
  * @param {NewExpression} expression new expression
3749
4154
  */
3750
4155
  walkNewExpression(expression) {
@@ -3761,6 +4166,7 @@ class JavascriptParser extends Parser {
3761
4166
  }
3762
4167
 
3763
4168
  /**
4169
+ * Walk yield expression.
3764
4170
  * @param {YieldExpression} expression yield expression
3765
4171
  */
3766
4172
  walkYieldExpression(expression) {
@@ -3770,6 +4176,7 @@ class JavascriptParser extends Parser {
3770
4176
  }
3771
4177
 
3772
4178
  /**
4179
+ * Walk template literal.
3773
4180
  * @param {TemplateLiteral} expression template literal
3774
4181
  */
3775
4182
  walkTemplateLiteral(expression) {
@@ -3779,6 +4186,7 @@ class JavascriptParser extends Parser {
3779
4186
  }
3780
4187
 
3781
4188
  /**
4189
+ * Walk tagged template expression.
3782
4190
  * @param {TaggedTemplateExpression} expression tagged template expression
3783
4191
  */
3784
4192
  walkTaggedTemplateExpression(expression) {
@@ -3793,6 +4201,7 @@ class JavascriptParser extends Parser {
3793
4201
  }
3794
4202
 
3795
4203
  /**
4204
+ * Walk class expression.
3796
4205
  * @param {ClassExpression} expression the class expression
3797
4206
  */
3798
4207
  walkClassExpression(expression) {
@@ -3800,6 +4209,7 @@ class JavascriptParser extends Parser {
3800
4209
  }
3801
4210
 
3802
4211
  /**
4212
+ * Walk chain expression.
3803
4213
  * @param {ChainExpression} expression expression
3804
4214
  */
3805
4215
  walkChainExpression(expression) {
@@ -3815,6 +4225,7 @@ class JavascriptParser extends Parser {
3815
4225
  }
3816
4226
 
3817
4227
  /**
4228
+ * Processes the provided function expression.
3818
4229
  * @private
3819
4230
  * @param {FunctionExpression | ArrowFunctionExpression} functionExpression function expression
3820
4231
  * @param {(Expression | SpreadElement)[]} options options
@@ -3822,6 +4233,7 @@ class JavascriptParser extends Parser {
3822
4233
  */
3823
4234
  _walkIIFE(functionExpression, options, currentThis) {
3824
4235
  /**
4236
+ * Returns var info.
3825
4237
  * @param {Expression | SpreadElement} argOrThis arg or this
3826
4238
  * @returns {string | VariableInfo | undefined} var info
3827
4239
  */
@@ -3890,6 +4302,7 @@ class JavascriptParser extends Parser {
3890
4302
  }
3891
4303
 
3892
4304
  /**
4305
+ * Walk import expression.
3893
4306
  * @param {ImportExpression} expression import expression
3894
4307
  */
3895
4308
  walkImportExpression(expression) {
@@ -3900,18 +4313,13 @@ class JavascriptParser extends Parser {
3900
4313
  }
3901
4314
 
3902
4315
  /**
4316
+ * Walk call expression.
3903
4317
  * @param {CallExpression} expression expression
3904
4318
  */
3905
4319
  walkCallExpression(expression) {
3906
- /**
3907
- * @param {FunctionExpression | ArrowFunctionExpression} fn function
3908
- * @returns {boolean} true when simple function
3909
- */
3910
- const isSimpleFunction = (fn) =>
3911
- fn.params.every((p) => p.type === "Identifier");
3912
4320
  if (
3913
4321
  expression.callee.type === "MemberExpression" &&
3914
- expression.callee.object.type.endsWith("FunctionExpression") &&
4322
+ isFunctionExpression(expression.callee.object.type) &&
3915
4323
  !expression.callee.computed &&
3916
4324
  /** @type {boolean} */
3917
4325
  (
@@ -3934,7 +4342,7 @@ class JavascriptParser extends Parser {
3934
4342
  expression.arguments[0]
3935
4343
  );
3936
4344
  } else if (
3937
- expression.callee.type.endsWith("FunctionExpression") &&
4345
+ isFunctionExpression(expression.callee.type) &&
3938
4346
  isSimpleFunction(
3939
4347
  /** @type {FunctionExpression | ArrowFunctionExpression} */
3940
4348
  (expression.callee)
@@ -3949,21 +4357,29 @@ class JavascriptParser extends Parser {
3949
4357
  );
3950
4358
  } else {
3951
4359
  if (expression.callee.type === "MemberExpression") {
3952
- const exprInfo = this.getMemberExpressionInfo(
3953
- expression.callee,
3954
- ALLOWED_MEMBER_TYPES_CALL_EXPRESSION
3955
- );
3956
- if (exprInfo && exprInfo.type === "call") {
3957
- const result = this.callHooksForInfo(
3958
- this.hooks.callMemberChainOfCallMemberChain,
3959
- exprInfo.rootInfo,
3960
- expression,
3961
- exprInfo.getCalleeMembers(),
3962
- exprInfo.call,
3963
- exprInfo.getMembers(),
3964
- exprInfo.getMemberRanges()
4360
+ // callMemberChainOfCallMemberChain only applies to call-rooted
4361
+ // chains (e.g. `a().b()`); for the common identifier/this-rooted
4362
+ // callee the CALL lookup always rejects, so gate on the cheap root.
4363
+ if (
4364
+ this.getMemberExpressionRoot(expression.callee).type ===
4365
+ "CallExpression"
4366
+ ) {
4367
+ const exprInfo = this.getMemberExpressionInfo(
4368
+ expression.callee,
4369
+ ALLOWED_MEMBER_TYPES_CALL_EXPRESSION
3965
4370
  );
3966
- if (result === true) return;
4371
+ if (exprInfo && exprInfo.type === "call") {
4372
+ const result = this.callHooksForInfo(
4373
+ this.hooks.callMemberChainOfCallMemberChain,
4374
+ exprInfo.rootInfo,
4375
+ expression,
4376
+ exprInfo.getCalleeMembers(),
4377
+ exprInfo.call,
4378
+ exprInfo.getMembers(),
4379
+ exprInfo.getMemberRanges()
4380
+ );
4381
+ if (result === true) return;
4382
+ }
3967
4383
  }
3968
4384
  // import("./m").then(m => { ... })
3969
4385
  if (
@@ -3978,19 +4394,33 @@ class JavascriptParser extends Parser {
3978
4394
  if (result === true) return;
3979
4395
  }
3980
4396
  }
4397
+ if (
4398
+ expression.callee.type === "Identifier" &&
4399
+ this._evalIdentOwnTaps &&
4400
+ expression.callee.name !== "undefined" &&
4401
+ this._isDefinedPlainVariable(expression.callee.name)
4402
+ ) {
4403
+ // a defined, untagged callee can only evaluate to the fallthrough
4404
+ // result, so no call hooks apply — walk callee and arguments
4405
+ // directly, skipping the hook dispatch and its result object
4406
+ this.walkExpression(expression.callee);
4407
+ if (expression.arguments) this.walkExpressions(expression.arguments);
4408
+ return;
4409
+ }
3981
4410
  const callee = this.evaluateExpression(expression.callee);
3982
4411
  if (callee.isIdentifier()) {
4412
+ const members =
4413
+ /** @type {NonNullable<BasicEvaluatedExpression["getMembers"]>} */
4414
+ (callee.getMembers)();
3983
4415
  const result1 = this.callHooksForInfo(
3984
4416
  this.hooks.callMemberChain,
3985
4417
  /** @type {NonNullable<BasicEvaluatedExpression["rootInfo"]>} */
3986
4418
  (callee.rootInfo),
3987
4419
  expression,
3988
- /** @type {NonNullable<BasicEvaluatedExpression["getMembers"]>} */
3989
- (callee.getMembers)(),
4420
+ members,
3990
4421
  callee.getMembersOptionals
3991
4422
  ? callee.getMembersOptionals()
3992
- : /** @type {NonNullable<BasicEvaluatedExpression["getMembers"]>} */
3993
- (callee.getMembers)().map(() => false),
4423
+ : members.map(RETURN_FALSE),
3994
4424
  callee.getMemberRanges ? callee.getMemberRanges() : []
3995
4425
  );
3996
4426
  if (result1 === true) return;
@@ -4019,6 +4449,7 @@ class JavascriptParser extends Parser {
4019
4449
  }
4020
4450
 
4021
4451
  /**
4452
+ * Walk member expression.
4022
4453
  * @param {MemberExpression} expression member expression
4023
4454
  */
4024
4455
  walkMemberExpression(expression) {
@@ -4085,6 +4516,7 @@ class JavascriptParser extends Parser {
4085
4516
  }
4086
4517
 
4087
4518
  /**
4519
+ * Walk member expression with expression name.
4088
4520
  * @template R
4089
4521
  * @param {MemberExpression} expression member expression
4090
4522
  * @param {string} name name
@@ -4102,10 +4534,10 @@ class JavascriptParser extends Parser {
4102
4534
  if (expression.object.type === "MemberExpression") {
4103
4535
  // optimize the case where expression.object is a MemberExpression too.
4104
4536
  // we can keep info here when calling walkMemberExpression directly
4105
- const property =
4106
- /** @type {Identifier} */
4107
- (expression.property).name ||
4108
- `${/** @type {Literal} */ (expression.property).value}`;
4537
+ // Read the property from `members` (already extracted by
4538
+ // extractMemberExpressionChain) since the AST node may be a
4539
+ // TemplateLiteral, which has neither .name nor .value.
4540
+ const property = members[members.length - 1];
4109
4541
  name = name.slice(0, -property.length - 1);
4110
4542
  members.pop();
4111
4543
  const result = this.callHooksForInfo(
@@ -4128,6 +4560,7 @@ class JavascriptParser extends Parser {
4128
4560
  }
4129
4561
 
4130
4562
  /**
4563
+ * Walk this expression.
4131
4564
  * @param {ThisExpression} expression this expression
4132
4565
  */
4133
4566
  walkThisExpression(expression) {
@@ -4135,6 +4568,7 @@ class JavascriptParser extends Parser {
4135
4568
  }
4136
4569
 
4137
4570
  /**
4571
+ * Processes the provided expression.
4138
4572
  * @param {Identifier} expression identifier
4139
4573
  */
4140
4574
  walkIdentifier(expression) {
@@ -4142,6 +4576,7 @@ class JavascriptParser extends Parser {
4142
4576
  }
4143
4577
 
4144
4578
  /**
4579
+ * Walk meta property.
4145
4580
  * @param {MetaProperty} metaProperty meta property
4146
4581
  */
4147
4582
  walkMetaProperty(metaProperty) {
@@ -4149,6 +4584,7 @@ class JavascriptParser extends Parser {
4149
4584
  }
4150
4585
 
4151
4586
  /**
4587
+ * Call hooks for expression.
4152
4588
  * @template T
4153
4589
  * @template R
4154
4590
  * @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
@@ -4167,6 +4603,7 @@ class JavascriptParser extends Parser {
4167
4603
  }
4168
4604
 
4169
4605
  /**
4606
+ * Call hooks for expression with fallback.
4170
4607
  * @template T
4171
4608
  * @template R
4172
4609
  * @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
@@ -4201,6 +4638,7 @@ class JavascriptParser extends Parser {
4201
4638
  }
4202
4639
 
4203
4640
  /**
4641
+ * Call hooks for name.
4204
4642
  * @template T
4205
4643
  * @template R
4206
4644
  * @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
@@ -4209,16 +4647,17 @@ class JavascriptParser extends Parser {
4209
4647
  * @returns {R | undefined} result of hook
4210
4648
  */
4211
4649
  callHooksForName(hookMap, name, ...args) {
4212
- return this.callHooksForNameWithFallback(
4650
+ return this._callHooksForInfo(
4213
4651
  hookMap,
4214
- name,
4652
+ this.getVariableInfo(name),
4215
4653
  undefined,
4216
4654
  undefined,
4217
- ...args
4655
+ args
4218
4656
  );
4219
4657
  }
4220
4658
 
4221
4659
  /**
4660
+ * Call hooks for info.
4222
4661
  * @template T
4223
4662
  * @template R
4224
4663
  * @param {HookMap<SyncBailHook<T, R>>} hookMap hooks that should be called
@@ -4227,16 +4666,11 @@ class JavascriptParser extends Parser {
4227
4666
  * @returns {R | undefined} result of hook
4228
4667
  */
4229
4668
  callHooksForInfo(hookMap, info, ...args) {
4230
- return this.callHooksForInfoWithFallback(
4231
- hookMap,
4232
- info,
4233
- undefined,
4234
- undefined,
4235
- ...args
4236
- );
4669
+ return this._callHooksForInfo(hookMap, info, undefined, undefined, args);
4237
4670
  }
4238
4671
 
4239
4672
  /**
4673
+ * Call hooks for info with fallback.
4240
4674
  * @template T
4241
4675
  * @template R
4242
4676
  * @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
@@ -4247,6 +4681,23 @@ class JavascriptParser extends Parser {
4247
4681
  * @returns {R | undefined} result of hook
4248
4682
  */
4249
4683
  callHooksForInfoWithFallback(hookMap, info, fallback, defined, ...args) {
4684
+ return this._callHooksForInfo(hookMap, info, fallback, defined, args);
4685
+ }
4686
+
4687
+ /**
4688
+ * Shared core for the callHooksFor* helpers. Takes `args` as an already
4689
+ * collected array so the public wrappers each allocate it once instead of
4690
+ * re-collecting it through several rest-parameter layers (hot per identifier).
4691
+ * @template T
4692
+ * @template R
4693
+ * @param {HookMap<SyncBailHook<T, R>>} hookMap hooks that should be called
4694
+ * @param {ExportedVariableInfo} info variable info
4695
+ * @param {((name: string) => R | undefined) | undefined} fallback callback when variable is not handled by hooks
4696
+ * @param {((result?: string) => R | undefined) | undefined} defined callback when variable is defined
4697
+ * @param {AsArray<T>} args args for the hook
4698
+ * @returns {R | undefined} result of hook
4699
+ */
4700
+ _callHooksForInfo(hookMap, info, fallback, defined, args) {
4250
4701
  /** @type {string} */
4251
4702
  let name;
4252
4703
  if (typeof info === "string") {
@@ -4288,6 +4739,7 @@ class JavascriptParser extends Parser {
4288
4739
  }
4289
4740
 
4290
4741
  /**
4742
+ * Call hooks for name with fallback.
4291
4743
  * @template T
4292
4744
  * @template R
4293
4745
  * @param {HookMap<SyncBailHook<T, R>>} hookMap hooks the should be called
@@ -4298,16 +4750,17 @@ class JavascriptParser extends Parser {
4298
4750
  * @returns {R | undefined} result of hook
4299
4751
  */
4300
4752
  callHooksForNameWithFallback(hookMap, name, fallback, defined, ...args) {
4301
- return this.callHooksForInfoWithFallback(
4753
+ return this._callHooksForInfo(
4302
4754
  hookMap,
4303
4755
  this.getVariableInfo(name),
4304
4756
  fallback,
4305
4757
  defined,
4306
- ...args
4758
+ args
4307
4759
  );
4308
4760
  }
4309
4761
 
4310
4762
  /**
4763
+ * Processes the provided param.
4311
4764
  * @deprecated
4312
4765
  * @param {(string | Pattern | Property)[]} params scope params
4313
4766
  * @param {() => void} fn inner function
@@ -4328,9 +4781,7 @@ class JavascriptParser extends Parser {
4328
4781
 
4329
4782
  this.undefineVariable("this");
4330
4783
 
4331
- this.enterPatterns(params, (ident) => {
4332
- this.defineVariable(ident);
4333
- });
4784
+ this.enterPatterns(params, this._defineVariable);
4334
4785
 
4335
4786
  fn();
4336
4787
 
@@ -4338,6 +4789,7 @@ class JavascriptParser extends Parser {
4338
4789
  }
4339
4790
 
4340
4791
  /**
4792
+ * Processes the provided has thi.
4341
4793
  * @param {boolean} hasThis true, when this is defined
4342
4794
  * @param {Identifier[]} params scope params
4343
4795
  * @param {() => void} fn inner function
@@ -4360,9 +4812,7 @@ class JavascriptParser extends Parser {
4360
4812
  this.undefineVariable("this");
4361
4813
  }
4362
4814
 
4363
- this.enterPatterns(params, (ident) => {
4364
- this.defineVariable(ident);
4365
- });
4815
+ this.enterPatterns(params, this._defineVariable);
4366
4816
 
4367
4817
  fn();
4368
4818
 
@@ -4370,6 +4820,7 @@ class JavascriptParser extends Parser {
4370
4820
  }
4371
4821
 
4372
4822
  /**
4823
+ * Processes the provided has thi.
4373
4824
  * @param {boolean} hasThis true, when this is defined
4374
4825
  * @param {(Pattern | string)[]} params scope params
4375
4826
  * @param {() => void} fn inner function
@@ -4392,9 +4843,7 @@ class JavascriptParser extends Parser {
4392
4843
  this.undefineVariable("this");
4393
4844
  }
4394
4845
 
4395
- this.enterPatterns(params, (ident) => {
4396
- this.defineVariable(ident);
4397
- });
4846
+ this.enterPatterns(params, this._defineVariable);
4398
4847
 
4399
4848
  fn();
4400
4849
 
@@ -4402,6 +4851,7 @@ class JavascriptParser extends Parser {
4402
4851
  }
4403
4852
 
4404
4853
  /**
4854
+ * Processes the provided fn.
4405
4855
  * @param {() => void} fn inner function
4406
4856
  * @param {boolean} inExecutedPath executed state
4407
4857
  * @returns {void}
@@ -4431,37 +4881,34 @@ class JavascriptParser extends Parser {
4431
4881
  }
4432
4882
 
4433
4883
  /**
4884
+ * Processes the provided statement.
4434
4885
  * @param {(Directive | Statement | ModuleDeclaration)[]} statements statements
4435
4886
  */
4436
4887
  detectMode(statements) {
4437
- const isLiteral =
4438
- statements.length >= 1 &&
4439
- statements[0].type === "ExpressionStatement" &&
4440
- statements[0].expression.type === "Literal";
4888
+ const statement = statements.length >= 1 ? statements[0] : undefined;
4441
4889
  if (
4442
- isLiteral &&
4443
- /** @type {Literal} */
4444
- (/** @type {ExpressionStatement} */ (statements[0]).expression).value ===
4445
- "use strict"
4890
+ statement === undefined ||
4891
+ statement.type !== "ExpressionStatement" ||
4892
+ statement.expression.type !== "Literal"
4446
4893
  ) {
4447
- this.scope.isStrict = true;
4894
+ return;
4448
4895
  }
4449
- if (
4450
- isLiteral &&
4451
- /** @type {Literal} */
4452
- (/** @type {ExpressionStatement} */ (statements[0]).expression).value ===
4453
- "use asm"
4454
- ) {
4896
+ const value = /** @type {Literal} */ (statement.expression).value;
4897
+ if (value === "use strict") {
4898
+ this.scope.isStrict = true;
4899
+ } else if (value === "use asm") {
4455
4900
  this.scope.isAsmJs = true;
4456
4901
  }
4457
4902
  }
4458
4903
 
4459
4904
  /**
4905
+ * Processes the provided pattern.
4460
4906
  * @param {(string | Pattern | Property)[]} patterns patterns
4461
4907
  * @param {OnIdentString} onIdent on ident callback
4462
4908
  */
4463
4909
  enterPatterns(patterns, onIdent) {
4464
- for (const pattern of patterns) {
4910
+ for (let i = 0, len = patterns.length; i < len; i++) {
4911
+ const pattern = patterns[i];
4465
4912
  if (typeof pattern !== "string") {
4466
4913
  this.enterPattern(pattern, onIdent);
4467
4914
  } else if (pattern) {
@@ -4471,27 +4918,20 @@ class JavascriptParser extends Parser {
4471
4918
  }
4472
4919
 
4473
4920
  /**
4921
+ * Processes the provided pattern.
4474
4922
  * @param {Pattern | Property} pattern pattern
4475
4923
  * @param {OnIdent} onIdent on ident callback
4476
4924
  */
4477
4925
  enterPattern(pattern, onIdent) {
4478
4926
  if (!pattern) return;
4927
+ // plain identifiers dominate bindings, so match them first
4479
4928
  switch (pattern.type) {
4480
- case "ArrayPattern":
4481
- this.enterArrayPattern(pattern, onIdent);
4482
- break;
4483
- case "AssignmentPattern":
4484
- this.enterAssignmentPattern(pattern, onIdent);
4485
- break;
4486
4929
  case "Identifier":
4487
4930
  this.enterIdentifier(pattern, onIdent);
4488
4931
  break;
4489
4932
  case "ObjectPattern":
4490
4933
  this.enterObjectPattern(pattern, onIdent);
4491
4934
  break;
4492
- case "RestElement":
4493
- this.enterRestElement(pattern, onIdent);
4494
- break;
4495
4935
  case "Property":
4496
4936
  if (pattern.shorthand && pattern.value.type === "Identifier") {
4497
4937
  this.scope.inShorthand = pattern.value.name;
@@ -4501,10 +4941,20 @@ class JavascriptParser extends Parser {
4501
4941
  this.enterPattern(/** @type {Pattern} */ (pattern.value), onIdent);
4502
4942
  }
4503
4943
  break;
4944
+ case "ArrayPattern":
4945
+ this.enterArrayPattern(pattern, onIdent);
4946
+ break;
4947
+ case "AssignmentPattern":
4948
+ this.enterAssignmentPattern(pattern, onIdent);
4949
+ break;
4950
+ case "RestElement":
4951
+ this.enterRestElement(pattern, onIdent);
4952
+ break;
4504
4953
  }
4505
4954
  }
4506
4955
 
4507
4956
  /**
4957
+ * Processes the provided pattern.
4508
4958
  * @param {Identifier} pattern identifier pattern
4509
4959
  * @param {OnIdent} onIdent callback
4510
4960
  */
@@ -4515,6 +4965,7 @@ class JavascriptParser extends Parser {
4515
4965
  }
4516
4966
 
4517
4967
  /**
4968
+ * Enter object pattern.
4518
4969
  * @param {ObjectPattern} pattern object pattern
4519
4970
  * @param {OnIdent} onIdent callback
4520
4971
  */
@@ -4530,6 +4981,7 @@ class JavascriptParser extends Parser {
4530
4981
  }
4531
4982
 
4532
4983
  /**
4984
+ * Enter array pattern.
4533
4985
  * @param {ArrayPattern} pattern object pattern
4534
4986
  * @param {OnIdent} onIdent callback
4535
4987
  */
@@ -4548,6 +5000,7 @@ class JavascriptParser extends Parser {
4548
5000
  }
4549
5001
 
4550
5002
  /**
5003
+ * Enter rest element.
4551
5004
  * @param {RestElement} pattern object pattern
4552
5005
  * @param {OnIdent} onIdent callback
4553
5006
  */
@@ -4556,6 +5009,7 @@ class JavascriptParser extends Parser {
4556
5009
  }
4557
5010
 
4558
5011
  /**
5012
+ * Enter assignment pattern.
4559
5013
  * @param {AssignmentPattern} pattern object pattern
4560
5014
  * @param {OnIdent} onIdent callback
4561
5015
  */
@@ -4564,6 +5018,7 @@ class JavascriptParser extends Parser {
4564
5018
  }
4565
5019
 
4566
5020
  /**
5021
+ * Evaluate expression.
4567
5022
  * @param {Expression | SpreadElement | PrivateIdentifier | Super} expression expression node
4568
5023
  * @returns {BasicEvaluatedExpression} evaluation result
4569
5024
  */
@@ -4582,12 +5037,13 @@ class JavascriptParser extends Parser {
4582
5037
  console.warn(err);
4583
5038
  // ignore error
4584
5039
  }
4585
- return new BasicEvaluatedExpression()
4586
- .setRange(/** @type {Range} */ (expression.range))
4587
- .setExpression(expression);
5040
+ // no setRange: the range is served lazily from the expression on first
5041
+ // read, so plain results don't materialize the node's range array at all
5042
+ return new BasicEvaluatedExpression().setExpression(expression);
4588
5043
  }
4589
5044
 
4590
5045
  /**
5046
+ * Returns parsed string.
4591
5047
  * @param {Expression} expression expression
4592
5048
  * @returns {string} parsed string
4593
5049
  */
@@ -4612,6 +5068,7 @@ class JavascriptParser extends Parser {
4612
5068
  /** @typedef {{ range?: Range, value: string, code: boolean, conditional: false | CalculatedStringResult[] }} CalculatedStringResult */
4613
5069
 
4614
5070
  /**
5071
+ * Parses calculated string.
4615
5072
  * @param {Expression} expression expression
4616
5073
  * @returns {CalculatedStringResult} result
4617
5074
  */
@@ -4701,6 +5158,7 @@ class JavascriptParser extends Parser {
4701
5158
  }
4702
5159
 
4703
5160
  /**
5161
+ * Parses the provided source and updates the parser state.
4704
5162
  * @param {string | Buffer | PreparsedAst} source the source to parse
4705
5163
  * @param {ParserState} state the parser state
4706
5164
  * @returns {ParserState} the parser state
@@ -4712,35 +5170,29 @@ class JavascriptParser extends Parser {
4712
5170
 
4713
5171
  if (Buffer.isBuffer(source)) {
4714
5172
  source = source.toString("utf8");
5173
+ // Keep `state.source` as a string so downstream walkers can read
5174
+ // the original text without re-decoding the Buffer on every use.
5175
+ state.source = source;
4715
5176
  }
4716
5177
 
4717
5178
  let ast;
4718
5179
  /** @type {Comment[]} */
4719
5180
  let comments;
4720
- /** @type {Set<number>} */
4721
- let semicolons;
4722
5181
 
4723
5182
  if (typeof source === "object") {
4724
- semicolons = new Set();
4725
-
4726
5183
  ast = /** @type {Program} */ (source);
4727
5184
  comments = source.comments;
4728
- if (source.semicolons) {
4729
- // Forward semicolon information from the preparsed AST if present
4730
- // This ensures the output is consistent with that of a fresh AST
4731
- for (const pos of source.semicolons) {
4732
- semicolons.add(pos);
4733
- }
4734
- }
4735
5185
  } else {
4736
- ({ ast, comments, semicolons } = JavascriptParser._parse(
5186
+ ({ ast, comments } = JavascriptParser._parse(
4737
5187
  source,
4738
5188
  {
4739
5189
  sourceType: this.sourceType,
4740
- locations: true,
5190
+ // line/column locations are derived from node offsets via
5191
+ // getLocation — parsers never need to track them
5192
+ locations: false,
4741
5193
  ranges: true,
4742
5194
  comments: true,
4743
- semicolons: true
5195
+ importPhases: this.options.importPhases === true
4744
5196
  },
4745
5197
  this.options.parse
4746
5198
  ));
@@ -4752,6 +5204,18 @@ class JavascriptParser extends Parser {
4752
5204
  const oldSemicolons = this.semicolons;
4753
5205
  const oldStatementPath = this.statementPath;
4754
5206
  const oldPrevStatement = this.prevStatement;
5207
+ const oldStrictInModuleOutput = this._strictInModuleOutput;
5208
+ const oldSource = this._source;
5209
+ const oldLineStarts = this._lineStarts;
5210
+ // a preparsed AST carries no text, but the build passes the module
5211
+ // source in the state — offsets still map for it
5212
+ this._source =
5213
+ typeof source === "string"
5214
+ ? source
5215
+ : typeof state.source === "string"
5216
+ ? state.source
5217
+ : undefined;
5218
+ this._lineStarts = undefined;
4755
5219
  this.scope = {
4756
5220
  topLevelScope: true,
4757
5221
  inTry: false,
@@ -4764,13 +5228,34 @@ class JavascriptParser extends Parser {
4764
5228
  };
4765
5229
  this.state = state;
4766
5230
  this.comments = comments;
4767
- this.semicolons = semicolons;
5231
+ this.semicolons = undefined;
5232
+ // evaluating a defined, untagged identifier can only fall through when
5233
+ // every `evaluate.for("Identifier")` tap is the parser's own — plugins
5234
+ // tapping or intercepting it disable the callee/rename fast paths
5235
+ const identifierEvalHook = this.hooks.evaluate.get("Identifier");
5236
+ this._evalIdentOwnTaps =
5237
+ identifierEvalHook !== undefined &&
5238
+ identifierEvalHook.interceptors.length === 0 &&
5239
+ identifierEvalHook.taps.every((tap) => tap.name === CLASS_NAME);
4768
5240
  this.statementPath = [];
4769
5241
  this.prevStatement = undefined;
5242
+ // The output is emitted as strict-mode ESM, but this module was parsed as
5243
+ // a loose script — acorn skipped the strict early errors that will break
5244
+ // the bundle at runtime. Enables the strict-mode diagnostics below.
5245
+ this._strictInModuleOutput =
5246
+ this.options.strictModeViolations !== false &&
5247
+ state.compilation !== undefined &&
5248
+ state.compilation.runtimeTemplate.isModule();
4770
5249
  if (this.hooks.program.call(ast, comments) === undefined) {
4771
5250
  this.destructuringAssignmentProperties = new WeakMap();
4772
5251
  this.detectMode(ast.body);
5252
+ // a strict program (ESM source, `"use strict"`) keeps its behavior in
5253
+ // strict output — drop the flag so the walk pays no per-node checks
5254
+ if (this._strictInModuleOutput && this.scope.isStrict) {
5255
+ this._strictInModuleOutput = false;
5256
+ }
4773
5257
  this.modulePreWalkStatements(ast.body);
5258
+ this.prevStatement = undefined;
4774
5259
  this.preWalkStatements(ast.body);
4775
5260
  this.prevStatement = undefined;
4776
5261
  this.blockPreWalkStatements(ast.body);
@@ -4785,19 +5270,54 @@ class JavascriptParser extends Parser {
4785
5270
  this.semicolons = oldSemicolons;
4786
5271
  this.statementPath = oldStatementPath;
4787
5272
  this.prevStatement = oldPrevStatement;
5273
+ this._strictInModuleOutput = oldStrictInModuleOutput;
5274
+ // release — these retain the whole source string and its line table
5275
+ this._source = oldSource;
5276
+ this._lineStarts = oldLineStarts;
4788
5277
  return state;
4789
5278
  }
4790
5279
 
4791
5280
  /**
5281
+ * Returns evaluation result.
4792
5282
  * @param {string} source source code
4793
5283
  * @returns {BasicEvaluatedExpression} evaluation result
4794
5284
  */
4795
5285
  evaluate(source) {
4796
- const { ast } = JavascriptParser._parse(
4797
- `(${source})`,
4798
- { sourceType: this.sourceType },
4799
- this.options.parse
4800
- );
5286
+ const importPhases = this.options.importPhases === true;
5287
+ const compilation = this.state && this.state.compilation;
5288
+ /** @type {Map<string, Program> | undefined} */
5289
+ let cache;
5290
+ // custom parse functions are not necessarily pure, do not cache for them
5291
+ if (compilation !== undefined && typeof this.options.parse !== "function") {
5292
+ cache = evaluateAstCaches.get(compilation);
5293
+ if (cache === undefined) {
5294
+ cache = new Map();
5295
+ evaluateAstCaches.set(compilation, cache);
5296
+ }
5297
+ }
5298
+ const cacheKey =
5299
+ cache === undefined
5300
+ ? undefined
5301
+ : `${this.sourceType}|${importPhases}|${source}`;
5302
+ let ast =
5303
+ cacheKey === undefined
5304
+ ? undefined
5305
+ : /** @type {Map<string, Program>} */ (cache).get(cacheKey);
5306
+ if (ast === undefined) {
5307
+ ({ ast } = JavascriptParser._parse(
5308
+ `(${source})`,
5309
+ {
5310
+ sourceType: this.sourceType,
5311
+ importPhases
5312
+ },
5313
+ this.options.parse
5314
+ ));
5315
+ if (cacheKey !== undefined) {
5316
+ const map = /** @type {Map<string, Program>} */ (cache);
5317
+ if (map.size >= EVALUATE_AST_CACHE_LIMIT) map.clear();
5318
+ map.set(cacheKey, ast);
5319
+ }
5320
+ }
4801
5321
  if (ast.body.length !== 1 || ast.body[0].type !== "ExpressionStatement") {
4802
5322
  throw new Error("evaluate: Source is not a expression");
4803
5323
  }
@@ -4805,6 +5325,7 @@ class JavascriptParser extends Parser {
4805
5325
  }
4806
5326
 
4807
5327
  /**
5328
+ * Checks whether this javascript parser is pure.
4808
5329
  * @param {Expression | Declaration | PrivateIdentifier | MaybeNamedFunctionDeclaration | MaybeNamedClassDeclaration | null | undefined} expr an expression
4809
5330
  * @param {number} commentsStartPos source position from which annotation comments are checked
4810
5331
  * @returns {boolean} true, when the expression is pure
@@ -4816,7 +5337,6 @@ class JavascriptParser extends Parser {
4816
5337
  .call(expr, commentsStartPos);
4817
5338
  if (typeof result === "boolean") return result;
4818
5339
  switch (expr.type) {
4819
- // TODO handle more cases
4820
5340
  case "ClassDeclaration":
4821
5341
  case "ClassExpression": {
4822
5342
  if (expr.body.type !== "ClassBody") return false;
@@ -4869,9 +5389,15 @@ class JavascriptParser extends Parser {
4869
5389
  });
4870
5390
  }
4871
5391
  case "TemplateLiteral":
4872
- return expr.expressions.every((expr) =>
4873
- this.isPure(expr, /** @type {Range} */ (expr.range)[0])
4874
- );
5392
+ // Thread `commentsStartPos` through the interpolations so a
5393
+ // /*#__PURE__*/ comment that sits inside `${ ... }` (or before
5394
+ // the first interpolation) is part of the scanned range when
5395
+ // the inner expression's purity is evaluated.
5396
+ return expr.expressions.every((e) => {
5397
+ const pureFlag = this.isPure(e, commentsStartPos);
5398
+ commentsStartPos = /** @type {Range} */ (e.range)[1];
5399
+ return pureFlag;
5400
+ });
4875
5401
  case "FunctionDeclaration":
4876
5402
  case "FunctionExpression":
4877
5403
  case "ArrowFunctionExpression":
@@ -4886,6 +5412,78 @@ class JavascriptParser extends Parser {
4886
5412
  this.isPure(decl.init, /** @type {Range} */ (decl.range)[0])
4887
5413
  );
4888
5414
 
5415
+ case "ArrayExpression":
5416
+ return expr.elements.every((element) => {
5417
+ if (element === null) return true;
5418
+ if (element.type === "SpreadElement") return false;
5419
+ const pureFlag = this.isPure(element, commentsStartPos);
5420
+ commentsStartPos = /** @type {Range} */ (element.range)[1];
5421
+ return pureFlag;
5422
+ });
5423
+
5424
+ case "ObjectExpression": {
5425
+ return expr.properties.every((property) => {
5426
+ if (property.type === "SpreadElement") return false;
5427
+
5428
+ if (
5429
+ property.computed &&
5430
+ !this.isPure(property.key, commentsStartPos)
5431
+ ) {
5432
+ return false;
5433
+ }
5434
+
5435
+ const pureFlag = this.isPure(
5436
+ /** @type {Exclude<Property["value"], AssignmentPattern | ObjectPattern | ArrayPattern | RestElement>} */
5437
+ (property.value),
5438
+ /** @type {Range} */ (property.key.range)[1]
5439
+ );
5440
+ commentsStartPos = /** @type {Range} */ (property.range)[1];
5441
+ return pureFlag;
5442
+ });
5443
+ }
5444
+
5445
+ case "ChainExpression":
5446
+ return this.isPure(expr.expression, commentsStartPos);
5447
+
5448
+ case "UnaryExpression":
5449
+ // Safe unary operators — produce their result without invoking
5450
+ // user code on the operand:
5451
+ // - `typeof` returns a type tag and never throws, even for
5452
+ // undeclared identifiers; no coercion.
5453
+ // - `void` evaluates the operand and discards it, returning
5454
+ // `undefined`; pure iff the operand is pure.
5455
+ // - `!` coerces via ToBoolean, which is defined to not call
5456
+ // any user code (objects → true, etc.).
5457
+ // Other operators (`+`, `-`, `~`, `delete`) fall through to
5458
+ // the generic evaluator which can still recognize literal
5459
+ // cases (e.g. `-1`, `+5`).
5460
+ if (
5461
+ expr.operator === "typeof" ||
5462
+ expr.operator === "void" ||
5463
+ expr.operator === "!"
5464
+ ) {
5465
+ return this.isPure(expr.argument, commentsStartPos);
5466
+ }
5467
+ break;
5468
+
5469
+ case "MetaProperty":
5470
+ return true;
5471
+
5472
+ case "BinaryExpression":
5473
+ // Strict (in)equality compares without coercion and never invokes
5474
+ // user code on its operands, so the result is pure iff both sides
5475
+ // are pure. All other binary operators may invoke `valueOf` /
5476
+ // `toString` / `[Symbol.hasInstance]` / Proxy traps and fall through
5477
+ // to the generic evaluator, which can still recognize the cases
5478
+ // where both sides evaluate to known primitive literals.
5479
+ if (expr.operator === "===" || expr.operator === "!==") {
5480
+ return (
5481
+ this.isPure(expr.left, commentsStartPos) &&
5482
+ this.isPure(expr.right, /** @type {Range} */ (expr.left.range)[1])
5483
+ );
5484
+ }
5485
+ break;
5486
+
4889
5487
  case "ConditionalExpression":
4890
5488
  return (
4891
5489
  this.isPure(expr.test, commentsStartPos) &&
@@ -4921,7 +5519,7 @@ class JavascriptParser extends Parser {
4921
5519
  ]).some(
4922
5520
  (comment) =>
4923
5521
  comment.type === "Block" &&
4924
- /^\s*(?:#|@)__PURE__\s*$/.test(comment.value)
5522
+ CompilerHintNotationRegExp.Pure.test(comment.value)
4925
5523
  );
4926
5524
  if (!pureFlag) return false;
4927
5525
  commentsStartPos = /** @type {Range} */ (expr.callee.range)[1];
@@ -4932,40 +5530,177 @@ class JavascriptParser extends Parser {
4932
5530
  return pureFlag;
4933
5531
  });
4934
5532
  }
5533
+
5534
+ case "NewExpression": {
5535
+ const pureFlag =
5536
+ /** @type {Range} */ (expr.range)[0] - commentsStartPos > 12 &&
5537
+ this.getComments([
5538
+ commentsStartPos,
5539
+ /** @type {Range} */ (expr.range)[0]
5540
+ ]).some(
5541
+ (comment) =>
5542
+ comment.type === "Block" &&
5543
+ CompilerHintNotationRegExp.Pure.test(comment.value)
5544
+ );
5545
+ if (!pureFlag) return false;
5546
+ commentsStartPos = /** @type {Range} */ (expr.callee.range)[1];
5547
+ return expr.arguments.every((arg) => {
5548
+ if (arg.type === "SpreadElement") return false;
5549
+ const pureFlag = this.isPure(arg, commentsStartPos);
5550
+ commentsStartPos = /** @type {Range} */ (arg.range)[1];
5551
+ return pureFlag;
5552
+ });
5553
+ }
5554
+
5555
+ case "TaggedTemplateExpression": {
5556
+ const pureFlag =
5557
+ /** @type {Range} */ (expr.range)[0] - commentsStartPos > 12 &&
5558
+ this.getComments([
5559
+ commentsStartPos,
5560
+ /** @type {Range} */ (expr.range)[0]
5561
+ ]).some(
5562
+ (comment) =>
5563
+ comment.type === "Block" &&
5564
+ CompilerHintNotationRegExp.Pure.test(comment.value)
5565
+ );
5566
+ if (!pureFlag) return false;
5567
+ commentsStartPos = /** @type {Range} */ (expr.tag.range)[1];
5568
+ return expr.quasi.expressions.every((e) => {
5569
+ const pureFlag = this.isPure(e, commentsStartPos);
5570
+ commentsStartPos = /** @type {Range} */ (e.range)[1];
5571
+ return pureFlag;
5572
+ });
5573
+ }
4935
5574
  }
4936
5575
  const evaluated = this.evaluateExpression(expr);
4937
5576
  return !evaluated.couldHaveSideEffects();
4938
5577
  }
4939
5578
 
4940
5579
  /**
5580
+ * Returns the location of a node or comment, computed from its offsets so
5581
+ * ASTs from parsers without location support work too. Falls back to the
5582
+ * node's own `loc` only when no source text is available (preparsed ASTs).
5583
+ * Offsets can only be mapped while parsing — callbacks deferred past the
5584
+ * `parse()` call must take the location upfront.
5585
+ * @param {{ start?: number, end?: number, range?: Range, loc?: SourceLocation | null }} node node or comment
5586
+ * @returns {DependencyLocation} location of the node
5587
+ */
5588
+ getLocation(node) {
5589
+ const source = this._source;
5590
+ if (source !== undefined) {
5591
+ const start =
5592
+ typeof node.start === "number"
5593
+ ? node.start
5594
+ : node.range
5595
+ ? node.range[0]
5596
+ : undefined;
5597
+ if (start !== undefined) {
5598
+ const end =
5599
+ typeof node.end === "number"
5600
+ ? node.end
5601
+ : node.range
5602
+ ? node.range[1]
5603
+ : start;
5604
+ const lineStarts =
5605
+ this._lineStarts || (this._lineStarts = buildLineStarts(source));
5606
+ return {
5607
+ start: positionAt(lineStarts, start),
5608
+ end: positionAt(lineStarts, end)
5609
+ };
5610
+ }
5611
+ }
5612
+ return /** @type {DependencyLocation} */ (node.loc);
5613
+ }
5614
+
5615
+ /**
5616
+ * Returns comments in the range.
4941
5617
  * @param {Range} range range
4942
5618
  * @returns {Comment[]} comments in the range
4943
5619
  */
4944
5620
  getComments(range) {
4945
- const [rangeStart, rangeEnd] = range;
4946
- /**
4947
- * @param {Comment} comment comment
4948
- * @param {number} needle needle
4949
- * @returns {number} compared
4950
- */
4951
- const compare = (comment, needle) =>
4952
- /** @type {Range} */ (comment.range)[0] - needle;
4953
- const comments = /** @type {Comment[]} */ (this.comments);
4954
- let idx = binarySearchBounds.ge(comments, rangeStart, compare);
4955
- /** @type {Comment[]} */
4956
- const commentsInRange = [];
4957
- while (
4958
- comments[idx] &&
4959
- /** @type {Range} */ (comments[idx].range)[1] <= rangeEnd
4960
- ) {
4961
- commentsInRange.push(comments[idx]);
4962
- idx++;
5621
+ return getCommentsInRange(
5622
+ /** @type {(Comment & { range: [number, number] })[]} */ (this.comments),
5623
+ range
5624
+ );
5625
+ }
5626
+
5627
+ /**
5628
+ * First significant char code at or after `pos`, skipping whitespace and
5629
+ * comments, or -1 at end of source.
5630
+ * @param {string} source source text
5631
+ * @param {number} pos start offset
5632
+ * @returns {number} char code of the next token, or -1
5633
+ */
5634
+ _nextTokenCharCode(source, pos) {
5635
+ const len = source.length;
5636
+ for (let i = pos; i < len; i++) {
5637
+ const c = source.charCodeAt(i);
5638
+ // whitespace and line terminators acorn skips between tokens
5639
+ if (
5640
+ c === 32 ||
5641
+ c === 9 ||
5642
+ c === 10 ||
5643
+ c === 13 ||
5644
+ c === 11 ||
5645
+ c === 12 ||
5646
+ c === 0xa0 ||
5647
+ c === 0xfeff ||
5648
+ c === 0x2028 ||
5649
+ c === 0x2029
5650
+ ) {
5651
+ continue;
5652
+ }
5653
+ if (c === 47 /* / */) {
5654
+ const n = source.charCodeAt(i + 1);
5655
+ if (n === 47 /* / */) {
5656
+ i += 2;
5657
+ while (i < len) {
5658
+ const cc = source.charCodeAt(i);
5659
+ if (cc === 10 || cc === 13 || cc === 0x2028 || cc === 0x2029) break;
5660
+ i++;
5661
+ }
5662
+ continue;
5663
+ }
5664
+ if (n === 42 /* * */) {
5665
+ i += 2;
5666
+ while (
5667
+ i < len &&
5668
+ !(source.charCodeAt(i) === 42 && source.charCodeAt(i + 1) === 47)
5669
+ ) {
5670
+ i++;
5671
+ }
5672
+ i++;
5673
+ continue;
5674
+ }
5675
+ }
5676
+ return c;
4963
5677
  }
5678
+ return -1;
5679
+ }
4964
5680
 
4965
- return commentsInRange;
5681
+ /**
5682
+ * Whether a statement ending at `pos` relies on ASI (no real separator).
5683
+ * Derived from the source text unless overridden by set/unsetAsiPosition.
5684
+ * A statement terminated by a real `;` or continued by a `,` (a sequence
5685
+ * element) is not an ASI position; anything else (newline, `}`, eof) is.
5686
+ * @param {number} pos statement end offset
5687
+ * @returns {boolean} true when ASI inserts a semicolon at this position
5688
+ */
5689
+ _isAsiPosition(pos) {
5690
+ if (this.semicolons !== undefined) {
5691
+ const override = this.semicolons.get(pos);
5692
+ if (override !== undefined) return override;
5693
+ }
5694
+ const source = this._source;
5695
+ if (source === undefined) return true;
5696
+ // a real semicolon is the statement's last char (exclusive end at pos)
5697
+ if (source.charCodeAt(pos - 1) === 59 /* ; */) return false;
5698
+ const next = this._nextTokenCharCode(source, pos);
5699
+ return next !== 44 /* , */ && next !== 59; /* ; */
4966
5700
  }
4967
5701
 
4968
5702
  /**
5703
+ * Checks whether this javascript parser is asi position.
4969
5704
  * @param {number} pos source code position
4970
5705
  * @returns {boolean} true when a semicolon has been inserted before this position, false if not
4971
5706
  */
@@ -4981,37 +5716,37 @@ class JavascriptParser extends Parser {
4981
5716
 
4982
5717
  return (
4983
5718
  // Either asking directly for the end position of the current statement
4984
- (range[1] === pos &&
4985
- /** @type {Set<number>} */ (this.semicolons).has(pos)) ||
5719
+ (range[1] === pos && this._isAsiPosition(pos)) ||
4986
5720
  // Or asking for the start position of the current statement,
4987
5721
  // here we have to check multiple things
4988
5722
  (range[0] === pos &&
4989
5723
  // is there a previous statement which might be relevant?
4990
5724
  this.prevStatement !== undefined &&
4991
5725
  // is the end position of the previous statement an ASI position?
4992
- /** @type {Set<number>} */ (this.semicolons).has(
4993
- /** @type {Range} */ (this.prevStatement.range)[1]
4994
- ))
5726
+ this._isAsiPosition(/** @type {Range} */ (this.prevStatement.range)[1]))
4995
5727
  );
4996
5728
  }
4997
5729
 
4998
5730
  /**
5731
+ * Updates asi position using the provided po.
4999
5732
  * @param {number} pos source code position
5000
5733
  * @returns {void}
5001
5734
  */
5002
5735
  setAsiPosition(pos) {
5003
- /** @type {Set<number>} */ (this.semicolons).add(pos);
5736
+ (this.semicolons || (this.semicolons = new Map())).set(pos, true);
5004
5737
  }
5005
5738
 
5006
5739
  /**
5740
+ * Unset asi position.
5007
5741
  * @param {number} pos source code position
5008
5742
  * @returns {void}
5009
5743
  */
5010
5744
  unsetAsiPosition(pos) {
5011
- /** @type {Set<number>} */ (this.semicolons).delete(pos);
5745
+ (this.semicolons || (this.semicolons = new Map())).set(pos, false);
5012
5746
  }
5013
5747
 
5014
5748
  /**
5749
+ * Checks whether this javascript parser is statement level expression.
5015
5750
  * @param {Expression} expr expression
5016
5751
  * @returns {boolean} true, when the expression is a statement level expression
5017
5752
  */
@@ -5030,6 +5765,7 @@ class JavascriptParser extends Parser {
5030
5765
  }
5031
5766
 
5032
5767
  /**
5768
+ * Returns tag data.
5033
5769
  * @param {string} name name
5034
5770
  * @param {Tag} tag tag info
5035
5771
  * @returns {TagData | undefined} tag data
@@ -5046,6 +5782,7 @@ class JavascriptParser extends Parser {
5046
5782
  }
5047
5783
 
5048
5784
  /**
5785
+ * Processes the provided name.
5049
5786
  * @param {string} name name
5050
5787
  * @param {Tag} tag tag info
5051
5788
  * @param {TagData=} data data
@@ -5083,6 +5820,7 @@ class JavascriptParser extends Parser {
5083
5820
  }
5084
5821
 
5085
5822
  /**
5823
+ * Processes the provided name.
5086
5824
  * @param {string} name variable name
5087
5825
  */
5088
5826
  defineVariable(name) {
@@ -5098,6 +5836,7 @@ class JavascriptParser extends Parser {
5098
5836
  }
5099
5837
 
5100
5838
  /**
5839
+ * Processes the provided name.
5101
5840
  * @param {string} name variable name
5102
5841
  */
5103
5842
  undefineVariable(name) {
@@ -5105,6 +5844,7 @@ class JavascriptParser extends Parser {
5105
5844
  }
5106
5845
 
5107
5846
  /**
5847
+ * Checks whether this javascript parser is variable defined.
5108
5848
  * @param {string} name variable name
5109
5849
  * @returns {boolean} true, when variable is defined
5110
5850
  */
@@ -5118,6 +5858,23 @@ class JavascriptParser extends Parser {
5118
5858
  }
5119
5859
 
5120
5860
  /**
5861
+ * Whether evaluating an identifier of this name can only fall through:
5862
+ * the exact negative of the identifier evaluator's `getInfo` — defined in
5863
+ * some scope and neither free nor tagged nor carrying tag info.
5864
+ * @param {string} name variable name
5865
+ * @returns {boolean} true when the identifier evaluates to nothing
5866
+ */
5867
+ _isDefinedPlainVariable(name) {
5868
+ const info = this.scope.definitions.get(name);
5869
+ if (info === undefined) return false;
5870
+ if (info instanceof VariableInfo) {
5871
+ return !(info.isFree() || info.isTagged() || info.tagInfo !== undefined);
5872
+ }
5873
+ return true;
5874
+ }
5875
+
5876
+ /**
5877
+ * Gets variable info.
5121
5878
  * @param {string} name variable name
5122
5879
  * @returns {ExportedVariableInfo} info for this variable
5123
5880
  */
@@ -5130,6 +5887,7 @@ class JavascriptParser extends Parser {
5130
5887
  }
5131
5888
 
5132
5889
  /**
5890
+ * Updates variable using the provided name.
5133
5891
  * @param {string} name variable name
5134
5892
  * @param {ExportedVariableInfo} variableInfo new info for this variable
5135
5893
  * @returns {void}
@@ -5155,6 +5913,7 @@ class JavascriptParser extends Parser {
5155
5913
  }
5156
5914
 
5157
5915
  /**
5916
+ * Evaluated variable.
5158
5917
  * @param {TagInfo} tagInfo tag info
5159
5918
  * @returns {VariableInfo} variable info
5160
5919
  */
@@ -5168,49 +5927,54 @@ class JavascriptParser extends Parser {
5168
5927
  }
5169
5928
 
5170
5929
  /**
5930
+ * Parses comment options.
5171
5931
  * @param {Range} range range of the comment
5172
5932
  * @returns {{ options: Record<string, EXPECTED_ANY> | null, errors: (Error & { comment: Comment })[] | null }} result
5173
5933
  */
5174
5934
  parseCommentOptions(range) {
5175
- const comments = this.getComments(range);
5176
- if (comments.length === 0) {
5177
- return EMPTY_COMMENT_OPTIONS;
5178
- }
5179
- /** @type {Record<string, EXPECTED_ANY>} */
5180
- const options = {};
5181
- /** @type {(Error & { comment: Comment })[]} */
5182
- const errors = [];
5183
- for (const comment of comments) {
5184
- const { value } = comment;
5185
- if (value && webpackCommentRegExp.test(value)) {
5186
- // try compile only if webpack options comment is present
5187
- try {
5188
- for (let [key, val] of Object.entries(
5189
- vm.runInContext(
5190
- `(function(){return {${value}};})()`,
5191
- this.magicCommentContext
5192
- )
5193
- )) {
5194
- if (typeof val === "object" && val !== null) {
5195
- val =
5196
- val.constructor.name === "RegExp"
5197
- ? new RegExp(val)
5198
- : JSON.parse(JSON.stringify(val));
5199
- }
5200
- options[key] = val;
5201
- }
5202
- } catch (err) {
5203
- const newErr = new Error(String(/** @type {Error} */ (err).message));
5204
- newErr.stack = String(/** @type {Error} */ (err).stack);
5205
- Object.assign(newErr, { comment });
5206
- errors.push(/** @type {(Error & { comment: Comment })} */ (newErr));
5935
+ return parseCommentOptionsInRange(
5936
+ /** @type {(Comment & { range: [number, number], value: string })[]} */ (
5937
+ this.comments
5938
+ ),
5939
+ range,
5940
+ this.magicCommentContext
5941
+ );
5942
+ }
5943
+
5944
+ /**
5945
+ * Finds the root object of a member expression chain without allocating the
5946
+ * member arrays. The traversal/break logic must stay in sync with
5947
+ * `extractMemberExpressionChain`; it lets `getMemberExpressionInfo` reject
5948
+ * unrecognized roots (~77% of calls) before paying for the arrays.
5949
+ * @param {Expression | Super} expression a member expression
5950
+ * @returns {Expression | Super} the root object of the chain
5951
+ */
5952
+ getMemberExpressionRoot(expression) {
5953
+ /** @type {Node} */
5954
+ let expr = expression;
5955
+ while (expr.type === "MemberExpression") {
5956
+ if (expr.computed) {
5957
+ const prop = expr.property;
5958
+ if (
5959
+ prop.type !== "Literal" &&
5960
+ !(
5961
+ prop.type === "TemplateLiteral" &&
5962
+ prop.expressions.length === 0 &&
5963
+ typeof prop.quasis[0].value.cooked === "string"
5964
+ )
5965
+ ) {
5966
+ break;
5207
5967
  }
5968
+ } else if (expr.property.type !== "Identifier") {
5969
+ break;
5208
5970
  }
5971
+ expr = expr.object;
5209
5972
  }
5210
- return { options, errors };
5973
+ return /** @type {Expression | Super} */ (expr);
5211
5974
  }
5212
5975
 
5213
5976
  /**
5977
+ * Extract member expression chain.
5214
5978
  * @param {Expression | Super} expression a member expression
5215
5979
  * @returns {{ members: Members, object: Expression | Super, membersOptionals: MembersOptionals, memberRanges: MemberRanges }} member names (reverse order) and remaining object
5216
5980
  */
@@ -5225,9 +5989,20 @@ class JavascriptParser extends Parser {
5225
5989
  const memberRanges = [];
5226
5990
  while (expr.type === "MemberExpression") {
5227
5991
  if (expr.computed) {
5228
- if (expr.property.type !== "Literal") break;
5229
- members.push(`${expr.property.value}`); // the literal
5230
- memberRanges.push(/** @type {Range} */ (expr.object.range)); // the range of the expression fragment before the literal
5992
+ const prop = expr.property;
5993
+ if (prop.type === "Literal") {
5994
+ members.push(`${prop.value}`); // the literal
5995
+ } else if (
5996
+ prop.type === "TemplateLiteral" &&
5997
+ prop.expressions.length === 0 &&
5998
+ typeof prop.quasis[0].value.cooked === "string"
5999
+ ) {
6000
+ // `[`url`]` is statically a string just like `["url"]`
6001
+ members.push(prop.quasis[0].value.cooked);
6002
+ } else {
6003
+ break;
6004
+ }
6005
+ memberRanges.push(/** @type {Range} */ (expr.object.range)); // the range of the expression fragment before the property
5231
6006
  } else {
5232
6007
  if (expr.property.type !== "Identifier") break;
5233
6008
  members.push(expr.property.name); // the identifier
@@ -5246,6 +6021,7 @@ class JavascriptParser extends Parser {
5246
6021
  }
5247
6022
 
5248
6023
  /**
6024
+ * Gets free info from variable.
5249
6025
  * @param {string} varName variable name
5250
6026
  * @returns {{ name: string, info: VariableInfo | string } | undefined} name of the free variable and variable info for that
5251
6027
  */
@@ -5265,6 +6041,7 @@ class JavascriptParser extends Parser {
5265
6041
  }
5266
6042
 
5267
6043
  /**
6044
+ * Gets name info from variable.
5268
6045
  * @param {string} varName variable name
5269
6046
  * @returns {{ name: string, info: VariableInfo | string } | undefined} name of the free variable and variable info for that
5270
6047
  */
@@ -5287,38 +6064,45 @@ class JavascriptParser extends Parser {
5287
6064
  /** @typedef {{ type: "expression", rootInfo: string | VariableInfo, name: string, getMembers: () => Members, getMembersOptionals: () => MembersOptionals, getMemberRanges: () => MemberRanges }} ExpressionExpressionInfo */
5288
6065
 
5289
6066
  /**
6067
+ * Gets member expression info.
5290
6068
  * @param {Expression | Super} expression a member expression
5291
6069
  * @param {number} allowedTypes which types should be returned, presented in bit mask
5292
6070
  * @returns {CallExpressionInfo | ExpressionExpressionInfo | undefined} expression info
5293
6071
  */
5294
6072
  getMemberExpressionInfo(expression, allowedTypes) {
5295
- const { object, members, membersOptionals, memberRanges } =
5296
- this.extractMemberExpressionChain(expression);
6073
+ // Resolve the root first (no allocation); most calls reject here and so
6074
+ // never build the member arrays via extractMemberExpressionChain.
6075
+ const object = this.getMemberExpressionRoot(expression);
5297
6076
  switch (object.type) {
5298
6077
  case "CallExpression": {
5299
6078
  if ((allowedTypes & ALLOWED_MEMBER_TYPES_CALL_EXPRESSION) === 0) return;
5300
- let callee = object.callee;
5301
- let rootMembers = EMPTY_ARRAY;
5302
- if (callee.type === "MemberExpression") {
5303
- ({ object: callee, members: rootMembers } =
5304
- this.extractMemberExpressionChain(callee));
5305
- }
6079
+ const calleeExpr = object.callee;
6080
+ const callee =
6081
+ calleeExpr.type === "MemberExpression"
6082
+ ? this.getMemberExpressionRoot(calleeExpr)
6083
+ : calleeExpr;
5306
6084
  const rootName = getRootName(callee);
5307
6085
  if (!rootName) return;
5308
6086
  const result = this.getNameInfoFromVariable(rootName);
5309
6087
  if (!result) return;
5310
6088
  const { info: rootInfo, name: resolvedRoot } = result;
6089
+ const rootMembers =
6090
+ calleeExpr.type === "MemberExpression"
6091
+ ? this.extractMemberExpressionChain(calleeExpr).members
6092
+ : EMPTY_ARRAY;
6093
+ const { members, membersOptionals, memberRanges } =
6094
+ this.extractMemberExpressionChain(expression);
5311
6095
  const calleeName = objectAndMembersToName(resolvedRoot, rootMembers);
5312
6096
  return {
5313
6097
  type: "call",
5314
6098
  call: object,
5315
6099
  calleeName,
5316
6100
  rootInfo,
5317
- getCalleeMembers: memoize(() => rootMembers.reverse()),
6101
+ getCalleeMembers: lazyReverse(rootMembers),
5318
6102
  name: objectAndMembersToName(`${calleeName}()`, members),
5319
- getMembers: memoize(() => members.reverse()),
5320
- getMembersOptionals: memoize(() => membersOptionals.reverse()),
5321
- getMemberRanges: memoize(() => memberRanges.reverse())
6103
+ getMembers: lazyReverse(members),
6104
+ getMembersOptionals: lazyReverse(membersOptionals),
6105
+ getMemberRanges: lazyReverse(memberRanges)
5322
6106
  };
5323
6107
  }
5324
6108
  case "Identifier":
@@ -5331,19 +6115,22 @@ class JavascriptParser extends Parser {
5331
6115
  const result = this.getNameInfoFromVariable(rootName);
5332
6116
  if (!result) return;
5333
6117
  const { info: rootInfo, name: resolvedRoot } = result;
6118
+ const { members, membersOptionals, memberRanges } =
6119
+ this.extractMemberExpressionChain(expression);
5334
6120
  return {
5335
6121
  type: "expression",
5336
6122
  name: objectAndMembersToName(resolvedRoot, members),
5337
6123
  rootInfo,
5338
- getMembers: memoize(() => members.reverse()),
5339
- getMembersOptionals: memoize(() => membersOptionals.reverse()),
5340
- getMemberRanges: memoize(() => memberRanges.reverse())
6124
+ getMembers: lazyReverse(members),
6125
+ getMembersOptionals: lazyReverse(membersOptionals),
6126
+ getMemberRanges: lazyReverse(memberRanges)
5341
6127
  };
5342
6128
  }
5343
6129
  }
5344
6130
  }
5345
6131
 
5346
6132
  /**
6133
+ * Gets name for expression.
5347
6134
  * @param {Expression} expression an expression
5348
6135
  * @returns {{ name: string, rootInfo: ExportedVariableInfo, getMembers: () => Members } | undefined} name info
5349
6136
  */
@@ -5355,6 +6142,7 @@ class JavascriptParser extends Parser {
5355
6142
  }
5356
6143
 
5357
6144
  /**
6145
+ * Get module parse function.
5358
6146
  * @param {Compilation} compilation compilation
5359
6147
  * @param {Module} module module
5360
6148
  * @returns {ParseFunction | undefined} parser
@@ -5375,6 +6163,7 @@ class JavascriptParser extends Parser {
5375
6163
  }
5376
6164
 
5377
6165
  /**
6166
+ * Returns parse result.
5378
6167
  * @param {string} code source code
5379
6168
  * @param {InternalParseOptions} options parsing options
5380
6169
  * @param {ParseFunction=} customParse custom function to parse
@@ -5383,13 +6172,32 @@ class JavascriptParser extends Parser {
5383
6172
  static _parse(code, options, customParse) {
5384
6173
  const type = options ? options.sourceType : "module";
5385
6174
  /** @type {ParseOptions} */
5386
- const parserOptions = {
5387
- ...defaultParserOptions,
5388
- allowReturnOutsideFunction: type === "script",
5389
- ...options,
5390
- sourceType: type === "auto" ? "module" : type
5391
- };
6175
+ let parserOptions;
6176
+ if (typeof customParse === "function") {
6177
+ // a user parse function may retain the options object — keep it fresh
6178
+ parserOptions = {
6179
+ ...defaultParserOptions,
6180
+ allowReturnOutsideFunction: type === "script",
6181
+ ...options,
6182
+ sourceType: type === "auto" ? "module" : type
6183
+ };
6184
+ } else {
6185
+ // reuse one options object across parses (parsing is synchronous) to
6186
+ // skip re-materializing it per module; acorn copies it via getOptions.
6187
+ // Every non-default key a caller may pass must be reset here.
6188
+ parserOptions = REUSED_PARSER_OPTIONS;
6189
+ parserOptions.importPhases = false;
6190
+ Object.assign(parserOptions, defaultParserOptions);
6191
+ parserOptions.allowReturnOutsideFunction = type === "script";
6192
+ if (options) Object.assign(parserOptions, options);
6193
+ parserOptions.sourceType = type === "auto" ? "module" : type;
6194
+ // let WebpackParser downgrade module->script in place on script-only
6195
+ // syntax so `auto` avoids a second full parse in the common case
6196
+ parserOptions.moduleFallback = type === "auto";
6197
+ }
6198
+ const wantRanges = parserOptions.ranges === true;
5392
6199
  /**
6200
+ * Returns parse result.
5393
6201
  * @param {string} code source code
5394
6202
  * @param {ParseOptions} options parsing options
5395
6203
  * @returns {ParseResult} parse result
@@ -5402,36 +6210,46 @@ class JavascriptParser extends Parser {
5402
6210
  /** @type {Comment[]} */
5403
6211
  const comments = [];
5404
6212
 
5405
- if (options.comments) {
5406
- /** @type {AcornOptions} */
5407
- (options).onComment = comments;
6213
+ // Whenever ranges are wanted (the main parse path and the concatenation
6214
+ // re-parse), have the parser plugin serve `range` on demand instead of
6215
+ // eagerly. `wantRanges` is hoisted since the auto-fallback re-enters
6216
+ // with the same (mutated) options object.
6217
+ options.lazyNodes = wantRanges;
6218
+ if (wantRanges) {
6219
+ // the lazy plugin replaces acorn's native tracking — disabling it
6220
+ // here lets WebpackParser skip its defensive options copy
6221
+ options.locations = false;
6222
+ options.ranges = false;
5408
6223
  }
5409
6224
 
5410
- /** @type {Set<number>} */
5411
- const semicolons = new Set();
5412
-
5413
- if (options.semicolons) {
5414
- /** @type {AcornOptions} */
5415
- (options).onInsertedSemicolon = (pos) => semicolons.add(pos);
6225
+ if (options.comments) {
6226
+ if (wantRanges) {
6227
+ // the parser plugin collects the comments itself, deferring the
6228
+ // text slice until some hook actually reads `value`
6229
+ options.lazyComments = comments;
6230
+ } else {
6231
+ /** @type {AcornOptions} */
6232
+ (options).onComment =
6233
+ /** @type {import("acorn").Comment[]} */
6234
+ (/** @type {unknown} */ (comments));
6235
+ }
5416
6236
  }
5417
6237
 
5418
6238
  const ast =
5419
6239
  /** @type {Program} */
5420
6240
  (parser.parse(code, /** @type {AcornOptions} */ (options)));
5421
6241
 
5422
- return { ast, comments, semicolons };
6242
+ return { ast, comments };
5423
6243
  };
5424
6244
 
5425
6245
  /** @type {Program | undefined} */
5426
6246
  let ast;
5427
6247
  /** @type {Comment[] | undefined} */
5428
6248
  let comments;
5429
- /** @type {Set<number> | undefined} */
5430
- let semicolons;
5431
6249
  let error;
5432
6250
  let threw = false;
5433
6251
  try {
5434
- ({ ast, comments, semicolons } = internalParse(code, parserOptions));
6252
+ ({ ast, comments } = internalParse(code, parserOptions));
5435
6253
  } catch (err) {
5436
6254
  error = err;
5437
6255
  threw = true;
@@ -5440,9 +6258,11 @@ class JavascriptParser extends Parser {
5440
6258
  if (threw && type === "auto") {
5441
6259
  parserOptions.sourceType = "script";
5442
6260
  parserOptions.allowReturnOutsideFunction = true;
6261
+ // the retry is already a full script parse — no in-place downgrade
6262
+ parserOptions.moduleFallback = false;
5443
6263
 
5444
6264
  try {
5445
- ({ ast, comments, semicolons } = internalParse(code, parserOptions));
6265
+ ({ ast, comments } = internalParse(code, parserOptions));
5446
6266
  threw = false;
5447
6267
  } catch (_err) {
5448
6268
  // we use the error from first parse try
@@ -5450,15 +6270,22 @@ class JavascriptParser extends Parser {
5450
6270
  }
5451
6271
  }
5452
6272
 
6273
+ // release per-parse state retained on the (possibly reused) options
6274
+ // object — the comments array retains source text slices
6275
+ parserOptions.lazyComments = undefined;
6276
+ /** @type {AcornOptions} */
6277
+ (parserOptions).onComment = undefined;
6278
+
5453
6279
  if (threw) {
5454
6280
  throw error;
5455
6281
  }
5456
6282
 
5457
- return /** @type {ParseResult} */ ({ ast, comments, semicolons });
6283
+ return /** @type {ParseResult} */ ({ ast, comments });
5458
6284
  }
5459
6285
 
5460
6286
  /**
5461
- * @param {((BaseParser: typeof AcornParser) => typeof AcornParser)[]} plugins parser plugin
6287
+ * Returns parser.
6288
+ * @param {((BaseParser: AcornParser) => AcornParser)[]} plugins parser plugin
5462
6289
  * @returns {typeof JavascriptParser} parser
5463
6290
  */
5464
6291
  static extend(...plugins) {