diff --git a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs index 1f0b3312b4013..cc23ffac005be 100644 --- a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs +++ b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs @@ -37,7 +37,7 @@ use oxc_span::SPAN; use oxc_syntax::operator::{AssignmentOperator, BinaryOperator}; use oxc_traverse::{Traverse, TraverseCtx}; -use crate::context::Ctx; +use crate::{context::Ctx, helpers::stack::SparseStack}; /// ES2016: Exponentiation Operator /// @@ -47,7 +47,7 @@ use crate::context::Ctx; /// * pub struct ExponentiationOperator<'a> { _ctx: Ctx<'a>, - var_declarations: std::vec::Vec>>, + var_declarations: SparseStack>>, } #[derive(Debug)] @@ -58,17 +58,22 @@ struct Exploded<'a> { impl<'a> ExponentiationOperator<'a> { pub fn new(ctx: Ctx<'a>) -> Self { - Self { _ctx: ctx, var_declarations: vec![] } + Self { _ctx: ctx, var_declarations: SparseStack::new() } } } impl<'a> Traverse<'a> for ExponentiationOperator<'a> { + #[inline] // Inline because it's no-op in release mode + fn exit_program(&mut self, _program: &mut Program<'a>, _ctx: &mut TraverseCtx<'a>) { + debug_assert!(self.var_declarations.is_empty()); + } + fn enter_statements( &mut self, _statements: &mut Vec<'a, Statement<'a>>, - ctx: &mut TraverseCtx<'a>, + _ctx: &mut TraverseCtx<'a>, ) { - self.var_declarations.push(ctx.ast.vec()); + self.var_declarations.push(None); } fn exit_statements( @@ -77,9 +82,7 @@ impl<'a> Traverse<'a> for ExponentiationOperator<'a> { ctx: &mut TraverseCtx<'a>, ) { if let Some(declarations) = self.var_declarations.pop() { - if declarations.is_empty() { - return; - } + debug_assert!(!declarations.is_empty()); let variable = ctx.ast.alloc_variable_declaration( SPAN, VariableDeclarationKind::Var, @@ -318,8 +321,7 @@ impl<'a> ExponentiationOperator<'a> { 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() + .get_mut_or_init(|| ctx.ast.vec()) .push(ctx.ast.variable_declarator(SPAN, kind, id, None, false)); } diff --git a/crates/oxc_transformer/src/es2016/mod.rs b/crates/oxc_transformer/src/es2016/mod.rs index 857c4fa012623..4fd48ac555d08 100644 --- a/crates/oxc_transformer/src/es2016/mod.rs +++ b/crates/oxc_transformer/src/es2016/mod.rs @@ -27,6 +27,13 @@ impl<'a> ES2016<'a> { } impl<'a> Traverse<'a> for ES2016<'a> { + #[inline] // Inline because it's no-op in release mode + fn exit_program(&mut self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) { + if self.options.exponentiation_operator { + self.exponentiation_operator.exit_program(program, ctx); + } + } + fn enter_statements( &mut self, statements: &mut Vec<'a, Statement<'a>>, diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index 1a854c0b9ba53..c178f9ffbf5ff 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -133,6 +133,7 @@ impl<'a> Traverse<'a> for Transformer<'a> { self.x1_react.exit_program(program, ctx); self.x0_typescript.exit_program(program, ctx); self.x2_es2020.exit_program(program, ctx); + self.x2_es2016.exit_program(program, ctx); self.x3_es2015.exit_program(program, ctx); }