webpack 5.111.1 → 5.112.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (793) hide show
  1. package/README.md +1 -1
  2. package/bin/webpack.js +13 -7
  3. package/lib/Chunk.js +3 -966
  4. package/lib/Compilation.js +373 -163
  5. package/lib/Compiler.js +31 -44
  6. package/lib/Dependency.js +3 -551
  7. package/lib/DependencyTemplate.js +3 -70
  8. package/lib/EntryPlugin.js +3 -68
  9. package/lib/Entrypoint.js +3 -121
  10. package/lib/ExternalsPlugin.js +3 -92
  11. package/lib/FileSystemInfo.js +3 -4629
  12. package/lib/InitFragment.js +3 -204
  13. package/lib/LibraryTemplatePlugin.js +3 -46
  14. package/lib/ModuleFilenameHelpers.js +3 -400
  15. package/lib/ModuleNotFoundError.js +2 -2
  16. package/lib/MultiCompiler.js +37 -8
  17. package/lib/NormalModule.js +3 -2242
  18. package/lib/NullFactory.js +3 -22
  19. package/lib/ProgressPlugin.js +3 -908
  20. package/lib/RawModule.js +3 -197
  21. package/lib/RequestShortener.js +3 -37
  22. package/lib/SingleEntryPlugin.js +1 -1
  23. package/lib/WebpackError.js +2 -2
  24. package/lib/asset/AssetBytesGenerator.js +21 -13
  25. package/lib/asset/AssetBytesParser.js +12 -10
  26. package/lib/asset/AssetGenerator.js +71 -69
  27. package/lib/asset/AssetModule.js +13 -2
  28. package/lib/asset/AssetModulesPlugin.js +10 -12
  29. package/lib/asset/AssetParser.js +10 -10
  30. package/lib/asset/AssetSourceGenerator.js +23 -15
  31. package/lib/asset/AssetSourceParser.js +12 -10
  32. package/lib/asset/RawDataUrlModule.js +17 -10
  33. package/lib/asset/WebManifestGenerator.js +17 -12
  34. package/lib/asset/WebManifestParser.js +8 -8
  35. package/lib/async-modules/AsyncModuleHelpers.js +12 -5
  36. package/lib/async-modules/AwaitDependenciesInitFragment.js +4 -4
  37. package/lib/async-modules/InferAsyncModulesPlugin.js +9 -3
  38. package/lib/async-modules/isGeneratorLowered.js +3 -3
  39. package/lib/bun/BunTargetPlugin.js +1 -1
  40. package/lib/cache/AddBuildDependenciesPlugin.js +2 -19
  41. package/lib/{Cache.js → cache/Cache.js} +1 -1
  42. package/lib/{CacheFacade.js → cache/CacheFacade.js} +6 -6
  43. package/lib/cache/IdleFileCachePlugin.js +2 -2
  44. package/lib/cache/MemoryCachePlugin.js +2 -2
  45. package/lib/cache/MemoryWithGcCachePlugin.js +2 -2
  46. package/lib/cache/PackFileCacheStrategy.js +13 -19
  47. package/lib/cache/ResolverCachePlugin.js +65 -11
  48. package/lib/cache/mergeEtags.js +1 -1
  49. package/lib/{OptionsApply.js → config/OptionsApply.js} +3 -3
  50. package/lib/{PlatformPlugin.js → config/PlatformPlugin.js} +2 -2
  51. package/lib/{WebpackOptionsApply.js → config/WebpackOptionsApply.js} +209 -212
  52. package/lib/{WebpackOptionsDefaulter.js → config/WebpackOptionsDefaulter.js} +3 -3
  53. package/lib/config/browserslistTargetHandler.js +1 -1
  54. package/lib/{cli.js → config/cli.js} +14 -164
  55. package/lib/config/defaults.js +166 -59
  56. package/lib/config/getClaimedAssetTypes.js +22 -14
  57. package/lib/config/normalization.js +18 -7
  58. package/lib/config/target.js +11 -1
  59. package/lib/container/ContainerEntryDependency.js +1 -1
  60. package/lib/container/ContainerEntryModule.js +13 -11
  61. package/lib/container/ContainerEntryModuleFactory.js +2 -2
  62. package/lib/container/ContainerExposedDependency.js +1 -1
  63. package/lib/container/ContainerPlugin.js +178 -5
  64. package/lib/container/ContainerReferencePlugin.js +75 -14
  65. package/lib/container/FallbackDependency.js +1 -1
  66. package/lib/container/FallbackItemDependency.js +1 -1
  67. package/lib/container/FallbackModule.js +12 -10
  68. package/lib/container/FallbackModuleFactory.js +2 -2
  69. package/lib/container/HoistContainerReferencesPlugin.js +10 -11
  70. package/lib/container/ModuleFederationPlugin.js +306 -7
  71. package/lib/container/RemoteModule.js +14 -10
  72. package/lib/container/RemoteRuntimeModule.js +5 -5
  73. package/lib/container/RemoteToExternalDependency.js +1 -1
  74. package/lib/container/moduleFederationHooks.js +1 -1
  75. package/lib/context/ContextModule.js +37 -26
  76. package/lib/context/ContextModuleFactory.js +14 -11
  77. package/lib/context/ContextReplacementPlugin.js +6 -12
  78. package/lib/css/CssGenerator.js +78 -68
  79. package/lib/css/CssInjectStyleRuntimeModule.js +36 -30
  80. package/lib/css/CssLoadingRuntimeModule.js +77 -44
  81. package/lib/css/CssModule.js +37 -29
  82. package/lib/css/CssModulesPlugin.js +129 -45
  83. package/lib/css/CssParser.js +714 -322
  84. package/lib/css/CssServerStylesRuntimeModule.js +3 -3
  85. package/lib/{util → css}/conventions.js +1 -1
  86. package/lib/css/cssMinify.js +110 -37
  87. package/lib/css/data.js +6990 -5125
  88. package/lib/css/syntax-parser.js +20734 -0
  89. package/lib/css/syntax-printer.js +6092 -0
  90. package/lib/css/syntax.js +37 -18686
  91. package/lib/debug/ProfilingPlugin.js +106 -51
  92. package/lib/{DefinePlugin.js → define/DefinePlugin.js} +416 -55
  93. package/lib/{DotenvPlugin.js → define/DotenvPlugin.js} +19 -15
  94. package/lib/{EnvironmentPlugin.js → define/EnvironmentPlugin.js} +6 -4
  95. package/lib/deno/DenoTargetPlugin.js +1 -1
  96. package/lib/dependencies/ConstDependency.js +3 -120
  97. package/lib/dependencies/ContextElementDependency.js +5 -172
  98. package/lib/dependencies/NullDependency.js +3 -37
  99. package/lib/dependencies/{AMDDefineDependency.js → amd/AMDDefineDependency.js} +12 -11
  100. package/lib/dependencies/{AMDDefineDependencyParserPlugin.js → amd/AMDDefineDependencyParserPlugin.js} +10 -11
  101. package/lib/dependencies/{AMDPlugin.js → amd/AMDPlugin.js} +11 -11
  102. package/lib/dependencies/{AMDRequireArrayDependency.js → amd/AMDRequireArrayDependency.js} +15 -13
  103. package/lib/dependencies/{AMDRequireContextDependency.js → amd/AMDRequireContextDependency.js} +11 -10
  104. package/lib/dependencies/{AMDRequireDependenciesBlock.js → amd/AMDRequireDependenciesBlock.js} +7 -6
  105. package/lib/dependencies/{AMDRequireDependenciesBlockParserPlugin.js → amd/AMDRequireDependenciesBlockParserPlugin.js} +14 -11
  106. package/lib/dependencies/{AMDRequireDependency.js → amd/AMDRequireDependency.js} +13 -12
  107. package/lib/dependencies/{AMDRequireItemDependency.js → amd/AMDRequireItemDependency.js} +8 -7
  108. package/lib/dependencies/{AMDRuntimeModules.js → amd/AMDRuntimeModules.js} +3 -3
  109. package/lib/dependencies/{LocalModule.js → amd/LocalModule.js} +8 -4
  110. package/lib/dependencies/{LocalModuleDependency.js → amd/LocalModuleDependency.js} +17 -10
  111. package/lib/dependencies/{LocalModulesHelpers.js → amd/LocalModulesHelpers.js} +1 -1
  112. package/lib/dependencies/{RequireJsStuffPlugin.js → amd/RequireJsStuffPlugin.js} +9 -9
  113. package/lib/dependencies/{UnsupportedDependency.js → amd/UnsupportedDependency.js} +11 -10
  114. package/lib/dependencies/{CommonJsDependencyHelpers.js → commonjs/CommonJsDependencyHelpers.js} +8 -9
  115. package/lib/dependencies/{CommonJsExportRequireDependency.js → commonjs/CommonJsExportRequireDependency.js} +166 -36
  116. package/lib/dependencies/{CommonJsExportsDependency.js → commonjs/CommonJsExportsDependency.js} +15 -14
  117. package/lib/dependencies/{CommonJsExportsParserPlugin.js → commonjs/CommonJsExportsParserPlugin.js} +154 -92
  118. package/lib/dependencies/{CommonJsFullRequireDependency.js → commonjs/CommonJsFullRequireDependency.js} +32 -24
  119. package/lib/dependencies/{CommonJsImportsParserPlugin.js → commonjs/CommonJsImportsParserPlugin.js} +36 -33
  120. package/lib/dependencies/{CommonJsObjectExportDependency.js → commonjs/CommonJsObjectExportDependency.js} +17 -16
  121. package/lib/dependencies/{CommonJsPlugin.js → commonjs/CommonJsPlugin.js} +48 -39
  122. package/lib/dependencies/{CommonJsRequireContextDependency.js → commonjs/CommonJsRequireContextDependency.js} +15 -14
  123. package/lib/dependencies/{CommonJsRequireDependency.js → commonjs/CommonJsRequireDependency.js} +33 -25
  124. package/lib/dependencies/{CommonJsSelfReferenceDependency.js → commonjs/CommonJsSelfReferenceDependency.js} +17 -16
  125. package/lib/dependencies/{ModuleDecoratorDependency.js → commonjs/ModuleDecoratorDependency.js} +16 -15
  126. package/lib/dependencies/{RequireEnsureDependenciesBlock.js → commonjs/RequireEnsureDependenciesBlock.js} +8 -7
  127. package/lib/dependencies/{RequireEnsureDependenciesBlockParserPlugin.js → commonjs/RequireEnsureDependenciesBlockParserPlugin.js} +9 -6
  128. package/lib/dependencies/{RequireEnsureDependency.js → commonjs/RequireEnsureDependency.js} +13 -12
  129. package/lib/dependencies/{RequireEnsureItemDependency.js → commonjs/RequireEnsureItemDependency.js} +7 -6
  130. package/lib/dependencies/{RequireEnsurePlugin.js → commonjs/RequireEnsurePlugin.js} +8 -8
  131. package/lib/dependencies/{RequireHeaderDependency.js → commonjs/RequireHeaderDependency.js} +14 -13
  132. package/lib/dependencies/{RequireIncludeDependency.js → commonjs/RequireIncludeDependency.js} +13 -12
  133. package/lib/dependencies/{RequireIncludeDependencyParserPlugin.js → commonjs/RequireIncludeDependencyParserPlugin.js} +3 -27
  134. package/lib/dependencies/{RequireIncludePlugin.js → commonjs/RequireIncludePlugin.js} +4 -4
  135. package/lib/dependencies/{RequireResolveContextDependency.js → commonjs/RequireResolveContextDependency.js} +11 -10
  136. package/lib/dependencies/{RequireResolveDependency.js → commonjs/RequireResolveDependency.js} +12 -11
  137. package/lib/dependencies/{RequireResolveHeaderDependency.js → commonjs/RequireResolveHeaderDependency.js} +13 -12
  138. package/lib/dependencies/commonjs/TopLevelThisParserPlugin.js +59 -0
  139. package/lib/dependencies/{ContextDependency.js → context/ContextDependency.js} +15 -14
  140. package/lib/dependencies/{ContextDependencyHelpers.js → context/ContextDependencyHelpers.js} +31 -9
  141. package/lib/dependencies/{ContextDependencyTemplateAsId.js → context/ContextDependencyTemplateAsId.js} +3 -3
  142. package/lib/dependencies/{ContextDependencyTemplateAsRequireCall.js → context/ContextDependencyTemplateAsRequireCall.js} +3 -3
  143. package/lib/dependencies/context/ContextElementDependency.js +198 -0
  144. package/lib/dependencies/{ImportMetaContextDependency.js → context/ImportMetaContextDependency.js} +7 -6
  145. package/lib/dependencies/{ImportMetaContextDependencyParserPlugin.js → context/ImportMetaContextDependencyParserPlugin.js} +10 -11
  146. package/lib/dependencies/{ImportMetaContextPlugin.js → context/ImportMetaContextPlugin.js} +5 -5
  147. package/lib/dependencies/{ImportMetaGlobDependency.js → context/ImportMetaGlobDependency.js} +7 -6
  148. package/lib/dependencies/{ImportMetaGlobDependencyParserPlugin.js → context/ImportMetaGlobDependencyParserPlugin.js} +7 -10
  149. package/lib/dependencies/{ImportMetaGlobHelpers.js → context/ImportMetaGlobHelpers.js} +17 -19
  150. package/lib/dependencies/{RequireContextDependency.js → context/RequireContextDependency.js} +7 -6
  151. package/lib/dependencies/{RequireContextDependencyParserPlugin.js → context/RequireContextDependencyParserPlugin.js} +2 -2
  152. package/lib/dependencies/{RequireContextPlugin.js → context/RequireContextPlugin.js} +5 -5
  153. package/lib/dependencies/{CachedConstDependency.js → core/CachedConstDependency.js} +21 -17
  154. package/lib/dependencies/core/ConstDependency.js +131 -0
  155. package/lib/dependencies/{ImportPhase.js → core/ImportPhase.js} +5 -4
  156. package/lib/dependencies/{ModuleDependency.js → core/ModuleDependency.js} +10 -7
  157. package/lib/dependencies/{ModuleDependencyTemplateAsId.js → core/ModuleDependencyTemplateAsId.js} +3 -3
  158. package/lib/dependencies/{ModuleDependencyTemplateAsRequireId.js → core/ModuleDependencyTemplateAsRequireId.js} +2 -2
  159. package/lib/dependencies/{ModuleInitFragmentDependency.js → core/ModuleInitFragmentDependency.js} +10 -9
  160. package/lib/dependencies/core/NullDependency.js +44 -0
  161. package/lib/dependencies/{RuntimeRequirementsDependency.js → core/RuntimeRequirementsDependency.js} +10 -9
  162. package/lib/dependencies/{StaticExportsDependency.js → core/StaticExportsDependency.js} +15 -8
  163. package/lib/dependencies/{CssIcssExportDependency.js → css/CssIcssExportDependency.js} +375 -99
  164. package/lib/dependencies/{CssIcssImportDependency.js → css/CssIcssImportDependency.js} +24 -19
  165. package/lib/dependencies/{CssIcssSymbolDependency.js → css/CssIcssSymbolDependency.js} +13 -12
  166. package/lib/dependencies/{CssImportDependency.js → css/CssImportDependency.js} +15 -11
  167. package/lib/dependencies/{CssUrlDependency.js → css/CssUrlDependency.js} +25 -22
  168. package/lib/dependencies/{CreateRequireParserPlugin.js → esm/CreateRequireParserPlugin.js} +9 -9
  169. package/lib/dependencies/{HarmonyAcceptDependency.js → esm/ESMAcceptDependency.js} +41 -38
  170. package/lib/dependencies/esm/ESMAcceptImportDependency.js +39 -0
  171. package/lib/dependencies/{HarmonyCompatibilityDependency.js → esm/ESMCompatibilityDependency.js} +29 -21
  172. package/lib/dependencies/{HarmonyDetectionParserPlugin.js → esm/ESMDetectionParserPlugin.js} +20 -20
  173. package/lib/dependencies/{HarmonyEvaluatedImportSpecifierDependency.js → esm/ESMEvaluatedImportSpecifierDependency.js} +33 -30
  174. package/lib/dependencies/{HarmonyExportDependencyParserPlugin.js → esm/ESMExportDependencyParserPlugin.js} +60 -89
  175. package/lib/dependencies/{HarmonyExportExpressionDependency.js → esm/ESMExportExpressionDependency.js} +80 -45
  176. package/lib/dependencies/{HarmonyExportHeaderDependency.js → esm/ESMExportHeaderDependency.js} +17 -15
  177. package/lib/dependencies/esm/ESMExportImportedSideEffectDependency.js +37 -0
  178. package/lib/dependencies/{HarmonyExportImportedSpecifierDependency.js → esm/ESMExportImportedSpecifierDependency.js} +146 -133
  179. package/lib/dependencies/{HarmonyExportInitFragment.js → esm/ESMExportInitFragment.js} +48 -30
  180. package/lib/dependencies/{HarmonyExportSpecifierDependency.js → esm/ESMExportSpecifierDependency.js} +78 -37
  181. package/lib/dependencies/{HarmonyExports.js → esm/ESMExports.js} +4 -12
  182. package/lib/dependencies/{HarmonyImportBareSideEffectDependency.js → esm/ESMImportBareSideEffectDependency.js} +21 -13
  183. package/lib/dependencies/{HarmonyImportDependency.js → esm/ESMImportDependency.js} +86 -68
  184. package/lib/dependencies/{HarmonyImportDependencyParserPlugin.js → esm/ESMImportDependencyParserPlugin.js} +104 -100
  185. package/lib/dependencies/{HarmonyImportGuard.js → esm/ESMImportGuard.js} +36 -51
  186. package/lib/dependencies/{HarmonyImportSideEffectDependency.js → esm/ESMImportSideEffectDependency.js} +83 -39
  187. package/lib/dependencies/{HarmonyImportSpecifierDependency.js → esm/ESMImportSpecifierDependency.js} +98 -60
  188. package/lib/dependencies/esm/ESMLiveExportDependency.js +311 -0
  189. package/lib/dependencies/esm/ESMLiveExportParserPlugin.js +862 -0
  190. package/lib/dependencies/esm/ESMModulesPlugin.js +205 -0
  191. package/lib/dependencies/{HarmonyTopLevelThisParserPlugin.js → esm/ESMTopLevelThisParserPlugin.js} +7 -7
  192. package/lib/dependencies/{TopLevelAwaitDependency.js → esm/TopLevelAwaitDependency.js} +12 -18
  193. package/lib/dependencies/{DynamicExports.js → helpers/DynamicExports.js} +5 -7
  194. package/lib/{util → dependencies/helpers}/chainedImports.js +5 -5
  195. package/lib/dependencies/{processExportInfo.js → helpers/processExportInfo.js} +4 -4
  196. package/lib/{util → dependencies/helpers}/traverseDestructuringAssignmentProperties.js +1 -1
  197. package/lib/dependencies/{ImportMetaHotAcceptDependency.js → hmr/ImportMetaHotAcceptDependency.js} +8 -7
  198. package/lib/dependencies/{ImportMetaHotDeclineDependency.js → hmr/ImportMetaHotDeclineDependency.js} +8 -7
  199. package/lib/dependencies/{ModuleHotAcceptDependency.js → hmr/ModuleHotAcceptDependency.js} +8 -7
  200. package/lib/dependencies/{ModuleHotDeclineDependency.js → hmr/ModuleHotDeclineDependency.js} +8 -7
  201. package/lib/dependencies/{HtmlEntryDependency.js → html/HtmlEntryDependency.js} +52 -151
  202. package/lib/dependencies/{HtmlInlineHtmlDependency.js → html/HtmlInlineHtmlDependency.js} +13 -15
  203. package/lib/dependencies/{HtmlInlineScriptDependency.js → html/HtmlInlineScriptDependency.js} +69 -23
  204. package/lib/dependencies/{HtmlInlineStyleDependency.js → html/HtmlInlineStyleDependency.js} +50 -18
  205. package/lib/dependencies/{HtmlSourceDependency.js → html/HtmlSourceDependency.js} +23 -16
  206. package/lib/dependencies/{ImportContextDependency.js → import/ImportContextDependency.js} +24 -10
  207. package/lib/dependencies/{ImportDependency.js → import/ImportDependency.js} +26 -18
  208. package/lib/dependencies/{ImportEagerDependency.js → import/ImportEagerDependency.js} +18 -10
  209. package/lib/dependencies/{ImportParserPlugin.js → import/ImportParserPlugin.js} +22 -25
  210. package/lib/dependencies/{ImportPlugin.js → import/ImportPlugin.js} +4 -4
  211. package/lib/dependencies/{ImportWeakDependency.js → import/ImportWeakDependency.js} +18 -10
  212. package/lib/dependencies/{importOptionsCheck.js → import/importOptionsCheck.js} +2 -2
  213. package/lib/dependencies/{BuildTimeConstDependency.js → import-meta/BuildTimeConstDependency.js} +12 -11
  214. package/lib/dependencies/{ImportMetaMainDependency.js → import-meta/ImportMetaMainDependency.js} +12 -11
  215. package/lib/dependencies/{ImportMetaPlugin.js → import-meta/ImportMetaPlugin.js} +122 -103
  216. package/lib/dependencies/{SystemPlugin.js → system/SystemPlugin.js} +11 -38
  217. package/lib/dependencies/{SystemRuntimeModule.js → system/SystemRuntimeModule.js} +3 -3
  218. package/lib/dependencies/{ImportMetaResolveDependency.js → url/ImportMetaResolveDependency.js} +9 -8
  219. package/lib/dependencies/{URLContextDependency.js → url/URLContextDependency.js} +11 -10
  220. package/lib/dependencies/{URLDependency.js → url/URLDependency.js} +28 -20
  221. package/lib/{url → dependencies/url}/URLParserPlugin.js +17 -19
  222. package/lib/dependencies/{URLPlugin.js → url/URLPlugin.js} +6 -7
  223. package/lib/dependencies/{WebAssemblyExportImportedDependency.js → wasm/WebAssemblyExportImportedDependency.js} +18 -11
  224. package/lib/dependencies/{WebAssemblyImportDependency.js → wasm/WebAssemblyImportDependency.js} +19 -12
  225. package/lib/dependencies/{CreateScriptUrlDependency.js → worker/CreateScriptUrlDependency.js} +12 -11
  226. package/lib/dependencies/{WorkerAndWorkletPlugin.js → worker/WorkerAndWorkletPlugin.js} +82 -53
  227. package/lib/dependencies/{WorkerDependency.js → worker/WorkerDependency.js} +22 -15
  228. package/lib/dependencies/{WorkletDependency.js → worker/WorkletDependency.js} +19 -18
  229. package/lib/{EvalDevToolModulePlugin.js → devtool/EvalDevToolModulePlugin.js} +20 -6
  230. package/lib/{EvalSourceMapDevToolPlugin.js → devtool/EvalSourceMapDevToolPlugin.js} +32 -24
  231. package/lib/devtool/ModuleFilenameHelpers.js +413 -0
  232. package/lib/{SourceMapDevToolModuleOptionsPlugin.js → devtool/SourceMapDevToolModuleOptionsPlugin.js} +10 -3
  233. package/lib/{SourceMapDevToolPlugin.js → devtool/SourceMapDevToolPlugin.js} +155 -27
  234. package/lib/{util → devtool}/generateDebugId.js +1 -1
  235. package/lib/{IgnoreWarningsPlugin.js → diagnostics/IgnoreWarningsPlugin.js} +2 -2
  236. package/lib/{NoEmitOnErrorsPlugin.js → diagnostics/NoEmitOnErrorsPlugin.js} +1 -1
  237. package/lib/diagnostics/WarnCaseSensitiveModulesPlugin.js +64 -0
  238. package/lib/{WarnDeprecatedOptionPlugin.js → diagnostics/WarnDeprecatedOptionPlugin.js} +2 -22
  239. package/lib/diagnostics/WarnNoModeSetPlugin.js +27 -0
  240. package/lib/dll/DelegatedModule.js +23 -21
  241. package/lib/dll/DelegatedModuleFactoryPlugin.js +2 -2
  242. package/lib/dll/DelegatedPlugin.js +1 -1
  243. package/lib/{dependencies → dll}/DelegatedSourceDependency.js +5 -4
  244. package/lib/{dependencies → dll}/DllEntryDependency.js +6 -5
  245. package/lib/dll/DllEntryPlugin.js +3 -3
  246. package/lib/dll/DllModule.js +14 -10
  247. package/lib/dll/DllModuleFactory.js +3 -3
  248. package/lib/dll/DllPlugin.js +18 -6
  249. package/lib/dll/DllReferencePlugin.js +103 -30
  250. package/lib/dll/LibManifestPlugin.js +9 -7
  251. package/lib/electron/ElectronTargetPlugin.js +2 -2
  252. package/lib/{DynamicEntryPlugin.js → entry/DynamicEntryPlugin.js} +3 -3
  253. package/lib/{dependencies → entry}/EntryDependency.js +11 -2
  254. package/lib/{EntryOptionPlugin.js → entry/EntryOptionPlugin.js} +6 -6
  255. package/lib/entry/EntryPlugin.js +75 -0
  256. package/lib/errors/AbstractMethodError.js +1 -1
  257. package/lib/{performance → errors}/AssetsOverSizeLimitWarning.js +2 -2
  258. package/lib/errors/AsyncDependencyToInitialChunkError.js +2 -2
  259. package/lib/errors/BuildCycleError.js +1 -1
  260. package/lib/{WarnCaseSensitiveModulesPlugin.js → errors/CaseSensitiveModulesWarning.js} +4 -56
  261. package/lib/errors/ChunkRenderError.js +1 -1
  262. package/lib/errors/CodeGenerationError.js +1 -1
  263. package/lib/errors/CommentCompilationWarning.js +1 -1
  264. package/lib/errors/ConflictingEntryExportsWarning.js +38 -0
  265. package/lib/{dependencies → errors}/CriticalDependencyWarning.js +4 -3
  266. package/lib/errors/DeprecatedOptionWarning.js +30 -0
  267. package/lib/errors/DllManifestError.js +26 -0
  268. package/lib/{performance → errors}/DuplicatePackagesWarning.js +6 -6
  269. package/lib/{dependencies/HarmonyLinkingError.js → errors/ESMLinkingError.js} +4 -4
  270. package/lib/{performance → errors}/EntrypointsOverSizeLimitWarning.js +2 -2
  271. package/lib/errors/EnvironmentNotSupportAsyncWarning.js +2 -2
  272. package/lib/{ErrorHelpers.js → errors/ErrorHelpers.js} +9 -6
  273. package/lib/errors/ExternalStarReexportError.js +2 -2
  274. package/lib/{library → errors}/FalseIIFEUmdWarning.js +1 -1
  275. package/lib/errors/HookWebpackError.js +6 -5
  276. package/lib/errors/IgnoreErrorModuleFactory.js +3 -3
  277. package/lib/errors/InvalidDependenciesModuleWarning.js +1 -1
  278. package/lib/errors/JSONParseError.js +4 -4
  279. package/lib/{optimize → errors}/MinMaxSizeWarning.js +1 -1
  280. package/lib/errors/ModuleBuildError.js +1 -1
  281. package/lib/errors/ModuleDependencyError.js +2 -2
  282. package/lib/errors/ModuleDependencyWarning.js +2 -2
  283. package/lib/errors/ModuleError.js +1 -1
  284. package/lib/errors/ModuleHashingError.js +1 -1
  285. package/lib/errors/ModuleNotFoundError.js +3 -3
  286. package/lib/errors/ModuleParseError.js +1 -1
  287. package/lib/errors/ModuleRestoreError.js +1 -1
  288. package/lib/errors/ModuleStoreError.js +1 -1
  289. package/lib/errors/ModuleWarning.js +1 -1
  290. package/lib/{performance → errors}/NoAsyncChunksWarning.js +1 -1
  291. package/lib/{WarnNoModeSetPlugin.js → errors/NoModeWarning.js} +2 -19
  292. package/lib/errors/NodeStuffInWebError.js +7 -2
  293. package/lib/errors/PathVariableError.js +31 -0
  294. package/lib/errors/RequireIncludeDeprecationWarning.js +40 -0
  295. package/lib/{performance → errors}/RuntimeInLargeChunkWarning.js +1 -1
  296. package/lib/errors/RuntimeModuleGenerationError.js +51 -0
  297. package/lib/errors/SSRManifestAutoPublicPathWarning.js +24 -0
  298. package/lib/errors/SystemImportDeprecationWarning.js +43 -0
  299. package/lib/errors/UnmergeableEntryExportsError.js +34 -0
  300. package/lib/errors/UnsupportedFeatureWarning.js +1 -1
  301. package/lib/{wasm-sync → errors}/UnsupportedWebAssemblyFeatureError.js +1 -1
  302. package/lib/{wasm-sync → errors}/WebAssemblyInInitialChunkError.js +7 -5
  303. package/lib/errors/WebpackError.js +13 -3
  304. package/lib/esm/ExportWebpackRequireRuntimeModule.js +2 -2
  305. package/lib/esm/ModuleChunkFormatPlugin.js +55 -20
  306. package/lib/esm/ModuleChunkLoadingPlugin.js +3 -3
  307. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +8 -8
  308. package/lib/{ExternalModule.js → externals/ExternalModule.js} +90 -63
  309. package/lib/{ExternalModuleFactoryPlugin.js → externals/ExternalModuleFactoryPlugin.js} +42 -41
  310. package/lib/externals/ExternalsPlugin.js +99 -0
  311. package/lib/fs/FileSystemInfo.js +4642 -0
  312. package/lib/{util → fs}/fs.js +22 -9
  313. package/lib/{AsyncDependenciesBlock.js → graph/AsyncDependenciesBlock.js} +27 -4
  314. package/lib/graph/Chunk.js +985 -0
  315. package/lib/{ChunkGraph.js → graph/ChunkGraph.js} +192 -80
  316. package/lib/{ChunkGroup.js → graph/ChunkGroup.js} +11 -3
  317. package/lib/{DependenciesBlock.js → graph/DependenciesBlock.js} +16 -4
  318. package/lib/graph/Dependency.js +634 -0
  319. package/lib/graph/Entrypoint.js +136 -0
  320. package/lib/{ExportsInfo.js → graph/ExportsInfo.js} +131 -83
  321. package/lib/{HotUpdateChunk.js → graph/HotUpdateChunk.js} +8 -0
  322. package/lib/{ModuleGraph.js → graph/ModuleGraph.js} +44 -33
  323. package/lib/{ModuleGraphConnection.js → graph/ModuleGraphConnection.js} +2 -2
  324. package/lib/{buildChunkGraph.js → graph/buildChunkGraph.js} +169 -76
  325. package/lib/{util → graph}/findGraphRoots.js +15 -9
  326. package/lib/graph/isDependencyKind.js +23 -0
  327. package/lib/hmr/HotModuleReplacement.runtime.js +12 -11
  328. package/lib/{HotModuleReplacementPlugin.js → hmr/HotModuleReplacementPlugin.js} +51 -57
  329. package/lib/hmr/HotModuleReplacementRuntimeModule.js +3 -3
  330. package/lib/hmr/JavascriptHotModuleReplacement.runtime.js +25 -26
  331. package/lib/hmr/JavascriptHotModuleReplacementHelper.js +2 -2
  332. package/lib/hmr/LazyCompilationPlugin.js +32 -28
  333. package/lib/html/HtmlGenerator.js +132 -60
  334. package/lib/html/HtmlModule.js +16 -2
  335. package/lib/html/HtmlModulesPlugin.js +184 -87
  336. package/lib/html/HtmlParser.js +511 -160
  337. package/lib/html/builtinEmbeddedRenderer.js +70 -25
  338. package/lib/html/data.js +44 -22
  339. package/lib/html/htmlMinify.js +114 -41
  340. package/lib/html/syntax-parser.js +15795 -0
  341. package/lib/html/syntax-printer.js +1033 -0
  342. package/lib/html/syntax.js +37 -13952
  343. package/lib/html/xmlMinify.js +70 -0
  344. package/lib/ids/ChunkModuleIdRangePlugin.js +2 -2
  345. package/lib/ids/DeterministicModuleIdsPlugin.js +1 -1
  346. package/lib/ids/HashedModuleIdsPlugin.js +32 -5
  347. package/lib/ids/IdHelpers.js +4 -4
  348. package/lib/ids/NaturalChunkIdsPlugin.js +1 -1
  349. package/lib/ids/OccurrenceChunkIdsPlugin.js +6 -5
  350. package/lib/ids/OccurrenceModuleIdsPlugin.js +6 -5
  351. package/lib/{RecordIdsPlugin.js → ids/RecordIdsPlugin.js} +5 -5
  352. package/lib/ids/SyncModuleIdsPlugin.js +3 -3
  353. package/lib/{util → ids}/numberHash.js +1 -1
  354. package/lib/index.js +312 -105
  355. package/lib/{APIPlugin.js → javascript/APIPlugin.js} +31 -37
  356. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +4 -5
  357. package/lib/javascript/BasicEvaluatedExpression.js +9 -9
  358. package/lib/javascript/ChunkHelpers.js +64 -4
  359. package/lib/javascript/CommonJsChunkFormatPlugin.js +5 -13
  360. package/lib/{CompatibilityPlugin.js → javascript/CompatibilityPlugin.js} +7 -7
  361. package/lib/{ConstPlugin.js → javascript/ConstPlugin.js} +75 -8
  362. package/lib/{ExportsInfoApiPlugin.js → javascript/ExportsInfoApiPlugin.js} +5 -5
  363. package/lib/{dependencies → javascript}/ExportsInfoDependency.js +10 -9
  364. package/lib/javascript/JavascriptGenerator.js +32 -27
  365. package/lib/{JavascriptMetaInfoPlugin.js → javascript/JavascriptMetaInfoPlugin.js} +8 -20
  366. package/lib/javascript/JavascriptModule.js +14 -3
  367. package/lib/javascript/JavascriptModulesPlugin.js +441 -214
  368. package/lib/javascript/JavascriptParser.js +318 -144
  369. package/lib/javascript/JavascriptParserHelpers.js +1 -1
  370. package/lib/javascript/MergedEntryExports.js +196 -0
  371. package/lib/javascript/ScopeAnalyzer.js +3924 -13
  372. package/lib/javascript/StartupHelpers.js +6 -6
  373. package/lib/{UseStrictPlugin.js → javascript/UseStrictPlugin.js} +13 -19
  374. package/lib/{dependencies → javascript}/WebpackIsIncludedDependency.js +10 -9
  375. package/lib/{WebpackIsIncludedPlugin.js → javascript/WebpackIsIncludedPlugin.js} +8 -8
  376. package/lib/javascript/data.js +533 -122
  377. package/lib/javascript/jsMinify.js +272 -0
  378. package/lib/javascript/regexp.js +67 -32
  379. package/lib/javascript/syntax-parser.js +19169 -0
  380. package/lib/javascript/syntax-printer-data.js +1099 -0
  381. package/lib/javascript/syntax-printer.js +53878 -0
  382. package/lib/javascript/syntax.js +20 -11274
  383. package/lib/json/JsonData.js +1 -1
  384. package/lib/{dependencies → json}/JsonExportsDependency.js +8 -7
  385. package/lib/json/JsonGenerator.js +24 -16
  386. package/lib/json/JsonModule.js +13 -2
  387. package/lib/json/JsonModulesPlugin.js +1 -1
  388. package/lib/json/JsonParser.js +11 -10
  389. package/lib/json/jsonMinify.js +69 -0
  390. package/lib/library/AbstractLibraryPlugin.js +28 -15
  391. package/lib/library/AmdLibraryPlugin.js +4 -4
  392. package/lib/library/AssignLibraryPlugin.js +28 -12
  393. package/lib/library/EnableLibraryPlugin.js +1 -1
  394. package/lib/library/ExportPropertyLibraryPlugin.js +4 -4
  395. package/lib/library/JsonpLibraryPlugin.js +2 -2
  396. package/lib/library/LibraryTemplatePlugin.js +53 -0
  397. package/lib/library/ModuleLibraryPlugin.js +557 -187
  398. package/lib/library/SystemLibraryPlugin.js +6 -8
  399. package/lib/library/UmdLibraryPlugin.js +3 -4
  400. package/lib/{dependencies → loaders}/LoaderDependency.js +3 -3
  401. package/lib/{dependencies → loaders}/LoaderImportDependency.js +9 -3
  402. package/lib/{LoaderOptionsPlugin.js → loaders/LoaderOptionsPlugin.js} +30 -12
  403. package/lib/{dependencies → loaders}/LoaderPlugin.js +2 -2
  404. package/lib/loaders/LoaderRunner.js +94 -46
  405. package/lib/{LoaderTargetPlugin.js → loaders/LoaderTargetPlugin.js} +2 -2
  406. package/lib/loaders/loadLoader.js +16 -10
  407. package/lib/logging/Logger.js +7 -9
  408. package/lib/logging/ProgressPlugin.js +957 -0
  409. package/lib/{CodeGenerationResults.js → module/CodeGenerationResults.js} +7 -7
  410. package/lib/{Generator.js → module/Generator.js} +33 -23
  411. package/lib/{Module.js → module/Module.js} +121 -53
  412. package/lib/{ModuleFactory.js → module/ModuleFactory.js} +3 -3
  413. package/lib/module/NormalModule.js +2350 -0
  414. package/lib/{NormalModuleFactory.js → module/NormalModuleFactory.js} +64 -71
  415. package/lib/module/NullFactory.js +29 -0
  416. package/lib/{Parser.js → module/Parser.js} +12 -5
  417. package/lib/module/RawModule.js +208 -0
  418. package/lib/{SelfModuleFactory.js → module/SelfModuleFactory.js} +1 -1
  419. package/lib/{util → module}/extractSourceMap.js +71 -20
  420. package/lib/{util → module}/findCaseMismatch.js +4 -4
  421. package/lib/node/CommonJsChunkLoadingPlugin.js +3 -3
  422. package/lib/{dependencies → node}/ExternalModuleDependency.js +8 -7
  423. package/lib/{dependencies → node}/ExternalModuleInitFragment.js +7 -6
  424. package/lib/{dependencies → node}/ExternalModuleInitFragmentDependency.js +14 -9
  425. package/lib/node/NodeEnvironmentPlugin.js +11 -1
  426. package/lib/{NodeStuffPlugin.js → node/NodeStuffPlugin.js} +17 -17
  427. package/lib/node/NodeTargetPlugin.js +1 -1
  428. package/lib/node/NodeWatchFileSystem.js +58 -6
  429. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +7 -7
  430. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +13 -19
  431. package/lib/node/ReadFileCompileWasmPlugin.js +9 -11
  432. package/lib/node/RequireChunkLoadingRuntimeModule.js +7 -7
  433. package/lib/node/nodeConsole.js +6 -7
  434. package/lib/optimize/AggressiveMergingPlugin.js +2 -2
  435. package/lib/optimize/AggressiveSplittingPlugin.js +12 -8
  436. package/lib/{CircularModulesPlugin.js → optimize/CircularModulesPlugin.js} +14 -14
  437. package/lib/optimize/ConcatenatedModule.js +231 -220
  438. package/lib/{ConcatenationScope.js → optimize/ConcatenationScope.js} +39 -6
  439. package/lib/optimize/ConstExportsPlugin.js +7 -7
  440. package/lib/optimize/EnsureChunkConditionsPlugin.js +3 -3
  441. package/lib/{FlagAllModulesAsUsedPlugin.js → optimize/FlagAllModulesAsUsedPlugin.js} +3 -3
  442. package/lib/{FlagDependencyExportsPlugin.js → optimize/FlagDependencyExportsPlugin.js} +23 -28
  443. package/lib/{FlagDependencyUsagePlugin.js → optimize/FlagDependencyUsagePlugin.js} +44 -19
  444. package/lib/{FlagEntryExportAsUsedPlugin.js → optimize/FlagEntryExportAsUsedPlugin.js} +2 -2
  445. package/lib/optimize/FlagIncludedChunksPlugin.js +2 -2
  446. package/lib/optimize/InlineExports.js +12 -7
  447. package/lib/optimize/InnerGraph.js +5 -13
  448. package/lib/optimize/InnerGraphPlugin.js +10 -10
  449. package/lib/optimize/LazyBarrels.js +620 -0
  450. package/lib/{util → optimize}/LazyBucketSortedSet.js +2 -2
  451. package/lib/optimize/LimitChunkCountPlugin.js +16 -7
  452. package/lib/optimize/MangleExportsPlugin.js +5 -5
  453. package/lib/optimize/MergeDuplicateChunksPlugin.js +7 -6
  454. package/lib/optimize/MinChunkSizePlugin.js +9 -6
  455. package/lib/optimize/ModuleConcatenationPlugin.js +28 -22
  456. package/lib/{dependencies → optimize}/PureExpressionDependency.js +11 -10
  457. package/lib/optimize/RealContentHashPlugin.js +18 -13
  458. package/lib/optimize/RemoveEmptyChunksPlugin.js +2 -2
  459. package/lib/optimize/RemoveParentModulesPlugin.js +4 -4
  460. package/lib/optimize/SideEffectsFlagPlugin.js +24 -38
  461. package/lib/optimize/SplitChunksPlugin.js +719 -174
  462. package/lib/{util → optimize}/TupleQueue.js +9 -9
  463. package/lib/optimize/chunkSetIntersections.js +437 -0
  464. package/lib/{util → optimize}/deterministicGrouping.js +17 -17
  465. package/lib/{BannerPlugin.js → output/BannerPlugin.js} +82 -14
  466. package/lib/{CleanPlugin.js → output/CleanPlugin.js} +69 -25
  467. package/lib/{CopyPlugin.js → output/CopyPlugin.js} +144 -70
  468. package/lib/{ManifestPlugin.js → output/ManifestPlugin.js} +91 -17
  469. package/lib/output/SSRManifestPlugin.js +349 -0
  470. package/lib/performance/AnalyzableBailoutsPlugin.js +1 -1
  471. package/lib/performance/AsyncChunkWaterfallsPlugin.js +1 -1
  472. package/lib/performance/BroadContextsPlugin.js +4 -4
  473. package/lib/performance/CacheEffectivenessPlugin.js +2 -3
  474. package/lib/performance/ConflictingResourceHintsPlugin.js +1 -1
  475. package/lib/performance/DuplicateModulesPlugin.js +3 -4
  476. package/lib/performance/DuplicatePackagesPlugin.js +3 -3
  477. package/lib/performance/DynamicExportsPlugin.js +2 -2
  478. package/lib/performance/EvalUsagePlugin.js +4 -6
  479. package/lib/performance/HotspotsPlugin.js +39 -14
  480. package/lib/performance/LargeModulesPlugin.js +2 -3
  481. package/lib/performance/LegacyJavascriptPlugin.js +1 -2
  482. package/lib/performance/MissingSideEffectsPlugin.js +2 -3
  483. package/lib/performance/MissingSourceMapsPlugin.js +5 -6
  484. package/lib/performance/PureAnnotationsPlugin.js +19 -13
  485. package/lib/performance/RedundantDynamicImportsPlugin.js +6 -8
  486. package/lib/performance/ScopeHoistingBailoutsPlugin.js +2 -2
  487. package/lib/performance/SizeLimitsPlugin.js +11 -12
  488. package/lib/performance/TopLevelThisPlugin.js +22 -13
  489. package/lib/performance/UnsplitVendorsPlugin.js +1 -2
  490. package/lib/performance/UnusedAliasesPlugin.js +6 -7
  491. package/lib/performance/UnusedAssetsPlugin.js +5 -5
  492. package/lib/performance/UnusedDefinesPlugin.js +2 -2
  493. package/lib/performance/UnusedExternalsPlugin.js +3 -4
  494. package/lib/performance/UnusedFederationPlugin.js +2 -4
  495. package/lib/performance/UnusedModulesPlugin.js +5 -4
  496. package/lib/performance/getModuleSize.js +1 -1
  497. package/lib/performance/hasOnlyUnusedExports.js +4 -4
  498. package/lib/performance/isOnlyReexported.js +7 -6
  499. package/lib/{AutomaticPrefetchPlugin.js → prefetch/AutomaticPrefetchPlugin.js} +4 -5
  500. package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +2 -2
  501. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +1 -1
  502. package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +4 -4
  503. package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +4 -4
  504. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +4 -4
  505. package/lib/{dependencies → prefetch}/PrefetchDependency.js +1 -1
  506. package/lib/{PrefetchPlugin.js → prefetch/PrefetchPlugin.js} +2 -2
  507. package/lib/prefetch/ResourceHintPlugin.js +66 -45
  508. package/lib/prefetch/ResourceHintRuntimeModule.js +3 -3
  509. package/lib/prefetch/StartupAssetHintRuntimeModule.js +3 -3
  510. package/lib/prefetch/parseResourceHintOptions.js +4 -3
  511. package/lib/{ProvidePlugin.js → provide/ProvidePlugin.js} +7 -7
  512. package/lib/{dependencies → provide}/ProvidedDependency.js +50 -17
  513. package/lib/{IgnorePlugin.js → resolve/IgnorePlugin.js} +30 -13
  514. package/lib/{NormalModuleReplacementPlugin.js → resolve/NormalModuleReplacementPlugin.js} +4 -4
  515. package/lib/{ResolverFactory.js → resolve/ResolverFactory.js} +18 -5
  516. package/lib/resolve/getResolveOptionsKey.js +59 -0
  517. package/lib/rules/BasicEffectRulePlugin.js +1 -1
  518. package/lib/rules/RuleSetCompiler.js +42 -51
  519. package/lib/rules/UseEffectRulePlugin.js +1 -3
  520. package/lib/runtime/AsyncModuleGeneratorRuntimeModule.js +2 -2
  521. package/lib/runtime/AsyncModuleRuntimeModule.js +14 -5
  522. package/lib/runtime/AutoPublicPathRuntimeModule.js +5 -5
  523. package/lib/runtime/BaseUriRuntimeModule.js +3 -3
  524. package/lib/runtime/ChunkNameRuntimeModule.js +2 -2
  525. package/lib/runtime/CompatGetDefaultExportRuntimeModule.js +2 -2
  526. package/lib/runtime/CompatRuntimeModule.js +4 -4
  527. package/lib/runtime/ConcatenationWrapRuntimeModule.js +2 -2
  528. package/lib/runtime/ConstructRequireRuntimeModule.js +2 -2
  529. package/lib/runtime/CreateFakeNamespaceObjectRuntimeModule.js +2 -2
  530. package/lib/runtime/CreateScriptRuntimeModule.js +2 -2
  531. package/lib/runtime/CreateScriptUrlRuntimeModule.js +2 -2
  532. package/lib/runtime/DefinePropertyGettersRuntimeModule.js +6 -6
  533. package/lib/runtime/EnsureChunkRuntimeModule.js +4 -4
  534. package/lib/runtime/GetChunkFilenameRuntimeModule.js +7 -11
  535. package/lib/runtime/GetFullHashRuntimeModule.js +2 -2
  536. package/lib/runtime/GetMainFilenameRuntimeModule.js +4 -4
  537. package/lib/runtime/GetTrustedTypesPolicyRuntimeModule.js +3 -3
  538. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +3 -3
  539. package/lib/runtime/GlobalRuntimeModule.js +3 -3
  540. package/lib/runtime/HasOwnPropertyRuntimeModule.js +3 -3
  541. package/lib/runtime/HelperRuntimeModule.js +16 -1
  542. package/lib/runtime/LoadScriptRuntimeModule.js +3 -3
  543. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +80 -17
  544. package/lib/runtime/MakeNamespaceObjectRuntimeModule.js +2 -2
  545. package/lib/runtime/NonceRuntimeModule.js +2 -2
  546. package/lib/runtime/OnChunksLoadedRuntimeModule.js +4 -4
  547. package/lib/runtime/PublicPathRuntimeModule.js +2 -2
  548. package/lib/runtime/RelativeUrlRuntimeModule.js +2 -2
  549. package/lib/{RuntimeGlobals.js → runtime/RuntimeGlobals.js} +24 -1
  550. package/lib/runtime/RuntimeIdRuntimeModule.js +4 -4
  551. package/lib/{RuntimeModule.js → runtime/RuntimeModule.js} +36 -21
  552. package/lib/{RuntimePlugin.js → runtime/RuntimePlugin.js} +50 -50
  553. package/lib/runtime/SetAnonymousDefaultNameRuntimeModule.js +2 -2
  554. package/lib/runtime/SpecNamespaceObjectRuntimeModule.js +2 -2
  555. package/lib/runtime/StartupChunkDependenciesPlugin.js +2 -2
  556. package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +5 -5
  557. package/lib/runtime/StartupEntrypointRuntimeModule.js +3 -3
  558. package/lib/runtime/SystemContextRuntimeModule.js +2 -2
  559. package/lib/runtime/ToBinaryRuntimeModule.js +3 -3
  560. package/lib/runtime/WorkerRuntimeModule.js +1 -1
  561. package/lib/runtime/baseUri.js +1 -1
  562. package/lib/schemes/DataUriPlugin.js +1 -1
  563. package/lib/schemes/HttpUriPlugin.js +68 -13
  564. package/lib/schemes/VirtualUrlPlugin.js +52 -16
  565. package/lib/serialization/AggregateErrorSerializer.js +4 -4
  566. package/lib/serialization/BinaryMiddleware.js +4 -1
  567. package/lib/serialization/ErrorObjectSerializer.js +2 -5
  568. package/lib/serialization/FileMiddleware.js +3 -3
  569. package/lib/serialization/ObjectMiddleware.js +62 -29
  570. package/lib/serialization/PlainObjectSerializer.js +3 -7
  571. package/lib/serialization/Serializer.js +21 -11
  572. package/lib/serialization/SerializerMiddleware.js +10 -8
  573. package/lib/serialization/SingleItemMiddleware.js +4 -2
  574. package/lib/sharing/ConsumeSharedFallbackDependency.js +9 -1
  575. package/lib/sharing/ConsumeSharedModule.js +18 -14
  576. package/lib/sharing/ConsumeSharedPlugin.js +148 -42
  577. package/lib/sharing/ConsumeSharedRuntimeModule.js +8 -8
  578. package/lib/sharing/ProvideForSharedDependency.js +9 -1
  579. package/lib/sharing/ProvideSharedDependency.js +1 -1
  580. package/lib/sharing/ProvideSharedModule.js +11 -9
  581. package/lib/sharing/ProvideSharedModuleFactory.js +2 -2
  582. package/lib/sharing/ProvideSharedPlugin.js +111 -20
  583. package/lib/sharing/SharePlugin.js +102 -9
  584. package/lib/sharing/ShareRuntimeModule.js +6 -6
  585. package/lib/sharing/resolveMatchedConfigs.js +1 -1
  586. package/lib/{util → sharing}/semver.js +14 -16
  587. package/lib/sharing/utils.js +59 -2
  588. package/lib/stats/DefaultStatsFactoryPlugin.js +57 -54
  589. package/lib/stats/DefaultStatsPresetPlugin.js +3 -7
  590. package/lib/stats/DefaultStatsPrinterPlugin.js +15 -14
  591. package/lib/{MultiStats.js → stats/MultiStats.js} +4 -4
  592. package/lib/{Stats.js → stats/Stats.js} +4 -4
  593. package/lib/stats/StatsFactory.js +208 -37
  594. package/lib/stats/StatsPrinter.js +126 -13
  595. package/lib/{ChunkTemplate.js → template/ChunkTemplate.js} +7 -7
  596. package/lib/{ConditionalInitFragment.js → template/ConditionalInitFragment.js} +3 -3
  597. package/lib/template/DependencyTemplate.js +77 -0
  598. package/lib/{DependencyTemplates.js → template/DependencyTemplates.js} +9 -4
  599. package/lib/template/InitFragment.js +223 -0
  600. package/lib/{MainTemplate.js → template/MainTemplate.js} +11 -11
  601. package/lib/{ModuleInfoHeaderPlugin.js → template/ModuleInfoHeaderPlugin.js} +30 -8
  602. package/lib/{ModuleTemplate.js → template/ModuleTemplate.js} +6 -6
  603. package/lib/{RuntimeTemplate.js → template/RuntimeTemplate.js} +158 -95
  604. package/lib/{Template.js → template/Template.js} +14 -12
  605. package/lib/{TemplatedPathPlugin.js → template/TemplatedPathPlugin.js} +19 -23
  606. package/lib/typescript/TypeScriptPlugin.js +3 -3
  607. package/lib/util/RequestShortener.js +44 -0
  608. package/lib/util/SortableSet.js +87 -22
  609. package/lib/util/SourceProcessor.js +439 -51
  610. package/lib/util/TupleSet.js +27 -27
  611. package/lib/util/WeakTupleMap.js +20 -16
  612. package/lib/util/buildDiagnostics.js +2 -2
  613. package/lib/util/cleverMerge.js +61 -33
  614. package/lib/util/comparators.js +19 -15
  615. package/lib/util/concatenate.js +28 -147
  616. package/lib/util/createMappings.js +111 -0
  617. package/lib/util/dataURL.js +96 -15
  618. package/lib/util/deprecation.js +5 -4
  619. package/lib/util/extractComments.js +118 -0
  620. package/lib/util/formatLocation.js +1 -1
  621. package/lib/util/globUtils.js +198 -20
  622. package/lib/util/haltVisitors.js +51 -0
  623. package/lib/util/handlerKeys.js +2 -2
  624. package/lib/util/identifier.js +117 -1
  625. package/lib/util/implicitTypeLoaderFallback.js +6 -4
  626. package/lib/util/internalSerializables.js +296 -102
  627. package/lib/util/magicComment.js +12 -7
  628. package/lib/util/makeSerializable.js +28 -7
  629. package/lib/util/memoize.js +1 -1
  630. package/lib/util/parseJson.js +2 -2
  631. package/lib/util/preloadModuleType.js +5 -2
  632. package/lib/util/registerExternalSerializer.js +2 -2
  633. package/lib/util/removeBOM.js +1 -1
  634. package/lib/util/runtime.js +1 -1
  635. package/lib/util/serialization.js +35 -28
  636. package/lib/util/source.js +2 -2
  637. package/lib/util/terminalColors.js +161 -0
  638. package/lib/{wasm-async → wasm}/AsyncWasmCompileRuntimeModule.js +5 -5
  639. package/lib/{wasm-async → wasm}/AsyncWasmLoadingRuntimeModule.js +5 -5
  640. package/lib/{wasm-async → wasm}/AsyncWasmModule.js +19 -5
  641. package/lib/{wasm-async → wasm}/AsyncWebAssemblyGenerator.js +17 -9
  642. package/lib/{wasm-async → wasm}/AsyncWebAssemblyJavascriptGenerator.js +24 -15
  643. package/lib/{wasm-async → wasm}/AsyncWebAssemblyModulesPlugin.js +26 -10
  644. package/lib/{wasm-async → wasm}/AsyncWebAssemblyParser.js +14 -12
  645. package/lib/wasm/EnableWasmLoadingPlugin.js +1 -1
  646. package/lib/{wasm-async → wasm}/UniversalCompileAsyncWasmPlugin.js +11 -13
  647. package/lib/wasm/wasmModuleFilename.js +2 -2
  648. package/lib/wasm-sync/SyncWasmModule.js +18 -3
  649. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +8 -8
  650. package/lib/wasm-sync/WasmFinalizeExportsPlugin.js +3 -3
  651. package/lib/wasm-sync/WebAssemblyGenerator.js +22 -16
  652. package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +28 -21
  653. package/lib/wasm-sync/WebAssemblyModulesPlugin.js +9 -7
  654. package/lib/wasm-sync/WebAssemblyParser.js +15 -17
  655. package/lib/wasm-sync/WebAssemblyUtils.js +6 -5
  656. package/lib/{MultiWatching.js → watch/MultiWatching.js} +3 -3
  657. package/lib/{WatchIgnorePlugin.js → watch/WatchIgnorePlugin.js} +43 -9
  658. package/lib/{Watching.js → watch/Watching.js} +8 -8
  659. package/lib/web/FetchCompileAsyncWasmPlugin.js +12 -18
  660. package/lib/web/FetchCompileWasmPlugin.js +8 -10
  661. package/lib/web/JsonpChunkLoadingPlugin.js +3 -3
  662. package/lib/web/JsonpChunkLoadingRuntimeModule.js +6 -6
  663. package/lib/web/JsonpTemplatePlugin.js +1 -1
  664. package/lib/webpack.js +27 -17
  665. package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +3 -3
  666. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +6 -6
  667. package/package.json +57 -36
  668. package/schemas/WebpackOptions.check.js +4 -3
  669. package/schemas/WebpackOptions.d.json.ts +2 -0
  670. package/schemas/WebpackOptions.json +295 -75
  671. package/schemas/plugins/BannerPlugin.check.js +4 -3
  672. package/schemas/plugins/BannerPlugin.json +29 -2
  673. package/schemas/plugins/HtmlGeneratorOptions.check.js +4 -3
  674. package/schemas/plugins/HtmlParserOptions.check.js +4 -3
  675. package/schemas/plugins/IgnorePlugin.check.js +4 -3
  676. package/schemas/plugins/IgnorePlugin.d.json.ts +2 -0
  677. package/schemas/plugins/IgnorePlugin.json +1 -1
  678. package/schemas/plugins/LoaderOptionsPlugin.check.js +4 -3
  679. package/schemas/plugins/ManifestPlugin.check.js +4 -3
  680. package/schemas/plugins/ManifestPlugin.json +3 -3
  681. package/schemas/plugins/ProgressPlugin.check.js +4 -3
  682. package/schemas/plugins/ProgressPlugin.json +2 -7
  683. package/schemas/plugins/SSRManifestPlugin.check.js +7 -0
  684. package/schemas/plugins/SSRManifestPlugin.json +20 -0
  685. package/schemas/plugins/SourceMapDevToolPlugin.check.js +4 -3
  686. package/schemas/plugins/SourceMapDevToolPlugin.json +44 -12
  687. package/schemas/plugins/WatchIgnorePlugin.check.js +4 -3
  688. package/schemas/plugins/WatchIgnorePlugin.json +12 -3
  689. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +4 -3
  690. package/schemas/plugins/asset/AssetInlineGeneratorOptions.check.js +4 -3
  691. package/schemas/plugins/asset/AssetParserOptions.check.js +4 -3
  692. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +4 -3
  693. package/schemas/plugins/container/ContainerPlugin.check.js +4 -3
  694. package/schemas/plugins/container/ContainerPlugin.json +8 -0
  695. package/schemas/plugins/container/ContainerReferencePlugin.check.js +4 -3
  696. package/schemas/plugins/container/ExternalsType.check.js +4 -3
  697. package/schemas/plugins/container/ModuleFederationPlugin.check.js +4 -3
  698. package/schemas/plugins/container/ModuleFederationPlugin.json +40 -0
  699. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +4 -3
  700. package/schemas/plugins/css/CssGeneratorOptions.check.js +4 -3
  701. package/schemas/plugins/css/CssModuleGeneratorOptions.check.js +4 -3
  702. package/schemas/plugins/css/CssModuleParserOptions.check.js +4 -3
  703. package/schemas/plugins/css/CssParserOptions.check.js +4 -3
  704. package/schemas/plugins/debug/ProfilingPlugin.check.js +4 -3
  705. package/schemas/plugins/define/DotenvPluginOptions.check.js +7 -0
  706. package/schemas/plugins/define/DotenvPluginOptions.json +3 -0
  707. package/schemas/plugins/dll/DllPlugin.check.js +4 -3
  708. package/schemas/plugins/dll/DllReferencePlugin.check.js +4 -3
  709. package/schemas/plugins/dll/DllReferencePlugin.json +3 -18
  710. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +4 -3
  711. package/schemas/plugins/ids/OccurrenceChunkIdsPlugin.check.js +4 -3
  712. package/schemas/plugins/ids/OccurrenceModuleIdsPlugin.check.js +4 -3
  713. package/schemas/plugins/json/JsonModulesPluginGenerator.check.js +4 -3
  714. package/schemas/plugins/json/JsonModulesPluginParser.check.js +4 -3
  715. package/schemas/plugins/optimize/AggressiveSplittingPlugin.check.js +4 -3
  716. package/schemas/plugins/optimize/LimitChunkCountPlugin.check.js +4 -3
  717. package/schemas/plugins/optimize/MergeDuplicateChunksPlugin.check.js +4 -3
  718. package/schemas/plugins/optimize/MinChunkSizePlugin.check.js +4 -3
  719. package/schemas/plugins/output/CleanOptions.check.js +7 -0
  720. package/schemas/plugins/output/CleanOptions.json +3 -0
  721. package/schemas/plugins/schemes/HttpUriPlugin.check.js +4 -3
  722. package/schemas/plugins/schemes/VirtualUrlPlugin.check.js +4 -3
  723. package/schemas/plugins/sharing/ConsumeSharedPlugin.check.js +4 -3
  724. package/schemas/plugins/sharing/ConsumeSharedPlugin.json +32 -0
  725. package/schemas/plugins/sharing/ProvideSharedPlugin.check.js +4 -3
  726. package/schemas/plugins/sharing/ProvideSharedPlugin.json +32 -0
  727. package/schemas/plugins/sharing/SharePlugin.check.js +4 -3
  728. package/schemas/plugins/sharing/SharePlugin.json +32 -0
  729. package/types.d.ts +20780 -14174
  730. package/lib/LazyBarrel.js +0 -388
  731. package/lib/dependencies/HarmonyAcceptImportDependency.js +0 -39
  732. package/lib/dependencies/HarmonyModulesPlugin.js +0 -192
  733. package/lib/javascript/ChunkFormatHelpers.js +0 -72
  734. package/lib/javascript/grammar.js +0 -5546
  735. package/lib/javascript/parser.js +0 -1500
  736. package/lib/javascript/regexpData.js +0 -51
  737. package/lib/performance/getSourceModules.js +0 -22
  738. package/lib/util/Semaphore.js +0 -65
  739. package/lib/util/objectToMap.js +0 -15
  740. package/schemas/WebpackOptions.check.d.ts +0 -7
  741. package/schemas/_container.json +0 -155
  742. package/schemas/_sharing.json +0 -118
  743. package/schemas/plugins/BannerPlugin.check.d.ts +0 -7
  744. package/schemas/plugins/HtmlGeneratorOptions.check.d.ts +0 -7
  745. package/schemas/plugins/HtmlParserOptions.check.d.ts +0 -7
  746. package/schemas/plugins/IgnorePlugin.check.d.ts +0 -7
  747. package/schemas/plugins/LoaderOptionsPlugin.check.d.ts +0 -7
  748. package/schemas/plugins/ManifestPlugin.check.d.ts +0 -7
  749. package/schemas/plugins/ProgressPlugin.check.d.ts +0 -7
  750. package/schemas/plugins/SourceMapDevToolPlugin.check.d.ts +0 -7
  751. package/schemas/plugins/WatchIgnorePlugin.check.d.ts +0 -7
  752. package/schemas/plugins/asset/AssetGeneratorOptions.check.d.ts +0 -7
  753. package/schemas/plugins/asset/AssetInlineGeneratorOptions.check.d.ts +0 -7
  754. package/schemas/plugins/asset/AssetParserOptions.check.d.ts +0 -7
  755. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.d.ts +0 -7
  756. package/schemas/plugins/container/ContainerPlugin.check.d.ts +0 -7
  757. package/schemas/plugins/container/ContainerReferencePlugin.check.d.ts +0 -7
  758. package/schemas/plugins/container/ExternalsType.check.d.ts +0 -7
  759. package/schemas/plugins/container/ModuleFederationPlugin.check.d.ts +0 -7
  760. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.d.ts +0 -7
  761. package/schemas/plugins/css/CssGeneratorOptions.check.d.ts +0 -7
  762. package/schemas/plugins/css/CssModuleGeneratorOptions.check.d.ts +0 -7
  763. package/schemas/plugins/css/CssModuleParserOptions.check.d.ts +0 -7
  764. package/schemas/plugins/css/CssParserOptions.check.d.ts +0 -7
  765. package/schemas/plugins/debug/ProfilingPlugin.check.d.ts +0 -7
  766. package/schemas/plugins/dll/DllPlugin.check.d.ts +0 -7
  767. package/schemas/plugins/dll/DllReferencePlugin.check.d.ts +0 -7
  768. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.d.ts +0 -7
  769. package/schemas/plugins/ids/OccurrenceChunkIdsPlugin.check.d.ts +0 -7
  770. package/schemas/plugins/ids/OccurrenceModuleIdsPlugin.check.d.ts +0 -7
  771. package/schemas/plugins/json/JsonModulesPluginGenerator.check.d.ts +0 -7
  772. package/schemas/plugins/json/JsonModulesPluginParser.check.d.ts +0 -7
  773. package/schemas/plugins/optimize/AggressiveSplittingPlugin.check.d.ts +0 -7
  774. package/schemas/plugins/optimize/LimitChunkCountPlugin.check.d.ts +0 -7
  775. package/schemas/plugins/optimize/MergeDuplicateChunksPlugin.check.d.ts +0 -7
  776. package/schemas/plugins/optimize/MinChunkSizePlugin.check.d.ts +0 -7
  777. package/schemas/plugins/schemes/HttpUriPlugin.check.d.ts +0 -7
  778. package/schemas/plugins/schemes/VirtualUrlPlugin.check.d.ts +0 -7
  779. package/schemas/plugins/sharing/ConsumeSharedPlugin.check.d.ts +0 -7
  780. package/schemas/plugins/sharing/ProvideSharedPlugin.check.d.ts +0 -7
  781. package/schemas/plugins/sharing/SharePlugin.check.d.ts +0 -7
  782. /package/lib/{validateSchema.js → config/validateSchema.js} +0 -0
  783. /package/lib/{util → css}/topologicalSort.js +0 -0
  784. /package/lib/dependencies/{getFunctionExpression.js → helpers/getFunctionExpression.js} +0 -0
  785. /package/lib/{util → externals}/extractUrlAndGlobal.js +0 -0
  786. /package/lib/{util → fs}/StackedCacheMap.js +0 -0
  787. /package/lib/{util → javascript}/StackedMap.js +0 -0
  788. /package/lib/{ModuleProfile.js → module/ModuleProfile.js} +0 -0
  789. /package/lib/{ModuleSourceTypeConstants.js → module/ModuleSourceTypeConstants.js} +0 -0
  790. /package/lib/{ModuleTypeConstants.js → module/ModuleTypeConstants.js} +0 -0
  791. /package/lib/{OptimizationStages.js → optimize/OptimizationStages.js} +0 -0
  792. /package/lib/{util → optimize}/Queue.js +0 -0
  793. /package/lib/{util → stats}/smartGrouping.js +0 -0
@@ -5,12 +5,15 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ // cspell:ignore defun, fnames, funarg
9
+
8
10
  /**
9
11
  * @import {
10
12
  * Function as ESTreeFunction,
11
13
  * Identifier,
12
14
  * Node,
13
- * Program
15
+ * Program,
16
+ * Property
14
17
  * } from "estree"
15
18
  */
16
19
 
@@ -116,7 +119,7 @@ const CHILD_KEYS = {
116
119
  class Scope {
117
120
  /**
118
121
  * @param {ScopeType} type what opened this scope
119
- * @param {Node} block the node that opened this scope
122
+ * @param {Node} block the node that opened this scope, read but not kept
120
123
  * @param {Scope | null} upper the enclosing scope
121
124
  * @param {boolean} isVarScope whether `var` and function declarations hoist to here
122
125
  * @param {boolean} recordEveryReference whether every binding collects its references, not only the ones webpack reads
@@ -124,8 +127,10 @@ class Scope {
124
127
  constructor(type, block, upper, isVarScope, recordEveryReference) {
125
128
  /** @type {ScopeType} */
126
129
  this.type = type;
127
- /** @type {Node} */
128
- this.block = block;
130
+ /** @type {string} the type of the node that opened this scope */
131
+ this.blockType = block.type;
132
+ /** @type {number} where that node starts */
133
+ this.blockStart = /** @type {Node & Offset} */ (block).start;
129
134
  /** @type {Scope | null} */
130
135
  this.upper = upper;
131
136
  /** @type {Scope[]} */
@@ -384,15 +389,31 @@ class ScopeAnalyzer {
384
389
  */
385
390
  constructor(recordEveryReference) {
386
391
  /** @type {Scope} the scope the walker is currently inside */
387
- this.scope = /** @type {Scope} */ (/** @type {unknown} */ (null));
392
+ this.scope = /** @type {Scope} */ (/** @type {Scope | null} */ (null));
388
393
  /** @type {Identifier[]} identifiers awaiting resolution */
389
394
  this.pendingIdentifiers = [];
390
395
  /** @type {Scope[]} the scope each pending identifier was seen in */
391
396
  this.pendingScopes = [];
397
+ /** @type {Set<number>} where each shorthand property's identifier starts */
398
+ this.shorthandIdentifierStarts = new Set();
392
399
  /** @type {boolean} */
393
400
  this.recordEveryReference = recordEveryReference;
394
401
  }
395
402
 
403
+ /**
404
+ * Records where a shorthand property's identifier starts, so renaming it
405
+ * later needs the offset rather than the tree it was read from.
406
+ * @param {Property} property a property whose `shorthand` is set
407
+ * @returns {void}
408
+ */
409
+ _recordShorthandIdentifier(property) {
410
+ const value = property.value;
411
+ const identifier = value.type === "AssignmentPattern" ? value.left : value;
412
+ this.shorthandIdentifierStarts.add(
413
+ /** @type {Identifier & Offset} */ (identifier).start
414
+ );
415
+ }
416
+
396
417
  /**
397
418
  * @param {ScopeType} type scope kind
398
419
  * @param {Node} block node opening the scope
@@ -434,9 +455,9 @@ class ScopeAnalyzer {
434
455
  addBinding(scope, variable);
435
456
  }
436
457
  if (variable.identifiers === NO_IDENTIFIERS) {
437
- variable.identifiers = [/** @type {Identifier} */ (node)];
458
+ variable.identifiers = [node];
438
459
  } else {
439
- variable.identifiers.push(/** @type {Identifier} */ (node));
460
+ variable.identifiers.push(node);
440
461
  }
441
462
  }
442
463
 
@@ -512,6 +533,7 @@ class ScopeAnalyzer {
512
533
  }
513
534
  return;
514
535
  case "Property":
536
+ if (node.shorthand) this._recordShorthandIdentifier(node);
515
537
  if (node.computed) rightHandNodes.push(node.key);
516
538
  this._patternWalk(node.value, mode, target, defaults, rightHandNodes);
517
539
  return;
@@ -700,8 +722,8 @@ class ScopeAnalyzer {
700
722
  if (key === "key" && "computed" in node && node.computed === false) {
701
723
  continue;
702
724
  }
703
- const child = /** @type {Record<string, unknown>} */ (
704
- /** @type {unknown} */ (node)
725
+ const child = /** @type {NodeChildren} */ (
726
+ /** @type {Node | NodeChildren} */ (node)
705
727
  )[key];
706
728
  if (child === null || typeof child !== "object") continue;
707
729
  if (Array.isArray(child)) {
@@ -710,8 +732,8 @@ class ScopeAnalyzer {
710
732
  this._visit(item);
711
733
  }
712
734
  }
713
- } else if (/** @type {Node} */ (child).type) {
714
- this._visit(/** @type {Node} */ (child));
735
+ } else if (child.type) {
736
+ this._visit(child);
715
737
  }
716
738
  }
717
739
  }
@@ -794,6 +816,11 @@ class ScopeAnalyzer {
794
816
  return;
795
817
 
796
818
  case "Property":
819
+ if (node.shorthand) this._recordShorthandIdentifier(node);
820
+ if (node.computed) this._visit(node.key);
821
+ this._visit(node.value);
822
+ return;
823
+
797
824
  case "MethodDefinition":
798
825
  if (node.computed) this._visit(node.key);
799
826
  this._visit(node.value);
@@ -992,7 +1019,7 @@ class ScopeAnalyzer {
992
1019
  }
993
1020
  for (let i = 0; i < keys.length; i++) {
994
1021
  const child = /** @type {NodeChildren} */ (
995
- /** @type {unknown} */ (node)
1022
+ /** @type {Node | NodeChildren} */ (node)
996
1023
  )[keys[i]];
997
1024
  if (child === null || child === undefined) continue;
998
1025
  if (Array.isArray(child)) {
@@ -1068,6 +1095,7 @@ class ScopeAnalyzer {
1068
1095
  * @property {Scope} globalScope the outermost scope
1069
1096
  * @property {Scope} moduleScope the module body scope, where top-level declarations live
1070
1097
  * @property {Reference[]} unresolvedReferences every identifier that resolved to no binding — the module's free names
1098
+ * @property {Set<number>} shorthandIdentifierStarts where each shorthand property's identifier starts, so a rename can write `name: newName` without the tree
1071
1099
  */
1072
1100
 
1073
1101
  /**
@@ -1084,11 +1112,3894 @@ const analyzeScope = (ast, recordEveryReference = false) => {
1084
1112
  const moduleScope = analyzer._push("module", ast, true);
1085
1113
  analyzer._visitAll(ast.body);
1086
1114
  const unresolvedReferences = analyzer._resolve();
1087
- return { globalScope, moduleScope, unresolvedReferences };
1115
+ return {
1116
+ globalScope,
1117
+ moduleScope,
1118
+ unresolvedReferences,
1119
+ shorthandIdentifierStarts: analyzer.shorthandIdentifierStarts
1120
+ };
1121
+ };
1122
+
1123
+ /**
1124
+ * @typedef {import("./syntax-printer").PrintNode} PrintNode
1125
+ * @typedef {import("./syntax-printer").PrintProgram} PrintProgram
1126
+ * @typedef {import("./syntax-printer").PrintIdentifier} PrintIdentifier
1127
+ * @typedef {import("./syntax-printer").PrintLiteral} PrintLiteral
1128
+ * @typedef {import("./syntax-printer").PrintFunction} PrintFunction
1129
+ * @typedef {import("./syntax-printer").PrintClass} PrintClass
1130
+ * @typedef {import("./syntax-printer").PrintProperty} PrintProperty
1131
+ * @typedef {import("./syntax-printer").PrintObject} PrintObject
1132
+ * @typedef {import("./syntax-printer").PrintArray} PrintArray
1133
+ * @typedef {import("./syntax-printer").PrintCallExpression} PrintCallExpression
1134
+ * @typedef {import("./syntax-printer").PrintNewExpression} PrintNewExpression
1135
+ * @typedef {import("./syntax-printer").PrintForStatement} PrintForStatement
1136
+ * @typedef {import("./syntax-printer").PrintForInStatement} PrintForInStatement
1137
+ * @typedef {import("./syntax-printer").PrintForOfStatement} PrintForOfStatement
1138
+ * @typedef {import("./syntax-printer").PrintWhileStatement} PrintWhileStatement
1139
+ * @typedef {import("./syntax-printer").PrintVariableDeclaration} PrintVariableDeclaration
1140
+ * @typedef {import("./syntax-printer").PrintVariableDeclarator} PrintVariableDeclarator
1141
+ * @typedef {import("./syntax-printer").PrintExport} PrintExport
1142
+ * @typedef {import("./syntax-printer").NodeToken} Token
1143
+ * @typedef {NonNullable<PrintProgram["tokenTables"]>} TokenTables
1144
+ * @typedef {import("./syntax-printer").Node} CompressorNode
1145
+ * @typedef {import("./syntax-printer").Scope} CompressorScopeShape
1146
+ * @typedef {import("./syntax-printer").Definition} CompressorDefinition
1147
+ */
1148
+
1149
+ // How a minifier definition's name was declared, one code per kind of
1150
+ // terser's declaring symbol; a global is a name nothing declares.
1151
+ const DECLARES_VAR = 1;
1152
+ const DECLARES_FUNARG = 2;
1153
+ const DECLARES_LET = 3;
1154
+ const DECLARES_CONST = 4;
1155
+ const DECLARES_USING = 5;
1156
+ const DECLARES_CATCH = 6;
1157
+ const DECLARES_IMPORT = 7;
1158
+
1159
+ // What a name one long saves taking the name spelled beside it: a key's `:`
1160
+ // and the name, or an import's or export's ` as ` and the name.
1161
+ const SHORTHAND_SAVING = 2;
1162
+ const AS_SAVING = 5;
1163
+ // `spelledNames` collecting the names a key spells too, not only a module's.
1164
+ const SPELLED_KEYS = 2;
1165
+ // A name the mangler may hand out as it is spelled: one ASCII identifier, so it
1166
+ // prints bare and costs a byte a character.
1167
+ const SPELLABLE_NAME = /^[A-Za-z_$][\w$]*$/;
1168
+ // Names no binding may take in strict code, a module's, beyond the keywords.
1169
+ const NAMES_NO_BINDING_TAKES = new Set([
1170
+ "arguments",
1171
+ "await",
1172
+ "enum",
1173
+ "eval",
1174
+ "implements",
1175
+ "interface",
1176
+ "let",
1177
+ "package",
1178
+ "private",
1179
+ "protected",
1180
+ "public",
1181
+ "static",
1182
+ "yield"
1183
+ ]);
1184
+ const DECLARES_DEFUN = 8;
1185
+ const DECLARES_LAMBDA = 9;
1186
+ const DECLARES_CLASS = 10;
1187
+ const DECLARES_DEF_CLASS = 11;
1188
+ const DECLARES_GLOBAL = 12;
1189
+
1190
+ // The declarations a `var` or a parameter may not join, as `declarations` bits.
1191
+ const LEXICAL_DECLARATIONS =
1192
+ (1 << DECLARES_LET) | (1 << DECLARES_CONST) | (1 << DECLARES_USING);
1193
+
1194
+ // What the minifier's analysis records of a name read, replayed once all is
1195
+ // declared.
1196
+ const REFERENCE_CALLED = 1;
1197
+ const REFERENCE_EXPORTED = 1 << 1;
1198
+ const REFERENCE_FROM_MODULE = 1 << 2;
1199
+ const REFERENCE_CATCH = 1 << 3;
1200
+
1201
+ // How an `export` naming a definition keeps its name.
1202
+ const EXPORT_KEEP_NAME = 1;
1203
+ const EXPORT_WANT_MANGLE = 2;
1204
+
1205
+ // Past this many definitions a scope's `enclosed` is also held as a set, so
1206
+ // adding one stops scanning the list: a bundle's toplevel reaches thousands.
1207
+ const ENCLOSED_INDEX_THRESHOLD = 16;
1208
+ /** @type {WeakMap<MinifierVariable[], Set<MinifierVariable>>} */
1209
+ const enclosedIndexes = new WeakMap();
1210
+
1211
+ /**
1212
+ * Adds a definition to a scope's `enclosed` unless it is there. The list is
1213
+ * the record, since a cloned scope copies it; the set only answers membership.
1214
+ * @param {MinifierScope} scope a scope
1215
+ * @param {MinifierVariable} definition a definition it reaches
1216
+ * @returns {void}
1217
+ */
1218
+ const encloseUnique = (scope, definition) => {
1219
+ const { enclosed } = scope;
1220
+ if (enclosed.length < ENCLOSED_INDEX_THRESHOLD) {
1221
+ if (!enclosed.includes(definition)) enclosed.push(definition);
1222
+ return;
1223
+ }
1224
+ let index = enclosedIndexes.get(enclosed);
1225
+ if (index === undefined || index.size !== enclosed.length) {
1226
+ index = new Set(enclosed);
1227
+ enclosedIndexes.set(enclosed, index);
1228
+ }
1229
+ if (index.has(definition)) return;
1230
+ index.add(definition);
1231
+ enclosed.push(definition);
1232
+ };
1233
+
1234
+ /**
1235
+ * A scope as the minifier reads it: terser's, which opens one for every block
1236
+ * and loop, besides what it names in.
1237
+ */
1238
+ class MinifierScope extends Scope {
1239
+ /**
1240
+ * @param {ScopeType} type what opened this scope
1241
+ * @param {PrintNode} node the node opening it
1242
+ * @param {MinifierScope | null} upper the enclosing scope
1243
+ * @param {boolean} isVarScope whether `var` and function declarations hoist to here
1244
+ */
1245
+ constructor(type, node, upper, isVarScope) {
1246
+ super(type, /** @type {Node} */ (node), upper, isVarScope, false);
1247
+ /** @type {PrintNode} */
1248
+ this.node = node;
1249
+ /** @type {MinifierVariable[]} the definitions it or a scope inside it reads, in the order first read */
1250
+ this.enclosed = [];
1251
+ /** @type {number} how many names it has handed out, less one */
1252
+ this.cname = -1;
1253
+ /** @type {boolean} whether a direct `eval` can reach its names */
1254
+ this.usesEval = false;
1255
+ /** @type {boolean} whether a `with` can reach its names */
1256
+ this.usesWith = false;
1257
+ /** @type {MinifierVariable | null} a function expression's own name */
1258
+ this.functionName = null;
1259
+ /** @type {number} the first name its parameter list reads, as the analysis counts them, or -1 */
1260
+ this.parameterStart = -1;
1261
+ /** @type {number} the name after the last its parameter list reads, or -1 */
1262
+ this.parameterEnd = -1;
1263
+ }
1264
+
1265
+ /**
1266
+ * terser's `is_block_scope`.
1267
+ * @returns {boolean} whether a block or a loop opens it
1268
+ */
1269
+ isBlockScope() {
1270
+ return this.variableScope !== this;
1271
+ }
1272
+
1273
+ /**
1274
+ * terser's `get_defun_scope`.
1275
+ * @returns {MinifierScope} the nearest scope around it, or it, that is not a block's
1276
+ */
1277
+ getDefunScope() {
1278
+ return /** @type {MinifierScope} */ (this.variableScope);
1279
+ }
1280
+
1281
+ /**
1282
+ * terser's `pinned`.
1283
+ * @returns {boolean} whether `eval` or `with` can reach its names
1284
+ */
1285
+ isPinned() {
1286
+ return this.usesEval || this.usesWith;
1287
+ }
1288
+
1289
+ /**
1290
+ * terser's `find_variable`.
1291
+ * @param {string} name a name
1292
+ * @returns {MinifierVariable | undefined} what it resolves to from here
1293
+ */
1294
+ findVariable(name) {
1295
+ return findMinifierVariable(this, name);
1296
+ }
1297
+
1298
+ /**
1299
+ * terser's `conflicting_def_shallow`.
1300
+ * @param {string} name a name
1301
+ * @returns {boolean} whether it is declared here or names a definition read here
1302
+ */
1303
+ conflictingDefinitionShallow(name) {
1304
+ const { enclosed } = this;
1305
+ for (let i = 0; i < enclosed.length; i++) {
1306
+ if (enclosed[i].name === name) return true;
1307
+ }
1308
+ return this.getBinding(name) !== undefined;
1309
+ }
1310
+
1311
+ /**
1312
+ * terser's `conflicting_def`.
1313
+ * @param {string} name a name
1314
+ * @returns {boolean} whether it is taken here or further out
1315
+ */
1316
+ conflictingDefinition(name) {
1317
+ for (
1318
+ let scope = /** @type {MinifierScope | null} */ (this);
1319
+ scope !== null;
1320
+ scope = /** @type {MinifierScope | null} */ (scope.upper)
1321
+ ) {
1322
+ if (scope.conflictingDefinitionShallow(name)) return true;
1323
+ }
1324
+ return false;
1325
+ }
1326
+
1327
+ /**
1328
+ * terser's `mark_enclosed`: records that each scope from this one out to a
1329
+ * definition's reads it.
1330
+ * @param {MinifierVariable} variable the definition
1331
+ * @returns {void}
1332
+ */
1333
+ markEnclosed(variable) {
1334
+ encloseVariable(this, variable);
1335
+ }
1336
+ }
1337
+
1338
+ /**
1339
+ * One name declared in one scope, or a global: terser's `SymbolDef`, less
1340
+ * what only the compressor reads.
1341
+ */
1342
+ class MinifierVariable extends Variable {
1343
+ /**
1344
+ * @param {string} name the declared name
1345
+ * @param {MinifierScope} scope the declaring scope, the toplevel for a global
1346
+ * @param {number} kind how it was first declared, as a `DECLARES_*` code
1347
+ */
1348
+ constructor(name, scope, kind) {
1349
+ super(name, scope);
1350
+ /** @type {number} how it was first declared, as a `DECLARES_*` code */
1351
+ this.kind = kind;
1352
+ /** @type {number} every way it was declared, one bit per `DECLARES_*` code */
1353
+ this.declarations = 1 << kind;
1354
+ /** @type {boolean} whether the toplevel declares it */
1355
+ this.global = false;
1356
+ /** @type {boolean} whether nothing declares it */
1357
+ this.undeclared = false;
1358
+ /** @type {number} how an `export` naming it keeps its name, as `EXPORT_*` */
1359
+ this.export = 0;
1360
+ /** @type {string | null} the name mangling gives it */
1361
+ // eslint-disable-next-line camelcase -- terser's name, which the printer reads
1362
+ this.mangled_name = null;
1363
+ /** @type {number} how many names read or write it, which the mangler gives the short names by */
1364
+ this.referenceCount = 0;
1365
+ }
1366
+ }
1367
+
1368
+ /**
1369
+ * Whether a definition is a variable rather than a label or a compressor's own definition.
1370
+ * @param {MinifierVariable | MinifierLabel | CompressorDefinition | import("./syntax-printer").NamedDefinition | null | undefined} value a definition
1371
+ * @returns {value is MinifierVariable} true when the value is a variable
1372
+ */
1373
+ const isMinifierVariable = (value) => value instanceof MinifierVariable;
1374
+
1375
+ /** A label: a statement's, its `break`s and `continue`s naming it too. */
1376
+ class MinifierLabel {
1377
+ /**
1378
+ * @param {string} name the name
1379
+ * @param {MinifierLabel | null} parent the label of the nearest labeled statement around, across functions
1380
+ */
1381
+ constructor(name, parent) {
1382
+ /** @type {string} */
1383
+ this.name = name;
1384
+ /** @type {string | null} the name mangling gives it */
1385
+ // eslint-disable-next-line camelcase -- terser's name, which the printer reads
1386
+ this.mangled_name = null;
1387
+ /** @type {MinifierLabel | null} */
1388
+ this.parent = parent;
1389
+ /** @type {number} where the mangler's label names stood when it named this one */
1390
+ this.counter = -1;
1391
+ }
1392
+ }
1393
+
1394
+ /**
1395
+ * A scope as the compressor reads it: the minifier's, and what terser's
1396
+ * compressor records of it besides. The node opening it holds it as its
1397
+ * `block_scope`, a function's or the program's as a block's does.
1398
+ */
1399
+ class CompressorScope extends MinifierScope {
1400
+ /**
1401
+ * @param {ScopeType} type what opened this scope
1402
+ * @param {CompressorNode} node the node opening it
1403
+ * @param {CompressorScopeShape | null} upper the enclosing scope
1404
+ * @param {boolean} isVarScope whether `var` and function declarations hoist to here
1405
+ */
1406
+ constructor(type, node, upper, isVarScope) {
1407
+ // Made with no parent, so the parent lists no child: the compressor never
1408
+ // reads `childScopes`, and its tree moves, copies and drops scopes.
1409
+ super(
1410
+ type,
1411
+ /** @type {PrintNode} */ (
1412
+ /** @type {PrintNode | CompressorNode} */ (node)
1413
+ ),
1414
+ null,
1415
+ true
1416
+ );
1417
+ this.upper = /** @type {Scope | null} */ (
1418
+ /** @type {Scope | CompressorScopeShape | null} */ (upper)
1419
+ );
1420
+ if (!isVarScope) {
1421
+ this.variableScope = /** @type {Scope} */ (this.upper).variableScope;
1422
+ }
1423
+ /** @type {boolean} whether a function reads its own `arguments` */
1424
+ this.usesArguments = false;
1425
+ /** @type {import("./syntax-printer").UnusedScanLog | null} what `drop_unused` found scanning the function, for the scopes around it */
1426
+ this.unusedScan = null;
1427
+ /** @type {number} where the symbols under this scope's node start in the reduce phase's symbol order */
1428
+ this.hoistStart = 0;
1429
+ /** @type {number} where they end, exclusive */
1430
+ this.hoistEnd = 0;
1431
+ }
1432
+
1433
+ /**
1434
+ * The scope of a node made of this scope's node: as terser's node was a
1435
+ * scope, it is a scope of its own, holding and reading the same definitions.
1436
+ * @param {CompressorNode} node the node made of this scope's
1437
+ * @returns {CompressorScopeShape} the scope
1438
+ */
1439
+ share(node) {
1440
+ const shared = new CompressorScope(
1441
+ this.type,
1442
+ node,
1443
+ /** @type {CompressorScopeShape | null} */ (
1444
+ /** @type {CompressorScopeShape | Scope | null} */ (this.upper)
1445
+ ),
1446
+ this.variableScope === this
1447
+ );
1448
+ shared.variables = this.variables;
1449
+ shared._index = this._index;
1450
+ shared.enclosed = this.enclosed;
1451
+ shared.usesEval = this.usesEval;
1452
+ shared.usesWith = this.usesWith;
1453
+ shared.usesArguments = this.usesArguments;
1454
+ return /** @type {CompressorScopeShape} */ (
1455
+ /** @type {CompressorScopeShape | CompressorScope} */ (shared)
1456
+ );
1457
+ }
1458
+
1459
+ /**
1460
+ * Takes copies of what this scope shares with the scope it was made of, as
1461
+ * terser's `clone` of a scope does.
1462
+ * @returns {void}
1463
+ */
1464
+ detach() {
1465
+ if (this.variables !== NO_VARIABLE_LIST) {
1466
+ this.variables = [...this.variables];
1467
+ }
1468
+ if (this._index !== undefined) this._index = new Map(this._index);
1469
+ this.enclosed = [...this.enclosed];
1470
+ }
1471
+
1472
+ /**
1473
+ * A copy of this scope for a copy of its node.
1474
+ * @param {CompressorNode} node the copy of its node
1475
+ * @returns {CompressorScopeShape} the copy
1476
+ */
1477
+ copyFor(node) {
1478
+ const copy = this.share(node);
1479
+ copy.detach();
1480
+ return copy;
1481
+ }
1482
+
1483
+ /**
1484
+ * Adds a definition this scope declares under its name.
1485
+ * @param {CompressorDefinition} variable the definition
1486
+ * @returns {void}
1487
+ */
1488
+ bind(variable) {
1489
+ addBinding(
1490
+ this,
1491
+ /** @type {Variable} */ (
1492
+ /** @type {Variable | CompressorDefinition} */ (variable)
1493
+ )
1494
+ );
1495
+ }
1496
+
1497
+ /**
1498
+ * terser's `def_variable`: declares a symbol's name here.
1499
+ * @param {CompressorNode} symbol the declaring symbol
1500
+ * @param {CompressorNode | null | undefined} init what it is initialized to
1501
+ * @param {(node: CompressorNode) => boolean} isFunction whether a node is a function expression
1502
+ * @returns {CompressorDefinition} its definition, made or joined
1503
+ */
1504
+ defineVariable(symbol, init, isFunction) {
1505
+ const name = symbol.name;
1506
+ let variable = /** @type {CompressorDefinition | undefined} */ (
1507
+ /** @type {CompressorDefinition | Variable | undefined} */ (
1508
+ this.getBinding(name)
1509
+ )
1510
+ );
1511
+ if (variable !== undefined) {
1512
+ variable.identifiers.push(symbol);
1513
+ if (
1514
+ variable.init &&
1515
+ (variable.scope !== symbol.scope || isFunction(variable.init))
1516
+ ) {
1517
+ variable.init = init;
1518
+ }
1519
+ } else {
1520
+ variable = createCompressorDefinition(
1521
+ name,
1522
+ /** @type {CompressorScopeShape} */ (
1523
+ /** @type {CompressorScopeShape | CompressorScope} */ (this)
1524
+ ),
1525
+ 0,
1526
+ symbol,
1527
+ init
1528
+ );
1529
+ this.bind(variable);
1530
+ variable.global = this.upper === null;
1531
+ }
1532
+ return (symbol.definition = variable);
1533
+ }
1534
+
1535
+ /**
1536
+ * terser's `add_child_scope`: moves a function's or class's scope into this
1537
+ * one, which with each scope around it reads what the moved one reads from
1538
+ * them. Nothing lists a compressor scope's children, so nothing else moves.
1539
+ * @param {CompressorScopeShape} child the scope moved in
1540
+ * @param {(() => boolean) | null} readsArguments for an arrow, whether it reads the `arguments` of the function it moves into
1541
+ * @returns {void}
1542
+ */
1543
+ adopt(child, readsArguments) {
1544
+ const self = /** @type {CompressorScopeShape} */ (
1545
+ /** @type {CompressorScopeShape | CompressorScope} */ (this)
1546
+ );
1547
+ if (child.upper === self) return;
1548
+ child.upper = self;
1549
+ if (
1550
+ readsArguments !== null &&
1551
+ this.type === "function" &&
1552
+ !this.usesArguments
1553
+ ) {
1554
+ this.usesArguments = readsArguments();
1555
+ }
1556
+ this.usesWith = this.usesWith || child.usesWith;
1557
+ this.usesEval = this.usesEval || child.usesEval;
1558
+ /** @type {CompressorScopeShape[]} */
1559
+ const ancestry = [];
1560
+ for (
1561
+ let current = /** @type {CompressorScopeShape | null} */ (self);
1562
+ current !== null;
1563
+ current = current.upper
1564
+ ) {
1565
+ ancestry.push(current);
1566
+ }
1567
+ ancestry.reverse();
1568
+ const enclosedByChild = new Set(child.enclosed);
1569
+ /** @type {CompressorDefinition[]} */
1570
+ const toEnclose = [];
1571
+ for (const ancestor of ancestry) {
1572
+ const scope = /** @type {MinifierScope} */ (
1573
+ /** @type {MinifierScope | CompressorScopeShape} */ (ancestor)
1574
+ );
1575
+ for (const definition of toEnclose) {
1576
+ encloseUnique(
1577
+ scope,
1578
+ /** @type {MinifierVariable} */ (
1579
+ /** @type {MinifierVariable | CompressorDefinition} */ (definition)
1580
+ )
1581
+ );
1582
+ }
1583
+ const { variables } = ancestor;
1584
+ // Where the moved scope encloses fewer names than this one declares,
1585
+ // they are looked up here, and the variables read in order only to
1586
+ // order two or more of them.
1587
+ let left = variables.length;
1588
+ /** @type {CompressorDefinition | undefined} */
1589
+ let declared;
1590
+ if (left > enclosedByChild.size) {
1591
+ left = 0;
1592
+ for (const definition of enclosedByChild) {
1593
+ if (ancestor.getBinding(definition.name) !== definition) continue;
1594
+ declared = definition;
1595
+ left++;
1596
+ }
1597
+ if (left === 0) continue;
1598
+ if (left === 1) {
1599
+ const only = /** @type {CompressorDefinition} */ (declared);
1600
+ if (!toEnclose.includes(only)) toEnclose.push(only);
1601
+ encloseUnique(
1602
+ scope,
1603
+ /** @type {MinifierVariable} */ (
1604
+ /** @type {MinifierVariable | CompressorDefinition} */ (only)
1605
+ )
1606
+ );
1607
+ continue;
1608
+ }
1609
+ }
1610
+ for (let i = 0; i < variables.length; i++) {
1611
+ const definition = variables[i];
1612
+ if (enclosedByChild.has(definition)) {
1613
+ if (!toEnclose.includes(definition)) toEnclose.push(definition);
1614
+ encloseUnique(
1615
+ scope,
1616
+ /** @type {MinifierVariable} */ (
1617
+ /** @type {MinifierVariable | CompressorDefinition} */ (
1618
+ definition
1619
+ )
1620
+ )
1621
+ );
1622
+ if (--left === 0) break;
1623
+ }
1624
+ }
1625
+ }
1626
+ }
1627
+
1628
+ /**
1629
+ * terser's `add_reference`: a symbol in this scope reads its definition.
1630
+ * @param {CompressorNode} symbol the symbol
1631
+ * @returns {void}
1632
+ */
1633
+ addReference(symbol) {
1634
+ const variable = symbol.definition;
1635
+ variable.references.push(symbol);
1636
+ encloseVariable(
1637
+ this,
1638
+ /** @type {MinifierVariable} */ (
1639
+ /** @type {MinifierVariable | CompressorDefinition} */ (variable)
1640
+ )
1641
+ );
1642
+ }
1643
+ }
1644
+
1645
+ let nextCompressorVariableId = 1;
1646
+
1647
+ /**
1648
+ * One name declared in one scope, or a global: terser's `SymbolDef`, its
1649
+ * `orig` the base's `identifiers`, with what the compressor records of it.
1650
+ */
1651
+ class CompressorVariable extends MinifierVariable {
1652
+ /**
1653
+ * @param {string} name the declared name
1654
+ * @param {CompressorScopeShape | null} scope the declaring scope, the toplevel for a global
1655
+ * @param {number} kind how it was first declared, as a `DECLARES_*` code, 0 where the compressor declares it
1656
+ * @param {CompressorNode | { name: string }} orig its first declaring symbol
1657
+ * @param {CompressorNode | null | undefined} init what it is initialized to
1658
+ */
1659
+ constructor(name, scope, kind, orig, init) {
1660
+ super(
1661
+ name,
1662
+ /** @type {MinifierScope} */ (
1663
+ /** @type {MinifierScope | CompressorScopeShape | null} */ (scope)
1664
+ ),
1665
+ kind
1666
+ );
1667
+ this.identifiers = [
1668
+ /** @type {Identifier} */ (
1669
+ /** @type {Identifier | CompressorNode | { name: string }} */ (orig)
1670
+ )
1671
+ ];
1672
+ /** @type {CompressorNode | null | undefined} what it is initialized to */
1673
+ this.init = init;
1674
+ /** @type {number} a number no other definition has, in the order made */
1675
+ this.id = nextCompressorVariableId++;
1676
+ /* eslint-disable camelcase -- terser's names, which the compressor reads */
1677
+ /** @type {number} how many of its declarations were dropped */
1678
+ this.eliminated = 0;
1679
+ /** @type {number} how many times it is assigned */
1680
+ this.assignments = 0;
1681
+ /** @type {number} how many times a destructuring pattern or a loop head names it, each a write `assignments` misses */
1682
+ this.patternWrites = 0;
1683
+ /** @type {number} how many of its reads were replaced by its value */
1684
+ this.replaced = 0;
1685
+ /** @type {boolean} whether it is assigned in a chain */
1686
+ this.chained = false;
1687
+ /** @type {boolean} whether its value is read where it may be changed */
1688
+ this.direct_access = false;
1689
+ /** @type {number} how many properties are read off it before its value escapes, 0 where it does not */
1690
+ this.escaped = 0;
1691
+ /** @type {boolean} whether its value itself escapes, not only a property read off it */
1692
+ this.leaked = false;
1693
+ /** @type {number} how many of its reads are its own function's calls of itself */
1694
+ this.recursive_refs = 0;
1695
+ /** @type {boolean | string | undefined} whether it is read once, "m" where that read may change it */
1696
+ this.single_use = false;
1697
+ /** @type {CompressorNode | (() => CompressorNode) | false | null | undefined} its value, as `reduce_vars` worked it out, false where unknown */
1698
+ this.fixed = false;
1699
+ /* eslint-enable camelcase */
1700
+ /** @type {Reference[]} the symbols reading it, which `SymbolDefinition` types as nodes */
1701
+ this.references = [];
1702
+ /** @type {number} the last `drop_unused` run to find it in use, 0 for none */
1703
+ this.inUseRun = 0;
1704
+ /** @type {CompressorNode | undefined} the name a copy of it was set from, kept where a write through the copy dropped `fixed` */
1705
+ this.copyOf = undefined;
1706
+ /** @type {boolean} whether `reduce_vars` met a read of it before any value was set */
1707
+ this.readUnset = false;
1708
+ /** @type {boolean} whether `reduce_vars` met a declaration of it giving a value */
1709
+ this.declaredWithValue = false;
1710
+ }
1711
+ }
1712
+
1713
+ /**
1714
+ * A definition the compressor reads, typed as it reads the shared model.
1715
+ * @param {string} name the declared name
1716
+ * @param {CompressorScopeShape | null} scope the declaring scope, the toplevel for a global
1717
+ * @param {number} kind how it was first declared, as a `DECLARES_*` code, 0 where the compressor declares it
1718
+ * @param {CompressorNode | { name: string }} orig its first declaring symbol
1719
+ * @param {CompressorNode | null | undefined} init what it is initialized to
1720
+ * @returns {CompressorDefinition} the definition
1721
+ */
1722
+ const createCompressorDefinition = (name, scope, kind, orig, init) =>
1723
+ /** @type {CompressorDefinition} */ (
1724
+ /** @type {CompressorDefinition | CompressorVariable} */ (
1725
+ new CompressorVariable(name, scope, kind, orig, init)
1726
+ )
1727
+ );
1728
+
1729
+ /**
1730
+ * A scope the compressor reads, typed as it reads the shared model.
1731
+ * @param {ScopeType} type what opened this scope
1732
+ * @param {CompressorNode} node the node opening it
1733
+ * @param {CompressorScopeShape | null} upper the enclosing scope
1734
+ * @param {boolean} isVarScope whether `var` and function declarations hoist to here
1735
+ * @returns {CompressorScopeShape} the scope
1736
+ */
1737
+ const createCompressorScope = (type, node, upper, isVarScope) =>
1738
+ /** @type {CompressorScopeShape} */ (
1739
+ /** @type {CompressorScopeShape | CompressorScope} */ (
1740
+ new CompressorScope(type, node, upper, isVarScope)
1741
+ )
1742
+ );
1743
+
1744
+ /**
1745
+ * The options the minifier's analysis reads, its mangle options among them.
1746
+ * @typedef {object} MinifierScopeOptions
1747
+ * @property {boolean=} module whether the program is a module, so strict
1748
+ * @property {boolean=} ie8 whether catch parameters belong to their function
1749
+ * @property {boolean=} safari10 whether a loop's scope reads its parent's names, and catch parameters belong to their function
1750
+ * @property {boolean | RegExp=} keep_fnames which function names survive, collecting the declarators naming one
1751
+ * @property {boolean | RegExp=} keep_classnames which class names survive, collecting the declarators naming one under `classDeclarators`
1752
+ * @property {boolean=} classDeclarators whether, under `keep_classnames`, the names declarators give anonymous classes are kept as `keep_fnames` keeps a function's
1753
+ * @property {boolean=} parameterScopes whether names are scoped as the spec scopes them where terser does not: a parameter list's or a catch parameter's reads skip what the body declares, and a block's async or generator function stays in the block
1754
+ * @property {number=} spelledNames which names to collect that the mangler may give the name beside them to write less: 1 for an import's or export's, 2 for a key's too
1755
+ */
1756
+
1757
+ /**
1758
+ * @typedef {object} MinifierScopeAnalysis
1759
+ * @property {MinifierScope} toplevel the program's scope, its `childScopes` in the order the mangler walks them
1760
+ * @property {MinifierLabel[]} labels every label, in the same order
1761
+ * @property {Map<string, MinifierVariable>} globals the names nothing declares, in the order first read
1762
+ * @property {Set<MinifierScope>} blockDefunScopes the function scopes holding a function declared in a block
1763
+ * @property {PrintIdentifier[] | null} functionDeclarators under `keep_fnames`, the names declarators give anonymous functions, in the order the mangler asks `keep_fnames` of them
1764
+ * @property {PrintIdentifier[] | null} classDeclarators under `classDeclarators` and `keep_classnames`, the names declarators give anonymous classes
1765
+ * @property {PrintIdentifier[]} catchParameters unless `ie8` or `safari10` move them, the catch parameters, each named where the mangler's walk meets its scope
1766
+ * @property {boolean} namesPrivate whether the program names a private member, which renaming walks it for
1767
+ * @property {SpelledNames | null} spelledNames under `spelledNames`, the names a key or an import or export spells for a name beside it
1768
+ */
1769
+
1770
+ /**
1771
+ * Where a name stands beside one spelled for it: a property's key, which the
1772
+ * name as its value lets print alone, or an import's or export's other name.
1773
+ * @typedef {object} SpelledNames
1774
+ * @property {PrintIdentifier[]} identifiers each name, its `definition` read once the analysis resolves
1775
+ * @property {string[]} spellings the name spelled beside each
1776
+ * @property {number[]} savings the characters each saves, its own name one long, where it takes the name spelled
1777
+ */
1778
+
1779
+ /**
1780
+ * @param {PrintNode} node a node
1781
+ * @returns {boolean} whether terser holds it as a scope its statements sit in directly
1782
+ */
1783
+ const isStatementScope = (node) =>
1784
+ node.type === "Program" ||
1785
+ node.type === "FunctionDeclaration" ||
1786
+ node.type === "FunctionExpression" ||
1787
+ node.type === "ArrowFunctionExpression" ||
1788
+ node.type === "StaticBlock";
1789
+
1790
+ /**
1791
+ * @param {PrintNode | null} node a binding pattern, `null` for an array's hole
1792
+ * @param {string} name a name
1793
+ * @returns {boolean} whether the pattern binds the name
1794
+ */
1795
+ const bindsName = (node, name) => {
1796
+ if (node === null) return false;
1797
+ switch (node.type) {
1798
+ case "ObjectPattern":
1799
+ return node.properties.some((property) =>
1800
+ bindsName(
1801
+ property.type === "Property" ? property.value : property,
1802
+ name
1803
+ )
1804
+ );
1805
+ case "ArrayPattern":
1806
+ return node.elements.some((element) => bindsName(element, name));
1807
+ case "AssignmentPattern":
1808
+ return bindsName(node.left, name);
1809
+ case "RestElement":
1810
+ return bindsName(node.argument, name);
1811
+ default:
1812
+ return /** @type {PrintIdentifier} */ (node).name === name;
1813
+ }
1814
+ };
1815
+
1816
+ /**
1817
+ * @param {PrintNode | null | undefined} node a statement, or a loop's head, which a compressed `for` may lack
1818
+ * @param {string} name a name
1819
+ * @returns {boolean} whether it declares the name with `let`, `const`, `using` or a class
1820
+ */
1821
+ const declaresLexically = (node, name) =>
1822
+ node !== null &&
1823
+ node !== undefined &&
1824
+ (node.type === "VariableDeclaration"
1825
+ ? node.kind !== "var" &&
1826
+ node.declarations.some((declarator) =>
1827
+ bindsName(/** @type {PrintVariableDeclarator} */ (declarator).id, name)
1828
+ )
1829
+ : node.type === "ClassDeclaration" &&
1830
+ /** @type {PrintIdentifier} */ (node.id).name === name);
1831
+
1832
+ /**
1833
+ * @param {PrintNode} node a node
1834
+ * @returns {node is PrintExport} whether it is an `export`
1835
+ */
1836
+ const isExport = (node) =>
1837
+ node.type === "ExportNamedDeclaration" ||
1838
+ node.type === "ExportDefaultDeclaration" ||
1839
+ node.type === "ExportAllDeclaration";
1840
+
1841
+ /**
1842
+ * @param {MinifierScope} scope the scope declaring it
1843
+ * @param {MinifierVariable} variable a definition
1844
+ * @param {number} read the read's place in the analysis's count
1845
+ * @returns {boolean} whether the read sits in the scope's parameter list and the definition in its body, which the list cannot see
1846
+ */
1847
+ const isHiddenFromParameters = (scope, variable, read) =>
1848
+ read < scope.parameterEnd &&
1849
+ read >= scope.parameterStart &&
1850
+ variable.kind !== DECLARES_FUNARG &&
1851
+ variable.kind !== DECLARES_LAMBDA &&
1852
+ variable.kind !== DECLARES_CATCH;
1853
+
1854
+ /**
1855
+ * @param {MinifierScope} from the scope a name is read in
1856
+ * @param {string} name the name
1857
+ * @param {number=} read the read's place in the analysis's count, under `parameterScopes`
1858
+ * @returns {MinifierVariable | undefined} what it resolves to from there
1859
+ */
1860
+ const findMinifierVariable = (from, name, read = -1) => {
1861
+ for (let scope = /** @type {Scope | null} */ (from); scope !== null;) {
1862
+ // `getBinding`, inlined: the interpreter pays a call per scope climbed
1863
+ const index = scope._index;
1864
+ /** @type {MinifierVariable | undefined} */
1865
+ let variable;
1866
+ if (index !== undefined) {
1867
+ variable = /** @type {MinifierVariable | undefined} */ (index.get(name));
1868
+ } else {
1869
+ const variables = scope.variables;
1870
+ for (let i = 0; i < variables.length; i++) {
1871
+ if (variables[i].name === name) {
1872
+ variable = /** @type {MinifierVariable} */ (variables[i]);
1873
+ break;
1874
+ }
1875
+ }
1876
+ }
1877
+ if (
1878
+ variable !== undefined &&
1879
+ !isHiddenFromParameters(
1880
+ /** @type {MinifierScope} */ (scope),
1881
+ variable,
1882
+ read
1883
+ )
1884
+ ) {
1885
+ return variable;
1886
+ }
1887
+ scope = scope.upper;
1888
+ }
1889
+ return undefined;
1890
+ };
1891
+
1892
+ /**
1893
+ * terser's `mark_enclosed`: each scope from one out to a definition's reads it.
1894
+ * @param {MinifierScope} from the scope reading it
1895
+ * @param {MinifierVariable} variable the definition
1896
+ * @returns {void}
1897
+ */
1898
+ const encloseVariable = (from, variable) => {
1899
+ for (let scope = /** @type {Scope | null} */ (from); scope !== null;) {
1900
+ encloseUnique(/** @type {MinifierScope} */ (scope), variable);
1901
+ if (scope === variable.scope) break;
1902
+ scope = scope.upper;
1903
+ }
1904
+ };
1905
+
1906
+ /**
1907
+ * Analyses the minifier's tree as terser's `figure_out_scope` does for its
1908
+ * mangler: the same scopes, definitions, enclosed lists and errors, in the
1909
+ * same orders, which the names it hands out depend on. Every name's
1910
+ * `definition` is set: its definition, its label, or null.
1911
+ */
1912
+ class MinifierScopeAnalyzer extends ScopeAnalyzer {
1913
+ /**
1914
+ * @param {PrintProgram} program the tree, its names as written
1915
+ * @param {MinifierScopeOptions} options the mangle options
1916
+ * @param {(node: PrintNode, message: string, tables?: TokenTables) => never} raise throws the parse error a misplaced declaration is
1917
+ * @param {((node: PrintNode) => void) | undefined} release drops what only the compressor read off each node read, where nobody keeps the tree
1918
+ */
1919
+ constructor(program, options, raise, release) {
1920
+ super(false);
1921
+ /** @type {(node: PrintNode, message: string, tables?: TokenTables) => never} */
1922
+ this.raise = raise;
1923
+ /** @type {((node: PrintNode) => void) | undefined} */
1924
+ this.release = release;
1925
+ // What the tree's token numbers are read through, for a message's place.
1926
+ /** @type {TokenTables | undefined} */
1927
+ this.tokenTables = program.tokenTables || undefined;
1928
+ /** @type {boolean} */
1929
+ this.legacyCatch = Boolean(options.ie8 || options.safari10);
1930
+ /** @type {boolean} */
1931
+ this.safari10 = Boolean(options.safari10);
1932
+ /** @type {boolean} */
1933
+ this.parameterScopes = Boolean(options.parameterScopes);
1934
+ // Only this analysis's reads are counted against a range, so each is
1935
+ // cleared once they resolve, before an analysis of a copy counts anew.
1936
+ /** @type {MinifierScope[]} the scopes holding a range of parameter reads */
1937
+ this.parameterRanges = [];
1938
+ /** @type {MinifierScope} */
1939
+ this.toplevel = new MinifierScope("global", program, null, true);
1940
+ this.scope = this.toplevel;
1941
+ /** @type {MinifierLabel[]} */
1942
+ this.labels = [];
1943
+ /** @type {Map<string, MinifierVariable>} */
1944
+ this.globals = new Map();
1945
+ /** @type {Set<MinifierScope>} */
1946
+ this.blockDefunScopes = new Set();
1947
+ /** @type {PrintIdentifier[] | null} */
1948
+ this.functionDeclarators = options.keep_fnames ? [] : null;
1949
+ /** @type {PrintIdentifier[] | null} */
1950
+ this.classDeclarators =
1951
+ options.classDeclarators && options.keep_classnames ? [] : null;
1952
+ /** @type {MinifierScope[]} */
1953
+ this.forScopes = [];
1954
+ // The names read, and catch parameters, in the order terser's walk meets them.
1955
+ /** @type {(PrintIdentifier | PrintLiteral)[]} */
1956
+ this.referenceNodes = [];
1957
+ /** @type {MinifierScope[]} */
1958
+ this.referenceScopes = [];
1959
+ /** @type {number[]} */
1960
+ this.referenceFlags = [];
1961
+ // Under `ie8` or `safari10`, the catch parameters in `walk`'s order.
1962
+ /** @type {PrintIdentifier[]} */
1963
+ this.catchNames = [];
1964
+ /** @type {MinifierScope[]} */
1965
+ this.catchScopes = [];
1966
+ // Otherwise the catch parameters, which the mangler names with their scope.
1967
+ /** @type {PrintIdentifier[]} */
1968
+ this.catchParameters = [];
1969
+ /** @type {boolean} whether the program names a private member */
1970
+ this.namesPrivate = false;
1971
+ /** @type {PrintNode[]} the nodes terser's walk has pushed, the node visited last */
1972
+ this.stack = [];
1973
+ /** @type {boolean} */
1974
+ this.strict = Boolean(options.module);
1975
+ /** @type {Map<string, MinifierLabel>} the labels of the statements around, up to the nearest function */
1976
+ this.labelsInScope = new Map();
1977
+ /** @type {MinifierLabel | null} */
1978
+ this.currentLabel = null;
1979
+ /** @type {PrintNode | null} the pattern the walk is inside, which `_markExport` counts from */
1980
+ this.inDestructuring = null;
1981
+ /** @type {SpelledNames | null} */
1982
+ this.spelledNames = options.spelledNames
1983
+ ? { identifiers: [], spellings: [], savings: [] }
1984
+ : null;
1985
+ /** @type {boolean} whether a key spells a name, which prints alone where it is its value's */
1986
+ this.spelledKeys = options.spelledNames === SPELLED_KEYS;
1987
+ }
1988
+
1989
+ /**
1990
+ * Collects a name and one spelled beside it, under `spelledNames`.
1991
+ * @param {PrintNode | null} identifier the name, if it is one
1992
+ * @param {PrintNode | null} spelled what spells the other, if a name
1993
+ * @param {number} saving the characters it saves taking that name
1994
+ * @returns {void}
1995
+ */
1996
+ _spell(identifier, spelled, saving) {
1997
+ const names = this.spelledNames;
1998
+ if (
1999
+ names === null ||
2000
+ identifier === null ||
2001
+ spelled === null ||
2002
+ identifier.type !== "Identifier"
2003
+ ) {
2004
+ return;
2005
+ }
2006
+ const spelling =
2007
+ spelled.type === "Identifier"
2008
+ ? spelled.name
2009
+ : spelled.type !== "Literal"
2010
+ ? undefined
2011
+ : typeof spelled.value === "string"
2012
+ ? spelled.value
2013
+ : // A module's quoted name holds its text as its name.
2014
+ /** @type {{ name?: string }} */ (spelled).name;
2015
+ if (
2016
+ spelling === undefined ||
2017
+ !SPELLABLE_NAME.test(spelling) ||
2018
+ NAMES_NO_BINDING_TAKES.has(spelling) ||
2019
+ // A shorthand `__proto__` is an own property; `__proto__:` sets the prototype.
2020
+ spelling === "__proto__"
2021
+ ) {
2022
+ return;
2023
+ }
2024
+ names.identifiers.push(identifier);
2025
+ names.spellings.push(spelling);
2026
+ names.savings.push(saving);
2027
+ }
2028
+
2029
+ /**
2030
+ * Collects a property's value named as its key could be, under `spelledNames`.
2031
+ * @param {PrintProperty} property a property of an object or a pattern
2032
+ * @returns {void}
2033
+ */
2034
+ _spellProperty(property) {
2035
+ if (!this.spelledKeys || property.computed) return;
2036
+ const { value } = property;
2037
+ this._spell(
2038
+ value.type === "AssignmentPattern" ? value.left : value,
2039
+ property.key,
2040
+ SHORTHAND_SAVING
2041
+ );
2042
+ }
2043
+
2044
+ /**
2045
+ * @param {Token | number | null | undefined} token a node's token, or its number
2046
+ * @returns {Token | null | undefined} the token itself
2047
+ */
2048
+ tokenOf(token) {
2049
+ return this.tokenTables === undefined
2050
+ ? /** @type {Token | null | undefined} */ (token)
2051
+ : this.tokenTables.of(token);
2052
+ }
2053
+
2054
+ /**
2055
+ * @param {ScopeType} type what opens it
2056
+ * @param {PrintNode} node the node opening it
2057
+ * @param {boolean} isVarScope whether `var` hoists to here
2058
+ * @returns {MinifierScope} the scope, now current
2059
+ */
2060
+ _open(type, node, isVarScope) {
2061
+ const scope = new MinifierScope(type, node, this.scope, isVarScope);
2062
+ this.scope = scope;
2063
+ return scope;
2064
+ }
2065
+
2066
+ /**
2067
+ * Opens a block's scope, which inherits whether a `with` reaches it.
2068
+ * @param {ScopeType} type what opens it
2069
+ * @param {PrintNode} node a block's node
2070
+ * @returns {MinifierScope} the scope it leaves, now the new scope's parent
2071
+ */
2072
+ _enterBlock(type, node) {
2073
+ const outer = this.scope;
2074
+ this._open(type, node, false).usesWith = outer.usesWith;
2075
+ return outer;
2076
+ }
2077
+
2078
+ /**
2079
+ * terser's `def_variable`.
2080
+ * @param {MinifierScope} target the scope declaring it
2081
+ * @param {PrintIdentifier | null} identifier the name declaring it, if written
2082
+ * @param {string} name the name
2083
+ * @param {number} kind how it is declared
2084
+ * @returns {MinifierVariable} its definition, made or joined
2085
+ */
2086
+ _defineVariable(target, identifier, name, kind) {
2087
+ return this._addDeclaration(
2088
+ target,
2089
+ /** @type {MinifierVariable | undefined} */ (target.getBinding(name)),
2090
+ identifier,
2091
+ name,
2092
+ kind
2093
+ );
2094
+ }
2095
+
2096
+ /**
2097
+ * terser's `def_variable`, the scope's binding of the name already looked up.
2098
+ * @param {MinifierScope} target the scope declaring it
2099
+ * @param {MinifierVariable | undefined} variable what the scope binds the name to, if anything
2100
+ * @param {PrintIdentifier | null} identifier the name declaring it, if written
2101
+ * @param {string} name the name
2102
+ * @param {number} kind how it is declared
2103
+ * @returns {MinifierVariable} its definition, made or joined
2104
+ */
2105
+ _addDeclaration(target, variable, identifier, name, kind) {
2106
+ if (variable !== undefined) {
2107
+ variable.declarations |= 1 << kind;
2108
+ } else {
2109
+ variable = new MinifierVariable(name, target, kind);
2110
+ variable.global = target.upper === null;
2111
+ if (this.legacyCatch && kind === DECLARES_CATCH) {
2112
+ variable.references = [];
2113
+ }
2114
+ addBinding(target, variable);
2115
+ }
2116
+ if (identifier !== null) {
2117
+ if (this.release !== undefined) this.release(identifier);
2118
+ identifier.definition = variable;
2119
+ }
2120
+ return variable;
2121
+ }
2122
+
2123
+ /**
2124
+ * terser's `reference`.
2125
+ * @param {PrintIdentifier} identifier the name read
2126
+ * @param {MinifierScope} from the scope reading it
2127
+ * @param {MinifierVariable} variable what it reads
2128
+ * @returns {void}
2129
+ */
2130
+ _referenceVariable(identifier, from, variable) {
2131
+ variable.referenceCount++;
2132
+ if (variable.references !== NO_REFERENCES) {
2133
+ variable.references.push(
2134
+ new Reference(/** @type {Identifier} */ (identifier), from)
2135
+ );
2136
+ }
2137
+ encloseVariable(from, variable);
2138
+ }
2139
+
2140
+ /**
2141
+ * terser's `mark_export`, which counts its levels on terser's stack.
2142
+ * @param {MinifierVariable} variable a definition just made
2143
+ * @param {number} level where its declaration's statement is
2144
+ * @returns {void}
2145
+ */
2146
+ _markExport(variable, level) {
2147
+ const stack = this.stack;
2148
+ if (this.inDestructuring !== null) {
2149
+ let i = 0;
2150
+ do {
2151
+ level++;
2152
+ } while (stack[stack.length - 1 - i++] !== this.inDestructuring);
2153
+ }
2154
+ const node = stack[stack.length - 1 - level];
2155
+ if (node === undefined || !isExport(node)) {
2156
+ variable.export = 0;
2157
+ return;
2158
+ }
2159
+ // An ESTree tree read in makes a declaration a value terser keeps named.
2160
+ const declaration = /** @type {PrintNode} */ (
2161
+ node.exported_value || node.exported_definition
2162
+ );
2163
+ variable.export =
2164
+ node.type === "ExportDefaultDeclaration" &&
2165
+ Boolean(node.exported_definition) &&
2166
+ (declaration.type === "FunctionDeclaration" ||
2167
+ declaration.type === "ClassDeclaration")
2168
+ ? EXPORT_WANT_MANGLE
2169
+ : EXPORT_KEEP_NAME;
2170
+ }
2171
+
2172
+ /**
2173
+ * @param {PrintNode} node an import or export
2174
+ * @param {string} type terser's name for it
2175
+ * @returns {void}
2176
+ */
2177
+ _checkModuleStatement(node, type) {
2178
+ if (this.scope !== this.toplevel) {
2179
+ this.raise(
2180
+ node,
2181
+ `"${type}" statement may only appear at the top level`,
2182
+ this.tokenTables
2183
+ );
2184
+ }
2185
+ }
2186
+
2187
+ /**
2188
+ * @param {PrintIdentifier | PrintLiteral} node a name read, or a re-exported string
2189
+ * @param {number} flags what else is known of it, as `REFERENCE_*` bits
2190
+ * @returns {void}
2191
+ */
2192
+ _addReference(node, flags) {
2193
+ if (this.release !== undefined) this.release(node);
2194
+ this.referenceNodes.push(node);
2195
+ this.referenceScopes.push(this.scope);
2196
+ this.referenceFlags.push(flags);
2197
+ }
2198
+
2199
+ /**
2200
+ * A name a declaration or a pattern binds, or reads where `kind` is 0.
2201
+ * @param {PrintNode} node the name or pattern
2202
+ * @param {number} kind how it declares, as a `DECLARES_*` code, or 0
2203
+ * @returns {void}
2204
+ */
2205
+ _visitBinding(node, kind) {
2206
+ const stack = this.stack;
2207
+ switch (node.type) {
2208
+ case "Identifier":
2209
+ if (kind === 0) this._visitPrint(node);
2210
+ else this._declare(node, kind);
2211
+ return;
2212
+ case "ObjectPattern":
2213
+ this._visitPattern(node, node.properties, kind);
2214
+ return;
2215
+ case "ArrayPattern":
2216
+ this._visitPattern(node, node.elements, kind);
2217
+ return;
2218
+ case "AssignmentPattern":
2219
+ stack.push(node);
2220
+ this._visitBinding(node.left, kind);
2221
+ this._visitPrint(node.right);
2222
+ stack.pop();
2223
+ return;
2224
+ case "RestElement":
2225
+ stack.push(node);
2226
+ this._visitBinding(node.argument, kind);
2227
+ stack.pop();
2228
+ return;
2229
+ default:
2230
+ this._visitPrint(node);
2231
+ }
2232
+ }
2233
+
2234
+ /**
2235
+ * @param {PrintObject | PrintArray} pattern an object or array pattern
2236
+ * @param {(PrintNode | null)[]} elements its properties or elements, holes null
2237
+ * @param {number} kind how it declares, as a `DECLARES_*` code, or 0
2238
+ * @returns {void}
2239
+ */
2240
+ _visitPattern(pattern, elements, kind) {
2241
+ const stack = this.stack;
2242
+ const outer = this.inDestructuring;
2243
+ this.inDestructuring = pattern;
2244
+ stack.push(pattern);
2245
+ for (let i = 0; i < elements.length; i++) {
2246
+ const element = elements[i];
2247
+ if (!element) continue;
2248
+ if (element.type !== "Property") {
2249
+ this._visitBinding(element, kind);
2250
+ continue;
2251
+ }
2252
+ stack.push(element);
2253
+ if (element.computed) this._visitPrint(element.key);
2254
+ this._visitBinding(element.value, kind);
2255
+ this._spellProperty(element);
2256
+ stack.pop();
2257
+ }
2258
+ stack.pop();
2259
+ this.inDestructuring = outer;
2260
+ }
2261
+
2262
+ /**
2263
+ * A `var`, parameter, `let`, `const`, `using`, catch parameter or import.
2264
+ * @param {PrintIdentifier} identifier the name declared
2265
+ * @param {number} kind how, as a `DECLARES_*` code
2266
+ * @returns {void}
2267
+ */
2268
+ _declare(identifier, kind) {
2269
+ const { name } = identifier;
2270
+ const scope = this.scope;
2271
+ if (kind === DECLARES_IMPORT) {
2272
+ this._defineVariable(scope, identifier, name, kind);
2273
+ return;
2274
+ }
2275
+ const blockDeclaration =
2276
+ kind === DECLARES_LET ||
2277
+ kind === DECLARES_CONST ||
2278
+ kind === DECLARES_USING ||
2279
+ kind === DECLARES_CATCH;
2280
+ const defun = /** @type {MinifierScope} */ (scope.variableScope);
2281
+ const target = blockDeclaration ? scope : defun;
2282
+ const before = /** @type {MinifierVariable | undefined} */ (
2283
+ target.getBinding(name)
2284
+ );
2285
+ const earlier = before === undefined ? 0 : before.declarations;
2286
+ const variable = this._addDeclaration(
2287
+ target,
2288
+ before,
2289
+ identifier,
2290
+ name,
2291
+ kind
2292
+ );
2293
+ // A body's lexical `arguments` shadows the function's own, which is declared
2294
+ // as a parameter here; a parameter so named beside it the parser refuses.
2295
+ const shadowsOwnArguments =
2296
+ this.parameterScopes &&
2297
+ name === "arguments" &&
2298
+ earlier === 1 << DECLARES_FUNARG;
2299
+ if (
2300
+ !shadowsOwnArguments &&
2301
+ (blockDeclaration
2302
+ ? (earlier & ~(1 << DECLARES_LAMBDA)) !== 0
2303
+ : (earlier & LEXICAL_DECLARATIONS) !== 0)
2304
+ ) {
2305
+ this.raise(identifier, `"${name}" is redeclared`, this.tokenTables);
2306
+ }
2307
+ if (kind !== DECLARES_FUNARG) this._markExport(variable, 2);
2308
+ if (defun !== scope) {
2309
+ encloseVariable(scope, variable);
2310
+ const found = /** @type {MinifierVariable} */ (
2311
+ findMinifierVariable(scope, name)
2312
+ );
2313
+ if (found !== variable) {
2314
+ identifier.definition = found;
2315
+ this._referenceVariable(identifier, scope, found);
2316
+ }
2317
+ }
2318
+ if (kind === DECLARES_CATCH) {
2319
+ this._addReference(identifier, REFERENCE_CATCH);
2320
+ if (this.legacyCatch) {
2321
+ this.catchNames.push(identifier);
2322
+ this.catchScopes.push(scope);
2323
+ } else {
2324
+ this.catchParameters.push(identifier);
2325
+ }
2326
+ }
2327
+ }
2328
+
2329
+ /**
2330
+ * @param {PrintNode[]} nodes statements, arguments or a template's segments
2331
+ * @returns {void}
2332
+ */
2333
+ _visitList(nodes) {
2334
+ for (let i = 0; i < nodes.length; i++) this._visitPrint(nodes[i]);
2335
+ }
2336
+
2337
+ /**
2338
+ * Annex B's test for a sloppy block's function: a `var` of its name would be
2339
+ * an early error, which keeps the function in its block.
2340
+ * @param {MinifierScope} scope the scope the function is declared in
2341
+ * @param {string} name the function's name
2342
+ * @returns {boolean} true for `f` in `{ let f; { function f() {} } }`
2343
+ */
2344
+ _keepsInBlock(scope, name) {
2345
+ while (scope !== scope.variableScope) {
2346
+ const node = scope.node;
2347
+ switch (node.type) {
2348
+ case "BlockStatement":
2349
+ if (
2350
+ node.body.some((statement) => declaresLexically(statement, name))
2351
+ ) {
2352
+ return true;
2353
+ }
2354
+ break;
2355
+ case "SwitchStatement":
2356
+ if (
2357
+ node.cases.some((branch) =>
2358
+ branch.consequent.some((statement) =>
2359
+ declaresLexically(statement, name)
2360
+ )
2361
+ )
2362
+ ) {
2363
+ return true;
2364
+ }
2365
+ break;
2366
+ case "ForStatement":
2367
+ if (declaresLexically(node.init, name)) return true;
2368
+ break;
2369
+ case "ForInStatement":
2370
+ case "ForOfStatement":
2371
+ if (declaresLexically(node.left, name)) return true;
2372
+ break;
2373
+ case "CatchClause":
2374
+ // B.3.5 lets a `var` redeclare a plain catch parameter, not a pattern's.
2375
+ // The body's statements sit in this scope, with no block of their own.
2376
+ if (
2377
+ (node.param &&
2378
+ node.param.type !== "Identifier" &&
2379
+ bindsName(node.param, name)) ||
2380
+ node.body.body.some((statement) =>
2381
+ declaresLexically(statement, name)
2382
+ )
2383
+ ) {
2384
+ return true;
2385
+ }
2386
+ break;
2387
+ }
2388
+ scope = /** @type {MinifierScope} */ (scope.upper);
2389
+ }
2390
+ const node = scope.node;
2391
+ if (node.type === "Program") {
2392
+ return node.body.some((statement) => declaresLexically(statement, name));
2393
+ }
2394
+ const owner = /** @type {PrintFunction} */ (node);
2395
+ return (
2396
+ owner.params.some((param) => bindsName(param, name)) ||
2397
+ owner.body.body.some((statement) => declaresLexically(statement, name))
2398
+ );
2399
+ }
2400
+
2401
+ /**
2402
+ * @param {PrintFunction} node a function
2403
+ * @returns {void}
2404
+ */
2405
+ _visitMinifierFunction(node) {
2406
+ const outerStrict = this.strict;
2407
+ const outer = this.scope;
2408
+ const outerLabels = this.labelsInScope;
2409
+ const stack = this.stack;
2410
+ const inBlock =
2411
+ node.type === "FunctionDeclaration" &&
2412
+ !isStatementScope(stack[stack.length - 1]);
2413
+ if (inBlock) {
2414
+ this.blockDefunScopes.add(
2415
+ /** @type {MinifierScope} */ (outer.variableScope)
2416
+ );
2417
+ }
2418
+ stack.push(node);
2419
+ const lambda = this._open("function", node, true);
2420
+ if (node.type !== "ArrowFunctionExpression") {
2421
+ this._defineVariable(lambda, null, "arguments", DECLARES_FUNARG);
2422
+ }
2423
+ this.labelsInScope = new Map();
2424
+ const { id } = node;
2425
+ if (!id) {
2426
+ // An arrow or a method has no name of its own.
2427
+ } else if (id.role === "defun") {
2428
+ this._markExport(
2429
+ this._defineVariable(
2430
+ // Annex B hoists a sloppy block's plain function only.
2431
+ this.strict ||
2432
+ (this.parameterScopes &&
2433
+ (node.async ||
2434
+ node.generator ||
2435
+ (inBlock && this._keepsInBlock(outer, id.name))))
2436
+ ? outer
2437
+ : /** @type {MinifierScope} */ (outer.variableScope),
2438
+ id,
2439
+ id.name,
2440
+ DECLARES_DEFUN
2441
+ ),
2442
+ 1
2443
+ );
2444
+ } else {
2445
+ this._defineVariable(lambda, id, id.name, DECLARES_LAMBDA);
2446
+ }
2447
+ if (id && node.type === "FunctionExpression") {
2448
+ lambda.functionName = /** @type {MinifierVariable} */ (id.definition);
2449
+ }
2450
+ const { params } = node;
2451
+ const ranged = this.parameterScopes && params.length !== 0;
2452
+ if (ranged) {
2453
+ lambda.parameterStart = this.referenceNodes.length;
2454
+ this.parameterRanges.push(lambda);
2455
+ }
2456
+ for (let i = 0; i < params.length; i++) {
2457
+ this._visitBinding(params[i], DECLARES_FUNARG);
2458
+ }
2459
+ if (ranged) lambda.parameterEnd = this.referenceNodes.length;
2460
+ if (this.release !== undefined) this.release(node.body);
2461
+ this._visitList(node.body.body);
2462
+ this.scope = outer;
2463
+ this.labelsInScope = outerLabels;
2464
+ this.strict = outerStrict;
2465
+ stack.pop();
2466
+ }
2467
+
2468
+ /**
2469
+ * @param {PrintClass} node a class
2470
+ * @returns {void}
2471
+ */
2472
+ _visitMinifierClass(node) {
2473
+ const outerStrict = this.strict;
2474
+ const outer = this.scope;
2475
+ const outerLabels = this.labelsInScope;
2476
+ this.stack.push(node);
2477
+ this.strict = true;
2478
+ const classScope = this._open("class", node, true);
2479
+ this.labelsInScope = new Map();
2480
+ const { id } = node;
2481
+ if (id) {
2482
+ this._markExport(
2483
+ id.role === "defClass"
2484
+ ? this._defineVariable(outer, id, id.name, DECLARES_DEF_CLASS)
2485
+ : this._defineVariable(classScope, id, id.name, DECLARES_CLASS),
2486
+ 1
2487
+ );
2488
+ }
2489
+ if (node.superClass) this._visitPrint(node.superClass);
2490
+ this._visitList(node.body.body);
2491
+ this.scope = outer;
2492
+ this.labelsInScope = outerLabels;
2493
+ this.strict = outerStrict;
2494
+ this.stack.pop();
2495
+ }
2496
+
2497
+ /**
2498
+ * A call under `ie8` or `safari10`, whose catch parameters terser's
2499
+ * `walk` meets callee first, where its `_walk` meets the arguments first.
2500
+ * @param {PrintCallExpression | PrintNewExpression} node the call
2501
+ * @returns {void}
2502
+ */
2503
+ _visitLegacyCall(node) {
2504
+ const { catchNames, catchScopes } = this;
2505
+ this.stack.push(node);
2506
+ const argumentsStart = catchNames.length;
2507
+ this._visitList(node.arguments);
2508
+ const calleeStart = catchNames.length;
2509
+ this._visitPrint(node.callee);
2510
+ if (argumentsStart < calleeStart && calleeStart < catchNames.length) {
2511
+ catchNames.splice(argumentsStart, 0, ...catchNames.splice(calleeStart));
2512
+ catchScopes.splice(argumentsStart, 0, ...catchScopes.splice(calleeStart));
2513
+ }
2514
+ this.stack.pop();
2515
+ }
2516
+
2517
+ /**
2518
+ * A loop's children, its scope entered.
2519
+ * @param {PrintForStatement | PrintForInStatement | PrintForOfStatement | PrintWhileStatement} node the loop
2520
+ * @returns {void}
2521
+ */
2522
+ _visitLoop(node) {
2523
+ switch (node.type) {
2524
+ case "ForStatement":
2525
+ if (node.init) this._visitPrint(node.init);
2526
+ if (node.test) this._visitPrint(node.test);
2527
+ if (node.update) this._visitPrint(node.update);
2528
+ break;
2529
+ case "WhileStatement":
2530
+ this._visitPrint(node.test);
2531
+ break;
2532
+ case "DoWhileStatement":
2533
+ this._visitPrint(node.body);
2534
+ this._visitPrint(node.test);
2535
+ return;
2536
+ default:
2537
+ this._visitBinding(node.left, 0);
2538
+ this._visitPrint(node.right);
2539
+ }
2540
+ this._visitPrint(node.body);
2541
+ }
2542
+
2543
+ /**
2544
+ * @param {PrintVariableDeclaration} node a `var`, `let`, `const` or `using`
2545
+ * @returns {void}
2546
+ */
2547
+ _visitDeclaration(node) {
2548
+ const kind =
2549
+ node.kind === "var"
2550
+ ? DECLARES_VAR
2551
+ : node.kind === "let"
2552
+ ? DECLARES_LET
2553
+ : node.kind === "const"
2554
+ ? DECLARES_CONST
2555
+ : DECLARES_USING;
2556
+ const { stack, functionDeclarators, classDeclarators } = this;
2557
+ stack.push(node);
2558
+ const { declarations } = node;
2559
+ for (let i = 0; i < declarations.length; i++) {
2560
+ const declarator = /** @type {PrintVariableDeclarator} */ (
2561
+ declarations[i]
2562
+ );
2563
+ const { id, init } = declarator;
2564
+ if (
2565
+ functionDeclarators !== null &&
2566
+ kind !== DECLARES_USING &&
2567
+ id.type === "Identifier" &&
2568
+ init &&
2569
+ (init.type === "FunctionExpression" ||
2570
+ init.type === "ArrowFunctionExpression") &&
2571
+ !init.id
2572
+ ) {
2573
+ functionDeclarators.push(id);
2574
+ } else if (
2575
+ classDeclarators !== null &&
2576
+ kind !== DECLARES_USING &&
2577
+ id.type === "Identifier" &&
2578
+ init &&
2579
+ init.type === "ClassExpression" &&
2580
+ !init.id
2581
+ ) {
2582
+ classDeclarators.push(id);
2583
+ }
2584
+ stack.push(declarator);
2585
+ this._visitBinding(id, kind);
2586
+ if (init) this._visitPrint(init);
2587
+ stack.pop();
2588
+ }
2589
+ stack.pop();
2590
+ }
2591
+
2592
+ /**
2593
+ * @param {Node} node node to visit
2594
+ * @returns {void}
2595
+ */
2596
+ _visit(node) {
2597
+ // the shared walk's way back in, for the children of what it reads
2598
+ this._visitPrint(
2599
+ /** @type {PrintNode} */ (/** @type {PrintNode | Node} */ (node))
2600
+ );
2601
+ }
2602
+
2603
+ /**
2604
+ * Reads what is scoped as webpack does with the shared walk, pushed as
2605
+ * terser's walk pushes it, and the rest as terser's analysis does.
2606
+ * @param {PrintNode} current node to visit
2607
+ * @returns {void}
2608
+ */
2609
+ _visitPrint(current) {
2610
+ if (this.release !== undefined) this.release(current);
2611
+ const stack = this.stack;
2612
+ switch (current.type) {
2613
+ case "Identifier": {
2614
+ if (current.atom === true) return;
2615
+ const parent = stack[stack.length - 1];
2616
+ this._addReference(
2617
+ current,
2618
+ current.name === "eval" &&
2619
+ (parent.type === "CallExpression" ||
2620
+ parent.type === "NewExpression")
2621
+ ? REFERENCE_CALLED
2622
+ : 0
2623
+ );
2624
+ return;
2625
+ }
2626
+ // the commonest kinds first: the chain is a sequence of comparisons
2627
+ case "MemberExpression":
2628
+ stack.push(current);
2629
+ this._visitPrint(current.object);
2630
+ if (current.computed) {
2631
+ this._visitPrint(current.property);
2632
+ } else if (current.property.type === "PrivateIdentifier") {
2633
+ this.namesPrivate = true;
2634
+ }
2635
+ stack.pop();
2636
+ return;
2637
+ case "CallExpression":
2638
+ case "NewExpression":
2639
+ if (this.legacyCatch) {
2640
+ this._visitLegacyCall(current);
2641
+ return;
2642
+ }
2643
+ // terser's walk reaches the arguments first.
2644
+ stack.push(current);
2645
+ this._visitList(current.arguments);
2646
+ this._visitPrint(current.callee);
2647
+ stack.pop();
2648
+ return;
2649
+ case "Literal":
2650
+ case "ThisExpression":
2651
+ return;
2652
+ case "ExpressionStatement":
2653
+ if (typeof current.directive === "string") {
2654
+ if (current.directive === "use strict") this.strict = true;
2655
+ return;
2656
+ }
2657
+ stack.push(current);
2658
+ this._visitPrint(current.expression);
2659
+ stack.pop();
2660
+ return;
2661
+ case "BinaryExpression":
2662
+ case "LogicalExpression":
2663
+ case "AssignmentExpression":
2664
+ stack.push(current);
2665
+ this._visitPrint(current.left);
2666
+ this._visitPrint(current.right);
2667
+ stack.pop();
2668
+ return;
2669
+ case "BlockStatement": {
2670
+ stack.push(current);
2671
+ const outer = this._enterBlock("block", current);
2672
+ this._visitList(current.body);
2673
+ this.scope = outer;
2674
+ stack.pop();
2675
+ return;
2676
+ }
2677
+ case "ReturnStatement":
2678
+ case "UnaryExpression":
2679
+ case "UpdateExpression":
2680
+ case "ThrowStatement":
2681
+ case "AwaitExpression":
2682
+ case "SpreadElement":
2683
+ case "YieldExpression":
2684
+ stack.push(current);
2685
+ if (current.argument) this._visitPrint(current.argument);
2686
+ stack.pop();
2687
+ return;
2688
+ case "VariableDeclaration":
2689
+ this._visitDeclaration(current);
2690
+ return;
2691
+ case "FunctionDeclaration":
2692
+ case "FunctionExpression":
2693
+ case "ArrowFunctionExpression":
2694
+ this._visitMinifierFunction(current);
2695
+ return;
2696
+ case "ClassDeclaration":
2697
+ case "ClassExpression":
2698
+ this._visitMinifierClass(current);
2699
+ return;
2700
+ case "ForStatement":
2701
+ case "ForInStatement":
2702
+ case "ForOfStatement":
2703
+ case "WhileStatement":
2704
+ case "DoWhileStatement": {
2705
+ stack.push(current);
2706
+ const outer = this._enterBlock(
2707
+ current.type.startsWith("For") ? "for" : "block",
2708
+ current
2709
+ );
2710
+ if (this.safari10 && current.type.startsWith("For")) {
2711
+ this.forScopes.push(this.scope);
2712
+ }
2713
+ this._visitLoop(current);
2714
+ this.scope = outer;
2715
+ stack.pop();
2716
+ return;
2717
+ }
2718
+ case "SwitchStatement": {
2719
+ stack.push(current);
2720
+ const outer = this._enterBlock("switch", current);
2721
+ // The switched expression belongs to the scope around the switch.
2722
+ const block = this.scope;
2723
+ this.scope = outer;
2724
+ this._visitPrint(current.discriminant);
2725
+ this.scope = block;
2726
+ this._visitList(current.cases);
2727
+ this.scope = outer;
2728
+ stack.pop();
2729
+ return;
2730
+ }
2731
+ case "CatchClause": {
2732
+ stack.push(current);
2733
+ const outer = this._enterBlock("catch", current);
2734
+ const catchScope = this.scope;
2735
+ const ranged = this.parameterScopes && Boolean(current.param);
2736
+ if (ranged) {
2737
+ catchScope.parameterStart = this.referenceNodes.length;
2738
+ this.parameterRanges.push(catchScope);
2739
+ }
2740
+ if (current.param) this._visitBinding(current.param, DECLARES_CATCH);
2741
+ if (ranged) catchScope.parameterEnd = this.referenceNodes.length;
2742
+ if (this.release !== undefined) this.release(current.body);
2743
+ this._visitList(current.body.body);
2744
+ this.scope = outer;
2745
+ stack.pop();
2746
+ return;
2747
+ }
2748
+ case "StaticBlock": {
2749
+ const outer = this.scope;
2750
+ const outerLabels = this.labelsInScope;
2751
+ stack.push(current);
2752
+ this._open("class-static-block", current, true);
2753
+ this.labelsInScope = new Map();
2754
+ this._visitList(current.body);
2755
+ this.scope = outer;
2756
+ this.labelsInScope = outerLabels;
2757
+ stack.pop();
2758
+ return;
2759
+ }
2760
+ case "LabeledStatement": {
2761
+ const labelName = /** @type {PrintIdentifier} */ (current.label);
2762
+ const { name } = labelName;
2763
+ if (this.labelsInScope.has(name)) {
2764
+ throw new Error(`Label ${name} defined twice`);
2765
+ }
2766
+ const label = new MinifierLabel(name, this.currentLabel);
2767
+ this.labels.push(label);
2768
+ if (this.release !== undefined) this.release(labelName);
2769
+ labelName.definition = label;
2770
+ this.labelsInScope.set(name, label);
2771
+ stack.push(current);
2772
+ this.currentLabel = label;
2773
+ this._visitPrint(current.body);
2774
+ this.currentLabel = label.parent;
2775
+ stack.pop();
2776
+ this.labelsInScope.delete(name);
2777
+ return;
2778
+ }
2779
+ case "BreakStatement":
2780
+ case "ContinueStatement": {
2781
+ const name = /** @type {PrintIdentifier | null} */ (current.label);
2782
+ if (!name) return;
2783
+ const label = this.labelsInScope.get(name.name);
2784
+ if (label === undefined) {
2785
+ const start = /** @type {Token} */ (this.tokenOf(name.startToken));
2786
+ throw new Error(
2787
+ `Undefined label ${name.name} [${start.line},${start.col}]`
2788
+ );
2789
+ }
2790
+ if (this.release !== undefined) this.release(name);
2791
+ name.definition = label;
2792
+ return;
2793
+ }
2794
+ case "WithStatement":
2795
+ for (
2796
+ let outer = /** @type {MinifierScope | null} */ (this.scope);
2797
+ outer !== null;
2798
+ outer = /** @type {MinifierScope | null} */ (outer.upper)
2799
+ ) {
2800
+ outer.usesWith = true;
2801
+ }
2802
+ stack.push(current);
2803
+ this._visitPrint(current.object);
2804
+ this._visitPrint(current.body);
2805
+ stack.pop();
2806
+ return;
2807
+ case "Property":
2808
+ case "PropertyDefinition":
2809
+ if (current.key.type === "PrivateIdentifier") this.namesPrivate = true;
2810
+ stack.push(current);
2811
+ if (current.computed) this._visitPrint(current.key);
2812
+ if (current.value) this._visitPrint(current.value);
2813
+ if (
2814
+ current.type === "Property" &&
2815
+ current.kind === "init" &&
2816
+ !current.method
2817
+ ) {
2818
+ this._spellProperty(current);
2819
+ }
2820
+ stack.pop();
2821
+ return;
2822
+ case "ObjectPattern":
2823
+ case "ArrayPattern":
2824
+ case "AssignmentPattern":
2825
+ case "RestElement":
2826
+ this._visitBinding(current, 0);
2827
+ return;
2828
+ case "TemplateLiteral":
2829
+ stack.push(current);
2830
+ this._visitList(current.segments);
2831
+ stack.pop();
2832
+ return;
2833
+ case "ImportExpression":
2834
+ stack.push(current);
2835
+ this._visitList(current.args);
2836
+ stack.pop();
2837
+ return;
2838
+ case "MethodDefinition":
2839
+ if (current.key.type === "PrivateIdentifier") this.namesPrivate = true;
2840
+ // falls through
2841
+ case "IfStatement":
2842
+ case "ConditionalExpression":
2843
+ case "SwitchCase":
2844
+ case "ArrayExpression":
2845
+ case "ObjectExpression":
2846
+ case "SequenceExpression":
2847
+ case "TaggedTemplateExpression":
2848
+ case "ChainExpression":
2849
+ case "TryStatement":
2850
+ // scoped alike, so read by the shared walk, pushed as terser's walk does
2851
+ stack.push(current);
2852
+ super._visit(
2853
+ /** @type {Node} */ (/** @type {Node | PrintNode} */ (current))
2854
+ );
2855
+ stack.pop();
2856
+ return;
2857
+ case "PrivateIdentifier":
2858
+ this.namesPrivate = true;
2859
+ return;
2860
+ case "Super":
2861
+ case "EmptyStatement":
2862
+ case "DebuggerStatement":
2863
+ case "MetaProperty":
2864
+ case "TemplateElement":
2865
+ return;
2866
+ case "ImportDeclaration": {
2867
+ this._checkModuleStatement(current, "Import");
2868
+ stack.push(current);
2869
+ // terser holds a default import's name with no node around it.
2870
+ if (current.imported_name) {
2871
+ this._declare(current.imported_name, DECLARES_IMPORT);
2872
+ }
2873
+ const names = current.imported_names;
2874
+ if (names) {
2875
+ for (let i = 0; i < names.length; i++) {
2876
+ const specifier = names[i];
2877
+ stack.push(specifier);
2878
+ this._declare(
2879
+ /** @type {PrintIdentifier} */ (specifier.local),
2880
+ DECLARES_IMPORT
2881
+ );
2882
+ if (specifier.type === "ImportSpecifier") {
2883
+ this._spell(specifier.local, specifier.imported, AS_SAVING);
2884
+ }
2885
+ stack.pop();
2886
+ }
2887
+ }
2888
+ stack.pop();
2889
+ return;
2890
+ }
2891
+ case "ExportNamedDeclaration": {
2892
+ this._checkModuleStatement(current, "Export");
2893
+ stack.push(current);
2894
+ const declaration =
2895
+ current.exported_value || current.exported_definition;
2896
+ if (declaration) this._visitPrint(declaration);
2897
+ const fromModule = Boolean(current.source);
2898
+ const specifiers = current.exported_names;
2899
+ if (specifiers) {
2900
+ for (let i = 0; i < specifiers.length; i++) {
2901
+ const specifier = specifiers[i];
2902
+ stack.push(specifier);
2903
+ this._addReference(
2904
+ /** @type {PrintIdentifier | PrintLiteral} */ (specifier.local),
2905
+ fromModule
2906
+ ? REFERENCE_EXPORTED | REFERENCE_FROM_MODULE
2907
+ : REFERENCE_EXPORTED
2908
+ );
2909
+ if (!fromModule) {
2910
+ this._spell(specifier.local, specifier.exported, AS_SAVING);
2911
+ }
2912
+ stack.pop();
2913
+ }
2914
+ }
2915
+ stack.pop();
2916
+ return;
2917
+ }
2918
+ case "ExportDefaultDeclaration":
2919
+ this._checkModuleStatement(current, "Export");
2920
+ stack.push(current);
2921
+ this._visitPrint(
2922
+ /** @type {PrintNode} */ (
2923
+ current.exported_value || current.exported_definition
2924
+ )
2925
+ );
2926
+ stack.pop();
2927
+ return;
2928
+ case "ExportAllDeclaration":
2929
+ // terser's `*` reads a global no name in the output depends on.
2930
+ this._checkModuleStatement(current, "Export");
2931
+ return;
2932
+ default:
2933
+ throw new Error(
2934
+ `The minifier's scope analysis cannot read a ${current.type} node`
2935
+ );
2936
+ }
2937
+ }
2938
+
2939
+ /**
2940
+ * Drops the ranges of parameter reads this analysis counted.
2941
+ * @returns {void}
2942
+ */
2943
+ _clearParameterRanges() {
2944
+ const { parameterRanges } = this;
2945
+ for (let i = 0; i < parameterRanges.length; i++) {
2946
+ parameterRanges[i].parameterStart = -1;
2947
+ parameterRanges[i].parameterEnd = -1;
2948
+ }
2949
+ parameterRanges.length = 0;
2950
+ }
2951
+
2952
+ /**
2953
+ * Resolves each name read, finds `eval`, and encloses what a catch
2954
+ * parameter redefines, then moves the catch parameters old engines scope
2955
+ * to their function.
2956
+ * @returns {void}
2957
+ */
2958
+ _resolveMinifier() {
2959
+ const { referenceNodes, referenceScopes, referenceFlags, globals } = this;
2960
+ for (let i = 0; i < referenceNodes.length; i++) {
2961
+ const node = referenceNodes[i];
2962
+ const from = referenceScopes[i];
2963
+ const flags = referenceFlags[i];
2964
+ if (flags & REFERENCE_CATCH) {
2965
+ // The definition a catch parameter redefines in its function's scope.
2966
+ const redefinition = /** @type {MinifierVariable | undefined} */ (
2967
+ from.variableScope.getBinding(
2968
+ /** @type {PrintIdentifier} */ (node).name
2969
+ )
2970
+ );
2971
+ if (redefinition !== undefined) encloseVariable(from, redefinition);
2972
+ continue;
2973
+ }
2974
+ const { name } = node;
2975
+ if (flags & REFERENCE_CALLED) {
2976
+ for (
2977
+ let outer = /** @type {MinifierScope | null} */ (from);
2978
+ outer !== null && !outer.usesEval;
2979
+ outer = /** @type {MinifierScope | null} */ (outer.upper)
2980
+ ) {
2981
+ outer.usesEval = true;
2982
+ }
2983
+ }
2984
+ let variable =
2985
+ flags & REFERENCE_FROM_MODULE
2986
+ ? undefined
2987
+ : findMinifierVariable(from, name, i);
2988
+ if (variable === undefined) {
2989
+ variable = globals.get(name);
2990
+ if (variable === undefined) {
2991
+ variable = new MinifierVariable(name, this.toplevel, DECLARES_GLOBAL);
2992
+ variable.undeclared = true;
2993
+ variable.global = true;
2994
+ globals.set(name, variable);
2995
+ }
2996
+ if (flags & REFERENCE_EXPORTED) variable.export = EXPORT_KEEP_NAME;
2997
+ }
2998
+ if (node.type === "Identifier") {
2999
+ node.definition = variable;
3000
+ this._referenceVariable(node, from, variable);
3001
+ } else {
3002
+ // A re-exported string reads a global, which keeps no references.
3003
+ encloseVariable(from, variable);
3004
+ }
3005
+ }
3006
+
3007
+ this._clearParameterRanges();
3008
+
3009
+ // Passes 3 and 4: work around old engines' catch and loop scopes.
3010
+ const { catchNames, catchScopes } = this;
3011
+ for (let i = 0; i < catchNames.length; i++) {
3012
+ const identifier = catchNames[i];
3013
+ const { name } = identifier;
3014
+ const references = /** @type {MinifierVariable} */ (identifier.definition)
3015
+ .references;
3016
+ const defunScope = /** @type {MinifierScope} */ (
3017
+ catchScopes[i].variableScope
3018
+ );
3019
+ const variable =
3020
+ findMinifierVariable(defunScope, name) ||
3021
+ globals.get(name) ||
3022
+ this._defineVariable(defunScope, null, name, DECLARES_CATCH);
3023
+ // As terser's `forEach`: referencing appends to the list it reads.
3024
+ const { length } = references;
3025
+ for (let j = 0; j < length; j++) {
3026
+ const read = /** @type {PrintIdentifier} */ (
3027
+ /** @type {PrintIdentifier | Identifier} */ (references[j].identifier)
3028
+ );
3029
+ read.definition = variable;
3030
+ this._referenceVariable(
3031
+ read,
3032
+ /** @type {MinifierScope} */ (references[j].from),
3033
+ variable
3034
+ );
3035
+ }
3036
+ identifier.definition = variable;
3037
+ this._referenceVariable(identifier, catchScopes[i], variable);
3038
+ }
3039
+ const { forScopes } = this;
3040
+ for (let i = 0; i < forScopes.length; i++) {
3041
+ const forScope = forScopes[i];
3042
+ const variables = /** @type {MinifierScope} */ (forScope.upper).variables;
3043
+ for (let j = 0; j < variables.length; j++) {
3044
+ encloseUnique(forScope, /** @type {MinifierVariable} */ (variables[j]));
3045
+ }
3046
+ }
3047
+ }
3048
+ }
3049
+
3050
+ /**
3051
+ * Analyses the minifier's tree with terser's scoping, which the names it
3052
+ * hands out depend on: see `MinifierScopeAnalyzer`.
3053
+ * @param {PrintProgram} program the tree, its names as written
3054
+ * @param {MinifierScopeOptions} options the mangle options
3055
+ * @param {(node: PrintNode, message: string, tables?: TokenTables) => never} raise throws the parse error a misplaced declaration is
3056
+ * @param {((node: PrintNode) => void)=} release drops what only the compressor read off each node read, where nobody keeps the tree
3057
+ * @returns {MinifierScopeAnalysis} the scopes
3058
+ */
3059
+ const analyzeMinifierScope = (program, options, raise, release) => {
3060
+ const analyzer = new MinifierScopeAnalyzer(program, options, raise, release);
3061
+ if (release !== undefined) release(program);
3062
+ analyzer.stack.push(program);
3063
+ analyzer._visitList(program.body);
3064
+ analyzer.stack.pop();
3065
+ analyzer._resolveMinifier();
3066
+ return {
3067
+ toplevel: analyzer.toplevel,
3068
+ labels: analyzer.labels,
3069
+ globals: analyzer.globals,
3070
+ blockDefunScopes: analyzer.blockDefunScopes,
3071
+ functionDeclarators: analyzer.functionDeclarators,
3072
+ classDeclarators: analyzer.classDeclarators,
3073
+ catchParameters: analyzer.catchParameters,
3074
+ namesPrivate: analyzer.namesPrivate,
3075
+ spelledNames: analyzer.spelledNames
3076
+ };
3077
+ };
3078
+
3079
+ /**
3080
+ * @typedef {import("./syntax-parser").SyntaxTree} SyntaxTree
3081
+ * @typedef {MinifierVariable | MinifierLabel | null} TreeDefinition
3082
+ */
3083
+
3084
+ /**
3085
+ * The scopes the minifier's analysis reads off a `SyntaxTree`: each name's
3086
+ * definition is held by its node's number.
3087
+ * @typedef {MinifierScopeAnalysis & { definitions: TreeDefinition[] }} MinifierTreeScopeAnalysis
3088
+ */
3089
+
3090
+ // The tree's tables, read when a first tree is analysed: wherever webpack
3091
+ // reads a scope, requiring them would load the parser's data too.
3092
+ /** @type {typeof import("./data").NodeType} */
3093
+ let NodeType;
3094
+ /** @type {typeof import("./data").Field} */
3095
+ let Field;
3096
+ /** @type {typeof import("./data").Flag} */
3097
+ let Flag;
3098
+ /** @type {typeof import("./data").Part} */
3099
+ let Part;
3100
+
3101
+ /**
3102
+ * `MinifierScopeAnalyzer` over a `SyntaxTree` of the source terser's tree
3103
+ * was read from: the same walk, pushing the same nodes, so the same scopes,
3104
+ * definitions and orders. Neither `ie8` nor `safari10` is read.
3105
+ */
3106
+ class MinifierTreeScopeAnalyzer {
3107
+ /**
3108
+ * @param {SyntaxTree} tree the tree
3109
+ * @param {number} program its program
3110
+ * @param {Uint8Array} types each node's type, as terser's tree types it
3111
+ * @param {MinifierScopeOptions} options the mangle options
3112
+ * @param {(node: number, message: string) => never} raise throws the parse error a misplaced import or export is
3113
+ */
3114
+ constructor(tree, program, types, options, raise) {
3115
+ /** @type {SyntaxTree} */
3116
+ this.tree = tree;
3117
+ /** @type {Uint8Array} */
3118
+ this.types = types;
3119
+ /** @type {(node: number, message: string) => never} */
3120
+ this.raise = raise;
3121
+ /** @type {boolean} */
3122
+ this.parameterScopes = Boolean(options.parameterScopes);
3123
+ /** @type {MinifierScope[]} */
3124
+ this.parameterRanges = [];
3125
+ /** @type {MinifierScope} */
3126
+ this.toplevel = new MinifierScope(
3127
+ "global",
3128
+ /** @type {PrintNode} */ (/** @type {PrintNode | number} */ (program)),
3129
+ null,
3130
+ true
3131
+ );
3132
+ /** @type {MinifierScope} */
3133
+ this.scope = this.toplevel;
3134
+ /** @type {MinifierLabel[]} */
3135
+ this.labels = [];
3136
+ /** @type {Map<string, MinifierVariable>} */
3137
+ this.globals = new Map();
3138
+ /** @type {Set<MinifierScope>} */
3139
+ this.blockDefunScopes = new Set();
3140
+ /** @type {number[] | null} */
3141
+ this.functionDeclarators = options.keep_fnames ? [] : null;
3142
+ /** @type {number[] | null} */
3143
+ this.classDeclarators =
3144
+ options.classDeclarators && options.keep_classnames ? [] : null;
3145
+ /** @type {number[]} */
3146
+ this.referenceNodes = [];
3147
+ /** @type {MinifierScope[]} */
3148
+ this.referenceScopes = [];
3149
+ /** @type {number[]} */
3150
+ this.referenceFlags = [];
3151
+ /** @type {number[]} */
3152
+ this.catchParameters = [];
3153
+ /** @type {boolean} */
3154
+ this.namesPrivate = false;
3155
+ /** @type {number[]} the nodes terser's walk has pushed, 0 for an arrow's implicit `return` */
3156
+ this.stack = [];
3157
+ /** @type {boolean} */
3158
+ this.strict = Boolean(options.module);
3159
+ /** @type {Map<string, MinifierLabel>} */
3160
+ this.labelsInScope = new Map();
3161
+ /** @type {MinifierLabel | null} */
3162
+ this.currentLabel = null;
3163
+ /** @type {number} the pattern the walk is inside, 0 for none */
3164
+ this.inDestructuring = 0;
3165
+ // Filled in place: `Array.from` takes four times as long on a large tree.
3166
+ /** @type {TreeDefinition[]} */
3167
+ // eslint-disable-next-line unicorn/no-new-array
3168
+ this.definitions = new Array(types.length).fill(null);
3169
+ /** @type {number[] | null} each name with one spelled beside it */
3170
+ this.spelledIdentifiers = options.spelledNames ? [] : null;
3171
+ /** @type {string[]} the name spelled beside each */
3172
+ this.spellings = [];
3173
+ /** @type {number[]} the characters each pair saves */
3174
+ this.spelledSavings = [];
3175
+ /** @type {boolean} whether a key spells a name, which prints alone where it is its value's */
3176
+ this.spelledKeys = options.spelledNames === SPELLED_KEYS;
3177
+ }
3178
+
3179
+ /**
3180
+ * Collects a name and one spelled beside it, under `spelledNames`.
3181
+ * @param {number} identifier the name, 0 for none
3182
+ * @param {number} spelled what spells the other, 0 for none
3183
+ * @param {number} saving the characters it saves taking that name
3184
+ * @returns {void}
3185
+ */
3186
+ _spell(identifier, spelled, saving) {
3187
+ const identifiers = this.spelledIdentifiers;
3188
+ const { types, tree } = this;
3189
+ if (
3190
+ identifiers === null ||
3191
+ identifier === 0 ||
3192
+ spelled === 0 ||
3193
+ types[identifier] !== NodeType.Identifier
3194
+ ) {
3195
+ return;
3196
+ }
3197
+ /** @type {ReturnType<SyntaxTree["value"]>} */
3198
+ let spelling;
3199
+ if (types[spelled] === NodeType.Identifier) {
3200
+ spelling = tree.name(spelled);
3201
+ } else if (types[spelled] === NodeType.Literal) {
3202
+ spelling = tree.value(spelled);
3203
+ }
3204
+ if (
3205
+ typeof spelling !== "string" ||
3206
+ !SPELLABLE_NAME.test(spelling) ||
3207
+ NAMES_NO_BINDING_TAKES.has(spelling) ||
3208
+ // A shorthand `__proto__` is an own property; `__proto__:` sets the prototype.
3209
+ spelling === "__proto__"
3210
+ ) {
3211
+ return;
3212
+ }
3213
+ identifiers.push(identifier);
3214
+ this.spellings.push(spelling);
3215
+ this.spelledSavings.push(saving);
3216
+ }
3217
+
3218
+ /**
3219
+ * Collects a property's value named as its key could be, under `spelledNames`.
3220
+ * @param {number} property a property of an object or a pattern
3221
+ * @returns {void}
3222
+ */
3223
+ _spellProperty(property) {
3224
+ const { tree } = this;
3225
+ if (!this.spelledKeys || tree.flag(Flag.computed, property)) {
3226
+ return;
3227
+ }
3228
+ const value = tree.field(0, Field.value, property);
3229
+ this._spell(
3230
+ this.types[value] === NodeType.AssignmentPattern
3231
+ ? tree.field(0, Field.left, value)
3232
+ : value,
3233
+ tree.field(0, Field.key, property),
3234
+ SHORTHAND_SAVING
3235
+ );
3236
+ }
3237
+
3238
+ /**
3239
+ * @returns {SpelledNames | null} the names collected under `spelledNames`, resolved
3240
+ */
3241
+ _spelledNames() {
3242
+ const identifiers = this.spelledIdentifiers;
3243
+ if (identifiers === null) return null;
3244
+ return {
3245
+ identifiers: this._asNames(identifiers),
3246
+ spellings: this.spellings,
3247
+ savings: this.spelledSavings
3248
+ };
3249
+ }
3250
+
3251
+ /**
3252
+ * @param {number} field the `Field`
3253
+ * @param {number} node a node
3254
+ * @param {number=} i the item's index, for a list
3255
+ * @returns {number} the node the field holds, past parentheses, 0 for none
3256
+ */
3257
+ _child(field, node, i = 0) {
3258
+ const { tree } = this;
3259
+ let child = tree.field(i, field, node);
3260
+ while (
3261
+ child !== 0 &&
3262
+ tree.type(child) === NodeType.ParenthesizedExpression
3263
+ ) {
3264
+ child = tree.field(0, Field.expression, child);
3265
+ }
3266
+ return child;
3267
+ }
3268
+
3269
+ /**
3270
+ * @param {number} field the `Field`, a list
3271
+ * @param {number} node a node
3272
+ * @returns {void}
3273
+ */
3274
+ _visitList(field, node) {
3275
+ const count = this.tree.fieldCount(field, node);
3276
+ for (let i = 0; i < count; i++) {
3277
+ const child = this._child(field, node, i);
3278
+ if (child !== 0) this._visit(child);
3279
+ }
3280
+ }
3281
+
3282
+ /**
3283
+ * @param {number} field the `Field`
3284
+ * @param {number} node a node
3285
+ * @returns {void}
3286
+ */
3287
+ _visitChild(field, node) {
3288
+ const child = this._child(field, node);
3289
+ if (child !== 0) this._visit(child);
3290
+ }
3291
+
3292
+ /**
3293
+ * @param {number} node a node
3294
+ * @returns {string} the name it is, a quoted module name's among them
3295
+ */
3296
+ _nameOf(node) {
3297
+ const { tree } = this;
3298
+ return tree.type(node) === NodeType.Literal
3299
+ ? String(tree.value(node))
3300
+ : tree.name(node);
3301
+ }
3302
+
3303
+ /**
3304
+ * @param {ScopeType} type what opens it
3305
+ * @param {number} node the node opening it
3306
+ * @param {boolean} isVarScope whether `var` hoists to here
3307
+ * @returns {MinifierScope} the scope, now current
3308
+ */
3309
+ _open(type, node, isVarScope) {
3310
+ const scope = new MinifierScope(
3311
+ type,
3312
+ /** @type {PrintNode} */ (/** @type {PrintNode | number} */ (node)),
3313
+ this.scope,
3314
+ isVarScope
3315
+ );
3316
+ this.scope = scope;
3317
+ return scope;
3318
+ }
3319
+
3320
+ /**
3321
+ * @param {ScopeType} type what opens it
3322
+ * @param {number} node a block's node
3323
+ * @returns {MinifierScope} the scope it leaves
3324
+ */
3325
+ _enterBlock(type, node) {
3326
+ const outer = this.scope;
3327
+ this._open(type, node, false).usesWith = outer.usesWith;
3328
+ return outer;
3329
+ }
3330
+
3331
+ /**
3332
+ * terser's `def_variable`.
3333
+ * @param {MinifierScope} target the scope declaring it
3334
+ * @param {number} identifier the name declaring it, 0 for none written
3335
+ * @param {string} name the name
3336
+ * @param {number} kind how it is declared
3337
+ * @returns {MinifierVariable} its definition, made or joined
3338
+ */
3339
+ _defineVariable(target, identifier, name, kind) {
3340
+ let variable = /** @type {MinifierVariable | undefined} */ (
3341
+ target.getBinding(name)
3342
+ );
3343
+ if (variable !== undefined) {
3344
+ variable.declarations |= 1 << kind;
3345
+ } else {
3346
+ variable = new MinifierVariable(name, target, kind);
3347
+ variable.global = target.upper === null;
3348
+ addBinding(target, variable);
3349
+ }
3350
+ if (identifier !== 0) this.definitions[identifier] = variable;
3351
+ return variable;
3352
+ }
3353
+
3354
+ /**
3355
+ * @param {MinifierScope} from the scope reading it
3356
+ * @param {MinifierVariable} variable what it reads
3357
+ * @returns {void}
3358
+ */
3359
+ _referenceVariable(from, variable) {
3360
+ variable.referenceCount++;
3361
+ encloseVariable(from, variable);
3362
+ }
3363
+
3364
+ /**
3365
+ * terser's `mark_export`, counting levels on the walk's stack.
3366
+ * @param {MinifierVariable} variable a definition just made
3367
+ * @param {number} level where its declaration's statement is
3368
+ * @returns {void}
3369
+ */
3370
+ _markExport(variable, level) {
3371
+ const { stack } = this;
3372
+ if (this.inDestructuring !== 0) {
3373
+ let i = 0;
3374
+ do {
3375
+ level++;
3376
+ } while (stack[stack.length - 1 - i++] !== this.inDestructuring);
3377
+ }
3378
+ const node = stack[stack.length - 1 - level];
3379
+ const type = node === undefined ? 0 : this.types[node];
3380
+ if (
3381
+ type !== NodeType.ExportNamedDeclaration &&
3382
+ type !== NodeType.ExportDefaultDeclaration &&
3383
+ type !== NodeType.ExportAllDeclaration
3384
+ ) {
3385
+ variable.export = 0;
3386
+ return;
3387
+ }
3388
+ variable.export =
3389
+ type === NodeType.ExportDefaultDeclaration && !this._exportsValue(node)
3390
+ ? EXPORT_WANT_MANGLE
3391
+ : EXPORT_KEEP_NAME;
3392
+ }
3393
+
3394
+ /**
3395
+ * @param {number} node an `export default`
3396
+ * @returns {boolean} whether terser holds what it exports as a value, not a named declaration
3397
+ */
3398
+ _exportsValue(node) {
3399
+ const declaration = this.tree.field(0, Field.declaration, node);
3400
+ const type = this.tree.type(declaration);
3401
+ return (
3402
+ (type !== NodeType.FunctionDeclaration &&
3403
+ type !== NodeType.ClassDeclaration) ||
3404
+ this.tree.field(0, Field.id, declaration) === 0
3405
+ );
3406
+ }
3407
+
3408
+ /**
3409
+ * @param {number} node an import or export
3410
+ * @param {string} type terser's name for it
3411
+ * @returns {void}
3412
+ */
3413
+ _checkModuleStatement(node, type) {
3414
+ if (this.scope !== this.toplevel) {
3415
+ this.raise(node, `"${type}" statement may only appear at the top level`);
3416
+ }
3417
+ }
3418
+
3419
+ /**
3420
+ * @param {number} node a name read, or a re-exported string
3421
+ * @param {number} flags what else is known of it, as `REFERENCE_*` bits
3422
+ * @returns {void}
3423
+ */
3424
+ _addReference(node, flags) {
3425
+ this.referenceNodes.push(node);
3426
+ this.referenceScopes.push(this.scope);
3427
+ this.referenceFlags.push(flags);
3428
+ }
3429
+
3430
+ /**
3431
+ * A name a declaration or a pattern binds, or reads where `kind` is 0.
3432
+ * @param {number} node the name or pattern
3433
+ * @param {number} kind how it declares, as a `DECLARES_*` code, or 0
3434
+ * @returns {void}
3435
+ */
3436
+ _visitBinding(node, kind) {
3437
+ const { stack } = this;
3438
+ switch (this.types[node]) {
3439
+ case NodeType.Identifier:
3440
+ if (kind === 0) this._visit(node);
3441
+ else this._declare(node, kind);
3442
+ return;
3443
+ case NodeType.ObjectPattern:
3444
+ this._visitPattern(node, Field.properties, kind);
3445
+ return;
3446
+ case NodeType.ArrayPattern:
3447
+ this._visitPattern(node, Field.elements, kind);
3448
+ return;
3449
+ case NodeType.AssignmentPattern:
3450
+ stack.push(node);
3451
+ this._visitBinding(this._child(Field.left, node), kind);
3452
+ this._visit(this._child(Field.right, node));
3453
+ stack.pop();
3454
+ return;
3455
+ case NodeType.RestElement:
3456
+ stack.push(node);
3457
+ this._visitBinding(this._child(Field.argument, node), kind);
3458
+ stack.pop();
3459
+ return;
3460
+ default:
3461
+ this._visit(node);
3462
+ }
3463
+ }
3464
+
3465
+ /**
3466
+ * @param {number} pattern an object or array pattern
3467
+ * @param {number} field its properties or elements
3468
+ * @param {number} kind how it declares, as a `DECLARES_*` code, or 0
3469
+ * @returns {void}
3470
+ */
3471
+ _visitPattern(pattern, field, kind) {
3472
+ const { stack, tree } = this;
3473
+ const outer = this.inDestructuring;
3474
+ this.inDestructuring = pattern;
3475
+ stack.push(pattern);
3476
+ const count = tree.fieldCount(field, pattern);
3477
+ for (let i = 0; i < count; i++) {
3478
+ const element = this._child(field, pattern, i);
3479
+ if (element === 0) continue;
3480
+ if (this.types[element] !== NodeType.Property) {
3481
+ this._visitBinding(element, kind);
3482
+ continue;
3483
+ }
3484
+ stack.push(element);
3485
+ if (tree.flag(Flag.computed, element)) {
3486
+ this._visitChild(Field.key, element);
3487
+ }
3488
+ this._visitBinding(this._child(Field.value, element), kind);
3489
+ this._spellProperty(element);
3490
+ stack.pop();
3491
+ }
3492
+ stack.pop();
3493
+ this.inDestructuring = outer;
3494
+ }
3495
+
3496
+ /**
3497
+ * A `var`, parameter, `let`, `const`, `using`, catch parameter or import.
3498
+ * @param {number} identifier the name declared
3499
+ * @param {number} kind how, as a `DECLARES_*` code
3500
+ * @returns {void}
3501
+ */
3502
+ _declare(identifier, kind) {
3503
+ const name = this.tree.name(identifier);
3504
+ const { scope } = this;
3505
+ if (kind === DECLARES_IMPORT) {
3506
+ this._defineVariable(scope, identifier, name, kind);
3507
+ return;
3508
+ }
3509
+ const blockDeclaration =
3510
+ kind === DECLARES_LET ||
3511
+ kind === DECLARES_CONST ||
3512
+ kind === DECLARES_USING ||
3513
+ kind === DECLARES_CATCH;
3514
+ const defun = /** @type {MinifierScope} */ (scope.variableScope);
3515
+ // A redeclaration terser refuses here the tree's parser refused first.
3516
+ const variable = this._defineVariable(
3517
+ blockDeclaration ? scope : defun,
3518
+ identifier,
3519
+ name,
3520
+ kind
3521
+ );
3522
+ if (kind !== DECLARES_FUNARG) this._markExport(variable, 2);
3523
+ if (defun !== scope) {
3524
+ encloseVariable(scope, variable);
3525
+ const found = /** @type {MinifierVariable} */ (
3526
+ findMinifierVariable(scope, name)
3527
+ );
3528
+ if (found !== variable) {
3529
+ this.definitions[identifier] = found;
3530
+ this._referenceVariable(scope, found);
3531
+ }
3532
+ }
3533
+ if (kind === DECLARES_CATCH) {
3534
+ this._addReference(identifier, REFERENCE_CATCH);
3535
+ this.catchParameters.push(identifier);
3536
+ }
3537
+ }
3538
+
3539
+ /**
3540
+ * @param {number} node a binding pattern, 0 for an array's hole
3541
+ * @param {string} name a name
3542
+ * @returns {boolean} whether the pattern binds the name
3543
+ */
3544
+ _bindsName(node, name) {
3545
+ if (node === 0) return false;
3546
+ const { tree } = this;
3547
+ switch (this.types[node]) {
3548
+ case NodeType.ObjectPattern:
3549
+ return this._someChild(Field.properties, node, (property) =>
3550
+ this._bindsName(
3551
+ this.types[property] === NodeType.Property
3552
+ ? this._child(Field.value, property)
3553
+ : property,
3554
+ name
3555
+ )
3556
+ );
3557
+ case NodeType.ArrayPattern:
3558
+ return this._someChild(Field.elements, node, (element) =>
3559
+ this._bindsName(element, name)
3560
+ );
3561
+ case NodeType.AssignmentPattern:
3562
+ return this._bindsName(this._child(Field.left, node), name);
3563
+ case NodeType.RestElement:
3564
+ return this._bindsName(this._child(Field.argument, node), name);
3565
+ default:
3566
+ return tree.name(node) === name;
3567
+ }
3568
+ }
3569
+
3570
+ /**
3571
+ * @param {number} field the `Field`, a list
3572
+ * @param {number} node a node
3573
+ * @param {(child: number) => boolean} test what a child is asked
3574
+ * @returns {boolean} whether it holds for a child, holes 0
3575
+ */
3576
+ _someChild(field, node, test) {
3577
+ const count = this.tree.fieldCount(field, node);
3578
+ for (let i = 0; i < count; i++) {
3579
+ if (test(this._child(field, node, i))) return true;
3580
+ }
3581
+ return false;
3582
+ }
3583
+
3584
+ /**
3585
+ * @param {number} node a statement, or a loop's head, 0 for none
3586
+ * @param {string} name a name
3587
+ * @returns {boolean} whether it declares the name with `let`, `const`, `using` or a class
3588
+ */
3589
+ _declaresLexically(node, name) {
3590
+ if (node === 0) return false;
3591
+ const { tree } = this;
3592
+ const type = this.types[node];
3593
+ if (type === NodeType.VariableDeclaration) {
3594
+ return (
3595
+ tree.textOf(Part.kind, node) !== "var" &&
3596
+ this._someChild(Field.declarations, node, (declarator) =>
3597
+ this._bindsName(tree.field(0, Field.id, declarator), name)
3598
+ )
3599
+ );
3600
+ }
3601
+ return (
3602
+ type === NodeType.ClassDeclaration &&
3603
+ tree.name(tree.field(0, Field.id, node)) === name
3604
+ );
3605
+ }
3606
+
3607
+ /**
3608
+ * @param {number} owner a node listing statements
3609
+ * @param {number} field the `Field` listing them
3610
+ * @param {string} name a name
3611
+ * @returns {boolean} whether one of them declares it lexically
3612
+ */
3613
+ _listDeclaresLexically(owner, field, name) {
3614
+ const count = this.tree.fieldCount(field, owner);
3615
+ for (let i = 0; i < count; i++) {
3616
+ if (this._declaresLexically(this.tree.field(i, field, owner), name)) {
3617
+ return true;
3618
+ }
3619
+ }
3620
+ return false;
3621
+ }
3622
+
3623
+ /**
3624
+ * Annex B's test for a sloppy block's function: a `var` of its name would be
3625
+ * an early error, which keeps the function in its block.
3626
+ * @param {MinifierScope} scope the scope the function is declared in
3627
+ * @param {string} name the function's name
3628
+ * @returns {boolean} true for `f` in `{ let f; { function f() {} } }`
3629
+ */
3630
+ _keepsInBlock(scope, name) {
3631
+ const { tree } = this;
3632
+ while (scope !== scope.variableScope) {
3633
+ const node = /** @type {number} */ (
3634
+ /** @type {number | PrintNode} */ (scope.node)
3635
+ );
3636
+ switch (this.types[node]) {
3637
+ case NodeType.BlockStatement:
3638
+ if (this._listDeclaresLexically(node, Field.body, name)) return true;
3639
+ break;
3640
+ case NodeType.SwitchStatement: {
3641
+ const count = tree.fieldCount(Field.cases, node);
3642
+ for (let i = 0; i < count; i++) {
3643
+ const branch = tree.field(i, Field.cases, node);
3644
+ if (this._listDeclaresLexically(branch, Field.consequent, name)) {
3645
+ return true;
3646
+ }
3647
+ }
3648
+ break;
3649
+ }
3650
+ case NodeType.ForStatement:
3651
+ if (this._declaresLexically(this._child(Field.init, node), name)) {
3652
+ return true;
3653
+ }
3654
+ break;
3655
+ case NodeType.ForInStatement:
3656
+ case NodeType.ForOfStatement:
3657
+ if (this._declaresLexically(this._child(Field.left, node), name)) {
3658
+ return true;
3659
+ }
3660
+ break;
3661
+ case NodeType.CatchClause: {
3662
+ const param = tree.field(0, Field.param, node);
3663
+ if (
3664
+ (param !== 0 &&
3665
+ this.types[param] !== NodeType.Identifier &&
3666
+ this._bindsName(param, name)) ||
3667
+ this._listDeclaresLexically(
3668
+ tree.field(0, Field.body, node),
3669
+ Field.body,
3670
+ name
3671
+ )
3672
+ ) {
3673
+ return true;
3674
+ }
3675
+ break;
3676
+ }
3677
+ }
3678
+ scope = /** @type {MinifierScope} */ (scope.upper);
3679
+ }
3680
+ const node = /** @type {number} */ (
3681
+ /** @type {number | PrintNode} */ (scope.node)
3682
+ );
3683
+ if (this.types[node] === NodeType.Program) {
3684
+ return this._listDeclaresLexically(node, Field.body, name);
3685
+ }
3686
+ // A function holding a statement has a block for its body.
3687
+ return (
3688
+ this._someChild(Field.params, node, (param) =>
3689
+ this._bindsName(param, name)
3690
+ ) ||
3691
+ this._listDeclaresLexically(
3692
+ this._child(Field.body, node),
3693
+ Field.body,
3694
+ name
3695
+ )
3696
+ );
3697
+ }
3698
+
3699
+ /**
3700
+ * @param {number} node a function
3701
+ * @returns {void}
3702
+ */
3703
+ _visitFunction(node) {
3704
+ const { stack, tree } = this;
3705
+ const outerStrict = this.strict;
3706
+ const outer = this.scope;
3707
+ const outerLabels = this.labelsInScope;
3708
+ const type = this.types[node];
3709
+ const parentType = this.types[stack[stack.length - 1]];
3710
+ const inBlock =
3711
+ type === NodeType.FunctionDeclaration &&
3712
+ parentType !== NodeType.Program &&
3713
+ parentType !== NodeType.FunctionDeclaration &&
3714
+ parentType !== NodeType.FunctionExpression &&
3715
+ parentType !== NodeType.ArrowFunctionExpression &&
3716
+ parentType !== NodeType.StaticBlock;
3717
+ if (inBlock) {
3718
+ this.blockDefunScopes.add(
3719
+ /** @type {MinifierScope} */ (outer.variableScope)
3720
+ );
3721
+ }
3722
+ stack.push(node);
3723
+ const lambda = this._open("function", node, true);
3724
+ if (type !== NodeType.ArrowFunctionExpression) {
3725
+ this._defineVariable(lambda, 0, "arguments", DECLARES_FUNARG);
3726
+ }
3727
+ this.labelsInScope = new Map();
3728
+ const id = tree.field(0, Field.id, node);
3729
+ if (id === 0) {
3730
+ // An arrow or a method has no name of its own.
3731
+ } else if (type === NodeType.FunctionDeclaration) {
3732
+ const name = tree.name(id);
3733
+ this._markExport(
3734
+ this._defineVariable(
3735
+ // Annex B hoists a sloppy block's plain function only.
3736
+ this.strict ||
3737
+ (this.parameterScopes &&
3738
+ (tree.flag(Flag.async, node) ||
3739
+ tree.flag(Flag.generator, node) ||
3740
+ (inBlock && this._keepsInBlock(outer, name))))
3741
+ ? outer
3742
+ : /** @type {MinifierScope} */ (outer.variableScope),
3743
+ id,
3744
+ name,
3745
+ DECLARES_DEFUN
3746
+ ),
3747
+ 1
3748
+ );
3749
+ } else {
3750
+ this._defineVariable(lambda, id, tree.name(id), DECLARES_LAMBDA);
3751
+ lambda.functionName = /** @type {MinifierVariable} */ (
3752
+ this.definitions[id]
3753
+ );
3754
+ }
3755
+ const params = tree.fieldCount(Field.params, node);
3756
+ const ranged = this.parameterScopes && params !== 0;
3757
+ if (ranged) {
3758
+ lambda.parameterStart = this.referenceNodes.length;
3759
+ this.parameterRanges.push(lambda);
3760
+ }
3761
+ for (let i = 0; i < params; i++) {
3762
+ this._visitBinding(this._child(Field.params, node, i), DECLARES_FUNARG);
3763
+ }
3764
+ if (ranged) lambda.parameterEnd = this.referenceNodes.length;
3765
+ const body = this._child(Field.body, node);
3766
+ if (this.types[body] === NodeType.BlockStatement) {
3767
+ this._visitList(Field.body, body);
3768
+ } else {
3769
+ // terser's arrow returns its expression from a statement of its own.
3770
+ stack.push(0);
3771
+ this._visit(body);
3772
+ stack.pop();
3773
+ }
3774
+ this.scope = outer;
3775
+ this.labelsInScope = outerLabels;
3776
+ this.strict = outerStrict;
3777
+ stack.pop();
3778
+ }
3779
+
3780
+ /**
3781
+ * @param {number} node a class
3782
+ * @returns {void}
3783
+ */
3784
+ _visitClass(node) {
3785
+ const { tree } = this;
3786
+ const outerStrict = this.strict;
3787
+ const outer = this.scope;
3788
+ const outerLabels = this.labelsInScope;
3789
+ this.stack.push(node);
3790
+ this.strict = true;
3791
+ const classScope = this._open("class", node, true);
3792
+ this.labelsInScope = new Map();
3793
+ const id = tree.field(0, Field.id, node);
3794
+ if (id !== 0) {
3795
+ const name = tree.name(id);
3796
+ this._markExport(
3797
+ this.types[node] === NodeType.ClassDeclaration
3798
+ ? this._defineVariable(outer, id, name, DECLARES_DEF_CLASS)
3799
+ : this._defineVariable(classScope, id, name, DECLARES_CLASS),
3800
+ 1
3801
+ );
3802
+ }
3803
+ this._visitChild(Field.superClass, node);
3804
+ this._visitList(Field.body, tree.field(0, Field.body, node));
3805
+ this.scope = outer;
3806
+ this.labelsInScope = outerLabels;
3807
+ this.strict = outerStrict;
3808
+ this.stack.pop();
3809
+ }
3810
+
3811
+ /**
3812
+ * @param {number} node a `var`, `let`, `const` or `using`
3813
+ * @returns {void}
3814
+ */
3815
+ _visitDeclaration(node) {
3816
+ const { stack, tree, functionDeclarators, classDeclarators } = this;
3817
+ const text = tree.textOf(Part.kind, node);
3818
+ const kind =
3819
+ text === "var"
3820
+ ? DECLARES_VAR
3821
+ : text === "let"
3822
+ ? DECLARES_LET
3823
+ : text === "const"
3824
+ ? DECLARES_CONST
3825
+ : DECLARES_USING;
3826
+ stack.push(node);
3827
+ const count = tree.fieldCount(Field.declarations, node);
3828
+ for (let i = 0; i < count; i++) {
3829
+ const declarator = tree.field(i, Field.declarations, node);
3830
+ const id = tree.field(0, Field.id, declarator);
3831
+ const init = this._child(Field.init, declarator);
3832
+ if (
3833
+ functionDeclarators !== null &&
3834
+ kind !== DECLARES_USING &&
3835
+ this.types[id] === NodeType.Identifier &&
3836
+ init !== 0 &&
3837
+ (this.types[init] === NodeType.FunctionExpression ||
3838
+ this.types[init] === NodeType.ArrowFunctionExpression) &&
3839
+ tree.field(0, Field.id, init) === 0
3840
+ ) {
3841
+ functionDeclarators.push(id);
3842
+ } else if (
3843
+ classDeclarators !== null &&
3844
+ kind !== DECLARES_USING &&
3845
+ this.types[id] === NodeType.Identifier &&
3846
+ init !== 0 &&
3847
+ this.types[init] === NodeType.ClassExpression &&
3848
+ tree.field(0, Field.id, init) === 0
3849
+ ) {
3850
+ classDeclarators.push(id);
3851
+ }
3852
+ stack.push(declarator);
3853
+ this._visitBinding(id, kind);
3854
+ if (init !== 0) this._visit(init);
3855
+ stack.pop();
3856
+ }
3857
+ stack.pop();
3858
+ }
3859
+
3860
+ /**
3861
+ * A loop's children, its scope entered.
3862
+ * @param {number} node the loop
3863
+ * @returns {void}
3864
+ */
3865
+ _visitLoop(node) {
3866
+ switch (this.types[node]) {
3867
+ case NodeType.ForStatement:
3868
+ this._visitChild(Field.init, node);
3869
+ this._visitChild(Field.test, node);
3870
+ this._visitChild(Field.update, node);
3871
+ break;
3872
+ case NodeType.WhileStatement:
3873
+ this._visitChild(Field.test, node);
3874
+ break;
3875
+ case NodeType.DoWhileStatement:
3876
+ this._visitChild(Field.body, node);
3877
+ this._visitChild(Field.test, node);
3878
+ return;
3879
+ default:
3880
+ this._visitBinding(this._child(Field.left, node), 0);
3881
+ this._visitChild(Field.right, node);
3882
+ }
3883
+ this._visitChild(Field.body, node);
3884
+ }
3885
+
3886
+ /**
3887
+ * Reads one node as `MinifierScopeAnalyzer#_visitPrint` reads terser's.
3888
+ * @param {number} node node to visit
3889
+ * @returns {void}
3890
+ */
3891
+ _visit(node) {
3892
+ const { stack, tree } = this;
3893
+ const type = this.types[node];
3894
+ switch (type) {
3895
+ case NodeType.Identifier: {
3896
+ // A number too large for a double, which terser holds as an atom.
3897
+ if (tree.type(node) !== NodeType.Identifier) return;
3898
+ const parentType = this.types[stack[stack.length - 1]];
3899
+ this._addReference(
3900
+ node,
3901
+ tree.name(node) === "eval" &&
3902
+ (parentType === NodeType.CallExpression ||
3903
+ parentType === NodeType.NewExpression)
3904
+ ? REFERENCE_CALLED
3905
+ : 0
3906
+ );
3907
+ return;
3908
+ }
3909
+ case NodeType.MemberExpression: {
3910
+ stack.push(node);
3911
+ this._visitChild(Field.object, node);
3912
+ const property = this._child(Field.property, node);
3913
+ if (tree.flag(Flag.computed, node)) {
3914
+ this._visit(property);
3915
+ } else if (tree.type(property) === NodeType.PrivateIdentifier) {
3916
+ this.namesPrivate = true;
3917
+ }
3918
+ stack.pop();
3919
+ return;
3920
+ }
3921
+ case NodeType.CallExpression:
3922
+ case NodeType.NewExpression:
3923
+ // terser's walk reaches the arguments first.
3924
+ stack.push(node);
3925
+ this._visitList(Field.arguments, node);
3926
+ this._visitChild(Field.callee, node);
3927
+ stack.pop();
3928
+ return;
3929
+ case NodeType.Literal:
3930
+ case NodeType.ThisExpression:
3931
+ return;
3932
+ case NodeType.ExpressionStatement: {
3933
+ const directive = tree.textOf(Part.directive, node);
3934
+ if (directive !== null) {
3935
+ if (directive === "use strict") this.strict = true;
3936
+ return;
3937
+ }
3938
+ stack.push(node);
3939
+ this._visitChild(Field.expression, node);
3940
+ stack.pop();
3941
+ return;
3942
+ }
3943
+ case NodeType.BinaryExpression:
3944
+ case NodeType.LogicalExpression:
3945
+ case NodeType.AssignmentExpression:
3946
+ stack.push(node);
3947
+ this._visitChild(Field.left, node);
3948
+ this._visitChild(Field.right, node);
3949
+ stack.pop();
3950
+ return;
3951
+ case NodeType.BlockStatement: {
3952
+ stack.push(node);
3953
+ const outer = this._enterBlock("block", node);
3954
+ this._visitList(Field.body, node);
3955
+ this.scope = outer;
3956
+ stack.pop();
3957
+ return;
3958
+ }
3959
+ case NodeType.ReturnStatement:
3960
+ case NodeType.UnaryExpression:
3961
+ case NodeType.UpdateExpression:
3962
+ case NodeType.ThrowStatement:
3963
+ case NodeType.AwaitExpression:
3964
+ case NodeType.SpreadElement:
3965
+ case NodeType.YieldExpression:
3966
+ stack.push(node);
3967
+ this._visitChild(Field.argument, node);
3968
+ stack.pop();
3969
+ return;
3970
+ case NodeType.VariableDeclaration:
3971
+ this._visitDeclaration(node);
3972
+ return;
3973
+ case NodeType.FunctionDeclaration:
3974
+ case NodeType.FunctionExpression:
3975
+ case NodeType.ArrowFunctionExpression:
3976
+ this._visitFunction(node);
3977
+ return;
3978
+ case NodeType.ClassDeclaration:
3979
+ case NodeType.ClassExpression:
3980
+ this._visitClass(node);
3981
+ return;
3982
+ case NodeType.ForStatement:
3983
+ case NodeType.ForInStatement:
3984
+ case NodeType.ForOfStatement:
3985
+ case NodeType.WhileStatement:
3986
+ case NodeType.DoWhileStatement: {
3987
+ stack.push(node);
3988
+ const outer = this._enterBlock(
3989
+ type === NodeType.WhileStatement || type === NodeType.DoWhileStatement
3990
+ ? "block"
3991
+ : "for",
3992
+ node
3993
+ );
3994
+ this._visitLoop(node);
3995
+ this.scope = outer;
3996
+ stack.pop();
3997
+ return;
3998
+ }
3999
+ case NodeType.SwitchStatement: {
4000
+ stack.push(node);
4001
+ const outer = this._enterBlock("switch", node);
4002
+ // The switched expression belongs to the scope around the switch.
4003
+ const block = this.scope;
4004
+ this.scope = outer;
4005
+ this._visitChild(Field.discriminant, node);
4006
+ this.scope = block;
4007
+ this._visitList(Field.cases, node);
4008
+ this.scope = outer;
4009
+ stack.pop();
4010
+ return;
4011
+ }
4012
+ case NodeType.CatchClause: {
4013
+ stack.push(node);
4014
+ const outer = this._enterBlock("catch", node);
4015
+ const catchScope = this.scope;
4016
+ const param = tree.field(0, Field.param, node);
4017
+ const ranged = this.parameterScopes && param !== 0;
4018
+ if (ranged) {
4019
+ catchScope.parameterStart = this.referenceNodes.length;
4020
+ this.parameterRanges.push(catchScope);
4021
+ }
4022
+ if (param !== 0) this._visitBinding(param, DECLARES_CATCH);
4023
+ if (ranged) catchScope.parameterEnd = this.referenceNodes.length;
4024
+ this._visitList(Field.body, tree.field(0, Field.body, node));
4025
+ this.scope = outer;
4026
+ stack.pop();
4027
+ return;
4028
+ }
4029
+ case NodeType.StaticBlock: {
4030
+ const outer = this.scope;
4031
+ const outerLabels = this.labelsInScope;
4032
+ stack.push(node);
4033
+ this._open("class-static-block", node, true);
4034
+ this.labelsInScope = new Map();
4035
+ this._visitList(Field.body, node);
4036
+ this.scope = outer;
4037
+ this.labelsInScope = outerLabels;
4038
+ stack.pop();
4039
+ return;
4040
+ }
4041
+ case NodeType.LabeledStatement: {
4042
+ // The tree's parser refuses a label defined twice or undefined.
4043
+ const labelName = tree.field(0, Field.label, node);
4044
+ const name = tree.name(labelName);
4045
+ const label = new MinifierLabel(name, this.currentLabel);
4046
+ this.labels.push(label);
4047
+ this.definitions[labelName] = label;
4048
+ this.labelsInScope.set(name, label);
4049
+ stack.push(node);
4050
+ this.currentLabel = label;
4051
+ this._visitChild(Field.body, node);
4052
+ this.currentLabel = label.parent;
4053
+ stack.pop();
4054
+ this.labelsInScope.delete(name);
4055
+ return;
4056
+ }
4057
+ case NodeType.BreakStatement:
4058
+ case NodeType.ContinueStatement: {
4059
+ const labelName = tree.field(0, Field.label, node);
4060
+ if (labelName === 0) return;
4061
+ this.definitions[labelName] = /** @type {MinifierLabel} */ (
4062
+ this.labelsInScope.get(tree.name(labelName))
4063
+ );
4064
+ return;
4065
+ }
4066
+ case NodeType.WithStatement:
4067
+ for (
4068
+ let outer = /** @type {MinifierScope | null} */ (this.scope);
4069
+ outer !== null;
4070
+ outer = /** @type {MinifierScope | null} */ (outer.upper)
4071
+ ) {
4072
+ outer.usesWith = true;
4073
+ }
4074
+ stack.push(node);
4075
+ this._visitChild(Field.object, node);
4076
+ this._visitChild(Field.body, node);
4077
+ stack.pop();
4078
+ return;
4079
+ case NodeType.Property:
4080
+ case NodeType.PropertyDefinition:
4081
+ if (
4082
+ tree.type(tree.field(0, Field.key, node)) ===
4083
+ NodeType.PrivateIdentifier
4084
+ ) {
4085
+ this.namesPrivate = true;
4086
+ }
4087
+ stack.push(node);
4088
+ if (tree.flag(Flag.computed, node)) this._visitChild(Field.key, node);
4089
+ this._visitChild(Field.value, node);
4090
+ if (
4091
+ this.types[node] === NodeType.Property &&
4092
+ tree.textOf(Part.kind, node) === "init" &&
4093
+ !tree.flag(Flag.method, node)
4094
+ ) {
4095
+ this._spellProperty(node);
4096
+ }
4097
+ stack.pop();
4098
+ return;
4099
+ case NodeType.ObjectPattern:
4100
+ case NodeType.ArrayPattern:
4101
+ case NodeType.AssignmentPattern:
4102
+ case NodeType.RestElement:
4103
+ this._visitBinding(node, 0);
4104
+ return;
4105
+ case NodeType.TemplateLiteral:
4106
+ // Its strings, between the expressions, read nothing.
4107
+ stack.push(node);
4108
+ this._visitList(Field.expressions, node);
4109
+ stack.pop();
4110
+ return;
4111
+ case NodeType.ImportExpression:
4112
+ stack.push(node);
4113
+ this._visitChild(Field.source, node);
4114
+ this._visitChild(Field.options, node);
4115
+ stack.pop();
4116
+ return;
4117
+ case NodeType.MethodDefinition:
4118
+ if (
4119
+ tree.type(tree.field(0, Field.key, node)) ===
4120
+ NodeType.PrivateIdentifier
4121
+ ) {
4122
+ this.namesPrivate = true;
4123
+ }
4124
+ stack.push(node);
4125
+ if (tree.flag(Flag.computed, node)) this._visitChild(Field.key, node);
4126
+ this._visitChild(Field.value, node);
4127
+ stack.pop();
4128
+ return;
4129
+ case NodeType.IfStatement:
4130
+ case NodeType.ConditionalExpression:
4131
+ stack.push(node);
4132
+ this._visitChild(Field.test, node);
4133
+ this._visitChild(Field.consequent, node);
4134
+ this._visitChild(Field.alternate, node);
4135
+ stack.pop();
4136
+ return;
4137
+ case NodeType.SwitchCase:
4138
+ stack.push(node);
4139
+ this._visitChild(Field.test, node);
4140
+ this._visitList(Field.consequent, node);
4141
+ stack.pop();
4142
+ return;
4143
+ case NodeType.ArrayExpression:
4144
+ stack.push(node);
4145
+ this._visitList(Field.elements, node);
4146
+ stack.pop();
4147
+ return;
4148
+ case NodeType.ObjectExpression:
4149
+ stack.push(node);
4150
+ this._visitList(Field.properties, node);
4151
+ stack.pop();
4152
+ return;
4153
+ case NodeType.SequenceExpression:
4154
+ stack.push(node);
4155
+ this._visitList(Field.expressions, node);
4156
+ stack.pop();
4157
+ return;
4158
+ case NodeType.TaggedTemplateExpression:
4159
+ stack.push(node);
4160
+ this._visitChild(Field.tag, node);
4161
+ this._visitChild(Field.quasi, node);
4162
+ stack.pop();
4163
+ return;
4164
+ case NodeType.ChainExpression:
4165
+ stack.push(node);
4166
+ this._visitChild(Field.expression, node);
4167
+ stack.pop();
4168
+ return;
4169
+ case NodeType.TryStatement:
4170
+ stack.push(node);
4171
+ this._visitChild(Field.block, node);
4172
+ this._visitChild(Field.handler, node);
4173
+ this._visitChild(Field.finalizer, node);
4174
+ stack.pop();
4175
+ return;
4176
+ case NodeType.PrivateIdentifier:
4177
+ this.namesPrivate = true;
4178
+ return;
4179
+ case NodeType.ImportDeclaration: {
4180
+ this._checkModuleStatement(node, "Import");
4181
+ stack.push(node);
4182
+ const count = tree.fieldCount(Field.specifiers, node);
4183
+ for (let i = 0; i < count; i++) {
4184
+ const specifier = tree.field(i, Field.specifiers, node);
4185
+ const local = tree.field(0, Field.local, specifier);
4186
+ // terser holds a default import's name with no node around it.
4187
+ if (this.types[specifier] === NodeType.ImportDefaultSpecifier) {
4188
+ this._declare(local, DECLARES_IMPORT);
4189
+ continue;
4190
+ }
4191
+ stack.push(specifier);
4192
+ this._declare(local, DECLARES_IMPORT);
4193
+ if (this.types[specifier] === NodeType.ImportSpecifier) {
4194
+ this._spell(
4195
+ local,
4196
+ tree.field(0, Field.imported, specifier),
4197
+ AS_SAVING
4198
+ );
4199
+ }
4200
+ stack.pop();
4201
+ }
4202
+ stack.pop();
4203
+ return;
4204
+ }
4205
+ case NodeType.ExportNamedDeclaration: {
4206
+ this._checkModuleStatement(node, "Export");
4207
+ stack.push(node);
4208
+ this._visitChild(Field.declaration, node);
4209
+ const flags =
4210
+ tree.field(0, Field.source, node) !== 0
4211
+ ? REFERENCE_EXPORTED | REFERENCE_FROM_MODULE
4212
+ : REFERENCE_EXPORTED;
4213
+ const count = tree.fieldCount(Field.specifiers, node);
4214
+ for (let i = 0; i < count; i++) {
4215
+ const specifier = tree.field(i, Field.specifiers, node);
4216
+ stack.push(specifier);
4217
+ const local = tree.field(0, Field.local, specifier);
4218
+ this._addReference(local, flags);
4219
+ if ((flags & REFERENCE_FROM_MODULE) === 0) {
4220
+ this._spell(
4221
+ local,
4222
+ tree.field(0, Field.exported, specifier),
4223
+ AS_SAVING
4224
+ );
4225
+ }
4226
+ stack.pop();
4227
+ }
4228
+ stack.pop();
4229
+ return;
4230
+ }
4231
+ case NodeType.ExportDefaultDeclaration:
4232
+ this._checkModuleStatement(node, "Export");
4233
+ stack.push(node);
4234
+ this._visitChild(Field.declaration, node);
4235
+ stack.pop();
4236
+ return;
4237
+ case NodeType.ExportAllDeclaration:
4238
+ // terser's `*` reads a global no name in the output depends on.
4239
+ this._checkModuleStatement(node, "Export");
4240
+ return;
4241
+ case NodeType.Super:
4242
+ case NodeType.EmptyStatement:
4243
+ case NodeType.DebuggerStatement:
4244
+ case NodeType.MetaProperty:
4245
+ return;
4246
+ default:
4247
+ throw new Error(
4248
+ `The minifier's scope analysis cannot read a node of type ${type}`
4249
+ );
4250
+ }
4251
+ }
4252
+
4253
+ /**
4254
+ * Resolves each name read, finds `eval`, and encloses what a catch
4255
+ * parameter redefines.
4256
+ * @returns {void}
4257
+ */
4258
+ _resolve() {
4259
+ const { referenceNodes, referenceScopes, referenceFlags, globals, tree } =
4260
+ this;
4261
+ for (let i = 0; i < referenceNodes.length; i++) {
4262
+ const node = referenceNodes[i];
4263
+ const from = referenceScopes[i];
4264
+ const flags = referenceFlags[i];
4265
+ if (flags & REFERENCE_CATCH) {
4266
+ const redefinition = /** @type {MinifierVariable | undefined} */ (
4267
+ from.variableScope.getBinding(tree.name(node))
4268
+ );
4269
+ if (redefinition !== undefined) encloseVariable(from, redefinition);
4270
+ continue;
4271
+ }
4272
+ const name = this._nameOf(node);
4273
+ if (flags & REFERENCE_CALLED) {
4274
+ for (
4275
+ let outer = /** @type {MinifierScope | null} */ (from);
4276
+ outer !== null && !outer.usesEval;
4277
+ outer = /** @type {MinifierScope | null} */ (outer.upper)
4278
+ ) {
4279
+ outer.usesEval = true;
4280
+ }
4281
+ }
4282
+ let variable =
4283
+ flags & REFERENCE_FROM_MODULE
4284
+ ? undefined
4285
+ : findMinifierVariable(from, name, i);
4286
+ if (variable === undefined) {
4287
+ variable = globals.get(name);
4288
+ if (variable === undefined) {
4289
+ variable = new MinifierVariable(name, this.toplevel, DECLARES_GLOBAL);
4290
+ variable.undeclared = true;
4291
+ variable.global = true;
4292
+ globals.set(name, variable);
4293
+ }
4294
+ if (flags & REFERENCE_EXPORTED) variable.export = EXPORT_KEEP_NAME;
4295
+ }
4296
+ if (tree.type(node) === NodeType.Identifier) {
4297
+ this.definitions[node] = variable;
4298
+ this._referenceVariable(from, variable);
4299
+ } else {
4300
+ // A re-exported string reads a global, which keeps no references.
4301
+ encloseVariable(from, variable);
4302
+ }
4303
+ }
4304
+ const { parameterRanges } = this;
4305
+ for (let i = 0; i < parameterRanges.length; i++) {
4306
+ parameterRanges[i].parameterStart = -1;
4307
+ parameterRanges[i].parameterEnd = -1;
4308
+ }
4309
+ }
4310
+
4311
+ /**
4312
+ * @param {number[]} identifiers names
4313
+ * @returns {PrintIdentifier[]} each as the mangler reads it: its name and its definition
4314
+ */
4315
+ _asNames(identifiers) {
4316
+ return identifiers.map(
4317
+ (identifier) =>
4318
+ /** @type {PrintIdentifier} */ (
4319
+ /** @type {PrintIdentifier | { name: string, definition: TreeDefinition }} */ ({
4320
+ name: this.tree.name(identifier),
4321
+ definition: this.definitions[identifier]
4322
+ })
4323
+ )
4324
+ );
4325
+ }
4326
+ }
4327
+
4328
+ /**
4329
+ * Analyses a `SyntaxTree` as `analyzeMinifierScope` does terser's tree of
4330
+ * the same source; neither `ie8` nor `safari10` may be on.
4331
+ * @param {SyntaxTree} tree the tree
4332
+ * @param {number} program its program
4333
+ * @param {Uint8Array} types each node's type, as terser's tree types it
4334
+ * @param {MinifierScopeOptions} options the mangle options
4335
+ * @param {(node: number, message: string) => never} raise throws the parse error a misplaced import or export is
4336
+ * @returns {MinifierTreeScopeAnalysis} the scopes, and each name's definition
4337
+ */
4338
+ const analyzeMinifierTree = (tree, program, types, options, raise) => {
4339
+ if (NodeType === undefined) {
4340
+ ({ NodeType, Field, Flag, Part } = require("./data"));
4341
+ }
4342
+ const analyzer = new MinifierTreeScopeAnalyzer(
4343
+ tree,
4344
+ program,
4345
+ types,
4346
+ options,
4347
+ raise
4348
+ );
4349
+ analyzer.stack.push(program);
4350
+ analyzer._visitList(Field.body, program);
4351
+ analyzer.stack.pop();
4352
+ analyzer._resolve();
4353
+ const { functionDeclarators, classDeclarators } = analyzer;
4354
+ return {
4355
+ toplevel: analyzer.toplevel,
4356
+ labels: analyzer.labels,
4357
+ globals: analyzer.globals,
4358
+ blockDefunScopes: analyzer.blockDefunScopes,
4359
+ functionDeclarators:
4360
+ functionDeclarators === null
4361
+ ? null
4362
+ : analyzer._asNames(functionDeclarators),
4363
+ classDeclarators:
4364
+ classDeclarators === null ? null : analyzer._asNames(classDeclarators),
4365
+ catchParameters: analyzer._asNames(analyzer.catchParameters),
4366
+ namesPrivate: analyzer.namesPrivate,
4367
+ spelledNames: analyzer._spelledNames(),
4368
+ definitions: analyzer.definitions
4369
+ };
4370
+ };
4371
+
4372
+ // The declarations whose name a block keeps: a read of any other name from a
4373
+ // block is the function's, as terser re-points it.
4374
+ const BLOCK_DECLARATIONS =
4375
+ (1 << DECLARES_LET) |
4376
+ (1 << DECLARES_CONST) |
4377
+ (1 << DECLARES_USING) |
4378
+ (1 << DECLARES_CATCH) |
4379
+ (1 << DECLARES_DEF_CLASS) |
4380
+ (1 << DECLARES_IMPORT);
4381
+
4382
+ // The declarations naming a function, which terser's `def_function` defines.
4383
+ const FUNCTION_DECLARATIONS =
4384
+ (1 << DECLARES_LAMBDA) | (1 << DECLARES_DEFUN) | (1 << DECLARES_DEF_CLASS);
4385
+
4386
+ /**
4387
+ * What the compressor's analysis asks of its tree's nodes, which only the
4388
+ * tree's kinds answer.
4389
+ * @typedef {object} CompressorDialect
4390
+ * @property {(node: CompressorNode) => boolean} isSymbol whether a node is one of terser's symbols, which records its scope
4391
+ * @property {(node: CompressorNode) => boolean} isFunction whether a node is a function expression, not a method
4392
+ * @property {(node: CompressorNode) => boolean} isDefun whether a node is a function declaration
4393
+ * @property {(node: CompressorNode) => boolean} isObjectKeyValue whether a property is a plain key and value, its key a name only where computed
4394
+ * @property {(node: CompressorNode) => boolean} isPrivateField whether a class field is a private one, its key no symbol
4395
+ * @property {(lambda: CompressorNode) => CompressorNode} argumentsSymbol the symbol a function's own `arguments` is declared by
4396
+ */
4397
+
4398
+ /**
4399
+ * The compressor's analysis: the minifier's, recording what terser's
4400
+ * `figure_out_scope` gives the compressor besides. Each scope is a
4401
+ * `CompressorScope` its node holds, each definition a `CompressorVariable`
4402
+ * with its declaring symbols, its value and its reads, and each symbol its
4403
+ * scope; a label is its own definition, its `break`s and `continue`s its
4404
+ * references.
4405
+ */
4406
+ class CompressorScopeAnalyzer extends MinifierScopeAnalyzer {
4407
+ /**
4408
+ * @param {CompressorNode} root the program, or a function or class analysed again
4409
+ * @param {MinifierScopeOptions} options the options
4410
+ * @param {(node: PrintNode, message: string, tables?: TokenTables) => never} raise throws the parse error a misplaced declaration is
4411
+ * @param {CompressorDialect} dialect what the tree's kinds answer
4412
+ * @param {CompressorScopeShape} parentScope the scope the root sits in, the program's own for the program
4413
+ * @param {CompressorScopeShape} toplevel the program's scope
4414
+ */
4415
+ constructor(root, options, raise, dialect, parentScope, toplevel) {
4416
+ super(
4417
+ /** @type {PrintProgram} */ (
4418
+ /** @type {PrintProgram | CompressorNode} */ (root)
4419
+ ),
4420
+ {
4421
+ ie8: options.ie8,
4422
+ safari10: options.safari10,
4423
+ module: options.module,
4424
+ parameterScopes: options.parameterScopes
4425
+ },
4426
+ raise,
4427
+ undefined
4428
+ );
4429
+ /** @type {CompressorDialect} */
4430
+ this.dialect = dialect;
4431
+ this.toplevel = /** @type {MinifierScope} */ (
4432
+ /** @type {MinifierScope | CompressorScopeShape} */ (toplevel)
4433
+ );
4434
+ this.tokenTables =
4435
+ /** @type {PrintProgram} */ (
4436
+ /** @type {PrintProgram | CompressorNode} */ (toplevel.node)
4437
+ ).tokenTables || undefined;
4438
+ this.scope = /** @type {MinifierScope} */ (
4439
+ /** @type {MinifierScope | CompressorScopeShape} */ (parentScope)
4440
+ );
4441
+ // The program's node holds its globals, as terser's did.
4442
+ this.globals = /** @type {Map<string, MinifierVariable>} */ (
4443
+ /** @type {Map<string, MinifierVariable> | Map<string, CompressorDefinition>} */ (
4444
+ toplevel.node.globals
4445
+ )
4446
+ );
4447
+ }
4448
+
4449
+ /**
4450
+ * @param {ScopeType} type what opens it
4451
+ * @param {PrintNode} node the node opening it
4452
+ * @param {boolean} isVarScope whether `var` hoists to here
4453
+ * @returns {MinifierScope} the scope, now current
4454
+ */
4455
+ _open(type, node, isVarScope) {
4456
+ const opener = /** @type {CompressorNode} */ (
4457
+ /** @type {CompressorNode | PrintNode} */ (node)
4458
+ );
4459
+ const scope = createCompressorScope(
4460
+ type,
4461
+ opener,
4462
+ /** @type {CompressorScopeShape | null} */ (
4463
+ /** @type {CompressorScopeShape | MinifierScope | null} */ (this.scope)
4464
+ ),
4465
+ isVarScope
4466
+ );
4467
+ // eslint-disable-next-line camelcase -- terser's name, which the compressor reads
4468
+ opener.block_scope = scope;
4469
+ this.scope = /** @type {MinifierScope} */ (
4470
+ /** @type {MinifierScope | CompressorScopeShape} */ (scope)
4471
+ );
4472
+ return this.scope;
4473
+ }
4474
+
4475
+ /**
4476
+ * terser's `def_variable`, the scope's binding of the name already looked up.
4477
+ * @param {MinifierScope} target the scope declaring it
4478
+ * @param {MinifierVariable | undefined} variable what the scope binds the name to, if anything
4479
+ * @param {PrintIdentifier | null} identifier the name declaring it, if written
4480
+ * @param {string} name the name
4481
+ * @param {number} kind how it is declared
4482
+ * @returns {MinifierVariable} its definition, made or joined
4483
+ */
4484
+ _addDeclaration(target, variable, identifier, name, kind) {
4485
+ const scope = /** @type {CompressorScopeShape} */ (
4486
+ /** @type {CompressorScopeShape | MinifierScope} */ (target)
4487
+ );
4488
+ const opener = /** @type {CompressorNode} */ (
4489
+ /** @type {CompressorNode | PrintNode} */ (this.scope.node)
4490
+ );
4491
+ /** @type {CompressorNode | null | undefined} */
4492
+ let init;
4493
+ let symbol;
4494
+ if (identifier === null) {
4495
+ symbol = this.dialect.argumentsSymbol(opener);
4496
+ } else {
4497
+ symbol = /** @type {CompressorNode} */ (
4498
+ /** @type {CompressorNode | PrintIdentifier} */ (identifier)
4499
+ );
4500
+ if ((1 << kind) & (FUNCTION_DECLARATIONS | (1 << DECLARES_CLASS))) {
4501
+ // A function's or class's name, its scope where it is declared.
4502
+ symbol.scope = scope;
4503
+ // A function expression named `arguments` is not its own value.
4504
+ init =
4505
+ kind === DECLARES_LAMBDA && name === "arguments" ? undefined : opener;
4506
+ } else if (kind !== DECLARES_FUNARG && kind !== DECLARES_IMPORT) {
4507
+ init = null;
4508
+ }
4509
+ }
4510
+ let definition = /** @type {CompressorDefinition | undefined} */ (
4511
+ /** @type {CompressorDefinition | MinifierVariable | undefined} */ (
4512
+ variable
4513
+ )
4514
+ );
4515
+ if (definition !== undefined) {
4516
+ definition.declarations |= 1 << kind;
4517
+ definition.identifiers.push(symbol);
4518
+ if (
4519
+ definition.init &&
4520
+ (definition.scope !== symbol.scope ||
4521
+ this.dialect.isFunction(definition.init))
4522
+ ) {
4523
+ definition.init = init;
4524
+ }
4525
+ } else {
4526
+ definition = createCompressorDefinition(name, scope, kind, symbol, init);
4527
+ definition.global = scope.upper === null;
4528
+ scope.bind(definition);
4529
+ }
4530
+ if (
4531
+ (1 << kind) & FUNCTION_DECLARATIONS &&
4532
+ (!definition.init || this.dialect.isDefun(definition.init))
4533
+ ) {
4534
+ definition.init = init;
4535
+ }
4536
+ symbol.definition = definition;
4537
+ return /** @type {MinifierVariable} */ (
4538
+ /** @type {MinifierVariable | CompressorDefinition} */ (definition)
4539
+ );
4540
+ }
4541
+
4542
+ /**
4543
+ * terser's `reference`.
4544
+ * @param {PrintIdentifier} identifier the name read
4545
+ * @param {MinifierScope} from the scope reading it
4546
+ * @param {MinifierVariable} variable what it reads
4547
+ * @returns {void}
4548
+ */
4549
+ _referenceVariable(identifier, from, variable) {
4550
+ /** @type {CompressorDefinition} */ (
4551
+ /** @type {CompressorDefinition | MinifierVariable} */ (variable)
4552
+ ).references.push(
4553
+ /** @type {CompressorNode} */ (
4554
+ /** @type {CompressorNode | PrintIdentifier} */ (identifier)
4555
+ )
4556
+ );
4557
+ encloseVariable(from, variable);
4558
+ }
4559
+
4560
+ /**
4561
+ * A `var`, parameter, `let`, `const`, `using`, catch parameter or import.
4562
+ * @param {PrintIdentifier} identifier the name declared
4563
+ * @param {number} kind how, as a `DECLARES_*` code
4564
+ * @returns {void}
4565
+ */
4566
+ _declare(identifier, kind) {
4567
+ /** @type {CompressorNode} */ (
4568
+ /** @type {CompressorNode | PrintIdentifier} */ (identifier)
4569
+ ).scope = /** @type {CompressorScopeShape} */ (
4570
+ /** @type {CompressorScopeShape | MinifierScope} */ (this.scope)
4571
+ );
4572
+ super._declare(identifier, kind);
4573
+ }
4574
+
4575
+ /**
4576
+ * @param {PrintIdentifier | PrintLiteral} node a name read, or a re-exported string
4577
+ * @param {number} flags what else is known of it, as `REFERENCE_*` bits
4578
+ * @returns {void}
4579
+ */
4580
+ _addReference(node, flags) {
4581
+ // The name holds the scope it is read in, as its `scope`.
4582
+ this.referenceNodes.push(node);
4583
+ this.referenceFlags.push(flags);
4584
+ }
4585
+
4586
+ /**
4587
+ * Records the scope of a symbol the walk reaches but the minifier's does not
4588
+ * read: a member's name, a label, or a name an import or export maps.
4589
+ * @param {PrintNode | CompressorNode | null | undefined} node a node, if any
4590
+ * @returns {void}
4591
+ */
4592
+ _recordScope(node) {
4593
+ if (node === null || node === undefined) return;
4594
+ const symbol = /** @type {CompressorNode} */ (node);
4595
+ if (this.dialect.isSymbol(symbol)) {
4596
+ symbol.scope = /** @type {CompressorScopeShape} */ (
4597
+ /** @type {CompressorScopeShape | MinifierScope} */ (this.scope)
4598
+ );
4599
+ }
4600
+ }
4601
+
4602
+ /**
4603
+ * Reads what is scoped as webpack does with the shared walk, pushed as
4604
+ * terser's walk pushes it, and the rest as terser's analysis does.
4605
+ * @param {PrintNode} current node to visit
4606
+ * @returns {void}
4607
+ */
4608
+ _visitPrint(current) {
4609
+ const node = /** @type {CompressorNode} */ (
4610
+ /** @type {CompressorNode | PrintNode} */ (current)
4611
+ );
4612
+ switch (current.type) {
4613
+ case "Identifier":
4614
+ case "ThisExpression":
4615
+ case "Super":
4616
+ case "PrivateIdentifier":
4617
+ case "Literal":
4618
+ this._recordScope(current);
4619
+ break;
4620
+ case "MethodDefinition":
4621
+ if (!current.computed) this._recordScope(current.key);
4622
+ break;
4623
+ case "Property":
4624
+ if (
4625
+ !current.computed &&
4626
+ !this.dialect.isObjectKeyValue(
4627
+ /** @type {CompressorNode} */ (
4628
+ /** @type {CompressorNode | PrintNode} */ (current)
4629
+ )
4630
+ )
4631
+ ) {
4632
+ this._recordScope(current.key);
4633
+ }
4634
+ break;
4635
+ case "PropertyDefinition":
4636
+ if (
4637
+ !current.computed &&
4638
+ !this.dialect.isPrivateField(
4639
+ /** @type {CompressorNode} */ (
4640
+ /** @type {CompressorNode | PrintNode} */ (current)
4641
+ )
4642
+ )
4643
+ ) {
4644
+ this._recordScope(current.key);
4645
+ }
4646
+ break;
4647
+ case "LabeledStatement":
4648
+ this._visitLabeled(node);
4649
+ return;
4650
+ case "BreakStatement":
4651
+ case "ContinueStatement":
4652
+ this._visitLoopControl(node);
4653
+ return;
4654
+ case "ImportDeclaration":
4655
+ this._visitNameMappings(node.imported_names);
4656
+ break;
4657
+ case "ExportNamedDeclaration":
4658
+ this._visitNameMappings(node.exported_names);
4659
+ break;
4660
+ case "ExportAllDeclaration":
4661
+ this._visitExportAll(node);
4662
+ return;
4663
+ }
4664
+ super._visitPrint(current);
4665
+ }
4666
+
4667
+ /**
4668
+ * @param {CompressorNode[] | null | undefined} mappings an import's or export's names
4669
+ * @returns {void}
4670
+ */
4671
+ _visitNameMappings(mappings) {
4672
+ if (!mappings) return;
4673
+ for (let i = 0; i < mappings.length; i++) {
4674
+ const mapping = mappings[i];
4675
+ this._recordScope(mapping.imported);
4676
+ this._recordScope(mapping.exported);
4677
+ this._recordScope(mapping.local);
4678
+ }
4679
+ }
4680
+
4681
+ /**
4682
+ * An `export *`, whose names read terser's `*` global.
4683
+ * @param {CompressorNode} node the export
4684
+ * @returns {void}
4685
+ */
4686
+ _visitExportAll(node) {
4687
+ const exported = /** @type {PrintNode} */ (
4688
+ /** @type {PrintNode | CompressorNode} */ (node)
4689
+ );
4690
+ this._checkModuleStatement(exported, "Export");
4691
+ /** @type {CompressorNode[]} */
4692
+ const names = node.exported_names;
4693
+ this._visitNameMappings(names);
4694
+ const stack = this.stack;
4695
+ stack.push(exported);
4696
+ for (let i = 0; i < names.length; i++) {
4697
+ const mapping = names[i];
4698
+ stack.push(
4699
+ /** @type {PrintNode} */ (
4700
+ /** @type {PrintNode | CompressorNode} */ (mapping)
4701
+ )
4702
+ );
4703
+ this._addReference(
4704
+ /** @type {PrintIdentifier} */ (mapping.local),
4705
+ REFERENCE_EXPORTED | REFERENCE_FROM_MODULE
4706
+ );
4707
+ stack.pop();
4708
+ }
4709
+ stack.pop();
4710
+ }
4711
+
4712
+ /**
4713
+ * A labeled statement, its label its own definition.
4714
+ * @param {CompressorNode} node the statement
4715
+ * @returns {void}
4716
+ */
4717
+ _visitLabeled(node) {
4718
+ const { label } = node;
4719
+ const { name } = label;
4720
+ const labels = /** @type {Map<string, CompressorNode>} */ (
4721
+ /** @type {Map<string, CompressorNode> | Map<string, MinifierLabel>} */ (
4722
+ this.labelsInScope
4723
+ )
4724
+ );
4725
+ if (labels.has(name)) throw new Error(`Label ${name} defined twice`);
4726
+ this._recordScope(label);
4727
+ // A label's definition is the label itself.
4728
+ label.definition = /** @type {CompressorDefinition} */ (
4729
+ /** @type {CompressorDefinition | CompressorNode} */ (label)
4730
+ );
4731
+ label.references = [];
4732
+ labels.set(name, label);
4733
+ this.stack.push(
4734
+ /** @type {PrintNode} */ (
4735
+ /** @type {PrintNode | CompressorNode} */ (node)
4736
+ )
4737
+ );
4738
+ this._visitPrint(
4739
+ /** @type {PrintNode} */ (
4740
+ /** @type {PrintNode | CompressorNode | CompressorNode[]} */ (node.body)
4741
+ )
4742
+ );
4743
+ this.stack.pop();
4744
+ labels.delete(name);
4745
+ }
4746
+
4747
+ /**
4748
+ * A `break` or `continue`, one of its label's references.
4749
+ * @param {CompressorNode} node the statement
4750
+ * @returns {void}
4751
+ */
4752
+ _visitLoopControl(node) {
4753
+ const name = /** @type {CompressorNode | null} */ (node.label);
4754
+ if (!name) return;
4755
+ this._recordScope(name);
4756
+ const label = /** @type {Map<string, CompressorNode>} */ (
4757
+ /** @type {Map<string, CompressorNode> | Map<string, MinifierLabel>} */ (
4758
+ this.labelsInScope
4759
+ )
4760
+ ).get(name.name);
4761
+ if (label === undefined) {
4762
+ const start = /** @type {Token} */ (this.tokenOf(name.startToken));
4763
+ throw new Error(
4764
+ `Undefined label ${name.name} [${start.line},${start.col}]`
4765
+ );
4766
+ }
4767
+ name.definition = /** @type {CompressorDefinition} */ (
4768
+ /** @type {CompressorDefinition | CompressorNode} */ (label)
4769
+ );
4770
+ label.references.push(node);
4771
+ }
4772
+
4773
+ /**
4774
+ * Resolves each name read as terser's compressor reads it: the definition's
4775
+ * reads, a function's own `arguments` read, and a read from a block of a
4776
+ * name the block does not keep moved to the function's scope.
4777
+ * @returns {void}
4778
+ */
4779
+ _resolveCompressor() {
4780
+ const { referenceNodes, referenceFlags } = this;
4781
+ const globals = /** @type {Map<string, CompressorDefinition>} */ (
4782
+ /** @type {Map<string, CompressorDefinition> | Map<string, MinifierVariable>} */ (
4783
+ this.globals
4784
+ )
4785
+ );
4786
+ const toplevel = /** @type {CompressorScopeShape} */ (
4787
+ /** @type {CompressorScopeShape | MinifierScope} */ (this.toplevel)
4788
+ );
4789
+ for (let i = 0; i < referenceNodes.length; i++) {
4790
+ const node = /** @type {CompressorNode} */ (
4791
+ /** @type {CompressorNode | PrintIdentifier | PrintLiteral} */ (
4792
+ referenceNodes[i]
4793
+ )
4794
+ );
4795
+ const from = /** @type {MinifierScope} */ (
4796
+ /** @type {MinifierScope | CompressorScopeShape} */ (node.scope)
4797
+ );
4798
+ const flags = referenceFlags[i];
4799
+ const { name } = node;
4800
+ if (flags & REFERENCE_CATCH) {
4801
+ const redefinition = /** @type {MinifierVariable | undefined} */ (
4802
+ from.variableScope.getBinding(name)
4803
+ );
4804
+ if (redefinition !== undefined) encloseVariable(from, redefinition);
4805
+ continue;
4806
+ }
4807
+ if (flags & REFERENCE_CALLED) {
4808
+ for (
4809
+ let outer = /** @type {MinifierScope | null} */ (from);
4810
+ outer !== null && !outer.usesEval;
4811
+ outer = /** @type {MinifierScope | null} */ (outer.upper)
4812
+ ) {
4813
+ outer.usesEval = true;
4814
+ }
4815
+ }
4816
+ let definition = /** @type {CompressorDefinition | undefined} */ (
4817
+ /** @type {CompressorDefinition | MinifierVariable | undefined} */ (
4818
+ flags & REFERENCE_FROM_MODULE
4819
+ ? undefined
4820
+ : findMinifierVariable(from, name, i)
4821
+ )
4822
+ );
4823
+ if (definition === undefined) {
4824
+ definition = globals.get(name);
4825
+ if (definition === undefined) {
4826
+ definition = createCompressorDefinition(
4827
+ name,
4828
+ toplevel,
4829
+ DECLARES_GLOBAL,
4830
+ node,
4831
+ undefined
4832
+ );
4833
+ definition.undeclared = true;
4834
+ definition.global = true;
4835
+ globals.set(name, definition);
4836
+ }
4837
+ if (flags & REFERENCE_EXPORTED) definition.export = EXPORT_KEEP_NAME;
4838
+ } else if (name === "arguments" && definition.scope.type === "function") {
4839
+ definition.scope.getDefunScope().usesArguments = true;
4840
+ }
4841
+ node.definition = definition;
4842
+ definition.references.push(node);
4843
+ encloseVariable(
4844
+ from,
4845
+ /** @type {MinifierVariable} */ (
4846
+ /** @type {MinifierVariable | CompressorDefinition} */ (definition)
4847
+ )
4848
+ );
4849
+ if (
4850
+ from.variableScope !== from &&
4851
+ ((1 << definition.kind) & BLOCK_DECLARATIONS) === 0
4852
+ ) {
4853
+ node.scope = /** @type {CompressorScopeShape} */ (
4854
+ /** @type {CompressorScopeShape | Scope} */ (from.variableScope)
4855
+ );
4856
+ }
4857
+ }
4858
+
4859
+ this._clearParameterRanges();
4860
+
4861
+ // Passes 3 and 4: work around old engines' catch and loop scopes.
4862
+ const { catchNames, catchScopes } = this;
4863
+ for (let i = 0; i < catchNames.length; i++) {
4864
+ const symbol = /** @type {CompressorNode} */ (
4865
+ /** @type {CompressorNode | PrintIdentifier} */ (catchNames[i])
4866
+ );
4867
+ const { name } = symbol;
4868
+ const { references } = symbol.definition;
4869
+ const defunScope = /** @type {CompressorScopeShape} */ (
4870
+ /** @type {CompressorScopeShape | Scope} */ (
4871
+ catchScopes[i].variableScope
4872
+ )
4873
+ );
4874
+ let definition = defunScope.findVariable(name) || globals.get(name);
4875
+ if (definition === undefined) {
4876
+ definition = createCompressorDefinition(
4877
+ name,
4878
+ defunScope,
4879
+ DECLARES_CATCH,
4880
+ symbol,
4881
+ undefined
4882
+ );
4883
+ definition.global = defunScope.upper === null;
4884
+ defunScope.bind(definition);
4885
+ }
4886
+ // As terser's `forEach`: referencing appends to the list it reads.
4887
+ const { length } = references;
4888
+ for (let j = 0; j < length; j++) {
4889
+ const read = references[j];
4890
+ read.definition = definition;
4891
+ read.scope.addReference(read);
4892
+ }
4893
+ symbol.definition = definition;
4894
+ symbol.scope.addReference(symbol);
4895
+ }
4896
+ const { forScopes } = this;
4897
+ for (let i = 0; i < forScopes.length; i++) {
4898
+ const forScope = forScopes[i];
4899
+ const variables = /** @type {MinifierScope} */ (forScope.upper).variables;
4900
+ for (let j = 0; j < variables.length; j++) {
4901
+ encloseUnique(forScope, /** @type {MinifierVariable} */ (variables[j]));
4902
+ }
4903
+ }
4904
+ }
4905
+ }
4906
+
4907
+ /**
4908
+ * Analyses the compressor's tree, or a function or class of it again, with
4909
+ * terser's scoping, recording what the compressor reads: see
4910
+ * `CompressorScopeAnalyzer`.
4911
+ * @param {CompressorNode} root the program, or a function or class in it
4912
+ * @param {MinifierScopeOptions} options the options
4913
+ * @param {(node: PrintNode, message: string, tables?: TokenTables) => never} raise throws the parse error a misplaced declaration is
4914
+ * @param {CompressorDialect} dialect what the tree's kinds answer
4915
+ * @param {CompressorScopeShape | null} parentScope the scope the root sits in, unless it is the program
4916
+ * @param {CompressorNode} program the program
4917
+ * @returns {void}
4918
+ */
4919
+ const analyzeCompressorScope = (
4920
+ root,
4921
+ options,
4922
+ raise,
4923
+ dialect,
4924
+ parentScope,
4925
+ program
4926
+ ) => {
4927
+ const isProgram = root === program;
4928
+ let toplevel;
4929
+ if (isProgram) {
4930
+ toplevel = createCompressorScope("global", root, null, true);
4931
+ root.globals = new Map();
4932
+ // eslint-disable-next-line camelcase -- terser's name, which the compressor reads
4933
+ root.block_scope = toplevel;
4934
+ } else {
4935
+ toplevel = program.block_scope;
4936
+ }
4937
+ const analyzer = new CompressorScopeAnalyzer(
4938
+ root,
4939
+ options,
4940
+ raise,
4941
+ dialect,
4942
+ isProgram ? toplevel : /** @type {CompressorScopeShape} */ (parentScope),
4943
+ toplevel
4944
+ );
4945
+ if (isProgram) {
4946
+ analyzer.stack.push(
4947
+ /** @type {PrintNode} */ (
4948
+ /** @type {PrintNode | CompressorNode} */ (root)
4949
+ )
4950
+ );
4951
+ analyzer._visitList(
4952
+ /** @type {PrintProgram} */ (
4953
+ /** @type {PrintProgram | CompressorNode} */ (root)
4954
+ ).body
4955
+ );
4956
+ } else {
4957
+ // What a declaration's `export` is read off is not there.
4958
+ analyzer.stack.push(
4959
+ /** @type {PrintNode} */ (
4960
+ /** @type {PrintNode | CompressorNode} */ (
4961
+ /** @type {CompressorScopeShape} */ (parentScope).node
4962
+ )
4963
+ )
4964
+ );
4965
+ analyzer._visitPrint(
4966
+ /** @type {PrintNode} */ (
4967
+ /** @type {PrintNode | CompressorNode} */ (root)
4968
+ )
4969
+ );
4970
+ }
4971
+ analyzer.stack.pop();
4972
+ analyzer._resolveCompressor();
1088
4973
  };
1089
4974
 
1090
4975
  analyzeScope.Reference = Reference;
1091
4976
  analyzeScope.Scope = Scope;
1092
4977
  analyzeScope.Variable = Variable;
4978
+ analyzeScope.MinifierLabel = MinifierLabel;
4979
+ analyzeScope.MinifierScope = MinifierScope;
4980
+ analyzeScope.MinifierVariable = MinifierVariable;
4981
+ analyzeScope.isMinifierVariable = isMinifierVariable;
4982
+ analyzeScope.CompressorScope = CompressorScope;
4983
+ analyzeScope.CompressorVariable = CompressorVariable;
4984
+ analyzeScope.createCompressorDefinition = createCompressorDefinition;
4985
+ analyzeScope.createCompressorScope = createCompressorScope;
4986
+ analyzeScope.analyzeMinifierScope = analyzeMinifierScope;
4987
+ analyzeScope.analyzeMinifierTree = analyzeMinifierTree;
4988
+ analyzeScope.analyzeCompressorScope = analyzeCompressorScope;
4989
+ analyzeScope.encloseUnique = encloseUnique;
4990
+ analyzeScope.DECLARES_VAR = DECLARES_VAR;
4991
+ analyzeScope.DECLARES_FUNARG = DECLARES_FUNARG;
4992
+ analyzeScope.DECLARES_LET = DECLARES_LET;
4993
+ analyzeScope.DECLARES_CONST = DECLARES_CONST;
4994
+ analyzeScope.DECLARES_USING = DECLARES_USING;
4995
+ analyzeScope.DECLARES_CATCH = DECLARES_CATCH;
4996
+ analyzeScope.DECLARES_IMPORT = DECLARES_IMPORT;
4997
+ analyzeScope.DECLARES_DEFUN = DECLARES_DEFUN;
4998
+ analyzeScope.DECLARES_LAMBDA = DECLARES_LAMBDA;
4999
+ analyzeScope.DECLARES_CLASS = DECLARES_CLASS;
5000
+ analyzeScope.DECLARES_DEF_CLASS = DECLARES_DEF_CLASS;
5001
+ analyzeScope.DECLARES_GLOBAL = DECLARES_GLOBAL;
5002
+ analyzeScope.EXPORT_KEEP_NAME = EXPORT_KEEP_NAME;
5003
+ analyzeScope.EXPORT_WANT_MANGLE = EXPORT_WANT_MANGLE;
1093
5004
 
1094
5005
  module.exports = analyzeScope;