Merge pull request #6860 from Microsoft/checksuperbeforethislexically

Check using "super" before "this" lexically
This commit is contained in:
Yui
2016-02-11 13:12:59 -08:00
31 changed files with 742 additions and 46 deletions
+68 -34
View File
@@ -7306,6 +7306,46 @@ namespace ts {
}
}
function findFirstSuperCall(n: Node): Node {
if (isSuperCallExpression(n)) {
return n;
}
else if (isFunctionLike(n)) {
return undefined;
}
return forEachChild(n, findFirstSuperCall);
}
/**
* Return a cached result if super-statement is already found.
* Otherwise, find a super statement in a given constructor function and cache the result in the node-links of the constructor
*
* @param constructor constructor-function to look for super statement
*/
function getSuperCallInConstructor(constructor: ConstructorDeclaration): ExpressionStatement {
const links = getNodeLinks(constructor);
// Only trying to find super-call if we haven't yet tried to find one. Once we try, we will record the result
if (links.hasSuperCall === undefined) {
links.superCall = <ExpressionStatement>findFirstSuperCall(constructor.body);
links.hasSuperCall = links.superCall ? true : false;
}
return links.superCall;
}
/**
* Check if the given class-declaration extends null then return true.
* Otherwise, return false
* @param classDecl a class declaration to check if it extends null
*/
function classDeclarationExtendsNull(classDecl: ClassDeclaration): boolean {
const classSymbol = getSymbolOfNode(classDecl);
const classInstanceType = <InterfaceType>getDeclaredTypeOfSymbol(classSymbol);
const baseConstructorType = getBaseConstructorTypeOfClass(classInstanceType);
return baseConstructorType === nullType;
}
function checkThisExpression(node: Node): Type {
// Stop at the first arrow function so that we can
// tell whether 'this' needs to be captured.
@@ -7313,10 +7353,25 @@ namespace ts {
let needToCaptureLexicalThis = false;
if (container.kind === SyntaxKind.Constructor) {
const baseTypeNode = getClassExtendsHeritageClauseElement(<ClassLikeDeclaration>container.parent);
if (baseTypeNode && !(getNodeCheckFlags(container) & NodeCheckFlags.HasSeenSuperCall)) {
// In ES6, super inside constructor of class-declaration has to precede "this" accessing
error(node, Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class);
const containingClassDecl = <ClassDeclaration>container.parent;
const baseTypeNode = getClassExtendsHeritageClauseElement(containingClassDecl);
// If a containing class does not have extends clause or the class extends null
// skip checking whether super statement is called before "this" accessing.
if (baseTypeNode && !classDeclarationExtendsNull(containingClassDecl)) {
const superCall = getSuperCallInConstructor(<ConstructorDeclaration>container);
// We should give an error in the following cases:
// - No super-call
// - "this" is accessing before super-call.
// i.e super(this)
// this.x; super();
// We want to make sure that super-call is done before accessing "this" so that
// "this" is not accessed as a parameter of the super-call.
if (!superCall || superCall.end > node.pos) {
// In ES6, super inside constructor of class-declaration has to precede "this" accessing
error(node, Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class);
}
}
}
@@ -10263,14 +10318,11 @@ namespace ts {
checkGrammarTypeArguments(node, node.typeArguments) || checkGrammarArguments(node, node.arguments);
const signature = getResolvedSignature(node);
if (node.expression.kind === SyntaxKind.SuperKeyword) {
const containgFunction = getContainingFunction(node.expression);
if (containgFunction && containgFunction.kind === SyntaxKind.Constructor) {
getNodeLinks(containgFunction).flags |= NodeCheckFlags.HasSeenSuperCall;
}
if (node.expression.kind === SyntaxKind.SuperKeyword) {
return voidType;
}
if (node.kind === SyntaxKind.NewExpression) {
const declaration = signature.declaration;
@@ -11813,23 +11865,6 @@ namespace ts {
return;
}
function containsSuperCallAsComputedPropertyName(n: Declaration): boolean {
return n.name && containsSuperCall(n.name);
}
function containsSuperCall(n: Node): boolean {
if (isSuperCallExpression(n)) {
return true;
}
else if (isFunctionLike(n)) {
return false;
}
else if (isClassLike(n)) {
return forEach((<ClassLikeDeclaration>n).members, containsSuperCallAsComputedPropertyName);
}
return forEachChild(n, containsSuperCall);
}
function markThisReferencesAsErrors(n: Node): void {
if (n.kind === SyntaxKind.ThisKeyword) {
error(n, Diagnostics.this_cannot_be_referenced_in_current_location);
@@ -11850,13 +11885,11 @@ namespace ts {
// constructors of derived classes must contain at least one super call somewhere in their function body.
const containingClassDecl = <ClassDeclaration>node.parent;
if (getClassExtendsHeritageClauseElement(containingClassDecl)) {
const containingClassSymbol = getSymbolOfNode(containingClassDecl);
const containingClassInstanceType = <InterfaceType>getDeclaredTypeOfSymbol(containingClassSymbol);
const baseConstructorType = getBaseConstructorTypeOfClass(containingClassInstanceType);
if (containsSuperCall(node.body)) {
if (baseConstructorType === nullType) {
error(node, Diagnostics.A_constructor_cannot_contain_a_super_call_when_its_class_extends_null);
const classExtendsNull = classDeclarationExtendsNull(containingClassDecl);
const superCall = getSuperCallInConstructor(node);
if (superCall) {
if (classExtendsNull) {
error(superCall, Diagnostics.A_constructor_cannot_contain_a_super_call_when_its_class_extends_null);
}
// The first statement in the body of a constructor (excluding prologue directives) must be a super call
@@ -11873,6 +11906,7 @@ namespace ts {
if (superCallShouldBeFirst) {
const statements = (<Block>node.body).statements;
let superCallStatement: ExpressionStatement;
for (const statement of statements) {
if (statement.kind === SyntaxKind.ExpressionStatement && isSuperCallExpression((<ExpressionStatement>statement).expression)) {
superCallStatement = <ExpressionStatement>statement;
@@ -11887,7 +11921,7 @@ namespace ts {
}
}
}
else if (baseConstructorType !== nullType) {
else if (!classExtendsNull) {
error(node, Diagnostics.Constructors_for_derived_classes_must_contain_a_super_call);
}
}
+5 -5
View File
@@ -459,7 +459,6 @@ namespace ts {
IntrinsicElement = IntrinsicNamedElement | IntrinsicIndexedElement,
}
/* @internal */
export const enum RelationComparisonResult {
Succeeded = 1, // Should be truthy
@@ -2068,10 +2067,9 @@ namespace ts {
LoopWithCapturedBlockScopedBinding = 0x00010000, // Loop that contains block scoped variable captured in closure
CapturedBlockScopedBinding = 0x00020000, // Block-scoped binding that is captured in some function
BlockScopedBindingInLoop = 0x00040000, // Block-scoped binding with declaration nested inside iteration statement
HasSeenSuperCall = 0x00080000, // Set during the binding when encounter 'super'
ClassWithBodyScopedClassBinding = 0x00100000, // Decorated class that contains a binding to itself inside of the class body.
BodyScopedClassBinding = 0x00200000, // Binding to a decorated class inside of the class's body.
NeedsLoopOutParameter = 0x00400000, // Block scoped binding whose value should be explicitly copied outside of the converted loop
ClassWithBodyScopedClassBinding = 0x0080000, // Decorated class that contains a binding to itself inside of the class body.
BodyScopedClassBinding = 0x00100000, // Binding to a decorated class inside of the class's body.
NeedsLoopOutParameter = 0x00200000, // Block scoped binding whose value should be explicitly copied outside of the converted loop
}
/* @internal */
@@ -2090,6 +2088,8 @@ namespace ts {
importOnRightSide?: Symbol; // for import declarations - import that appear on the right side
jsxFlags?: JsxFlags; // flags for knowning what kind of element/attributes we're dealing with
resolvedJsxType?: Type; // resolved element attributes type of a JSX openinglike element
hasSuperCall?: boolean; // recorded result when we try to find super-call. We only try to find one if this flag is undefined, indicating that we haven't made an attempt.
superCall?: ExpressionStatement; // Cached first super-call found in the constructor. Used in checking whether super is called before this-accessing
}
export const enum TypeFlags {
@@ -1,17 +1,14 @@
tests/cases/compiler/classExtendsNull.ts(2,5): error TS17005: A constructor cannot contain a 'super' call when its class extends 'null'
tests/cases/compiler/classExtendsNull.ts(3,9): error TS17005: A constructor cannot contain a 'super' call when its class extends 'null'
==== tests/cases/compiler/classExtendsNull.ts (1 errors) ====
class C extends null {
constructor() {
~~~~~~~~~~~~~~~
super();
~~~~~~~~~~~~~~~~
return Object.create(null);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}
~~~~~
~~~~~~~
!!! error TS17005: A constructor cannot contain a 'super' call when its class extends 'null'
return Object.create(null);
}
}
class D extends null {
@@ -0,0 +1,40 @@
//// [superCallBeforeThisAccessing1.ts]
declare var Factory: any
class Base {
constructor(c) { }
}
class D extends Base {
private _t;
constructor() {
super(i);
var s = {
t: this._t
}
var i = Factory.create(s);
}
}
//// [superCallBeforeThisAccessing1.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 Base = (function () {
function Base(c) {
}
return Base;
}());
var D = (function (_super) {
__extends(D, _super);
function D() {
_super.call(this, i);
var s = {
t: this._t
};
var i = Factory.create(s);
}
return D;
}(Base));
@@ -0,0 +1,38 @@
=== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing1.ts ===
declare var Factory: any
>Factory : Symbol(Factory, Decl(superCallBeforeThisAccessing1.ts, 0, 11))
class Base {
>Base : Symbol(Base, Decl(superCallBeforeThisAccessing1.ts, 0, 24))
constructor(c) { }
>c : Symbol(c, Decl(superCallBeforeThisAccessing1.ts, 3, 16))
}
class D extends Base {
>D : Symbol(D, Decl(superCallBeforeThisAccessing1.ts, 4, 1))
>Base : Symbol(Base, Decl(superCallBeforeThisAccessing1.ts, 0, 24))
private _t;
>_t : Symbol(_t, Decl(superCallBeforeThisAccessing1.ts, 5, 22))
constructor() {
super(i);
>super : Symbol(Base, Decl(superCallBeforeThisAccessing1.ts, 0, 24))
>i : Symbol(i, Decl(superCallBeforeThisAccessing1.ts, 12, 11))
var s = {
>s : Symbol(s, Decl(superCallBeforeThisAccessing1.ts, 9, 11))
t: this._t
>t : Symbol(t, Decl(superCallBeforeThisAccessing1.ts, 9, 17))
>this._t : Symbol(_t, Decl(superCallBeforeThisAccessing1.ts, 5, 22))
>this : Symbol(D, Decl(superCallBeforeThisAccessing1.ts, 4, 1))
>_t : Symbol(_t, Decl(superCallBeforeThisAccessing1.ts, 5, 22))
}
var i = Factory.create(s);
>i : Symbol(i, Decl(superCallBeforeThisAccessing1.ts, 12, 11))
>Factory : Symbol(Factory, Decl(superCallBeforeThisAccessing1.ts, 0, 11))
>s : Symbol(s, Decl(superCallBeforeThisAccessing1.ts, 9, 11))
}
}
@@ -0,0 +1,43 @@
=== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing1.ts ===
declare var Factory: any
>Factory : any
class Base {
>Base : Base
constructor(c) { }
>c : any
}
class D extends Base {
>D : D
>Base : Base
private _t;
>_t : any
constructor() {
super(i);
>super(i) : void
>super : typeof Base
>i : any
var s = {
>s : { t: any; }
>{ t: this._t } : { t: any; }
t: this._t
>t : any
>this._t : any
>this : this
>_t : any
}
var i = Factory.create(s);
>i : any
>Factory.create(s) : any
>Factory.create : any
>Factory : any
>create : any
>s : { t: any; }
}
}
@@ -0,0 +1,31 @@
//// [superCallBeforeThisAccessing2.ts]
class Base {
constructor(c) { }
}
class D extends Base {
private _t;
constructor() {
super(() => { this._t }); // no error. only check when this is directly accessing in constructor
}
}
//// [superCallBeforeThisAccessing2.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 Base = (function () {
function Base(c) {
}
return Base;
}());
var D = (function (_super) {
__extends(D, _super);
function D() {
var _this = this;
_super.call(this, function () { _this._t; }); // no error. only check when this is directly accessing in constructor
}
return D;
}(Base));
@@ -0,0 +1,23 @@
=== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing2.ts ===
class Base {
>Base : Symbol(Base, Decl(superCallBeforeThisAccessing2.ts, 0, 0))
constructor(c) { }
>c : Symbol(c, Decl(superCallBeforeThisAccessing2.ts, 1, 16))
}
class D extends Base {
>D : Symbol(D, Decl(superCallBeforeThisAccessing2.ts, 2, 1))
>Base : Symbol(Base, Decl(superCallBeforeThisAccessing2.ts, 0, 0))
private _t;
>_t : Symbol(_t, Decl(superCallBeforeThisAccessing2.ts, 3, 22))
constructor() {
super(() => { this._t }); // no error. only check when this is directly accessing in constructor
>super : Symbol(Base, Decl(superCallBeforeThisAccessing2.ts, 0, 0))
>this._t : Symbol(_t, Decl(superCallBeforeThisAccessing2.ts, 3, 22))
>this : Symbol(D, Decl(superCallBeforeThisAccessing2.ts, 2, 1))
>_t : Symbol(_t, Decl(superCallBeforeThisAccessing2.ts, 3, 22))
}
}
@@ -0,0 +1,25 @@
=== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing2.ts ===
class Base {
>Base : Base
constructor(c) { }
>c : any
}
class D extends Base {
>D : D
>Base : Base
private _t;
>_t : any
constructor() {
super(() => { this._t }); // no error. only check when this is directly accessing in constructor
>super(() => { this._t }) : void
>super : typeof Base
>() => { this._t } : () => void
>this._t : any
>this : this
>_t : any
}
}
@@ -0,0 +1,19 @@
tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing3.ts(9,9): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class.
==== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing3.ts (1 errors) ====
class Base {
constructor(c) { }
}
class D extends Base {
private _t;
constructor() {
let x = () => { this._t };
x(); // no error; we only check super is called before this when the container is a constructor
this._t; // error
~~~~
!!! error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class.
super(undefined);
}
}
@@ -0,0 +1,37 @@
//// [superCallBeforeThisAccessing3.ts]
class Base {
constructor(c) { }
}
class D extends Base {
private _t;
constructor() {
let x = () => { this._t };
x(); // no error; we only check super is called before this when the container is a constructor
this._t; // error
super(undefined);
}
}
//// [superCallBeforeThisAccessing3.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 Base = (function () {
function Base(c) {
}
return Base;
}());
var D = (function (_super) {
__extends(D, _super);
function D() {
var _this = this;
var x = function () { _this._t; };
x(); // no error; we only check super is called before this when the container is a constructor
this._t; // error
_super.call(this, undefined);
}
return D;
}(Base));
@@ -0,0 +1,24 @@
tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing4.ts(5,9): error TS17005: A constructor cannot contain a 'super' call when its class extends 'null'
tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing4.ts(12,9): error TS17005: A constructor cannot contain a 'super' call when its class extends 'null'
==== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing4.ts (2 errors) ====
class D extends null {
private _t;
constructor() {
this._t;
super();
~~~~~~~
!!! error TS17005: A constructor cannot contain a 'super' call when its class extends 'null'
}
}
class E extends null {
private _t;
constructor() {
super();
~~~~~~~
!!! error TS17005: A constructor cannot contain a 'super' call when its class extends 'null'
this._t;
}
}
@@ -0,0 +1,39 @@
//// [superCallBeforeThisAccessing4.ts]
class D extends null {
private _t;
constructor() {
this._t;
super();
}
}
class E extends null {
private _t;
constructor() {
super();
this._t;
}
}
//// [superCallBeforeThisAccessing4.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 D = (function (_super) {
__extends(D, _super);
function D() {
this._t;
_super.call(this);
}
return D;
}(null));
var E = (function (_super) {
__extends(E, _super);
function E() {
_super.call(this);
this._t;
}
return E;
}(null));
@@ -0,0 +1,22 @@
//// [superCallBeforeThisAccessing5.ts]
class D extends null {
private _t;
constructor() {
this._t; // No error
}
}
//// [superCallBeforeThisAccessing5.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 D = (function (_super) {
__extends(D, _super);
function D() {
this._t; // No error
}
return D;
}(null));
@@ -0,0 +1,15 @@
=== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing5.ts ===
class D extends null {
>D : Symbol(D, Decl(superCallBeforeThisAccessing5.ts, 0, 0))
private _t;
>_t : Symbol(_t, Decl(superCallBeforeThisAccessing5.ts, 0, 22))
constructor() {
this._t; // No error
>this._t : Symbol(_t, Decl(superCallBeforeThisAccessing5.ts, 0, 22))
>this : Symbol(D, Decl(superCallBeforeThisAccessing5.ts, 0, 0))
>_t : Symbol(_t, Decl(superCallBeforeThisAccessing5.ts, 0, 22))
}
}
@@ -0,0 +1,16 @@
=== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing5.ts ===
class D extends null {
>D : D
>null : null
private _t;
>_t : any
constructor() {
this._t; // No error
>this._t : any
>this : this
>_t : any
}
}
@@ -0,0 +1,16 @@
tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing6.ts(7,15): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class.
==== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing6.ts (1 errors) ====
class Base {
constructor(c) { }
}
class D extends Base {
private _t;
constructor() {
super(this);
~~~~
!!! error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class.
}
}
@@ -0,0 +1,30 @@
//// [superCallBeforeThisAccessing6.ts]
class Base {
constructor(c) { }
}
class D extends Base {
private _t;
constructor() {
super(this);
}
}
//// [superCallBeforeThisAccessing6.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 Base = (function () {
function Base(c) {
}
return Base;
}());
var D = (function (_super) {
__extends(D, _super);
function D() {
_super.call(this, this);
}
return D;
}(Base));
@@ -0,0 +1,19 @@
tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing7.ts(8,16): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class.
==== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing7.ts (1 errors) ====
class Base {
constructor(c) { }
}
class D extends Base {
private _t;
constructor() {
let x = {
j: this._t,
~~~~
!!! error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class.
}
super(undefined);
}
}
@@ -0,0 +1,36 @@
//// [superCallBeforeThisAccessing7.ts]
class Base {
constructor(c) { }
}
class D extends Base {
private _t;
constructor() {
let x = {
j: this._t,
}
super(undefined);
}
}
//// [superCallBeforeThisAccessing7.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 Base = (function () {
function Base(c) {
}
return Base;
}());
var D = (function (_super) {
__extends(D, _super);
function D() {
var x = {
j: this._t
};
_super.call(this, undefined);
}
return D;
}(Base));
@@ -0,0 +1,36 @@
//// [superCallBeforeThisAccessing8.ts]
class Base {
constructor(c) { }
}
class D extends Base {
private _t;
constructor() {
let x = {
k: super(undefined),
j: this._t, // no error
}
}
}
//// [superCallBeforeThisAccessing8.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 Base = (function () {
function Base(c) {
}
return Base;
}());
var D = (function (_super) {
__extends(D, _super);
function D() {
var x = {
k: _super.call(this, undefined),
j: this._t
};
}
return D;
}(Base));
@@ -0,0 +1,32 @@
=== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing8.ts ===
class Base {
>Base : Symbol(Base, Decl(superCallBeforeThisAccessing8.ts, 0, 0))
constructor(c) { }
>c : Symbol(c, Decl(superCallBeforeThisAccessing8.ts, 1, 16))
}
class D extends Base {
>D : Symbol(D, Decl(superCallBeforeThisAccessing8.ts, 2, 1))
>Base : Symbol(Base, Decl(superCallBeforeThisAccessing8.ts, 0, 0))
private _t;
>_t : Symbol(_t, Decl(superCallBeforeThisAccessing8.ts, 3, 22))
constructor() {
let x = {
>x : Symbol(x, Decl(superCallBeforeThisAccessing8.ts, 6, 11))
k: super(undefined),
>k : Symbol(k, Decl(superCallBeforeThisAccessing8.ts, 6, 17))
>super : Symbol(Base, Decl(superCallBeforeThisAccessing8.ts, 0, 0))
>undefined : Symbol(undefined)
j: this._t, // no error
>j : Symbol(j, Decl(superCallBeforeThisAccessing8.ts, 7, 32))
>this._t : Symbol(_t, Decl(superCallBeforeThisAccessing8.ts, 3, 22))
>this : Symbol(D, Decl(superCallBeforeThisAccessing8.ts, 2, 1))
>_t : Symbol(_t, Decl(superCallBeforeThisAccessing8.ts, 3, 22))
}
}
}
@@ -0,0 +1,34 @@
=== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing8.ts ===
class Base {
>Base : Base
constructor(c) { }
>c : any
}
class D extends Base {
>D : D
>Base : Base
private _t;
>_t : any
constructor() {
let x = {
>x : { k: void; j: any; }
>{ k: super(undefined), j: this._t, // no error } : { k: void; j: any; }
k: super(undefined),
>k : void
>super(undefined) : void
>super : typeof Base
>undefined : undefined
j: this._t, // no error
>j : any
>this._t : any
>this : this
>_t : any
}
}
}
@@ -0,0 +1,15 @@
declare var Factory: any
class Base {
constructor(c) { }
}
class D extends Base {
private _t;
constructor() {
super(i);
var s = {
t: this._t
}
var i = Factory.create(s);
}
}
@@ -0,0 +1,9 @@
class Base {
constructor(c) { }
}
class D extends Base {
private _t;
constructor() {
super(() => { this._t }); // no error. only check when this is directly accessing in constructor
}
}
@@ -0,0 +1,12 @@
class Base {
constructor(c) { }
}
class D extends Base {
private _t;
constructor() {
let x = () => { this._t };
x(); // no error; we only check super is called before this when the container is a constructor
this._t; // error
super(undefined);
}
}
@@ -0,0 +1,15 @@
class D extends null {
private _t;
constructor() {
this._t;
super();
}
}
class E extends null {
private _t;
constructor() {
super();
this._t;
}
}
@@ -0,0 +1,6 @@
class D extends null {
private _t;
constructor() {
this._t; // No error
}
}
@@ -0,0 +1,9 @@
class Base {
constructor(c) { }
}
class D extends Base {
private _t;
constructor() {
super(this);
}
}
@@ -0,0 +1,12 @@
class Base {
constructor(c) { }
}
class D extends Base {
private _t;
constructor() {
let x = {
j: this._t,
}
super(undefined);
}
}
@@ -0,0 +1,12 @@
class Base {
constructor(c) { }
}
class D extends Base {
private _t;
constructor() {
let x = {
k: super(undefined),
j: this._t, // no error
}
}
}