mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #6860 from Microsoft/checksuperbeforethislexically
Check using "super" before "this" lexically
This commit is contained in:
+68
-34
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user