diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 551f428ca9ac2..a0c4d2143f681 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6577,6 +6577,21 @@ namespace ts { let container = getThisContainer(node, /* includeArrowFunctions */ true); let needToCaptureLexicalThis = false; + + if (container.kind === SyntaxKind.Constructor) { + // Keep track of whether we have seen "super" before encounter "this" so that + // we can report appropriate error later in checkConstructorDeclaration + // We have to do the check here to make sure we won't give false error when + // "this" is used in arrow functions + // For example: + // constructor() { + // (()=>this); // No Error + // super(); + // } + let nodeLinks = getNodeLinks(container); + nodeLinks.flags |= NodeCheckFlags.HasSeenThisCall; + } + // Now skip arrow functions to get the "real" owner of 'this'. if (container.kind === SyntaxKind.ArrowFunction) { container = getThisContainer(container, /* includeArrowFunctions */ false); @@ -9285,6 +9300,14 @@ namespace ts { let signature = getResolvedSignature(node); if (node.expression.kind === SyntaxKind.SuperKeyword) { + let containgFunction = getContainingFunction(node.expression); + + if (containgFunction && containgFunction.kind === SyntaxKind.Constructor) { + let nodeLinks = getNodeLinks(containgFunction); + if (!(nodeLinks.flags & NodeCheckFlags.HasSeenThisCall)) { + nodeLinks.flags |= NodeCheckFlags.HasSeenSuperBeforeThis; + } + } return voidType; } if (node.kind === SyntaxKind.NewExpression) { @@ -10794,8 +10817,25 @@ namespace ts { let containingClassSymbol = getSymbolOfNode(containingClassDecl); let containingClassInstanceType = getDeclaredTypeOfSymbol(containingClassSymbol); let baseConstructorType = getBaseConstructorTypeOfClass(containingClassInstanceType); + let statements = (node.body).statements; + let superCallStatement: ExpressionStatement; + let isSuperCallFirstStatment: boolean; + + for (let statement of statements) { + if (statement.kind === SyntaxKind.ExpressionStatement && isSuperCallExpression((statement).expression)) { + superCallStatement = statement; + if (isSuperCallFirstStatment === undefined) { + isSuperCallFirstStatment = true; + } + } + else if (isSuperCallFirstStatment === undefined && !isPrologueDirective(statement)) { + isSuperCallFirstStatment = false; + } + } - if (containsSuperCall(node.body)) { + // The main different between looping through each statement in constructor and calling containsSuperCall is that, + // containsSuperCall will consider "super" inside computed-property for inner class declaration + if (superCallStatement || containsSuperCall(node.body)) { if (baseConstructorType === nullType) { error(node, Diagnostics.A_constructor_cannot_contain_a_super_call_when_its_class_extends_null); } @@ -10812,25 +10852,18 @@ namespace ts { // Skip past any prologue directives to find the first statement // to ensure that it was a super call. if (superCallShouldBeFirst) { - let statements = (node.body).statements; - let superCallStatement: ExpressionStatement; - for (let statement of statements) { - if (statement.kind === SyntaxKind.ExpressionStatement && isSuperCallExpression((statement).expression)) { - superCallStatement = statement; - break; - } - if (!isPrologueDirective(statement)) { - break; - } - } - if (!superCallStatement) { - error(node, Diagnostics.A_super_call_must_be_the_first_statement_in_the_constructor_when_a_class_contains_initialized_properties_or_has_parameter_properties); + if (!isSuperCallFirstStatment) { + error(superCallStatement, Diagnostics.A_super_call_must_be_the_first_statement_in_the_constructor_when_a_class_contains_initialized_properties_or_has_parameter_properties); } else { // In such a required super call, it is a compile-time error for argument expressions to reference this. markThisReferencesAsErrors(superCallStatement.expression); } } + else if (!(getNodeCheckFlags(node) & NodeCheckFlags.HasSeenSuperBeforeThis)) { + // In ES6, super inside constructor of class-declaration has to precede "this" accessing + error(superCallStatement, Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class); + } } else if (baseConstructorType !== nullType) { error(node, Diagnostics.Constructors_for_derived_classes_must_contain_a_super_call); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index f6656edb250dd..f301da2fdbb0f 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2469,5 +2469,9 @@ "A constructor cannot contain a 'super' call when its class extends 'null'": { "category": "Error", "code": 17005 + }, + "'super' must be called before accessing 'this' in the constructor of a derived class.": { + "category": "Error", + "code": 17006 } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 773083d49b64f..10285844145ca 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1746,6 +1746,8 @@ namespace ts { EnumValuesComputed = 0x00002000, BlockScopedBindingInLoop = 0x00004000, LexicalModuleMergesWithClass= 0x00008000, // Instantiated lexical module declaration is merged with a previous class declaration. + HasSeenSuperBeforeThis = 0x00010000, // Set during the binding if the 'super' is used before 'this' in constructor function + HasSeenThisCall = 0x00020000, // Set during the binding when encounter 'this' } /* @internal */ @@ -2298,7 +2300,7 @@ namespace ts { export interface ModuleResolutionHost { fileExists(fileName: string): boolean; // readFile function is used to read arbitrary text files on disk, i.e. when resolution procedure needs the content of 'package.json' - // to determine location of bundled typings for node module + // to determine location of bundled typings for node module readFile(fileName: string): string; } @@ -2318,6 +2320,8 @@ namespace ts { failedLookupLocations: string[]; } + export type ModuleNameResolver = (moduleName: string, containingFile: string, options: CompilerOptions, host: ModuleResolutionHost) => ResolvedModule; + export interface CompilerHost extends ModuleResolutionHost { getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile; getCancellationToken?(): CancellationToken; @@ -2329,11 +2333,11 @@ namespace ts { getNewLine(): string; /* - * CompilerHost must either implement resolveModuleNames (in case if it wants to be completely in charge of - * module name resolution) or provide implementation for methods from ModuleResolutionHost (in this case compiler + * CompilerHost must either implement resolveModuleNames (in case if it wants to be completely in charge of + * module name resolution) or provide implementation for methods from ModuleResolutionHost (in this case compiler * will appply built-in module resolution logic and use members of ModuleResolutionHost to ask host specific questions). - * If resolveModuleNames is implemented then implementation for members from ModuleResolutionHost can be just - * 'throw new Error("NotImplemented")' + * If resolveModuleNames is implemented then implementation for members from ModuleResolutionHost can be just + * 'throw new Error("NotImplemented")' */ resolveModuleNames?(moduleNames: string[], containingFile: string): ResolvedModule[]; } diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing1.js b/tests/baselines/reference/checkSuperCallBeforeThisAccessing1.js new file mode 100644 index 0000000000000..ec6e6e39ee8aa --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing1.js @@ -0,0 +1,33 @@ +//// [checkSuperCallBeforeThisAccessing1.ts] +class Based { } +class Derived extends Based { + public x: number; + constructor() { + super(); + this; + this.x = 10; + var that = this; + } +} + +//// [checkSuperCallBeforeThisAccessing1.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 Based = (function () { + function Based() { + } + return Based; +})(); +var Derived = (function (_super) { + __extends(Derived, _super); + function Derived() { + _super.call(this); + this; + this.x = 10; + var that = this; + } + return Derived; +})(Based); diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing1.symbols b/tests/baselines/reference/checkSuperCallBeforeThisAccessing1.symbols new file mode 100644 index 0000000000000..008d1156b564d --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing1.symbols @@ -0,0 +1,28 @@ +=== tests/cases/compiler/checkSuperCallBeforeThisAccessing1.ts === +class Based { } +>Based : Symbol(Based, Decl(checkSuperCallBeforeThisAccessing1.ts, 0, 0)) + +class Derived extends Based { +>Derived : Symbol(Derived, Decl(checkSuperCallBeforeThisAccessing1.ts, 0, 15)) +>Based : Symbol(Based, Decl(checkSuperCallBeforeThisAccessing1.ts, 0, 0)) + + public x: number; +>x : Symbol(x, Decl(checkSuperCallBeforeThisAccessing1.ts, 1, 29)) + + constructor() { + super(); +>super : Symbol(Based, Decl(checkSuperCallBeforeThisAccessing1.ts, 0, 0)) + + this; +>this : Symbol(Derived, Decl(checkSuperCallBeforeThisAccessing1.ts, 0, 15)) + + this.x = 10; +>this.x : Symbol(x, Decl(checkSuperCallBeforeThisAccessing1.ts, 1, 29)) +>this : Symbol(Derived, Decl(checkSuperCallBeforeThisAccessing1.ts, 0, 15)) +>x : Symbol(x, Decl(checkSuperCallBeforeThisAccessing1.ts, 1, 29)) + + var that = this; +>that : Symbol(that, Decl(checkSuperCallBeforeThisAccessing1.ts, 7, 11)) +>this : Symbol(Derived, Decl(checkSuperCallBeforeThisAccessing1.ts, 0, 15)) + } +} diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing1.types b/tests/baselines/reference/checkSuperCallBeforeThisAccessing1.types new file mode 100644 index 0000000000000..d734b0c6ad091 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing1.types @@ -0,0 +1,31 @@ +=== tests/cases/compiler/checkSuperCallBeforeThisAccessing1.ts === +class Based { } +>Based : Based + +class Derived extends Based { +>Derived : Derived +>Based : Based + + public x: number; +>x : number + + constructor() { + super(); +>super() : void +>super : typeof Based + + this; +>this : this + + this.x = 10; +>this.x = 10 : number +>this.x : number +>this : this +>x : number +>10 : number + + var that = this; +>that : this +>this : this + } +} diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing2.errors.txt b/tests/baselines/reference/checkSuperCallBeforeThisAccessing2.errors.txt new file mode 100644 index 0000000000000..6fdb2e3e3943f --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing2.errors.txt @@ -0,0 +1,16 @@ +tests/cases/compiler/checkSuperCallBeforeThisAccessing2.ts(6,9): error TS17006: 'super' must be called before accessing 'this' in the constructor of a derived class. + + +==== tests/cases/compiler/checkSuperCallBeforeThisAccessing2.ts (1 errors) ==== + class Based { } + class Derived extends Based { + public x: number; + constructor() { + this.x = 100; + super(); + ~~~~~~~~ +!!! error TS17006: 'super' must be called before accessing 'this' in the constructor of a derived class. + this.x = 10; + var that = this; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing2.js b/tests/baselines/reference/checkSuperCallBeforeThisAccessing2.js new file mode 100644 index 0000000000000..eb58afd820b80 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing2.js @@ -0,0 +1,33 @@ +//// [checkSuperCallBeforeThisAccessing2.ts] +class Based { } +class Derived extends Based { + public x: number; + constructor() { + this.x = 100; + super(); + this.x = 10; + var that = this; + } +} + +//// [checkSuperCallBeforeThisAccessing2.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 Based = (function () { + function Based() { + } + return Based; +})(); +var Derived = (function (_super) { + __extends(Derived, _super); + function Derived() { + this.x = 100; + _super.call(this); + this.x = 10; + var that = this; + } + return Derived; +})(Based); diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing3.js b/tests/baselines/reference/checkSuperCallBeforeThisAccessing3.js new file mode 100644 index 0000000000000..2c5652cf95fa7 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing3.js @@ -0,0 +1,43 @@ +//// [checkSuperCallBeforeThisAccessing3.ts] +class Based { } +class Derived extends Based { + public x: number; + constructor() { + class innver { + public y: boolean; + constructor() { + this.y = true; + } + } + super(); + this.x = 10; + var that = this; + } +} + +//// [checkSuperCallBeforeThisAccessing3.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 Based = (function () { + function Based() { + } + return Based; +})(); +var Derived = (function (_super) { + __extends(Derived, _super); + function Derived() { + var innver = (function () { + function innver() { + this.y = true; + } + return innver; + })(); + _super.call(this); + this.x = 10; + var that = this; + } + return Derived; +})(Based); diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing3.symbols b/tests/baselines/reference/checkSuperCallBeforeThisAccessing3.symbols new file mode 100644 index 0000000000000..8dd68fc3b7494 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing3.symbols @@ -0,0 +1,38 @@ +=== tests/cases/compiler/checkSuperCallBeforeThisAccessing3.ts === +class Based { } +>Based : Symbol(Based, Decl(checkSuperCallBeforeThisAccessing3.ts, 0, 0)) + +class Derived extends Based { +>Derived : Symbol(Derived, Decl(checkSuperCallBeforeThisAccessing3.ts, 0, 15)) +>Based : Symbol(Based, Decl(checkSuperCallBeforeThisAccessing3.ts, 0, 0)) + + public x: number; +>x : Symbol(x, Decl(checkSuperCallBeforeThisAccessing3.ts, 1, 29)) + + constructor() { + class innver { +>innver : Symbol(innver, Decl(checkSuperCallBeforeThisAccessing3.ts, 3, 19)) + + public y: boolean; +>y : Symbol(y, Decl(checkSuperCallBeforeThisAccessing3.ts, 4, 22)) + + constructor() { + this.y = true; +>this.y : Symbol(y, Decl(checkSuperCallBeforeThisAccessing3.ts, 4, 22)) +>this : Symbol(innver, Decl(checkSuperCallBeforeThisAccessing3.ts, 3, 19)) +>y : Symbol(y, Decl(checkSuperCallBeforeThisAccessing3.ts, 4, 22)) + } + } + super(); +>super : Symbol(Based, Decl(checkSuperCallBeforeThisAccessing3.ts, 0, 0)) + + this.x = 10; +>this.x : Symbol(x, Decl(checkSuperCallBeforeThisAccessing3.ts, 1, 29)) +>this : Symbol(Derived, Decl(checkSuperCallBeforeThisAccessing3.ts, 0, 15)) +>x : Symbol(x, Decl(checkSuperCallBeforeThisAccessing3.ts, 1, 29)) + + var that = this; +>that : Symbol(that, Decl(checkSuperCallBeforeThisAccessing3.ts, 12, 11)) +>this : Symbol(Derived, Decl(checkSuperCallBeforeThisAccessing3.ts, 0, 15)) + } +} diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing3.types b/tests/baselines/reference/checkSuperCallBeforeThisAccessing3.types new file mode 100644 index 0000000000000..c4e9e15ed8ef2 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing3.types @@ -0,0 +1,43 @@ +=== tests/cases/compiler/checkSuperCallBeforeThisAccessing3.ts === +class Based { } +>Based : Based + +class Derived extends Based { +>Derived : Derived +>Based : Based + + public x: number; +>x : number + + constructor() { + class innver { +>innver : innver + + public y: boolean; +>y : boolean + + constructor() { + this.y = true; +>this.y = true : boolean +>this.y : boolean +>this : this +>y : boolean +>true : boolean + } + } + super(); +>super() : void +>super : typeof Based + + this.x = 10; +>this.x = 10 : number +>this.x : number +>this : this +>x : number +>10 : number + + var that = this; +>that : this +>this : this + } +} diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing4.js b/tests/baselines/reference/checkSuperCallBeforeThisAccessing4.js new file mode 100644 index 0000000000000..eacec00c43878 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing4.js @@ -0,0 +1,52 @@ +//// [checkSuperCallBeforeThisAccessing4.ts] +class Based { } +class Derived extends Based { + public x: number; + constructor() { + (() => { + this; // No error + }); + () => { + this; // No error + }; + (() => { + this; // No error + })(); + super(); + super(); + this.x = 10; + var that = this; + } +} + +//// [checkSuperCallBeforeThisAccessing4.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 Based = (function () { + function Based() { + } + return Based; +})(); +var Derived = (function (_super) { + __extends(Derived, _super); + function Derived() { + var _this = this; + (function () { + _this; // No error + }); + (function () { + _this; // No error + }); + (function () { + _this; // No error + })(); + _super.call(this); + _super.call(this); + this.x = 10; + var that = this; + } + return Derived; +})(Based); diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing4.symbols b/tests/baselines/reference/checkSuperCallBeforeThisAccessing4.symbols new file mode 100644 index 0000000000000..7101280358dbe --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing4.symbols @@ -0,0 +1,43 @@ +=== tests/cases/compiler/checkSuperCallBeforeThisAccessing4.ts === +class Based { } +>Based : Symbol(Based, Decl(checkSuperCallBeforeThisAccessing4.ts, 0, 0)) + +class Derived extends Based { +>Derived : Symbol(Derived, Decl(checkSuperCallBeforeThisAccessing4.ts, 0, 15)) +>Based : Symbol(Based, Decl(checkSuperCallBeforeThisAccessing4.ts, 0, 0)) + + public x: number; +>x : Symbol(x, Decl(checkSuperCallBeforeThisAccessing4.ts, 1, 29)) + + constructor() { + (() => { + this; // No error +>this : Symbol(Derived, Decl(checkSuperCallBeforeThisAccessing4.ts, 0, 15)) + + }); + () => { + this; // No error +>this : Symbol(Derived, Decl(checkSuperCallBeforeThisAccessing4.ts, 0, 15)) + + }; + (() => { + this; // No error +>this : Symbol(Derived, Decl(checkSuperCallBeforeThisAccessing4.ts, 0, 15)) + + })(); + super(); +>super : Symbol(Based, Decl(checkSuperCallBeforeThisAccessing4.ts, 0, 0)) + + super(); +>super : Symbol(Based, Decl(checkSuperCallBeforeThisAccessing4.ts, 0, 0)) + + this.x = 10; +>this.x : Symbol(x, Decl(checkSuperCallBeforeThisAccessing4.ts, 1, 29)) +>this : Symbol(Derived, Decl(checkSuperCallBeforeThisAccessing4.ts, 0, 15)) +>x : Symbol(x, Decl(checkSuperCallBeforeThisAccessing4.ts, 1, 29)) + + var that = this; +>that : Symbol(that, Decl(checkSuperCallBeforeThisAccessing4.ts, 16, 11)) +>this : Symbol(Derived, Decl(checkSuperCallBeforeThisAccessing4.ts, 0, 15)) + } +} diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing4.types b/tests/baselines/reference/checkSuperCallBeforeThisAccessing4.types new file mode 100644 index 0000000000000..f42a0ac8563ba --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing4.types @@ -0,0 +1,56 @@ +=== tests/cases/compiler/checkSuperCallBeforeThisAccessing4.ts === +class Based { } +>Based : Based + +class Derived extends Based { +>Derived : Derived +>Based : Based + + public x: number; +>x : number + + constructor() { + (() => { +>(() => { this; // No error }) : () => void +>() => { this; // No error } : () => void + + this; // No error +>this : this + + }); + () => { +>() => { this; // No error } : () => void + + this; // No error +>this : this + + }; + (() => { +>(() => { this; // No error })() : void +>(() => { this; // No error }) : () => void +>() => { this; // No error } : () => void + + this; // No error +>this : this + + })(); + super(); +>super() : void +>super : typeof Based + + super(); +>super() : void +>super : typeof Based + + this.x = 10; +>this.x = 10 : number +>this.x : number +>this : this +>x : number +>10 : number + + var that = this; +>that : this +>this : this + } +} diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing5.errors.txt b/tests/baselines/reference/checkSuperCallBeforeThisAccessing5.errors.txt new file mode 100644 index 0000000000000..edd7745a03cb4 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing5.errors.txt @@ -0,0 +1,13 @@ +tests/cases/compiler/checkSuperCallBeforeThisAccessing5.ts(5,9): error TS17006: 'super' must be called before accessing 'this' in the constructor of a derived class. + + +==== tests/cases/compiler/checkSuperCallBeforeThisAccessing5.ts (1 errors) ==== + class Based { constructor(...arg) { } } + class Derived extends Based { + public x: number; + constructor() { + super(this.x); + ~~~~~~~~~~~~~~ +!!! error TS17006: 'super' must be called before accessing 'this' in the constructor of a derived class. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing5.js b/tests/baselines/reference/checkSuperCallBeforeThisAccessing5.js new file mode 100644 index 0000000000000..489c7200050e8 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing5.js @@ -0,0 +1,31 @@ +//// [checkSuperCallBeforeThisAccessing5.ts] +class Based { constructor(...arg) { } } +class Derived extends Based { + public x: number; + constructor() { + super(this.x); + } +} + +//// [checkSuperCallBeforeThisAccessing5.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 Based = (function () { + function Based() { + var arg = []; + for (var _i = 0; _i < arguments.length; _i++) { + arg[_i - 0] = arguments[_i]; + } + } + return Based; +})(); +var Derived = (function (_super) { + __extends(Derived, _super); + function Derived() { + _super.call(this, this.x); + } + return Derived; +})(Based); diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing6.js b/tests/baselines/reference/checkSuperCallBeforeThisAccessing6.js new file mode 100644 index 0000000000000..6ad9773bc5f39 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing6.js @@ -0,0 +1,36 @@ +//// [checkSuperCallBeforeThisAccessing6.ts] +class Base { + constructor(...arg) { + } +} +class Super extends Base { + constructor() { + (() => this); // No Error + super(); + } +} + +//// [checkSuperCallBeforeThisAccessing6.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() { + var arg = []; + for (var _i = 0; _i < arguments.length; _i++) { + arg[_i - 0] = arguments[_i]; + } + } + return Base; +})(); +var Super = (function (_super) { + __extends(Super, _super); + function Super() { + var _this = this; + (function () { return _this; }); // No Error + _super.call(this); + } + return Super; +})(Base); diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing6.symbols b/tests/baselines/reference/checkSuperCallBeforeThisAccessing6.symbols new file mode 100644 index 0000000000000..84bac5775ec25 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing6.symbols @@ -0,0 +1,20 @@ +=== tests/cases/compiler/checkSuperCallBeforeThisAccessing6.ts === +class Base { +>Base : Symbol(Base, Decl(checkSuperCallBeforeThisAccessing6.ts, 0, 0)) + + constructor(...arg) { +>arg : Symbol(arg, Decl(checkSuperCallBeforeThisAccessing6.ts, 1, 16)) + } +} +class Super extends Base { +>Super : Symbol(Super, Decl(checkSuperCallBeforeThisAccessing6.ts, 3, 1)) +>Base : Symbol(Base, Decl(checkSuperCallBeforeThisAccessing6.ts, 0, 0)) + + constructor() { + (() => this); // No Error +>this : Symbol(Super, Decl(checkSuperCallBeforeThisAccessing6.ts, 3, 1)) + + super(); +>super : Symbol(Base, Decl(checkSuperCallBeforeThisAccessing6.ts, 0, 0)) + } +} diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing6.types b/tests/baselines/reference/checkSuperCallBeforeThisAccessing6.types new file mode 100644 index 0000000000000..826dab0c40055 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing6.types @@ -0,0 +1,23 @@ +=== tests/cases/compiler/checkSuperCallBeforeThisAccessing6.ts === +class Base { +>Base : Base + + constructor(...arg) { +>arg : any[] + } +} +class Super extends Base { +>Super : Super +>Base : Base + + constructor() { + (() => this); // No Error +>(() => this) : () => this +>() => this : () => this +>this : this + + super(); +>super() : void +>super : typeof Base + } +} diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing7.js b/tests/baselines/reference/checkSuperCallBeforeThisAccessing7.js new file mode 100644 index 0000000000000..eafc662085ff9 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing7.js @@ -0,0 +1,30 @@ +//// [checkSuperCallBeforeThisAccessing7.ts] +class Base { + constructor(func: ()=>Base) { + } +} +class Super extends Base { + constructor() { + super((() => this)); // No error + } +} + +//// [checkSuperCallBeforeThisAccessing7.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(func) { + } + return Base; +})(); +var Super = (function (_super) { + __extends(Super, _super); + function Super() { + var _this = this; + _super.call(this, (function () { return _this; })); // No error + } + return Super; +})(Base); diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing7.symbols b/tests/baselines/reference/checkSuperCallBeforeThisAccessing7.symbols new file mode 100644 index 0000000000000..3611429d2b272 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing7.symbols @@ -0,0 +1,19 @@ +=== tests/cases/compiler/checkSuperCallBeforeThisAccessing7.ts === +class Base { +>Base : Symbol(Base, Decl(checkSuperCallBeforeThisAccessing7.ts, 0, 0)) + + constructor(func: ()=>Base) { +>func : Symbol(func, Decl(checkSuperCallBeforeThisAccessing7.ts, 1, 16)) +>Base : Symbol(Base, Decl(checkSuperCallBeforeThisAccessing7.ts, 0, 0)) + } +} +class Super extends Base { +>Super : Symbol(Super, Decl(checkSuperCallBeforeThisAccessing7.ts, 3, 1)) +>Base : Symbol(Base, Decl(checkSuperCallBeforeThisAccessing7.ts, 0, 0)) + + constructor() { + super((() => this)); // No error +>super : Symbol(Base, Decl(checkSuperCallBeforeThisAccessing7.ts, 0, 0)) +>this : Symbol(Super, Decl(checkSuperCallBeforeThisAccessing7.ts, 3, 1)) + } +} diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing7.types b/tests/baselines/reference/checkSuperCallBeforeThisAccessing7.types new file mode 100644 index 0000000000000..11d2ab26d20a6 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing7.types @@ -0,0 +1,22 @@ +=== tests/cases/compiler/checkSuperCallBeforeThisAccessing7.ts === +class Base { +>Base : Base + + constructor(func: ()=>Base) { +>func : () => Base +>Base : Base + } +} +class Super extends Base { +>Super : Super +>Base : Base + + constructor() { + super((() => this)); // No error +>super((() => this)) : void +>super : typeof Base +>(() => this) : () => this +>() => this : () => this +>this : this + } +} diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing8.errors.txt b/tests/baselines/reference/checkSuperCallBeforeThisAccessing8.errors.txt new file mode 100644 index 0000000000000..39db87d41a1d8 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing8.errors.txt @@ -0,0 +1,16 @@ +tests/cases/compiler/checkSuperCallBeforeThisAccessing8.ts(8,9): error TS17006: 'super' must be called before accessing 'this' in the constructor of a derived class. + + +==== tests/cases/compiler/checkSuperCallBeforeThisAccessing8.ts (1 errors) ==== + class Base { + constructor(...arg) { + } + } + class Super extends Base { + constructor() { + var that = this; + super(); + ~~~~~~~~ +!!! error TS17006: 'super' must be called before accessing 'this' in the constructor of a derived class. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing8.js b/tests/baselines/reference/checkSuperCallBeforeThisAccessing8.js new file mode 100644 index 0000000000000..4675d328b38a2 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing8.js @@ -0,0 +1,35 @@ +//// [checkSuperCallBeforeThisAccessing8.ts] +class Base { + constructor(...arg) { + } +} +class Super extends Base { + constructor() { + var that = this; + super(); + } +} + +//// [checkSuperCallBeforeThisAccessing8.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() { + var arg = []; + for (var _i = 0; _i < arguments.length; _i++) { + arg[_i - 0] = arguments[_i]; + } + } + return Base; +})(); +var Super = (function (_super) { + __extends(Super, _super); + function Super() { + var that = this; + _super.call(this); + } + return Super; +})(Base); diff --git a/tests/baselines/reference/classUpdateTests.errors.txt b/tests/baselines/reference/classUpdateTests.errors.txt index 59e9bc9ced182..559657564101a 100644 --- a/tests/baselines/reference/classUpdateTests.errors.txt +++ b/tests/baselines/reference/classUpdateTests.errors.txt @@ -1,11 +1,11 @@ tests/cases/compiler/classUpdateTests.ts(34,2): error TS2377: Constructors for derived classes must contain a 'super' call. tests/cases/compiler/classUpdateTests.ts(43,18): error TS2335: 'super' can only be referenced in a derived class. -tests/cases/compiler/classUpdateTests.ts(57,2): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. +tests/cases/compiler/classUpdateTests.ts(59,3): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. tests/cases/compiler/classUpdateTests.ts(63,7): error TS2415: Class 'L' incorrectly extends base class 'G'. Property 'p1' is private in type 'L' but not in type 'G'. tests/cases/compiler/classUpdateTests.ts(69,7): error TS2415: Class 'M' incorrectly extends base class 'G'. Property 'p1' is private in type 'M' but not in type 'G'. -tests/cases/compiler/classUpdateTests.ts(70,2): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. +tests/cases/compiler/classUpdateTests.ts(72,3): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. tests/cases/compiler/classUpdateTests.ts(93,3): error TS1128: Declaration or statement expected. tests/cases/compiler/classUpdateTests.ts(95,1): error TS1128: Declaration or statement expected. tests/cases/compiler/classUpdateTests.ts(99,3): error TS1128: Declaration or statement expected. @@ -80,14 +80,11 @@ tests/cases/compiler/classUpdateTests.ts(113,1): error TS1128: Declaration or st class K extends G { constructor(public p1:number) { // ERROR - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var i = 0; - ~~~~~~~~~~~~ super(); - ~~~~~~~~~~ - } - ~~ + ~~~~~~~~ !!! error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. + } } class L extends G { @@ -104,14 +101,11 @@ tests/cases/compiler/classUpdateTests.ts(113,1): error TS1128: Declaration or st !!! error TS2415: Class 'M' incorrectly extends base class 'G'. !!! error TS2415: Property 'p1' is private in type 'M' but not in type 'G'. constructor(private p1:number) { // ERROR - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var i = 0; - ~~~~~~~~~~~~ super(); - ~~~~~~~~~~ - } - ~~ + ~~~~~~~~ !!! error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. + } } // diff --git a/tests/baselines/reference/derivedClassParameterProperties.errors.txt b/tests/baselines/reference/derivedClassParameterProperties.errors.txt index 0dba0d24cb0ff..c5d853dec56d2 100644 --- a/tests/baselines/reference/derivedClassParameterProperties.errors.txt +++ b/tests/baselines/reference/derivedClassParameterProperties.errors.txt @@ -1,10 +1,11 @@ -tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(15,5): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. -tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(30,5): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. -tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(56,5): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. -tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(79,5): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. +tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(17,9): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. +tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(32,9): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. +tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(49,9): error TS17006: 'super' must be called before accessing 'this' in the constructor of a derived class. +tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(59,9): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. +tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(82,9): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. -==== tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts (4 errors) ==== +==== tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts (5 errors) ==== // ordering of super calls in derived constructors matters depending on other class contents class Base { @@ -20,14 +21,11 @@ tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassP class Derived2 extends Base { constructor(public y: string) { - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var a = 1; - ~~~~~~~~~~~~~~~~~~ super(); // error - ~~~~~~~~~~~~~~~~~~~~~~~~~ - } - ~~~~~ + ~~~~~~~~ !!! error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. + } } class Derived3 extends Base { @@ -40,14 +38,11 @@ tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassP class Derived4 extends Base { a = 1; constructor(y: string) { - ~~~~~~~~~~~~~~~~~~~~~~~~ var b = 2; - ~~~~~~~~~~~~~~~~~~ super(); // error - ~~~~~~~~~~~~~~~~~~~~~~~~~ - } - ~~~~~ + ~~~~~~~~ !!! error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. + } } class Derived5 extends Base { @@ -63,7 +58,9 @@ tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassP constructor(y: string) { this.a = 1; var b = 2; - super(); // ok + super(); // error: "super" has to be called before "this" accessing + ~~~~~~~~ +!!! error TS17006: 'super' must be called before accessing 'this' in the constructor of a derived class. } } @@ -71,16 +68,12 @@ tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassP a = 1; b: number; constructor(y: string) { - ~~~~~~~~~~~~~~~~~~~~~~~~ this.a = 3; - ~~~~~~~~~~~~~~~~~~~ this.b = 3; - ~~~~~~~~~~~~~~~~~~~ super(); // error - ~~~~~~~~~~~~~~~~~~~~~~~~~ - } - ~~~~~ + ~~~~~~~~ !!! error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. + } } class Derived8 extends Base { @@ -100,16 +93,12 @@ tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassP a = 1; b: number; constructor(y: string) { - ~~~~~~~~~~~~~~~~~~~~~~~~ this.a = 3; - ~~~~~~~~~~~~~~~~~~~ this.b = 3; - ~~~~~~~~~~~~~~~~~~~ super(); // error - ~~~~~~~~~~~~~~~~~~~~~~~~~ - } - ~~~~~ + ~~~~~~~~ !!! error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. + } } class Derived10 extends Base2 { diff --git a/tests/baselines/reference/derivedClassParameterProperties.js b/tests/baselines/reference/derivedClassParameterProperties.js index 55c0a312b7163..0d4a476af12a7 100644 --- a/tests/baselines/reference/derivedClassParameterProperties.js +++ b/tests/baselines/reference/derivedClassParameterProperties.js @@ -47,7 +47,7 @@ class Derived6 extends Base { constructor(y: string) { this.a = 1; var b = 2; - super(); // ok + super(); // error: "super" has to be called before "this" accessing } } @@ -155,7 +155,7 @@ var Derived6 = (function (_super) { function Derived6(y) { this.a = 1; var b = 2; - _super.call(this); // ok + _super.call(this); // error: "super" has to be called before "this" accessing } return Derived6; })(Base); diff --git a/tests/baselines/reference/derivedClassSuperCallsWithThisArg.errors.txt b/tests/baselines/reference/derivedClassSuperCallsWithThisArg.errors.txt index ef43d1d6f528d..e72dbe293e9ed 100644 --- a/tests/baselines/reference/derivedClassSuperCallsWithThisArg.errors.txt +++ b/tests/baselines/reference/derivedClassSuperCallsWithThisArg.errors.txt @@ -1,8 +1,9 @@ +tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassSuperCallsWithThisArg.ts(8,9): error TS17006: 'super' must be called before accessing 'this' in the constructor of a derived class. tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassSuperCallsWithThisArg.ts(14,15): error TS2332: 'this' cannot be referenced in current location. tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassSuperCallsWithThisArg.ts(20,21): error TS2332: 'this' cannot be referenced in current location. -==== tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassSuperCallsWithThisArg.ts (2 errors) ==== +==== tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassSuperCallsWithThisArg.ts (3 errors) ==== class Base { x: string; constructor(a) { } @@ -11,6 +12,8 @@ tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassS class Derived extends Base { constructor() { super(this); // ok + ~~~~~~~~~~~~ +!!! error TS17006: 'super' must be called before accessing 'this' in the constructor of a derived class. } } diff --git a/tests/baselines/reference/strictModeInConstructor.errors.txt b/tests/baselines/reference/strictModeInConstructor.errors.txt index 9a80732842afe..3c38530cc12d7 100644 --- a/tests/baselines/reference/strictModeInConstructor.errors.txt +++ b/tests/baselines/reference/strictModeInConstructor.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/strictModeInConstructor.ts(27,5): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. +tests/cases/compiler/strictModeInConstructor.ts(29,9): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. ==== tests/cases/compiler/strictModeInConstructor.ts (1 errors) ==== @@ -29,16 +29,12 @@ tests/cases/compiler/strictModeInConstructor.ts(27,5): error TS2376: A 'super' c public s: number = 9; constructor () { - ~~~~~~~~~~~~~~~~ var x = 1; // Error - ~~~~~~~~~~~~~~~~~~~~~~~~~~~ super(); - ~~~~~~~~~~~~~~~~ + ~~~~~~~~ +!!! error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. "use strict"; - ~~~~~~~~~~~~~~~~~~~~~ } - ~~~~~ -!!! error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. } class Bs extends A { diff --git a/tests/baselines/reference/thisInInvalidContexts.errors.txt b/tests/baselines/reference/thisInInvalidContexts.errors.txt index 76b90ed7c207a..b722540c0868d 100644 --- a/tests/baselines/reference/thisInInvalidContexts.errors.txt +++ b/tests/baselines/reference/thisInInvalidContexts.errors.txt @@ -1,4 +1,5 @@ tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts(3,16): error TS2334: 'this' cannot be referenced in a static property initializer. +tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts(14,9): error TS17006: 'super' must be called before accessing 'this' in the constructor of a derived class. tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts(22,15): error TS2332: 'this' cannot be referenced in current location. tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts(28,13): error TS2331: 'this' cannot be referenced in a module or namespace body. tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts(36,13): error TS2526: A 'this' type is available only in a non-static member of a class or interface. @@ -7,7 +8,7 @@ tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts(44,9): tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts(45,9): error TS2332: 'this' cannot be referenced in current location. -==== tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts (7 errors) ==== +==== tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts (8 errors) ==== //'this' in static member initializer class ErrClass1 { static t = this; // Error @@ -23,7 +24,9 @@ tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts(45,9): t; //'this' in optional super call constructor() { - super(this); // OK + super(this); // Error + ~~~~~~~~~~~~ +!!! error TS17006: 'super' must be called before accessing 'this' in the constructor of a derived class. } } diff --git a/tests/baselines/reference/thisInInvalidContexts.js b/tests/baselines/reference/thisInInvalidContexts.js index d5ba69ff5364c..66cbdb9682ca2 100644 --- a/tests/baselines/reference/thisInInvalidContexts.js +++ b/tests/baselines/reference/thisInInvalidContexts.js @@ -12,7 +12,7 @@ class ClassWithNoInitializer extends BaseErrClass { t; //'this' in optional super call constructor() { - super(this); // OK + super(this); // Error } } @@ -70,7 +70,7 @@ var ClassWithNoInitializer = (function (_super) { __extends(ClassWithNoInitializer, _super); //'this' in optional super call function ClassWithNoInitializer() { - _super.call(this, this); // OK + _super.call(this, this); // Error } return ClassWithNoInitializer; })(BaseErrClass); diff --git a/tests/baselines/reference/thisInInvalidContextsExternalModule.errors.txt b/tests/baselines/reference/thisInInvalidContextsExternalModule.errors.txt index 2aa474d4cdc56..b0bae517598d4 100644 --- a/tests/baselines/reference/thisInInvalidContextsExternalModule.errors.txt +++ b/tests/baselines/reference/thisInInvalidContextsExternalModule.errors.txt @@ -1,4 +1,5 @@ tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts(3,16): error TS2334: 'this' cannot be referenced in a static property initializer. +tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts(14,9): error TS17006: 'super' must be called before accessing 'this' in the constructor of a derived class. tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts(22,15): error TS2332: 'this' cannot be referenced in current location. tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts(28,13): error TS2331: 'this' cannot be referenced in a module or namespace body. tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts(36,13): error TS2526: A 'this' type is available only in a non-static member of a class or interface. @@ -8,7 +9,7 @@ tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalMod tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts(48,1): error TS1148: Cannot compile modules unless the '--module' flag is provided. -==== tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts (8 errors) ==== +==== tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts (9 errors) ==== //'this' in static member initializer class ErrClass1 { static t = this; // Error @@ -24,7 +25,9 @@ tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalMod t; //'this' in optional super call constructor() { - super(this); // OK + super(this); // error: "super" has to be called before "this" accessing + ~~~~~~~~~~~~ +!!! error TS17006: 'super' must be called before accessing 'this' in the constructor of a derived class. } } diff --git a/tests/baselines/reference/thisInInvalidContextsExternalModule.js b/tests/baselines/reference/thisInInvalidContextsExternalModule.js index 7c19596494798..794f95ca662ce 100644 --- a/tests/baselines/reference/thisInInvalidContextsExternalModule.js +++ b/tests/baselines/reference/thisInInvalidContextsExternalModule.js @@ -12,7 +12,7 @@ class ClassWithNoInitializer extends BaseErrClass { t; //'this' in optional super call constructor() { - super(this); // OK + super(this); // error: "super" has to be called before "this" accessing } } @@ -70,7 +70,7 @@ var ClassWithNoInitializer = (function (_super) { __extends(ClassWithNoInitializer, _super); //'this' in optional super call function ClassWithNoInitializer() { - _super.call(this, this); // OK + _super.call(this, this); // error: "super" has to be called before "this" accessing } return ClassWithNoInitializer; })(BaseErrClass); diff --git a/tests/baselines/reference/thisInSuperCall.errors.txt b/tests/baselines/reference/thisInSuperCall.errors.txt index 57255aa958235..ea4b6fd742a3e 100644 --- a/tests/baselines/reference/thisInSuperCall.errors.txt +++ b/tests/baselines/reference/thisInSuperCall.errors.txt @@ -1,15 +1,18 @@ +tests/cases/compiler/thisInSuperCall.ts(7,9): error TS17006: 'super' must be called before accessing 'this' in the constructor of a derived class. tests/cases/compiler/thisInSuperCall.ts(14,15): error TS2332: 'this' cannot be referenced in current location. tests/cases/compiler/thisInSuperCall.ts(20,15): error TS2332: 'this' cannot be referenced in current location. -==== tests/cases/compiler/thisInSuperCall.ts (2 errors) ==== +==== tests/cases/compiler/thisInSuperCall.ts (3 errors) ==== class Base { constructor(x: any) {} } class Foo extends Base { constructor() { - super(this); // no error + super(this); // error: "super" has to be called before "this" accessing + ~~~~~~~~~~~~ +!!! error TS17006: 'super' must be called before accessing 'this' in the constructor of a derived class. } } diff --git a/tests/baselines/reference/thisInSuperCall.js b/tests/baselines/reference/thisInSuperCall.js index f7d7ca4e4fd65..0bcaf35fcbf5d 100644 --- a/tests/baselines/reference/thisInSuperCall.js +++ b/tests/baselines/reference/thisInSuperCall.js @@ -5,7 +5,7 @@ class Base { class Foo extends Base { constructor() { - super(this); // no error + super(this); // error: "super" has to be called before "this" accessing } } @@ -36,7 +36,7 @@ var Base = (function () { var Foo = (function (_super) { __extends(Foo, _super); function Foo() { - _super.call(this, this); // no error + _super.call(this, this); // error: "super" has to be called before "this" accessing } return Foo; })(Base); diff --git a/tests/baselines/reference/thisInSuperCall2.errors.txt b/tests/baselines/reference/thisInSuperCall2.errors.txt index d3a94f79487ce..7130ee8deb885 100644 --- a/tests/baselines/reference/thisInSuperCall2.errors.txt +++ b/tests/baselines/reference/thisInSuperCall2.errors.txt @@ -1,7 +1,8 @@ +tests/cases/compiler/thisInSuperCall2.ts(8,9): error TS17006: 'super' must be called before accessing 'this' in the constructor of a derived class. tests/cases/compiler/thisInSuperCall2.ts(16,15): error TS2332: 'this' cannot be referenced in current location. -==== tests/cases/compiler/thisInSuperCall2.ts (1 errors) ==== +==== tests/cases/compiler/thisInSuperCall2.ts (2 errors) ==== class Base { constructor(a: any) {} } @@ -9,7 +10,9 @@ tests/cases/compiler/thisInSuperCall2.ts(16,15): error TS2332: 'this' cannot be class Foo extends Base { public x: number; constructor() { - super(this); // no error + super(this); // error: "super" has to be called before "this" accessing + ~~~~~~~~~~~~ +!!! error TS17006: 'super' must be called before accessing 'this' in the constructor of a derived class. } } diff --git a/tests/baselines/reference/thisInSuperCall2.js b/tests/baselines/reference/thisInSuperCall2.js index a9bbeda9fe798..8957a08921022 100644 --- a/tests/baselines/reference/thisInSuperCall2.js +++ b/tests/baselines/reference/thisInSuperCall2.js @@ -6,7 +6,7 @@ class Base { class Foo extends Base { public x: number; constructor() { - super(this); // no error + super(this); // error: "super" has to be called before "this" accessing } } @@ -33,7 +33,7 @@ var Base = (function () { var Foo = (function (_super) { __extends(Foo, _super); function Foo() { - _super.call(this, this); // no error + _super.call(this, this); // error: "super" has to be called before "this" accessing } return Foo; })(Base); diff --git a/tests/cases/compiler/checkSuperCallBeforeThisAccessing1.ts b/tests/cases/compiler/checkSuperCallBeforeThisAccessing1.ts new file mode 100644 index 0000000000000..e8dd78ef54651 --- /dev/null +++ b/tests/cases/compiler/checkSuperCallBeforeThisAccessing1.ts @@ -0,0 +1,10 @@ +class Based { } +class Derived extends Based { + public x: number; + constructor() { + super(); + this; + this.x = 10; + var that = this; + } +} \ No newline at end of file diff --git a/tests/cases/compiler/checkSuperCallBeforeThisAccessing2.ts b/tests/cases/compiler/checkSuperCallBeforeThisAccessing2.ts new file mode 100644 index 0000000000000..e6545f242889c --- /dev/null +++ b/tests/cases/compiler/checkSuperCallBeforeThisAccessing2.ts @@ -0,0 +1,10 @@ +class Based { } +class Derived extends Based { + public x: number; + constructor() { + this.x = 100; + super(); + this.x = 10; + var that = this; + } +} \ No newline at end of file diff --git a/tests/cases/compiler/checkSuperCallBeforeThisAccessing3.ts b/tests/cases/compiler/checkSuperCallBeforeThisAccessing3.ts new file mode 100644 index 0000000000000..fd9de120b057a --- /dev/null +++ b/tests/cases/compiler/checkSuperCallBeforeThisAccessing3.ts @@ -0,0 +1,15 @@ +class Based { } +class Derived extends Based { + public x: number; + constructor() { + class innver { + public y: boolean; + constructor() { + this.y = true; + } + } + super(); + this.x = 10; + var that = this; + } +} \ No newline at end of file diff --git a/tests/cases/compiler/checkSuperCallBeforeThisAccessing4.ts b/tests/cases/compiler/checkSuperCallBeforeThisAccessing4.ts new file mode 100644 index 0000000000000..1fdee00c2f861 --- /dev/null +++ b/tests/cases/compiler/checkSuperCallBeforeThisAccessing4.ts @@ -0,0 +1,19 @@ +class Based { } +class Derived extends Based { + public x: number; + constructor() { + (() => { + this; // No error + }); + () => { + this; // No error + }; + (() => { + this; // No error + })(); + super(); + super(); + this.x = 10; + var that = this; + } +} \ No newline at end of file diff --git a/tests/cases/compiler/checkSuperCallBeforeThisAccessing5.ts b/tests/cases/compiler/checkSuperCallBeforeThisAccessing5.ts new file mode 100644 index 0000000000000..65d1db6df7522 --- /dev/null +++ b/tests/cases/compiler/checkSuperCallBeforeThisAccessing5.ts @@ -0,0 +1,7 @@ +class Based { constructor(...arg) { } } +class Derived extends Based { + public x: number; + constructor() { + super(this.x); + } +} \ No newline at end of file diff --git a/tests/cases/compiler/checkSuperCallBeforeThisAccessing6.ts b/tests/cases/compiler/checkSuperCallBeforeThisAccessing6.ts new file mode 100644 index 0000000000000..2cdcb9ad3a810 --- /dev/null +++ b/tests/cases/compiler/checkSuperCallBeforeThisAccessing6.ts @@ -0,0 +1,10 @@ +class Base { + constructor(...arg) { + } +} +class Super extends Base { + constructor() { + (() => this); // No Error + super(); + } +} \ No newline at end of file diff --git a/tests/cases/compiler/checkSuperCallBeforeThisAccessing7.ts b/tests/cases/compiler/checkSuperCallBeforeThisAccessing7.ts new file mode 100644 index 0000000000000..1c4af98f0a294 --- /dev/null +++ b/tests/cases/compiler/checkSuperCallBeforeThisAccessing7.ts @@ -0,0 +1,9 @@ +class Base { + constructor(func: ()=>Base) { + } +} +class Super extends Base { + constructor() { + super((() => this)); // No error + } +} \ No newline at end of file diff --git a/tests/cases/compiler/checkSuperCallBeforeThisAccessing8.ts b/tests/cases/compiler/checkSuperCallBeforeThisAccessing8.ts new file mode 100644 index 0000000000000..230b40fc24df6 --- /dev/null +++ b/tests/cases/compiler/checkSuperCallBeforeThisAccessing8.ts @@ -0,0 +1,10 @@ +class Base { + constructor(...arg) { + } +} +class Super extends Base { + constructor() { + var that = this; + super(); + } +} \ No newline at end of file diff --git a/tests/cases/compiler/thisInSuperCall.ts b/tests/cases/compiler/thisInSuperCall.ts index 6a54e9ac6f12e..b7df7cbafad74 100644 --- a/tests/cases/compiler/thisInSuperCall.ts +++ b/tests/cases/compiler/thisInSuperCall.ts @@ -4,7 +4,7 @@ class Base { class Foo extends Base { constructor() { - super(this); // no error + super(this); // error: "super" has to be called before "this" accessing } } diff --git a/tests/cases/compiler/thisInSuperCall2.ts b/tests/cases/compiler/thisInSuperCall2.ts index 5de7c34cf3252..2869ab9a80553 100644 --- a/tests/cases/compiler/thisInSuperCall2.ts +++ b/tests/cases/compiler/thisInSuperCall2.ts @@ -5,7 +5,7 @@ class Base { class Foo extends Base { public x: number; constructor() { - super(this); // no error + super(this); // error: "super" has to be called before "this" accessing } } diff --git a/tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts b/tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts index edfd7ab4f8c17..a054ed0f6831b 100644 --- a/tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts +++ b/tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts @@ -46,7 +46,7 @@ class Derived6 extends Base { constructor(y: string) { this.a = 1; var b = 2; - super(); // ok + super(); // error: "super" has to be called before "this" accessing } } diff --git a/tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts b/tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts index 0afbc45004087..2b929318c13fe 100644 --- a/tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts +++ b/tests/cases/conformance/expressions/thisKeyword/thisInInvalidContexts.ts @@ -11,7 +11,7 @@ class ClassWithNoInitializer extends BaseErrClass { t; //'this' in optional super call constructor() { - super(this); // OK + super(this); // Error } } diff --git a/tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts b/tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts index 513e56977df5e..e3d8ce9f5fcd2 100644 --- a/tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts +++ b/tests/cases/conformance/expressions/thisKeyword/thisInInvalidContextsExternalModule.ts @@ -11,7 +11,7 @@ class ClassWithNoInitializer extends BaseErrClass { t; //'this' in optional super call constructor() { - super(this); // OK + super(this); // error: "super" has to be called before "this" accessing } }