diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index e2c7fc5e3..0f64bb4eb 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -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); diff --git a/tasks/transform_conformance/oxc.snap.md b/tasks/transform_conformance/oxc.snap.md index 57949f650..e7f97fc25 100644 --- a/tasks/transform_conformance/oxc.snap.md +++ b/tasks/transform_conformance/oxc.snap.md @@ -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: diff --git a/tasks/transform_conformance/tests/babel-plugin-transform-nullish-coalescing-operator/test/fixtures/options.json b/tasks/transform_conformance/tests/babel-plugin-transform-nullish-coalescing-operator/test/fixtures/options.json new file mode 100644 index 000000000..30d908eec --- /dev/null +++ b/tasks/transform_conformance/tests/babel-plugin-transform-nullish-coalescing-operator/test/fixtures/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["transform-nullish-coalescing-operator"] +} diff --git a/tasks/transform_conformance/tests/babel-plugin-transform-nullish-coalescing-operator/test/fixtures/transform-in-arrow-function-expression/input.js b/tasks/transform_conformance/tests/babel-plugin-transform-nullish-coalescing-operator/test/fixtures/transform-in-arrow-function-expression/input.js new file mode 100644 index 000000000..ce98f5b2d --- /dev/null +++ b/tasks/transform_conformance/tests/babel-plugin-transform-nullish-coalescing-operator/test/fixtures/transform-in-arrow-function-expression/input.js @@ -0,0 +1 @@ +(() => a ?? b); diff --git a/tasks/transform_conformance/tests/babel-plugin-transform-nullish-coalescing-operator/test/fixtures/transform-in-arrow-function-expression/output.js b/tasks/transform_conformance/tests/babel-plugin-transform-nullish-coalescing-operator/test/fixtures/transform-in-arrow-function-expression/output.js new file mode 100644 index 000000000..68b246e84 --- /dev/null +++ b/tasks/transform_conformance/tests/babel-plugin-transform-nullish-coalescing-operator/test/fixtures/transform-in-arrow-function-expression/output.js @@ -0,0 +1,4 @@ +() => { + var _a; + return (_a = a) !== null && _a !== void 0 ? _a : b; +};