Skip to content

Commit 68b38b3

Browse files
committed
Merge pull request #2658 from Microsoft/fixDecoratorBindingForSuperThis
Fixes #2601, incorrect resolution of this/super
2 parents de2e145 + e9911a5 commit 68b38b3

File tree

8 files changed

+154
-1
lines changed

8 files changed

+154
-1
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5600,7 +5600,7 @@ module ts {
56005600
}
56015601
}
56025602

5603-
if (container.kind === SyntaxKind.ComputedPropertyName) {
5603+
if (container && container.kind === SyntaxKind.ComputedPropertyName) {
56045604
error(node, Diagnostics.super_cannot_be_referenced_in_a_computed_property_name);
56055605
}
56065606
else if (isCallExpression) {

src/compiler/utilities.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,19 @@ module ts {
526526
// the *body* of the container.
527527
node = node.parent;
528528
break;
529+
case SyntaxKind.Decorator:
530+
// Decorators are always applied outside of the body of a class or method.
531+
if (node.parent.kind === SyntaxKind.Parameter && isClassElement(node.parent.parent)) {
532+
// If the decorator's parent is a Parameter, we resolve the this container from
533+
// the grandparent class declaration.
534+
node = node.parent.parent;
535+
}
536+
else if (isClassElement(node.parent)) {
537+
// If the decorator's parent is a class element, we resolve the 'this' container
538+
// from the parent class declaration.
539+
node = node.parent;
540+
}
541+
break;
529542
case SyntaxKind.ArrowFunction:
530543
if (!includeArrowFunctions) {
531544
continue;
@@ -568,6 +581,19 @@ module ts {
568581
// the *body* of the container.
569582
node = node.parent;
570583
break;
584+
case SyntaxKind.Decorator:
585+
// Decorators are always applied outside of the body of a class or method.
586+
if (node.parent.kind === SyntaxKind.Parameter && isClassElement(node.parent.parent)) {
587+
// If the decorator's parent is a Parameter, we resolve the this container from
588+
// the grandparent class declaration.
589+
node = node.parent.parent;
590+
}
591+
else if (isClassElement(node.parent)) {
592+
// If the decorator's parent is a class element, we resolve the 'this' container
593+
// from the parent class declaration.
594+
node = node.parent;
595+
}
596+
break;
571597
case SyntaxKind.FunctionDeclaration:
572598
case SyntaxKind.FunctionExpression:
573599
case SyntaxKind.ArrowFunction:
@@ -919,6 +945,7 @@ module ts {
919945
case SyntaxKind.MethodDeclaration:
920946
case SyntaxKind.GetAccessor:
921947
case SyntaxKind.SetAccessor:
948+
case SyntaxKind.MethodSignature:
922949
case SyntaxKind.IndexSignature:
923950
return true;
924951
default:
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
tests/cases/conformance/decorators/class/method/decoratorOnClassMethod11.ts(5,10): error TS2331: 'this' cannot be referenced in a module body.
2+
3+
4+
==== tests/cases/conformance/decorators/class/method/decoratorOnClassMethod11.ts (1 errors) ====
5+
module M {
6+
class C {
7+
decorator(target: Object, key: string): void { }
8+
9+
@this.decorator
10+
~~~~
11+
!!! error TS2331: 'this' cannot be referenced in a module body.
12+
method() { }
13+
}
14+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//// [decoratorOnClassMethod11.ts]
2+
module M {
3+
class C {
4+
decorator(target: Object, key: string): void { }
5+
6+
@this.decorator
7+
method() { }
8+
}
9+
}
10+
11+
//// [decoratorOnClassMethod11.js]
12+
var __decorate = this.__decorate || (typeof Reflect === "object" && Reflect.decorate) || function (decorators, target, key, desc) {
13+
switch (arguments.length) {
14+
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
15+
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
16+
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
17+
}
18+
};
19+
var M;
20+
(function (M) {
21+
var C = (function () {
22+
function C() {
23+
}
24+
C.prototype.decorator = function (target, key) { };
25+
C.prototype.method = function () { };
26+
Object.defineProperty(C.prototype, "method",
27+
__decorate([
28+
this.decorator
29+
], C.prototype, "method", Object.getOwnPropertyDescriptor(C.prototype, "method")));
30+
return C;
31+
})();
32+
})(M || (M = {}));
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
tests/cases/conformance/decorators/class/method/decoratorOnClassMethod12.ts(6,10): error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class
2+
3+
4+
==== tests/cases/conformance/decorators/class/method/decoratorOnClassMethod12.ts (1 errors) ====
5+
module M {
6+
class S {
7+
decorator(target: Object, key: string): void { }
8+
}
9+
class C extends S {
10+
@super.decorator
11+
~~~~~
12+
!!! error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class
13+
method() { }
14+
}
15+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//// [decoratorOnClassMethod12.ts]
2+
module M {
3+
class S {
4+
decorator(target: Object, key: string): void { }
5+
}
6+
class C extends S {
7+
@super.decorator
8+
method() { }
9+
}
10+
}
11+
12+
//// [decoratorOnClassMethod12.js]
13+
var __extends = this.__extends || function (d, b) {
14+
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
15+
function __() { this.constructor = d; }
16+
__.prototype = b.prototype;
17+
d.prototype = new __();
18+
};
19+
var __decorate = this.__decorate || (typeof Reflect === "object" && Reflect.decorate) || function (decorators, target, key, desc) {
20+
switch (arguments.length) {
21+
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
22+
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
23+
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
24+
}
25+
};
26+
var M;
27+
(function (M) {
28+
var S = (function () {
29+
function S() {
30+
}
31+
S.prototype.decorator = function (target, key) { };
32+
return S;
33+
})();
34+
var C = (function (_super) {
35+
__extends(C, _super);
36+
function C() {
37+
_super.apply(this, arguments);
38+
}
39+
C.prototype.method = function () { };
40+
Object.defineProperty(C.prototype, "method",
41+
__decorate([
42+
_super.decorator
43+
], C.prototype, "method", Object.getOwnPropertyDescriptor(C.prototype, "method")));
44+
return C;
45+
})(S);
46+
})(M || (M = {}));
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// @target: ES5
2+
module M {
3+
class C {
4+
decorator(target: Object, key: string): void { }
5+
6+
@this.decorator
7+
method() { }
8+
}
9+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// @target: ES5
2+
module M {
3+
class S {
4+
decorator(target: Object, key: string): void { }
5+
}
6+
class C extends S {
7+
@super.decorator
8+
method() { }
9+
}
10+
}

0 commit comments

Comments
 (0)