diff --git a/tsc/internal/transformers/tstransforms/legacydecorators.go b/tsc/internal/transformers/tstransforms/legacydecorators.go index 8eaa45e5071ad..b69b450f6842a 100644 --- a/tsc/internal/transformers/tstransforms/legacydecorators.go +++ b/tsc/internal/transformers/tstransforms/legacydecorators.go @@ -1,6 +1,8 @@ package tstransforms import ( + "slices" + "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/binder" "github.com/microsoft/TypeScript/tsc/internal/collections" @@ -20,6 +22,8 @@ type LegacyDecoratorsTransformer struct { */ classAliases map[*ast.Node]*ast.Node enclosingClasses []*ast.ClassDeclaration + // Class aliases that should not be substituted while visiting a direct computed member name. + excludedClassAliases []*ast.Node } func NewLegacyDecoratorsTransformer(opt *transformers.TransformOptions) *transformers.Transformer { @@ -60,10 +64,12 @@ func (tx *LegacyDecoratorsTransformer) visit(node *ast.Node) *ast.Node { case ast.KindSourceFile: tx.classAliases = make(map[*ast.Node]*ast.Node) tx.enclosingClasses = nil + tx.excludedClassAliases = nil result := tx.Visitor().VisitEachChild(node) tx.EmitContext().AddEmitHelper(result, tx.EmitContext().ReadEmitHelpers()...) tx.classAliases = nil tx.enclosingClasses = nil + tx.excludedClassAliases = nil return result default: return tx.Visitor().VisitEachChild(node) @@ -73,7 +79,7 @@ func (tx *LegacyDecoratorsTransformer) visit(node *ast.Node) *ast.Node { func (tx *LegacyDecoratorsTransformer) visitIdentifier(node *ast.Identifier) *ast.Node { // takes the place of `substituteIdentifier` in the strada transform for _, d := range tx.enclosingClasses { - if _, ok := tx.classAliases[d.AsNode()]; ok && tx.referenceResolver.GetReferencedValueDeclaration(tx.EmitContext().MostOriginal(node.AsNode())) == tx.EmitContext().MostOriginal(d.AsNode()) { + if _, ok := tx.classAliases[d.AsNode()]; ok && !slices.Contains(tx.excludedClassAliases, d.AsNode()) && tx.referenceResolver.GetReferencedValueDeclaration(tx.EmitContext().MostOriginal(node.AsNode())) == tx.EmitContext().MostOriginal(d.AsNode()) { return tx.classAliases[d.AsNode()] } } @@ -152,6 +158,20 @@ func (tx *LegacyDecoratorsTransformer) visitParamerDeclaration(node *ast.Paramet // with decorators, a temporary value is stored for later use. func (tx *LegacyDecoratorsTransformer) visitPropertyNameOfClassElement(member *ast.Node) *ast.Node { name := member.Name() + if ast.IsComputedPropertyName(name) { + // A direct computed name is evaluated before its class alias is assigned. Exclude only + // that class so references to aliases of enclosing classes are still substituted. + for i := len(tx.enclosingClasses) - 1; i >= 0; i-- { + class := tx.enclosingClasses[i] + if slices.Contains(class.Members.Nodes, member) { + tx.excludedClassAliases = append(tx.excludedClassAliases, class.AsNode()) + defer func() { + tx.excludedClassAliases = tx.excludedClassAliases[:len(tx.excludedClassAliases)-1] + }() + break + } + } + } if ast.IsComputedPropertyName(name) && ast.HasDecorators(member) { expression := tx.Visitor().VisitNode(name.AsComputedPropertyName().Expression) innerExpression := ast.SkipPartiallyEmittedExpressions(expression) @@ -511,8 +531,18 @@ func (tx *LegacyDecoratorsTransformer) transformClassDeclarationWithClassDecorat func (tx *LegacyDecoratorsTransformer) hasInternalStaticReference(node *ast.ClassDeclaration) bool { classNode := tx.EmitContext().MostOriginal(node.AsNode()) + computedNames := make(map[*ast.Node]struct{}) + for _, member := range node.Members.Nodes { + if name := member.Name(); name != nil && ast.IsComputedPropertyName(name) { + // Direct computed names are evaluated before the class alias can be assigned. + computedNames[name] = struct{}{} + } + } var isOrContainsStaticSelfReference func(n *ast.Node) bool isOrContainsStaticSelfReference = func(n *ast.Node) bool { + if _, ok := computedNames[n]; ok { + return false + } if ast.IsIdentifier(n) && tx.referenceResolver.GetReferencedValueDeclaration(tx.EmitContext().MostOriginal(n)) == classNode { return true } diff --git a/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2020).errors.txt b/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2020).errors.txt new file mode 100644 index 0000000000000..1e31c54b34d1e --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2020).errors.txt @@ -0,0 +1,47 @@ +legacyDecoratorClassAliasComputedNames.ts(6,6): error TS2449: Class 'C' used before its declaration. +legacyDecoratorClassAliasComputedNames.ts(7,10): error TS2449: Class 'C' used before its declaration. +legacyDecoratorClassAliasComputedNames.ts(8,10): error TS2449: Class 'C' used before its declaration. +legacyDecoratorClassAliasComputedNames.ts(14,13): error TS2449: Class 'D' used before its declaration. + + +==== legacyDecoratorClassAliasComputedNames.ts (4 errors) ==== + declare function dec(...args: any[]): any; + + @dec + class C { + constructor() {} + [C.name]() {} + ~ +!!! error TS2449: Class 'C' used before its declaration. +!!! related TS2728 legacyDecoratorClassAliasComputedNames.ts:4:7: 'C' is declared here. + get [C.name]() { return 1; } + ~ +!!! error TS2449: Class 'C' used before its declaration. +!!! related TS2728 legacyDecoratorClassAliasComputedNames.ts:4:7: 'C' is declared here. + set [C.name](value: number) {} + ~ +!!! error TS2449: Class 'C' used before its declaration. +!!! related TS2728 legacyDecoratorClassAliasComputedNames.ts:4:7: 'C' is declared here. + } + + @dec + class D { + @dec + static [D.name] = 1; + ~ +!!! error TS2449: Class 'D' used before its declaration. +!!! related TS2728 legacyDecoratorClassAliasComputedNames.ts:12:7: 'D' is declared here. + static getSelf() { + return D; + } + } + + @dec + class Outer { + method() { + return class { + [Outer.name]() {} + }; + } + } + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2020).js b/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2020).js new file mode 100644 index 0000000000000..178d4cbbc9804 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2020).js @@ -0,0 +1,73 @@ +//// [tests/cases/compiler/legacyDecoratorClassAliasComputedNames.ts] //// + +//// [legacyDecoratorClassAliasComputedNames.ts] +declare function dec(...args: any[]): any; + +@dec +class C { + constructor() {} + [C.name]() {} + get [C.name]() { return 1; } + set [C.name](value: number) {} +} + +@dec +class D { + @dec + static [D.name] = 1; + static getSelf() { + return D; + } +} + +@dec +class Outer { + method() { + return class { + [Outer.name]() {} + }; + } +} + + +//// [legacyDecoratorClassAliasComputedNames.js] +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var D_1, _a, Outer_1; +let C = class C { + constructor() { } + [C.name]() { } + get [C.name]() { return 1; } + set [C.name](value) { } +}; +C = __decorate([ + dec +], C); +let D = D_1 = class D { + static getSelf() { + return D_1; + } +}; +_a = D.name; +D[_a] = 1; +__decorate([ + dec +], D, _a, void 0); +D = D_1 = __decorate([ + dec +], D); +let Outer = Outer_1 = class Outer { + method() { + return class { + [Outer_1.name]() { } + }; + } +}; +Outer = Outer_1 = __decorate([ + dec +], Outer); diff --git a/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2020).symbols b/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2020).symbols new file mode 100644 index 0000000000000..3cf933b967320 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2020).symbols @@ -0,0 +1,77 @@ +//// [tests/cases/compiler/legacyDecoratorClassAliasComputedNames.ts] //// + +=== legacyDecoratorClassAliasComputedNames.ts === +declare function dec(...args: any[]): any; +>dec : Symbol(dec, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 0)) +>args : Symbol(args, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 21)) + +@dec +>dec : Symbol(dec, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 0)) + +class C { +>C : Symbol(C, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 42)) + + constructor() {} + [C.name]() {} +>[C.name] : Symbol(C[C.name], Decl(legacyDecoratorClassAliasComputedNames.ts, 4, 20)) +>C.name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) +>C : Symbol(C, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 42)) +>name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) + + get [C.name]() { return 1; } +>[C.name] : Symbol(C[C.name], Decl(legacyDecoratorClassAliasComputedNames.ts, 5, 17)) +>C.name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) +>C : Symbol(C, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 42)) +>name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) + + set [C.name](value: number) {} +>[C.name] : Symbol(C[C.name], Decl(legacyDecoratorClassAliasComputedNames.ts, 6, 32)) +>C.name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) +>C : Symbol(C, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 42)) +>name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) +>value : Symbol(value, Decl(legacyDecoratorClassAliasComputedNames.ts, 7, 17)) +} + +@dec +>dec : Symbol(dec, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 0)) + +class D { +>D : Symbol(D, Decl(legacyDecoratorClassAliasComputedNames.ts, 8, 1)) + + @dec +>dec : Symbol(dec, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 0)) + + static [D.name] = 1; +>[D.name] : Symbol(D[D.name], Decl(legacyDecoratorClassAliasComputedNames.ts, 11, 9)) +>D.name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) +>D : Symbol(D, Decl(legacyDecoratorClassAliasComputedNames.ts, 8, 1)) +>name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) + + static getSelf() { +>getSelf : Symbol(D.getSelf, Decl(legacyDecoratorClassAliasComputedNames.ts, 13, 24)) + + return D; +>D : Symbol(D, Decl(legacyDecoratorClassAliasComputedNames.ts, 8, 1)) + } +} + +@dec +>dec : Symbol(dec, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 0)) + +class Outer { +>Outer : Symbol(Outer, Decl(legacyDecoratorClassAliasComputedNames.ts, 17, 1)) + + method() { +>method : Symbol(Outer.method, Decl(legacyDecoratorClassAliasComputedNames.ts, 20, 13)) + + return class { + [Outer.name]() {} +>[Outer.name] : Symbol((Anonymous class)[Outer.name], Decl(legacyDecoratorClassAliasComputedNames.ts, 22, 22)) +>Outer.name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) +>Outer : Symbol(Outer, Decl(legacyDecoratorClassAliasComputedNames.ts, 17, 1)) +>name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) + + }; + } +} + diff --git a/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2020).types b/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2020).types new file mode 100644 index 0000000000000..d791330f6bf28 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2020).types @@ -0,0 +1,81 @@ +//// [tests/cases/compiler/legacyDecoratorClassAliasComputedNames.ts] //// + +=== legacyDecoratorClassAliasComputedNames.ts === +declare function dec(...args: any[]): any; +>dec : (...args: any[]) => any +>args : any[] + +@dec +>dec : (...args: any[]) => any + +class C { +>C : C + + constructor() {} + [C.name]() {} +>[C.name] : () => void +>C.name : string +>C : typeof C +>name : string + + get [C.name]() { return 1; } +>[C.name] : number +>C.name : string +>C : typeof C +>name : string +>1 : 1 + + set [C.name](value: number) {} +>[C.name] : number +>C.name : string +>C : typeof C +>name : string +>value : number +} + +@dec +>dec : (...args: any[]) => any + +class D { +>D : D + + @dec +>dec : (...args: any[]) => any + + static [D.name] = 1; +>[D.name] : number +>D.name : string +>D : typeof D +>name : string +>1 : 1 + + static getSelf() { +>getSelf : () => typeof D + + return D; +>D : typeof D + } +} + +@dec +>dec : (...args: any[]) => any + +class Outer { +>Outer : Outer + + method() { +>method : () => typeof (Anonymous class) + + return class { +>class { [Outer.name]() {} } : typeof (Anonymous class) + + [Outer.name]() {} +>[Outer.name] : () => void +>Outer.name : string +>Outer : typeof Outer +>name : string + + }; + } +} + diff --git a/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2022).errors.txt b/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2022).errors.txt new file mode 100644 index 0000000000000..1e31c54b34d1e --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2022).errors.txt @@ -0,0 +1,47 @@ +legacyDecoratorClassAliasComputedNames.ts(6,6): error TS2449: Class 'C' used before its declaration. +legacyDecoratorClassAliasComputedNames.ts(7,10): error TS2449: Class 'C' used before its declaration. +legacyDecoratorClassAliasComputedNames.ts(8,10): error TS2449: Class 'C' used before its declaration. +legacyDecoratorClassAliasComputedNames.ts(14,13): error TS2449: Class 'D' used before its declaration. + + +==== legacyDecoratorClassAliasComputedNames.ts (4 errors) ==== + declare function dec(...args: any[]): any; + + @dec + class C { + constructor() {} + [C.name]() {} + ~ +!!! error TS2449: Class 'C' used before its declaration. +!!! related TS2728 legacyDecoratorClassAliasComputedNames.ts:4:7: 'C' is declared here. + get [C.name]() { return 1; } + ~ +!!! error TS2449: Class 'C' used before its declaration. +!!! related TS2728 legacyDecoratorClassAliasComputedNames.ts:4:7: 'C' is declared here. + set [C.name](value: number) {} + ~ +!!! error TS2449: Class 'C' used before its declaration. +!!! related TS2728 legacyDecoratorClassAliasComputedNames.ts:4:7: 'C' is declared here. + } + + @dec + class D { + @dec + static [D.name] = 1; + ~ +!!! error TS2449: Class 'D' used before its declaration. +!!! related TS2728 legacyDecoratorClassAliasComputedNames.ts:12:7: 'D' is declared here. + static getSelf() { + return D; + } + } + + @dec + class Outer { + method() { + return class { + [Outer.name]() {} + }; + } + } + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2022).js b/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2022).js new file mode 100644 index 0000000000000..bcce5af1d8201 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2022).js @@ -0,0 +1,73 @@ +//// [tests/cases/compiler/legacyDecoratorClassAliasComputedNames.ts] //// + +//// [legacyDecoratorClassAliasComputedNames.ts] +declare function dec(...args: any[]): any; + +@dec +class C { + constructor() {} + [C.name]() {} + get [C.name]() { return 1; } + set [C.name](value: number) {} +} + +@dec +class D { + @dec + static [D.name] = 1; + static getSelf() { + return D; + } +} + +@dec +class Outer { + method() { + return class { + [Outer.name]() {} + }; + } +} + + +//// [legacyDecoratorClassAliasComputedNames.js] +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var D_1, _a, Outer_1; +let C = class C { + constructor() { } + [C.name]() { } + get [C.name]() { return 1; } + set [C.name](value) { } +}; +C = __decorate([ + dec +], C); +let D = class D { + static { D_1 = this; } + static [_a = D.name] = 1; + static getSelf() { + return D_1; + } +}; +__decorate([ + dec +], D, _a, void 0); +D = D_1 = __decorate([ + dec +], D); +let Outer = Outer_1 = class Outer { + method() { + return class { + [Outer_1.name]() { } + }; + } +}; +Outer = Outer_1 = __decorate([ + dec +], Outer); diff --git a/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2022).symbols b/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2022).symbols new file mode 100644 index 0000000000000..3cf933b967320 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2022).symbols @@ -0,0 +1,77 @@ +//// [tests/cases/compiler/legacyDecoratorClassAliasComputedNames.ts] //// + +=== legacyDecoratorClassAliasComputedNames.ts === +declare function dec(...args: any[]): any; +>dec : Symbol(dec, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 0)) +>args : Symbol(args, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 21)) + +@dec +>dec : Symbol(dec, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 0)) + +class C { +>C : Symbol(C, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 42)) + + constructor() {} + [C.name]() {} +>[C.name] : Symbol(C[C.name], Decl(legacyDecoratorClassAliasComputedNames.ts, 4, 20)) +>C.name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) +>C : Symbol(C, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 42)) +>name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) + + get [C.name]() { return 1; } +>[C.name] : Symbol(C[C.name], Decl(legacyDecoratorClassAliasComputedNames.ts, 5, 17)) +>C.name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) +>C : Symbol(C, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 42)) +>name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) + + set [C.name](value: number) {} +>[C.name] : Symbol(C[C.name], Decl(legacyDecoratorClassAliasComputedNames.ts, 6, 32)) +>C.name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) +>C : Symbol(C, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 42)) +>name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) +>value : Symbol(value, Decl(legacyDecoratorClassAliasComputedNames.ts, 7, 17)) +} + +@dec +>dec : Symbol(dec, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 0)) + +class D { +>D : Symbol(D, Decl(legacyDecoratorClassAliasComputedNames.ts, 8, 1)) + + @dec +>dec : Symbol(dec, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 0)) + + static [D.name] = 1; +>[D.name] : Symbol(D[D.name], Decl(legacyDecoratorClassAliasComputedNames.ts, 11, 9)) +>D.name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) +>D : Symbol(D, Decl(legacyDecoratorClassAliasComputedNames.ts, 8, 1)) +>name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) + + static getSelf() { +>getSelf : Symbol(D.getSelf, Decl(legacyDecoratorClassAliasComputedNames.ts, 13, 24)) + + return D; +>D : Symbol(D, Decl(legacyDecoratorClassAliasComputedNames.ts, 8, 1)) + } +} + +@dec +>dec : Symbol(dec, Decl(legacyDecoratorClassAliasComputedNames.ts, 0, 0)) + +class Outer { +>Outer : Symbol(Outer, Decl(legacyDecoratorClassAliasComputedNames.ts, 17, 1)) + + method() { +>method : Symbol(Outer.method, Decl(legacyDecoratorClassAliasComputedNames.ts, 20, 13)) + + return class { + [Outer.name]() {} +>[Outer.name] : Symbol((Anonymous class)[Outer.name], Decl(legacyDecoratorClassAliasComputedNames.ts, 22, 22)) +>Outer.name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) +>Outer : Symbol(Outer, Decl(legacyDecoratorClassAliasComputedNames.ts, 17, 1)) +>name : Symbol(Function.name, Decl(lib.es2015.core.d.ts, --, --)) + + }; + } +} + diff --git a/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2022).types b/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2022).types new file mode 100644 index 0000000000000..d791330f6bf28 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/legacyDecoratorClassAliasComputedNames(target=es2022).types @@ -0,0 +1,81 @@ +//// [tests/cases/compiler/legacyDecoratorClassAliasComputedNames.ts] //// + +=== legacyDecoratorClassAliasComputedNames.ts === +declare function dec(...args: any[]): any; +>dec : (...args: any[]) => any +>args : any[] + +@dec +>dec : (...args: any[]) => any + +class C { +>C : C + + constructor() {} + [C.name]() {} +>[C.name] : () => void +>C.name : string +>C : typeof C +>name : string + + get [C.name]() { return 1; } +>[C.name] : number +>C.name : string +>C : typeof C +>name : string +>1 : 1 + + set [C.name](value: number) {} +>[C.name] : number +>C.name : string +>C : typeof C +>name : string +>value : number +} + +@dec +>dec : (...args: any[]) => any + +class D { +>D : D + + @dec +>dec : (...args: any[]) => any + + static [D.name] = 1; +>[D.name] : number +>D.name : string +>D : typeof D +>name : string +>1 : 1 + + static getSelf() { +>getSelf : () => typeof D + + return D; +>D : typeof D + } +} + +@dec +>dec : (...args: any[]) => any + +class Outer { +>Outer : Outer + + method() { +>method : () => typeof (Anonymous class) + + return class { +>class { [Outer.name]() {} } : typeof (Anonymous class) + + [Outer.name]() {} +>[Outer.name] : () => void +>Outer.name : string +>Outer : typeof Outer +>name : string + + }; + } +} + diff --git a/tsc/testdata/tests/cases/compiler/legacyDecoratorClassAliasComputedNames.ts b/tsc/testdata/tests/cases/compiler/legacyDecoratorClassAliasComputedNames.ts new file mode 100644 index 0000000000000..23a49be8e2483 --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/legacyDecoratorClassAliasComputedNames.ts @@ -0,0 +1,30 @@ +// @target: es2020, es2022 +// @experimentalDecorators: true + +declare function dec(...args: any[]): any; + +@dec +class C { + constructor() {} + [C.name]() {} + get [C.name]() { return 1; } + set [C.name](value: number) {} +} + +@dec +class D { + @dec + static [D.name] = 1; + static getSelf() { + return D; + } +} + +@dec +class Outer { + method() { + return class { + [Outer.name]() {} + }; + } +}