perf(transformer): call transform_jsx in exit_expression rather than 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.
This commit is contained in:
Dunqing 2024-09-13 17:58:41 +00:00
parent aac83168b3
commit 36e698b411
7 changed files with 84 additions and 31 deletions

View file

@ -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() {
@ -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();

View file

@ -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);
}
}
}

View file

@ -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);
}

View file

@ -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) => {

View file

@ -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>,
@ -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);
}

View file

@ -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")
@ -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:
@ -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:

View file

@ -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: