Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/compiler/transformers/es2015.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1024,8 +1024,11 @@ namespace ts {
}
}

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

if (superCallExpression.kind !== SyntaxKind.BinaryExpression
Expand Down
6 changes: 4 additions & 2 deletions tests/baselines/reference/arrowFunctionContexts.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ var Base = (function () {
var Derived = (function (_super) {
__extends(Derived, _super);
function Derived() {
return _super.call(this, function () { return _this; }) || this;
var _this = _super.call(this, function () { return _this; }) || this;

@markboyall markboyall Dec 14, 2016

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These baselines don't quite seem correct. Surely, _this should be declared and set to this first before the super call. That way, if the super call invokes the function, it'll still function as expected if the super does not return a new value for this.

@DanielRosenwasser DanielRosenwasser Dec 14, 2016

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is intentional - in ES2015 it is an error for this to be used before a call to super(...) completes.

This means that it shouldn't be an error to reference _this, but it should be an error to evaluate _this in a callback before the super(...) call returns.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ES2015 doesn't have a bunch of existing TypeScript code that evaluates this in a callback before the super() call returns.

return _this;
}
return Derived;
}(Base));
Expand Down Expand Up @@ -157,7 +158,8 @@ var M2;
var Derived = (function (_super) {
__extends(Derived, _super);
function Derived() {
return _super.call(this, function () { return _this; }) || this;
var _this = _super.call(this, function () { return _this; }) || this;
return _this;
}
return Derived;
}(Base));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
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.


==== tests/cases/compiler/captureSuperPropertyAccessInSuperCall01.ts (1 errors) ====
class A {
constructor(f: () => string) {
}
public blah(): string { return ""; }
}

class B extends A {
constructor() {
super(() => { return super.blah(); })
~~~~~
!!! error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class.
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//// [captureSuperPropertyAccessInSuperCall01.ts]
class A {
constructor(f: () => string) {
}
public blah(): string { return ""; }
}

class B extends A {
constructor() {
super(() => { return super.blah(); })
}
}

//// [captureSuperPropertyAccessInSuperCall01.js]
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var A = (function () {
function A(f) {
}
A.prototype.blah = function () { return ""; };
return A;
}());
var B = (function (_super) {
__extends(B, _super);
function B() {
var _this = _super.call(this, function () { return _super.blah.call(_this); }) || this;
return _this;
}
return B;
}(A));
3 changes: 2 additions & 1 deletion tests/baselines/reference/captureThisInSuperCall.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ var A = (function () {
var B = (function (_super) {
__extends(B, _super);
function B() {
return _super.call(this, { test: function () { return _this.someMethod(); } }) || this;
var _this = _super.call(this, { test: function () { return _this.someMethod(); } }) || this;
return _this;
}
B.prototype.someMethod = function () { };
return B;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ var Based = (function () {
var Derived = (function (_super) {
__extends(Derived, _super);
function Derived() {
return _super.call(this, this.x) || this;
var _this = _super.call(this, _this.x) || this;
return _this;
}
return Derived;
}(Based));
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ var Base = (function () {
var Super = (function (_super) {
__extends(Super, _super);
function Super() {
return _super.call(this, (function () { return _this; })) || this;
var _this = _super.call(this, (function () { return _this; })) || this;
return _this;
}
return Super;
}(Base));
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ var Base = (function () {
var Derived = (function (_super) {
__extends(Derived, _super);
function Derived() {
return _super.call(this, _this) || this;
var _this = _super.call(this, _this) || this;
return _this;
}
return Derived;
}(Base));
Expand Down
3 changes: 2 additions & 1 deletion tests/baselines/reference/superCallBeforeThisAccessing2.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ var Base = (function () {
var D = (function (_super) {
__extends(D, _super);
function D() {
return _super.call(this, function () { _this._t; }) || this;
var _this = _super.call(this, function () { _this._t; }) || this;
return _this;
}
return D;
}(Base));
3 changes: 2 additions & 1 deletion tests/baselines/reference/superCallBeforeThisAccessing6.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ var Base = (function () {
var D = (function (_super) {
__extends(D, _super);
function D() {
return _super.call(this, this) || this;
var _this = _super.call(this, _this) || this;
return _this;
}
return D;
}(Base));
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
tests/cases/compiler/superPropertyAccessInSuperCall01.ts(9,9): error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class.


==== tests/cases/compiler/superPropertyAccessInSuperCall01.ts (1 errors) ====
class A {
constructor(f: string) {
}
public blah(): string { return ""; }
}

class B extends A {
constructor() {
super(super.blah())
~~~~~
!!! error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class.
}
}
33 changes: 33 additions & 0 deletions tests/baselines/reference/superPropertyAccessInSuperCall01.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//// [superPropertyAccessInSuperCall01.ts]
class A {
constructor(f: string) {
}
public blah(): string { return ""; }
}

class B extends A {
constructor() {
super(super.blah())
}
}

//// [superPropertyAccessInSuperCall01.js]
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var A = (function () {
function A(f) {
}
A.prototype.blah = function () { return ""; };
return A;
}());
var B = (function (_super) {
__extends(B, _super);
function B() {
var _this = _super.call(this, _super.blah.call(_this)) || this;
return _this;
}
return B;
}(A));
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ var C1 = (function (_super) {
var C2 = (function (_super) {
__extends(C2, _super);
function C2() {
return _super.call(this, _super.x.call(_this)) || this;
var _this = _super.call(this, _super.x.call(_this)) || this;
return _this;
}
return C2;
}(B));
3 changes: 2 additions & 1 deletion tests/baselines/reference/thisInInvalidContexts.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ var ClassWithNoInitializer = (function (_super) {
__extends(ClassWithNoInitializer, _super);
//'this' in optional super call
function ClassWithNoInitializer() {
return _super.call(this, _this) || this;
var _this = _super.call(this, _this) || this;
return _this;
}
return ClassWithNoInitializer;
}(BaseErrClass));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ var ClassWithNoInitializer = (function (_super) {
__extends(ClassWithNoInitializer, _super);
//'this' in optional super call
function ClassWithNoInitializer() {
return _super.call(this, _this) || this;
var _this = _super.call(this, _this) || this;
return _this;
}
return ClassWithNoInitializer;
}(BaseErrClass));
Expand Down
3 changes: 2 additions & 1 deletion tests/baselines/reference/thisInSuperCall.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ var Base = (function () {
var Foo = (function (_super) {
__extends(Foo, _super);
function Foo() {
return _super.call(this, _this) || this;
var _this = _super.call(this, _this) || this;
return _this;
}
return Foo;
}(Base));
Expand Down
3 changes: 2 additions & 1 deletion tests/baselines/reference/thisInSuperCall2.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ var Base = (function () {
var Foo = (function (_super) {
__extends(Foo, _super);
function Foo() {
return _super.call(this, _this) || this;
var _this = _super.call(this, _this) || this;
return _this;
}
return Foo;
}(Base));
Expand Down
3 changes: 2 additions & 1 deletion tests/baselines/reference/validUseOfThisInSuper.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ var Base = (function () {
var Super = (function (_super) {
__extends(Super, _super);
function Super() {
return _super.call(this, (function () { return _this; })()) || this;
var _this = _super.call(this, (function () { return _this; })()) || this;
return _this;
}
return Super;
}(Base));
11 changes: 11 additions & 0 deletions tests/cases/compiler/captureSuperPropertyAccessInSuperCall01.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class A {
constructor(f: () => string) {
}
public blah(): string { return ""; }
}

class B extends A {
constructor() {
super(() => { return super.blah(); })
}
}
11 changes: 11 additions & 0 deletions tests/cases/compiler/superPropertyAccessInSuperCall01.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class A {
constructor(f: string) {
}
public blah(): string { return ""; }
}

class B extends A {
constructor() {
super(super.blah())
}
}