fix(transformer/arrow-functions): reaches unreachable when <this.foo> is inside an arrow function (#5356)

Fixes: https://github.com/oxc-project/oxc/issues/5353#issuecomment-2321792915
This commit is contained in:
Dunqing 2024-09-02 18:06:08 +00:00
parent 01cc2ceac0
commit 94ff94cd34
6 changed files with 58 additions and 17 deletions

View file

@ -137,22 +137,31 @@ impl<'a> Traverse<'a> for ArrowFunctions<'a> {
return;
}
let ident = match name {
JSXElementName::Identifier(ident) => ident,
JSXElementName::MemberExpression(member_expr) => {
member_expr.get_object_identifier_mut()
if let JSXElementName::Identifier(ident) = name {
if ident.name == "this" {
let mut new_ident = self.get_this_name(ctx).create_read_reference(ctx);
new_ident.span = ident.span;
*name = self.ctx.ast.jsx_element_name_from_identifier_reference(new_ident);
}
}
}
/// Change <this.foo></this.foo> to <_this.foo></_this.foo>, and mark it as found
fn enter_jsx_member_expression_object(
&mut self,
node: &mut JSXMemberExpressionObject<'a>,
ctx: &mut TraverseCtx<'a>,
) {
if !self.is_inside_arrow_function() {
return;
}
if let JSXMemberExpressionObject::IdentifierReference(ident) = node {
if ident.name == "this" {
let mut new_ident = self.get_this_name(ctx).create_read_reference(ctx);
new_ident.span = ident.span;
*node = ctx.ast.jsx_member_expression_object_from_identifier_reference(new_ident);
}
JSXElementName::IdentifierReference(_) | JSXElementName::NamespacedName(_) => return,
};
if ident.name == "this" {
// We can't produce a proper identifier with a `ReferenceId` because `JSXIdentifier`
// lacks that field. https://github.com/oxc-project/oxc/issues/3528
// So generate a reference and just use its name.
// If JSX transform is enabled, that transform runs before this and will have converted
// this to a proper `ThisExpression`, and this visitor won't run.
// So only a problem if JSX transform is disabled.
let new_ident = self.get_this_name(ctx).create_read_reference(ctx);
ident.name = new_ident.name;
}
}

View file

@ -57,6 +57,16 @@ impl<'a> Traverse<'a> for ES2015<'a> {
}
}
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);
}
}
fn enter_declaration(&mut self, decl: &mut Declaration<'a>, ctx: &mut TraverseCtx<'a>) {
if self.options.arrow_function.is_some() {
self.arrow_functions.enter_declaration(decl, ctx);

View file

@ -240,6 +240,14 @@ impl<'a> Traverse<'a> for Transformer<'a> {
self.x3_es2015.enter_jsx_element_name(elem, 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_method_definition(
&mut self,
def: &mut MethodDefinition<'a>,

View file

@ -1,10 +1,9 @@
commit: 3bcfee23
Passed: 10/38
Passed: 10/39
# All Passed:
* babel-plugin-transform-optional-catch-binding
* babel-plugin-transform-arrow-functions
# babel-plugin-transform-nullish-coalescing-operator (0/1)
@ -15,6 +14,14 @@ Passed: 10/38
# babel-plugin-transform-arrow-functions (1/2)
* with-this-member-expression/input.jsx
x Unresolved references mismatch:
| after transform: ["this"]
| rebuilt : []
# babel-plugin-transform-typescript (2/8)
* class-property-definition/input.ts
x Unresolved references mismatch:

View file

@ -0,0 +1,3 @@
() => {
<this.foo></this.foo>
}

View file

@ -0,0 +1,4 @@
var _this = this;
(function() {
<_this.foo></_this.foo>;
});