@depup/webpack 5.111.1-depup.1 → 5.112.0-depup.0

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