From 39876654902cff7a13a49cd58d41aac45cb14428 Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Tue, 6 Aug 2024 02:57:19 +0000 Subject: [PATCH] fix(transformer/typescript): incorrect enum-related `symbol_id`/`reference_id` (#4660) part of #4581 --- crates/oxc_transformer/src/typescript/enum.rs | 36 ++++++++++++------- tasks/transform_conformance/babel.snap.md | 22 ++---------- 2 files changed, 26 insertions(+), 32 deletions(-) diff --git a/crates/oxc_transformer/src/typescript/enum.rs b/crates/oxc_transformer/src/typescript/enum.rs index 436a18c1a7815..66c1ad021de53 100644 --- a/crates/oxc_transformer/src/typescript/enum.rs +++ b/crates/oxc_transformer/src/typescript/enum.rs @@ -82,12 +82,13 @@ impl<'a> TypeScriptEnum<'a> { func_scope_id, AstNodeId::DUMMY, ); + ctx.scopes_mut().add_binding(func_scope_id, enum_name.to_compact_str(), param_symbol_id); let ident = BindingIdentifier { span: decl.id.span, name: decl.id.name.clone(), symbol_id: Cell::new(Some(param_symbol_id)), }; - let kind = ast.binding_pattern_kind_from_binding_identifier(ident); + let kind = ast.binding_pattern_kind_from_binding_identifier(ident.clone()); let id = ast.binding_pattern(kind, Option::::None, false); // ((Foo) => { @@ -102,7 +103,8 @@ impl<'a> TypeScriptEnum<'a> { // Foo[Foo["X"] = 0] = "X"; let is_already_declared = self.enums.contains_key(&enum_name); - let statements = self.transform_ts_enum_members(&decl.members, enum_name.clone(), ctx); + + let statements = self.transform_ts_enum_members(&decl.members, &ident, ctx); let body = ast.alloc_function_body(decl.span, ast.vec(), statements); let callee = Expression::FunctionExpression(ctx.alloc(Function { r#type: FunctionType::FunctionExpression, @@ -187,19 +189,29 @@ impl<'a> TypeScriptEnum<'a> { Some(stmt) } + #[allow(clippy::needless_pass_by_value)] fn transform_ts_enum_members( &mut self, members: &Vec<'a, TSEnumMember<'a>>, - enum_name: Atom<'a>, - ctx: &TraverseCtx<'a>, + param: &BindingIdentifier<'a>, + ctx: &mut TraverseCtx<'a>, ) -> Vec<'a, Statement<'a>> { - // TODO: Set `span` and `references_id` on all `IdentifierReference`s created here + let create_identifier_reference = |ctx: &mut TraverseCtx<'a>| { + let ident = ctx.create_reference_id( + param.span, + param.name.clone(), + param.symbol_id.get(), + ReferenceFlag::Read, + ); + ctx.ast.expression_from_identifier_reference(ident) + }; let ast = ctx.ast; let mut statements = ast.vec(); let mut prev_constant_value = Some(ConstantValue::Number(-1.0)); - let mut previous_enum_members = self.enums.entry(enum_name.clone()).or_default().clone(); + let mut previous_enum_members = self.enums.entry(param.name.clone()).or_default().clone(); + let mut prev_member_name: Option> = None; for member in members { @@ -238,7 +250,7 @@ impl<'a> TypeScriptEnum<'a> { ); if !has_binding { IdentifierReferenceRename::new( - enum_name.clone(), + param.name.clone(), previous_enum_members.clone(), ctx, ) @@ -276,7 +288,7 @@ impl<'a> TypeScriptEnum<'a> { } } else if let Some(prev_member_name) = prev_member_name { let self_ref = { - let obj = ast.expression_identifier_reference(SPAN, &enum_name); + let obj = create_identifier_reference(ctx); let expr = ctx.ast.expression_string_literal(SPAN, prev_member_name); ast.member_expression_computed(SPAN, obj, expr, false).into() }; @@ -292,7 +304,7 @@ impl<'a> TypeScriptEnum<'a> { // Foo["x"] = init let member_expr = { - let obj = ast.expression_identifier_reference(SPAN, &enum_name); + let obj = create_identifier_reference(ctx); let expr = ast.expression_string_literal(SPAN, member_name); ast.member_expression_computed(SPAN, obj, expr, false) @@ -304,7 +316,7 @@ impl<'a> TypeScriptEnum<'a> { // Foo[Foo["x"] = init] = "x" if !is_str { let member_expr = { - let obj = ast.expression_identifier_reference(SPAN, &enum_name); + let obj = create_identifier_reference(ctx); ast.member_expression_computed(SPAN, obj, expr, false) }; let left = ast.simple_assignment_target_member_expression(member_expr); @@ -317,9 +329,9 @@ impl<'a> TypeScriptEnum<'a> { statements.push(ast.statement_expression(member.span, expr)); } - self.enums.insert(enum_name.clone(), previous_enum_members.clone()); + self.enums.insert(param.name.clone(), previous_enum_members.clone()); - let enum_ref = ast.expression_identifier_reference(SPAN, enum_name); + let enum_ref = create_identifier_reference(ctx); // return Foo; let return_stmt = ast.statement_return(SPAN, Some(enum_ref)); statements.push(return_stmt); diff --git a/tasks/transform_conformance/babel.snap.md b/tasks/transform_conformance/babel.snap.md index fe635cc51138e..ae66627ffeb70 100644 --- a/tasks/transform_conformance/babel.snap.md +++ b/tasks/transform_conformance/babel.snap.md @@ -1,6 +1,6 @@ commit: 12619ffe -Passed: 435/927 +Passed: 453/927 # All Passed: * babel-preset-react @@ -445,33 +445,15 @@ Passed: 435/927 * opts/optimizeConstEnums/input.ts * opts/rewriteImportExtensions/input.ts -# babel-plugin-transform-typescript (91/151) +# babel-plugin-transform-typescript (109/151) * class/accessor-allowDeclareFields-false/input.ts * class/accessor-allowDeclareFields-true/input.ts -* enum/boolean-value/input.ts -* enum/const/input.ts -* enum/constant-folding/input.ts -* enum/enum-merging-inner-references/input.ts -* enum/enum-merging-inner-references-shadow/input.ts -* enum/export/input.ts -* enum/inferred/input.ts -* enum/inner-references/input.ts * enum/mix-references/input.ts -* enum/non-foldable-constant/input.ts -* enum/non-scoped/input.ts -* enum/outer-references/input.ts -* enum/scoped/input.ts -* enum/string-value/input.ts -* enum/string-value-template/input.ts -* enum/string-values-computed/input.ts * enum/ts5.0-const-foldable/input.ts * exports/declared-types/input.ts -* exports/export-const-enums/input.ts * exports/export-import=/input.ts * exports/interface/input.ts * imports/elide-type-referenced-in-imports-equal-no/input.ts -* imports/enum-id/input.ts -* imports/enum-value/input.ts * imports/import=-module/input.ts * imports/only-remove-type-imports/input.ts * imports/type-only-export-specifier-2/input.ts