Skip to content

Commit

Permalink
fix(transformer): ensure last expression statement in arrow function …
Browse files Browse the repository at this point in the history
…expression is wrapped in return (#8192)

The class properties plugin will insert new statements after the expression statement, which causes the expression statement to no longer be at the end. This PR fixed it by reverse looping the statements to find the expression statement and transforming it to wrapped in `return`.

This is not a good way to do it, a potential problem is if there is a plugin that inserts a new expression statement after the original expression statement, which will cause a wrong expression wrapped in a `return`
  • Loading branch information
Dunqing committed Dec 31, 2024
1 parent 06e1780 commit 3eaff2a
Showing 1 changed file with 23 additions and 11 deletions.
34 changes: 23 additions & 11 deletions crates/oxc_transformer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,18 +482,30 @@ impl<'a, 'ctx> Traverse<'a> for TransformerImpl<'a, 'ctx> {
// which can cause issues with the `() => x;` case, as it only allows a single statement.
// To address this, we wrap the last statement in a return statement and set the expression to false.
// This transforms the arrow function into the form `() => { return x; };`.
if arrow.expression && arrow.body.statements.len() > 1 {
let Statement::ExpressionStatement(statement) = arrow.body.statements.pop().unwrap()
else {
unreachable!(
"The last statement in an ArrowFunctionExpression should always be an ExpressionStatement."
)
};
arrow
.body
.statements
.push(ctx.ast.statement_return(SPAN, Some(statement.unbox().expression)));
let statements = &mut arrow.body.statements;
if arrow.expression && statements.len() > 1 {
arrow.expression = false;

// Reverse looping to find the expression statement, because other plugins could
// insert new statements after the expression statement.
// `() => x;`
// ->
// ```
// () => {
// var new_insert_variable;
// return x;
// function new_insert_function() {}
// };
// ```
for stmt in statements.iter_mut().rev() {
let Statement::ExpressionStatement(expr_stmt) = stmt else {
continue;
};
let expression = Some(ctx.ast.move_expression(&mut expr_stmt.expression));
*stmt = ctx.ast.statement_return(SPAN, expression);
return;
}
unreachable!("At least one statement should be expression statement")
}
}

Expand Down

0 comments on commit 3eaff2a

Please sign in to comment.