Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
refactor: align with babel without cloning.
  • Loading branch information
7086cmd committed Sep 30, 2024
commit facd2e271e99cb4d7cbc566e0514d34533450b28
161 changes: 116 additions & 45 deletions crates/oxc_transformer/src/es2017/async_to_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@
//!

use crate::context::Ctx;
use oxc_allocator::CloneIn;
use oxc_ast::ast::{ArrowFunctionExpression, Expression, FormalParameterKind, Function, FunctionType, Statement, YieldExpression};
use oxc_ast::ast::{
ArrowFunctionExpression, Expression, FormalParameterKind, Function, FunctionType, Statement,
VariableDeclarationKind, YieldExpression,
};
use oxc_ast::NONE;
use oxc_span::{Atom, SPAN};
use oxc_syntax::reference::ReferenceFlags;
Expand All @@ -68,6 +70,65 @@ impl<'a> AsyncToGenerator<'a> {
let property = ctx.ast.identifier_name(SPAN, Atom::from("asyncToGenerator"));
Expression::from(ctx.ast.member_expression_static(SPAN, object, property, false))
}

fn transform_function(func: &mut Function<'a>, ctx: &mut TraverseCtx<'a>) -> Function<'a> {
let babel_helpers_id =
ctx.scopes().find_binding(ctx.current_scope_id(), "babelHelpers");
let callee = Self::get_helper_callee(babel_helpers_id, ctx);
let target = ctx.ast.function(
func.r#type,
SPAN,
None,
true,
false,
false,
func.type_parameters.take(),
func.this_param.take(),
ctx.ast.alloc(ctx.ast.formal_parameters(
SPAN,
FormalParameterKind::FormalParameter,
ctx.ast.vec(),
NONE,
)),
func.return_type.take(),
func.body.take(),
);
let parameters =
ctx.ast.vec1(ctx.ast.argument_expression(ctx.ast.expression_from_function(target)));
let call = ctx.ast.expression_call(SPAN, callee, NONE, parameters, false);
let call = ctx.ast.expression_member(ctx.ast.member_expression_static(
SPAN,
call,
ctx.ast.identifier_name(SPAN, "apply"),
false
));
let call = ctx.ast.expression_call(SPAN, call, NONE, {
let mut items = ctx.ast.vec();
items.push(ctx.ast.argument_expression(ctx.ast.expression_this(SPAN)));
items.push(ctx.ast.argument_expression(
ctx.ast.expression_identifier_reference(SPAN, "arguments"),
));
items
}, false);
let returns = ctx.ast.return_statement(SPAN, Some(call));
let body = Statement::ReturnStatement(ctx.ast.alloc(returns));
let body = ctx.ast.function_body(SPAN, ctx.ast.vec(), ctx.ast.vec1(body));
let body = ctx.ast.alloc(body);
let params = ctx.ast.formal_parameters(SPAN, func.params.kind, ctx.ast.move_vec(&mut func.params.items), func.params.rest.take());
ctx.ast.function(
FunctionType::FunctionExpression,
SPAN,
None,
false,
false,
false,
func.type_parameters.take(),
func.this_param.take(),
params,
func.return_type.take(),
Some(body)
)
}
}

impl<'a> Traverse<'a> for AsyncToGenerator<'a> {
Expand All @@ -84,7 +145,7 @@ impl<'a> Traverse<'a> for AsyncToGenerator<'a> {
} else {
None
}
} else if let Ancestor::ArrowFunctionExpressionBody(body) = ance {
} else if let Ancestor::ArrowFunctionExpressionBody(_) = ance {
Some(true)
} else {
None
Expand All @@ -100,54 +161,55 @@ impl<'a> Traverse<'a> for AsyncToGenerator<'a> {
let expression = ctx.ast.alloc(yield_expression);
*expr = Expression::YieldExpression(expression);
}
} else if let Expression::FunctionExpression(func) = expr {
if !func.r#async || func.generator { return }
let new_function = Self::transform_function(func, ctx);
*expr = ctx.ast.expression_from_function(new_function);
}
}

