Skip to content

Commit 8e94d84

Browse files
Merge pull request #12893 from Microsoft/capturedThisFix
Avoid replacing last statement of derived constructors if 'this' is referenced.
2 parents 2e97cff + 784eac5 commit 8e94d84

20 files changed

+155
-16
lines changed

src/compiler/transformers/es2015.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,8 +1024,11 @@ namespace ts {
10241024
}
10251025
}
10261026

1027-
// Return the result if we have an immediate super() call on the last statement.
1028-
if (superCallExpression && statementOffset === ctorStatements.length - 1) {
1027+
// Return the result if we have an immediate super() call on the last statement,
1028+
// but only if the constructor itself doesn't use 'this' elsewhere.
1029+
if (superCallExpression
1030+
&& statementOffset === ctorStatements.length - 1
1031+
&& !(ctor.transformFlags & (TransformFlags.ContainsLexicalThis | TransformFlags.ContainsCapturedLexicalThis))) {
10291032
const returnStatement = createReturn(superCallExpression);
10301033

10311034
if (superCallExpression.kind !== SyntaxKind.BinaryExpression

tests/baselines/reference/arrowFunctionContexts.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ var Base = (function () {
116116
var Derived = (function (_super) {
117117
__extends(Derived, _super);
118118
function Derived() {
119-
return _super.call(this, function () { return _this; }) || this;
119+
var _this = _super.call(this, function () { return _this; }) || this;
120+
return _this;
120121
}
121122
return Derived;
122123
}(Base));
@@ -157,7 +158,8 @@ var M2;
157158
var Derived = (function (_super) {
158159
__extends(Derived, _super);
159160
function Derived() {
160-
return _super.call(this, function () { return _this; }) || this;
161+
var _this = _super.call(this, function () { return _this; }) || this;
162+
return _this;
161163
}
162164
return Derived;
163165
}(Base));
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
tests/cases/compiler/captureSuperPropertyAccessInSuperCall01.ts(9,24): error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class.
2+
3+
4+
==== tests/cases/compiler/captureSuperPropertyAccessInSuperCall01.ts (1 errors) ====
5+
class A {
6+
constructor(f: () => string) {
7+
}
8+
public blah(): string { return ""; }
9+
}
10+
11+
class B extends A {
12+
constructor() {
13+
super(() => { return super.blah(); })
14+
~~~~~
15+
!!! error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class.
16+
}
17+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//// [captureSuperPropertyAccessInSuperCall01.ts]
2+
class A {
3+
constructor(f: () => string) {
4+
}
5+
public blah(): string { return ""; }
6+
}
7+
8+
class B extends A {
9+
constructor() {
10+
super(() => { return super.blah(); })
11+
}
12+
}
13+
14+
//// [captureSuperPropertyAccessInSuperCall01.js]
15+
var __extends = (this && this.__extends) || function (d, b) {
16+
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
17+
function __() { this.constructor = d; }
18+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
19+
};
20+
var A = (function () {
21+
function A(f) {
22+
}
23+
A.prototype.blah = function () { return ""; };
24+
return A;
25+
}());
26+
var B = (function (_super) {
27+
__extends(B, _super);
28+
function B() {
29+
var _this = _super.call(this, function () { return _super.blah.call(_this); }) || this;
30+
return _this;
31+
}
32+
return B;
33+
}(A));

tests/baselines/reference/captureThisInSuperCall.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ var A = (function () {
2222
var B = (function (_super) {
2323
__extends(B, _super);
2424
function B() {
25-
return _super.call(this, { test: function () { return _this.someMethod(); } }) || this;
25+
var _this = _super.call(this, { test: function () { return _this.someMethod(); } }) || this;
26+
return _this;
2627
}
2728
B.prototype.someMethod = function () { };
2829
return B;

tests/baselines/reference/checkSuperCallBeforeThisAccessing5.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ var Based = (function () {
2525
var Derived = (function (_super) {
2626
__extends(Derived, _super);
2727
function Derived() {
28-
return _super.call(this, this.x) || this;
28+
var _this = _super.call(this, _this.x) || this;
29+
return _this;
2930
}
3031
return Derived;
3132
}(Based));

tests/baselines/reference/checkSuperCallBeforeThisAccessing7.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ var Base = (function () {
2323
var Super = (function (_super) {
2424
__extends(Super, _super);
2525
function Super() {
26-
return _super.call(this, (function () { return _this; })) || this;
26+
var _this = _super.call(this, (function () { return _this; })) || this;
27+
return _this;
2728
}
2829
return Super;
2930
}(Base));

tests/baselines/reference/derivedClassSuperCallsWithThisArg.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ var Base = (function () {
4242
var Derived = (function (_super) {
4343
__extends(Derived, _super);
4444
function Derived() {
45-
return _super.call(this, _this) || this;
45+
var _this = _super.call(this, _this) || this;
46+
return _this;
4647
}
4748
return Derived;
4849
}(Base));

tests/baselines/reference/superCallBeforeThisAccessing2.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ var Base = (function () {
2424
var D = (function (_super) {
2525
__extends(D, _super);
2626
function D() {
27-
return _super.call(this, function () { _this._t; }) || this;
27+
var _this = _super.call(this, function () { _this._t; }) || this;
28+
return _this;
2829
}
2930
return D;
3031
}(Base));

tests/baselines/reference/superCallBeforeThisAccessing6.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ var Base = (function () {
2424
var D = (function (_super) {
2525
__extends(D, _super);
2626
function D() {
27-
return _super.call(this, this) || this;
27+
var _this = _super.call(this, _this) || this;
28+
return _this;
2829
}
2930
return D;
3031
}(Base));

0 commit comments

Comments
 (0)