Skip to content

Commit 4e28fd3

Browse files
committed
Fix ClassDecoratorContext.name to use literal class name (#62870)
When a class has a static `name` getter or property, the decorator context's `name` property was incorrectly returning the getter's value instead of the actual class name. This changes the emitted code from: { kind: "class", name: _classThis.name, ... } to: { kind: "class", name: "ClassName", ... } Fixes #62870
1 parent 0a07132 commit 4e28fd3

File tree

172 files changed

+425
-245
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

172 files changed

+425
-245
lines changed

src/compiler/transformers/esDecorators.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -876,11 +876,14 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc
876876
leadingBlockStatements ??= [];
877877

878878
// produces:
879-
// __esDecorate(null, _classDescriptor = { value: this }, _classDecorators, { kind: "class", name: this.name, metadata }, _classExtraInitializers);
879+
// __esDecorate(null, _classDescriptor = { value: this }, _classDecorators, { kind: "class", name: "C", metadata }, _classExtraInitializers);
880880
const valueProperty = factory.createPropertyAssignment("value", renamedClassThis);
881881
const classDescriptor = factory.createObjectLiteralExpression([valueProperty]);
882882
const classDescriptorAssignment = factory.createAssignment(classInfo.classDescriptorName, classDescriptor);
883-
const classNameReference = factory.createPropertyAccessExpression(renamedClassThis, "name");
883+
// Use the literal class name to avoid triggering a static `name` getter (see #62870)
884+
const classNameReference = node.name
885+
? factory.createStringLiteralFromNode(node.name)
886+
: node.emitNode?.assignedName ?? factory.createStringLiteral("");
884887
const esDecorateHelper = emitHelpers().createESDecorateHelper(
885888
factory.createNull(),
886889
classDescriptorAssignment,

tests/baselines/reference/esDecorators-classDeclaration-accessors-staticPrivate(target=es2015).js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ let D = (() => {
5555
__setFunctionName(_classThis, "D");
5656
(() => {
5757
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
58-
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
58+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: "D", metadata: _metadata }, null, _classExtraInitializers);
5959
D = _classThis = _classDescriptor.value;
6060
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
6161
})();

tests/baselines/reference/esDecorators-classDeclaration-accessors-staticPrivate(target=es2022).js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ let D = (() => {
5252
static { _D_method1_get = function _D_method1_get() { return 0; }, _D_method1_set = function _D_method1_set(value) { }; }
5353
static {
5454
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
55-
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
55+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: "D", metadata: _metadata }, null, _classExtraInitializers);
5656
D = _classThis = _classDescriptor.value;
5757
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
5858
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
//// [tests/cases/conformance/esDecorators/classDeclaration/esDecorators-classDeclaration-classDecoratorContextNameStaticGetter.ts] ////
2+
3+
//// [esDecorators-classDeclaration-classDecoratorContextNameStaticGetter.ts]
4+
// https://github.com/microsoft/TypeScript/issues/62870
5+
// ClassDecoratorContext.name should use the actual class name, not the static name getter
6+
7+
const decorate = (_: unknown, ctx: ClassDecoratorContext) => {
8+
console.log('decorate(%o)', ctx.name);
9+
};
10+
11+
// Named class with static name getter - ctx.name should be "A", not the getter value
12+
@decorate
13+
class A {
14+
static get name() {
15+
return 2434;
16+
}
17+
}
18+
19+
// Named class with static name property - ctx.name should be "B", not the property value
20+
@decorate
21+
class B {
22+
static name = "not B";
23+
}
24+
25+
// Named class without overriding name - ctx.name should be "C"
26+
@decorate
27+
class C {
28+
}
29+
30+
31+
//// [esDecorators-classDeclaration-classDecoratorContextNameStaticGetter.js]
32+
// https://github.com/microsoft/TypeScript/issues/62870
33+
// ClassDecoratorContext.name should use the actual class name, not the static name getter
34+
const decorate = (_, ctx) => {
35+
console.log('decorate(%o)', ctx.name);
36+
};
37+
// Named class with static name getter - ctx.name should be "A", not the getter value
38+
let A = (() => {
39+
let _classDecorators = [decorate];
40+
let _classDescriptor;
41+
let _classExtraInitializers = [];
42+
let _classThis;
43+
var A = class {
44+
static { _classThis = this; }
45+
static {
46+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
47+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: "A", metadata: _metadata }, null, _classExtraInitializers);
48+
A = _classThis = _classDescriptor.value;
49+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
50+
__runInitializers(_classThis, _classExtraInitializers);
51+
}
52+
static get name() {
53+
return 2434;
54+
}
55+
};
56+
return A = _classThis;
57+
})();
58+
// Named class with static name property - ctx.name should be "B", not the property value
59+
let B = (() => {
60+
let _classDecorators = [decorate];
61+
let _classDescriptor;
62+
let _classExtraInitializers = [];
63+
let _classThis;
64+
var B = class {
65+
static { _classThis = this; }
66+
static {
67+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
68+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: "B", metadata: _metadata }, null, _classExtraInitializers);
69+
B = _classThis = _classDescriptor.value;
70+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
71+
}
72+
static name = "not B";
73+
static {
74+
__runInitializers(_classThis, _classExtraInitializers);
75+
}
76+
};
77+
return B = _classThis;
78+
})();
79+
// Named class without overriding name - ctx.name should be "C"
80+
let C = (() => {
81+
let _classDecorators = [decorate];
82+
let _classDescriptor;
83+
let _classExtraInitializers = [];
84+
let _classThis;
85+
var C = class {
86+
static { _classThis = this; }
87+
static {
88+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
89+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: "C", metadata: _metadata }, null, _classExtraInitializers);
90+
C = _classThis = _classDescriptor.value;
91+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
92+
__runInitializers(_classThis, _classExtraInitializers);
93+
}
94+
};
95+
return C = _classThis;
96+
})();
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//// [tests/cases/conformance/esDecorators/classDeclaration/esDecorators-classDeclaration-classDecoratorContextNameStaticGetter.ts] ////
2+
3+
//// [esDecorators-classDeclaration-classDecoratorContextNameStaticGetter.ts]
4+
// https://github.com/microsoft/TypeScript/issues/62870
5+
// ClassDecoratorContext.name should use the actual class name, not the static name getter
6+
7+
const decorate = (_: unknown, ctx: ClassDecoratorContext) => {
8+
console.log('decorate(%o)', ctx.name);
9+
};
10+
11+
// Named class with static name getter - ctx.name should be "A", not the getter value
12+
@decorate
13+
class A {
14+
static get name() {
15+
return 2434;
16+
}
17+
}
18+
19+
// Named class with static name property - ctx.name should be "B", not the property value
20+
@decorate
21+
class B {
22+
static name = "not B";
23+
}
24+
25+
// Named class without overriding name - ctx.name should be "C"
26+
@decorate
27+
class C {
28+
}
29+
30+
31+
//// [esDecorators-classDeclaration-classDecoratorContextNameStaticGetter.js]
32+
// https://github.com/microsoft/TypeScript/issues/62870
33+
// ClassDecoratorContext.name should use the actual class name, not the static name getter
34+
const decorate = (_, ctx) => {
35+
console.log('decorate(%o)', ctx.name);
36+
};
37+
// Named class with static name getter - ctx.name should be "A", not the getter value
38+
@decorate
39+
class A {
40+
static get name() {
41+
return 2434;
42+
}
43+
}
44+
// Named class with static name property - ctx.name should be "B", not the property value
45+
@decorate
46+
class B {
47+
static name = "not B";
48+
}
49+
// Named class without overriding name - ctx.name should be "C"
50+
@decorate
51+
class C {
52+
}

