From afe09d43065c5c64d9d03ab20b894bce932c4cb8 Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Wed, 19 Nov 2025 14:50:30 -0500 Subject: [PATCH 01/23] exponentation_operator --- .../src/es2016/exponentation_operator.rs | 12 +++++++++++ crates/swc_ecma_transformer/src/es2016/mod.rs | 20 ++++++++++--------- 2 files changed, 23 insertions(+), 9 deletions(-) create mode 100644 crates/swc_ecma_transformer/src/es2016/exponentation_operator.rs diff --git a/crates/swc_ecma_transformer/src/es2016/exponentation_operator.rs b/crates/swc_ecma_transformer/src/es2016/exponentation_operator.rs new file mode 100644 index 000000000000..5ad93b1e4d36 --- /dev/null +++ b/crates/swc_ecma_transformer/src/es2016/exponentation_operator.rs @@ -0,0 +1,12 @@ +use swc_ecma_hooks::VisitMutHook; + +use crate::TraverseCtx; + +pub fn hook() -> impl VisitMutHook { + ExponentiationOperatorPass::default() +} + +#[derive(Default)] +struct ExponentiationOperatorPass {} + +impl VisitMutHook for ExponentiationOperatorPass {} diff --git a/crates/swc_ecma_transformer/src/es2016/mod.rs b/crates/swc_ecma_transformer/src/es2016/mod.rs index 590c9a35dd7b..1fb2e9f92b5b 100644 --- a/crates/swc_ecma_transformer/src/es2016/mod.rs +++ b/crates/swc_ecma_transformer/src/es2016/mod.rs @@ -1,17 +1,19 @@ +mod exponentation_operator; + use swc_ecma_hooks::VisitMutHook; -use crate::TraverseCtx; +use crate::{hook_utils::OptionalHook, TraverseCtx}; #[derive(Debug, Default)] #[non_exhaustive] -pub struct Es2016Options {} - -pub fn hook(options: Es2016Options) -> impl VisitMutHook { - Es2016Pass { options } +pub struct Es2016Options { + pub exponentation_operator: bool, } -struct Es2016Pass { - options: Es2016Options, +pub fn hook(options: Es2016Options) -> impl VisitMutHook { + OptionalHook(if options.exponentation_operator { + Some(self::exponentation_operator::hook()) + } else { + None + }) } - -impl VisitMutHook for Es2016Pass {} From 7be7cd384ddccd61c632afade625bdef71445292 Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Wed, 19 Nov 2025 14:50:35 -0500 Subject: [PATCH 02/23] preset-env --- crates/swc_ecma_preset_env/src/lib.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/swc_ecma_preset_env/src/lib.rs b/crates/swc_ecma_preset_env/src/lib.rs index a1ad267eb870..0f44690fbf33 100644 --- a/crates/swc_ecma_preset_env/src/lib.rs +++ b/crates/swc_ecma_preset_env/src/lib.rs @@ -16,7 +16,7 @@ use swc_ecma_transforms::{ bugfixes, class_fields_use_set::class_fields_use_set, es2015::{self, generator::generator}, - es2016, es2017, es2018, es2019, es2020, es2022, es3, + es2017, es2018, es2019, es2020, es2022, es3, }, Assumptions, }; @@ -209,7 +209,9 @@ where ); // ES2016 - let pass = add!(pass, ExponentiationOperator, es2016::exponentiation()); + if !caniuse(Feature::ExponentiationOperator) { + options.env.es2016.exponentation_operator = true; + } // Single-pass compiler let pass = (pass, options.into_pass()); From 820d2b7ad1ad5c5411c8a2d67d891e2a06665faf Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Wed, 19 Nov 2025 15:47:12 -0500 Subject: [PATCH 03/23] compat --- crates/swc_ecma_compat_es2016/Cargo.toml | 1 + .../src/exponentiation.rs | 130 +----------------- 2 files changed, 4 insertions(+), 127 deletions(-) diff --git a/crates/swc_ecma_compat_es2016/Cargo.toml b/crates/swc_ecma_compat_es2016/Cargo.toml index 08676f5b1d43..ef89a5a603cd 100644 --- a/crates/swc_ecma_compat_es2016/Cargo.toml +++ b/crates/swc_ecma_compat_es2016/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_transforms_macros = { version = "1.0.1", path = "../swc_ecma_transforms_macros" } swc_ecma_utils = { version = "24.0.0", path = "../swc_ecma_utils" } diff --git a/crates/swc_ecma_compat_es2016/src/exponentiation.rs b/crates/swc_ecma_compat_es2016/src/exponentiation.rs index a7027ead414b..42520b04fa5d 100644 --- a/crates/swc_ecma_compat_es2016/src/exponentiation.rs +++ b/crates/swc_ecma_compat_es2016/src/exponentiation.rs @@ -1,10 +1,4 @@ -use swc_common::{util::take::Take, Span, Spanned, DUMMY_SP}; use swc_ecma_ast::*; -use swc_ecma_transforms_base::perf::{ParExplode, Parallel}; -use swc_ecma_transforms_macros::parallel; -use swc_ecma_utils::{member_expr, private_ident, ExprFactory}; -use swc_ecma_visit::{noop_visit_mut_type, visit_mut_pass, VisitMut, VisitMutWith}; -use swc_trace_macro::swc_trace; /// `@babel/plugin-transform-exponentiation-operator` /// @@ -26,127 +20,9 @@ use swc_trace_macro::swc_trace; /// x = Math.pow(x, 3); /// ``` pub fn exponentiation() -> impl Pass { - visit_mut_pass(Exponentiation::default()) -} - -#[derive(Default)] -struct Exponentiation { - vars: Vec, -} - -impl Parallel for Exponentiation { - fn create(&self) -> Self { - Self::default() - } - - fn merge(&mut self, other: Self) { - self.vars.extend(other.vars); - } -} - -#[swc_trace] -impl ParExplode for Exponentiation { - fn after_one_stmt(&mut self, stmts: &mut Vec) { - if !self.vars.is_empty() { - stmts.push( - VarDecl { - span: DUMMY_SP, - kind: VarDeclKind::Var, - decls: self.vars.take(), - declare: false, - ..Default::default() - } - .into(), - ); - } - } - - fn after_one_module_item(&mut self, stmts: &mut Vec) { - if !self.vars.is_empty() { - stmts.push( - VarDecl { - span: DUMMY_SP, - kind: VarDeclKind::Var, - decls: self.vars.take(), - declare: false, - ..Default::default() - } - .into(), - ); - } - } -} - -#[swc_trace] -#[parallel(explode)] -impl VisitMut for Exponentiation { - noop_visit_mut_type!(fail); - - fn visit_mut_expr(&mut self, e: &mut Expr) { - e.visit_mut_children_with(self); - - match e { - Expr::Assign(AssignExpr { - span, - left, - op: op @ op!("**="), - right, - }) => { - let lhs: Ident = match left { - _ if left.as_ident().is_some() => left.as_ident().unwrap().clone().into(), - - // unimplemented - AssignTarget::Simple(ref e) => { - let ref_ident = private_ident!(e.span(), "ref"); - - self.vars.push(VarDeclarator { - span: DUMMY_SP, - name: ref_ident.clone().into(), - init: Some(e.clone().into()), - definite: false, - }); - ref_ident - } - - left => { - *e = AssignExpr { - span: *span, - left: left.take(), - op: op!("="), - right: right.take(), - } - .into(); - return; - } - }; - - *op = op!("="); - *right = Box::new(mk_call(*span, Box::new(lhs.into()), right.take())); - } - Expr::Bin(BinExpr { - span, - left, - op: op!("**"), - right, - }) => { - *e = mk_call(*span, left.take(), right.take()); - } - _ => {} - } - } -} - -#[tracing::instrument(level = "debug", skip_all)] -fn mk_call(span: Span, left: Box, right: Box) -> Expr { - // Math.pow() - CallExpr { - span, - callee: member_expr!(Default::default(), span, Math.pow).as_callee(), - - args: vec![left.as_arg(), right.as_arg()], - ..Default::default() - } - .into() + let mut options = swc_ecma_transformer::Options::default(); + options.env.es2016.exponentation_operator = true; + options.into_pass() } #[cfg(test)] From c24f9abbf88d0bcf06e83c4a962d77ed98358c4a Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Wed, 19 Nov 2025 15:47:17 -0500 Subject: [PATCH 04/23] lockfile --- Cargo.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.lock b/Cargo.lock index 4255c8ce8a96..c7f690b0b02d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5918,6 +5918,7 @@ dependencies = [ "swc_common", "swc_ecma_ast", "swc_ecma_parser", + "swc_ecma_transformer", "swc_ecma_transforms_base", "swc_ecma_transforms_macros", "swc_ecma_transforms_testing", From 30a61c2591f59314190bef62d4a59f3ef77094d9 Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Wed, 19 Nov 2025 15:48:22 -0500 Subject: [PATCH 05/23] typo --- crates/swc_ecma_compat_es2016/src/exponentiation.rs | 2 +- crates/swc_ecma_preset_env/src/lib.rs | 2 +- ...entation_operator.rs => exponentiation_operator.rs} | 0 crates/swc_ecma_transformer/src/es2016/mod.rs | 10 +++++----- 4 files changed, 7 insertions(+), 7 deletions(-) rename crates/swc_ecma_transformer/src/es2016/{exponentation_operator.rs => exponentiation_operator.rs} (100%) diff --git a/crates/swc_ecma_compat_es2016/src/exponentiation.rs b/crates/swc_ecma_compat_es2016/src/exponentiation.rs index 42520b04fa5d..1ec38632a8aa 100644 --- a/crates/swc_ecma_compat_es2016/src/exponentiation.rs +++ b/crates/swc_ecma_compat_es2016/src/exponentiation.rs @@ -21,7 +21,7 @@ use swc_ecma_ast::*; /// ``` pub fn exponentiation() -> impl Pass { let mut options = swc_ecma_transformer::Options::default(); - options.env.es2016.exponentation_operator = true; + options.env.es2016.exponentiation_operator = true; options.into_pass() } diff --git a/crates/swc_ecma_preset_env/src/lib.rs b/crates/swc_ecma_preset_env/src/lib.rs index 0f44690fbf33..4efd4234b199 100644 --- a/crates/swc_ecma_preset_env/src/lib.rs +++ b/crates/swc_ecma_preset_env/src/lib.rs @@ -210,7 +210,7 @@ where // ES2016 if !caniuse(Feature::ExponentiationOperator) { - options.env.es2016.exponentation_operator = true; + options.env.es2016.exponentiation_operator = true; } // Single-pass compiler diff --git a/crates/swc_ecma_transformer/src/es2016/exponentation_operator.rs b/crates/swc_ecma_transformer/src/es2016/exponentiation_operator.rs similarity index 100% rename from crates/swc_ecma_transformer/src/es2016/exponentation_operator.rs rename to crates/swc_ecma_transformer/src/es2016/exponentiation_operator.rs diff --git a/crates/swc_ecma_transformer/src/es2016/mod.rs b/crates/swc_ecma_transformer/src/es2016/mod.rs index 1fb2e9f92b5b..0370c143a6be 100644 --- a/crates/swc_ecma_transformer/src/es2016/mod.rs +++ b/crates/swc_ecma_transformer/src/es2016/mod.rs @@ -1,18 +1,18 @@ -mod exponentation_operator; - use swc_ecma_hooks::VisitMutHook; use crate::{hook_utils::OptionalHook, TraverseCtx}; +mod exponentiation_operator; + #[derive(Debug, Default)] #[non_exhaustive] pub struct Es2016Options { - pub exponentation_operator: bool, + pub exponentiation_operator: bool, } pub fn hook(options: Es2016Options) -> impl VisitMutHook { - OptionalHook(if options.exponentation_operator { - Some(self::exponentation_operator::hook()) + OptionalHook(if options.exponentiation_operator { + Some(self::exponentiation_operator::hook()) } else { None }) From 18a06143f732e361480f003505dd12573f8ef285 Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Wed, 19 Nov 2025 16:56:00 -0500 Subject: [PATCH 06/23] hook utils --- crates/swc_ecma_transformer/src/hook_utils.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/swc_ecma_transformer/src/hook_utils.rs b/crates/swc_ecma_transformer/src/hook_utils.rs index e577cca68781..7743c462700c 100644 --- a/crates/swc_ecma_transformer/src/hook_utils.rs +++ b/crates/swc_ecma_transformer/src/hook_utils.rs @@ -31,12 +31,20 @@ where optional_method!(enter_expr, exit_expr, Expr); + optional_method!(enter_expr_stmt, exit_expr_stmt, ExprStmt); + optional_method!(enter_pat, exit_pat, Pat); optional_method!(enter_stmt, exit_stmt, Stmt); + optional_method!(enter_stmts, exit_stmts, Vec); + + optional_method!(enter_block_stmt, exit_block_stmt, BlockStmt); + optional_method!(enter_module_item, exit_module_item, ModuleItem); + optional_method!(enter_module_items, exit_module_items, Vec); + optional_method!(enter_module, exit_module, Module); optional_method!(enter_script, exit_script, Script); From 4aa1d64a1c19321740ee069c196948f9a275fbf4 Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Thu, 20 Nov 2025 05:58:01 -0500 Subject: [PATCH 07/23] mod common --- crates/swc_ecma_transformer/src/common/mod.rs | 3 +++ crates/swc_ecma_transformer/src/common/statement_injector.rs | 0 crates/swc_ecma_transformer/src/lib.rs | 1 + 3 files changed, 4 insertions(+) create mode 100644 crates/swc_ecma_transformer/src/common/mod.rs create mode 100644 crates/swc_ecma_transformer/src/common/statement_injector.rs diff --git a/crates/swc_ecma_transformer/src/common/mod.rs b/crates/swc_ecma_transformer/src/common/mod.rs new file mode 100644 index 000000000000..5f8fa3d2b349 --- /dev/null +++ b/crates/swc_ecma_transformer/src/common/mod.rs @@ -0,0 +1,3 @@ +pub use self::statement_injector::*; + +mod statement_injector; diff --git a/crates/swc_ecma_transformer/src/common/statement_injector.rs b/crates/swc_ecma_transformer/src/common/statement_injector.rs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/crates/swc_ecma_transformer/src/lib.rs b/crates/swc_ecma_transformer/src/lib.rs index 4b09cafcf84b..d37772d6e4d3 100644 --- a/crates/swc_ecma_transformer/src/lib.rs +++ b/crates/swc_ecma_transformer/src/lib.rs @@ -8,6 +8,7 @@ use crate::hook_utils::{HookBuilder, NoopHook}; pub use crate::options::*; mod bugfix; +mod common; mod decorators; mod es2015; mod es2016; From 595c3ea5c73574e3c725aa718d246f81ebdcd6f6 Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Thu, 20 Nov 2025 06:00:56 -0500 Subject: [PATCH 08/23] Dep --- crates/swc_ecma_transformer/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/swc_ecma_transformer/Cargo.toml b/crates/swc_ecma_transformer/Cargo.toml index 4304eabfec2c..8102b5db840f 100644 --- a/crates/swc_ecma_transformer/Cargo.toml +++ b/crates/swc_ecma_transformer/Cargo.toml @@ -13,6 +13,7 @@ version = "1.0.0" unexpected_cfgs = { level = "warn", check-cfg = ['cfg(swc_ast_unknown)'] } [dependencies] +rustc-hash = { workspace = true } swc_atoms = { version = "9.0.0", path = "../swc_atoms" } swc_common = { version = "17.0.1", path = "../swc_common" } swc_ecma_ast = { version = "18.0.0", path = "../swc_ecma_ast" } From 1c3098132792a3553fdca68ae73ec13a01e6925e Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Thu, 20 Nov 2025 06:00:59 -0500 Subject: [PATCH 09/23] lockfile --- Cargo.lock | 1 + crates/swc_ecma_compat_es2016/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index c7f690b0b02d..361b2b6e13be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6332,6 +6332,7 @@ dependencies = [ name = "swc_ecma_transformer" version = "1.0.0" dependencies = [ + "rustc-hash 2.1.1", "swc_atoms", "swc_common", "swc_ecma_ast", diff --git a/crates/swc_ecma_compat_es2016/Cargo.toml b/crates/swc_ecma_compat_es2016/Cargo.toml index ef89a5a603cd..f66f13f8a892 100644 --- a/crates/swc_ecma_compat_es2016/Cargo.toml +++ b/crates/swc_ecma_compat_es2016/Cargo.toml @@ -18,7 +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_transformer = { version = "1.0.0", path = "../swc_ecma_transformer" } swc_ecma_transforms_base = { version = "30.0.0", path = "../swc_ecma_transforms_base" } swc_ecma_transforms_macros = { version = "1.0.1", path = "../swc_ecma_transforms_macros" } swc_ecma_utils = { version = "24.0.0", path = "../swc_ecma_utils" } From 90cc6bb9f30da47de1e4cf472e0ff2b80692e3a0 Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Thu, 20 Nov 2025 06:01:36 -0500 Subject: [PATCH 10/23] Enable `path` --- crates/swc_ecma_transformer/Cargo.toml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/crates/swc_ecma_transformer/Cargo.toml b/crates/swc_ecma_transformer/Cargo.toml index 8102b5db840f..b6fefdf2663a 100644 --- a/crates/swc_ecma_transformer/Cargo.toml +++ b/crates/swc_ecma_transformer/Cargo.toml @@ -13,12 +13,14 @@ version = "1.0.0" unexpected_cfgs = { level = "warn", check-cfg = ['cfg(swc_ast_unknown)'] } [dependencies] -rustc-hash = { workspace = true } -swc_atoms = { version = "9.0.0", path = "../swc_atoms" } -swc_common = { version = "17.0.1", path = "../swc_common" } -swc_ecma_ast = { version = "18.0.0", path = "../swc_ecma_ast" } -swc_ecma_hooks = { version = "0.2.0", path = "../swc_ecma_hooks" } +rustc-hash = { workspace = true } +swc_atoms = { version = "9.0.0", path = "../swc_atoms" } +swc_common = { version = "17.0.1", path = "../swc_common" } +swc_ecma_ast = { version = "18.0.0", path = "../swc_ecma_ast" } +swc_ecma_hooks = { version = "0.2.0", path = "../swc_ecma_hooks" } 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" } -tracing = { workspace = true } +swc_ecma_utils = { version = "24.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "18.0.1", path = "../swc_ecma_visit", features = [ + "path", +] } +tracing = { workspace = true } From 15001e9f8c5c141b541c41d551b4d6a12e18414f Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Thu, 20 Nov 2025 06:03:27 -0500 Subject: [PATCH 11/23] stmt injector --- .../src/common/statement_injector.rs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/crates/swc_ecma_transformer/src/common/statement_injector.rs b/crates/swc_ecma_transformer/src/common/statement_injector.rs index e69de29bb2d1..1fcee0e149b3 100644 --- a/crates/swc_ecma_transformer/src/common/statement_injector.rs +++ b/crates/swc_ecma_transformer/src/common/statement_injector.rs @@ -0,0 +1,31 @@ +use std::cell::RefCell; + +use rustc_hash::FxHashMap; +use swc_ecma_ast::*; +use swc_ecma_hooks::VisitMutHook; +use swc_ecma_visit::AstKindPath; + +use crate::TraverseCtx; + +#[derive(Debug, Default)] +pub struct StatementInjector {} + +#[derive(Debug)] +enum Direction { + Before, + After, +} + +#[derive(Debug)] +struct AdjacentStatement { + stmt: Stmt, + direction: Direction, +} + +/// Store for statements to be added to the statements. +#[derive(Default)] +pub struct StatementInjectorStore { + insertions: RefCell>>, +} + +impl VisitMutHook for StatementInjector {} From 3f55698c03948c971878bfd93ebb6b9394975695 Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Thu, 20 Nov 2025 06:12:14 -0500 Subject: [PATCH 12/23] cmt --- .../src/common/statement_injector.rs | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/crates/swc_ecma_transformer/src/common/statement_injector.rs b/crates/swc_ecma_transformer/src/common/statement_injector.rs index 1fcee0e149b3..f895efaa6658 100644 --- a/crates/swc_ecma_transformer/src/common/statement_injector.rs +++ b/crates/swc_ecma_transformer/src/common/statement_injector.rs @@ -1,3 +1,20 @@ +//! Utility transform to add new statements before or after the specified +//! statement. +//! +//! `StatementInjectorStore` contains a `FxHashMap>`. It is stored on `TransformCtx`. +//! +//! `StatementInjector` transform inserts new statements before or after a +//! statement which is determined by the address of the statement. +//! +//! Other transforms can add statements to the store with following methods: +//! +//! ```rs +//! self.ctx.statement_injector.insert_before(address, statement); +//! self.ctx.statement_injector.insert_after(address, statement); +//! self.ctx.statement_injector.insert_many_after(address, statements); +//! ``` + use std::cell::RefCell; use rustc_hash::FxHashMap; @@ -8,7 +25,7 @@ use swc_ecma_visit::AstKindPath; use crate::TraverseCtx; #[derive(Debug, Default)] -pub struct StatementInjector {} +pub struct StmtInjector {} #[derive(Debug)] enum Direction { @@ -17,15 +34,15 @@ enum Direction { } #[derive(Debug)] -struct AdjacentStatement { +struct AdjacentStmt { stmt: Stmt, direction: Direction, } -/// Store for statements to be added to the statements. +/// Store for Stmts to be added to the Stmts. #[derive(Default)] -pub struct StatementInjectorStore { - insertions: RefCell>>, +pub struct StmtInjectorStore { + insertions: RefCell>>, } -impl VisitMutHook for StatementInjector {} +impl VisitMutHook for StmtInjector {} From 77cb29c50a59a81d43337e9aef3a618d409906ec Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Thu, 20 Nov 2025 06:18:31 -0500 Subject: [PATCH 13/23] remove --- .../swc_ecma_transformer/src/common/statement_injector.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/crates/swc_ecma_transformer/src/common/statement_injector.rs b/crates/swc_ecma_transformer/src/common/statement_injector.rs index f895efaa6658..c50573ed6b66 100644 --- a/crates/swc_ecma_transformer/src/common/statement_injector.rs +++ b/crates/swc_ecma_transformer/src/common/statement_injector.rs @@ -15,12 +15,8 @@ //! self.ctx.statement_injector.insert_many_after(address, statements); //! ``` -use std::cell::RefCell; - -use rustc_hash::FxHashMap; use swc_ecma_ast::*; use swc_ecma_hooks::VisitMutHook; -use swc_ecma_visit::AstKindPath; use crate::TraverseCtx; @@ -41,8 +37,6 @@ struct AdjacentStmt { /// Store for Stmts to be added to the Stmts. #[derive(Default)] -pub struct StmtInjectorStore { - insertions: RefCell>>, -} +pub struct StmtInjectorStore {} impl VisitMutHook for StmtInjector {} From 267c14439907246acb620c8f23bdc09ac097f339 Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Thu, 20 Nov 2025 06:24:54 -0500 Subject: [PATCH 14/23] Inject! --- .../src/common/statement_injector.rs | 88 ++++++- .../src/es2016/exponentiation_operator.rs | 214 +++++++++++++++++- crates/swc_ecma_transformer/src/lib.rs | 17 +- 3 files changed, 314 insertions(+), 5 deletions(-) diff --git a/crates/swc_ecma_transformer/src/common/statement_injector.rs b/crates/swc_ecma_transformer/src/common/statement_injector.rs index c50573ed6b66..537c475fd0f6 100644 --- a/crates/swc_ecma_transformer/src/common/statement_injector.rs +++ b/crates/swc_ecma_transformer/src/common/statement_injector.rs @@ -15,6 +15,7 @@ //! self.ctx.statement_injector.insert_many_after(address, statements); //! ``` +use rustc_hash::FxHashMap; use swc_ecma_ast::*; use swc_ecma_hooks::VisitMutHook; @@ -36,7 +37,90 @@ struct AdjacentStmt { } /// Store for Stmts to be added to the Stmts. +/// +/// The key is the address of the statement in the AST, represented as a +/// pointer. #[derive(Default)] -pub struct StmtInjectorStore {} +pub struct StmtInjectorStore { + /// Map from statement address to adjacent statements to insert + stmts: FxHashMap>, +} + +impl StmtInjectorStore { + /// Insert a statement before the statement at the given address + pub fn insert_before(&mut self, address: usize, stmt: Stmt) { + self.stmts.entry(address).or_default().push(AdjacentStmt { + stmt, + direction: Direction::Before, + }); + } + + /// Insert a statement after the statement at the given address + pub fn insert_after(&mut self, address: usize, stmt: Stmt) { + self.stmts.entry(address).or_default().push(AdjacentStmt { + stmt, + direction: Direction::After, + }); + } + + /// Insert multiple statements after the statement at the given address + pub fn insert_many_after(&mut self, address: usize, stmts: Vec) { + let entry = self.stmts.entry(address).or_default(); + for stmt in stmts { + entry.push(AdjacentStmt { + stmt, + direction: Direction::After, + }); + } + } + + /// Get all statements to be inserted at the given address + fn take_stmts(&mut self, address: usize) -> Option> { + self.stmts.remove(&address) + } +} -impl VisitMutHook for StmtInjector {} +impl VisitMutHook for StmtInjector { + fn enter_stmts(&mut self, stmts: &mut Vec, ctx: &mut TraverseCtx) { + let mut i = 0; + while i < stmts.len() { + let stmt = &stmts[i]; + let address = stmt as *const Stmt as usize; + + // Check if there are any statements to insert at this address + if let Some(adjacent_stmts) = ctx.statement_injector.take_stmts(address) { + let mut before_stmts = Vec::new(); + let mut after_stmts = Vec::new(); + + // Separate statements by direction + for adjacent in adjacent_stmts { + match adjacent.direction { + Direction::Before => before_stmts.push(adjacent.stmt), + Direction::After => after_stmts.push(adjacent.stmt), + } + } + + // Insert statements before + let before_count = before_stmts.len(); + if before_count > 0 { + // Insert all before statements at position i + for (offset, stmt) in before_stmts.into_iter().enumerate() { + stmts.insert(i + offset, stmt); + } + // Move index forward by the number of inserted statements + i += before_count; + } + + // Insert statements after + if !after_stmts.is_empty() { + // Insert all after statements at position i + 1 + for (offset, stmt) in after_stmts.into_iter().enumerate() { + stmts.insert(i + 1 + offset, stmt); + } + } + } + + i += 1; + } + } +} diff --git a/crates/swc_ecma_transformer/src/es2016/exponentiation_operator.rs b/crates/swc_ecma_transformer/src/es2016/exponentiation_operator.rs index 5ad93b1e4d36..d5b7d1001726 100644 --- a/crates/swc_ecma_transformer/src/es2016/exponentiation_operator.rs +++ b/crates/swc_ecma_transformer/src/es2016/exponentiation_operator.rs @@ -1,3 +1,38 @@ +//! ES2016: Exponentiation Operator +//! +//! This plugin transforms the exponentiation operator (`**`) to `Math.pow`. +//! +//! > This plugin is included in `preset-env`, in ES2016 +//! +//! ## Example +//! +//! Input: +//! ```js +//! let x = 10 ** 2; +//! x **= 3; +//! obj.prop **= 4; +//! ``` +//! +//! Output: +//! ```js +//! let x = Math.pow(10, 2); +//! x = Math.pow(x, 3); +//! obj["prop"] = Math.pow(obj["prop"], 4); +//! ``` +//! +//! ## Implementation +//! +//! Implementation based on [@babel/plugin-transform-exponentiation-operator](https://babel.dev/docs/babel-plugin-transform-exponentiation-operator). +//! +//! ## References: +//! +//! * Babel plugin implementation: +//! +//! * Exponentiation operator TC39 proposal: +//! * Exponentiation operator specification: + +use swc_common::{util::take::Take, SyntaxContext, DUMMY_SP}; +use swc_ecma_ast::*; use swc_ecma_hooks::VisitMutHook; use crate::TraverseCtx; @@ -9,4 +44,181 @@ pub fn hook() -> impl VisitMutHook { #[derive(Default)] struct ExponentiationOperatorPass {} -impl VisitMutHook for ExponentiationOperatorPass {} +impl VisitMutHook for ExponentiationOperatorPass { + fn enter_expr(&mut self, expr: &mut Expr, _ctx: &mut TraverseCtx) { + match expr { + // `left ** right` -> `Math.pow(left, right)` + Expr::Bin(bin_expr) if bin_expr.op == BinaryOp::Exp => { + // Do not transform BigInt + if is_bigint_literal(&bin_expr.left) || is_bigint_literal(&bin_expr.right) { + return; + } + + let left = bin_expr.left.take(); + let right = bin_expr.right.take(); + *expr = create_math_pow(left, right); + } + // `left **= right` -> various transformations + Expr::Assign(assign_expr) if assign_expr.op == AssignOp::ExpAssign => { + // Do not transform BigInt + if is_bigint_literal(&assign_expr.right) { + return; + } + + self.transform_exp_assign(expr); + } + _ => {} + } + } +} + +impl ExponentiationOperatorPass { + /// Transform exponentiation assignment expression + /// + /// Transforms based on the type of left side: + /// - Identifier: `x **= 2` -> `x = Math.pow(x, 2)` + /// - Member expression: `obj.prop **= 2` -> `obj.prop = Math.pow(obj.prop, + /// 2)` or with temp var + fn transform_exp_assign(&self, expr: &mut Expr) { + let Expr::Assign(assign_expr) = expr else { + return; + }; + + match &assign_expr.left { + // Simple identifier: `x **= 2` -> `x = Math.pow(x, 2)` + AssignTarget::Simple(SimpleAssignTarget::Ident(ident)) => { + let left = ident.id.clone(); + let right = assign_expr.right.take(); + + let pow_left = Box::new(Expr::Ident(left.clone())); + let pow_call = create_math_pow(pow_left, right); + + *expr = Expr::Assign(AssignExpr { + span: DUMMY_SP, + op: AssignOp::Assign, + left: AssignTarget::Simple(SimpleAssignTarget::Ident(BindingIdent { + id: left, + type_ann: None, + })), + right: Box::new(pow_call), + }); + } + // Member expression: needs special handling to avoid side effects + AssignTarget::Simple(SimpleAssignTarget::Member(member_expr)) => { + // Clone the data we need before borrowing mutably + let obj = member_expr.obj.clone(); + let prop = member_expr.prop.clone(); + let right = assign_expr.right.take(); + + self.transform_member_exp_assign_impl(expr, obj, prop, right); + } + _ => {} + } + } + + /// Transform member expression exponentiation assignment implementation + /// + /// `obj.prop **= 2` or `obj[prop] **= 2` + fn transform_member_exp_assign_impl( + &self, + expr: &mut Expr, + obj: Box, + prop: MemberProp, + right: Box, + ) { + // For simplicity, handle the basic case without temp variables + // A more complete implementation would add temp variables to avoid side effects + match prop { + // obj.prop **= right -> obj.prop = Math.pow(obj.prop, right) + MemberProp::Ident(prop_name) => { + // Create Math.pow(obj.prop, right) + let pow_left = Box::new(Expr::Member(MemberExpr { + span: DUMMY_SP, + obj: obj.clone(), + prop: MemberProp::Ident(prop_name.clone()), + })); + let pow_call = create_math_pow(pow_left, right); + + // obj.prop = Math.pow(obj.prop, right) + *expr = Expr::Assign(AssignExpr { + span: DUMMY_SP, + op: AssignOp::Assign, + left: AssignTarget::Simple(SimpleAssignTarget::Member(MemberExpr { + span: DUMMY_SP, + obj, + prop: MemberProp::Ident(prop_name), + })), + right: Box::new(pow_call), + }); + } + // obj[computed] **= right -> obj[computed] = Math.pow(obj[computed], right) + MemberProp::Computed(computed) => { + let computed_prop = computed.expr; + + // Create Math.pow(obj[computed], right) + let pow_left = Box::new(Expr::Member(MemberExpr { + span: DUMMY_SP, + obj: obj.clone(), + prop: MemberProp::Computed(ComputedPropName { + span: DUMMY_SP, + expr: computed_prop.clone(), + }), + })); + let pow_call = create_math_pow(pow_left, right); + + // obj[computed] = Math.pow(obj[computed], right) + *expr = Expr::Assign(AssignExpr { + span: DUMMY_SP, + op: AssignOp::Assign, + left: AssignTarget::Simple(SimpleAssignTarget::Member(MemberExpr { + span: DUMMY_SP, + obj, + prop: MemberProp::Computed(ComputedPropName { + span: DUMMY_SP, + expr: computed_prop, + }), + })), + right: Box::new(pow_call), + }); + } + _ => {} + } + } +} + +/// Create `Math.pow(left, right)` call expression +fn create_math_pow(left: Box, right: Box) -> Expr { + Expr::Call(CallExpr { + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + callee: Callee::Expr(Box::new(Expr::Member(MemberExpr { + span: DUMMY_SP, + obj: Box::new(Expr::Ident(Ident { + span: DUMMY_SP, + ctxt: SyntaxContext::empty(), + sym: "Math".into(), + optional: false, + })), + prop: MemberProp::Ident(IdentName { + span: DUMMY_SP, + sym: "pow".into(), + }), + }))), + args: vec![ + ExprOrSpread { + spread: None, + expr: left, + }, + ExprOrSpread { + spread: None, + expr: right, + }, + ], + type_args: None, + }) +} + +/// Check if an expression is a BigInt literal +fn is_bigint_literal(expr: &Expr) -> bool { + matches!(expr, Expr::Lit(Lit::BigInt(_))) +} diff --git a/crates/swc_ecma_transformer/src/lib.rs b/crates/swc_ecma_transformer/src/lib.rs index d37772d6e4d3..7e7922fe2d01 100644 --- a/crates/swc_ecma_transformer/src/lib.rs +++ b/crates/swc_ecma_transformer/src/lib.rs @@ -26,7 +26,17 @@ mod regexp; mod typescript; mod utils; -pub struct TraverseCtx {} +pub struct TraverseCtx { + pub statement_injector: common::StmtInjectorStore, +} + +impl Default for TraverseCtx { + fn default() -> Self { + Self { + statement_injector: Default::default(), + } + } +} pub fn transform_hook(options: Options) -> impl VisitMutHook { let hook = HookBuilder::new(NoopHook); @@ -47,11 +57,14 @@ pub fn transform_hook(options: Options) -> impl VisitMutHook { let hook = hook.chain_optional(crate::regexp::hook(options.env.regexp)); let hook = hook.chain(crate::bugfix::hook(options.env.bugfix)); + // Statement injector must be last to process all injected statements + let hook = hook.chain(common::StmtInjector::default()); + hook.build() } pub fn hook_pass>(hook: H) -> impl Pass { - let ctx = TraverseCtx {}; + let ctx = TraverseCtx::default(); visit_mut_pass(VisitMutWithHook { hook, context: ctx }) } From 4a2a25ad24231a94f066ee8418f4689b04ee5c04 Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Thu, 20 Nov 2025 06:38:24 -0500 Subject: [PATCH 15/23] Dep --- crates/swc_ecma_compat_es2016/Cargo.toml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/crates/swc_ecma_compat_es2016/Cargo.toml b/crates/swc_ecma_compat_es2016/Cargo.toml index f66f13f8a892..cc83c51222d5 100644 --- a/crates/swc_ecma_compat_es2016/Cargo.toml +++ b/crates/swc_ecma_compat_es2016/Cargo.toml @@ -16,16 +16,15 @@ version = "30.0.0" 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 = "1.0.0", path = "../swc_ecma_transformer" } -swc_ecma_transforms_base = { version = "30.0.0", path = "../swc_ecma_transforms_base" } -swc_ecma_transforms_macros = { version = "1.0.1", path = "../swc_ecma_transforms_macros" } -swc_ecma_utils = { version = "24.0.0", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "18.0.1", path = "../swc_ecma_visit" } -swc_trace_macro = { version = "2.0.2", path = "../swc_trace_macro" } -tracing = { workspace = true } +swc_ecma_ast = { version = "18.0.0", path = "../swc_ecma_ast" } +swc_ecma_transformer = { version = "1.0.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" } +tracing = { workspace = true } [dev-dependencies] +swc_common = { version = "17.0.1", path = "../swc_common" } swc_ecma_parser = { version = "27.0.6", path = "../swc_ecma_parser" } +swc_ecma_transforms_macros = { version = "1.0.1", path = "../swc_ecma_transforms_macros" } swc_ecma_transforms_testing = { version = "33.0.0", path = "../swc_ecma_transforms_testing" } +swc_ecma_visit = { version = "18.0.1", path = "../swc_ecma_visit" } From 995c7ca2690cb9e536a1b342630c27a6384fe15d Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Thu, 20 Nov 2025 06:38:27 -0500 Subject: [PATCH 16/23] lockfile --- Cargo.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 361b2b6e13be..d16c835f7fb2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5924,7 +5924,6 @@ dependencies = [ "swc_ecma_transforms_testing", "swc_ecma_utils", "swc_ecma_visit", - "swc_trace_macro", "tracing", ] From 7e62bea7a0ef3511a6795e7205a9c99ced2f01ae Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Thu, 20 Nov 2025 06:38:33 -0500 Subject: [PATCH 17/23] derive default --- crates/swc_ecma_transformer/src/lib.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/crates/swc_ecma_transformer/src/lib.rs b/crates/swc_ecma_transformer/src/lib.rs index 7e7922fe2d01..d21345398b45 100644 --- a/crates/swc_ecma_transformer/src/lib.rs +++ b/crates/swc_ecma_transformer/src/lib.rs @@ -26,16 +26,9 @@ mod regexp; mod typescript; mod utils; +#[derive(Default)] pub struct TraverseCtx { - pub statement_injector: common::StmtInjectorStore, -} - -impl Default for TraverseCtx { - fn default() -> Self { - Self { - statement_injector: Default::default(), - } - } + pub(crate) statement_injector: common::StmtInjectorStore, } pub fn transform_hook(options: Options) -> impl VisitMutHook { From 1bf452ece714570429de169da8812103c5a3a494 Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Thu, 20 Nov 2025 06:39:59 -0500 Subject: [PATCH 18/23] Update test refs --- .../src/exponentiation.rs/assign_to_object_property.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/swc_ecma_compat_es2016/tests/__swc_snapshots__/src/exponentiation.rs/assign_to_object_property.js b/crates/swc_ecma_compat_es2016/tests/__swc_snapshots__/src/exponentiation.rs/assign_to_object_property.js index 811166c0f311..6aa394ad9179 100644 --- a/crates/swc_ecma_compat_es2016/tests/__swc_snapshots__/src/exponentiation.rs/assign_to_object_property.js +++ b/crates/swc_ecma_compat_es2016/tests/__swc_snapshots__/src/exponentiation.rs/assign_to_object_property.js @@ -1,3 +1,2 @@ var self = {}; -var ref = self.x; -self.x = Math.pow(ref, 3); +self.x = Math.pow(self.x, 3); From 6b92ca228d14453a830801ca5b9e2069a26e29ec Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Thu, 20 Nov 2025 06:41:00 -0500 Subject: [PATCH 19/23] Update test refs --- ...tiationAssignmentLHSIsReference.1.normal.js | 12 ++++-------- ...ationAssignmentLHSIsReference.2.minified.js | 10 ++-------- ...ionAssignmentWithIndexingOnLHS1.1.normal.js | 12 ++++-------- ...nAssignmentWithIndexingOnLHS1.2.minified.js | 16 ++++++++-------- ...ionAssignmentWithIndexingOnLHS2.1.normal.js | 18 ++++++------------ ...nAssignmentWithIndexingOnLHS2.2.minified.js | 13 +------------ ...ionAssignmentWithIndexingOnLHS3.1.normal.js | 9 +++------ ...nAssignmentWithIndexingOnLHS3.2.minified.js | 8 ++------ ...ionAssignmentWithIndexingOnLHS4.1.normal.js | 9 +++------ ...nAssignmentWithIndexingOnLHS4.2.minified.js | 8 ++------ ...mentWithPropertyAccessingOnLHS1.1.normal.js | 18 ++++++------------ ...ntWithPropertyAccessingOnLHS1.2.minified.js | 13 +------------ ...ularExpressionMixedWithComments.1.normal.js | 4 ++-- 13 files changed, 44 insertions(+), 106 deletions(-) diff --git a/crates/swc/tests/tsc-references/compoundExponentiationAssignmentLHSIsReference.1.normal.js b/crates/swc/tests/tsc-references/compoundExponentiationAssignmentLHSIsReference.1.normal.js index b5635beea28d..db004433160f 100644 --- a/crates/swc/tests/tsc-references/compoundExponentiationAssignmentLHSIsReference.1.normal.js +++ b/crates/swc/tests/tsc-references/compoundExponentiationAssignmentLHSIsReference.1.normal.js @@ -8,16 +8,12 @@ function fn1(x2) { } // property accesses var x3; -var ref = x3.a; -x3.a = Math.pow(ref, value); -var ref1 = x3['a']; -x3['a'] = Math.pow(ref1, value); +x3.a = Math.pow(x3.a, value); +x3['a'] = Math.pow(x3['a'], value); // parentheses, the contained expression is reference x1 = Math.pow(x1, value); function fn2(x4) { x4 = Math.pow(x4, value); } -var ref2 = x3.a; -x3.a = Math.pow(ref2, value); -var ref3 = x3['a']; -x3['a'] = Math.pow(ref3, value); +x3.a = Math.pow(x3.a, value); +x3['a'] = Math.pow(x3['a'], value); diff --git a/crates/swc/tests/tsc-references/compoundExponentiationAssignmentLHSIsReference.2.minified.js b/crates/swc/tests/tsc-references/compoundExponentiationAssignmentLHSIsReference.2.minified.js index f3a19d3dc03f..c6ca68f8229d 100644 --- a/crates/swc/tests/tsc-references/compoundExponentiationAssignmentLHSIsReference.2.minified.js +++ b/crates/swc/tests/tsc-references/compoundExponentiationAssignmentLHSIsReference.2.minified.js @@ -1,9 +1,3 @@ //// [compoundExponentiationAssignmentLHSIsReference.ts] -var value, x3, x1 = Math.pow(x1, value), ref = x3.a; -x3.a = Math.pow(ref, value); -var ref1 = x3.a; -x3.a = Math.pow(ref1, value), x1 = Math.pow(x1, value); -var ref2 = x3.a; -x3.a = Math.pow(ref2, value); -var ref3 = x3.a; -x3.a = Math.pow(ref3, value); +var value, x1, x3; +x1 = Math.pow(x1, value), x3.a = Math.pow(x3.a, value), x3.a = Math.pow(x3.a, value), x1 = Math.pow(x1, value), x3.a = Math.pow(x3.a, value), x3.a = Math.pow(x3.a, value); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.1.normal.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.1.normal.js index e610d77e6c21..5e00f4599692 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.1.normal.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.1.normal.js @@ -5,29 +5,25 @@ var array0 = [ 3 ]; var i0 = 0; -var ref = array0[++i0]; -array0[++i0] = Math.pow(ref, 2); +array0[++i0] = Math.pow(array0[++i0], 2); var array1 = [ 1, 2, 3 ]; var i1 = 0; -var ref1 = array1[++i1], ref2 = array1[++i1]; -array1[++i1] = Math.pow(ref2, array1[++i1] = Math.pow(ref1, 2)); +array1[++i1] = Math.pow(array1[++i1], array1[++i1] = Math.pow(array1[++i1], 2)); var array2 = [ 1, 2, 3 ]; var i2 = 0; -var ref3 = array2[++i2]; -array2[++i2] = Math.pow(ref3, Math.pow(array2[++i2], 2)); +array2[++i2] = Math.pow(array2[++i2], Math.pow(array2[++i2], 2)); var array3 = [ 2, 2, 3 ]; var j0 = 0, j1 = 1; -var ref4 = array3[j0++], ref5 = array3[j1++], ref6 = array3[j0++]; -array3[j0++] = Math.pow(ref6, array3[j1++] = Math.pow(ref5, array3[j0++] = Math.pow(ref4, 1))); +array3[j0++] = Math.pow(array3[j0++], array3[j1++] = Math.pow(array3[j1++], array3[j0++] = Math.pow(array3[j0++], 1))); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.2.minified.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.2.minified.js index 8448c0e28c1d..23d9f65de20a 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.2.minified.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.2.minified.js @@ -3,23 +3,23 @@ var array0 = [ 1, 2, 3 -], i0 = 0, ref = array0[++i0]; -array0[++i0] = Math.pow(ref, 2); +], i0 = 0; +array0[++i0] = Math.pow(array0[++i0], 2); var array1 = [ 1, 2, 3 -], i1 = 0, ref1 = array1[++i1], ref2 = array1[++i1]; -array1[++i1] = Math.pow(ref2, array1[++i1] = Math.pow(ref1, 2)); +], i1 = 0; +array1[++i1] = Math.pow(array1[++i1], array1[++i1] = Math.pow(array1[++i1], 2)); var array2 = [ 1, 2, 3 -], i2 = 0, ref3 = array2[++i2]; -array2[++i2] = Math.pow(ref3, Math.pow(array2[++i2], 2)); +], i2 = 0; +array2[++i2] = Math.pow(array2[++i2], Math.pow(array2[++i2], 2)); var array3 = [ 2, 2, 3 -], j0 = 0, j1 = 1, ref4 = array3[j0++], ref5 = array3[j1++], ref6 = array3[j0++]; -array3[j0++] = Math.pow(ref6, array3[j1++] = Math.pow(ref5, array3[j0++] = Math.pow(ref4, 1))); +], j0 = 0, j1 = 1; +array3[j0++] = Math.pow(array3[j0++], array3[j1++] = Math.pow(array3[j1++], array3[j0++] = Math.pow(array3[j0++], 1))); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.1.normal.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.1.normal.js index 2d0b001efbe1..5c0f20a8f297 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.1.normal.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.1.normal.js @@ -6,15 +6,9 @@ function foo() { 0: 2 }; } -var ref = foo()[0]; -foo()[0] = Math.pow(ref, foo()[0]); -var ref1 = foo()[0]; -var result_foo1 = foo()[0] = Math.pow(ref1, foo()[0]); -var ref2 = foo()[0], ref3 = foo()[0]; -foo()[0] = Math.pow(ref3, foo()[0] = Math.pow(ref2, 2)); -var ref4 = foo()[0], ref5 = foo()[0]; -var result_foo2 = foo()[0] = Math.pow(ref5, foo()[0] = Math.pow(ref4, 2)); -var ref6 = foo()[0]; -foo()[0] = Math.pow(ref6, Math.pow(foo()[0], 2)); -var ref7 = foo()[0]; -var result_foo3 = foo()[0] = Math.pow(ref7, Math.pow(foo()[0], 2)); +foo()[0] = Math.pow(foo()[0], foo()[0]); +var result_foo1 = foo()[0] = Math.pow(foo()[0], foo()[0]); +foo()[0] = Math.pow(foo()[0], foo()[0] = Math.pow(foo()[0], 2)); +var result_foo2 = foo()[0] = Math.pow(foo()[0], foo()[0] = Math.pow(foo()[0], 2)); +foo()[0] = Math.pow(foo()[0], Math.pow(foo()[0], 2)); +var result_foo3 = foo()[0] = Math.pow(foo()[0], Math.pow(foo()[0], 2)); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.2.minified.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.2.minified.js index b467b3f68e6c..be92ab3c2159 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.2.minified.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.2.minified.js @@ -5,15 +5,4 @@ function foo() { 0: 2 }; } -var ref = foo()[0]; -foo()[0] = Math.pow(ref, foo()[0]); -var ref1 = foo()[0]; -foo()[0] = Math.pow(ref1, foo()[0]); -var ref2 = foo()[0], ref3 = foo()[0]; -foo()[0] = Math.pow(ref3, foo()[0] = Math.pow(ref2, 2)); -var ref4 = foo()[0], ref5 = foo()[0]; -foo()[0] = Math.pow(ref5, foo()[0] = Math.pow(ref4, 2)); -var ref6 = foo()[0]; -foo()[0] = Math.pow(ref6, Math.pow(foo()[0], 2)); -var ref7 = foo()[0]; -foo()[0] = Math.pow(ref7, Math.pow(foo()[0], 2)); +foo()[0] = Math.pow(foo()[0], foo()[0]), foo()[0] = Math.pow(foo()[0], foo()[0]), foo()[0] = Math.pow(foo()[0], foo()[0] = Math.pow(foo()[0], 2)), foo()[0] = Math.pow(foo()[0], foo()[0] = Math.pow(foo()[0], 2)), foo()[0] = Math.pow(foo()[0], Math.pow(foo()[0], 2)), foo()[0] = Math.pow(foo()[0], Math.pow(foo()[0], 2)); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.1.normal.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.1.normal.js index ec315697cc75..f499fb34ee37 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.1.normal.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.1.normal.js @@ -8,9 +8,6 @@ var object = { this._0 = x; } }; -var ref = object[0]; -object[0] = Math.pow(ref, object[0]); -var ref1 = object[0], ref2 = object[0]; -object[0] = Math.pow(ref2, object[0] = Math.pow(ref1, 2)); -var ref3 = object[0]; -object[0] = Math.pow(ref3, Math.pow(object[0], 2)); +object[0] = Math.pow(object[0], object[0]); +object[0] = Math.pow(object[0], object[0] = Math.pow(object[0], 2)); +object[0] = Math.pow(object[0], Math.pow(object[0], 2)); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.2.minified.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.2.minified.js index a4b3084767f2..6f946fd62f0d 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.2.minified.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.2.minified.js @@ -7,9 +7,5 @@ var object = { set 0 (x){ this._0 = x; } -}, ref = object[0]; -object[0] = Math.pow(ref, object[0]); -var ref1 = object[0], ref2 = object[0]; -object[0] = Math.pow(ref2, object[0] = Math.pow(ref1, 2)); -var ref3 = object[0]; -object[0] = Math.pow(ref3, Math.pow(object[0], 2)); +}; +object[0] = Math.pow(object[0], object[0]), object[0] = Math.pow(object[0], object[0] = Math.pow(object[0], 2)), object[0] = Math.pow(object[0], Math.pow(object[0], 2)); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.1.normal.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.1.normal.js index c27090edffd1..955ffce8ce2c 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.1.normal.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.1.normal.js @@ -12,9 +12,6 @@ var array1 = [ 4, 5 ]; -var ref = array1[incrementIdx(array1.length)]; -array1[incrementIdx(array1.length)] = Math.pow(ref, 3); -var ref1 = array1[incrementIdx(array1.length)], ref2 = array1[incrementIdx(array1.length)]; -array1[incrementIdx(array1.length)] = Math.pow(ref2, array1[incrementIdx(array1.length)] = Math.pow(ref1, 2)); -var ref3 = array1[incrementIdx(array1.length)]; -array1[incrementIdx(array1.length)] = Math.pow(ref3, Math.pow(array1[incrementIdx(array1.length)], 2)); +array1[incrementIdx(array1.length)] = Math.pow(array1[incrementIdx(array1.length)], 3); +array1[incrementIdx(array1.length)] = Math.pow(array1[incrementIdx(array1.length)], array1[incrementIdx(array1.length)] = Math.pow(array1[incrementIdx(array1.length)], 2)); +array1[incrementIdx(array1.length)] = Math.pow(array1[incrementIdx(array1.length)], Math.pow(array1[incrementIdx(array1.length)], 2)); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.2.minified.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.2.minified.js index 2214874da701..44ac184e8d0b 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.2.minified.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.2.minified.js @@ -9,9 +9,5 @@ var array1 = [ 3, 4, 5 -], ref = array1[incrementIdx(array1.length)]; -array1[incrementIdx(array1.length)] = Math.pow(ref, 3); -var ref1 = array1[incrementIdx(array1.length)], ref2 = array1[incrementIdx(array1.length)]; -array1[incrementIdx(array1.length)] = Math.pow(ref2, array1[incrementIdx(array1.length)] = Math.pow(ref1, 2)); -var ref3 = array1[incrementIdx(array1.length)]; -array1[incrementIdx(array1.length)] = Math.pow(ref3, Math.pow(array1[incrementIdx(array1.length)], 2)); +]; +array1[incrementIdx(array1.length)] = Math.pow(array1[incrementIdx(array1.length)], 3), array1[incrementIdx(array1.length)] = Math.pow(array1[incrementIdx(array1.length)], array1[incrementIdx(array1.length)] = Math.pow(array1[incrementIdx(array1.length)], 2)), array1[incrementIdx(array1.length)] = Math.pow(array1[incrementIdx(array1.length)], Math.pow(array1[incrementIdx(array1.length)], 2)); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.1.normal.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.1.normal.js index c8cf35793966..3522724690df 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.1.normal.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.1.normal.js @@ -6,15 +6,9 @@ function foo() { prop: 2 }; } -var ref = foo().prop; -foo().prop = Math.pow(ref, 2); -var ref1 = foo().prop; -var result0 = foo().prop = Math.pow(ref1, 2); -var ref2 = foo().prop, ref3 = foo().prop; -foo().prop = Math.pow(ref3, foo().prop = Math.pow(ref2, 2)); -var ref4 = foo().prop, ref5 = foo().prop; -var result1 = foo().prop = Math.pow(ref5, foo().prop = Math.pow(ref4, 2)); -var ref6 = foo().prop; -foo().prop = Math.pow(ref6, Math.pow(foo().prop, 2)); -var ref7 = foo().prop; -var result2 = foo().prop = Math.pow(ref7, Math.pow(foo().prop, 2)); +foo().prop = Math.pow(foo().prop, 2); +var result0 = foo().prop = Math.pow(foo().prop, 2); +foo().prop = Math.pow(foo().prop, foo().prop = Math.pow(foo().prop, 2)); +var result1 = foo().prop = Math.pow(foo().prop, foo().prop = Math.pow(foo().prop, 2)); +foo().prop = Math.pow(foo().prop, Math.pow(foo().prop, 2)); +var result2 = foo().prop = Math.pow(foo().prop, Math.pow(foo().prop, 2)); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.2.minified.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.2.minified.js index 723a6ac2c839..796551ba04b2 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.2.minified.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.2.minified.js @@ -5,15 +5,4 @@ function foo() { prop: 2 }; } -var ref = foo().prop; -foo().prop = Math.pow(ref, 2); -var ref1 = foo().prop; -foo().prop = Math.pow(ref1, 2); -var ref2 = foo().prop, ref3 = foo().prop; -foo().prop = Math.pow(ref3, foo().prop = Math.pow(ref2, 2)); -var ref4 = foo().prop, ref5 = foo().prop; -foo().prop = Math.pow(ref5, foo().prop = Math.pow(ref4, 2)); -var ref6 = foo().prop; -foo().prop = Math.pow(ref6, Math.pow(foo().prop, 2)); -var ref7 = foo().prop; -foo().prop = Math.pow(ref7, Math.pow(foo().prop, 2)); +foo().prop = Math.pow(foo().prop, 2), foo().prop = Math.pow(foo().prop, 2), foo().prop = Math.pow(foo().prop, foo().prop = Math.pow(foo().prop, 2)), foo().prop = Math.pow(foo().prop, foo().prop = Math.pow(foo().prop, 2)), foo().prop = Math.pow(foo().prop, Math.pow(foo().prop, 2)), foo().prop = Math.pow(foo().prop, Math.pow(foo().prop, 2)); diff --git a/crates/swc/tests/tsc-references/parseRegularExpressionMixedWithComments.1.normal.js b/crates/swc/tests/tsc-references/parseRegularExpressionMixedWithComments.1.normal.js index 202d8c8fa43f..32ebf9630007 100644 --- a/crates/swc/tests/tsc-references/parseRegularExpressionMixedWithComments.1.normal.js +++ b/crates/swc/tests/tsc-references/parseRegularExpressionMixedWithComments.1.normal.js @@ -2,5 +2,5 @@ var regex1 = / asdf /; var regex2 = /**/ / asdf /; var regex3 = /**/ 1; -var regex4 = /**/ Math.pow(/ /, /asdf /); -var regex5 = /**/ Math.pow(/ asdf/, / /); +var regex4 = Math.pow(/**/ / /, /asdf /); +var regex5 = Math.pow(/**/ / asdf/, / /); From 0ff6c155369243180fa4f286937cc93fa58d5e0e Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Thu, 20 Nov 2025 08:22:28 -0500 Subject: [PATCH 20/23] temp var --- .../src/es2016/exponentiation_operator.rs | 112 +++++++++++++++--- crates/swc_ecma_transformer/src/utils/mod.rs | 32 +++++ 2 files changed, 130 insertions(+), 14 deletions(-) diff --git a/crates/swc_ecma_transformer/src/es2016/exponentiation_operator.rs b/crates/swc_ecma_transformer/src/es2016/exponentiation_operator.rs index d5b7d1001726..9b2135dcb7f4 100644 --- a/crates/swc_ecma_transformer/src/es2016/exponentiation_operator.rs +++ b/crates/swc_ecma_transformer/src/es2016/exponentiation_operator.rs @@ -35,7 +35,7 @@ use swc_common::{util::take::Take, SyntaxContext, DUMMY_SP}; use swc_ecma_ast::*; use swc_ecma_hooks::VisitMutHook; -use crate::TraverseCtx; +use crate::{utils, TraverseCtx}; pub fn hook() -> impl VisitMutHook { ExponentiationOperatorPass::default() @@ -118,7 +118,10 @@ impl ExponentiationOperatorPass { /// Transform member expression exponentiation assignment implementation /// - /// `obj.prop **= 2` or `obj[prop] **= 2` + /// Uses temporary variables to avoid side effects: + /// - `obj.prop **= 2` -> `(_obj = obj, _obj.prop = Math.pow(_obj.prop, 2))` + /// - `obj[prop] **= 2` -> `(_obj = obj, _prop = prop, _obj[_prop] = + /// Math.pow(_obj[_prop], 2))` fn transform_member_exp_assign_impl( &self, expr: &mut Expr, @@ -126,66 +129,147 @@ impl ExponentiationOperatorPass { prop: MemberProp, right: Box, ) { - // For simplicity, handle the basic case without temp variables - // A more complete implementation would add temp variables to avoid side effects + // Check if we need a temp variable for the object + let needs_obj_temp = !matches!(*obj, Expr::Ident(_)); + + let mut sequence_exprs = Vec::new(); + + // Create temp variable for object if needed + let (final_obj, obj_for_pow) = if needs_obj_temp { + let temp_name = utils::generate_temp_var_name(&obj); + let temp_ident = utils::create_private_ident(&temp_name); + + // Add assignment to sequence: _obj = obj + sequence_exprs.push(Expr::Assign(AssignExpr { + span: DUMMY_SP, + op: AssignOp::Assign, + left: AssignTarget::Simple(SimpleAssignTarget::Ident(BindingIdent { + id: temp_ident.clone(), + type_ann: None, + })), + right: obj, + })); + + let obj_expr = Box::new(Expr::Ident(temp_ident.clone())); + (obj_expr.clone(), obj_expr) + } else { + (obj.clone(), obj) + }; + match prop { - // obj.prop **= right -> obj.prop = Math.pow(obj.prop, right) + // obj.prop **= right -> (_obj = obj, _obj.prop = Math.pow(_obj.prop, right)) MemberProp::Ident(prop_name) => { // Create Math.pow(obj.prop, right) let pow_left = Box::new(Expr::Member(MemberExpr { span: DUMMY_SP, - obj: obj.clone(), + obj: obj_for_pow, prop: MemberProp::Ident(prop_name.clone()), })); let pow_call = create_math_pow(pow_left, right); // obj.prop = Math.pow(obj.prop, right) - *expr = Expr::Assign(AssignExpr { + let assignment = Expr::Assign(AssignExpr { span: DUMMY_SP, op: AssignOp::Assign, left: AssignTarget::Simple(SimpleAssignTarget::Member(MemberExpr { span: DUMMY_SP, - obj, + obj: final_obj, prop: MemberProp::Ident(prop_name), })), right: Box::new(pow_call), }); + + if needs_obj_temp { + sequence_exprs.push(assignment); + *expr = Expr::Seq(SeqExpr { + span: DUMMY_SP, + exprs: sequence_exprs.into_iter().map(Box::new).collect(), + }); + } else { + *expr = assignment; + } } - // obj[computed] **= right -> obj[computed] = Math.pow(obj[computed], right) + // obj[computed] **= right -> (_obj = obj, _prop = prop, _obj[_prop] = + // Math.pow(_obj[_prop], right)) MemberProp::Computed(computed) => { let computed_prop = computed.expr; + // Check if we need a temp variable for the computed property + let needs_prop_temp = !is_literal_expr(&computed_prop); + + let (final_prop, prop_for_pow) = if needs_prop_temp { + let temp_name = match &*computed_prop { + Expr::Ident(ident) => format!("_{}", ident.sym), + _ => "_prop".to_string(), + }; + let temp_ident = utils::create_private_ident(&temp_name); + + // Add assignment to sequence: _prop = prop + sequence_exprs.push(Expr::Assign(AssignExpr { + span: DUMMY_SP, + op: AssignOp::Assign, + left: AssignTarget::Simple(SimpleAssignTarget::Ident(BindingIdent { + id: temp_ident.clone(), + type_ann: None, + })), + right: computed_prop, + })); + + let prop_expr = Box::new(Expr::Ident(temp_ident.clone())); + (prop_expr.clone(), prop_expr) + } else { + (computed_prop.clone(), computed_prop) + }; + // Create Math.pow(obj[computed], right) let pow_left = Box::new(Expr::Member(MemberExpr { span: DUMMY_SP, - obj: obj.clone(), + obj: obj_for_pow, prop: MemberProp::Computed(ComputedPropName { span: DUMMY_SP, - expr: computed_prop.clone(), + expr: prop_for_pow, }), })); let pow_call = create_math_pow(pow_left, right); // obj[computed] = Math.pow(obj[computed], right) - *expr = Expr::Assign(AssignExpr { + let assignment = Expr::Assign(AssignExpr { span: DUMMY_SP, op: AssignOp::Assign, left: AssignTarget::Simple(SimpleAssignTarget::Member(MemberExpr { span: DUMMY_SP, - obj, + obj: final_obj, prop: MemberProp::Computed(ComputedPropName { span: DUMMY_SP, - expr: computed_prop, + expr: final_prop, }), })), right: Box::new(pow_call), }); + + if needs_obj_temp || needs_prop_temp { + sequence_exprs.push(assignment); + *expr = Expr::Seq(SeqExpr { + span: DUMMY_SP, + exprs: sequence_exprs.into_iter().map(Box::new).collect(), + }); + } else { + *expr = assignment; + } } _ => {} } } } +/// Check if an expression is a literal (and safe to evaluate multiple times) +fn is_literal_expr(expr: &Expr) -> bool { + matches!( + expr, + Expr::Lit(_) | Expr::Ident(_) | Expr::This(_) | Expr::PrivateName(_) + ) +} + /// Create `Math.pow(left, right)` call expression fn create_math_pow(left: Box, right: Box) -> Expr { Expr::Call(CallExpr { diff --git a/crates/swc_ecma_transformer/src/utils/mod.rs b/crates/swc_ecma_transformer/src/utils/mod.rs index 12ae38bd114d..decd32e75f6f 100644 --- a/crates/swc_ecma_transformer/src/utils/mod.rs +++ b/crates/swc_ecma_transformer/src/utils/mod.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use swc_atoms::Atom; +use swc_common::{Mark, SyntaxContext, DUMMY_SP}; use swc_ecma_ast::*; pub(crate) fn normalize_module_export_name(module_export_name: &ModuleExportName) -> Cow { @@ -18,3 +19,34 @@ pub(crate) fn normalize_module_export_name(module_export_name: &ModuleExportName _ => panic!("unable to access unknown nodes"), } } + +/// Create a private identifier with the given name. +/// +/// The identifier will have a unique syntax context to avoid conflicts. +pub(crate) fn create_private_ident(name: &str) -> Ident { + let mark = Mark::new(); + let ctxt = SyntaxContext::empty().apply_mark(mark); + Ident::new(name.into(), DUMMY_SP, ctxt) +} + +/// Generate a temporary variable name based on an expression. +/// +/// For example: +/// - `obj.prop` -> `_obj_prop` +/// - `obj[expr]` -> `_obj` +pub(crate) fn generate_temp_var_name(expr: &Expr) -> String { + match expr { + Expr::Ident(ident) => format!("_{}", ident.sym), + Expr::Member(member) => { + let obj_name = match &*member.obj { + Expr::Ident(ident) => ident.sym.to_string(), + _ => "ref".to_string(), + }; + match &member.prop { + MemberProp::Ident(prop) => format!("_{}_{}", obj_name, prop.sym), + _ => format!("_{}", obj_name), + } + } + _ => "_ref".to_string(), + } +} From 1ecf525c06faf8f2184ea86acacd647cedc393a0 Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Thu, 20 Nov 2025 08:22:34 -0500 Subject: [PATCH 21/23] Update test refs --- ...entiationAssignmentWithIndexingOnLHS1.1.normal.js | 8 ++++---- ...tiationAssignmentWithIndexingOnLHS1.2.minified.js | 8 ++++---- ...entiationAssignmentWithIndexingOnLHS2.1.normal.js | 12 ++++++------ ...tiationAssignmentWithIndexingOnLHS2.2.minified.js | 2 +- ...entiationAssignmentWithIndexingOnLHS4.1.normal.js | 6 +++--- ...tiationAssignmentWithIndexingOnLHS4.2.minified.js | 2 +- ...AssignmentWithPropertyAccessingOnLHS1.1.normal.js | 12 ++++++------ ...signmentWithPropertyAccessingOnLHS1.2.minified.js | 2 +- 8 files changed, 26 insertions(+), 26 deletions(-) diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.1.normal.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.1.normal.js index 5e00f4599692..c4a31c730287 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.1.normal.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.1.normal.js @@ -5,25 +5,25 @@ var array0 = [ 3 ]; var i0 = 0; -array0[++i0] = Math.pow(array0[++i0], 2); +_prop = ++i0, array0[_prop] = Math.pow(array0[_prop], 2); var array1 = [ 1, 2, 3 ]; var i1 = 0; -array1[++i1] = Math.pow(array1[++i1], array1[++i1] = Math.pow(array1[++i1], 2)); +_prop = ++i1, array1[_prop] = Math.pow(array1[_prop], (_prop = ++i1, array1[_prop] = Math.pow(array1[_prop], 2))); var array2 = [ 1, 2, 3 ]; var i2 = 0; -array2[++i2] = Math.pow(array2[++i2], Math.pow(array2[++i2], 2)); +_prop = ++i2, array2[_prop] = Math.pow(array2[_prop], Math.pow(array2[++i2], 2)); var array3 = [ 2, 2, 3 ]; var j0 = 0, j1 = 1; -array3[j0++] = Math.pow(array3[j0++], array3[j1++] = Math.pow(array3[j1++], array3[j0++] = Math.pow(array3[j0++], 1))); +_prop = j0++, array3[_prop] = Math.pow(array3[_prop], (_prop = j1++, array3[_prop] = Math.pow(array3[_prop], (_prop = j0++, array3[_prop] = Math.pow(array3[_prop], 1))))); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.2.minified.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.2.minified.js index 23d9f65de20a..059d6631331f 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.2.minified.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.2.minified.js @@ -4,22 +4,22 @@ var array0 = [ 2, 3 ], i0 = 0; -array0[++i0] = Math.pow(array0[++i0], 2); +array0[_prop = ++i0] = Math.pow(array0[_prop], 2); var array1 = [ 1, 2, 3 ], i1 = 0; -array1[++i1] = Math.pow(array1[++i1], array1[++i1] = Math.pow(array1[++i1], 2)); +array1[_prop = ++i1] = Math.pow(array1[_prop], array1[_prop = ++i1] = Math.pow(array1[_prop], 2)); var array2 = [ 1, 2, 3 ], i2 = 0; -array2[++i2] = Math.pow(array2[++i2], Math.pow(array2[++i2], 2)); +array2[_prop = ++i2] = Math.pow(array2[_prop], Math.pow(array2[++i2], 2)); var array3 = [ 2, 2, 3 ], j0 = 0, j1 = 1; -array3[j0++] = Math.pow(array3[j0++], array3[j1++] = Math.pow(array3[j1++], array3[j0++] = Math.pow(array3[j0++], 1))); +array3[_prop = j0++] = Math.pow(array3[_prop], array3[_prop = j1++] = Math.pow(array3[_prop], array3[_prop = j0++] = Math.pow(array3[_prop], 1))); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.1.normal.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.1.normal.js index 5c0f20a8f297..08298c3d9c21 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.1.normal.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.1.normal.js @@ -6,9 +6,9 @@ function foo() { 0: 2 }; } -foo()[0] = Math.pow(foo()[0], foo()[0]); -var result_foo1 = foo()[0] = Math.pow(foo()[0], foo()[0]); -foo()[0] = Math.pow(foo()[0], foo()[0] = Math.pow(foo()[0], 2)); -var result_foo2 = foo()[0] = Math.pow(foo()[0], foo()[0] = Math.pow(foo()[0], 2)); -foo()[0] = Math.pow(foo()[0], Math.pow(foo()[0], 2)); -var result_foo3 = foo()[0] = Math.pow(foo()[0], Math.pow(foo()[0], 2)); +_ref = foo(), _ref[0] = Math.pow(_ref[0], foo()[0]); +var result_foo1 = (_ref = foo(), _ref[0] = Math.pow(_ref[0], foo()[0])); +_ref = foo(), _ref[0] = Math.pow(_ref[0], (_ref = foo(), _ref[0] = Math.pow(_ref[0], 2))); +var result_foo2 = (_ref = foo(), _ref[0] = Math.pow(_ref[0], (_ref = foo(), _ref[0] = Math.pow(_ref[0], 2)))); +_ref = foo(), _ref[0] = Math.pow(_ref[0], Math.pow(foo()[0], 2)); +var result_foo3 = (_ref = foo(), _ref[0] = Math.pow(_ref[0], Math.pow(foo()[0], 2))); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.2.minified.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.2.minified.js index be92ab3c2159..7f2b919dfc92 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.2.minified.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.2.minified.js @@ -5,4 +5,4 @@ function foo() { 0: 2 }; } -foo()[0] = Math.pow(foo()[0], foo()[0]), foo()[0] = Math.pow(foo()[0], foo()[0]), foo()[0] = Math.pow(foo()[0], foo()[0] = Math.pow(foo()[0], 2)), foo()[0] = Math.pow(foo()[0], foo()[0] = Math.pow(foo()[0], 2)), foo()[0] = Math.pow(foo()[0], Math.pow(foo()[0], 2)), foo()[0] = Math.pow(foo()[0], Math.pow(foo()[0], 2)); +(_ref = foo())[0] = Math.pow(_ref[0], foo()[0]), (_ref = foo())[0] = Math.pow(_ref[0], foo()[0]), (_ref = foo())[0] = Math.pow(_ref[0], (_ref = foo())[0] = Math.pow(_ref[0], 2)), (_ref = foo())[0] = Math.pow(_ref[0], (_ref = foo())[0] = Math.pow(_ref[0], 2)), (_ref = foo())[0] = Math.pow(_ref[0], Math.pow(foo()[0], 2)), (_ref = foo())[0] = Math.pow(_ref[0], Math.pow(foo()[0], 2)); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.1.normal.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.1.normal.js index 955ffce8ce2c..a5c4f462362c 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.1.normal.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.1.normal.js @@ -12,6 +12,6 @@ var array1 = [ 4, 5 ]; -array1[incrementIdx(array1.length)] = Math.pow(array1[incrementIdx(array1.length)], 3); -array1[incrementIdx(array1.length)] = Math.pow(array1[incrementIdx(array1.length)], array1[incrementIdx(array1.length)] = Math.pow(array1[incrementIdx(array1.length)], 2)); -array1[incrementIdx(array1.length)] = Math.pow(array1[incrementIdx(array1.length)], Math.pow(array1[incrementIdx(array1.length)], 2)); +_prop = incrementIdx(array1.length), array1[_prop] = Math.pow(array1[_prop], 3); +_prop = incrementIdx(array1.length), array1[_prop] = Math.pow(array1[_prop], (_prop = incrementIdx(array1.length), array1[_prop] = Math.pow(array1[_prop], 2))); +_prop = incrementIdx(array1.length), array1[_prop] = Math.pow(array1[_prop], Math.pow(array1[incrementIdx(array1.length)], 2)); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.2.minified.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.2.minified.js index 44ac184e8d0b..13eb5e46f412 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.2.minified.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.2.minified.js @@ -10,4 +10,4 @@ var array1 = [ 4, 5 ]; -array1[incrementIdx(array1.length)] = Math.pow(array1[incrementIdx(array1.length)], 3), array1[incrementIdx(array1.length)] = Math.pow(array1[incrementIdx(array1.length)], array1[incrementIdx(array1.length)] = Math.pow(array1[incrementIdx(array1.length)], 2)), array1[incrementIdx(array1.length)] = Math.pow(array1[incrementIdx(array1.length)], Math.pow(array1[incrementIdx(array1.length)], 2)); +_prop = incrementIdx(array1.length), array1[_prop] = Math.pow(array1[_prop], 3), _prop = incrementIdx(array1.length), array1[_prop] = Math.pow(array1[_prop], (_prop = incrementIdx(array1.length), array1[_prop] = Math.pow(array1[_prop], 2))), _prop = incrementIdx(array1.length), array1[_prop] = Math.pow(array1[_prop], Math.pow(array1[incrementIdx(array1.length)], 2)); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.1.normal.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.1.normal.js index 3522724690df..851185b6578e 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.1.normal.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.1.normal.js @@ -6,9 +6,9 @@ function foo() { prop: 2 }; } -foo().prop = Math.pow(foo().prop, 2); -var result0 = foo().prop = Math.pow(foo().prop, 2); -foo().prop = Math.pow(foo().prop, foo().prop = Math.pow(foo().prop, 2)); -var result1 = foo().prop = Math.pow(foo().prop, foo().prop = Math.pow(foo().prop, 2)); -foo().prop = Math.pow(foo().prop, Math.pow(foo().prop, 2)); -var result2 = foo().prop = Math.pow(foo().prop, Math.pow(foo().prop, 2)); +_ref = foo(), _ref.prop = Math.pow(_ref.prop, 2); +var result0 = (_ref = foo(), _ref.prop = Math.pow(_ref.prop, 2)); +_ref = foo(), _ref.prop = Math.pow(_ref.prop, (_ref = foo(), _ref.prop = Math.pow(_ref.prop, 2))); +var result1 = (_ref = foo(), _ref.prop = Math.pow(_ref.prop, (_ref = foo(), _ref.prop = Math.pow(_ref.prop, 2)))); +_ref = foo(), _ref.prop = Math.pow(_ref.prop, Math.pow(foo().prop, 2)); +var result2 = (_ref = foo(), _ref.prop = Math.pow(_ref.prop, Math.pow(foo().prop, 2))); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.2.minified.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.2.minified.js index 796551ba04b2..8b3f5f7648fd 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.2.minified.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.2.minified.js @@ -5,4 +5,4 @@ function foo() { prop: 2 }; } -foo().prop = Math.pow(foo().prop, 2), foo().prop = Math.pow(foo().prop, 2), foo().prop = Math.pow(foo().prop, foo().prop = Math.pow(foo().prop, 2)), foo().prop = Math.pow(foo().prop, foo().prop = Math.pow(foo().prop, 2)), foo().prop = Math.pow(foo().prop, Math.pow(foo().prop, 2)), foo().prop = Math.pow(foo().prop, Math.pow(foo().prop, 2)); +(_ref = foo()).prop = Math.pow(_ref.prop, 2), (_ref = foo()).prop = Math.pow(_ref.prop, 2), (_ref = foo()).prop = Math.pow(_ref.prop, (_ref = foo()).prop = Math.pow(_ref.prop, 2)), (_ref = foo()).prop = Math.pow(_ref.prop, (_ref = foo()).prop = Math.pow(_ref.prop, 2)), (_ref = foo()).prop = Math.pow(_ref.prop, Math.pow(foo().prop, 2)), (_ref = foo()).prop = Math.pow(_ref.prop, Math.pow(foo().prop, 2)); From 3841ccf59cb4772a5baa6cfb21a3a5f8108cf429 Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Thu, 20 Nov 2025 09:04:26 -0500 Subject: [PATCH 22/23] lint --- Cargo.lock | 3 --- crates/swc_ecma_compat_es2016/Cargo.toml | 3 --- crates/swc_ecma_transformer/src/utils/mod.rs | 2 +- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d16c835f7fb2..f37b3fb5abb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5915,15 +5915,12 @@ dependencies = [ name = "swc_ecma_compat_es2016" version = "30.0.0" dependencies = [ - "swc_common", "swc_ecma_ast", "swc_ecma_parser", "swc_ecma_transformer", "swc_ecma_transforms_base", - "swc_ecma_transforms_macros", "swc_ecma_transforms_testing", "swc_ecma_utils", - "swc_ecma_visit", "tracing", ] diff --git a/crates/swc_ecma_compat_es2016/Cargo.toml b/crates/swc_ecma_compat_es2016/Cargo.toml index cc83c51222d5..4a0deede07c3 100644 --- a/crates/swc_ecma_compat_es2016/Cargo.toml +++ b/crates/swc_ecma_compat_es2016/Cargo.toml @@ -23,8 +23,5 @@ swc_ecma_utils = { version = "24.0.0", path = "../swc_ecma_utils" } tracing = { workspace = true } [dev-dependencies] -swc_common = { version = "17.0.1", path = "../swc_common" } swc_ecma_parser = { version = "27.0.6", path = "../swc_ecma_parser" } -swc_ecma_transforms_macros = { version = "1.0.1", path = "../swc_ecma_transforms_macros" } swc_ecma_transforms_testing = { version = "33.0.0", path = "../swc_ecma_transforms_testing" } -swc_ecma_visit = { version = "18.0.1", path = "../swc_ecma_visit" } diff --git a/crates/swc_ecma_transformer/src/utils/mod.rs b/crates/swc_ecma_transformer/src/utils/mod.rs index decd32e75f6f..2cd22f63a6fb 100644 --- a/crates/swc_ecma_transformer/src/utils/mod.rs +++ b/crates/swc_ecma_transformer/src/utils/mod.rs @@ -44,7 +44,7 @@ pub(crate) fn generate_temp_var_name(expr: &Expr) -> String { }; match &member.prop { MemberProp::Ident(prop) => format!("_{}_{}", obj_name, prop.sym), - _ => format!("_{}", obj_name), + _ => format!("_{obj_name}"), } } _ => "_ref".to_string(), From f1fc503191dc8442f494eb8d897f3143572bb522 Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Fri, 21 Nov 2025 11:22:02 -0500 Subject: [PATCH 23/23] restore tests --- ...tiationAssignmentLHSIsReference.1.normal.js | 12 ++++++++---- ...ationAssignmentLHSIsReference.2.minified.js | 10 ++++++++-- ...ionAssignmentWithIndexingOnLHS1.1.normal.js | 12 ++++++++---- ...nAssignmentWithIndexingOnLHS1.2.minified.js | 16 ++++++++-------- ...ionAssignmentWithIndexingOnLHS2.1.normal.js | 18 ++++++++++++------ ...nAssignmentWithIndexingOnLHS2.2.minified.js | 13 ++++++++++++- ...ionAssignmentWithIndexingOnLHS3.1.normal.js | 9 ++++++--- ...nAssignmentWithIndexingOnLHS3.2.minified.js | 8 ++++++-- ...ionAssignmentWithIndexingOnLHS4.1.normal.js | 9 ++++++--- ...nAssignmentWithIndexingOnLHS4.2.minified.js | 8 ++++++-- ...mentWithPropertyAccessingOnLHS1.1.normal.js | 18 ++++++++++++------ ...ntWithPropertyAccessingOnLHS1.2.minified.js | 13 ++++++++++++- ...ularExpressionMixedWithComments.1.normal.js | 4 ++-- ...rserArrowFunctionExpression10.2.minified.js | 4 ++-- ...rserArrowFunctionExpression12.2.minified.js | 4 ++-- ...rserArrowFunctionExpression13.2.minified.js | 4 ++-- ...arserArrowFunctionExpression8.2.minified.js | 8 ++------ .../assign_to_object_property.js | 3 ++- 18 files changed, 116 insertions(+), 57 deletions(-) diff --git a/crates/swc/tests/tsc-references/compoundExponentiationAssignmentLHSIsReference.1.normal.js b/crates/swc/tests/tsc-references/compoundExponentiationAssignmentLHSIsReference.1.normal.js index db004433160f..b5635beea28d 100644 --- a/crates/swc/tests/tsc-references/compoundExponentiationAssignmentLHSIsReference.1.normal.js +++ b/crates/swc/tests/tsc-references/compoundExponentiationAssignmentLHSIsReference.1.normal.js @@ -8,12 +8,16 @@ function fn1(x2) { } // property accesses var x3; -x3.a = Math.pow(x3.a, value); -x3['a'] = Math.pow(x3['a'], value); +var ref = x3.a; +x3.a = Math.pow(ref, value); +var ref1 = x3['a']; +x3['a'] = Math.pow(ref1, value); // parentheses, the contained expression is reference x1 = Math.pow(x1, value); function fn2(x4) { x4 = Math.pow(x4, value); } -x3.a = Math.pow(x3.a, value); -x3['a'] = Math.pow(x3['a'], value); +var ref2 = x3.a; +x3.a = Math.pow(ref2, value); +var ref3 = x3['a']; +x3['a'] = Math.pow(ref3, value); diff --git a/crates/swc/tests/tsc-references/compoundExponentiationAssignmentLHSIsReference.2.minified.js b/crates/swc/tests/tsc-references/compoundExponentiationAssignmentLHSIsReference.2.minified.js index c6ca68f8229d..f3a19d3dc03f 100644 --- a/crates/swc/tests/tsc-references/compoundExponentiationAssignmentLHSIsReference.2.minified.js +++ b/crates/swc/tests/tsc-references/compoundExponentiationAssignmentLHSIsReference.2.minified.js @@ -1,3 +1,9 @@ //// [compoundExponentiationAssignmentLHSIsReference.ts] -var value, x1, x3; -x1 = Math.pow(x1, value), x3.a = Math.pow(x3.a, value), x3.a = Math.pow(x3.a, value), x1 = Math.pow(x1, value), x3.a = Math.pow(x3.a, value), x3.a = Math.pow(x3.a, value); +var value, x3, x1 = Math.pow(x1, value), ref = x3.a; +x3.a = Math.pow(ref, value); +var ref1 = x3.a; +x3.a = Math.pow(ref1, value), x1 = Math.pow(x1, value); +var ref2 = x3.a; +x3.a = Math.pow(ref2, value); +var ref3 = x3.a; +x3.a = Math.pow(ref3, value); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.1.normal.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.1.normal.js index c4a31c730287..e610d77e6c21 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.1.normal.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.1.normal.js @@ -5,25 +5,29 @@ var array0 = [ 3 ]; var i0 = 0; -_prop = ++i0, array0[_prop] = Math.pow(array0[_prop], 2); +var ref = array0[++i0]; +array0[++i0] = Math.pow(ref, 2); var array1 = [ 1, 2, 3 ]; var i1 = 0; -_prop = ++i1, array1[_prop] = Math.pow(array1[_prop], (_prop = ++i1, array1[_prop] = Math.pow(array1[_prop], 2))); +var ref1 = array1[++i1], ref2 = array1[++i1]; +array1[++i1] = Math.pow(ref2, array1[++i1] = Math.pow(ref1, 2)); var array2 = [ 1, 2, 3 ]; var i2 = 0; -_prop = ++i2, array2[_prop] = Math.pow(array2[_prop], Math.pow(array2[++i2], 2)); +var ref3 = array2[++i2]; +array2[++i2] = Math.pow(ref3, Math.pow(array2[++i2], 2)); var array3 = [ 2, 2, 3 ]; var j0 = 0, j1 = 1; -_prop = j0++, array3[_prop] = Math.pow(array3[_prop], (_prop = j1++, array3[_prop] = Math.pow(array3[_prop], (_prop = j0++, array3[_prop] = Math.pow(array3[_prop], 1))))); +var ref4 = array3[j0++], ref5 = array3[j1++], ref6 = array3[j0++]; +array3[j0++] = Math.pow(ref6, array3[j1++] = Math.pow(ref5, array3[j0++] = Math.pow(ref4, 1))); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.2.minified.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.2.minified.js index 059d6631331f..8448c0e28c1d 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.2.minified.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS1.2.minified.js @@ -3,23 +3,23 @@ var array0 = [ 1, 2, 3 -], i0 = 0; -array0[_prop = ++i0] = Math.pow(array0[_prop], 2); +], i0 = 0, ref = array0[++i0]; +array0[++i0] = Math.pow(ref, 2); var array1 = [ 1, 2, 3 -], i1 = 0; -array1[_prop = ++i1] = Math.pow(array1[_prop], array1[_prop = ++i1] = Math.pow(array1[_prop], 2)); +], i1 = 0, ref1 = array1[++i1], ref2 = array1[++i1]; +array1[++i1] = Math.pow(ref2, array1[++i1] = Math.pow(ref1, 2)); var array2 = [ 1, 2, 3 -], i2 = 0; -array2[_prop = ++i2] = Math.pow(array2[_prop], Math.pow(array2[++i2], 2)); +], i2 = 0, ref3 = array2[++i2]; +array2[++i2] = Math.pow(ref3, Math.pow(array2[++i2], 2)); var array3 = [ 2, 2, 3 -], j0 = 0, j1 = 1; -array3[_prop = j0++] = Math.pow(array3[_prop], array3[_prop = j1++] = Math.pow(array3[_prop], array3[_prop = j0++] = Math.pow(array3[_prop], 1))); +], j0 = 0, j1 = 1, ref4 = array3[j0++], ref5 = array3[j1++], ref6 = array3[j0++]; +array3[j0++] = Math.pow(ref6, array3[j1++] = Math.pow(ref5, array3[j0++] = Math.pow(ref4, 1))); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.1.normal.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.1.normal.js index 08298c3d9c21..2d0b001efbe1 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.1.normal.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.1.normal.js @@ -6,9 +6,15 @@ function foo() { 0: 2 }; } -_ref = foo(), _ref[0] = Math.pow(_ref[0], foo()[0]); -var result_foo1 = (_ref = foo(), _ref[0] = Math.pow(_ref[0], foo()[0])); -_ref = foo(), _ref[0] = Math.pow(_ref[0], (_ref = foo(), _ref[0] = Math.pow(_ref[0], 2))); -var result_foo2 = (_ref = foo(), _ref[0] = Math.pow(_ref[0], (_ref = foo(), _ref[0] = Math.pow(_ref[0], 2)))); -_ref = foo(), _ref[0] = Math.pow(_ref[0], Math.pow(foo()[0], 2)); -var result_foo3 = (_ref = foo(), _ref[0] = Math.pow(_ref[0], Math.pow(foo()[0], 2))); +var ref = foo()[0]; +foo()[0] = Math.pow(ref, foo()[0]); +var ref1 = foo()[0]; +var result_foo1 = foo()[0] = Math.pow(ref1, foo()[0]); +var ref2 = foo()[0], ref3 = foo()[0]; +foo()[0] = Math.pow(ref3, foo()[0] = Math.pow(ref2, 2)); +var ref4 = foo()[0], ref5 = foo()[0]; +var result_foo2 = foo()[0] = Math.pow(ref5, foo()[0] = Math.pow(ref4, 2)); +var ref6 = foo()[0]; +foo()[0] = Math.pow(ref6, Math.pow(foo()[0], 2)); +var ref7 = foo()[0]; +var result_foo3 = foo()[0] = Math.pow(ref7, Math.pow(foo()[0], 2)); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.2.minified.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.2.minified.js index 7f2b919dfc92..b467b3f68e6c 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.2.minified.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS2.2.minified.js @@ -5,4 +5,15 @@ function foo() { 0: 2 }; } -(_ref = foo())[0] = Math.pow(_ref[0], foo()[0]), (_ref = foo())[0] = Math.pow(_ref[0], foo()[0]), (_ref = foo())[0] = Math.pow(_ref[0], (_ref = foo())[0] = Math.pow(_ref[0], 2)), (_ref = foo())[0] = Math.pow(_ref[0], (_ref = foo())[0] = Math.pow(_ref[0], 2)), (_ref = foo())[0] = Math.pow(_ref[0], Math.pow(foo()[0], 2)), (_ref = foo())[0] = Math.pow(_ref[0], Math.pow(foo()[0], 2)); +var ref = foo()[0]; +foo()[0] = Math.pow(ref, foo()[0]); +var ref1 = foo()[0]; +foo()[0] = Math.pow(ref1, foo()[0]); +var ref2 = foo()[0], ref3 = foo()[0]; +foo()[0] = Math.pow(ref3, foo()[0] = Math.pow(ref2, 2)); +var ref4 = foo()[0], ref5 = foo()[0]; +foo()[0] = Math.pow(ref5, foo()[0] = Math.pow(ref4, 2)); +var ref6 = foo()[0]; +foo()[0] = Math.pow(ref6, Math.pow(foo()[0], 2)); +var ref7 = foo()[0]; +foo()[0] = Math.pow(ref7, Math.pow(foo()[0], 2)); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.1.normal.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.1.normal.js index f499fb34ee37..ec315697cc75 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.1.normal.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.1.normal.js @@ -8,6 +8,9 @@ var object = { this._0 = x; } }; -object[0] = Math.pow(object[0], object[0]); -object[0] = Math.pow(object[0], object[0] = Math.pow(object[0], 2)); -object[0] = Math.pow(object[0], Math.pow(object[0], 2)); +var ref = object[0]; +object[0] = Math.pow(ref, object[0]); +var ref1 = object[0], ref2 = object[0]; +object[0] = Math.pow(ref2, object[0] = Math.pow(ref1, 2)); +var ref3 = object[0]; +object[0] = Math.pow(ref3, Math.pow(object[0], 2)); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.2.minified.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.2.minified.js index 6f946fd62f0d..a4b3084767f2 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.2.minified.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.2.minified.js @@ -7,5 +7,9 @@ var object = { set 0 (x){ this._0 = x; } -}; -object[0] = Math.pow(object[0], object[0]), object[0] = Math.pow(object[0], object[0] = Math.pow(object[0], 2)), object[0] = Math.pow(object[0], Math.pow(object[0], 2)); +}, ref = object[0]; +object[0] = Math.pow(ref, object[0]); +var ref1 = object[0], ref2 = object[0]; +object[0] = Math.pow(ref2, object[0] = Math.pow(ref1, 2)); +var ref3 = object[0]; +object[0] = Math.pow(ref3, Math.pow(object[0], 2)); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.1.normal.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.1.normal.js index a5c4f462362c..c27090edffd1 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.1.normal.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.1.normal.js @@ -12,6 +12,9 @@ var array1 = [ 4, 5 ]; -_prop = incrementIdx(array1.length), array1[_prop] = Math.pow(array1[_prop], 3); -_prop = incrementIdx(array1.length), array1[_prop] = Math.pow(array1[_prop], (_prop = incrementIdx(array1.length), array1[_prop] = Math.pow(array1[_prop], 2))); -_prop = incrementIdx(array1.length), array1[_prop] = Math.pow(array1[_prop], Math.pow(array1[incrementIdx(array1.length)], 2)); +var ref = array1[incrementIdx(array1.length)]; +array1[incrementIdx(array1.length)] = Math.pow(ref, 3); +var ref1 = array1[incrementIdx(array1.length)], ref2 = array1[incrementIdx(array1.length)]; +array1[incrementIdx(array1.length)] = Math.pow(ref2, array1[incrementIdx(array1.length)] = Math.pow(ref1, 2)); +var ref3 = array1[incrementIdx(array1.length)]; +array1[incrementIdx(array1.length)] = Math.pow(ref3, Math.pow(array1[incrementIdx(array1.length)], 2)); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.2.minified.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.2.minified.js index 13eb5e46f412..2214874da701 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.2.minified.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithIndexingOnLHS4.2.minified.js @@ -9,5 +9,9 @@ var array1 = [ 3, 4, 5 -]; -_prop = incrementIdx(array1.length), array1[_prop] = Math.pow(array1[_prop], 3), _prop = incrementIdx(array1.length), array1[_prop] = Math.pow(array1[_prop], (_prop = incrementIdx(array1.length), array1[_prop] = Math.pow(array1[_prop], 2))), _prop = incrementIdx(array1.length), array1[_prop] = Math.pow(array1[_prop], Math.pow(array1[incrementIdx(array1.length)], 2)); +], ref = array1[incrementIdx(array1.length)]; +array1[incrementIdx(array1.length)] = Math.pow(ref, 3); +var ref1 = array1[incrementIdx(array1.length)], ref2 = array1[incrementIdx(array1.length)]; +array1[incrementIdx(array1.length)] = Math.pow(ref2, array1[incrementIdx(array1.length)] = Math.pow(ref1, 2)); +var ref3 = array1[incrementIdx(array1.length)]; +array1[incrementIdx(array1.length)] = Math.pow(ref3, Math.pow(array1[incrementIdx(array1.length)], 2)); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.1.normal.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.1.normal.js index 851185b6578e..c8cf35793966 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.1.normal.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.1.normal.js @@ -6,9 +6,15 @@ function foo() { prop: 2 }; } -_ref = foo(), _ref.prop = Math.pow(_ref.prop, 2); -var result0 = (_ref = foo(), _ref.prop = Math.pow(_ref.prop, 2)); -_ref = foo(), _ref.prop = Math.pow(_ref.prop, (_ref = foo(), _ref.prop = Math.pow(_ref.prop, 2))); -var result1 = (_ref = foo(), _ref.prop = Math.pow(_ref.prop, (_ref = foo(), _ref.prop = Math.pow(_ref.prop, 2)))); -_ref = foo(), _ref.prop = Math.pow(_ref.prop, Math.pow(foo().prop, 2)); -var result2 = (_ref = foo(), _ref.prop = Math.pow(_ref.prop, Math.pow(foo().prop, 2))); +var ref = foo().prop; +foo().prop = Math.pow(ref, 2); +var ref1 = foo().prop; +var result0 = foo().prop = Math.pow(ref1, 2); +var ref2 = foo().prop, ref3 = foo().prop; +foo().prop = Math.pow(ref3, foo().prop = Math.pow(ref2, 2)); +var ref4 = foo().prop, ref5 = foo().prop; +var result1 = foo().prop = Math.pow(ref5, foo().prop = Math.pow(ref4, 2)); +var ref6 = foo().prop; +foo().prop = Math.pow(ref6, Math.pow(foo().prop, 2)); +var ref7 = foo().prop; +var result2 = foo().prop = Math.pow(ref7, Math.pow(foo().prop, 2)); diff --git a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.2.minified.js b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.2.minified.js index 8b3f5f7648fd..723a6ac2c839 100644 --- a/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.2.minified.js +++ b/crates/swc/tests/tsc-references/emitCompoundExponentiationAssignmentWithPropertyAccessingOnLHS1.2.minified.js @@ -5,4 +5,15 @@ function foo() { prop: 2 }; } -(_ref = foo()).prop = Math.pow(_ref.prop, 2), (_ref = foo()).prop = Math.pow(_ref.prop, 2), (_ref = foo()).prop = Math.pow(_ref.prop, (_ref = foo()).prop = Math.pow(_ref.prop, 2)), (_ref = foo()).prop = Math.pow(_ref.prop, (_ref = foo()).prop = Math.pow(_ref.prop, 2)), (_ref = foo()).prop = Math.pow(_ref.prop, Math.pow(foo().prop, 2)), (_ref = foo()).prop = Math.pow(_ref.prop, Math.pow(foo().prop, 2)); +var ref = foo().prop; +foo().prop = Math.pow(ref, 2); +var ref1 = foo().prop; +foo().prop = Math.pow(ref1, 2); +var ref2 = foo().prop, ref3 = foo().prop; +foo().prop = Math.pow(ref3, foo().prop = Math.pow(ref2, 2)); +var ref4 = foo().prop, ref5 = foo().prop; +foo().prop = Math.pow(ref5, foo().prop = Math.pow(ref4, 2)); +var ref6 = foo().prop; +foo().prop = Math.pow(ref6, Math.pow(foo().prop, 2)); +var ref7 = foo().prop; +foo().prop = Math.pow(ref7, Math.pow(foo().prop, 2)); diff --git a/crates/swc/tests/tsc-references/parseRegularExpressionMixedWithComments.1.normal.js b/crates/swc/tests/tsc-references/parseRegularExpressionMixedWithComments.1.normal.js index 32ebf9630007..202d8c8fa43f 100644 --- a/crates/swc/tests/tsc-references/parseRegularExpressionMixedWithComments.1.normal.js +++ b/crates/swc/tests/tsc-references/parseRegularExpressionMixedWithComments.1.normal.js @@ -2,5 +2,5 @@ var regex1 = / asdf /; var regex2 = /**/ / asdf /; var regex3 = /**/ 1; -var regex4 = Math.pow(/**/ / /, /asdf /); -var regex5 = Math.pow(/**/ / asdf/, / /); +var regex4 = /**/ Math.pow(/ /, /asdf /); +var regex5 = /**/ Math.pow(/ asdf/, / /); diff --git a/crates/swc/tests/tsc-references/parserArrowFunctionExpression10.2.minified.js b/crates/swc/tests/tsc-references/parserArrowFunctionExpression10.2.minified.js index 55a0a8c14a76..310823993051 100644 --- a/crates/swc/tests/tsc-references/parserArrowFunctionExpression10.2.minified.js +++ b/crates/swc/tests/tsc-references/parserArrowFunctionExpression10.2.minified.js @@ -1,5 +1,5 @@ //// [parserArrowFunctionExpression10.ts] //// [fileJs.js] -a || ((e)=>f); +a; //// [fileTs.ts] -a || ((e)=>f); +a; diff --git a/crates/swc/tests/tsc-references/parserArrowFunctionExpression12.2.minified.js b/crates/swc/tests/tsc-references/parserArrowFunctionExpression12.2.minified.js index 3db81a70b451..624739b58f5e 100644 --- a/crates/swc/tests/tsc-references/parserArrowFunctionExpression12.2.minified.js +++ b/crates/swc/tests/tsc-references/parserArrowFunctionExpression12.2.minified.js @@ -1,5 +1,5 @@ //// [parserArrowFunctionExpression12.ts] //// [fileJs.js] -a || ((d)=>e); +a; //// [fileTs.ts] -a || ((d)=>e); +a; diff --git a/crates/swc/tests/tsc-references/parserArrowFunctionExpression13.2.minified.js b/crates/swc/tests/tsc-references/parserArrowFunctionExpression13.2.minified.js index 1d5876994726..6f281b189253 100644 --- a/crates/swc/tests/tsc-references/parserArrowFunctionExpression13.2.minified.js +++ b/crates/swc/tests/tsc-references/parserArrowFunctionExpression13.2.minified.js @@ -1,5 +1,5 @@ //// [parserArrowFunctionExpression13.ts] //// [fileJs.js] -a || (()=>null); +a; //// [fileTs.ts] -a || (()=>null); +a; diff --git a/crates/swc/tests/tsc-references/parserArrowFunctionExpression8.2.minified.js b/crates/swc/tests/tsc-references/parserArrowFunctionExpression8.2.minified.js index cf6b319eaf18..667f56c54964 100644 --- a/crates/swc/tests/tsc-references/parserArrowFunctionExpression8.2.minified.js +++ b/crates/swc/tests/tsc-references/parserArrowFunctionExpression8.2.minified.js @@ -1,9 +1,5 @@ //// [parserArrowFunctionExpression8.ts] //// [fileJs.js] -x || ((z)=>({ - z - })); +x; //// [fileTs.ts] -x || ((z)=>({ - z - })); +x; diff --git a/crates/swc_ecma_compat_es2016/tests/__swc_snapshots__/src/exponentiation.rs/assign_to_object_property.js b/crates/swc_ecma_compat_es2016/tests/__swc_snapshots__/src/exponentiation.rs/assign_to_object_property.js index 6aa394ad9179..811166c0f311 100644 --- a/crates/swc_ecma_compat_es2016/tests/__swc_snapshots__/src/exponentiation.rs/assign_to_object_property.js +++ b/crates/swc_ecma_compat_es2016/tests/__swc_snapshots__/src/exponentiation.rs/assign_to_object_property.js @@ -1,2 +1,3 @@ var self = {}; -self.x = Math.pow(self.x, 3); +var ref = self.x; +self.x = Math.pow(ref, 3);