Skip to content

Commit 2edc47b

Browse files
authored
Fix decorated accessor emit (microsoft#26016)
1 parent dfedb24 commit 2edc47b

9 files changed

+181
-16
lines changed

src/compiler/checker.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5124,20 +5124,25 @@ namespace ts {
51245124
}
51255125
}
51265126

5127-
function getAnnotatedAccessorType(accessor: AccessorDeclaration | undefined): Type | undefined {
5127+
function getAnnotatedAccessorTypeNode(accessor: AccessorDeclaration | undefined): TypeNode | undefined {
51285128
if (accessor) {
51295129
if (accessor.kind === SyntaxKind.GetAccessor) {
51305130
const getterTypeAnnotation = getEffectiveReturnTypeNode(accessor);
5131-
return getterTypeAnnotation && getTypeFromTypeNode(getterTypeAnnotation);
5131+
return getterTypeAnnotation;
51325132
}
51335133
else {
51345134
const setterTypeAnnotation = getEffectiveSetAccessorTypeAnnotationNode(accessor);
5135-
return setterTypeAnnotation && getTypeFromTypeNode(setterTypeAnnotation);
5135+
return setterTypeAnnotation;
51365136
}
51375137
}
51385138
return undefined;
51395139
}
51405140

5141+
function getAnnotatedAccessorType(accessor: AccessorDeclaration | undefined): Type | undefined {
5142+
const node = getAnnotatedAccessorTypeNode(accessor);
5143+
return node && getTypeFromTypeNode(node);
5144+
}
5145+
51415146
function getAnnotatedAccessorThisParameter(accessor: AccessorDeclaration): Symbol | undefined {
51425147
const parameter = getAccessorThisParameter(accessor);
51435148
return parameter && parameter.symbol;
@@ -23519,9 +23524,13 @@ namespace ts {
2351923524
}
2352023525
break;
2352123526

23522-
case SyntaxKind.MethodDeclaration:
2352323527
case SyntaxKind.GetAccessor:
2352423528
case SyntaxKind.SetAccessor:
23529+
const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor;
23530+
const otherAccessor = getDeclarationOfKind<AccessorDeclaration>(getSymbolOfNode(node as AccessorDeclaration), otherKind);
23531+
markDecoratorMedataDataTypeNodeAsReferenced(getAnnotatedAccessorTypeNode(node as AccessorDeclaration) || otherAccessor && getAnnotatedAccessorTypeNode(otherAccessor));
23532+
break;
23533+
case SyntaxKind.MethodDeclaration:
2352523534
for (const parameter of (<FunctionLikeDeclaration>node).parameters) {
2352623535
markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter));
2352723536
}
@@ -28074,8 +28083,8 @@ namespace ts {
2807428083
const otherAccessor = getDeclarationOfKind<AccessorDeclaration>(getSymbolOfNode(accessor), otherKind);
2807528084
const firstAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? otherAccessor : accessor;
2807628085
const secondAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? accessor : otherAccessor;
28077-
const setAccessor = accessor.kind === SyntaxKind.SetAccessor ? accessor : otherAccessor;
28078-
const getAccessor = accessor.kind === SyntaxKind.GetAccessor ? accessor : otherAccessor;
28086+
const setAccessor = accessor.kind === SyntaxKind.SetAccessor ? accessor : otherAccessor as SetAccessorDeclaration;
28087+
const getAccessor = accessor.kind === SyntaxKind.GetAccessor ? accessor : otherAccessor as GetAccessorDeclaration;
2807928088
return {
2808028089
firstAccessor,
2808128090
secondAccessor,

src/compiler/transformers/ts.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1752,6 +1752,12 @@ namespace ts {
17521752
type SerializedEntityNameAsExpression = Identifier | BinaryExpression | PropertyAccessExpression;
17531753
type SerializedTypeNode = SerializedEntityNameAsExpression | VoidExpression | ConditionalExpression;
17541754

1755+
function getAccessorTypeNode(node: AccessorDeclaration) {
1756+
const accessors = resolver.getAllAccessorDeclarations(node);
1757+
return accessors.setAccessor && getSetAccessorTypeAnnotationNode(accessors.setAccessor)
1758+
|| accessors.getAccessor && getEffectiveReturnTypeNode(accessors.getAccessor);
1759+
}
1760+
17551761
/**
17561762
* Serializes the type of a node for use with decorator type metadata.
17571763
*
@@ -1761,10 +1767,10 @@ namespace ts {
17611767
switch (node.kind) {
17621768
case SyntaxKind.PropertyDeclaration:
17631769
case SyntaxKind.Parameter:
1764-
case SyntaxKind.GetAccessor:
17651770
return serializeTypeNode((<PropertyDeclaration | ParameterDeclaration | GetAccessorDeclaration>node).type);
17661771
case SyntaxKind.SetAccessor:
1767-
return serializeTypeNode(getSetAccessorTypeAnnotationNode(<SetAccessorDeclaration>node));
1772+
case SyntaxKind.GetAccessor:
1773+
return serializeTypeNode(getAccessorTypeNode(node as AccessorDeclaration));
17681774
case SyntaxKind.ClassDeclaration:
17691775
case SyntaxKind.ClassExpression:
17701776
case SyntaxKind.MethodDeclaration:

src/compiler/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3315,8 +3315,8 @@ namespace ts {
33153315
export interface AllAccessorDeclarations {
33163316
firstAccessor: AccessorDeclaration;
33173317
secondAccessor: AccessorDeclaration | undefined;
3318-
getAccessor: AccessorDeclaration | undefined;
3319-
setAccessor: AccessorDeclaration | undefined;
3318+
getAccessor: GetAccessorDeclaration | undefined;
3319+
setAccessor: SetAccessorDeclaration | undefined;
33203320
}
33213321

33223322
/** Indicates how to serialize the name for a TypeReferenceNode when emitting decorator metadata */

src/compiler/utilities.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3310,8 +3310,8 @@ namespace ts {
33103310
// TODO: GH#18217
33113311
let firstAccessor!: AccessorDeclaration;
33123312
let secondAccessor!: AccessorDeclaration;
3313-
let getAccessor!: AccessorDeclaration;
3314-
let setAccessor!: AccessorDeclaration;
3313+
let getAccessor!: GetAccessorDeclaration;
3314+
let setAccessor!: SetAccessorDeclaration;
33153315
if (hasDynamicName(accessor)) {
33163316
firstAccessor = accessor;
33173317
if (accessor.kind === SyntaxKind.GetAccessor) {
@@ -3339,11 +3339,11 @@ namespace ts {
33393339
}
33403340

33413341
if (member.kind === SyntaxKind.GetAccessor && !getAccessor) {
3342-
getAccessor = <AccessorDeclaration>member;
3342+
getAccessor = <GetAccessorDeclaration>member;
33433343
}
33443344

33453345
if (member.kind === SyntaxKind.SetAccessor && !setAccessor) {
3346-
setAccessor = <AccessorDeclaration>member;
3346+
setAccessor = <SetAccessorDeclaration>member;
33473347
}
33483348
}
33493349
}

tests/baselines/reference/decoratorOnClassAccessor8.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ var A = /** @class */ (function () {
5050
});
5151
__decorate([
5252
dec,
53-
__metadata("design:type", Object),
53+
__metadata("design:type", Number),
5454
__metadata("design:paramtypes", [Number])
5555
], A.prototype, "x", null);
5656
return A;
@@ -98,7 +98,7 @@ var D = /** @class */ (function () {
9898
});
9999
__decorate([
100100
dec,
101-
__metadata("design:type", Object),
101+
__metadata("design:type", Number),
102102
__metadata("design:paramtypes", [Number])
103103
], D.prototype, "x", null);
104104
return D;
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//// [tests/cases/compiler/targetEs6DecoratorMetadataImportNotElided.ts] ////
2+
3+
//// [deps.ts]
4+
export function Input(): any { }
5+
export class TemplateRef { }
6+
7+
//// [index.ts]
8+
import { Input, TemplateRef } from './deps';
9+
10+
export class MyComponent {
11+
_ref: TemplateRef;
12+
13+
@Input()
14+
get ref() { return this._ref; }
15+
set ref(value: TemplateRef) { this._ref = value; }
16+
}
17+
18+
19+
//// [deps.js]
20+
export function Input() { }
21+
var TemplateRef = /** @class */ (function () {
22+
function TemplateRef() {
23+
}
24+
return TemplateRef;
25+
}());
26+
export { TemplateRef };
27+
//// [index.js]
28+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
29+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
30+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
31+
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;
32+
return c > 3 && r && Object.defineProperty(target, key, r), r;
33+
};
34+
var __metadata = (this && this.__metadata) || function (k, v) {
35+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
36+
};
37+
import { Input, TemplateRef } from './deps';
38+
var MyComponent = /** @class */ (function () {
39+
function MyComponent() {
40+
}
41+
Object.defineProperty(MyComponent.prototype, "ref", {
42+
get: function () { return this._ref; },
43+
set: function (value) { this._ref = value; },
44+
enumerable: true,
45+
configurable: true
46+
});
47+
__decorate([
48+
Input(),
49+
__metadata("design:type", TemplateRef),
50+
__metadata("design:paramtypes", [TemplateRef])
51+
], MyComponent.prototype, "ref", null);
52+
return MyComponent;
53+
}());
54+
export { MyComponent };
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
=== tests/cases/compiler/deps.ts ===
2+
export function Input(): any { }
3+
>Input : Symbol(Input, Decl(deps.ts, 0, 0))
4+
5+
export class TemplateRef { }
6+
>TemplateRef : Symbol(TemplateRef, Decl(deps.ts, 0, 32))
7+
8+
=== tests/cases/compiler/index.ts ===
9+
import { Input, TemplateRef } from './deps';
10+
>Input : Symbol(Input, Decl(index.ts, 0, 8))
11+
>TemplateRef : Symbol(TemplateRef, Decl(index.ts, 0, 15))
12+
13+
export class MyComponent {
14+
>MyComponent : Symbol(MyComponent, Decl(index.ts, 0, 44))
15+
16+
_ref: TemplateRef;
17+
>_ref : Symbol(MyComponent._ref, Decl(index.ts, 2, 26))
18+
>TemplateRef : Symbol(TemplateRef, Decl(index.ts, 0, 15))
19+
20+
@Input()
21+
>Input : Symbol(Input, Decl(index.ts, 0, 8))
22+
23+
get ref() { return this._ref; }
24+
>ref : Symbol(MyComponent.ref, Decl(index.ts, 3, 22), Decl(index.ts, 6, 35))
25+
>this._ref : Symbol(MyComponent._ref, Decl(index.ts, 2, 26))
26+
>this : Symbol(MyComponent, Decl(index.ts, 0, 44))
27+
>_ref : Symbol(MyComponent._ref, Decl(index.ts, 2, 26))
28+
29+
set ref(value: TemplateRef) { this._ref = value; }
30+
>ref : Symbol(MyComponent.ref, Decl(index.ts, 3, 22), Decl(index.ts, 6, 35))
31+
>value : Symbol(value, Decl(index.ts, 7, 12))
32+
>TemplateRef : Symbol(TemplateRef, Decl(index.ts, 0, 15))
33+
>this._ref : Symbol(MyComponent._ref, Decl(index.ts, 2, 26))
34+
>this : Symbol(MyComponent, Decl(index.ts, 0, 44))
35+
>_ref : Symbol(MyComponent._ref, Decl(index.ts, 2, 26))
36+
>value : Symbol(value, Decl(index.ts, 7, 12))
37+
}
38+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
=== tests/cases/compiler/deps.ts ===
2+
export function Input(): any { }
3+
>Input : () => any
4+
5+
export class TemplateRef { }
6+
>TemplateRef : TemplateRef
7+
8+
=== tests/cases/compiler/index.ts ===
9+
import { Input, TemplateRef } from './deps';
10+
>Input : () => any
11+
>TemplateRef : typeof TemplateRef
12+
13+
export class MyComponent {
14+
>MyComponent : MyComponent
15+
16+
_ref: TemplateRef;
17+
>_ref : TemplateRef
18+
>TemplateRef : TemplateRef
19+
20+
@Input()
21+
>Input() : any
22+
>Input : () => any
23+
24+
get ref() { return this._ref; }
25+
>ref : TemplateRef
26+
>this._ref : TemplateRef
27+
>this : this
28+
>_ref : TemplateRef
29+
30+
set ref(value: TemplateRef) { this._ref = value; }
31+
>ref : TemplateRef
32+
>value : TemplateRef
33+
>TemplateRef : TemplateRef
34+
>this._ref = value : TemplateRef
35+
>this._ref : TemplateRef
36+
>this : this
37+
>_ref : TemplateRef
38+
>value : TemplateRef
39+
}
40+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// @module: es6
2+
// @target: es5
3+
// @emitDecoratorMetadata: true
4+
// @experimentalDecorators: true
5+
// @filename: deps.ts
6+
export function Input(): any { }
7+
export class TemplateRef { }
8+
9+
// @filename: index.ts
10+
import { Input, TemplateRef } from './deps';
11+
12+
export class MyComponent {
13+
_ref: TemplateRef;
14+
15+
@Input()
16+
get ref() { return this._ref; }
17+
set ref(value: TemplateRef) { this._ref = value; }
18+
}

0 commit comments

Comments
 (0)