tests/baselines/reference/esDecorators-classDeclaration-classSuper.1.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ let C = (() => {
3535
static { _classThis = this; }
3636
static {
3737
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
38-
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
38+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: "C", metadata: _metadata }, null, _classExtraInitializers);
3939
C = _classThis = _classDescriptor.value;
4040
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
4141
}

tests/baselines/reference/esDecorators-classDeclaration-classSuper.2.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ let C1 = (() => {
4141
static { _classThis = this; }
4242
static {
4343
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
44-
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
44+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: "C1", metadata: _metadata }, null, _classExtraInitializers);
4545
C1 = _classThis = _classDescriptor.value;
4646
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
4747
}
@@ -65,7 +65,7 @@ let C2 = (() => {
6565
static { _classThis = this; }
6666
static {
6767
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
68-
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
68+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: "C2", metadata: _metadata }, null, _classExtraInitializers);
6969
C2 = _classThis = _classDescriptor.value;
7070
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
7171
}
@@ -89,7 +89,7 @@ let C3 = (() => {
8989
static { _classThis = this; }
9090
static {
9191
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
92-
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
92+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: "C3", metadata: _metadata }, null, _classExtraInitializers);
9393
C3 = _classThis = _classDescriptor.value;
9494
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
9595
}

tests/baselines/reference/esDecorators-classDeclaration-classSuper.3.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ let C = (() => {
5757
static { _classThis = this; }
5858
static {
5959
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
60-
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
60+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: "C", metadata: _metadata }, null, _classExtraInitializers);
6161
C = _classThis = _classDescriptor.value;
6262
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
6363
}

tests/baselines/reference/esDecorators-classDeclaration-classSuper.4.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ let C = (() => {
3232
static { _classThis = this; }
3333
static {
3434
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
35-
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
35+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: "C", metadata: _metadata }, null, _classExtraInitializers);
3636
C = _classThis = _classDescriptor.value;
3737
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
3838
}

tests/baselines/reference/esDecorators-classDeclaration-classSuper.5.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ let C1 = (() => {
6161
static { _classThis = this; }
6262
static {
6363
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
64-
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
64+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: "C1", metadata: _metadata }, null, _classExtraInitializers);
6565
C1 = _classThis = _classDescriptor.value;
6666
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
6767
}
@@ -108,7 +108,7 @@ let C2 = (() => {
108108
static { _classThis = this; }
109109
static {
110110
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
111-
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
111+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: "C2", metadata: _metadata }, null, _classExtraInitializers);
112112
C2 = _classThis = _classDescriptor.value;
113113
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
114114
}
@@ -155,7 +155,7 @@ let C3 = (() => {
155155
static { _classThis = this; }
156156
static {
157157
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
158-
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
158+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: "C3", metadata: _metadata }, null, _classExtraInitializers);
159159
C3 = _classThis = _classDescriptor.value;
160160
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
161161
}

0 commit comments

Comments
 (0)