diff --git a/crates/oxc_transformer/src/es2015/arrow_functions.rs b/crates/oxc_transformer/src/es2015/arrow_functions.rs index 68429f0ff1bd1b..02631743ff5d5c 100644 --- a/crates/oxc_transformer/src/es2015/arrow_functions.rs +++ b/crates/oxc_transformer/src/es2015/arrow_functions.rs @@ -65,7 +65,7 @@ use oxc_allocator::Vec; use oxc_ast::ast::*; use oxc_span::SPAN; use oxc_syntax::{scope::ScopeFlags, symbol::SymbolFlags}; -use oxc_traverse::TraverseCtx; +use oxc_traverse::{Traverse, TraverseCtx}; use serde::Deserialize; use crate::{context::Ctx, helpers::bindings::BoundIdentifier}; @@ -94,23 +94,14 @@ impl<'a> ArrowFunctions<'a> { pub fn new(options: ArrowFunctionsOptions, ctx: Ctx<'a>) -> Self { Self { ctx, _options: options, this_var: None, stacks: vec![], this_statements: vec![] } } +} - fn is_inside_arrow_function(&self) -> bool { - self.stacks.last().copied().unwrap_or(false) - } - - fn get_this_name(&mut self, ctx: &mut TraverseCtx<'a>) -> BoundIdentifier<'a> { - if self.this_var.is_none() { - self.this_var = Some(BoundIdentifier::new_uid_in_current_scope( - "this", - SymbolFlags::FunctionScopedVariable, - ctx, - )); - } - self.this_var.as_ref().unwrap().clone() - } - - pub fn transform_statements(&mut self, _stmts: &mut Vec<'a, Statement<'a>>) { +impl<'a> Traverse<'a> for ArrowFunctions<'a> { + fn enter_statements( + &mut self, + _stmts: &mut Vec<'a, Statement<'a>>, + _ctx: &mut TraverseCtx<'a>, + ) { self.this_statements.push(None); } @@ -125,7 +116,7 @@ impl<'a> ArrowFunctions<'a> { /// } /// ``` /// Insert the var _this = this; statement outside the arrow function - pub fn transform_statements_on_exit(&mut self, stmts: &mut Vec<'a, Statement<'a>>) { + fn exit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, _ctx: &mut TraverseCtx<'a>) { // Insert the var _this = this; if let Some(Some(stmt)) = self.this_statements.pop() { stmts.insert(0, stmt); @@ -171,11 +162,7 @@ impl<'a> ArrowFunctions<'a> { } /// Change to <_this>, and mark it as found - pub fn transform_jsx_element_name( - &mut self, - name: &mut JSXElementName<'a>, - ctx: &mut TraverseCtx<'a>, - ) { + fn enter_jsx_element_name(&mut self, name: &mut JSXElementName<'a>, ctx: &mut TraverseCtx<'a>) { if !self.is_inside_arrow_function() { return; } @@ -199,6 +186,75 @@ impl<'a> ArrowFunctions<'a> { } } + fn enter_expression(&mut self, expr: &mut Expression<'a>, _ctx: &mut TraverseCtx<'a>) { + match expr { + Expression::ArrowFunctionExpression(_) => { + self.stacks.push(true); + } + Expression::FunctionExpression(_) => self.stacks.push(false), + _ => {} + } + } + + fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { + match expr { + Expression::ThisExpression(this_expr) => { + if !self.is_inside_arrow_function() { + return; + } + + let ident = + self.get_this_name(ctx).create_spanned_read_reference(this_expr.span, ctx); + *expr = self.ctx.ast.expression_from_identifier_reference(ident); + } + Expression::ArrowFunctionExpression(arrow_function_expr) => { + *expr = self.transform_arrow_function_expression(arrow_function_expr, ctx); + self.stacks.pop(); + } + Expression::FunctionExpression(_) => { + self.stacks.pop(); + } + _ => {} + } + } + + fn enter_declaration(&mut self, decl: &mut Declaration<'a>, _ctx: &mut TraverseCtx<'a>) { + if let Declaration::FunctionDeclaration(_) = decl { + self.stacks.push(false); + } + } + + fn exit_declaration(&mut self, decl: &mut Declaration<'a>, _ctx: &mut TraverseCtx<'a>) { + if let Declaration::FunctionDeclaration(_) = decl { + self.stacks.pop(); + } + } + + fn enter_class(&mut self, _class: &mut Class<'a>, _ctx: &mut TraverseCtx<'a>) { + self.stacks.push(false); + } + + fn exit_class(&mut self, _class: &mut Class<'a>, _ctx: &mut TraverseCtx<'a>) { + self.stacks.pop(); + } +} + +impl<'a> ArrowFunctions<'a> { + fn is_inside_arrow_function(&self) -> bool { + self.stacks.last().copied().unwrap_or(false) + } + + fn get_this_name(&mut self, ctx: &mut TraverseCtx<'a>) -> BoundIdentifier<'a> { + if self.this_var.is_none() { + self.this_var = Some(BoundIdentifier::new_uid_in_current_scope( + "this", + SymbolFlags::FunctionScopedVariable, + ctx, + )); + } + self.this_var.as_ref().unwrap().clone() + } + fn transform_arrow_function_expression( &mut self, arrow_function_expr: &mut ArrowFunctionExpression<'a>, @@ -259,60 +315,4 @@ impl<'a> ArrowFunctions<'a> { // `() => {};` => `(function () {});` self.ctx.ast.expression_parenthesized(SPAN, expr) } - - pub fn transform_expression(&mut self, expr: &mut Expression<'a>) { - match expr { - Expression::ArrowFunctionExpression(_) => { - self.stacks.push(true); - } - Expression::FunctionExpression(_) => self.stacks.push(false), - _ => {} - } - } - - pub fn transform_expression_on_exit( - &mut self, - expr: &mut Expression<'a>, - ctx: &mut TraverseCtx<'a>, - ) { - match expr { - Expression::ThisExpression(this_expr) => { - if !self.is_inside_arrow_function() { - return; - } - - let ident = - self.get_this_name(ctx).create_spanned_read_reference(this_expr.span, ctx); - *expr = self.ctx.ast.expression_from_identifier_reference(ident); - } - Expression::ArrowFunctionExpression(arrow_function_expr) => { - *expr = self.transform_arrow_function_expression(arrow_function_expr, ctx); - self.stacks.pop(); - } - Expression::FunctionExpression(_) => { - self.stacks.pop(); - } - _ => {} - } - } - - pub fn transform_declaration(&mut self, decl: &mut Declaration<'a>) { - if let Declaration::FunctionDeclaration(_) = decl { - self.stacks.push(false); - } - } - - pub fn transform_declaration_on_exit(&mut self, decl: &mut Declaration<'a>) { - if let Declaration::FunctionDeclaration(_) = decl { - self.stacks.pop(); - } - } - - pub fn transform_class(&mut self, _class: &mut Class<'a>) { - self.stacks.push(false); - } - - pub fn transform_class_on_exit(&mut self, _class: &mut Class<'a>) { - self.stacks.pop(); - } } diff --git a/crates/oxc_transformer/src/es2015/mod.rs b/crates/oxc_transformer/src/es2015/mod.rs index f0304a24573116..a42028d45324cd 100644 --- a/crates/oxc_transformer/src/es2015/mod.rs +++ b/crates/oxc_transformer/src/es2015/mod.rs @@ -3,16 +3,16 @@ mod options; use std::rc::Rc; -pub use arrow_functions::{ArrowFunctions, ArrowFunctionsOptions}; -pub use options::ES2015Options; +use arrow_functions::{ArrowFunctions, ArrowFunctionsOptions}; +use options::ES2015Options; use oxc_allocator::Vec; use oxc_ast::ast::*; -use oxc_traverse::TraverseCtx; +use oxc_traverse::{Traverse, TraverseCtx}; use crate::context::Ctx; #[allow(dead_code)] -pub struct ES2015<'a> { +struct ES2015<'a> { ctx: Ctx<'a>, options: ES2015Options, @@ -21,7 +21,7 @@ pub struct ES2015<'a> { } impl<'a> ES2015<'a> { - pub fn new(options: ES2015Options, ctx: Ctx<'a>) -> Self { + fn new(options: ES2015Options, ctx: Ctx<'a>) -> Self { Self { arrow_functions: ArrowFunctions::new( options.arrow_function.clone().unwrap_or_default(), @@ -31,66 +31,60 @@ impl<'a> ES2015<'a> { options, } } +} - pub fn enter_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>) { +impl<'a> Traverse<'a> for ES2015<'a> { + fn enter_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) { if self.options.arrow_function.is_some() { - self.arrow_functions.transform_statements(stmts); + self.arrow_functions.enter_statements(stmts, ctx); } } - pub fn exit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>) { + fn exit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) { if self.options.arrow_function.is_some() { - self.arrow_functions.transform_statements_on_exit(stmts); + self.arrow_functions.exit_statements(stmts, ctx); } } - pub fn transform_jsx_element_name( - &mut self, - elem: &mut JSXElementName<'a>, - ctx: &mut TraverseCtx<'a>, - ) { + fn enter_jsx_element_name(&mut self, elem: &mut JSXElementName<'a>, ctx: &mut TraverseCtx<'a>) { if self.options.arrow_function.is_some() { - self.arrow_functions.transform_jsx_element_name(elem, ctx); + self.arrow_functions.enter_jsx_element_name(elem, ctx); } } - pub fn transform_declaration(&mut self, decl: &mut Declaration<'a>) { + fn enter_declaration(&mut self, decl: &mut Declaration<'a>, ctx: &mut TraverseCtx<'a>) { if self.options.arrow_function.is_some() { - self.arrow_functions.transform_declaration(decl); + self.arrow_functions.enter_declaration(decl, ctx); } } - pub fn transform_expression(&mut self, expr: &mut Expression<'a>) { + fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { if self.options.arrow_function.is_some() { - self.arrow_functions.transform_expression(expr); + self.arrow_functions.enter_expression(expr, ctx); } } - pub fn transform_expression_on_exit( - &mut self, - expr: &mut Expression<'a>, - ctx: &mut TraverseCtx<'a>, - ) { + fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { if self.options.arrow_function.is_some() { - self.arrow_functions.transform_expression_on_exit(expr, ctx); + self.arrow_functions.exit_expression(expr, ctx); } } - pub fn transform_declaration_on_exit(&mut self, decl: &mut Declaration<'a>) { + fn exit_declaration(&mut self, decl: &mut Declaration<'a>, ctx: &mut TraverseCtx<'a>) { if self.options.arrow_function.is_some() { - self.arrow_functions.transform_declaration_on_exit(decl); + self.arrow_functions.exit_declaration(decl, ctx); } } - pub fn transform_class(&mut self, class: &mut Class<'a>) { + fn enter_class(&mut self, class: &mut Class<'a>, ctx: &mut TraverseCtx<'a>) { if self.options.arrow_function.is_some() { - self.arrow_functions.transform_class(class); + self.arrow_functions.enter_class(class, ctx); } } - pub fn transform_class_on_exit(&mut self, class: &mut Class<'a>) { + fn exit_class(&mut self, class: &mut Class<'a>, ctx: &mut TraverseCtx<'a>) { if self.options.arrow_function.is_some() { - self.arrow_functions.transform_class_on_exit(class); + self.arrow_functions.exit_class(class, ctx); } } } diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index dc49199fae5a99..a756d124c5ebf3 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -144,13 +144,13 @@ impl<'a> Traverse<'a> for Transformer<'a> { self.x1_react.transform_call_expression(expr, ctx); } - fn enter_class(&mut self, class: &mut Class<'a>, _ctx: &mut TraverseCtx<'a>) { + fn enter_class(&mut self, class: &mut Class<'a>, ctx: &mut TraverseCtx<'a>) { self.x0_typescript.transform_class(class); - self.x3_es2015.transform_class(class); + self.x3_es2015.enter_class(class, ctx); } - fn exit_class(&mut self, class: &mut Class<'a>, _ctx: &mut TraverseCtx<'a>) { - self.x3_es2015.transform_class_on_exit(class); + fn exit_class(&mut self, class: &mut Class<'a>, ctx: &mut TraverseCtx<'a>) { + self.x3_es2015.exit_class(class, ctx); } fn enter_class_body(&mut self, body: &mut ClassBody<'a>, _ctx: &mut TraverseCtx<'a>) { @@ -170,12 +170,12 @@ impl<'a> Traverse<'a> for Transformer<'a> { self.x2_es2021.enter_expression(expr, ctx); self.x2_es2020.enter_expression(expr, ctx); self.x2_es2016.enter_expression(expr, ctx); - self.x3_es2015.transform_expression(expr); + self.x3_es2015.enter_expression(expr, ctx); } fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { self.x1_react.transform_expression_on_exit(expr, ctx); - self.x3_es2015.transform_expression_on_exit(expr, ctx); + self.x3_es2015.exit_expression(expr, ctx); } fn enter_simple_assignment_target( @@ -224,7 +224,7 @@ impl<'a> Traverse<'a> for Transformer<'a> { } fn enter_jsx_element_name(&mut self, elem: &mut JSXElementName<'a>, ctx: &mut TraverseCtx<'a>) { - self.x3_es2015.transform_jsx_element_name(elem, ctx); + self.x3_es2015.enter_jsx_element_name(elem, ctx); } fn enter_method_definition( @@ -261,7 +261,7 @@ impl<'a> Traverse<'a> for Transformer<'a> { self.x2_es2021.enter_statements(stmts, ctx); self.x2_es2020.enter_statements(stmts, ctx); self.x2_es2016.enter_statements(stmts, ctx); - self.x3_es2015.enter_statements(stmts); + self.x3_es2015.enter_statements(stmts, ctx); } fn exit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) { @@ -270,7 +270,7 @@ impl<'a> Traverse<'a> for Transformer<'a> { self.x2_es2021.exit_statements(stmts, ctx); self.x2_es2020.exit_statements(stmts, ctx); self.x2_es2016.exit_statements(stmts, ctx); - self.x3_es2015.exit_statements(stmts); + self.x3_es2015.exit_statements(stmts, ctx); } fn enter_tagged_template_expression( @@ -287,11 +287,11 @@ impl<'a> Traverse<'a> for Transformer<'a> { fn enter_declaration(&mut self, decl: &mut Declaration<'a>, ctx: &mut TraverseCtx<'a>) { self.x0_typescript.transform_declaration(decl, ctx); - self.x3_es2015.transform_declaration(decl); + self.x3_es2015.enter_declaration(decl, ctx); } - fn exit_declaration(&mut self, decl: &mut Declaration<'a>, _ctx: &mut TraverseCtx<'a>) { - self.x3_es2015.transform_declaration_on_exit(decl); + fn exit_declaration(&mut self, decl: &mut Declaration<'a>, ctx: &mut TraverseCtx<'a>) { + self.x3_es2015.exit_declaration(decl, ctx); } fn enter_if_statement(&mut self, stmt: &mut IfStatement<'a>, ctx: &mut TraverseCtx<'a>) {