Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 38 additions & 21 deletions crates/oxc_transformer/src/es2016/exponentiation_operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ impl<'a, 'ctx> Traverse<'a> for ExponentiationOperator<'a, 'ctx> {
// NOTE: Bail bigint arguments to `Math.pow`, which are runtime errors.
fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
match expr {
// left ** right
// `left ** right`
Expression::BinaryExpression(binary_expr) => {
if binary_expr.operator != BinaryOperator::Exponential
|| binary_expr.left.is_big_int_literal()
Expand All @@ -74,41 +74,58 @@ impl<'a, 'ctx> Traverse<'a> for ExponentiationOperator<'a, 'ctx> {
return;
}

let left = ctx.ast.move_expression(&mut binary_expr.left);
let right = ctx.ast.move_expression(&mut binary_expr.right);
*expr = Self::math_pow(left, right, ctx);
Self::convert_binary_expression(expr, ctx);
}
// left **= right
// `left **= right`
Expression::AssignmentExpression(assign_expr) => {
if assign_expr.operator != AssignmentOperator::Exponential
|| assign_expr.right.is_big_int_literal()
{
return;
}

let mut nodes = ctx.ast.vec();
let Some(Exploded { reference, uid }) =
self.explode(&mut assign_expr.left, &mut nodes, ctx)
else {
return;
};
let right = ctx.ast.move_expression(&mut assign_expr.right);
let right = Self::math_pow(uid, right, ctx);
let assign_expr = ctx.ast.expression_assignment(
SPAN,
AssignmentOperator::Assign,
reference,
right,
);
nodes.push(assign_expr);
*expr = ctx.ast.expression_sequence(SPAN, nodes);
self.convert_assignment_expression(expr, ctx);
}
_ => {}
}
}
}

impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> {
/// Convert `BinaryExpression`.
/// `left ** right` -> `Math.pow(left, right)`
fn convert_binary_expression(expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
let binary_expr = match ctx.ast.move_expression(expr) {
Expression::BinaryExpression(binary_expr) => binary_expr.unbox(),
_ => unreachable!(),
};
*expr = Self::math_pow(binary_expr.left, binary_expr.right, ctx);
}

/// Convert `AssignmentExpression`.
// `left **= right` -> `left = Math.pow(left, right)`
fn convert_assignment_expression(
&mut self,
expr: &mut Expression<'a>,
ctx: &mut TraverseCtx<'a>,
) {
let Expression::AssignmentExpression(assign_expr) = expr else { unreachable!() };

let mut nodes = ctx.ast.vec();
let Some(Exploded { reference, uid }) =
self.explode(&mut assign_expr.left, &mut nodes, ctx)
else {
return;
};
let right = ctx.ast.move_expression(&mut assign_expr.right);
let right = Self::math_pow(uid, right, ctx);
let assign_expr =
ctx.ast.expression_assignment(SPAN, AssignmentOperator::Assign, reference, right);
nodes.push(assign_expr);

*expr = ctx.ast.expression_sequence(SPAN, nodes);
}

fn clone_expression(expr: &Expression<'a>, ctx: &mut TraverseCtx<'a>) -> Expression<'a> {
match expr {
Expression::Identifier(ident) => ctx.ast.expression_from_identifier_reference(
Expand Down