fix(transformer): ArrowfunctionExpression's expression is true but has more than one body statement (#5366)

close: #5363

We insert the new statement here, but it's broken if it a `() => x;`, we need to transform it to `function () { return x }`

8d565d5b23/crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs (L59-L76)

I don't where we should put the fallback logic, It's useful for all plugins. We had already done the same thing in the react refresh plugin.

8d565d5b23/crates/oxc_transformer/src/react/refresh.rs (L578-L605)
This commit is contained in:
Dunqing 2024-08-31 14:49:58 +00:00
parent e75e0f1465
commit 35f03db464
5 changed files with 40 additions and 2 deletions

View file

@ -39,7 +39,7 @@ use oxc_allocator::{Allocator, Vec};
use oxc_ast::{ast::*, Trivias};
use oxc_diagnostics::OxcDiagnostic;
use oxc_semantic::{ScopeTree, SymbolTable};
use oxc_span::SourceType;
use oxc_span::{SourceType, SPAN};
use oxc_traverse::{traverse_mut, Traverse, TraverseCtx};
pub use crate::{
@ -284,6 +284,28 @@ impl<'a> Traverse<'a> for Transformer<'a> {
self.x2_es2016.enter_statements(stmts, ctx);
}
fn exit_arrow_function_expression(
&mut self,
arrow: &mut ArrowFunctionExpression<'a>,
ctx: &mut TraverseCtx<'a>,
) {
// Some plugins may add new statements to the ArrowFunctionExpression's body,
// 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)));
arrow.expression = false;
}
}
fn exit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_statements_on_exit(stmts, ctx);
self.x1_react.transform_statements_on_exit(stmts, ctx);

View file

@ -1,12 +1,20 @@
commit: 3bcfee23
Passed: 10/37
Passed: 10/38
# All Passed:
* babel-plugin-transform-optional-catch-binding
* babel-plugin-transform-arrow-functions
# babel-plugin-transform-nullish-coalescing-operator (0/1)
* transform-in-arrow-function-expression/input.js
x Reference flags mismatch:
| after transform: ReferenceId(3): ReferenceFlags(Write)
| rebuilt : ReferenceId(0): ReferenceFlags(Read | Write)
# babel-plugin-transform-typescript (2/8)
* class-property-definition/input.ts
x Unresolved references mismatch:

View file

@ -0,0 +1,3 @@
{
"plugins": ["transform-nullish-coalescing-operator"]
}

View file

@ -0,0 +1,4 @@
() => {
var _a;
return (_a = a) !== null && _a !== void 0 ? _a : b;
};