From c7a65b558ec853cf065e1127c6bf24d84ae0f051 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Tue, 1 Dec 2015 10:00:00 -0800 Subject: [PATCH] do not error on 'super' property access in ES6 --- src/compiler/checker.ts | 2 +- .../superPropertyAccess_ES5.errors.txt | 38 ++++++++ .../reference/superPropertyAccess_ES5.js | 84 +++++++++++++++++ .../reference/superPropertyAccess_ES6.js | 54 +++++++++++ .../reference/superPropertyAccess_ES6.symbols | 80 +++++++++++++++++ .../reference/superPropertyAccess_ES6.types | 89 +++++++++++++++++++ .../cases/compiler/superPropertyAccess_ES5.ts | 30 +++++++ .../cases/compiler/superPropertyAccess_ES6.ts | 30 +++++++ 8 files changed, 406 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/superPropertyAccess_ES5.errors.txt create mode 100644 tests/baselines/reference/superPropertyAccess_ES5.js create mode 100644 tests/baselines/reference/superPropertyAccess_ES6.js create mode 100644 tests/baselines/reference/superPropertyAccess_ES6.symbols create mode 100644 tests/baselines/reference/superPropertyAccess_ES6.types create mode 100644 tests/cases/compiler/superPropertyAccess_ES5.ts create mode 100644 tests/cases/compiler/superPropertyAccess_ES6.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9ed3ca55e198a..a76e7233c9b34 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8219,7 +8219,7 @@ namespace ts { // - In a static member function or static member accessor // where this references the constructor function object of a derived class, // a super property access is permitted and must specify a public static member function of the base class. - if (getDeclarationKindFromSymbol(prop) !== SyntaxKind.MethodDeclaration) { + if (languageVersion < ScriptTarget.ES6 && getDeclarationKindFromSymbol(prop) !== SyntaxKind.MethodDeclaration) { // `prop` refers to a *property* declared in the super class // rather than a *method*, so it does not satisfy the above criteria. diff --git a/tests/baselines/reference/superPropertyAccess_ES5.errors.txt b/tests/baselines/reference/superPropertyAccess_ES5.errors.txt new file mode 100644 index 0000000000000..08adcd36e6829 --- /dev/null +++ b/tests/baselines/reference/superPropertyAccess_ES5.errors.txt @@ -0,0 +1,38 @@ +tests/cases/compiler/superPropertyAccess_ES5.ts(12,22): error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword. +tests/cases/compiler/superPropertyAccess_ES5.ts(27,15): error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword. + + +==== tests/cases/compiler/superPropertyAccess_ES5.ts (2 errors) ==== + + class MyBase { + getValue(): number { return 1; } + get value(): number { return 1; } + } + + class MyDerived extends MyBase { + constructor() { + super(); + + const f1 = super.getValue(); + const f2 = super.value; + ~~~~~ +!!! error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword. + } + } + + var d = new MyDerived(); + var f3 = d.value; + + class A { + private _property: string; + get property() { return this._property; } + set property(value: string) { this._property = value } + } + + class B extends A { + set property(value: string) { + super.property = value + " addition"; + ~~~~~~~~ +!!! error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/superPropertyAccess_ES5.js b/tests/baselines/reference/superPropertyAccess_ES5.js new file mode 100644 index 0000000000000..a31c1dfdcba9c --- /dev/null +++ b/tests/baselines/reference/superPropertyAccess_ES5.js @@ -0,0 +1,84 @@ +//// [superPropertyAccess_ES5.ts] + +class MyBase { + getValue(): number { return 1; } + get value(): number { return 1; } +} + +class MyDerived extends MyBase { + constructor() { + super(); + + const f1 = super.getValue(); + const f2 = super.value; + } +} + +var d = new MyDerived(); +var f3 = d.value; + +class A { + private _property: string; + get property() { return this._property; } + set property(value: string) { this._property = value } +} + +class B extends A { + set property(value: string) { + super.property = value + " addition"; + } +} + +//// [superPropertyAccess_ES5.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 MyBase = (function () { + function MyBase() { + } + MyBase.prototype.getValue = function () { return 1; }; + Object.defineProperty(MyBase.prototype, "value", { + get: function () { return 1; }, + enumerable: true, + configurable: true + }); + return MyBase; +})(); +var MyDerived = (function (_super) { + __extends(MyDerived, _super); + function MyDerived() { + _super.call(this); + var f1 = _super.prototype.getValue.call(this); + var f2 = _super.prototype.value; + } + return MyDerived; +})(MyBase); +var d = new MyDerived(); +var f3 = d.value; +var A = (function () { + function A() { + } + Object.defineProperty(A.prototype, "property", { + get: function () { return this._property; }, + set: function (value) { this._property = value; }, + enumerable: true, + configurable: true + }); + return A; +})(); +var B = (function (_super) { + __extends(B, _super); + function B() { + _super.apply(this, arguments); + } + Object.defineProperty(B.prototype, "property", { + set: function (value) { + _super.prototype.property = value + " addition"; + }, + enumerable: true, + configurable: true + }); + return B; +})(A); diff --git a/tests/baselines/reference/superPropertyAccess_ES6.js b/tests/baselines/reference/superPropertyAccess_ES6.js new file mode 100644 index 0000000000000..1b23c6ca0d89c --- /dev/null +++ b/tests/baselines/reference/superPropertyAccess_ES6.js @@ -0,0 +1,54 @@ +//// [superPropertyAccess_ES6.ts] + +class MyBase { + getValue(): number { return 1; } + get value(): number { return 1; } +} + +class MyDerived extends MyBase { + constructor() { + super(); + + const f1 = super.getValue(); + const f2 = super.value; + } +} + +var d = new MyDerived(); +var f3 = d.value; + +class A { + private _property: string; + get property() { return this._property; } + set property(value: string) { this._property = value } +} + +class B extends A { + set property(value: string) { + super.property = value + " addition"; + } +} + +//// [superPropertyAccess_ES6.js] +class MyBase { + getValue() { return 1; } + get value() { return 1; } +} +class MyDerived extends MyBase { + constructor() { + super(); + const f1 = super.getValue(); + const f2 = super.value; + } +} +var d = new MyDerived(); +var f3 = d.value; +class A { + get property() { return this._property; } + set property(value) { this._property = value; } +} +class B extends A { + set property(value) { + super.property = value + " addition"; + } +} diff --git a/tests/baselines/reference/superPropertyAccess_ES6.symbols b/tests/baselines/reference/superPropertyAccess_ES6.symbols new file mode 100644 index 0000000000000..ada6c5b805703 --- /dev/null +++ b/tests/baselines/reference/superPropertyAccess_ES6.symbols @@ -0,0 +1,80 @@ +=== tests/cases/compiler/superPropertyAccess_ES6.ts === + +class MyBase { +>MyBase : Symbol(MyBase, Decl(superPropertyAccess_ES6.ts, 0, 0)) + + getValue(): number { return 1; } +>getValue : Symbol(getValue, Decl(superPropertyAccess_ES6.ts, 1, 14)) + + get value(): number { return 1; } +>value : Symbol(value, Decl(superPropertyAccess_ES6.ts, 2, 34)) +} + +class MyDerived extends MyBase { +>MyDerived : Symbol(MyDerived, Decl(superPropertyAccess_ES6.ts, 4, 1)) +>MyBase : Symbol(MyBase, Decl(superPropertyAccess_ES6.ts, 0, 0)) + + constructor() { + super(); +>super : Symbol(MyBase, Decl(superPropertyAccess_ES6.ts, 0, 0)) + + const f1 = super.getValue(); +>f1 : Symbol(f1, Decl(superPropertyAccess_ES6.ts, 10, 9)) +>super.getValue : Symbol(MyBase.getValue, Decl(superPropertyAccess_ES6.ts, 1, 14)) +>super : Symbol(MyBase, Decl(superPropertyAccess_ES6.ts, 0, 0)) +>getValue : Symbol(MyBase.getValue, Decl(superPropertyAccess_ES6.ts, 1, 14)) + + const f2 = super.value; +>f2 : Symbol(f2, Decl(superPropertyAccess_ES6.ts, 11, 9)) +>super.value : Symbol(MyBase.value, Decl(superPropertyAccess_ES6.ts, 2, 34)) +>super : Symbol(MyBase, Decl(superPropertyAccess_ES6.ts, 0, 0)) +>value : Symbol(MyBase.value, Decl(superPropertyAccess_ES6.ts, 2, 34)) + } +} + +var d = new MyDerived(); +>d : Symbol(d, Decl(superPropertyAccess_ES6.ts, 15, 3)) +>MyDerived : Symbol(MyDerived, Decl(superPropertyAccess_ES6.ts, 4, 1)) + +var f3 = d.value; +>f3 : Symbol(f3, Decl(superPropertyAccess_ES6.ts, 16, 3)) +>d.value : Symbol(MyBase.value, Decl(superPropertyAccess_ES6.ts, 2, 34)) +>d : Symbol(d, Decl(superPropertyAccess_ES6.ts, 15, 3)) +>value : Symbol(MyBase.value, Decl(superPropertyAccess_ES6.ts, 2, 34)) + +class A { +>A : Symbol(A, Decl(superPropertyAccess_ES6.ts, 16, 17)) + + private _property: string; +>_property : Symbol(_property, Decl(superPropertyAccess_ES6.ts, 18, 9)) + + get property() { return this._property; } +>property : Symbol(property, Decl(superPropertyAccess_ES6.ts, 19, 30), Decl(superPropertyAccess_ES6.ts, 20, 45)) +>this._property : Symbol(_property, Decl(superPropertyAccess_ES6.ts, 18, 9)) +>this : Symbol(A, Decl(superPropertyAccess_ES6.ts, 16, 17)) +>_property : Symbol(_property, Decl(superPropertyAccess_ES6.ts, 18, 9)) + + set property(value: string) { this._property = value } +>property : Symbol(property, Decl(superPropertyAccess_ES6.ts, 19, 30), Decl(superPropertyAccess_ES6.ts, 20, 45)) +>value : Symbol(value, Decl(superPropertyAccess_ES6.ts, 21, 17)) +>this._property : Symbol(_property, Decl(superPropertyAccess_ES6.ts, 18, 9)) +>this : Symbol(A, Decl(superPropertyAccess_ES6.ts, 16, 17)) +>_property : Symbol(_property, Decl(superPropertyAccess_ES6.ts, 18, 9)) +>value : Symbol(value, Decl(superPropertyAccess_ES6.ts, 21, 17)) +} + +class B extends A { +>B : Symbol(B, Decl(superPropertyAccess_ES6.ts, 22, 1)) +>A : Symbol(A, Decl(superPropertyAccess_ES6.ts, 16, 17)) + + set property(value: string) { +>property : Symbol(property, Decl(superPropertyAccess_ES6.ts, 24, 19)) +>value : Symbol(value, Decl(superPropertyAccess_ES6.ts, 25, 17)) + + super.property = value + " addition"; +>super.property : Symbol(A.property, Decl(superPropertyAccess_ES6.ts, 19, 30), Decl(superPropertyAccess_ES6.ts, 20, 45)) +>super : Symbol(A, Decl(superPropertyAccess_ES6.ts, 16, 17)) +>property : Symbol(A.property, Decl(superPropertyAccess_ES6.ts, 19, 30), Decl(superPropertyAccess_ES6.ts, 20, 45)) +>value : Symbol(value, Decl(superPropertyAccess_ES6.ts, 25, 17)) + } +} diff --git a/tests/baselines/reference/superPropertyAccess_ES6.types b/tests/baselines/reference/superPropertyAccess_ES6.types new file mode 100644 index 0000000000000..b10b1944a44ee --- /dev/null +++ b/tests/baselines/reference/superPropertyAccess_ES6.types @@ -0,0 +1,89 @@ +=== tests/cases/compiler/superPropertyAccess_ES6.ts === + +class MyBase { +>MyBase : MyBase + + getValue(): number { return 1; } +>getValue : () => number +>1 : number + + get value(): number { return 1; } +>value : number +>1 : number +} + +class MyDerived extends MyBase { +>MyDerived : MyDerived +>MyBase : MyBase + + constructor() { + super(); +>super() : void +>super : typeof MyBase + + const f1 = super.getValue(); +>f1 : number +>super.getValue() : number +>super.getValue : () => number +>super : MyBase +>getValue : () => number + + const f2 = super.value; +>f2 : number +>super.value : number +>super : MyBase +>value : number + } +} + +var d = new MyDerived(); +>d : MyDerived +>new MyDerived() : MyDerived +>MyDerived : typeof MyDerived + +var f3 = d.value; +>f3 : number +>d.value : number +>d : MyDerived +>value : number + +class A { +>A : A + + private _property: string; +>_property : string + + get property() { return this._property; } +>property : string +>this._property : string +>this : this +>_property : string + + set property(value: string) { this._property = value } +>property : string +>value : string +>this._property = value : string +>this._property : string +>this : this +>_property : string +>value : string +} + +class B extends A { +>B : B +>A : A + + set property(value: string) { +>property : string +>value : string + + super.property = value + " addition"; +>super.property = value + " addition" : string +>super.property : string +>super : A +>property : string +>value + " addition" : string +>value : string +>" addition" : string + } +} diff --git a/tests/cases/compiler/superPropertyAccess_ES5.ts b/tests/cases/compiler/superPropertyAccess_ES5.ts new file mode 100644 index 0000000000000..37897b9e549e7 --- /dev/null +++ b/tests/cases/compiler/superPropertyAccess_ES5.ts @@ -0,0 +1,30 @@ +// @target: ES5 + +class MyBase { + getValue(): number { return 1; } + get value(): number { return 1; } +} + +class MyDerived extends MyBase { + constructor() { + super(); + + const f1 = super.getValue(); + const f2 = super.value; + } +} + +var d = new MyDerived(); +var f3 = d.value; + +class A { + private _property: string; + get property() { return this._property; } + set property(value: string) { this._property = value } +} + +class B extends A { + set property(value: string) { + super.property = value + " addition"; + } +} \ No newline at end of file diff --git a/tests/cases/compiler/superPropertyAccess_ES6.ts b/tests/cases/compiler/superPropertyAccess_ES6.ts new file mode 100644 index 0000000000000..ed082b1903215 --- /dev/null +++ b/tests/cases/compiler/superPropertyAccess_ES6.ts @@ -0,0 +1,30 @@ +// @target: ES6 + +class MyBase { + getValue(): number { return 1; } + get value(): number { return 1; } +} + +class MyDerived extends MyBase { + constructor() { + super(); + + const f1 = super.getValue(); + const f2 = super.value; + } +} + +var d = new MyDerived(); +var f3 = d.value; + +class A { + private _property: string; + get property() { return this._property; } + set property(value: string) { this._property = value } +} + +class B extends A { + set property(value: string) { + super.property = value + " addition"; + } +} \ No newline at end of file