Skip to content

Commit

Permalink
perf(transformer): call transform_jsx in exit_expression rather t…
Browse files Browse the repository at this point in the history
…han `enter_expression` (#5751)

### Difference

In `enter_expression`: Recursive transform JSX
In `exit_expression`: Deep first transform

After the change,  `transform_jsx` still has a lot of room for improvement.
  • Loading branch information
Dunqing committed Sep 13, 2024
1 parent aac8316 commit 36e698b
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 31 deletions.
44 changes: 37 additions & 7 deletions crates/oxc_transformer/src/es2015/arrow_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,17 +131,37 @@ impl<'a> Traverse<'a> for ArrowFunctions<'a> {
self.insert_this_var_statement_at_the_top_of_statements(&mut body.statements);
}

fn enter_expression(&mut self, expr: &mut Expression<'a>, _ctx: &mut TraverseCtx<'a>) {
match expr {
Expression::ArrowFunctionExpression(_) => {
self.stacks.push(true);
fn enter_jsx_element_name(
&mut self,
element_name: &mut JSXElementName<'a>,
ctx: &mut TraverseCtx<'a>,
) {
if let JSXElementName::ThisExpression(this) = element_name {
if !self.is_inside_arrow_function() {
return;
}
Expression::FunctionExpression(_) => self.stacks.push(false),
_ => {}

let ident = self.get_this_name(ctx).create_spanned_read_reference(this.span, ctx);
*element_name = self.ctx.ast.jsx_element_name_from_identifier_reference(ident);
};
}

fn enter_jsx_member_expression_object(
&mut self,
object: &mut JSXMemberExpressionObject<'a>,
ctx: &mut TraverseCtx<'a>,
) {
if let JSXMemberExpressionObject::ThisExpression(this) = object {
if !self.is_inside_arrow_function() {
return;
}

let ident = self.get_this_name(ctx).create_spanned_read_reference(this.span, ctx);
*object = self.ctx.ast.jsx_member_expression_object_from_identifier_reference(ident);
}
}

fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
match expr {
Expression::ThisExpression(this_expr) => {
if !self.is_inside_arrow_function() {
Expand All @@ -152,6 +172,16 @@ impl<'a> Traverse<'a> for ArrowFunctions<'a> {
self.get_this_name(ctx).create_spanned_read_reference(this_expr.span, ctx);
*expr = self.ctx.ast.expression_from_identifier_reference(ident);
}
Expression::ArrowFunctionExpression(_) => {
self.stacks.push(true);
}
Expression::FunctionExpression(_) => self.stacks.push(false),
_ => {}
}
}

fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
match expr {
Expression::ArrowFunctionExpression(arrow_function_expr) => {
*expr = self.transform_arrow_function_expression(arrow_function_expr, ctx);
self.stacks.pop();
Expand Down
16 changes: 16 additions & 0 deletions crates/oxc_transformer/src/es2015/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,20 @@ impl<'a> Traverse<'a> for ES2015<'a> {
self.arrow_functions.enter_variable_declarator(node, ctx);
}
}

fn enter_jsx_element_name(&mut self, node: &mut JSXElementName<'a>, ctx: &mut TraverseCtx<'a>) {
if self.options.arrow_function.is_some() {
self.arrow_functions.enter_jsx_element_name(node, ctx);
}
}

fn enter_jsx_member_expression_object(
&mut self,
node: &mut JSXMemberExpressionObject<'a>,
ctx: &mut TraverseCtx<'a>,
) {
if self.options.arrow_function.is_some() {
self.arrow_functions.enter_jsx_member_expression_object(node, ctx);
}
}
}
12 changes: 12 additions & 0 deletions crates/oxc_transformer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,18 @@ impl<'a> Traverse<'a> for Transformer<'a> {
self.x0_typescript.enter_jsx_element(node, ctx);
}

fn enter_jsx_element_name(&mut self, node: &mut JSXElementName<'a>, ctx: &mut TraverseCtx<'a>) {
self.x3_es2015.enter_jsx_element_name(node, ctx);
}

fn enter_jsx_member_expression_object(
&mut self,
node: &mut JSXMemberExpressionObject<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.x3_es2015.enter_jsx_member_expression_object(node, ctx);
}

fn enter_jsx_fragment(&mut self, node: &mut JSXFragment<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.enter_jsx_fragment(node, ctx);
}
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_transformer/src/react/jsx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ impl<'a> Traverse<'a> for ReactJsx<'a> {
self.add_runtime_imports(program, ctx);
}

fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
*expr = match expr {
Expression::JSXElement(e) => self.transform_jsx(&JSXElementOrFragment::Element(e), ctx),
Expression::JSXFragment(e) => {
Expand Down
21 changes: 10 additions & 11 deletions crates/oxc_transformer/src/react/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,6 @@ impl<'a> Traverse<'a> for React<'a> {
}
}

fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
if self.jsx_plugin {
self.jsx.enter_expression(expr, ctx);
}
}

fn enter_call_expression(
&mut self,
call_expr: &mut CallExpression<'a>,
Expand All @@ -121,15 +115,20 @@ impl<'a> Traverse<'a> for React<'a> {
elem: &mut JSXOpeningElement<'a>,
ctx: &mut TraverseCtx<'a>,
) {
if self.jsx_self_plugin && self.jsx.jsx_self.can_add_self_attribute(ctx) {
self.jsx.jsx_self.enter_jsx_opening_element(elem, ctx);
}
if self.jsx_source_plugin {
self.jsx.jsx_source.enter_jsx_opening_element(elem, ctx);
if !self.jsx_plugin {
if self.jsx_self_plugin && self.jsx.jsx_self.can_add_self_attribute(ctx) {
self.jsx.jsx_self.enter_jsx_opening_element(elem, ctx);
}
if self.jsx_source_plugin {
self.jsx.jsx_source.enter_jsx_opening_element(elem, ctx);
}
}
}

fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
if self.jsx_plugin {
self.jsx.exit_expression(expr, ctx);
}
if self.refresh_plugin {
self.refresh.exit_expression(expr, ctx);
}
Expand Down
12 changes: 6 additions & 6 deletions tasks/coverage/semantic_typescript.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5487,7 +5487,7 @@ Scope children mismatch:
after transform: ScopeId(0): [ScopeId(1), ScopeId(8), ScopeId(9)]
rebuilt : ScopeId(0): [ScopeId(1), ScopeId(2)]
Symbol reference IDs mismatch:
after transform: SymbolId(0): [ReferenceId(6), ReferenceId(14), ReferenceId(17), ReferenceId(18), ReferenceId(20), ReferenceId(23), ReferenceId(24)]
after transform: SymbolId(0): [ReferenceId(6), ReferenceId(15), ReferenceId(16), ReferenceId(18), ReferenceId(21), ReferenceId(22), ReferenceId(24)]
rebuilt : SymbolId(1): [ReferenceId(0), ReferenceId(3), ReferenceId(5), ReferenceId(8), ReferenceId(10), ReferenceId(12)]
Reference symbol mismatch:
after transform: ReferenceId(8): Some("DropdownMenu")
Expand Down Expand Up @@ -21130,10 +21130,13 @@ rebuilt : ["undefined"]
tasks/coverage/typescript/tests/cases/compiler/jsxEmptyExpressionNotCountedAsChild.tsx
semantic error: Bindings mismatch:
after transform: ScopeId(0): ["Props", "React", "Wrapper", "_jsx", "_jsxFileName", "element"]
rebuilt : ScopeId(0): ["Wrapper", "_jsx", "_jsxFileName", "element"]
rebuilt : ScopeId(0): ["React", "Wrapper", "_jsx", "_jsxFileName", "element"]
Scope children mismatch:
after transform: ScopeId(0): [ScopeId(1), ScopeId(2)]
rebuilt : ScopeId(0): [ScopeId(1)]
Symbol reference IDs mismatch:
after transform: SymbolId(0): [ReferenceId(0)]
rebuilt : SymbolId(0): []

tasks/coverage/typescript/tests/cases/compiler/jsxFactoryAndJsxFragmentFactory.tsx
semantic error: Bindings mismatch:
Expand Down Expand Up @@ -21371,10 +21374,7 @@ after transform: ["Function"]
rebuilt : []

tasks/coverage/typescript/tests/cases/compiler/jsxPartialSpread.tsx
semantic error: Bindings mismatch:
after transform: ScopeId(0): ["React", "Repro", "Select", "_jsx", "_jsxFileName"]
rebuilt : ScopeId(0): ["Repro", "Select", "_jsx", "_jsxFileName"]
Symbol reference IDs mismatch:
semantic error: Symbol reference IDs mismatch:
after transform: SymbolId(0): [ReferenceId(2), ReferenceId(3)]
rebuilt : SymbolId(0): [ReferenceId(3)]
Unresolved references mismatch:
Expand Down
8 changes: 2 additions & 6 deletions tasks/transform_conformance/oxc.snap.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
commit: 3bcfee23

Passed: 42/53
Passed: 43/53

# All Passed:
* babel-plugin-transform-nullish-coalescing-operator
* babel-plugin-transform-optional-catch-binding
* babel-plugin-transform-arrow-functions
* babel-preset-typescript
* regexp


# babel-plugin-transform-arrow-functions (1/2)
* with-this-member-expression/input.jsx
x Output mismatch


# babel-plugin-transform-typescript (1/8)
* class-property-definition/input.ts
Unresolved references mismatch:
Expand Down

0 comments on commit 36e698b

Please sign in to comment.