fn exit_function(&mut self, func: &mut Function<'a>, ctx: &mut TraverseCtx<'a>) {
let babel_helpers_id = ctx.scopes().find_binding(ctx.current_scope_id(), "babelHelpers");
let callee = Self::get_helper_callee(babel_helpers_id, ctx);
let target = ctx.ast.function(
func.r#type.clone(),
SPAN,
func.id.clone(),
true,
false,
false,
func.type_parameters.take(),
func.this_param.take(),
ctx.ast.alloc(ctx.ast.formal_parameters(
SPAN,
FormalParameterKind::FormalParameter,
ctx.ast.vec(),
NONE,
)),
func.return_type.take(),
func.body.take()
);
let parameters = {
let mut items = ctx.ast.vec();
items.push(ctx.ast.argument_expression(ctx.ast.expression_this(SPAN)));
items.push(ctx.ast.argument_expression(ctx.ast.expression_null_literal(SPAN)));
items.push(ctx.ast.argument_expression(ctx.ast.expression_from_function(target)));
items
};
let call = ctx.ast.expression_call(SPAN, callee, NONE, parameters, false);
let returns = ctx.ast.return_statement(SPAN, Some(call));
let body = Statement::ReturnStatement(ctx.ast.alloc(returns));
let body = ctx.ast.function_body(SPAN, ctx.ast.vec(), ctx.ast.vec1(body));
let body = ctx.ast.alloc(body);
func.r#async = false;
func.body = Some(body);
fn exit_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) {
if let Statement::FunctionDeclaration(func) = stmt {
if !func.r#async || func.generator { return }
let new_function = Self::transform_function(func, ctx);
if let Some(id) = func.id.take() {
*stmt = ctx.ast.statement_declaration(ctx.ast.declaration_variable(
SPAN,
VariableDeclarationKind::Const,
ctx.ast.vec1(ctx.ast.variable_declarator(
SPAN,
VariableDeclarationKind::Const,
ctx.ast.binding_pattern(
ctx.ast.binding_pattern_kind_from_binding_identifier(id),
NONE,
false,
),
Some(ctx.ast.expression_from_function(new_function)),
false,
)),
false,
));
} else {
*stmt = ctx.ast.statement_declaration(ctx.ast.declaration_from_function(new_function));
}
}
}

fn exit_arrow_function_expression(
&mut self,
arrow: &mut ArrowFunctionExpression<'a>,
ctx: &mut TraverseCtx<'a>,
) {
if !arrow.r#async {
return;
}
let babel_helpers_id = ctx.scopes().find_binding(ctx.current_scope_id(), "babelHelpers");
let callee = Self::get_helper_callee(babel_helpers_id, ctx);
let body = ctx.ast.function_body(SPAN, ctx.ast.move_vec(&mut arrow.body.directives), ctx.ast.move_vec(&mut arrow.body.statements));
let body = ctx.ast.function_body(
SPAN,
ctx.ast.move_vec(&mut arrow.body.directives),
ctx.ast.move_vec(&mut arrow.body.statements),
);
let target = ctx.ast.function(
FunctionType::FunctionExpression,
SPAN,
Expand All @@ -164,16 +226,25 @@ impl<'a> Traverse<'a> for AsyncToGenerator<'a> {
NONE,
)),
arrow.return_type.take(),
Some(body)
Some(body),
);
let parameters = {
let parameters =
ctx.ast.vec1(ctx.ast.argument_expression(ctx.ast.expression_from_function(target)));
let call = ctx.ast.expression_call(SPAN, callee, NONE, parameters, false);
let call = ctx.ast.expression_member(ctx.ast.member_expression_static(
SPAN,
call,
ctx.ast.identifier_name(SPAN, "apply"),
false
));
let call = ctx.ast.expression_call(SPAN, call, NONE, {
let mut items = ctx.ast.vec();
items.push(ctx.ast.argument_expression(ctx.ast.expression_this(SPAN)));
items.push(ctx.ast.argument_expression(ctx.ast.expression_null_literal(SPAN)));
items.push(ctx.ast.argument_expression(ctx.ast.expression_from_function(target)));
items.push(ctx.ast.argument_expression(
ctx.ast.expression_identifier_reference(SPAN, "arguments"),
));
items
};
let call = ctx.ast.expression_call(SPAN, callee, NONE, parameters, false);
}, false);
let returns = ctx.ast.return_statement(SPAN, Some(call));
let body = Statement::ReturnStatement(ctx.ast.alloc(returns));
let body = ctx.ast.function_body(SPAN, ctx.ast.vec(), ctx.ast.vec1(body));
Expand Down
6 changes: 3 additions & 3 deletions crates/oxc_transformer/src/es2017/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub mod options;
use crate::context::Ctx;
use crate::es2017::async_to_generator::AsyncToGenerator;
use crate::es2017::options::ES2017Options;
use oxc_ast::ast::{ArrowFunctionExpression, Expression, Function};
use oxc_ast::ast::{ArrowFunctionExpression, Expression, Statement};
use oxc_traverse::{Traverse, TraverseCtx};
use std::rc::Rc;

Expand All @@ -30,9 +30,9 @@ impl<'a> Traverse<'a> for ES2017<'a> {
}
}

fn exit_function(&mut self, node: &mut Function<'a>, ctx: &mut TraverseCtx<'a>) {
fn exit_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) {
if self.options.async_to_generator {
self.async_to_generator.exit_function(node, ctx);
self.async_to_generator.exit_statement(stmt, ctx);
}
}

Expand Down
4 changes: 4 additions & 0 deletions crates/oxc_transformer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,10 @@ impl<'a, 'ctx> Traverse<'a> for TransformerImpl<'a, 'ctx> {
self.common.exit_statements(stmts, ctx);
}

fn exit_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) {
self.x2_es2017.exit_statement(stmt, ctx);
}

fn enter_tagged_template_expression(
&mut self,
expr: &mut TaggedTemplateExpression<'a>,
Expand Down
23 changes: 3 additions & 20 deletions tasks/transform_conformance/snapshots/babel.snap.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
commit: 3bcfee23

Passed: 330/1024
Passed: 333/1022

# All Passed:
* babel-plugin-transform-optional-catch-binding
Expand All @@ -10,7 +10,7 @@ Passed: 330/1024
* babel-plugin-transform-react-jsx-source


# babel-preset-env (106/585)
# babel-preset-env (109/585)
* .plugins-overlapping/chrome-49/input.js
x Output mismatch

Expand Down Expand Up @@ -230,9 +230,6 @@ x Output mismatch
* corejs2-babel-7/usage-regenerator-used-generator/input.mjs
x Output mismatch

* corejs2-babel-7/usage-regenerator-used-generator-native-support/input.mjs
x Output mismatch

* corejs2-babel-7/usage-remove-babel-polyfill-import/input.mjs
x Output mismatch

Expand Down Expand Up @@ -440,9 +437,6 @@ x Output mismatch
* corejs3/usage-regenerator-used-async-native-support/input.mjs
x Output mismatch

* corejs3/usage-regenerator-used-generator-native-support/input.mjs
x Output mismatch

* corejs3/usage-shippedProposals/input.mjs
x Output mismatch

Expand Down Expand Up @@ -701,9 +695,6 @@ x Output mismatch
* corejs3-babel-7/usage-regenerator-used-generator/input.mjs
x Output mismatch

* corejs3-babel-7/usage-regenerator-used-generator-native-support/input.mjs
x Output mismatch

* corejs3-babel-7/usage-shippedProposals/input.mjs
x Output mismatch

Expand Down Expand Up @@ -1665,14 +1656,6 @@ x Output mismatch
x Output mismatch


# babel-plugin-transform-async-to-generator (0/2)
* assumption-ignoreFunctionLength-true/basic/input.mjs
x Output mismatch

* assumption-ignoreFunctionLength-true/export-default-function/input.mjs
x Output mismatch


# babel-plugin-transform-exponentiation-operator (1/4)
* exponentiation-operator/assignment/input.js
Symbol reference IDs mismatch:
Expand Down Expand Up @@ -3462,7 +3445,7 @@ x Output mismatch
`----


* cross-platform/within-ts-module-block/input.tsx
* cross-platform/within-ts-module-block/input.ts
x Output mismatch


19 changes: 1 addition & 18 deletions tasks/transform_conformance/snapshots/babel_exec.snap.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
commit: 3bcfee23

Passed: 33/60
Passed: 32/54

# All Passed:
* babel-plugin-transform-logical-assignment-operators
Expand Down Expand Up @@ -74,23 +74,6 @@ exec failed
exec failed


# babel-plugin-transform-async-to-generator (1/6)
* regression/15978/exec.js
exec failed

* regression/8783/exec.js
exec failed

* regression/T6882/exec.js
exec failed

* regression/fn-name/exec.js
exec failed

* regression/test262-fn-length/exec.js
exec failed


# babel-plugin-transform-react-jsx-source (0/2)
* react-source/basic-sample/exec.js
exec failed
Expand Down
2 changes: 1 addition & 1 deletion tasks/transform_conformance/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub(crate) const PLUGINS: &[&str] = &[
// "babel-plugin-transform-dotall-regex",
// // [Regex] "babel-plugin-transform-named-capturing-groups-regex",
// // ES2017
"babel-plugin-transform-async-to-generator",
// "babel-plugin-transform-async-to-generator",
// ES2016
"babel-plugin-transform-exponentiation-operator",
// ES2015
Expand Down