From 6abc2f359ed838640bbd77f7b905f11b9a7875e2 Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Sun, 27 Apr 2025 11:15:11 +0000 Subject: [PATCH] fix(transformer/legacy-decorator): keep imports when it's referenced as metadata (#10632) Fixes https://github.com/oxc-project/oxc-node/pull/112#issuecomment-2829365637 We cannot remove `imports` when they are referenced as metadata, because `reflect-metadata` would call them in runtime. --- .../src/decorator/legacy/metadata.rs | 18 +- .../snapshots/semantic_typescript.snap | 177 ++++-------------- .../snapshots/oxc.snap.md | 23 +-- .../fixtures/oxc/metadata/imports/output.ts | 3 +- 4 files changed, 46 insertions(+), 175 deletions(-) diff --git a/crates/oxc_transformer/src/decorator/legacy/metadata.rs b/crates/oxc_transformer/src/decorator/legacy/metadata.rs index 0124cfc031f7a..7d1c85b6eae2f 100644 --- a/crates/oxc_transformer/src/decorator/legacy/metadata.rs +++ b/crates/oxc_transformer/src/decorator/legacy/metadata.rs @@ -89,7 +89,7 @@ /// * TypeScript's [emitDecoratorMetadata](https://www.typescriptlang.org/tsconfig#emitDecoratorMetadata) use oxc_allocator::{Box as ArenaBox, TakeIn}; use oxc_ast::ast::*; -use oxc_semantic::{Reference, ReferenceFlags}; +use oxc_semantic::ReferenceFlags; use oxc_span::{ContentEq, SPAN}; use oxc_traverse::{MaybeBoundIdentifier, Traverse, TraverseCtx}; @@ -505,18 +505,10 @@ impl<'a> LegacyDecoratorMetadata<'a, '_> { ctx: &TraverseCtx<'a>, ) -> ReferenceFlags { if let Some(symbol_id) = binding.symbol_id { - if ctx.scoping().get_resolved_references(symbol_id).any(Reference::is_value) { - // If the symbol has a value reference, we can use it as a value reference - ReferenceFlags::Read - } else { - // Otherwise, we can only use it as a type reference because the TypeScript plugin will - // remove imports by checking references of `Symbol` whether it contains a - // `ReferenceFlags::Read`. If it doesn't, that means the symbol can be removed. That's - // why we need to use `Type` flag here, which hints the TypeScript plugin this Reference - // is only used as a type reference. If no `ReferenceFlags::Read` is found, we can - // safely remove the import. - ReferenceFlags::Type - } + let flags = ctx.scoping().symbol_flags(symbol_id); + // `design::*type` would be called by `reflect-metadata` APIs, use `Read` flag + // to avoid TypeScript remove it because only used as types. + if flags.is_value() { ReferenceFlags::Read } else { ReferenceFlags::Type } } else { // Unresolved reference ReferenceFlags::Type | ReferenceFlags::Read diff --git a/tasks/coverage/snapshots/semantic_typescript.snap b/tasks/coverage/snapshots/semantic_typescript.snap index 09d3d044c0ce2..4dac7fe1d4898 100644 --- a/tasks/coverage/snapshots/semantic_typescript.snap +++ b/tasks/coverage/snapshots/semantic_typescript.snap @@ -8561,24 +8561,9 @@ after transform: [ReferenceId(11), ReferenceId(12)] rebuilt : [ReferenceId(13)] semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorMetadataElidedImport.ts -Bindings mismatch: -after transform: ScopeId(0): ["Observable", "Test", "_decorate", "_decorateMetadata", "_decorateParam", "_ref", "whatever"] -rebuilt : ScopeId(0): ["Test", "_decorate", "_decorateMetadata", "_decorateParam", "_ref", "whatever"] -Reference symbol mismatch for "Observable": -after transform: SymbolId(0) "Observable" -rebuilt : -Reference flags mismatch for "Observable": -after transform: ReferenceId(8): ReferenceFlags(Type) -rebuilt : ReferenceId(8): ReferenceFlags(Read) -Reference symbol mismatch for "Observable": -after transform: SymbolId(0) "Observable" -rebuilt : -Reference flags mismatch for "Observable": -after transform: ReferenceId(9): ReferenceFlags(Type) -rebuilt : ReferenceId(9): ReferenceFlags(Read) -Unresolved references mismatch: -after transform: ["Function", "Number", "Object", "String"] -rebuilt : ["Function", "Number", "Object", "Observable", "String"] +Symbol reference IDs mismatch for "Observable": +after transform: SymbolId(0): [ReferenceId(2), ReferenceId(8), ReferenceId(9)] +rebuilt : SymbolId(0): [ReferenceId(8), ReferenceId(9)] semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorMetadataElidedImportOnDeclare.ts Bindings mismatch: @@ -8693,56 +8678,26 @@ after transform: [ReferenceId(1), ReferenceId(10)] rebuilt : [ReferenceId(10)] semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorMetadataWithImportDeclarationNameCollision.ts -Bindings mismatch: -after transform: ScopeId(0): ["MyClass", "_decorate", "_decorateMetadata", "_defineProperty", "_ref", "db", "someDecorator"] -rebuilt : ScopeId(0): ["MyClass", "_decorate", "_decorateMetadata", "_defineProperty", "_ref", "someDecorator"] +Symbol reference IDs mismatch for "db": +after transform: SymbolId(0): [ReferenceId(2), ReferenceId(3), ReferenceId(6), ReferenceId(7)] +rebuilt : SymbolId(0): [ReferenceId(8), ReferenceId(9)] Symbol span mismatch for "MyClass": after transform: SymbolId(3): Span { start: 100, end: 107 } -rebuilt : SymbolId(6): Span { start: 0, end: 0 } +rebuilt : SymbolId(7): Span { start: 0, end: 0 } Symbol span mismatch for "MyClass": after transform: SymbolId(8): Span { start: 0, end: 0 } -rebuilt : SymbolId(7): Span { start: 100, end: 107 } -Reference symbol mismatch for "db": -after transform: SymbolId(0) "db" -rebuilt : -Reference flags mismatch for "db": -after transform: ReferenceId(6): ReferenceFlags(Type) -rebuilt : ReferenceId(8): ReferenceFlags(Read) -Reference symbol mismatch for "db": -after transform: SymbolId(0) "db" -rebuilt : -Reference flags mismatch for "db": -after transform: ReferenceId(7): ReferenceFlags(Type) -rebuilt : ReferenceId(9): ReferenceFlags(Read) -Unresolved references mismatch: -after transform: ["Object"] -rebuilt : ["Object", "db"] +rebuilt : SymbolId(8): Span { start: 100, end: 107 } semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorMetadataWithImportDeclarationNameCollision2.ts -Bindings mismatch: -after transform: ScopeId(0): ["Database", "MyClass", "_decorate", "_decorateMetadata", "_defineProperty", "_ref", "someDecorator"] -rebuilt : ScopeId(0): ["MyClass", "_decorate", "_decorateMetadata", "_defineProperty", "_ref", "someDecorator"] +Symbol reference IDs mismatch for "Database": +after transform: SymbolId(0): [ReferenceId(2), ReferenceId(3), ReferenceId(6), ReferenceId(7)] +rebuilt : SymbolId(0): [ReferenceId(8), ReferenceId(9)] Symbol span mismatch for "MyClass": after transform: SymbolId(3): Span { start: 112, end: 119 } -rebuilt : SymbolId(6): Span { start: 0, end: 0 } +rebuilt : SymbolId(7): Span { start: 0, end: 0 } Symbol span mismatch for "MyClass": after transform: SymbolId(8): Span { start: 0, end: 0 } -rebuilt : SymbolId(7): Span { start: 112, end: 119 } -Reference symbol mismatch for "Database": -after transform: SymbolId(0) "Database" -rebuilt : -Reference flags mismatch for "Database": -after transform: ReferenceId(6): ReferenceFlags(Type) -rebuilt : ReferenceId(8): ReferenceFlags(Read) -Reference symbol mismatch for "Database": -after transform: SymbolId(0) "Database" -rebuilt : -Reference flags mismatch for "Database": -after transform: ReferenceId(7): ReferenceFlags(Type) -rebuilt : ReferenceId(9): ReferenceFlags(Read) -Unresolved references mismatch: -after transform: ["Object"] -rebuilt : ["Database", "Object"] +rebuilt : SymbolId(8): Span { start: 112, end: 119 } semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorMetadataWithImportDeclarationNameCollision3.ts Symbol span mismatch for "MyClass": @@ -8754,70 +8709,34 @@ rebuilt : SymbolId(7): Span { start: 104, end: 111 } Reference symbol mismatch for "db": after transform: SymbolId(0) "db" rebuilt : -Reference flags mismatch for "db": -after transform: ReferenceId(7): ReferenceFlags(Type) -rebuilt : ReferenceId(8): ReferenceFlags(Read) Reference symbol mismatch for "db": after transform: SymbolId(0) "db" rebuilt : -Reference flags mismatch for "db": -after transform: ReferenceId(6): ReferenceFlags(Type) -rebuilt : ReferenceId(9): ReferenceFlags(Read) Unresolved references mismatch: after transform: ["Object"] rebuilt : ["Object", "db"] semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorMetadataWithImportDeclarationNameCollision5.ts -Bindings mismatch: -after transform: ScopeId(0): ["MyClass", "_decorate", "_decorateMetadata", "_defineProperty", "_ref", "db", "someDecorator"] -rebuilt : ScopeId(0): ["MyClass", "_decorate", "_decorateMetadata", "_defineProperty", "_ref", "someDecorator"] +Symbol reference IDs mismatch for "db": +after transform: SymbolId(0): [ReferenceId(2), ReferenceId(3), ReferenceId(6), ReferenceId(7)] +rebuilt : SymbolId(0): [ReferenceId(8), ReferenceId(9)] Symbol span mismatch for "MyClass": after transform: SymbolId(3): Span { start: 98, end: 105 } -rebuilt : SymbolId(6): Span { start: 0, end: 0 } +rebuilt : SymbolId(7): Span { start: 0, end: 0 } Symbol span mismatch for "MyClass": after transform: SymbolId(8): Span { start: 0, end: 0 } -rebuilt : SymbolId(7): Span { start: 98, end: 105 } -Reference symbol mismatch for "db": -after transform: SymbolId(0) "db" -rebuilt : -Reference flags mismatch for "db": -after transform: ReferenceId(6): ReferenceFlags(Type) -rebuilt : ReferenceId(8): ReferenceFlags(Read) -Reference symbol mismatch for "db": -after transform: SymbolId(0) "db" -rebuilt : -Reference flags mismatch for "db": -after transform: ReferenceId(7): ReferenceFlags(Type) -rebuilt : ReferenceId(9): ReferenceFlags(Read) -Unresolved references mismatch: -after transform: ["Object"] -rebuilt : ["Object", "db"] +rebuilt : SymbolId(8): Span { start: 98, end: 105 } semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorMetadataWithImportDeclarationNameCollision6.ts -Bindings mismatch: -after transform: ScopeId(0): ["MyClass", "_decorate", "_decorateMetadata", "_defineProperty", "_ref", "database", "someDecorator"] -rebuilt : ScopeId(0): ["MyClass", "_decorate", "_decorateMetadata", "_defineProperty", "_ref", "someDecorator"] +Symbol reference IDs mismatch for "database": +after transform: SymbolId(0): [ReferenceId(2), ReferenceId(3), ReferenceId(6), ReferenceId(7)] +rebuilt : SymbolId(0): [ReferenceId(8), ReferenceId(9)] Symbol span mismatch for "MyClass": after transform: SymbolId(3): Span { start: 104, end: 111 } -rebuilt : SymbolId(6): Span { start: 0, end: 0 } +rebuilt : SymbolId(7): Span { start: 0, end: 0 } Symbol span mismatch for "MyClass": after transform: SymbolId(8): Span { start: 0, end: 0 } -rebuilt : SymbolId(7): Span { start: 104, end: 111 } -Reference symbol mismatch for "database": -after transform: SymbolId(0) "database" -rebuilt : -Reference flags mismatch for "database": -after transform: ReferenceId(6): ReferenceFlags(Type) -rebuilt : ReferenceId(8): ReferenceFlags(Read) -Reference symbol mismatch for "database": -after transform: SymbolId(0) "database" -rebuilt : -Reference flags mismatch for "database": -after transform: ReferenceId(7): ReferenceFlags(Type) -rebuilt : ReferenceId(9): ReferenceFlags(Read) -Unresolved references mismatch: -after transform: ["Object"] -rebuilt : ["Object", "database"] +rebuilt : SymbolId(8): Span { start: 104, end: 111 } semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorMetadataWithImportDeclarationNameCollision8.ts Symbol span mismatch for "MyClass": @@ -8829,38 +8748,17 @@ rebuilt : SymbolId(7): Span { start: 110, end: 117 } Reference symbol mismatch for "database": after transform: SymbolId(0) "database" rebuilt : -Reference flags mismatch for "database": -after transform: ReferenceId(7): ReferenceFlags(Type) -rebuilt : ReferenceId(8): ReferenceFlags(Read) Reference symbol mismatch for "database": after transform: SymbolId(0) "database" rebuilt : -Reference flags mismatch for "database": -after transform: ReferenceId(6): ReferenceFlags(Type) -rebuilt : ReferenceId(9): ReferenceFlags(Read) Unresolved references mismatch: after transform: ["Object"] rebuilt : ["Object", "database"] semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorReferenceOnOtherProperty.ts -Bindings mismatch: -after transform: ScopeId(0): ["Bar", "Yoha", "_decorate", "_decorateMetadata", "_decorateParam", "_ref", "foo"] -rebuilt : ScopeId(0): ["Bar", "_decorate", "_decorateMetadata", "_decorateParam", "_ref", "foo"] -Reference symbol mismatch for "Yoha": -after transform: SymbolId(0) "Yoha" -rebuilt : -Reference flags mismatch for "Yoha": -after transform: ReferenceId(5): ReferenceFlags(Type) -rebuilt : ReferenceId(6): ReferenceFlags(Read) -Reference symbol mismatch for "Yoha": -after transform: SymbolId(0) "Yoha" -rebuilt : -Reference flags mismatch for "Yoha": -after transform: ReferenceId(6): ReferenceFlags(Type) -rebuilt : ReferenceId(7): ReferenceFlags(Read) -Unresolved references mismatch: -after transform: ["Function", "Object"] -rebuilt : ["Function", "Object", "Yoha"] +Symbol reference IDs mismatch for "Yoha": +after transform: SymbolId(0): [ReferenceId(1), ReferenceId(5), ReferenceId(6)] +rebuilt : SymbolId(0): [ReferenceId(6), ReferenceId(7)] semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorReferences.ts Bindings mismatch: @@ -36775,34 +36673,25 @@ rebuilt : SymbolId(0): [] semantic Error: tasks/coverage/typescript/tests/cases/conformance/decorators/decoratorMetadata.ts Bindings mismatch: after transform: ScopeId(0): ["MyComponent", "Service", "_decorate", "_decorateMetadata", "_ref", "decorator"] -rebuilt : ScopeId(0): ["MyComponent", "_decorate", "_decorateMetadata", "_ref"] +rebuilt : ScopeId(0): ["MyComponent", "Service", "_decorate", "_decorateMetadata", "_ref"] +Symbol reference IDs mismatch for "Service": +after transform: SymbolId(0): [ReferenceId(1), ReferenceId(3), ReferenceId(4)] +rebuilt : SymbolId(0): [ReferenceId(14), ReferenceId(15)] Symbol span mismatch for "MyComponent": after transform: SymbolId(2): Span { start: 80, end: 91 } -rebuilt : SymbolId(3): Span { start: 0, end: 0 } +rebuilt : SymbolId(4): Span { start: 0, end: 0 } Symbol span mismatch for "MyComponent": after transform: SymbolId(7): Span { start: 0, end: 0 } -rebuilt : SymbolId(4): Span { start: 80, end: 91 } +rebuilt : SymbolId(5): Span { start: 80, end: 91 } Reference symbol mismatch for "decorator": after transform: SymbolId(1) "decorator" rebuilt : Reference symbol mismatch for "decorator": after transform: SymbolId(1) "decorator" rebuilt : -Reference symbol mismatch for "Service": -after transform: SymbolId(0) "Service" -rebuilt : -Reference flags mismatch for "Service": -after transform: ReferenceId(3): ReferenceFlags(Type) -rebuilt : ReferenceId(14): ReferenceFlags(Read) -Reference symbol mismatch for "Service": -after transform: SymbolId(0) "Service" -rebuilt : -Reference flags mismatch for "Service": -after transform: ReferenceId(4): ReferenceFlags(Type) -rebuilt : ReferenceId(15): ReferenceFlags(Read) Unresolved references mismatch: after transform: ["Function", "Object"] -rebuilt : ["Function", "Object", "Service", "decorator"] +rebuilt : ["Function", "Object", "decorator"] semantic Error: tasks/coverage/typescript/tests/cases/conformance/decorators/decoratorMetadataWithTypeOnlyImport.ts Bindings mismatch: diff --git a/tasks/transform_conformance/snapshots/oxc.snap.md b/tasks/transform_conformance/snapshots/oxc.snap.md index ed85c288ac44e..22665953ddc7a 100644 --- a/tasks/transform_conformance/snapshots/oxc.snap.md +++ b/tasks/transform_conformance/snapshots/oxc.snap.md @@ -439,34 +439,25 @@ rebuilt : SymbolId(3): Span { start: 87, end: 94 } * oxc/metadata/imports/input.ts Bindings mismatch: after transform: ScopeId(0): ["Bar", "Cls", "Foo", "_ref", "dec"] -rebuilt : ScopeId(0): ["Cls", "_ref"] +rebuilt : ScopeId(0): ["Cls", "Foo", "_ref"] Scope children mismatch: after transform: ScopeId(0): [ScopeId(1), ScopeId(2)] rebuilt : ScopeId(0): [ScopeId(1)] +Symbol reference IDs mismatch for "Foo": +after transform: SymbolId(0): [ReferenceId(2), ReferenceId(3), ReferenceId(8), ReferenceId(9)] +rebuilt : SymbolId(0): [ReferenceId(7), ReferenceId(8)] Symbol span mismatch for "Cls": after transform: SymbolId(6): Span { start: 135, end: 138 } -rebuilt : SymbolId(1): Span { start: 0, end: 0 } +rebuilt : SymbolId(2): Span { start: 0, end: 0 } Symbol span mismatch for "Cls": after transform: SymbolId(10): Span { start: 0, end: 0 } -rebuilt : SymbolId(2): Span { start: 135, end: 138 } -Reference symbol mismatch for "Foo": -after transform: SymbolId(0) "Foo" -rebuilt : -Reference flags mismatch for "Foo": -after transform: ReferenceId(8): ReferenceFlags(Type) -rebuilt : ReferenceId(7): ReferenceFlags(Read) -Reference symbol mismatch for "Foo": -after transform: SymbolId(0) "Foo" -rebuilt : -Reference flags mismatch for "Foo": -after transform: ReferenceId(9): ReferenceFlags(Type) -rebuilt : ReferenceId(8): ReferenceFlags(Read) +rebuilt : SymbolId(3): Span { start: 135, end: 138 } Reference symbol mismatch for "dec": after transform: SymbolId(2) "dec" rebuilt : Unresolved references mismatch: after transform: ["Object", "PropertyDescriptor", "babelHelpers", "console"] -rebuilt : ["Foo", "Object", "babelHelpers", "console", "dec"] +rebuilt : ["Object", "babelHelpers", "console", "dec"] * oxc/metadata/typescript-syntax/input.ts Bindings mismatch: diff --git a/tasks/transform_conformance/tests/legacy-decorators/test/fixtures/oxc/metadata/imports/output.ts b/tasks/transform_conformance/tests/legacy-decorators/test/fixtures/oxc/metadata/imports/output.ts index 24b04aa3bb423..f92b5138ab108 100644 --- a/tasks/transform_conformance/tests/legacy-decorators/test/fixtures/oxc/metadata/imports/output.ts +++ b/tasks/transform_conformance/tests/legacy-decorators/test/fixtures/oxc/metadata/imports/output.ts @@ -1,3 +1,4 @@ +import { Foo } from "mod"; var _ref; let Cls = class Cls { @@ -18,5 +19,3 @@ Cls = babelHelpers.decorate( ], Cls, ); - -export {};