diff --git a/Cargo.lock b/Cargo.lock index d0234badceab..c0ccf174b614 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5966,6 +5966,7 @@ dependencies = [ "swc_common", "swc_ecma_ast", "swc_ecma_parser", + "swc_ecma_transformer", "swc_ecma_transforms_base", "swc_ecma_transforms_testing", "swc_ecma_utils", diff --git a/crates/swc_ecma_compat_es2019/Cargo.toml b/crates/swc_ecma_compat_es2019/Cargo.toml index 2e08bd0f3ddb..ddae839709be 100644 --- a/crates/swc_ecma_compat_es2019/Cargo.toml +++ b/crates/swc_ecma_compat_es2019/Cargo.toml @@ -18,6 +18,7 @@ unexpected_cfgs = { level = "warn", check-cfg = ['cfg(swc_ast_unknown)'] } [dependencies] swc_common = { version = "17.0.1", path = "../swc_common" } swc_ecma_ast = { version = "18.0.0", path = "../swc_ecma_ast" } +swc_ecma_transformer = { version = "0.1.0", path = "../swc_ecma_transformer" } swc_ecma_transforms_base = { version = "30.0.0", path = "../swc_ecma_transforms_base" } swc_ecma_utils = { version = "24.0.0", path = "../swc_ecma_utils" } swc_ecma_visit = { version = "18.0.1", path = "../swc_ecma_visit" } diff --git a/crates/swc_ecma_compat_es2019/src/optional_catch_binding.rs b/crates/swc_ecma_compat_es2019/src/optional_catch_binding.rs index 5eeede447ba4..e28dd44c0cc3 100644 --- a/crates/swc_ecma_compat_es2019/src/optional_catch_binding.rs +++ b/crates/swc_ecma_compat_es2019/src/optional_catch_binding.rs @@ -3,24 +3,10 @@ use swc_ecma_utils::private_ident; use swc_ecma_visit::{noop_visit_mut_type, visit_mut_pass, VisitMut, VisitMutWith}; use swc_trace_macro::swc_trace; -struct OptionalCatchBinding; - pub fn optional_catch_binding() -> impl Pass { - visit_mut_pass(OptionalCatchBinding) -} - -#[swc_trace] -impl VisitMut for OptionalCatchBinding { - noop_visit_mut_type!(fail); - - fn visit_mut_catch_clause(&mut self, cc: &mut CatchClause) { - cc.visit_mut_children_with(self); - - if cc.param.is_some() { - return; - } - cc.param = Some(private_ident!("e").into()); - } + let mut options = swc_ecma_transformer::Options::default(); + options.env.es2019.optional_catch_binding = true; + options.into_pass() } #[cfg(test)] diff --git a/crates/swc_ecma_preset_env/src/lib.rs b/crates/swc_ecma_preset_env/src/lib.rs index 609a8998a114..7ffd38f37a67 100644 --- a/crates/swc_ecma_preset_env/src/lib.rs +++ b/crates/swc_ecma_preset_env/src/lib.rs @@ -185,7 +185,9 @@ where ); // ES2019 - let pass = add!(pass, OptionalCatchBinding, es2019::optional_catch_binding()); + if !caniuse(Feature::OptionalCatchBinding) { + options.env.es2019.optional_catch_binding = true; + } // ES2018 if !caniuse(Feature::ObjectRestSpread) { diff --git a/crates/swc_ecma_transformer/src/es2019/mod.rs b/crates/swc_ecma_transformer/src/es2019/mod.rs index 9cb5e904c876..2e585353e913 100644 --- a/crates/swc_ecma_transformer/src/es2019/mod.rs +++ b/crates/swc_ecma_transformer/src/es2019/mod.rs @@ -1,17 +1,19 @@ use swc_ecma_hooks::VisitMutHook; -use crate::TraverseCtx; +use crate::{hook_utils::OptionalHook, TraverseCtx}; + +mod optional_catch_binding; #[derive(Debug, Default)] #[non_exhaustive] -pub struct Es2019Options {} - -pub fn hook(options: Es2019Options) -> impl VisitMutHook { - Es2019Pass { options } +pub struct Es2019Options { + pub optional_catch_binding: bool, } -struct Es2019Pass { - options: Es2019Options, +pub(crate) fn hook(options: Es2019Options) -> impl VisitMutHook { + OptionalHook(if options.optional_catch_binding { + Some(self::optional_catch_binding::hook()) + } else { + None + }) } - -impl VisitMutHook for Es2019Pass {} diff --git a/crates/swc_ecma_transformer/src/es2019/optional_catch_binding.rs b/crates/swc_ecma_transformer/src/es2019/optional_catch_binding.rs new file mode 100644 index 000000000000..749acfd07f98 --- /dev/null +++ b/crates/swc_ecma_transformer/src/es2019/optional_catch_binding.rs @@ -0,0 +1,21 @@ +use swc_ecma_ast::*; +use swc_ecma_hooks::VisitMutHook; +use swc_ecma_utils::private_ident; + +use crate::TraverseCtx; + +pub fn hook() -> impl VisitMutHook { + OptionalCatchBindingPass {} +} + +struct OptionalCatchBindingPass {} + +impl VisitMutHook for OptionalCatchBindingPass { + fn enter_catch_clause(&mut self, node: &mut CatchClause, _: &mut TraverseCtx) { + if node.param.is_none() { + // TODO: Do not use private_ident! here. + // All private identifiers should be tracked using TraverseCtx. + node.param = Some(Pat::Ident(private_ident!("unused"))); + } + } +} diff --git a/crates/swc_ecma_transformer/src/hook_utils.rs b/crates/swc_ecma_transformer/src/hook_utils.rs index 7743c462700c..523c80dbc893 100644 --- a/crates/swc_ecma_transformer/src/hook_utils.rs +++ b/crates/swc_ecma_transformer/src/hook_utils.rs @@ -50,6 +50,8 @@ where optional_method!(enter_script, exit_script, Script); optional_method!(enter_program, exit_program, Program); + + optional_method!(enter_catch_clause, exit_catch_clause, CatchClause); } pub(crate) struct NoopHook;