diff --git a/crates/oxc_isolated_declarations/src/module.rs b/crates/oxc_isolated_declarations/src/module.rs index b04ca2047f065..677cd2e40c0f1 100644 --- a/crates/oxc_isolated_declarations/src/module.rs +++ b/crates/oxc_isolated_declarations/src/module.rs @@ -1,4 +1,4 @@ -use oxc_allocator::{Box as ArenaBox, CloneIn, Vec as ArenaVec}; +use oxc_allocator::{Box as ArenaBox, CloneIn, TakeIn, Vec as ArenaVec}; use oxc_ast::{NONE, ast::*}; use oxc_span::{Atom, GetSpan, SPAN}; @@ -167,7 +167,7 @@ impl<'a> IsolatedDeclarations<'a> { stmts.iter_mut().for_each(|stmt| { if let Statement::ExportNamedDeclaration(decl) = stmt { if let Some(declaration) = &mut decl.declaration { - *stmt = Statement::from(self.ast.move_declaration(declaration)); + *stmt = Statement::from(declaration.take_in(self.ast.allocator)); } } }); diff --git a/crates/oxc_minifier/src/peephole/convert_to_dotted_properties.rs b/crates/oxc_minifier/src/peephole/convert_to_dotted_properties.rs index 7609a9b0b8c0a..378a9a75684a6 100644 --- a/crates/oxc_minifier/src/peephole/convert_to_dotted_properties.rs +++ b/crates/oxc_minifier/src/peephole/convert_to_dotted_properties.rs @@ -1,3 +1,4 @@ +use oxc_allocator::TakeIn; use oxc_ast::ast::*; use oxc_syntax::identifier::is_identifier_name; @@ -18,10 +19,13 @@ impl<'a> LatePeepholeOptimizations { let Expression::StringLiteral(s) = &e.expression else { return }; if is_identifier_name(&s.value) { let property = ctx.ast.identifier_name(s.span, s.value); - let object = ctx.ast.move_expression(&mut e.object); - *expr = MemberExpression::StaticMemberExpression( - ctx.ast.alloc_static_member_expression(e.span, object, property, e.optional), - ); + *expr = + MemberExpression::StaticMemberExpression(ctx.ast.alloc_static_member_expression( + e.span, + e.object.take_in(ctx.ast.allocator), + property, + e.optional, + )); return; } let v = s.value.as_str(); diff --git a/crates/oxc_minifier/src/peephole/fold_constants.rs b/crates/oxc_minifier/src/peephole/fold_constants.rs index ba60562be34b3..7840f3ac63b4a 100644 --- a/crates/oxc_minifier/src/peephole/fold_constants.rs +++ b/crates/oxc_minifier/src/peephole/fold_constants.rs @@ -1,3 +1,4 @@ +use oxc_allocator::TakeIn; use oxc_ast::ast::*; use oxc_ecmascript::{ ToJsString, @@ -131,7 +132,7 @@ impl<'a> PeepholeOptimizations { // (TRUE || x) => TRUE (also, (3 || x) => 3) // (FALSE && x) => FALSE if if lval { op.is_or() } else { op.is_and() } { - return Some(ctx.ast.move_expression(&mut logical_expr.left)); + return Some(logical_expr.left.take_in(ctx.ast.allocator)); } else if !left.may_have_side_effects(&ctx) { let should_keep_indirect_access = Self::should_keep_indirect_access(&logical_expr.right, ctx); @@ -146,19 +147,19 @@ impl<'a> PeepholeOptimizations { None, NumberBase::Decimal, ), - ctx.ast.move_expression(&mut logical_expr.right), + logical_expr.right.take_in(ctx.ast.allocator), ]), )); } // (FALSE || x) => x // (TRUE && x) => x - return Some(ctx.ast.move_expression(&mut logical_expr.right)); + return Some(logical_expr.right.take_in(ctx.ast.allocator)); } // Left side may have side effects, but we know its boolean value. // e.g. true_with_sideeffects || foo() => true_with_sideeffects, foo() // or: false_with_sideeffects && foo() => false_with_sideeffects, foo() - let left = ctx.ast.move_expression(&mut logical_expr.left); - let right = ctx.ast.move_expression(&mut logical_expr.right); + let left = logical_expr.left.take_in(ctx.ast.allocator); + let right = logical_expr.right.take_in(ctx.ast.allocator); let vec = ctx.ast.vec_from_array([left, right]); let sequence_expr = ctx.ast.expression_sequence(logical_expr.span, vec); return Some(sequence_expr); @@ -173,8 +174,8 @@ impl<'a> PeepholeOptimizations { if !right_boolean && left_child_op.is_or() || right_boolean && left_child_op.is_and() { - let left = ctx.ast.move_expression(&mut left_child.left); - let right = ctx.ast.move_expression(&mut logical_expr.right); + let left = left_child.left.take_in(ctx.ast.allocator); + let right = logical_expr.right.take_in(ctx.ast.allocator); let logic_expr = ctx.ast.expression_logical( logical_expr.span, left, @@ -203,8 +204,8 @@ impl<'a> PeepholeOptimizations { Some(if left.may_have_side_effects(&ctx) { // e.g. `(a(), null) ?? 1` => `(a(), null, 1)` let expressions = ctx.ast.vec_from_array([ - ctx.ast.move_expression(&mut logical_expr.left), - ctx.ast.move_expression(&mut logical_expr.right), + logical_expr.left.take_in(ctx.ast.allocator), + logical_expr.right.take_in(ctx.ast.allocator), ]); ctx.ast.expression_sequence(logical_expr.span, expressions) } else { @@ -221,12 +222,12 @@ impl<'a> PeepholeOptimizations { None, NumberBase::Decimal, ), - ctx.ast.move_expression(&mut logical_expr.right), + logical_expr.right.take_in(ctx.ast.allocator), ]), )); } // nullish condition => this expression evaluates to the right side. - ctx.ast.move_expression(&mut logical_expr.right) + logical_expr.right.take_in(ctx.ast.allocator) }) } ValueType::Number @@ -247,12 +248,12 @@ impl<'a> PeepholeOptimizations { None, NumberBase::Decimal, ), - ctx.ast.move_expression(&mut logical_expr.left), + logical_expr.left.take_in(ctx.ast.allocator), ]), )); } // non-nullish condition => this expression evaluates to the left side. - Some(ctx.ast.move_expression(&mut logical_expr.left)) + Some(logical_expr.left.take_in(ctx.ast.allocator)) } ValueType::Undetermined => None, } @@ -390,14 +391,14 @@ impl<'a> PeepholeOptimizations { let span = Span::new(left_binary_expr.right.span().start, e.right.span().end); let value = left_str.into_owned() + &right_str; let right = ctx.ast.expression_string_literal(span, value, None); - let left = ctx.ast.move_expression(&mut left_binary_expr.left); + let left = left_binary_expr.left.take_in(ctx.ast.allocator); return Some(ctx.ast.expression_binary(e.span, left, e.operator, right)); } if let Some(new_right) = Self::try_fold_add_op(&mut left_binary_expr.right, &mut e.right, ctx) { - let left = ctx.ast.move_expression(&mut left_binary_expr.left); + let left = left_binary_expr.left.take_in(ctx.ast.allocator); return Some(ctx.ast.expression_binary(e.span, left, e.operator, new_right)); } } @@ -436,7 +437,7 @@ impl<'a> PeepholeOptimizations { } left.quasis.extend(right.quasis.drain(1..)); // first quasi is already handled left.expressions.extend(right.expressions.drain(..)); - return Some(ctx.ast.move_expression(left_expr)); + return Some(left_expr.take_in(ctx.ast.allocator)); } // "`${x}y` + 'z'" => "`${x}yz`" @@ -452,7 +453,7 @@ impl<'a> PeepholeOptimizations { .cooked .map(|cooked| ctx.ast.atom(&(cooked.as_str().to_string() + &right_str))); last_quasi.value.cooked = new_cooked; - return Some(ctx.ast.move_expression(left_expr)); + return Some(left_expr.take_in(ctx.ast.allocator)); } } else if let Expression::TemplateLiteral(right) = right_expr { // "'x' + `y${z}`" => "`xy${z}`" @@ -470,17 +471,17 @@ impl<'a> PeepholeOptimizations { .cooked .map(|cooked| ctx.ast.atom(&(left_str.into_owned() + cooked.as_str()))); first_quasi.value.cooked = new_cooked; - return Some(ctx.ast.move_expression(right_expr)); + return Some(right_expr.take_in(ctx.ast.allocator)); } } // remove useless `+ ""` (e.g. `typeof foo + ""` -> `typeof foo`) if Self::evaluates_to_empty_string(left_expr) && right_expr.value_type(&ctx).is_string() { - return Some(ctx.ast.move_expression(right_expr)); + return Some(right_expr.take_in(ctx.ast.allocator)); } else if Self::evaluates_to_empty_string(right_expr) && left_expr.value_type(&ctx).is_string() { - return Some(ctx.ast.move_expression(left_expr)); + return Some(left_expr.take_in(ctx.ast.allocator)); } None @@ -522,7 +523,7 @@ impl<'a> PeepholeOptimizations { Some(ctx.ast.expression_binary( e.span, - ctx.ast.move_expression(expr_to_move), + expr_to_move.take_in(ctx.ast.allocator), op, ctx.value_to_expr(Span::new(left.right.span().start, e.right.span().end), v), )) diff --git a/crates/oxc_minifier/src/peephole/minimize_conditional_expression.rs b/crates/oxc_minifier/src/peephole/minimize_conditional_expression.rs index b96cf4b15e1ad..894e4da806894 100644 --- a/crates/oxc_minifier/src/peephole/minimize_conditional_expression.rs +++ b/crates/oxc_minifier/src/peephole/minimize_conditional_expression.rs @@ -1,3 +1,4 @@ +use oxc_allocator::TakeIn; use oxc_ast::{NONE, ast::*}; use oxc_ecmascript::side_effects::MayHaveSideEffects; use oxc_span::{ContentEq, GetSpan}; @@ -32,15 +33,15 @@ impl<'a> PeepholeOptimizations { Expression::SequenceExpression(sequence_expr) => { if sequence_expr.expressions.len() > 1 { let span = expr.span(); - let mut sequence = ctx.ast.move_expression(&mut expr.test); + let mut sequence = expr.test.take_in(ctx.ast.allocator); let Expression::SequenceExpression(sequence_expr) = &mut sequence else { unreachable!() }; let expr = self.minimize_conditional( span, sequence_expr.expressions.pop().unwrap(), - ctx.ast.move_expression(&mut expr.consequent), - ctx.ast.move_expression(&mut expr.alternate), + expr.consequent.take_in(ctx.ast.allocator), + expr.alternate.take_in(ctx.ast.allocator), ctx, ); sequence_expr.expressions.push(expr); @@ -50,9 +51,9 @@ impl<'a> PeepholeOptimizations { // "!a ? b : c" => "a ? c : b" Expression::UnaryExpression(test_expr) => { if test_expr.operator.is_not() { - let test = ctx.ast.move_expression(&mut test_expr.argument); - let consequent = ctx.ast.move_expression(&mut expr.alternate); - let alternate = ctx.ast.move_expression(&mut expr.consequent); + let test = test_expr.argument.take_in(ctx.ast.allocator); + let consequent = expr.alternate.take_in(ctx.ast.allocator); + let alternate = expr.consequent.take_in(ctx.ast.allocator); return Some( self.minimize_conditional(expr.span, test, consequent, alternate, ctx), ); @@ -65,8 +66,8 @@ impl<'a> PeepholeOptimizations { return Some(self.join_with_left_associative_op( expr.span, LogicalOperator::Or, - ctx.ast.move_expression(&mut expr.test), - ctx.ast.move_expression(&mut expr.alternate), + expr.test.take_in(ctx.ast.allocator), + expr.alternate.take_in(ctx.ast.allocator), ctx, )); } @@ -77,8 +78,8 @@ impl<'a> PeepholeOptimizations { return Some(self.join_with_left_associative_op( expr.span, LogicalOperator::And, - ctx.ast.move_expression(&mut expr.test), - ctx.ast.move_expression(&mut expr.consequent), + expr.test.take_in(ctx.ast.allocator), + expr.consequent.take_in(ctx.ast.allocator), ctx, )); } @@ -91,9 +92,9 @@ impl<'a> PeepholeOptimizations { BinaryOperator::Inequality | BinaryOperator::StrictInequality ) { test_expr.operator = test_expr.operator.equality_inverse_operator().unwrap(); - let test = ctx.ast.move_expression(&mut expr.test); - let consequent = ctx.ast.move_expression(&mut expr.consequent); - let alternate = ctx.ast.move_expression(&mut expr.alternate); + let test = expr.test.take_in(ctx.ast.allocator); + let consequent = expr.consequent.take_in(ctx.ast.allocator); + let alternate = expr.alternate.take_in(ctx.ast.allocator); return Some( self.minimize_conditional(expr.span, test, alternate, consequent, ctx), ); @@ -109,13 +110,13 @@ impl<'a> PeepholeOptimizations { { match (left.value, right.value) { (true, false) => { - let test = ctx.ast.move_expression(&mut expr.test); + let test = expr.test.take_in(ctx.ast.allocator); let test = self.minimize_not(expr.span, test, ctx); let test = self.minimize_not(expr.span, test, ctx); return Some(test); } (false, true) => { - let test = ctx.ast.move_expression(&mut expr.test); + let test = expr.test.take_in(ctx.ast.allocator); let test = self.minimize_not(expr.span, test, ctx); return Some(test); } @@ -131,12 +132,12 @@ impl<'a> PeepholeOptimizations { self.join_with_left_associative_op( expr.test.span(), LogicalOperator::And, - ctx.ast.move_expression(&mut expr.test), - ctx.ast.move_expression(&mut consequent.test), + expr.test.take_in(ctx.ast.allocator), + consequent.test.take_in(ctx.ast.allocator), ctx, ), - ctx.ast.move_expression(&mut consequent.consequent), - ctx.ast.move_expression(&mut consequent.alternate), + consequent.consequent.take_in(ctx.ast.allocator), + consequent.alternate.take_in(ctx.ast.allocator), )); } } @@ -149,12 +150,12 @@ impl<'a> PeepholeOptimizations { self.join_with_left_associative_op( expr.test.span(), LogicalOperator::Or, - ctx.ast.move_expression(&mut expr.test), - ctx.ast.move_expression(&mut alternate.test), + expr.test.take_in(ctx.ast.allocator), + alternate.test.take_in(ctx.ast.allocator), ctx, ), - ctx.ast.move_expression(&mut expr.consequent), - ctx.ast.move_expression(&mut alternate.alternate), + expr.consequent.take_in(ctx.ast.allocator), + alternate.alternate.take_in(ctx.ast.allocator), )); } } @@ -170,11 +171,11 @@ impl<'a> PeepholeOptimizations { self.join_with_left_associative_op( expr.test.span(), LogicalOperator::Or, - ctx.ast.move_expression(&mut expr.test), - ctx.ast.move_expression(&mut alternate.expressions[0]), + expr.test.take_in(ctx.ast.allocator), + alternate.expressions[0].take_in(ctx.ast.allocator), ctx, ), - ctx.ast.move_expression(&mut expr.consequent), + expr.consequent.take_in(ctx.ast.allocator), ]), )); } @@ -191,11 +192,11 @@ impl<'a> PeepholeOptimizations { self.join_with_left_associative_op( expr.test.span(), LogicalOperator::And, - ctx.ast.move_expression(&mut expr.test), - ctx.ast.move_expression(&mut consequent.expressions[0]), + expr.test.take_in(ctx.ast.allocator), + consequent.expressions[0].take_in(ctx.ast.allocator), ctx, ), - ctx.ast.move_expression(&mut expr.alternate), + expr.alternate.take_in(ctx.ast.allocator), ]), )); } @@ -209,12 +210,12 @@ impl<'a> PeepholeOptimizations { self.join_with_left_associative_op( expr.test.span(), LogicalOperator::And, - ctx.ast.move_expression(&mut expr.test), - ctx.ast.move_expression(&mut logical_expr.left), + expr.test.take_in(ctx.ast.allocator), + logical_expr.left.take_in(ctx.ast.allocator), ctx, ), LogicalOperator::Or, - ctx.ast.move_expression(&mut expr.alternate), + expr.alternate.take_in(ctx.ast.allocator), )); } } @@ -229,12 +230,12 @@ impl<'a> PeepholeOptimizations { self.join_with_left_associative_op( expr.test.span(), LogicalOperator::Or, - ctx.ast.move_expression(&mut expr.test), - ctx.ast.move_expression(&mut logical_expr.left), + expr.test.take_in(ctx.ast.allocator), + logical_expr.left.take_in(ctx.ast.allocator), ctx, ), LogicalOperator::And, - ctx.ast.move_expression(&mut expr.consequent), + expr.consequent.take_in(ctx.ast.allocator), )); } } @@ -261,25 +262,25 @@ impl<'a> PeepholeOptimizations { if matches!(consequent.arguments[0], Argument::SpreadElement(_)) && matches!(alternate.arguments[0], Argument::SpreadElement(_)) { - let callee = ctx.ast.move_expression(&mut consequent.callee); + let callee = consequent.callee.take_in(ctx.ast.allocator); let consequent_first_arg = { let Argument::SpreadElement(el) = &mut consequent.arguments[0] else { unreachable!() }; - ctx.ast.move_expression(&mut el.argument) + el.argument.take_in(ctx.ast.allocator) }; let alternate_first_arg = { let Argument::SpreadElement(el) = &mut alternate.arguments[0] else { unreachable!() }; - ctx.ast.move_expression(&mut el.argument) + el.argument.take_in(ctx.ast.allocator) }; let mut args = std::mem::replace(&mut consequent.arguments, ctx.ast.vec()); args[0] = ctx.ast.argument_spread_element( expr.span, ctx.ast.expression_conditional( expr.test.span(), - ctx.ast.move_expression(&mut expr.test), + expr.test.take_in(ctx.ast.allocator), consequent_first_arg, alternate_first_arg, ), @@ -290,16 +291,16 @@ impl<'a> PeepholeOptimizations { if !matches!(consequent.arguments[0], Argument::SpreadElement(_)) && !matches!(alternate.arguments[0], Argument::SpreadElement(_)) { - let callee = ctx.ast.move_expression(&mut consequent.callee); + let callee = consequent.callee.take_in(ctx.ast.allocator); let consequent_first_arg = - ctx.ast.move_expression(consequent.arguments[0].to_expression_mut()); + consequent.arguments[0].to_expression_mut().take_in(ctx.ast.allocator); let alternate_first_arg = - ctx.ast.move_expression(alternate.arguments[0].to_expression_mut()); + alternate.arguments[0].to_expression_mut().take_in(ctx.ast.allocator); let mut args = std::mem::replace(&mut consequent.arguments, ctx.ast.vec()); let cond_expr = self.minimize_conditional( expr.test.span(), - ctx.ast.move_expression(&mut expr.test), + expr.test.take_in(ctx.ast.allocator), consequent_first_arg, alternate_first_arg, ctx, @@ -353,13 +354,13 @@ impl<'a> PeepholeOptimizations { if maybe_same_id_expr.is_specific_id(&target_id_name) { return Some(ctx.ast.expression_logical( expr.span, - ctx.ast.move_expression(value_expr), + value_expr.take_in(ctx.ast.allocator), LogicalOperator::Coalesce, - ctx.ast.move_expression(if is_negate { - &mut expr.alternate + if is_negate { + expr.alternate.take_in(ctx.ast.allocator) } else { - &mut expr.consequent - }), + expr.consequent.take_in(ctx.ast.allocator) + }, )); } @@ -379,7 +380,7 @@ impl<'a> PeepholeOptimizations { ctx, ) { return Some( - ctx.ast.move_expression(expr_to_inject_optional_chaining), + expr_to_inject_optional_chaining.take_in(ctx.ast.allocator), ); } } @@ -391,13 +392,13 @@ impl<'a> PeepholeOptimizations { if ctx.expr_eq(&expr.alternate, &expr.consequent) { // "/* @__PURE__ */ a() ? b : b" => "b" if !expr.test.may_have_side_effects(&ctx) { - return Some(ctx.ast.move_expression(&mut expr.consequent)); + return Some(expr.consequent.take_in(ctx.ast.allocator)); } // "a ? b : b" => "a, b" let expressions = ctx.ast.vec_from_array([ - ctx.ast.move_expression(&mut expr.test), - ctx.ast.move_expression(&mut expr.consequent), + expr.test.take_in(ctx.ast.allocator), + expr.consequent.take_in(ctx.ast.allocator), ]); return Some(ctx.ast.expression_sequence(expr.span, expressions)); } @@ -436,15 +437,15 @@ impl<'a> PeepholeOptimizations { } let cond_expr = self.minimize_conditional( expr.span, - ctx.ast.move_expression(&mut expr.test), - ctx.ast.move_expression(&mut consequent.right), - ctx.ast.move_expression(&mut alternate.right), + expr.test.take_in(ctx.ast.allocator), + consequent.right.take_in(ctx.ast.allocator), + alternate.right.take_in(ctx.ast.allocator), ctx, ); Some(ctx.ast.expression_assignment( expr.span, consequent.operator, - ctx.ast.move_assignment_target(&mut alternate.left), + alternate.left.take_in(ctx.ast.allocator), cond_expr, )) } @@ -467,7 +468,7 @@ impl<'a> PeepholeOptimizations { if !matches!(expr, Expression::ChainExpression(_)) { *expr = ctx.ast.expression_chain( expr.span(), - ctx.ast.move_expression(expr).into_chain_element().unwrap(), + expr.take_in(ctx.ast.allocator).into_chain_element().unwrap(), ); } true @@ -487,7 +488,7 @@ impl<'a> PeepholeOptimizations { Expression::StaticMemberExpression(e) => { if e.object.is_specific_id(target_id_name) { e.optional = true; - e.object = ctx.ast.move_expression(expr_to_inject); + e.object = expr_to_inject.take_in(ctx.ast.allocator); return true; } if Self::inject_optional_chaining_if_matched_inner( @@ -502,7 +503,7 @@ impl<'a> PeepholeOptimizations { Expression::ComputedMemberExpression(e) => { if e.object.is_specific_id(target_id_name) { e.optional = true; - e.object = ctx.ast.move_expression(expr_to_inject); + e.object = expr_to_inject.take_in(ctx.ast.allocator); return true; } if Self::inject_optional_chaining_if_matched_inner( @@ -517,7 +518,7 @@ impl<'a> PeepholeOptimizations { Expression::CallExpression(e) => { if e.callee.is_specific_id(target_id_name) { e.optional = true; - e.callee = ctx.ast.move_expression(expr_to_inject); + e.callee = expr_to_inject.take_in(ctx.ast.allocator); return true; } if Self::inject_optional_chaining_if_matched_inner( @@ -533,7 +534,7 @@ impl<'a> PeepholeOptimizations { ChainElement::StaticMemberExpression(e) => { if e.object.is_specific_id(target_id_name) { e.optional = true; - e.object = ctx.ast.move_expression(expr_to_inject); + e.object = expr_to_inject.take_in(ctx.ast.allocator); return true; } if Self::inject_optional_chaining_if_matched_inner( @@ -548,7 +549,7 @@ impl<'a> PeepholeOptimizations { ChainElement::ComputedMemberExpression(e) => { if e.object.is_specific_id(target_id_name) { e.optional = true; - e.object = ctx.ast.move_expression(expr_to_inject); + e.object = expr_to_inject.take_in(ctx.ast.allocator); return true; } if Self::inject_optional_chaining_if_matched_inner( @@ -563,7 +564,7 @@ impl<'a> PeepholeOptimizations { ChainElement::CallExpression(e) => { if e.callee.is_specific_id(target_id_name) { e.optional = true; - e.callee = ctx.ast.move_expression(expr_to_inject); + e.callee = expr_to_inject.take_in(ctx.ast.allocator); return true; } if Self::inject_optional_chaining_if_matched_inner( diff --git a/crates/oxc_minifier/src/peephole/minimize_conditions.rs b/crates/oxc_minifier/src/peephole/minimize_conditions.rs index 0fbfe8c58572b..b9b07a74d9be1 100644 --- a/crates/oxc_minifier/src/peephole/minimize_conditions.rs +++ b/crates/oxc_minifier/src/peephole/minimize_conditions.rs @@ -1,3 +1,4 @@ +use oxc_allocator::TakeIn; use oxc_ast::ast::*; use oxc_ecmascript::{ ToInt32, @@ -93,9 +94,9 @@ impl<'a> PeepholeOptimizations { loop { if let Expression::LogicalExpression(logical_expr) = &mut b { if logical_expr.operator == op { - let right = ctx.ast.move_expression(&mut logical_expr.left); + let right = logical_expr.left.take_in(ctx.ast.allocator); a = self.join_with_left_associative_op(span, op, a, right, ctx); - b = ctx.ast.move_expression(&mut logical_expr.right); + b = logical_expr.right.take_in(ctx.ast.allocator); continue; } } @@ -152,9 +153,9 @@ impl<'a> PeepholeOptimizations { _ => return None, } Some(if b.value { - ctx.ast.move_expression(&mut e.left) + e.left.take_in(ctx.ast.allocator) } else { - let argument = ctx.ast.move_expression(&mut e.left); + let argument = e.left.take_in(ctx.ast.allocator); ctx.ast.expression_unary(e.span, UnaryOperator::LogicalNot, argument) }) } @@ -249,7 +250,7 @@ impl<'a> PeepholeOptimizations { let new_op = logical_expr.operator.to_assignment_operator(); expr.operator = new_op; - expr.right = ctx.ast.move_expression(&mut logical_expr.right); + expr.right = logical_expr.right.take_in(ctx.ast.allocator); true } @@ -271,7 +272,7 @@ impl<'a> PeepholeOptimizations { } expr.operator = new_op; - expr.right = ctx.ast.move_expression(&mut binary_expr.right); + expr.right = binary_expr.right.take_in(ctx.ast.allocator); true } diff --git a/crates/oxc_minifier/src/peephole/minimize_expression_in_boolean_context.rs b/crates/oxc_minifier/src/peephole/minimize_expression_in_boolean_context.rs index a5bc3c2d19c09..be7a9e999fc56 100644 --- a/crates/oxc_minifier/src/peephole/minimize_expression_in_boolean_context.rs +++ b/crates/oxc_minifier/src/peephole/minimize_expression_in_boolean_context.rs @@ -1,3 +1,4 @@ +use oxc_allocator::TakeIn; use oxc_ast::ast::*; use oxc_ecmascript::constant_evaluation::{ConstantEvaluation, IsInt32OrUint32}; use oxc_span::GetSpan; @@ -34,7 +35,7 @@ impl<'a> PeepholeOptimizations { Expression::UnaryExpression(u1) if u1.operator.is_not() => { if let Expression::UnaryExpression(u2) = &mut u1.argument { if u2.operator.is_not() { - let mut e = ctx.ast.move_expression(&mut u2.argument); + let mut e = u2.argument.take_in(ctx.ast.allocator); self.try_fold_expr_in_boolean_context(&mut e, ctx); *expr = e; return true; @@ -46,7 +47,7 @@ impl<'a> PeepholeOptimizations { && matches!(&e.right, Expression::NumericLiteral(lit) if lit.value == 0.0) && e.left.is_int32_or_uint32(&ctx) => { - let argument = ctx.ast.move_expression(&mut e.left); + let argument = e.left.take_in(ctx.ast.allocator); *expr = if matches!( e.operator, BinaryOperator::StrictInequality | BinaryOperator::Inequality @@ -65,7 +66,7 @@ impl<'a> PeepholeOptimizations { self.try_fold_expr_in_boolean_context(&mut e.right, ctx); // "if (anything && truthyNoSideEffects)" => "if (anything)" if e.right.get_side_free_boolean_value(&ctx) == Some(true) { - *expr = ctx.ast.move_expression(&mut e.left); + *expr = e.left.take_in(ctx.ast.allocator); return true; } } @@ -75,7 +76,7 @@ impl<'a> PeepholeOptimizations { self.try_fold_expr_in_boolean_context(&mut e.right, ctx); // "if (anything || falsyNoSideEffects)" => "if (anything)" if e.right.get_side_free_boolean_value(&ctx) == Some(false) { - *expr = ctx.ast.move_expression(&mut e.left); + *expr = e.left.take_in(ctx.ast.allocator); return true; } } @@ -84,8 +85,8 @@ impl<'a> PeepholeOptimizations { self.try_fold_expr_in_boolean_context(&mut e.consequent, ctx); self.try_fold_expr_in_boolean_context(&mut e.alternate, ctx); if let Some(boolean) = e.consequent.get_side_free_boolean_value(&ctx) { - let right = ctx.ast.move_expression(&mut e.alternate); - let left = ctx.ast.move_expression(&mut e.test); + let right = e.alternate.take_in(ctx.ast.allocator); + let left = e.test.take_in(ctx.ast.allocator); let span = e.span; let (op, left) = if boolean { // "if (anything1 ? truthyNoSideEffects : anything2)" => "if (anything1 || anything2)" @@ -98,8 +99,8 @@ impl<'a> PeepholeOptimizations { return true; } if let Some(boolean) = e.alternate.get_side_free_boolean_value(&ctx) { - let left = ctx.ast.move_expression(&mut e.test); - let right = ctx.ast.move_expression(&mut e.consequent); + let left = e.test.take_in(ctx.ast.allocator); + let right = e.consequent.take_in(ctx.ast.allocator); let span = e.span; let (op, left) = if boolean { // "if (anything1 ? anything2 : truthyNoSideEffects)" => "if (!anything1 || anything2)" diff --git a/crates/oxc_minifier/src/peephole/minimize_for_statement.rs b/crates/oxc_minifier/src/peephole/minimize_for_statement.rs index 1413e974129fe..98c779a74d086 100644 --- a/crates/oxc_minifier/src/peephole/minimize_for_statement.rs +++ b/crates/oxc_minifier/src/peephole/minimize_for_statement.rs @@ -1,3 +1,4 @@ +use oxc_allocator::TakeIn; use oxc_ast::ast::*; use oxc_span::GetSpan; @@ -36,9 +37,9 @@ impl<'a> PeepholeOptimizations { } let span = for_stmt.body.span(); - let (first, body) = match ctx.ast.move_statement(&mut for_stmt.body) { + let (first, body) = match for_stmt.body.take_in(ctx.ast.allocator) { Statement::BlockStatement(mut block_stmt) => ( - ctx.ast.move_statement(block_stmt.body.get_mut(0).unwrap()), + block_stmt.body.get_mut(0).unwrap().take_in(ctx.ast.allocator), Some(Statement::BlockStatement(block_stmt)), ), stmt => (stmt, None), @@ -46,7 +47,7 @@ impl<'a> PeepholeOptimizations { let Statement::IfStatement(mut if_stmt) = first else { unreachable!() }; - let expr = match ctx.ast.move_expression(&mut if_stmt.test) { + let expr = match if_stmt.test.take_in(ctx.ast.allocator) { Expression::UnaryExpression(unary_expr) if unary_expr.operator.is_not() => { unary_expr.unbox().argument } @@ -54,7 +55,7 @@ impl<'a> PeepholeOptimizations { }; if let Some(test) = &mut for_stmt.test { - let left = ctx.ast.move_expression(test); + let left = test.take_in(ctx.ast.allocator); let mut logical_expr = ctx.ast.logical_expression(test.span(), left, LogicalOperator::And, expr); *test = Self::try_fold_and_or(&mut logical_expr, ctx) @@ -78,9 +79,9 @@ impl<'a> PeepholeOptimizations { } let span = for_stmt.body.span(); - let (first, body) = match ctx.ast.move_statement(&mut for_stmt.body) { + let (first, body) = match for_stmt.body.take_in(ctx.ast.allocator) { Statement::BlockStatement(mut block_stmt) => ( - ctx.ast.move_statement(block_stmt.body.get_mut(0).unwrap()), + block_stmt.body.get_mut(0).unwrap().take_in(ctx.ast.allocator), Some(Statement::BlockStatement(block_stmt)), ), stmt => (stmt, None), @@ -88,10 +89,10 @@ impl<'a> PeepholeOptimizations { let Statement::IfStatement(mut if_stmt) = first else { unreachable!() }; - let expr = ctx.ast.move_expression(&mut if_stmt.test); + let expr = if_stmt.test.take_in(ctx.ast.allocator); if let Some(test) = &mut for_stmt.test { - let left = ctx.ast.move_expression(test); + let left = test.take_in(ctx.ast.allocator); let mut logical_expr = ctx.ast.logical_expression(test.span(), left, LogicalOperator::And, expr); *test = Self::try_fold_and_or(&mut logical_expr, ctx) @@ -100,7 +101,7 @@ impl<'a> PeepholeOptimizations { for_stmt.test = Some(expr); } - let consequent = ctx.ast.move_statement(&mut if_stmt.consequent); + let consequent = if_stmt.consequent.take_in(ctx.ast.allocator); for_stmt.body = Self::drop_first_statement(span, body, Some(consequent), ctx); state.changed = true; } @@ -119,7 +120,7 @@ impl<'a> PeepholeOptimizations { } else if block_stmt.body.len() == 2 && !Self::statement_cares_about_scope(&block_stmt.body[1]) { - return ctx.ast.move_statement(&mut block_stmt.body[1]); + return block_stmt.body[1].take_in(ctx.ast.allocator); } else { block_stmt.body.remove(0); } diff --git a/crates/oxc_minifier/src/peephole/minimize_if_statement.rs b/crates/oxc_minifier/src/peephole/minimize_if_statement.rs index d70909ebc6c01..f4cabd7d8ea43 100644 --- a/crates/oxc_minifier/src/peephole/minimize_if_statement.rs +++ b/crates/oxc_minifier/src/peephole/minimize_if_statement.rs @@ -1,3 +1,4 @@ +use oxc_allocator::TakeIn; use oxc_ast::ast::*; use oxc_semantic::ScopeId; @@ -26,17 +27,17 @@ impl<'a> PeepholeOptimizations { // "if (a) b();" => "a && b();" e => (LogicalOperator::And, e), }; - let a = ctx.ast.move_expression(e); - let b = ctx.ast.move_expression(&mut expr_stmt.expression); + let a = e.take_in(ctx.ast.allocator); + let b = expr_stmt.expression.take_in(ctx.ast.allocator); let expr = self.join_with_left_associative_op(if_stmt.span, op, a, b, ctx); return Some(ctx.ast.statement_expression(if_stmt.span, expr)); } else if let Some(Statement::ExpressionStatement(alternate_expr_stmt)) = &mut if_stmt.alternate { // "if (a) b(); else c();" => "a ? b() : c();" - let test = ctx.ast.move_expression(&mut if_stmt.test); - let consequent = ctx.ast.move_expression(&mut expr_stmt.expression); - let alternate = ctx.ast.move_expression(&mut alternate_expr_stmt.expression); + let test = if_stmt.test.take_in(ctx.ast.allocator); + let consequent = expr_stmt.expression.take_in(ctx.ast.allocator); + let alternate = alternate_expr_stmt.expression.take_in(ctx.ast.allocator); let expr = self.minimize_conditional(if_stmt.span, test, consequent, alternate, ctx); return Some(ctx.ast.statement_expression(if_stmt.span, expr)); @@ -46,7 +47,7 @@ impl<'a> PeepholeOptimizations { || if_stmt.alternate.as_ref().is_some_and(Self::is_statement_empty) { // "if (a) {}" => "a;" - let mut expr = ctx.ast.move_expression(&mut if_stmt.test); + let mut expr = if_stmt.test.take_in(ctx.ast.allocator); self.remove_unused_expression(&mut expr, state, ctx); return Some(ctx.ast.statement_expression(if_stmt.span, expr)); } else if let Some(Statement::ExpressionStatement(expr_stmt)) = &mut if_stmt.alternate { @@ -58,8 +59,8 @@ impl<'a> PeepholeOptimizations { // "if (a) {} else b();" => "a || b();" e => (LogicalOperator::Or, e), }; - let a = ctx.ast.move_expression(e); - let b = ctx.ast.move_expression(&mut expr_stmt.expression); + let a = e.take_in(ctx.ast.allocator); + let b = expr_stmt.expression.take_in(ctx.ast.allocator); let expr = self.join_with_left_associative_op(if_stmt.span, op, a, b, ctx); return Some(ctx.ast.statement_expression(if_stmt.span, expr)); } else if let Some(stmt) = &mut if_stmt.alternate { @@ -67,8 +68,8 @@ impl<'a> PeepholeOptimizations { match &mut if_stmt.test { // "if (!a) {} else return b;" => "if (a) return b;" Expression::UnaryExpression(unary_expr) if unary_expr.operator.is_not() => { - if_stmt.test = ctx.ast.move_expression(&mut unary_expr.argument); - if_stmt.consequent = ctx.ast.move_statement(stmt); + if_stmt.test = unary_expr.argument.take_in(ctx.ast.allocator); + if_stmt.consequent = stmt.take_in(ctx.ast.allocator); if_stmt.alternate = None; state.changed = true; } @@ -76,10 +77,10 @@ impl<'a> PeepholeOptimizations { _ => { if_stmt.test = self.minimize_not( if_stmt.test.span(), - ctx.ast.move_expression(&mut if_stmt.test), + if_stmt.test.take_in(ctx.ast.allocator), ctx, ); - if_stmt.consequent = ctx.ast.move_statement(stmt); + if_stmt.consequent = stmt.take_in(ctx.ast.allocator); if_stmt.alternate = None; self.try_minimize_if(if_stmt, state, ctx); state.changed = true; @@ -93,7 +94,7 @@ impl<'a> PeepholeOptimizations { if let Expression::UnaryExpression(unary_expr) = &mut if_stmt.test { if unary_expr.operator.is_not() { // "if (!a) return b; else return c;" => "if (a) return c; else return b;" - if_stmt.test = ctx.ast.move_expression(&mut unary_expr.argument); + if_stmt.test = unary_expr.argument.take_in(ctx.ast.allocator); std::mem::swap(&mut if_stmt.consequent, alternate); self.wrap_to_avoid_ambiguous_else(if_stmt, state, ctx); state.changed = true; @@ -105,8 +106,8 @@ impl<'a> PeepholeOptimizations { if let Statement::IfStatement(if2_stmt) = &mut if_stmt.consequent { if if2_stmt.alternate.is_none() { // "if (a) if (b) return c;" => "if (a && b) return c;" - let a = ctx.ast.move_expression(&mut if_stmt.test); - let b = ctx.ast.move_expression(&mut if2_stmt.test); + let a = if_stmt.test.take_in(ctx.ast.allocator); + let b = if2_stmt.test.take_in(ctx.ast.allocator); if_stmt.test = self.join_with_left_associative_op( if_stmt.test.span(), LogicalOperator::And, @@ -114,7 +115,7 @@ impl<'a> PeepholeOptimizations { b, ctx, ); - if_stmt.consequent = ctx.ast.move_statement(&mut if2_stmt.consequent); + if_stmt.consequent = if2_stmt.consequent.take_in(ctx.ast.allocator); state.changed = true; } } @@ -138,7 +139,7 @@ impl<'a> PeepholeOptimizations { if_stmt.consequent = Statement::BlockStatement(ctx.ast.alloc( ctx.ast.block_statement_with_scope_id( if_stmt.consequent.span(), - ctx.ast.vec1(ctx.ast.move_statement(&mut if_stmt.consequent)), + ctx.ast.vec1(if_stmt.consequent.take_in(ctx.ast.allocator)), scope_id, ), )); diff --git a/crates/oxc_minifier/src/peephole/minimize_logical_expression.rs b/crates/oxc_minifier/src/peephole/minimize_logical_expression.rs index 27b74f9370b3e..04be3e5d9a91a 100644 --- a/crates/oxc_minifier/src/peephole/minimize_logical_expression.rs +++ b/crates/oxc_minifier/src/peephole/minimize_logical_expression.rs @@ -1,3 +1,4 @@ +use oxc_allocator::TakeIn; use oxc_ast::ast::*; use oxc_span::{ContentEq, GetSpan}; use oxc_syntax::es_target::ESTarget; @@ -64,7 +65,7 @@ impl<'a> PeepholeOptimizations { .map(|new_expr| { ctx.ast.expression_logical( expr.span, - ctx.ast.move_expression(&mut left.left), + left.left.take_in(ctx.ast.allocator), expr.operator, new_expr, ) @@ -141,7 +142,7 @@ impl<'a> PeepholeOptimizations { }; Some(ctx.ast.expression_binary( span, - ctx.ast.move_expression(left_non_value_expr), + left_non_value_expr.take_in(ctx.ast.allocator), replace_op, ctx.ast.expression_null_literal(null_expr_span), )) @@ -225,6 +226,6 @@ impl<'a> PeepholeOptimizations { } assignment_expr.span = expr.span; assignment_expr.operator = new_op; - Some(ctx.ast.move_expression(&mut expr.right)) + Some(expr.right.take_in(ctx.ast.allocator)) } } diff --git a/crates/oxc_minifier/src/peephole/minimize_not_expression.rs b/crates/oxc_minifier/src/peephole/minimize_not_expression.rs index 89cbe76c3c2dd..07823b8dfddb1 100644 --- a/crates/oxc_minifier/src/peephole/minimize_not_expression.rs +++ b/crates/oxc_minifier/src/peephole/minimize_not_expression.rs @@ -1,3 +1,4 @@ +use oxc_allocator::TakeIn; use oxc_ast::ast::*; use oxc_ecmascript::constant_evaluation::DetermineValueType; use oxc_span::GetSpan; @@ -34,7 +35,7 @@ impl<'a> PeepholeOptimizations { Expression::UnaryExpression(e) if e.operator.is_not() && e.argument.value_type(&ctx).is_boolean() => { - Some(ctx.ast.move_expression(&mut e.argument)) + Some(e.argument.take_in(ctx.ast.allocator)) } // `!(a == b)` => `a != b` // `!(a != b)` => `a == b` @@ -42,17 +43,17 @@ impl<'a> PeepholeOptimizations { // `!(a !== b)` => `a === b` Expression::BinaryExpression(e) if e.operator.is_equality() => { e.operator = e.operator.equality_inverse_operator().unwrap(); - Some(ctx.ast.move_expression(&mut expr.argument)) + Some(expr.argument.take_in(ctx.ast.allocator)) } // "!(a, b)" => "a, !b" Expression::SequenceExpression(sequence_expr) => { if let Some(last_expr) = sequence_expr.expressions.last_mut() { *last_expr = self.minimize_not( last_expr.span(), - ctx.ast.move_expression(last_expr), + last_expr.take_in(ctx.ast.allocator), ctx, ); - return Some(ctx.ast.move_expression(&mut expr.argument)); + return Some(expr.argument.take_in(ctx.ast.allocator)); } None } diff --git a/crates/oxc_minifier/src/peephole/minimize_statements.rs b/crates/oxc_minifier/src/peephole/minimize_statements.rs index 8183e33316f19..eedbb7908de57 100644 --- a/crates/oxc_minifier/src/peephole/minimize_statements.rs +++ b/crates/oxc_minifier/src/peephole/minimize_statements.rs @@ -1,6 +1,6 @@ use std::ops::ControlFlow; -use oxc_allocator::{Box, Vec}; +use oxc_allocator::{Box, TakeIn, Vec}; use oxc_ast::ast::*; use oxc_ast_visit::Visit; use oxc_ecmascript::side_effects::MayHaveSideEffects; @@ -41,7 +41,7 @@ impl<'a> PeepholeOptimizations { let mut keep_var = KeepVar::new(ctx.ast); let mut new_stmts = ctx.ast.vec_from_iter(stmts.drain(..)); for i in 0..new_stmts.len() { - let stmt = ctx.ast.move_statement(&mut new_stmts[i]); + let stmt = new_stmts[i].take_in(ctx.ast.allocator); if is_control_flow_dead && !stmt.is_module_declaration() && !matches!(stmt.as_declaration(), Some(Declaration::FunctionDeclaration(_))) @@ -158,8 +158,7 @@ impl<'a> PeepholeOptimizations { // "if (!a) return b; return c;" => "return a ? c : b;" if let Expression::UnaryExpression(unary_expr) = &mut prev_if.test { if unary_expr.operator.is_not() { - prev_if.test = - ctx.ast.move_expression(&mut unary_expr.argument); + prev_if.test = unary_expr.argument.take_in(ctx.ast.allocator); std::mem::swap(&mut left, &mut right); } } @@ -176,7 +175,7 @@ impl<'a> PeepholeOptimizations { // "if (a) return b; return c;" => "return a ? b : c;" let mut expr = self.minimize_conditional( prev_if.span, - ctx.ast.move_expression(&mut prev_if.test), + prev_if.test.take_in(ctx.ast.allocator), left, right, ctx, @@ -246,8 +245,7 @@ impl<'a> PeepholeOptimizations { // "if (!a) throw b; throw c;" => "throw a ? c : b;" if let Expression::UnaryExpression(unary_expr) = &mut prev_if.test { if unary_expr.operator.is_not() { - prev_if.test = - ctx.ast.move_expression(&mut unary_expr.argument); + prev_if.test = unary_expr.argument.take_in(ctx.ast.allocator); std::mem::swap(&mut left, &mut right); } } @@ -264,7 +262,7 @@ impl<'a> PeepholeOptimizations { // "if (a) throw b; throw c;" => "throw a ? b : c;" let mut expr = self.minimize_conditional( prev_if.span, - ctx.ast.move_expression(&mut prev_if.test), + prev_if.test.take_in(ctx.ast.allocator), left, right, ctx, @@ -344,8 +342,8 @@ impl<'a> PeepholeOptimizations { b: &mut Expression<'a>, ctx: Ctx<'a, '_>, ) -> Expression<'a> { - let a = ctx.ast.move_expression(a); - let b = ctx.ast.move_expression(b); + let a = a.take_in(ctx.ast.allocator); + let b = b.take_in(ctx.ast.allocator); if let Expression::SequenceExpression(mut sequence_expr) = a { // `(a, b); c` sequence_expr.expressions.push(b); @@ -451,8 +449,8 @@ impl<'a> PeepholeOptimizations { if_stmt.test = self.join_with_left_associative_op( if_stmt.test.span(), LogicalOperator::Or, - ctx.ast.move_expression(&mut prev_if_stmt.test), - ctx.ast.move_expression(&mut if_stmt.test), + prev_if_stmt.test.take_in(ctx.ast.allocator), + if_stmt.test.take_in(ctx.ast.allocator), ctx, ); result.pop(); @@ -519,7 +517,7 @@ impl<'a> PeepholeOptimizations { self.minimize_statements(&mut body, state, ctx); let span = if body.is_empty() { if_stmt.consequent.span() } else { body[0].span() }; - let test = ctx.ast.move_expression(&mut if_stmt.test); + let test = if_stmt.test.take_in(ctx.ast.allocator); let mut test = self.minimize_not(test.span(), test, ctx); self.try_fold_expr_in_boolean_context(&mut test, ctx); let consequent = if body.len() == 1 { @@ -624,7 +622,7 @@ impl<'a> PeepholeOptimizations { } } else { for_stmt.init = Some(ForStatementInit::from( - ctx.ast.move_expression(&mut prev_expr_stmt.expression), + prev_expr_stmt.expression.take_in(ctx.ast.allocator), )); result.pop(); state.changed = true; @@ -644,9 +642,9 @@ impl<'a> PeepholeOptimizations { } } } else if prev_var_decl.kind.is_var() { - let var_decl = ctx.ast.move_variable_declaration(prev_var_decl); - for_stmt.init = - Some(ForStatementInit::VariableDeclaration(ctx.ast.alloc(var_decl))); + for_stmt.init = Some(ForStatementInit::VariableDeclaration( + prev_var_decl.take_in_box(ctx.ast.allocator), + )); result.pop(); state.changed = true; } @@ -712,7 +710,7 @@ impl<'a> PeepholeOptimizations { { if id.name == decl_id.name { for_in_stmt.left = ForStatementLeft::VariableDeclaration( - ctx.ast.alloc(ctx.ast.move_variable_declaration(prev_var_decl)), + prev_var_decl.take_in_box(ctx.ast.allocator), ); result.pop(); state.changed = true; @@ -752,7 +750,7 @@ impl<'a> PeepholeOptimizations { { if id.name == decl_id.name { for_of_stmt.left = ForStatementLeft::VariableDeclaration( - ctx.ast.alloc(ctx.ast.move_variable_declaration(prev_var_decl)), + prev_var_decl.take_in_box(ctx.ast.allocator), ); result.pop(); state.changed = true; diff --git a/crates/oxc_minifier/src/peephole/normalize.rs b/crates/oxc_minifier/src/peephole/normalize.rs index e3c087e98a213..70136b9c5bc0f 100644 --- a/crates/oxc_minifier/src/peephole/normalize.rs +++ b/crates/oxc_minifier/src/peephole/normalize.rs @@ -1,4 +1,4 @@ -use oxc_allocator::Vec; +use oxc_allocator::{TakeIn, Vec}; use oxc_ast::ast::*; use oxc_semantic::IsGlobalReference; use oxc_span::GetSpan; @@ -72,7 +72,7 @@ impl<'a> Traverse<'a> for Normalize { fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { if let Expression::ParenthesizedExpression(paren_expr) = expr { - *expr = ctx.ast.move_expression(&mut paren_expr.expression); + *expr = paren_expr.expression.take_in(ctx.ast.allocator); } if let Some(e) = match expr { Expression::Identifier(ident) => Self::try_compress_identifier(ident, ctx), @@ -143,7 +143,7 @@ impl<'a> Normalize { } fn convert_while_to_for(stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) { - let Statement::WhileStatement(while_stmt) = ctx.ast.move_statement(stmt) else { return }; + let Statement::WhileStatement(while_stmt) = stmt.take_in(ctx.ast.allocator) else { return }; let while_stmt = while_stmt.unbox(); let for_stmt = ctx.ast.alloc_for_statement_with_scope_id( while_stmt.span, diff --git a/crates/oxc_minifier/src/peephole/remove_dead_code.rs b/crates/oxc_minifier/src/peephole/remove_dead_code.rs index a19fc6c766373..c967bd0dda2c7 100644 --- a/crates/oxc_minifier/src/peephole/remove_dead_code.rs +++ b/crates/oxc_minifier/src/peephole/remove_dead_code.rs @@ -1,4 +1,4 @@ -use oxc_allocator::Vec; +use oxc_allocator::{TakeIn, Vec}; use oxc_ast::ast::*; use oxc_ast_visit::Visit; use oxc_ecmascript::{constant_evaluation::ConstantEvaluation, side_effects::MayHaveSideEffects}; @@ -224,19 +224,24 @@ impl<'a, 'b> PeepholeOptimizations { if_stmt.consequent = ctx.ast.statement_empty(if_stmt.consequent.span()); } } - return Some(ctx.ast.statement_if( - if_stmt.span, - ctx.ast.move_expression(&mut if_stmt.test), - ctx.ast.move_statement(&mut if_stmt.consequent), - if_stmt.alternate.as_mut().map(|alternate| ctx.ast.move_statement(alternate)), - )); + return Some( + ctx.ast.statement_if( + if_stmt.span, + if_stmt.test.take_in(ctx.ast.allocator), + if_stmt.consequent.take_in(ctx.ast.allocator), + if_stmt + .alternate + .as_mut() + .map(|alternate| alternate.take_in(ctx.ast.allocator)), + ), + ); } return Some(if boolean { - ctx.ast.move_statement(&mut if_stmt.consequent) + if_stmt.consequent.take_in(ctx.ast.allocator) } else { if_stmt.alternate.as_mut().map_or_else( || ctx.ast.statement_empty(if_stmt.span), - |alternate| ctx.ast.move_statement(alternate), + |alternate| alternate.take_in(ctx.ast.allocator), ) }); } @@ -279,10 +284,9 @@ impl<'a, 'b> PeepholeOptimizations { if let Some(var_decl) = &mut var_decl { var_decl .declarations - .splice(0..0, ctx.ast.move_vec(&mut var_init.declarations)); + .splice(0..0, var_init.declarations.take_in(ctx.ast.allocator)); } else { - var_decl = - Some(ctx.ast.alloc(ctx.ast.move_variable_declaration(var_init))); + var_decl = Some(var_init.take_in_box(ctx.ast.allocator)); } } Some(var_decl.map_or_else( @@ -400,23 +404,23 @@ impl<'a, 'b> PeepholeOptimizations { // "(a, true) ? b : c" => "a, b" let exprs = ctx.ast.vec_from_array([ { - let mut test = ctx.ast.move_expression(&mut expr.test); + let mut test = expr.test.take_in(ctx.ast.allocator); self.remove_unused_expression(&mut test, state, ctx); test }, - ctx.ast.move_expression(if v { - &mut expr.consequent + if v { + expr.consequent.take_in(ctx.ast.allocator) } else { - &mut expr.alternate - }), + expr.alternate.take_in(ctx.ast.allocator) + }, ]); ctx.ast.expression_sequence(expr.span, exprs) } else { - let result_expr = ctx.ast.move_expression(if v { - &mut expr.consequent + let result_expr = if v { + expr.consequent.take_in(ctx.ast.allocator) } else { - &mut expr.alternate - }); + expr.alternate.take_in(ctx.ast.allocator) + }; let should_keep_as_sequence_expr = Self::should_keep_indirect_access(&result_expr, ctx); diff --git a/crates/oxc_minifier/src/peephole/remove_unused_expression.rs b/crates/oxc_minifier/src/peephole/remove_unused_expression.rs index b725ecba865d1..048b9034a7535 100644 --- a/crates/oxc_minifier/src/peephole/remove_unused_expression.rs +++ b/crates/oxc_minifier/src/peephole/remove_unused_expression.rs @@ -1,6 +1,6 @@ use std::iter; -use oxc_allocator::Vec; +use oxc_allocator::{TakeIn, Vec}; use oxc_ast::ast::*; use oxc_ecmascript::{ ToPrimitive, @@ -46,7 +46,7 @@ impl<'a> PeepholeOptimizations { let Expression::UnaryExpression(unary_expr) = e else { return false }; match unary_expr.operator { UnaryOperator::Void | UnaryOperator::LogicalNot => { - *e = ctx.ast.move_expression(&mut unary_expr.argument); + *e = unary_expr.argument.take_in(ctx.ast.allocator); state.changed = true; self.remove_unused_expression(e, state, ctx) } @@ -54,7 +54,7 @@ impl<'a> PeepholeOptimizations { if unary_expr.argument.is_identifier_reference() { true } else { - *e = ctx.ast.move_expression(&mut unary_expr.argument); + *e = unary_expr.argument.take_in(ctx.ast.allocator); state.changed = true; self.remove_unused_expression(e, state, ctx) } @@ -94,7 +94,7 @@ impl<'a> PeepholeOptimizations { } if self.remove_unused_expression(&mut logical_expr.right, state, ctx) { self.remove_unused_expression(&mut logical_expr.left, state, ctx); - *e = ctx.ast.move_expression(&mut logical_expr.left); + *e = logical_expr.left.take_in(ctx.ast.allocator); state.changed = true; return false; } @@ -129,7 +129,7 @@ impl<'a> PeepholeOptimizations { logical_right, ctx, ) { - *e = ctx.ast.move_expression(logical_right); + *e = logical_right.take_in(ctx.ast.allocator); state.changed = true; return false; } @@ -160,7 +160,7 @@ impl<'a> PeepholeOptimizations { { assignment_expr.span = *logical_span; assignment_expr.operator = AssignmentOperator::LogicalNullish; - *e = ctx.ast.move_expression(logical_right); + *e = logical_right.take_in(ctx.ast.allocator); state.changed = true; return false; } @@ -168,9 +168,9 @@ impl<'a> PeepholeOptimizations { *e = ctx.ast.expression_logical( *logical_span, - ctx.ast.move_expression(new_left_hand_expr), + new_left_hand_expr.take_in(ctx.ast.allocator), LogicalOperator::Coalesce, - ctx.ast.move_expression(logical_right), + logical_right.take_in(ctx.ast.allocator), ); state.changed = true; return false; @@ -490,7 +490,7 @@ impl<'a> PeepholeOptimizations { if test { return true; } - *e = ctx.ast.move_expression(&mut conditional_expr.test); + *e = conditional_expr.test.take_in(ctx.ast.allocator); state.changed = true; return false; } @@ -500,8 +500,8 @@ impl<'a> PeepholeOptimizations { *e = self.join_with_left_associative_op( conditional_expr.span, LogicalOperator::Or, - ctx.ast.move_expression(&mut conditional_expr.test), - ctx.ast.move_expression(&mut conditional_expr.alternate), + conditional_expr.test.take_in(ctx.ast.allocator), + conditional_expr.alternate.take_in(ctx.ast.allocator), ctx, ); state.changed = true; @@ -513,8 +513,8 @@ impl<'a> PeepholeOptimizations { *e = self.join_with_left_associative_op( conditional_expr.span, LogicalOperator::And, - ctx.ast.move_expression(&mut conditional_expr.test), - ctx.ast.move_expression(&mut conditional_expr.consequent), + conditional_expr.test.take_in(ctx.ast.allocator), + conditional_expr.consequent.take_in(ctx.ast.allocator), ctx, ); state.changed = true; @@ -548,12 +548,12 @@ impl<'a> PeepholeOptimizations { match (left, right) { (true, true) => true, (true, false) => { - *e = ctx.ast.move_expression(&mut binary_expr.right); + *e = binary_expr.right.take_in(ctx.ast.allocator); state.changed = true; false } (false, true) => { - *e = ctx.ast.move_expression(&mut binary_expr.left); + *e = binary_expr.left.take_in(ctx.ast.allocator); state.changed = true; false } @@ -561,8 +561,8 @@ impl<'a> PeepholeOptimizations { *e = ctx.ast.expression_sequence( binary_expr.span, ctx.ast.vec_from_array([ - ctx.ast.move_expression(&mut binary_expr.left), - ctx.ast.move_expression(&mut binary_expr.right), + binary_expr.left.take_in(ctx.ast.allocator), + binary_expr.right.take_in(ctx.ast.allocator), ]), ); state.changed = true; @@ -605,7 +605,7 @@ impl<'a> PeepholeOptimizations { if right_as_primitive.is_symbol() == Some(false) && !binary_expr.right.may_have_side_effects(&ctx) { - *e = ctx.ast.move_expression(&mut binary_expr.left); + *e = binary_expr.left.take_in(ctx.ast.allocator); state.changed = true; return true; } @@ -666,19 +666,19 @@ impl<'a> PeepholeOptimizations { if f.expression { // Replace "(() => foo())()" with "foo()" let expr = f.get_expression_mut().unwrap(); - *e = ctx.ast.move_expression(expr); + *e = expr.take_in(ctx.ast.allocator); return self.remove_unused_expression(e, state, ctx); } match &mut f.body.statements[0] { Statement::ExpressionStatement(expr_stmt) => { // Replace "(() => { foo() })" with "foo()" - *e = ctx.ast.move_expression(&mut expr_stmt.expression); + *e = expr_stmt.expression.take_in(ctx.ast.allocator); return self.remove_unused_expression(e, state, ctx); } Statement::ReturnStatement(ret_stmt) => { if let Some(argument) = &mut ret_stmt.argument { // Replace "(() => { return foo() })" with "foo()" - *e = ctx.ast.move_expression(argument); + *e = argument.take_in(ctx.ast.allocator); return self.remove_unused_expression(e, state, ctx); } // Replace "(() => { return })" with "" diff --git a/crates/oxc_minifier/src/peephole/replace_known_methods.rs b/crates/oxc_minifier/src/peephole/replace_known_methods.rs index b8bf1a540e5cb..f2bd42931396c 100644 --- a/crates/oxc_minifier/src/peephole/replace_known_methods.rs +++ b/crates/oxc_minifier/src/peephole/replace_known_methods.rs @@ -1,7 +1,7 @@ use cow_utils::CowUtils; use std::borrow::Cow; -use oxc_allocator::IntoIn; +use oxc_allocator::{IntoIn, TakeIn}; use oxc_ast::ast::*; use oxc_ecmascript::{ StringCharAt, StringCharAtResult, StringCharCodeAt, StringIndexOf, StringLastIndexOf, @@ -403,12 +403,12 @@ impl<'a> PeepholeOptimizations { let wrap_with_unary_plus_if_needed = |expr: &mut Expression<'a>| { if expr.value_type(&ctx).is_number() { - ctx.ast.move_expression(expr) + expr.take_in(ctx.ast.allocator) } else { ctx.ast.expression_unary( SPAN, UnaryOperator::UnaryPlus, - ctx.ast.move_expression(expr), + expr.take_in(ctx.ast.allocator), ) } }; @@ -416,7 +416,7 @@ impl<'a> PeepholeOptimizations { Some(ctx.ast.expression_binary( span, // see [`PeepholeOptimizations::is_binary_operator_that_does_number_conversion`] why it does not require `wrap_with_unary_plus_if_needed` here - ctx.ast.move_expression(first_arg), + first_arg.take_in(ctx.ast.allocator), BinaryOperator::Exponential, wrap_with_unary_plus_if_needed(second_arg), )) @@ -626,10 +626,13 @@ impl<'a> PeepholeOptimizations { *node = ctx.ast.expression_call( original_span, - ctx.ast.move_expression(new_root_callee), + new_root_callee.take_in(ctx.ast.allocator), Option::::None, ctx.ast.vec_from_iter( - collected_arguments.into_iter().rev().flat_map(|arg| ctx.ast.move_vec(arg)), + collected_arguments + .into_iter() + .rev() + .flat_map(|arg| arg.take_in(ctx.ast.allocator)), ), false, ); @@ -691,13 +694,13 @@ impl<'a> PeepholeOptimizations { } if args.is_empty() { - Some(ctx.ast.move_expression(object)) + Some(object.take_in(ctx.ast.allocator)) } else if can_merge_until.is_some() { Some(ctx.ast.expression_call( span, - ctx.ast.move_expression(callee), + callee.take_in(ctx.ast.allocator), Option::::None, - ctx.ast.move_vec(args), + args.take_in(ctx.ast.allocator), false, )) } else { @@ -974,7 +977,7 @@ impl<'a> PeepholeOptimizations { s.span = span; s.value = ctx.ast.atom(&c.to_string()); s.raw = None; - Some(ctx.ast.move_expression(object)) + Some(object.take_in(ctx.ast.allocator)) } else { None } diff --git a/crates/oxc_minifier/src/peephole/substitute_alternate_syntax.rs b/crates/oxc_minifier/src/peephole/substitute_alternate_syntax.rs index 591d22c8ce115..679ba98fba926 100644 --- a/crates/oxc_minifier/src/peephole/substitute_alternate_syntax.rs +++ b/crates/oxc_minifier/src/peephole/substitute_alternate_syntax.rs @@ -1,6 +1,6 @@ use std::iter::repeat_with; -use oxc_allocator::{CloneIn, Vec}; +use oxc_allocator::{CloneIn, TakeIn, Vec}; use oxc_ast::{NONE, ast::*}; use oxc_ecmascript::constant_evaluation::DetermineValueType; use oxc_ecmascript::{ToJsString, ToNumber, side_effects::MayHaveSideEffects}; @@ -245,7 +245,7 @@ impl<'a> PeepholeOptimizations { if let Some(body) = arrow_expr.body.statements.first_mut() { if let Statement::ReturnStatement(ret_stmt) = body { let return_stmt_arg = - ret_stmt.argument.as_mut().map(|arg| ctx.ast.move_expression(arg)); + ret_stmt.argument.as_mut().map(|arg| arg.take_in(ctx.ast.allocator)); if let Some(arg) = return_stmt_arg { *body = ctx.ast.statement_expression(arg.span(), arg); arrow_expr.expression = true; @@ -288,14 +288,13 @@ impl<'a> PeepholeOptimizations { }; if let Expression::Identifier(ident) = &unary_expr.argument { if ctx.is_global_reference(ident) { - let left = ctx.ast.move_expression(&mut expr.left); + let left = expr.left.take_in(ctx.ast.allocator); let right = ctx.ast.expression_string_literal(expr.right.span(), "u", None); return Some(ctx.ast.expression_binary(expr.span, left, new_comp_op, right)); } } - let Expression::UnaryExpression(unary_expr) = ctx.ast.move_expression(&mut expr.left) - else { + let Expression::UnaryExpression(unary_expr) = expr.left.take_in(ctx.ast.allocator) else { unreachable!() }; let right = ctx.ast.void_0(expr.right.span()); @@ -330,7 +329,7 @@ impl<'a> PeepholeOptimizations { return None; } - Some(ctx.ast.move_expression(&mut expr.argument)) + Some(expr.argument.take_in(ctx.ast.allocator)) } /// For `+a - n` => `a - n` (assuming n is a number) @@ -386,9 +385,9 @@ impl<'a> PeepholeOptimizations { let mut new_left = ctx.ast.expression_logical( expr.span, - ctx.ast.move_expression(&mut expr.left), + expr.left.take_in(ctx.ast.allocator), expr.operator, - ctx.ast.move_expression(&mut right.left), + right.left.take_in(ctx.ast.allocator), ); { @@ -402,7 +401,7 @@ impl<'a> PeepholeOptimizations { expr.span, new_left, expr.operator, - ctx.ast.move_expression(&mut right.right), + right.right.take_in(ctx.ast.allocator), )) } @@ -458,7 +457,7 @@ impl<'a> PeepholeOptimizations { .map(|new_expr| { ctx.ast.expression_logical( expr.span, - ctx.ast.move_expression(&mut left.left), + left.left.take_in(ctx.ast.allocator), expr.operator, new_expr, ) @@ -578,15 +577,9 @@ impl<'a> PeepholeOptimizations { // `foo != void 0` -> `foo == null`, `foo == undefined` -> `foo == null` if e.operator == BinaryOperator::Inequality || e.operator == BinaryOperator::Equality { let (left, right) = if ctx.is_expression_undefined(&e.right) { - ( - ctx.ast.move_expression(&mut e.left), - ctx.ast.expression_null_literal(e.right.span()), - ) + (e.left.take_in(ctx.ast.allocator), ctx.ast.expression_null_literal(e.right.span())) } else if ctx.is_expression_undefined(&e.left) { - ( - ctx.ast.move_expression(&mut e.right), - ctx.ast.expression_null_literal(e.left.span()), - ) + (e.right.take_in(ctx.ast.allocator), ctx.ast.expression_null_literal(e.left.span())) } else { return None; }; @@ -688,7 +681,7 @@ impl<'a> PeepholeOptimizations { "Boolean" => match arg { None => Some(ctx.ast.expression_boolean_literal(span, false)), Some(arg) => { - let mut arg = ctx.ast.move_expression(arg); + let mut arg = arg.take_in(ctx.ast.allocator); self.try_fold_expr_in_boolean_context(&mut arg, ctx); let arg = ctx.ast.expression_unary(span, UnaryOperator::LogicalNot, arg); Some(self.minimize_not(span, arg, ctx)) @@ -707,7 +700,7 @@ impl<'a> PeepholeOptimizations { span, ctx.ast.expression_string_literal(call_expr.span, "", None), BinaryOperator::Addition, - ctx.ast.move_expression(arg), + arg.take_in(ctx.ast.allocator), )) } } @@ -725,7 +718,7 @@ impl<'a> PeepholeOptimizations { "BigInt" => match arg { None => None, Some(arg) => matches!(arg, Expression::BigIntLiteral(_)) - .then(|| ctx.ast.move_expression(arg)), + .then(|| arg.take_in(ctx.ast.allocator)), }, _ => None, } @@ -797,28 +790,28 @@ impl<'a> PeepholeOptimizations { } } let callee = ctx.ast.expression_identifier(n.span, "Array"); - let args = ctx.ast.move_vec(args); + let args = args.take_in(ctx.ast.allocator); Some(ctx.ast.expression_call(span, callee, NONE, args, false)) } // `new Array(literal)` -> `[literal]` else if arg.is_literal() || matches!(arg, Expression::ArrayExpression(_)) { let elements = ctx .ast - .vec1(ArrayExpressionElement::from(ctx.ast.move_expression(arg))); + .vec1(ArrayExpressionElement::from(arg.take_in(ctx.ast.allocator))); Some(ctx.ast.expression_array(span, elements, None)) } // `new Array(x)` -> `Array(x)` else { let callee = ctx.ast.expression_identifier(span, "Array"); - let args = ctx.ast.move_vec(args); + let args = args.take_in(ctx.ast.allocator); Some(ctx.ast.expression_call(span, callee, NONE, args, false)) } } else { // // `new Array(1, 2, 3)` -> `[1, 2, 3]` let elements = ctx.ast.vec_from_iter( - args.iter_mut() - .filter_map(|arg| arg.as_expression_mut()) - .map(|arg| ArrayExpressionElement::from(ctx.ast.move_expression(arg))), + args.iter_mut().filter_map(|arg| arg.as_expression_mut()).map(|arg| { + ArrayExpressionElement::from(arg.take_in(ctx.ast.allocator)) + }), ); Some(ctx.ast.expression_array(span, elements, None)) } @@ -861,9 +854,9 @@ impl<'a> PeepholeOptimizations { } { Some(ctx.ast.expression_call( e.span, - ctx.ast.move_expression(&mut e.callee), + e.callee.take_in(ctx.ast.allocator), NONE, - ctx.ast.move_vec(&mut e.arguments), + e.arguments.take_in(ctx.ast.allocator), false, )) } else { @@ -988,7 +981,7 @@ impl<'a> PeepholeOptimizations { ArrayExpressionElement::SpreadElement(spread_el) => { new_args.push(ctx.ast.argument_spread_element( spread_el.span, - ctx.ast.move_expression(&mut spread_el.argument), + spread_el.argument.take_in(ctx.ast.allocator), )); } ArrayExpressionElement::Elision(elision) => { @@ -996,14 +989,14 @@ impl<'a> PeepholeOptimizations { } match_expression!(ArrayExpressionElement) => { new_args - .push(ctx.ast.move_expression(el.to_expression_mut()).into()); + .push(el.to_expression_mut().take_in(ctx.ast.allocator).into()); } } } } else { new_args.push(ctx.ast.argument_spread_element( spread_el.span, - ctx.ast.move_expression(&mut spread_el.argument), + spread_el.argument.take_in(ctx.ast.allocator), )); } } else { diff --git a/crates/oxc_parser/src/js/expression.rs b/crates/oxc_parser/src/js/expression.rs index f4998c9c9a778..1f57162e496af 100644 --- a/crates/oxc_parser/src/js/expression.rs +++ b/crates/oxc_parser/src/js/expression.rs @@ -1,5 +1,5 @@ use cow_utils::CowUtils; -use oxc_allocator::Box; +use oxc_allocator::{Box, TakeIn}; use oxc_ast::ast::*; use oxc_diagnostics::Result; #[cfg(feature = "regular_expression")] @@ -651,7 +651,7 @@ impl<'a> ParserImpl<'a> { if let Expression::TSInstantiationExpression(mut expr) = lhs { expr.expression = self.map_to_chain_expression( expr.expression.span(), - self.ast.move_expression(&mut expr.expression), + expr.expression.take_in(self.ast.allocator), ); Ok(Expression::TSInstantiationExpression(expr)) } else { diff --git a/crates/oxc_transformer/src/common/arrow_function_converter.rs b/crates/oxc_transformer/src/common/arrow_function_converter.rs index 7c7128373e9e3..8f1368ada0a2b 100644 --- a/crates/oxc_transformer/src/common/arrow_function_converter.rs +++ b/crates/oxc_transformer/src/common/arrow_function_converter.rs @@ -91,7 +91,7 @@ use compact_str::CompactString; use indexmap::IndexMap; use rustc_hash::{FxBuildHasher, FxHashSet}; -use oxc_allocator::{Box as ArenaBox, Vec as ArenaVec}; +use oxc_allocator::{Box as ArenaBox, TakeIn, Vec as ArenaVec}; use oxc_ast::{NONE, ast::*}; use oxc_ast_visit::{VisitMut, walk_mut::walk_expression}; use oxc_data_structures::stack::{NonEmptyStack, SparseStack}; @@ -420,7 +420,10 @@ impl<'a> Traverse<'a> for ArrowFunctionConverter<'a> { // prop = (() => { return async () => {} })(); // } // ``` - Some(wrap_expression_in_arrow_function_iife(ctx.ast.move_expression(expr), ctx)) + Some(wrap_expression_in_arrow_function_iife( + expr.take_in(ctx.ast.allocator), + ctx, + )) } else { return; } @@ -446,7 +449,7 @@ impl<'a> Traverse<'a> for ArrowFunctionConverter<'a> { } let Expression::ArrowFunctionExpression(arrow_function_expr) = - ctx.ast.move_expression(expr) + expr.take_in(ctx.ast.allocator) else { unreachable!() }; @@ -746,8 +749,8 @@ impl<'a> ArrowFunctionConverter<'a> { // The property will as a parameter to pass to the new arrow function. // `super[property]` to `_superprop_get(property)` - argument = Some(ctx.ast.move_expression(&mut computed_member.expression)); - ctx.ast.move_expression(&mut computed_member.object) + argument = Some(computed_member.expression.take_in(ctx.ast.allocator)); + computed_member.object.take_in(ctx.ast.allocator) } MemberExpression::StaticMemberExpression(static_member) => { if !static_member.object.is_super() { @@ -756,7 +759,7 @@ impl<'a> ArrowFunctionConverter<'a> { // Used to generate the name of the arrow function. property = static_member.property.name.as_str(); - ctx.ast.move_expression(expr) + expr.take_in(ctx.ast.allocator) } MemberExpression::PrivateFieldExpression(_) => { // Private fields can't be accessed by `super`. @@ -783,7 +786,7 @@ impl<'a> ArrowFunctionConverter<'a> { } // _value if let Some(assign_value) = assign_value { - arguments.push(Argument::from(ctx.ast.move_expression(assign_value))); + arguments.push(Argument::from(assign_value.take_in(ctx.ast.allocator))); } let call = ctx.ast.expression_call(SPAN, callee, NONE, arguments, false); Some(call) @@ -820,7 +823,7 @@ impl<'a> ArrowFunctionConverter<'a> { // Add `this` as the first argument and original arguments as the rest. let mut arguments = ctx.ast.vec_with_capacity(call.arguments.len() + 1); arguments.push(Argument::from(ctx.ast.expression_this(SPAN))); - arguments.extend(ctx.ast.move_vec(&mut call.arguments)); + arguments.extend(call.arguments.take_in(ctx.ast.allocator)); let property = ctx.ast.identifier_name(SPAN, "call"); let callee = ctx.ast.member_expression_static(SPAN, object, property, false); @@ -857,7 +860,7 @@ impl<'a> ArrowFunctionConverter<'a> { return None; } - let assignment_target = ctx.ast.move_assignment_target(&mut assignment.left); + let assignment_target = assignment.left.take_in(ctx.ast.allocator); let mut assignment_expr = Expression::from(assignment_target.into_member_expression()); self.transform_member_expression_for_super( &mut assignment_expr, @@ -1317,7 +1320,7 @@ impl<'a> ConstructorBodyThisAfterSuperInserter<'a, '_> { fn transform_super_call_expression(&mut self, expr: &mut Expression<'a>) { let assignment = self.create_assignment_to_this_temp_var(); let span = expr.span(); - let exprs = self.ctx.ast.vec_from_array([self.ctx.ast.move_expression(expr), assignment]); + let exprs = self.ctx.ast.vec_from_array([expr.take_in(self.ctx.ast.allocator), assignment]); *expr = self.ctx.ast.expression_sequence(span, exprs); } diff --git a/crates/oxc_transformer/src/decorator/legacy/metadata.rs b/crates/oxc_transformer/src/decorator/legacy/metadata.rs index edadba992d3d9..903e7505e44f2 100644 --- a/crates/oxc_transformer/src/decorator/legacy/metadata.rs +++ b/crates/oxc_transformer/src/decorator/legacy/metadata.rs @@ -87,7 +87,7 @@ /// /// ## References /// * TypeScript's [emitDecoratorMetadata](https://www.typescriptlang.org/tsconfig#emitDecoratorMetadata) -use oxc_allocator::Box as ArenaBox; +use oxc_allocator::{Box as ArenaBox, TakeIn}; use oxc_ast::ast::*; use oxc_semantic::ReferenceFlags; use oxc_span::{ContentEq, SPAN}; @@ -381,7 +381,7 @@ impl<'a> LegacyDecoratorMetadata<'a, '_> { let binding = self.ctx.var_declarations.create_uid_var_based_on_node(&left, ctx); let Expression::LogicalExpression(logical) = &mut left else { unreachable!() }; - let right = ctx.ast.move_expression(&mut logical.right); + let right = logical.right.take_in(ctx.ast.allocator); // `(_a = A.B)` let right = ctx.ast.expression_assignment( SPAN, diff --git a/crates/oxc_transformer/src/decorator/legacy/mod.rs b/crates/oxc_transformer/src/decorator/legacy/mod.rs index 92bbd12edcbb9..7e19cc75ea82f 100644 --- a/crates/oxc_transformer/src/decorator/legacy/mod.rs +++ b/crates/oxc_transformer/src/decorator/legacy/mod.rs @@ -47,7 +47,7 @@ mod metadata; use std::mem; -use oxc_allocator::{Address, GetAddress, Vec as ArenaVec}; +use oxc_allocator::{Address, GetAddress, TakeIn, Vec as ArenaVec}; use oxc_ast::{NONE, ast::*}; use oxc_ast_visit::{Visit, VisitMut}; use oxc_semantic::{ScopeFlags, SymbolFlags}; @@ -492,7 +492,7 @@ impl<'a> LegacyDecorator<'a, '_> { let span = class.span; class.r#type = ClassType::ClassExpression; let initializer = Self::get_class_initializer( - Expression::ClassExpression(ctx.ast.alloc(ctx.ast.move_class(class))), + Expression::ClassExpression(class.take_in_box(ctx.ast.allocator)), alias_binding, ctx, ); @@ -938,7 +938,7 @@ impl<'a> LegacyDecorator<'a, '_> { let binding = self.ctx.var_declarations.create_uid_var_based_on_node(key, ctx); let operator = AssignmentOperator::Assign; let left = binding.create_read_write_target(ctx); - let right = ctx.ast.move_expression(key.to_expression_mut()); + let right = key.to_expression_mut().take_in(ctx.ast.allocator); let key_expr = ctx.ast.expression_assignment(SPAN, operator, left, right); *key = PropertyKey::from(key_expr); binding.create_read_expression(ctx) diff --git a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs index 1b876ad0f942d..f8cdf186a87e5 100644 --- a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs +++ b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs @@ -32,7 +32,7 @@ //! * Exponentiation operator TC39 proposal: //! * Exponentiation operator specification: -use oxc_allocator::{CloneIn, Vec as ArenaVec}; +use oxc_allocator::{CloneIn, TakeIn, Vec as ArenaVec}; use oxc_ast::{NONE, ast::*}; use oxc_semantic::ReferenceFlags; use oxc_span::SPAN; @@ -106,7 +106,7 @@ impl<'a> ExponentiationOperator<'a, '_> { // `#[inline]` so compiler knows `expr` is a `BinaryExpression` #[inline] fn convert_binary_expression(expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { - let binary_expr = match ctx.ast.move_expression(expr) { + let binary_expr = match expr.take_in(ctx.ast.allocator) { Expression::BinaryExpression(binary_expr) => binary_expr.unbox(), _ => unreachable!(), }; @@ -258,7 +258,7 @@ impl<'a> ExponentiationOperator<'a, '_> { let replacement_left = AssignmentTarget::ComputedMemberExpression(ctx.ast.alloc_computed_member_expression( member_expr.span, - ctx.ast.move_expression(&mut member_expr.object), + member_expr.object.take_in(ctx.ast.allocator), ctx.ast.expression_string_literal(prop_span, prop_name, None), false, )); @@ -337,7 +337,7 @@ impl<'a> ExponentiationOperator<'a, '_> { let prop = if prop.is_literal() { prop.clone_in(ctx.ast.allocator) } else { - let owned_prop = ctx.ast.move_expression(prop); + let owned_prop = prop.take_in(ctx.ast.allocator); let binding = self.create_temp_var(owned_prop, &mut temp_var_inits, ctx); *prop = binding.create_read_expression(ctx); binding.create_read_expression(ctx) @@ -498,7 +498,7 @@ impl<'a> ExponentiationOperator<'a, '_> { } } - let binding = self.create_temp_var(ctx.ast.move_expression(obj), temp_var_inits, ctx); + let binding = self.create_temp_var(obj.take_in(ctx.ast.allocator), temp_var_inits, ctx); *obj = binding.create_read_expression(ctx); binding.create_read_expression(ctx) } @@ -509,7 +509,7 @@ impl<'a> ExponentiationOperator<'a, '_> { pow_left: Expression<'a>, ctx: &mut TraverseCtx<'a>, ) { - let pow_right = ctx.ast.move_expression(&mut assign_expr.right); + let pow_right = assign_expr.right.take_in(ctx.ast.allocator); assign_expr.right = Self::math_pow(pow_left, pow_right, ctx); assign_expr.operator = AssignmentOperator::Assign; } @@ -522,7 +522,7 @@ impl<'a> ExponentiationOperator<'a, '_> { ) { if !temp_var_inits.is_empty() { temp_var_inits.reserve_exact(1); - temp_var_inits.push(ctx.ast.move_expression(expr)); + temp_var_inits.push(expr.take_in(ctx.ast.allocator)); *expr = ctx.ast.expression_sequence(SPAN, temp_var_inits); } } diff --git a/crates/oxc_transformer/src/es2017/async_to_generator.rs b/crates/oxc_transformer/src/es2017/async_to_generator.rs index 88e58f462fa70..925bead319683 100644 --- a/crates/oxc_transformer/src/es2017/async_to_generator.rs +++ b/crates/oxc_transformer/src/es2017/async_to_generator.rs @@ -53,7 +53,7 @@ use std::{borrow::Cow, mem}; -use oxc_allocator::{Box as ArenaBox, String as ArenaString}; +use oxc_allocator::{Box as ArenaBox, String as ArenaString, TakeIn}; use oxc_ast::{NONE, ast::*}; use oxc_ast_visit::Visit; use oxc_semantic::{ReferenceFlags, ScopeFlags, ScopeId, SymbolFlags}; @@ -176,7 +176,7 @@ impl<'a> AsyncToGenerator<'a, '_> { Some(ctx.ast.expression_yield( SPAN, false, - Some(ctx.ast.move_expression(&mut expr.argument)), + Some(expr.argument.take_in(ctx.ast.allocator)), )) } else { None @@ -302,7 +302,7 @@ impl<'a, 'ctx> AsyncGeneratorExecutor<'a, 'ctx> { ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { let body = wrapper_function.body.take().unwrap(); - let params = ctx.alloc(ctx.ast.move_formal_parameters(&mut wrapper_function.params)); + let params = wrapper_function.params.take_in_box(ctx.ast.allocator); let id = wrapper_function.id.take(); let has_function_id = id.is_some(); @@ -390,7 +390,7 @@ impl<'a, 'ctx> AsyncGeneratorExecutor<'a, 'ctx> { // Construct the IIFE let callee = - Expression::FunctionExpression(ctx.alloc(ctx.ast.move_function(wrapper_function))); + Expression::FunctionExpression(wrapper_function.take_in_box(ctx.ast.allocator)); ctx.ast.expression_call_with_pure(SPAN, callee, NONE, ctx.ast.vec(), false, true) } @@ -465,30 +465,25 @@ impl<'a, 'ctx> AsyncGeneratorExecutor<'a, 'ctx> { arrow: &mut ArrowFunctionExpression<'a>, ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { - let mut body = ctx.ast.move_function_body(&mut arrow.body); + let mut body = arrow.body.take_in_box(ctx.ast.allocator); // If the arrow's expression is true, we need to wrap the only one expression with return statement. if arrow.expression { let statement = body.statements.first_mut().unwrap(); let expression = match statement { - Statement::ExpressionStatement(es) => ctx.ast.move_expression(&mut es.expression), + Statement::ExpressionStatement(es) => es.expression.take_in(ctx.ast.allocator), _ => unreachable!(), }; *statement = ctx.ast.statement_return(expression.span(), Some(expression)); } - let params = ctx.alloc(ctx.ast.move_formal_parameters(&mut arrow.params)); + let params = arrow.params.take_in_box(ctx.ast.allocator); let generator_function_id = arrow.scope_id(); ctx.scoping_mut().scope_flags_mut(generator_function_id).remove(ScopeFlags::Arrow); let function_name = Self::infer_function_name_from_parent_node(ctx); if function_name.is_none() && !Self::is_function_length_affected(¶ms) { - return self.create_async_to_generator_call( - params, - ctx.alloc(body), - generator_function_id, - ctx, - ); + return self.create_async_to_generator_call(params, body, generator_function_id, ctx); } let wrapper_scope_id = ctx.create_child_scope(ctx.current_scope_id(), ScopeFlags::Function); @@ -523,7 +518,7 @@ impl<'a, 'ctx> AsyncGeneratorExecutor<'a, 'ctx> { let statement = self.create_async_to_generator_declaration( &bound_ident, params, - ctx.alloc(body), + body, generator_function_id, ctx, ); diff --git a/crates/oxc_transformer/src/es2018/async_generator_functions/for_await.rs b/crates/oxc_transformer/src/es2018/async_generator_functions/for_await.rs index 5ed0ecb373648..f2594fffb83bb 100644 --- a/crates/oxc_transformer/src/es2018/async_generator_functions/for_await.rs +++ b/crates/oxc_transformer/src/es2018/async_generator_functions/for_await.rs @@ -1,6 +1,6 @@ //! This module is responsible for transforming `for await` to `for` statement -use oxc_allocator::Vec as ArenaVec; +use oxc_allocator::{TakeIn, Vec as ArenaVec}; use oxc_ast::{NONE, ast::*}; use oxc_semantic::{ScopeFlags, ScopeId, SymbolFlags}; use oxc_span::SPAN; @@ -118,7 +118,7 @@ impl<'a> AsyncGeneratorFunctions<'a, '_> { } left @ match_assignment_target!(ForStatementLeft) => { // for await (i of test), for await ({ i } of test) - let target = ctx.ast.move_assignment_target(left.to_assignment_target_mut()); + let target = left.to_assignment_target_mut().take_in(ctx.ast.allocator); let expression = ctx.ast.expression_assignment( SPAN, AssignmentOperator::Assign, @@ -139,13 +139,13 @@ impl<'a> AsyncGeneratorFunctions<'a, '_> { // instead, we need to remove the useless scope. ctx.scoping_mut().delete_scope(block.scope_id()); } else { - statements.push(ctx.ast.move_statement(stmt_body)); + statements.push(stmt_body.take_in(ctx.ast.allocator)); } } statements }; - let iterator = ctx.ast.move_expression(&mut stmt.right); + let iterator = stmt.right.take_in(ctx.ast.allocator); let iterator = self.ctx.helper_call_expr( Helper::AsyncIterator, SPAN, diff --git a/crates/oxc_transformer/src/es2018/async_generator_functions/mod.rs b/crates/oxc_transformer/src/es2018/async_generator_functions/mod.rs index 0d6c558cfeff2..1d897951a6e7a 100644 --- a/crates/oxc_transformer/src/es2018/async_generator_functions/mod.rs +++ b/crates/oxc_transformer/src/es2018/async_generator_functions/mod.rs @@ -66,6 +66,7 @@ mod for_await; +use oxc_allocator::TakeIn; use oxc_ast::ast::*; use oxc_span::SPAN; use oxc_traverse::{Ancestor, Traverse, TraverseCtx}; @@ -164,7 +165,7 @@ impl<'a> AsyncGeneratorFunctions<'a, '_> { } expr.argument.as_mut().map(|argument| { - let argument = Argument::from(ctx.ast.move_expression(argument)); + let argument = Argument::from(argument.take_in(ctx.ast.allocator)); let arguments = ctx.ast.vec1(argument); let mut argument = self.ctx.helper_call_expr(Helper::AsyncIterator, SPAN, arguments, ctx); @@ -199,7 +200,7 @@ impl<'a> AsyncGeneratorFunctions<'a, '_> { return None; } - let mut argument = ctx.ast.move_expression(&mut expr.argument); + let mut argument = expr.argument.take_in(ctx.ast.allocator); let arguments = ctx.ast.vec1(Argument::from(argument)); argument = self.ctx.helper_call_expr(Helper::AwaitAsyncGenerator, SPAN, arguments, ctx); diff --git a/crates/oxc_transformer/src/es2018/object_rest_spread.rs b/crates/oxc_transformer/src/es2018/object_rest_spread.rs index 26d3b10ee9676..d9a46450817a2 100644 --- a/crates/oxc_transformer/src/es2018/object_rest_spread.rs +++ b/crates/oxc_transformer/src/es2018/object_rest_spread.rs @@ -31,7 +31,7 @@ use std::mem; use serde::Deserialize; -use oxc_allocator::{GetAddress, Vec as ArenaVec}; +use oxc_allocator::{GetAddress, TakeIn, Vec as ArenaVec}; use oxc_ast::{NONE, ast::*}; use oxc_diagnostics::OxcDiagnostic; use oxc_ecmascript::{ @@ -255,7 +255,7 @@ impl<'a> ObjectRestSpread<'a, '_> { expressions.push(ctx.ast.expression_assignment( SPAN, op, - ctx.ast.move_assignment_target(&mut assign_expr.left), + assign_expr.left.take_in(ctx.ast.allocator), reference_builder.create_read_expression(ctx), )); @@ -403,7 +403,7 @@ impl<'a> ObjectRestSpread<'a, '_> { break; } } - let mut expressions = ctx.ast.vec1(ctx.ast.move_expression(expr)); + let mut expressions = ctx.ast.vec1(expr.take_in(ctx.ast.allocator)); expressions.extend(exprs); *expr = ctx.ast.expression_sequence(SPAN, expressions); } @@ -443,7 +443,7 @@ impl<'a> ObjectRestSpread<'a, '_> { exprs.push(ctx.ast.expression_assignment( SPAN, AssignmentOperator::Assign, - ctx.ast.move_assignment_target(pat), + pat.take_in(ctx.ast.allocator), bound_identifier.create_read_expression(ctx), )); *pat = bound_identifier.create_spanned_write_target(SPAN, ctx); @@ -493,7 +493,7 @@ impl<'a, 'ctx> ObjectRestSpread<'a, 'ctx> { for prop in obj_expr.properties.drain(..) { if let ObjectPropertyKind::SpreadProperty(spread_prop) = prop { Self::make_object_spread(&mut call_expr, &mut props, transform_ctx, ctx); - let arg = ctx.ast.move_expression(&mut spread_prop.unbox().argument); + let arg = spread_prop.unbox().argument.take_in(ctx.ast.allocator); call_expr.as_mut().unwrap().arguments.push(Argument::from(arg)); } else { props.push(prop); @@ -637,7 +637,7 @@ impl<'a> ObjectRestSpread<'a, '_> { return; } let target = left.to_assignment_target_mut(); - let assign_left = ctx.ast.move_assignment_target(target); + let assign_left = target.take_in(ctx.ast.allocator); let flags = SymbolFlags::FunctionScopedVariable; let bound_identifier = ctx.generate_uid("ref", scope_id, flags); let id = bound_identifier.create_binding_pattern(ctx); @@ -669,7 +669,7 @@ impl<'a> ObjectRestSpread<'a, '_> { (empty_stmt.span, ctx.ast.vec()) } else { let span = stmt.span(); - (span, ctx.ast.vec1(ctx.ast.move_statement(stmt))) + (span, ctx.ast.vec1(stmt.take_in(ctx.ast.allocator))) }; *stmt = ctx.ast.statement_block_with_scope_id(span, stmts, scope_id); scope_id @@ -1151,7 +1151,7 @@ impl<'a> ReferenceBuilder<'a> { force_create_binding: bool, ctx: &mut TraverseCtx<'a>, ) -> Self { - let expr = ctx.ast.move_expression(expr); + let expr = expr.take_in(ctx.ast.allocator); let binding; let maybe_bound_identifier; match &expr { diff --git a/crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs b/crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs index ee12a8bd04c69..96adfb6dedbd9 100644 --- a/crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs +++ b/crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs @@ -28,7 +28,7 @@ //! * Babel plugin implementation: //! * Nullish coalescing TC39 proposal: -use oxc_allocator::Box as ArenaBox; +use oxc_allocator::{Box as ArenaBox, TakeIn}; use oxc_ast::{NONE, ast::*}; use oxc_semantic::{ScopeFlags, SymbolFlags}; use oxc_span::SPAN; @@ -56,7 +56,7 @@ impl<'a> Traverse<'a> for NullishCoalescingOperator<'a, '_> { } // Take ownership of the `LogicalExpression` - let Expression::LogicalExpression(logical_expr) = ctx.ast.move_expression(expr) else { + let Expression::LogicalExpression(logical_expr) = expr.take_in(ctx.ast.allocator) else { unreachable!() }; diff --git a/crates/oxc_transformer/src/es2020/optional_chaining.rs b/crates/oxc_transformer/src/es2020/optional_chaining.rs index c174329ab3108..52debee91a7a4 100644 --- a/crates/oxc_transformer/src/es2020/optional_chaining.rs +++ b/crates/oxc_transformer/src/es2020/optional_chaining.rs @@ -49,7 +49,7 @@ use std::mem; -use oxc_allocator::CloneIn; +use oxc_allocator::{CloneIn, TakeIn}; use oxc_ast::{NONE, ast::*}; use oxc_span::SPAN; use oxc_traverse::{Ancestor, BoundIdentifier, MaybeBoundIdentifier, Traverse, TraverseCtx}; @@ -256,7 +256,7 @@ impl<'a> OptionalChaining<'a, '_> { expr: &mut Expression<'a>, ctx: &TraverseCtx<'a>, ) -> Expression<'a> { - let Expression::ChainExpression(chain_expr) = ctx.ast.move_expression(expr) else { + let Expression::ChainExpression(chain_expr) = expr.take_in(ctx.ast.allocator) else { unreachable!() }; match chain_expr.unbox().expression { @@ -283,7 +283,7 @@ impl<'a> OptionalChaining<'a, '_> { // To insert the temp binding in the correct scope, we wrap the expression with // an arrow function. During the chain expression transformation, the temp binding // will be inserted into the arrow function's body. - wrap_expression_in_arrow_function_iife(ctx.ast.move_expression(expr), ctx) + wrap_expression_in_arrow_function_iife(expr.take_in(ctx.ast.allocator), ctx) } else { self.transform_chain_expression_impl(false, expr, ctx) } @@ -297,7 +297,7 @@ impl<'a> OptionalChaining<'a, '_> { ) { *expr = if self.is_inside_function_parameter { // Same as the above `transform_chain_expression` explanation - wrap_expression_in_arrow_function_iife(ctx.ast.move_expression(expr), ctx) + wrap_expression_in_arrow_function_iife(expr.take_in(ctx.ast.allocator), ctx) } else { // Unfortunately no way to get compiler to see that this branch is provably unreachable. // We don't want to inline this function, to keep `enter_expression` as small as possible. @@ -372,7 +372,7 @@ impl<'a> OptionalChaining<'a, '_> { let binding = self.ctx.var_declarations.create_uid_var_based_on_node(object, ctx); *object = Self::create_assignment_expression( binding.create_write_target(ctx), - ctx.ast.move_expression(object), + object.take_in(ctx.ast.allocator), ctx, ); binding.create_read_expression(ctx) @@ -486,7 +486,7 @@ impl<'a> OptionalChaining<'a, '_> { if let Expression::Identifier(ident) = callee { if self.should_specify_context(ident, ctx) { // `foo$bar(...)` -> `foo$bar.call(context, ...)` - let callee = ctx.ast.move_expression(callee); + let callee = callee.take_in(ctx.ast.allocator); let property = ctx.ast.identifier_name(SPAN, "call"); let member = ctx.ast.member_expression_static(SPAN, callee, property, false); @@ -532,7 +532,7 @@ impl<'a> OptionalChaining<'a, '_> { if ident.name == "eval" { // `eval?.()` is an indirect eval call transformed to `(0,eval)()` let zero = ctx.ast.number_0(); - let original_callee = ctx.ast.move_expression(expr); + let original_callee = expr.take_in(ctx.ast.allocator); let expressions = ctx.ast.vec_from_array([zero, original_callee]); *expr = ctx.ast.expression_sequence(SPAN, expressions); } @@ -649,7 +649,7 @@ impl<'a> OptionalChaining<'a, '_> { // `(_foo = foo)` *object = Self::create_assignment_expression( binding.create_write_target(ctx), - ctx.ast.move_expression(object), + object.take_in(ctx.ast.allocator), ctx, ); binding.to_maybe_bound_identifier() diff --git a/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs b/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs index fb669bb1b6f31..301d197682e00 100644 --- a/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs +++ b/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs @@ -54,6 +54,7 @@ //! * Babel plugin implementation: //! * Logical Assignment TC39 proposal: +use oxc_allocator::TakeIn; use oxc_ast::ast::*; use oxc_semantic::ReferenceFlags; use oxc_span::SPAN; @@ -125,7 +126,7 @@ impl<'a> LogicalAssignmentOperators<'a, '_> { }; let assign_op = AssignmentOperator::Assign; - let right = ctx.ast.move_expression(&mut assignment_expr.right); + let right = assignment_expr.right.take_in(ctx.ast.allocator); let right = ctx.ast.expression_assignment(SPAN, assign_op, assign_target, right); let logical_expr = ctx.ast.expression_logical(SPAN, left_expr, operator, right); @@ -152,7 +153,7 @@ impl<'a> LogicalAssignmentOperators<'a, '_> { static_expr: &mut StaticMemberExpression<'a>, ctx: &mut TraverseCtx<'a>, ) -> (Expression<'a>, AssignmentTarget<'a>) { - let object = ctx.ast.move_expression(&mut static_expr.object); + let object = static_expr.object.take_in(ctx.ast.allocator); let (object, object_ref) = self.ctx.duplicate_expression(object, true, ctx); let left_expr = Expression::from(ctx.ast.member_expression_static( @@ -178,10 +179,10 @@ impl<'a> LogicalAssignmentOperators<'a, '_> { computed_expr: &mut ComputedMemberExpression<'a>, ctx: &mut TraverseCtx<'a>, ) -> (Expression<'a>, AssignmentTarget<'a>) { - let object = ctx.ast.move_expression(&mut computed_expr.object); + let object = computed_expr.object.take_in(ctx.ast.allocator); let (object, object_ref) = self.ctx.duplicate_expression(object, true, ctx); - let expression = ctx.ast.move_expression(&mut computed_expr.expression); + let expression = computed_expr.expression.take_in(ctx.ast.allocator); let (expression, expression_ref) = self.ctx.duplicate_expression(expression, true, ctx); let left_expr = Expression::from(ctx.ast.member_expression_computed( diff --git a/crates/oxc_transformer/src/es2022/class_properties/class.rs b/crates/oxc_transformer/src/es2022/class_properties/class.rs index 62bf3476c5f7d..c80d878508ee7 100644 --- a/crates/oxc_transformer/src/es2022/class_properties/class.rs +++ b/crates/oxc_transformer/src/es2022/class_properties/class.rs @@ -2,7 +2,7 @@ //! Transform of class itself. use indexmap::map::Entry; -use oxc_allocator::{Address, GetAddress}; +use oxc_allocator::{Address, GetAddress, TakeIn}; use oxc_ast::{NONE, ast::*}; use oxc_span::SPAN; use oxc_syntax::{ @@ -670,7 +670,7 @@ impl<'a> ClassProperties<'a, '_> { } // `_Class = class {}` - let class_expr = ctx.ast.move_expression(expr); + let class_expr = expr.take_in(ctx.ast.allocator); let assignment = create_assignment(binding, class_expr, ctx); if exprs.is_empty() && self.insert_after_exprs.is_empty() { @@ -699,7 +699,7 @@ impl<'a> ClassProperties<'a, '_> { return; } - let class_expr = ctx.ast.move_expression(expr); + let class_expr = expr.take_in(ctx.ast.allocator); exprs.push(class_expr); } diff --git a/crates/oxc_transformer/src/es2022/class_properties/computed_key.rs b/crates/oxc_transformer/src/es2022/class_properties/computed_key.rs index 3ff887886c8a1..b47780fc0cbcf 100644 --- a/crates/oxc_transformer/src/es2022/class_properties/computed_key.rs +++ b/crates/oxc_transformer/src/es2022/class_properties/computed_key.rs @@ -1,6 +1,7 @@ //! ES2022: Class Properties //! Transform of class property/method computed keys. +use oxc_allocator::TakeIn; use oxc_ast::ast::*; use oxc_syntax::symbol::SymbolFlags; use oxc_traverse::TraverseCtx; @@ -34,7 +35,7 @@ impl<'a> ClassProperties<'a, '_> { // 3. At least one property satisfying the above is after this method, // or class contains a static block which is being transformed // (static blocks are always evaluated after computed keys, regardless of order) - let original_key = ctx.ast.move_expression(key); + let original_key = key.take_in(ctx.ast.allocator); let (assignment, temp_var) = self.create_computed_key_temp_var(original_key, ctx); self.insert_before.push(assignment); method.key = PropertyKey::from(temp_var); @@ -62,7 +63,7 @@ impl<'a> ClassProperties<'a, '_> { is_static: bool, ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { - let original_key = ctx.ast.move_expression(key); + let original_key = key.take_in(ctx.ast.allocator); if key_needs_temp_var(&original_key, ctx) { let (assignment, ident) = self.create_computed_key_temp_var(original_key, ctx); if is_static { @@ -137,7 +138,7 @@ impl<'a> ClassProperties<'a, '_> { } // Extract assignment from computed key and insert before class - let assignment = ctx.ast.move_property_key(&mut prop.key).into_expression(); + let assignment = prop.key.take_in(ctx.ast.allocator).into_expression(); self.insert_before.push(assignment); } } diff --git a/crates/oxc_transformer/src/es2022/class_properties/constructor.rs b/crates/oxc_transformer/src/es2022/class_properties/constructor.rs index b0c51e1738967..951b52f6dab84 100644 --- a/crates/oxc_transformer/src/es2022/class_properties/constructor.rs +++ b/crates/oxc_transformer/src/es2022/class_properties/constructor.rs @@ -101,6 +101,7 @@ use std::iter; +use oxc_allocator::TakeIn; use rustc_hash::FxHashMap; use oxc_ast::{NONE, ast::*}; @@ -589,7 +590,7 @@ impl<'a> ConstructorParamsSuperReplacer<'a, '_> { }); let ctx = &mut *self.ctx; - let super_call = ctx.ast.move_expression(expr); + let super_call = expr.take_in(ctx.ast.allocator); *expr = ctx.ast.expression_call( span, Expression::from(ctx.ast.member_expression_static( diff --git a/crates/oxc_transformer/src/es2022/class_properties/private_field.rs b/crates/oxc_transformer/src/es2022/class_properties/private_field.rs index 953d8be0855e1..3f773527b4efb 100644 --- a/crates/oxc_transformer/src/es2022/class_properties/private_field.rs +++ b/crates/oxc_transformer/src/es2022/class_properties/private_field.rs @@ -3,7 +3,7 @@ use std::mem; -use oxc_allocator::Box as ArenaBox; +use oxc_allocator::{Box as ArenaBox, TakeIn}; use oxc_ast::{NONE, ast::*}; use oxc_span::SPAN; use oxc_syntax::{reference::ReferenceId, symbol::SymbolId}; @@ -59,7 +59,7 @@ impl<'a> ClassProperties<'a, '_> { ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { let span = field_expr.span; - let object = ctx.ast.move_expression(&mut field_expr.object); + let object = field_expr.object.take_in(ctx.ast.allocator); let resolved = if is_assignment { match self.classes_stack.find_writeable_private_prop(&field_expr.field) { Some(prop) => prop, @@ -265,7 +265,7 @@ impl<'a> ClassProperties<'a, '_> { // `object.#prop(arg)` -> `_classPrivateFieldLooseBase(object, _prop)[_prop](arg)` let prop_binding = self.classes_stack.find_private_prop(&field_expr.field).prop_binding; - let object = ctx.ast.move_expression(&mut field_expr.object); + let object = field_expr.object.take_in(ctx.ast.allocator); call_expr.callee = Expression::from(Self::create_private_field_member_expr_loose( object, prop_binding, @@ -332,7 +332,7 @@ impl<'a> ClassProperties<'a, '_> { let span = field_expr.span; // `(object.#method)()` // ^^^^^^^^^^^^^^^^ is a parenthesized expression - let object = ctx.ast.move_expression(field_expr.object.get_inner_expression_mut()); + let object = field_expr.object.get_inner_expression_mut().take_in(ctx.ast.allocator); let Some(ResolvedPrivateProp { prop_binding, @@ -495,7 +495,7 @@ impl<'a> ClassProperties<'a, '_> { if self.private_fields_as_properties { // `object.#prop = value` -> `_classPrivateFieldLooseBase(object, _prop)[_prop] = value` // Same for all other assignment operators e.g. `+=`, `&&=`, `??=`. - let object = ctx.ast.move_expression(&mut field_expr.object); + let object = field_expr.object.take_in(ctx.ast.allocator); let replacement = Self::create_private_field_member_expr_loose( object, // At least one of `get_binding` or `set_binding` is always present @@ -632,7 +632,7 @@ impl<'a> ClassProperties<'a, '_> { if let Some(operator) = operator.to_binary_operator() { // `Class.#prop += value` -> `_prop._ = _prop._ + value` - let value = ctx.ast.move_expression(&mut assign_expr.right); + let value = assign_expr.right.take_in(ctx.ast.allocator); assign_expr.operator = AssignmentOperator::Assign; assign_expr.right = ctx.ast.expression_binary(SPAN, prop_obj, operator, value); } else if let Some(operator) = operator.to_logical_operator() { @@ -640,7 +640,7 @@ impl<'a> ClassProperties<'a, '_> { let span = assign_expr.span; assign_expr.span = SPAN; assign_expr.operator = AssignmentOperator::Assign; - let right = ctx.ast.move_expression(expr); + let right = expr.take_in(ctx.ast.allocator); *expr = ctx.ast.expression_logical(span, prop_obj, operator, right); } else { // The above covers all types of `AssignmentOperator` @@ -662,7 +662,7 @@ impl<'a> ClassProperties<'a, '_> { let object = field_expr.object.into_inner_expression(); let class_ident = class_binding.create_read_expression(ctx); - let value = ctx.ast.move_expression(&mut assign_expr.right); + let value = assign_expr.right.take_in(ctx.ast.allocator); if operator == AssignmentOperator::Assign { // Replace right side of assignment with `_assertClassBrand(Class, object, _prop)` @@ -672,7 +672,7 @@ impl<'a> ClassProperties<'a, '_> { self.create_assert_class_brand(class_ident, object, value, SPAN, ctx); } else { let class_ident = class_binding.create_read_expression(ctx); - let value = ctx.ast.move_expression(&mut assign_expr.right); + let value = assign_expr.right.take_in(ctx.ast.allocator); // Make 2 copies of `object` let (object1, object2) = self.duplicate_object(object, ctx); @@ -722,7 +722,7 @@ impl<'a> ClassProperties<'a, '_> { assign_expr.operator = AssignmentOperator::Assign; assign_expr.right = self.create_assert_class_brand(class_ident2, object2, value, SPAN, ctx); - let right = ctx.ast.move_expression(expr); + let right = expr.take_in(ctx.ast.allocator); // `_assertClassBrand(Class, object, _prop)._ && (_prop._ = _assertClassBrand(Class, object, value))` *expr = ctx.ast.expression_logical(span, left, operator, right); } else { @@ -754,7 +754,7 @@ impl<'a> ClassProperties<'a, '_> { class_binding: Option<&BoundIdentifier<'a>>, ctx: &mut TraverseCtx<'a>, ) { - let assign_expr = match ctx.ast.move_expression(expr) { + let assign_expr = match expr.take_in(ctx.ast.allocator) { Expression::AssignmentExpression(assign_expr) => assign_expr.unbox(), _ => unreachable!(), }; @@ -926,7 +926,7 @@ impl<'a> ClassProperties<'a, '_> { if self.private_fields_as_properties { let prop_binding = self.classes_stack.find_private_prop(&field_expr.field).prop_binding; // `object.#prop++` -> `_classPrivateFieldLooseBase(object, _prop)[_prop]++` - let object = ctx.ast.move_expression(&mut field_expr.object); + let object = field_expr.object.take_in(ctx.ast.allocator); let replacement = Self::create_private_field_member_expr_loose( object, prop_binding, @@ -952,7 +952,7 @@ impl<'a> ClassProperties<'a, '_> { // TODO(improve-on-babel): Could avoid `move_expression` here and replace `update_expr.argument` instead. // Only doing this first to match the order Babel creates temp vars. - let object = ctx.ast.move_expression(field_expr.object.get_inner_expression_mut()); + let object = field_expr.object.get_inner_expression_mut().take_in(ctx.ast.allocator); if is_static && !is_method { // Unwrap is safe because `is_method` is false, then private prop is always have a `get_binding` @@ -1024,7 +1024,7 @@ impl<'a> ClassProperties<'a, '_> { let UpdateExpression { span, prefix, .. } = **update_expr; update_expr.span = SPAN; update_expr.argument = temp_binding.create_read_write_simple_target(ctx); - let update_expr = ctx.ast.move_expression(expr); + let update_expr = expr.take_in(ctx.ast.allocator); if prefix { // Source = `++object.#prop` (prefix `++`) @@ -1121,7 +1121,7 @@ impl<'a> ClassProperties<'a, '_> { let UpdateExpression { span, prefix, .. } = **update_expr; update_expr.span = SPAN; update_expr.argument = temp_binding.create_read_write_simple_target(ctx); - let update_expr = ctx.ast.move_expression(expr); + let update_expr = expr.take_in(ctx.ast.allocator); if prefix { // Source = `++object.#prop` (prefix `++`) @@ -1375,7 +1375,7 @@ impl<'a> ClassProperties<'a, '_> { // `o?.Foo.#self.self?.self.unicorn;` -> `(result ? void 0 : object)?.self.unicorn` // ^^^^^^^^^^^^^^^^^ the object has transformed, if the current member is optional, // then we need to wrap it to a conditional expression - let owned_object = ctx.ast.move_expression(object); + let owned_object = object.take_in(ctx.ast.allocator); *object = Self::wrap_conditional_check(result, owned_object, ctx); None } else { @@ -1397,7 +1397,7 @@ impl<'a> ClassProperties<'a, '_> { // `Foo.bar.#m?.();` -> `_assertClassBrand(Foo, _Foo$bar = Foo.bar, _m)._?.call(_Foo$bar);` // ^^^^ only the private field is optional // Move out parenthesis and typescript syntax - call_expr.callee = ctx.ast.move_expression(callee); + call_expr.callee = callee.take_in(ctx.ast.allocator); self.transform_call_expression_impl(call_expr, ctx); return result; } @@ -1415,9 +1415,9 @@ impl<'a> ClassProperties<'a, '_> { // TODO(improve-on-babel): Consider remove this logic, because it seems no runtime behavior change. let result = result?; let object = callee.to_member_expression_mut().object_mut(); - let (assignment, context) = self.duplicate_object(ctx.ast.move_expression(object), ctx); + let (assignment, context) = self.duplicate_object(object.take_in(ctx.ast.allocator), ctx); *object = assignment; - let callee = ctx.ast.move_expression(&mut call_expr.callee); + let callee = call_expr.callee.take_in(ctx.ast.allocator); let callee = Self::wrap_conditional_check(result, callee, ctx); Self::substitute_callee_and_insert_context(call_expr, callee, context, ctx); @@ -1438,7 +1438,7 @@ impl<'a> ClassProperties<'a, '_> { object: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { - let mut owned_object = ctx.ast.move_expression(object.get_inner_expression_mut()); + let mut owned_object = object.get_inner_expression_mut().take_in(ctx.ast.allocator); let owned_object = if let Some(result) = self.transform_chain_element_recursively(&mut owned_object, ctx) @@ -1468,7 +1468,7 @@ impl<'a> ClassProperties<'a, '_> { expr: &mut Expression<'a>, ctx: &TraverseCtx<'a>, ) -> Expression<'a> { - let Expression::ChainExpression(chain_expr) = ctx.ast.move_expression(expr) else { + let Expression::ChainExpression(chain_expr) = expr.take_in(ctx.ast.allocator) else { unreachable!() }; match chain_expr.unbox().expression { @@ -1573,9 +1573,9 @@ impl<'a> ClassProperties<'a, '_> { // `o?.Foo.#self?.getSelf?.().#x;` -> `(_ref$getSelf = (_ref2 = _ref = o === null || o === void 0 ? // ^^ is optional void 0 : babelHelpers.assertClassBrand(Foo, o.Foo, _self)._)` *object = - Self::wrap_conditional_check(result, ctx.ast.move_expression(object), ctx); + Self::wrap_conditional_check(result, object.take_in(ctx.ast.allocator), ctx); let (assignment, context) = - self.duplicate_object(ctx.ast.move_expression(object), ctx); + self.duplicate_object(object.take_in(ctx.ast.allocator), ctx); *object = assignment; context } else { @@ -1585,10 +1585,10 @@ impl<'a> ClassProperties<'a, '_> { // the parent of callee (i.e `o?.Foo.#self`) to a temp variable, // and then use it as a first argument of `_ref.call`. let (assignment, context) = - self.duplicate_object(ctx.ast.move_expression(object), ctx); + self.duplicate_object(object.take_in(ctx.ast.allocator), ctx); *object = assignment; *callee = - Self::wrap_conditional_check(result, ctx.ast.move_expression(callee), ctx); + Self::wrap_conditional_check(result, callee.take_in(ctx.ast.allocator), ctx); context } } else { @@ -1596,14 +1596,15 @@ impl<'a> ClassProperties<'a, '_> { // ^^^^^^^^^^^^^^^^ this is a optional function call, to make sure it has a proper context, // we also need to assign `Foo?.bar()` to a temp variable, and then use // it as a first argument of `_Foo$bar$zoo`. - let (assignment, context) = self.duplicate_object(ctx.ast.move_expression(object), ctx); + let (assignment, context) = + self.duplicate_object(object.take_in(ctx.ast.allocator), ctx); *object = assignment; context }; // After the below transformation, the `callee` will be a temp variable. let result = self.transform_expression_to_wrap_nullish_check(callee, ctx); - let owned_callee = ctx.ast.move_expression(callee); + let owned_callee = callee.take_in(ctx.ast.allocator); Self::substitute_callee_and_insert_context(call, owned_callee, context, ctx); result } @@ -1700,7 +1701,7 @@ impl<'a> ClassProperties<'a, '_> { { // We still need this unary expr, but it needs to be used as the alternative of the conditional unary_expr.argument = chain_expr; - ctx.ast.move_expression(expr) + expr.take_in(ctx.ast.allocator) }, ); } @@ -1760,7 +1761,7 @@ impl<'a> ClassProperties<'a, '_> { // But this is not needed, so we omit it. let prop_binding = self.classes_stack.find_private_prop(&field_expr.field).prop_binding; - let object = ctx.ast.move_expression(&mut field_expr.object); + let object = field_expr.object.take_in(ctx.ast.allocator); let replacement = Self::create_private_field_member_expr_loose( object, prop_binding, @@ -1850,7 +1851,7 @@ impl<'a> ClassProperties<'a, '_> { expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>, ) { - let Expression::PrivateInExpression(private_in) = ctx.ast.move_expression(expr) else { + let Expression::PrivateInExpression(private_in) = expr.take_in(ctx.ast.allocator) else { unreachable!(); }; diff --git a/crates/oxc_transformer/src/es2022/class_properties/private_method.rs b/crates/oxc_transformer/src/es2022/class_properties/private_method.rs index 101e5026738ab..cac421307b38a 100644 --- a/crates/oxc_transformer/src/es2022/class_properties/private_method.rs +++ b/crates/oxc_transformer/src/es2022/class_properties/private_method.rs @@ -1,6 +1,7 @@ //! ES2022: Class Properties //! Transform of private method uses e.g. `this.#method()`. +use oxc_allocator::TakeIn; use oxc_ast::ast::*; use oxc_ast_visit::{VisitMut, walk_mut}; use oxc_semantic::ScopeFlags; @@ -46,7 +47,8 @@ impl<'a> ClassProperties<'a, '_> { return None; }; - let mut function = ctx.ast.move_function(value); + let mut function = value.take_in_box(ctx.ast.allocator); + let resolved_private_prop = if *kind == MethodDefinitionKind::Set { self.classes_stack.find_writeable_private_prop(ident) } else { @@ -75,7 +77,6 @@ impl<'a> ClassProperties<'a, '_> { PrivateMethodVisitor::new(*r#static, self, ctx) .visit_function(&mut function, ScopeFlags::Function); - let function = ctx.ast.alloc(function); Some(Statement::FunctionDeclaration(function)) } diff --git a/crates/oxc_transformer/src/es2022/class_properties/static_block_and_prop_init.rs b/crates/oxc_transformer/src/es2022/class_properties/static_block_and_prop_init.rs index e5e037e5cee16..57e1c032af1a3 100644 --- a/crates/oxc_transformer/src/es2022/class_properties/static_block_and_prop_init.rs +++ b/crates/oxc_transformer/src/es2022/class_properties/static_block_and_prop_init.rs @@ -3,6 +3,7 @@ use std::cell::Cell; +use oxc_allocator::TakeIn; use oxc_ast::ast::*; use oxc_ast_visit::{VisitMut, walk_mut}; use oxc_syntax::scope::{ScopeFlags, ScopeId}; @@ -87,7 +88,12 @@ impl<'a> ClassProperties<'a, '_> { let outer_scope_id = ctx.current_scope_id(); ctx.scoping_mut().change_scope_parent_id(scope_id, Some(outer_scope_id)); - wrap_statements_in_arrow_function_iife(ctx.ast.move_vec(stmts), scope_id, block.span, ctx) + wrap_statements_in_arrow_function_iife( + stmts.take_in(ctx.ast.allocator), + scope_id, + block.span, + ctx, + ) } fn convert_static_block_with_single_expression_to_expression( @@ -104,7 +110,7 @@ impl<'a> ClassProperties<'a, '_> { // Delete scope for static block ctx.scoping_mut().delete_scope(scope_id); - ctx.ast.move_expression(expr) + expr.take_in(ctx.ast.allocator) } /// Replace reference to class name with reference to temp var for class. diff --git a/crates/oxc_transformer/src/es2022/class_properties/super_converter.rs b/crates/oxc_transformer/src/es2022/class_properties/super_converter.rs index 6773b324993f9..b6cda77217b3b 100644 --- a/crates/oxc_transformer/src/es2022/class_properties/super_converter.rs +++ b/crates/oxc_transformer/src/es2022/class_properties/super_converter.rs @@ -1,7 +1,7 @@ //! ES2022: Class Properties //! Transform of `super` expressions. -use oxc_allocator::{Box as ArenaBox, Vec as ArenaVec}; +use oxc_allocator::{Box as ArenaBox, TakeIn, Vec as ArenaVec}; use oxc_ast::ast::*; use oxc_span::SPAN; use oxc_traverse::{TraverseCtx, ast_operations::get_var_name_from_node}; @@ -87,7 +87,7 @@ impl<'a> ClassPropertiesSuperConverter<'a, '_, '_> { is_callee: bool, ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { - let property = ctx.ast.move_expression(&mut member.expression); + let property = member.expression.take_in(ctx.ast.allocator); self.create_super_prop_get(member.span, property, is_callee, ctx) } @@ -202,7 +202,7 @@ impl<'a> ClassPropertiesSuperConverter<'a, '_, '_> { expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>, ) { - let Expression::AssignmentExpression(assign_expr) = ctx.ast.move_expression(expr) else { + let Expression::AssignmentExpression(assign_expr) = expr.take_in(ctx.ast.allocator) else { unreachable!() }; let AssignmentExpression { span, operator, right: value, left } = assign_expr.unbox(); @@ -230,7 +230,7 @@ impl<'a> ClassPropertiesSuperConverter<'a, '_, '_> { expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>, ) { - let Expression::AssignmentExpression(assign_expr) = ctx.ast.move_expression(expr) else { + let Expression::AssignmentExpression(assign_expr) = expr.take_in(ctx.ast.allocator) else { unreachable!() }; let AssignmentExpression { span, operator, right: value, left } = assign_expr.unbox(); @@ -365,7 +365,7 @@ impl<'a> ClassPropertiesSuperConverter<'a, '_, '_> { expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>, ) { - let Expression::UpdateExpression(mut update_expr) = ctx.ast.move_expression(expr) else { + let Expression::UpdateExpression(mut update_expr) = expr.take_in(ctx.ast.allocator) else { unreachable!() }; let SimpleAssignmentTarget::StaticMemberExpression(member) = &mut update_expr.argument @@ -428,7 +428,7 @@ impl<'a> ClassPropertiesSuperConverter<'a, '_, '_> { expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>, ) { - let Expression::UpdateExpression(mut update_expr) = ctx.ast.move_expression(expr) else { + let Expression::UpdateExpression(mut update_expr) = expr.take_in(ctx.ast.allocator) else { unreachable!() }; let SimpleAssignmentTarget::ComputedMemberExpression(member) = &mut update_expr.argument @@ -438,7 +438,7 @@ impl<'a> ClassPropertiesSuperConverter<'a, '_, '_> { let temp_var_name_base = get_var_name_from_node(member.as_ref()); - let property = ctx.ast.move_expression(member.expression.get_inner_expression_mut()); + let property = member.expression.get_inner_expression_mut().take_in(ctx.ast.allocator); *expr = self.transform_super_update_expression_impl( &temp_var_name_base, diff --git a/crates/oxc_transformer/src/es2022/class_static_block.rs b/crates/oxc_transformer/src/es2022/class_static_block.rs index 3b5b257e981d1..d714355de5cde 100644 --- a/crates/oxc_transformer/src/es2022/class_static_block.rs +++ b/crates/oxc_transformer/src/es2022/class_static_block.rs @@ -41,6 +41,7 @@ use itoa::Buffer as ItoaBuffer; +use oxc_allocator::TakeIn; use oxc_ast::{NONE, ast::*}; use oxc_span::SPAN; use oxc_syntax::scope::{ScopeFlags, ScopeId}; @@ -158,7 +159,12 @@ impl ClassStaticBlock { // Always strict mode since we're in a class. *ctx.scoping_mut().scope_flags_mut(scope_id) = ScopeFlags::Function | ScopeFlags::Arrow | ScopeFlags::StrictMode; - wrap_statements_in_arrow_function_iife(ctx.ast.move_vec(stmts), scope_id, block.span, ctx) + wrap_statements_in_arrow_function_iife( + stmts.take_in(ctx.ast.allocator), + scope_id, + block.span, + ctx, + ) } /// Convert static block to expression which will be value of private field, @@ -169,7 +175,7 @@ impl ClassStaticBlock { scope_id: ScopeId, ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { - let expr = ctx.ast.move_expression(expr); + let expr = expr.take_in(ctx.ast.allocator); // Remove the scope for the static block from the scope chain ctx.remove_scope_for_expression(scope_id, &expr); diff --git a/crates/oxc_transformer/src/jsx/jsx_impl.rs b/crates/oxc_transformer/src/jsx/jsx_impl.rs index d2ebe8135b5f3..9b4a2969e2198 100644 --- a/crates/oxc_transformer/src/jsx/jsx_impl.rs +++ b/crates/oxc_transformer/src/jsx/jsx_impl.rs @@ -88,7 +88,7 @@ //! //! * Babel plugin implementation: -use oxc_allocator::{Box as ArenaBox, Vec as ArenaVec}; +use oxc_allocator::{Box as ArenaBox, TakeIn, Vec as ArenaVec}; use oxc_ast::{AstBuilder, NONE, ast::*}; use oxc_ecmascript::PropName; use oxc_span::{Atom, SPAN, Span}; @@ -499,7 +499,7 @@ impl<'a> Traverse<'a> for JsxImpl<'a, '_> { if !matches!(expr, Expression::JSXElement(_) | Expression::JSXFragment(_)) { return; } - *expr = match ctx.ast.move_expression(expr) { + *expr = match expr.take_in(ctx.ast.allocator) { Expression::JSXElement(e) => self.transform_jsx_element(e, ctx), Expression::JSXFragment(e) => self.transform_jsx(e.span, None, e.unbox().children, ctx), _ => unreachable!(), diff --git a/crates/oxc_transformer/src/jsx/refresh.rs b/crates/oxc_transformer/src/jsx/refresh.rs index d67f029a8e991..9bc11d8023a6c 100644 --- a/crates/oxc_transformer/src/jsx/refresh.rs +++ b/crates/oxc_transformer/src/jsx/refresh.rs @@ -7,7 +7,7 @@ use base64::{ use rustc_hash::FxHashMap; use sha1::{Digest, Sha1}; -use oxc_allocator::{Address, CloneIn, GetAddress, String as ArenaString, Vec as ArenaVec}; +use oxc_allocator::{Address, CloneIn, GetAddress, String as ArenaString, TakeIn, Vec as ArenaVec}; use oxc_ast::{AstBuilder, NONE, ast::*, match_expression}; use oxc_semantic::{Reference, ReferenceFlags, ScopeFlags, ScopeId, SymbolFlags}; use oxc_span::{Atom, GetSpan, SPAN}; @@ -250,7 +250,7 @@ impl<'a> Traverse<'a> for ReactRefresh<'a, '_> { Some((binding_identifier.clone(), arguments.clone_in(ctx.ast.allocator))); } - arguments.insert(0, Argument::from(ctx.ast.move_expression(expr))); + arguments.insert(0, Argument::from(expr.take_in(ctx.ast.allocator))); *expr = ctx.ast.expression_call( SPAN, binding.create_read_expression(ctx), @@ -503,7 +503,7 @@ impl<'a> ReactRefresh<'a, '_> { SPAN, AssignmentOperator::Assign, self.create_registration(ctx.ast.atom(inferred_name), ctx), - ctx.ast.move_expression(expr), + expr.take_in(ctx.ast.allocator), ); } diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index 9704c4078ed64..d8895ea85bfdf 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -7,7 +7,7 @@ use std::path::Path; -use oxc_allocator::{Allocator, Vec as ArenaVec}; +use oxc_allocator::{Allocator, TakeIn, Vec as ArenaVec}; use oxc_ast::{AstBuilder, ast::*}; use oxc_diagnostics::OxcDiagnostic; use oxc_semantic::Scoping; @@ -531,7 +531,7 @@ impl<'a> Traverse<'a> for TransformerImpl<'a, '_> { let Statement::ExpressionStatement(expr_stmt) = stmt else { continue; }; - let expression = Some(ctx.ast.move_expression(&mut expr_stmt.expression)); + let expression = Some(expr_stmt.expression.take_in(ctx.ast.allocator)); *stmt = ctx.ast.statement_return(SPAN, expression); return; } diff --git a/crates/oxc_transformer/src/plugins/module_runner_transform.rs b/crates/oxc_transformer/src/plugins/module_runner_transform.rs index 5a5828774399b..ff31c26c9ef95 100644 --- a/crates/oxc_transformer/src/plugins/module_runner_transform.rs +++ b/crates/oxc_transformer/src/plugins/module_runner_transform.rs @@ -50,7 +50,7 @@ use std::iter; use itoa::Buffer as ItoaBuffer; use rustc_hash::{FxHashMap, FxHashSet}; -use oxc_allocator::{Allocator, Box as ArenaBox, Vec as ArenaVec}; +use oxc_allocator::{Allocator, Box as ArenaBox, TakeIn, Vec as ArenaVec}; use oxc_ast::{NONE, ast::*}; use oxc_ecmascript::BoundNames; use oxc_semantic::{ReferenceFlags, ScopeFlags, Scoping, SymbolFlags, SymbolId}; @@ -253,7 +253,7 @@ impl<'a> ModuleRunnerTransform<'a> { /// Transform `import(source, ...arguments)` to `__vite_ssr_dynamic_import__(source, ...arguments)`. #[inline] fn transform_dynamic_import(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { - let Expression::ImportExpression(import_expr) = ctx.ast.move_expression(expr) else { + let Expression::ImportExpression(import_expr) = expr.take_in(ctx.ast.allocator) else { unreachable!(); }; diff --git a/crates/oxc_transformer/src/proposals/explicit_resource_management.rs b/crates/oxc_transformer/src/proposals/explicit_resource_management.rs index a0f38ed4421dc..bb7c7b63d5ab7 100644 --- a/crates/oxc_transformer/src/proposals/explicit_resource_management.rs +++ b/crates/oxc_transformer/src/proposals/explicit_resource_management.rs @@ -37,7 +37,7 @@ use std::mem; use rustc_hash::FxHashMap; -use oxc_allocator::{Address, Box as ArenaBox, GetAddress, Vec as ArenaVec}; +use oxc_allocator::{Address, Box as ArenaBox, GetAddress, TakeIn, Vec as ArenaVec}; use oxc_ast::{NONE, ast::*}; use oxc_ecmascript::BoundNames; use oxc_semantic::{ScopeFlags, ScopeId, SymbolFlags}; @@ -129,7 +129,7 @@ impl<'a> Traverse<'a> for ExplicitResourceManagement<'a, '_> { body.body.insert(0, using_stmt); } else { // `for (const _x of y) x();` -> `for (const _x of y) { using x = _x; x(); }` - let old_body = ctx.ast.move_statement(&mut for_of_stmt.body); + let old_body = for_of_stmt.body.take_in(ctx.ast.allocator); let new_body = ctx.ast.vec_from_array([using_stmt, old_body]); for_of_stmt.body = ctx.ast.statement_block_with_scope_id(SPAN, new_body, scope_id); @@ -303,7 +303,7 @@ impl<'a> Traverse<'a> for ExplicitResourceManagement<'a, '_> { return; } - let program_body = ctx.ast.move_vec(&mut program.body); + let program_body = program.body.take_in(ctx.ast.allocator); let (mut program_body, inner_block): ( ArenaVec<'a, Statement<'a>>, @@ -412,9 +412,8 @@ impl<'a> Traverse<'a> for ExplicitResourceManagement<'a, '_> { return (program_body, inner_block); } - let decl = ctx.ast.move_declaration(decl); - let export_specifiers = match decl { + let export_specifiers = match decl.take_in(ctx.ast.allocator) { Declaration::ClassDeclaration(class_decl) => { let class_binding = class_decl.id.as_ref().unwrap(); let class_binding_name = class_binding.name; @@ -661,7 +660,7 @@ impl<'a> ExplicitResourceManagement<'a, '_> { )), false, )), - ctx.ast.move_statement(stmt), + stmt.take_in(ctx.ast.allocator), ]); ctx.ast.block_statement_with_scope_id(SPAN, vec, block_stmt_sid) @@ -756,7 +755,7 @@ impl<'a> ExplicitResourceManagement<'a, '_> { let using_ctx = using_ctx?; - let mut stmts = ctx.ast.move_vec(stmts); + let mut stmts = stmts.take_in(ctx.ast.allocator); // `var _usingCtx = babelHelpers.usingCtx();` let callee = self.ctx.helper_load(Helper::UsingCtx, ctx); diff --git a/crates/oxc_transformer/src/typescript/annotations.rs b/crates/oxc_transformer/src/typescript/annotations.rs index d3fbf5b24ff7c..2dfe90dc81577 100644 --- a/crates/oxc_transformer/src/typescript/annotations.rs +++ b/crates/oxc_transformer/src/typescript/annotations.rs @@ -1,6 +1,6 @@ use rustc_hash::FxHashSet; -use oxc_allocator::Vec as ArenaVec; +use oxc_allocator::{TakeIn, Vec as ArenaVec}; use oxc_ast::ast::*; use oxc_diagnostics::OxcDiagnostic; use oxc_semantic::SymbolFlags; @@ -203,7 +203,7 @@ impl<'a> Traverse<'a> for TypeScriptAnnotations<'a, '_> { fn enter_chain_element(&mut self, element: &mut ChainElement<'a>, ctx: &mut TraverseCtx<'a>) { if let ChainElement::TSNonNullExpression(e) = element { - *element = match ctx.ast.move_expression(e.expression.get_inner_expression_mut()) { + *element = match e.expression.get_inner_expression_mut().take_in(ctx.ast.allocator) { Expression::CallExpression(call_expr) => ChainElement::CallExpression(call_expr), expr @ match_member_expression!(Expression) => { ChainElement::from(expr.into_member_expression()) @@ -248,7 +248,7 @@ impl<'a> Traverse<'a> for TypeScriptAnnotations<'a, '_> { fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { if expr.is_typescript_syntax() { let inner_expr = expr.get_inner_expression_mut(); - *expr = ctx.ast.move_expression(inner_expr); + *expr = inner_expr.take_in(ctx.ast.allocator); } } @@ -261,7 +261,7 @@ impl<'a> Traverse<'a> for TypeScriptAnnotations<'a, '_> { match expr.get_inner_expression_mut() { // `foo!++` to `foo++` inner_expr @ Expression::Identifier(_) => { - let inner_expr = ctx.ast.move_expression(inner_expr); + let inner_expr = inner_expr.take_in(ctx.ast.allocator); let Expression::Identifier(ident) = inner_expr else { unreachable!(); }; @@ -269,7 +269,7 @@ impl<'a> Traverse<'a> for TypeScriptAnnotations<'a, '_> { } // `foo.bar!++` to `foo.bar++` inner_expr @ match_member_expression!(Expression) => { - let inner_expr = ctx.ast.move_expression(inner_expr); + let inner_expr = inner_expr.take_in(ctx.ast.allocator); let member_expr = inner_expr.into_member_expression(); *target = SimpleAssignmentTarget::from(member_expr); } @@ -289,7 +289,7 @@ impl<'a> Traverse<'a> for TypeScriptAnnotations<'a, '_> { if let Some(expr) = target.get_expression_mut() { let inner_expr = expr.get_inner_expression_mut(); if inner_expr.is_member_expression() { - let inner_expr = ctx.ast.move_expression(inner_expr); + let inner_expr = inner_expr.take_in(ctx.ast.allocator); let member_expr = inner_expr.into_member_expression(); *target = AssignmentTarget::from(member_expr); } @@ -481,7 +481,7 @@ impl<'a> Traverse<'a> for TypeScriptAnnotations<'a, '_> { _ => None, }; if let Some(span) = consequent_span { - let consequent = ctx.ast.move_statement(&mut stmt.consequent); + let consequent = stmt.consequent.take_in(ctx.ast.allocator); stmt.consequent = Self::create_block_with_statement(consequent, span, ctx); } diff --git a/crates/oxc_transformer/src/typescript/enum.rs b/crates/oxc_transformer/src/typescript/enum.rs index 2b61cbd4161bb..d39aeefb7c360 100644 --- a/crates/oxc_transformer/src/typescript/enum.rs +++ b/crates/oxc_transformer/src/typescript/enum.rs @@ -1,7 +1,7 @@ use rustc_hash::FxHashMap; use std::cell::Cell; -use oxc_allocator::Vec as ArenaVec; +use oxc_allocator::{TakeIn, Vec as ArenaVec}; use oxc_ast::{NONE, ast::*}; use oxc_ast_visit::{VisitMut, walk_mut}; use oxc_data_structures::stack::NonEmptyStack; @@ -228,7 +228,7 @@ impl<'a> TypeScriptEnum<'a> { let init = match constant_value { None => { prev_constant_value = None; - let mut new_initializer = ast.move_expression(initializer); + let mut new_initializer = initializer.take_in(ast.allocator); IdentifierReferenceRename::new( param_binding.name, diff --git a/crates/oxc_transformer/src/typescript/module.rs b/crates/oxc_transformer/src/typescript/module.rs index d9df9e23fd5f9..74cc9076ef69a 100644 --- a/crates/oxc_transformer/src/typescript/module.rs +++ b/crates/oxc_transformer/src/typescript/module.rs @@ -1,3 +1,4 @@ +use oxc_allocator::TakeIn; use oxc_ast::{NONE, ast::*}; use oxc_semantic::{Reference, SymbolFlags}; use oxc_span::SPAN; @@ -73,7 +74,7 @@ impl<'a> TypeScriptModule<'a, '_> { }; let left = AssignmentTarget::from(SimpleAssignmentTarget::from(module_exports)); - let right = ctx.ast.move_expression(&mut export_assignment.expression); + let right = export_assignment.expression.take_in(ctx.ast.allocator); let assignment_expr = ctx.ast.expression_assignment(SPAN, AssignmentOperator::Assign, left, right); ctx.ast.statement_expression(SPAN, assignment_expr) diff --git a/crates/oxc_transformer/src/typescript/namespace.rs b/crates/oxc_transformer/src/typescript/namespace.rs index 5e88eefa72e9c..08bc1c56cea65 100644 --- a/crates/oxc_transformer/src/typescript/namespace.rs +++ b/crates/oxc_transformer/src/typescript/namespace.rs @@ -1,4 +1,4 @@ -use oxc_allocator::{Box as ArenaBox, Vec as ArenaVec}; +use oxc_allocator::{Box as ArenaBox, TakeIn, Vec as ArenaVec}; use oxc_ast::{NONE, ast::*}; use oxc_ecmascript::BoundNames; use oxc_semantic::Reference; @@ -49,7 +49,7 @@ impl<'a> Traverse<'a> for TypeScriptNamespace<'a, '_> { // every time a namespace declaration is encountered. let mut new_stmts = ctx.ast.vec(); - for stmt in ctx.ast.move_vec(&mut program.body) { + for stmt in program.body.take_in(ctx.ast.allocator) { match stmt { Statement::TSModuleDeclaration(decl) => { if !self.allow_namespaces { @@ -430,7 +430,7 @@ impl<'a> TypeScriptNamespace<'a, '_> { false, )) .into(), - ctx.ast.move_expression(init), + init.take_in(ctx.ast.allocator), ), ); }