diff --git a/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs b/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs index 43a65f23f6a43..60047d60f4206 100644 --- a/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs +++ b/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs @@ -60,7 +60,7 @@ use oxc_ast::ast::*; use oxc_semantic::{ReferenceFlags, SymbolFlags}; use oxc_span::SPAN; use oxc_syntax::operator::{AssignmentOperator, LogicalOperator}; -use oxc_traverse::TraverseCtx; +use oxc_traverse::{Traverse, TraverseCtx}; use crate::context::Ctx; @@ -73,62 +73,14 @@ impl<'a> LogicalAssignmentOperators<'a> { pub fn new(ctx: Ctx<'a>) -> Self { Self { _ctx: ctx, var_declarations: vec![] } } +} - fn clone_identifier_reference( - ident: &IdentifierReference<'a>, - ctx: &mut TraverseCtx<'a>, - ) -> IdentifierReference<'a> { - let reference = ctx.symbols().get_reference(ident.reference_id.get().unwrap()); - let symbol_id = reference.symbol_id(); - let flags = reference.flags(); - ctx.create_reference_id(ident.span, ident.name.clone(), symbol_id, flags) - } - - pub fn maybe_generate_memoised( - &mut self, - expr: &Expression<'a>, - ctx: &mut TraverseCtx<'a>, - ) -> Option> { - let name = match expr { - Expression::Super(_) | Expression::ThisExpression(_) => return None, - Expression::Identifier(ident) => ident.name.clone(), - Expression::StringLiteral(str) => str.value.clone(), - _ => { - return None; - } - }; - - let symbol_id = - ctx.generate_uid_in_current_scope(name.as_str(), SymbolFlags::FunctionScopedVariable); - let symbol_name = ctx.ast.atom(ctx.symbols().get_name(symbol_id)); - - // var _name; - let binding_identifier = BindingIdentifier { - span: SPAN, - name: symbol_name.clone(), - symbol_id: Cell::new(Some(symbol_id)), - }; - let kind = VariableDeclarationKind::Var; - let id = ctx.ast.binding_pattern_kind_from_binding_identifier(binding_identifier); - let id = ctx.ast.binding_pattern(id, None::, false); - self.var_declarations - .last_mut() - .unwrap() - .push(ctx.ast.variable_declarator(SPAN, kind, id, None, false)); - - // _name = name - Some(ctx.create_reference_id(SPAN, symbol_name, Some(symbol_id), ReferenceFlags::Write)) - } - - pub fn transform_statements( - &mut self, - _statements: &mut Vec<'a, Statement<'a>>, - ctx: &mut TraverseCtx<'a>, - ) { +impl<'a> Traverse<'a> for LogicalAssignmentOperators<'a> { + fn enter_statements(&mut self, _stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) { self.var_declarations.push(ctx.ast.vec()); } - pub fn transform_statements_on_exit( + fn exit_statements( &mut self, statements: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>, @@ -147,7 +99,7 @@ impl<'a> LogicalAssignmentOperators<'a> { } } - pub fn transform_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { + fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { let Expression::AssignmentExpression(assignment_expr) = expr else { return }; // `&&=` `||=` `??=` @@ -319,3 +271,51 @@ impl<'a> LogicalAssignmentOperators<'a> { *expr = logical_expr; } } + +impl<'a> LogicalAssignmentOperators<'a> { + fn clone_identifier_reference( + ident: &IdentifierReference<'a>, + ctx: &mut TraverseCtx<'a>, + ) -> IdentifierReference<'a> { + let reference = ctx.symbols().get_reference(ident.reference_id.get().unwrap()); + let symbol_id = reference.symbol_id(); + let flags = reference.flags(); + ctx.create_reference_id(ident.span, ident.name.clone(), symbol_id, flags) + } + + pub fn maybe_generate_memoised( + &mut self, + expr: &Expression<'a>, + ctx: &mut TraverseCtx<'a>, + ) -> Option> { + let name = match expr { + Expression::Super(_) | Expression::ThisExpression(_) => return None, + Expression::Identifier(ident) => ident.name.clone(), + Expression::StringLiteral(str) => str.value.clone(), + _ => { + return None; + } + }; + + let symbol_id = + ctx.generate_uid_in_current_scope(name.as_str(), SymbolFlags::FunctionScopedVariable); + let symbol_name = ctx.ast.atom(ctx.symbols().get_name(symbol_id)); + + // var _name; + let binding_identifier = BindingIdentifier { + span: SPAN, + name: symbol_name.clone(), + symbol_id: Cell::new(Some(symbol_id)), + }; + let kind = VariableDeclarationKind::Var; + let id = ctx.ast.binding_pattern_kind_from_binding_identifier(binding_identifier); + let id = ctx.ast.binding_pattern(id, None::, false); + self.var_declarations + .last_mut() + .unwrap() + .push(ctx.ast.variable_declarator(SPAN, kind, id, None, false)); + + // _name = name + Some(ctx.create_reference_id(SPAN, symbol_name, Some(symbol_id), ReferenceFlags::Write)) + } +} diff --git a/crates/oxc_transformer/src/es2021/mod.rs b/crates/oxc_transformer/src/es2021/mod.rs index 215cb07d39327..392ff00949f2b 100644 --- a/crates/oxc_transformer/src/es2021/mod.rs +++ b/crates/oxc_transformer/src/es2021/mod.rs @@ -5,7 +5,7 @@ pub use logical_assignment_operators::LogicalAssignmentOperators; pub use options::ES2021Options; use oxc_allocator::Vec; use oxc_ast::ast::*; -use oxc_traverse::TraverseCtx; +use oxc_traverse::{Traverse, TraverseCtx}; use std::rc::Rc; use crate::context::Ctx; @@ -27,30 +27,32 @@ impl<'a> ES2021<'a> { options, } } +} - pub fn transform_statements( +impl<'a> Traverse<'a> for ES2021<'a> { + fn enter_statements( &mut self, statements: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>, ) { if self.options.logical_assignment_operators { - self.logical_assignment_operators.transform_statements(statements, ctx); + self.logical_assignment_operators.enter_statements(statements, ctx); } } - pub fn transform_statements_on_exit( + fn exit_statements( &mut self, statements: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>, ) { if self.options.logical_assignment_operators { - self.logical_assignment_operators.transform_statements_on_exit(statements, ctx); + self.logical_assignment_operators.exit_statements(statements, ctx); } } - pub fn transform_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { + fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { if self.options.logical_assignment_operators { - self.logical_assignment_operators.transform_expression(expr, ctx); + self.logical_assignment_operators.enter_expression(expr, ctx); } } } diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index a7eeced14f4dc..8516974740fd7 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -177,7 +177,7 @@ impl<'a> Traverse<'a> for Transformer<'a> { fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { self.x0_typescript.transform_expression(expr); self.x1_react.transform_expression(expr, ctx); - self.x2_es2021.transform_expression(expr, ctx); + self.x2_es2021.enter_expression(expr, ctx); self.x2_es2020.enter_expression(expr, ctx); self.x2_es2016.transform_expression(expr, ctx); self.x3_es2015.transform_expression(expr); @@ -268,7 +268,7 @@ impl<'a> Traverse<'a> for Transformer<'a> { fn enter_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) { self.x0_typescript.transform_statements(stmts); self.x1_react.transform_statements(stmts, ctx); - self.x2_es2021.transform_statements(stmts, ctx); + self.x2_es2021.enter_statements(stmts, ctx); self.x2_es2020.enter_statements(stmts, ctx); self.x2_es2016.transform_statements(stmts, ctx); self.x3_es2015.enter_statements(stmts); @@ -277,7 +277,7 @@ impl<'a> Traverse<'a> for Transformer<'a> { fn exit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) { self.x0_typescript.transform_statements_on_exit(stmts, ctx); self.x1_react.transform_statements_on_exit(stmts, ctx); - self.x2_es2021.transform_statements_on_exit(stmts, ctx); + self.x2_es2021.exit_statements(stmts, ctx); self.x2_es2020.exit_statements(stmts, ctx); self.x2_es2016.transform_statements_on_exit(stmts, ctx); self.x3_es2015.exit_statements(stmts);