Skip outer expressions when checking for super keyword in binder (#20164)

* Skip outter expressions when checking for super keyword in binder

* use TransformFlags to optimize and correct super call transforms

* Lint
This commit is contained in:
Wesley Wigham 2018-01-12 18:24:02 -08:00 committed by GitHub
parent 6f28b0ac25
commit 64305edbce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 753 additions and 43 deletions

View File

@ -2740,6 +2740,9 @@ namespace ts {
case SyntaxKind.PropertyAccessExpression:
return computePropertyAccess(<PropertyAccessExpression>node, subtreeFlags);
case SyntaxKind.ElementAccessExpression:
return computeElementAccess(<ElementAccessExpression>node, subtreeFlags);
default:
return computeOther(node, kind, subtreeFlags);
}
@ -2748,17 +2751,21 @@ namespace ts {
function computeCallExpression(node: CallExpression, subtreeFlags: TransformFlags) {
let transformFlags = subtreeFlags;
const expression = node.expression;
const expressionKind = expression.kind;
if (node.typeArguments) {
transformFlags |= TransformFlags.AssertTypeScript;
}
if (subtreeFlags & TransformFlags.ContainsSpread
|| isSuperOrSuperProperty(expression, expressionKind)) {
|| (expression.transformFlags & (TransformFlags.Super | TransformFlags.ContainsSuper))) {
// If the this node contains a SpreadExpression, or is a super call, then it is an ES6
// node.
transformFlags |= TransformFlags.AssertES2015;
// super property or element accesses could be inside lambdas, etc, and need a captured `this`,
// while super keyword for super calls (indicated by TransformFlags.Super) does not (since it can only be top-level in a constructor)
if (expression.transformFlags & TransformFlags.ContainsSuper) {
transformFlags |= TransformFlags.ContainsLexicalThis;
}
}
if (expression.kind === SyntaxKind.ImportKeyword) {
@ -2775,21 +2782,6 @@ namespace ts {
return transformFlags & ~TransformFlags.ArrayLiteralOrCallOrNewExcludes;
}
function isSuperOrSuperProperty(node: Node, kind: SyntaxKind) {
switch (kind) {
case SyntaxKind.SuperKeyword:
return true;
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.ElementAccessExpression:
const expression = (<PropertyAccessExpression | ElementAccessExpression>node).expression;
const expressionKind = expression.kind;
return expressionKind === SyntaxKind.SuperKeyword;
}
return false;
}
function computeNewExpression(node: NewExpression, subtreeFlags: TransformFlags) {
let transformFlags = subtreeFlags;
if (node.typeArguments) {
@ -2884,7 +2876,7 @@ namespace ts {
}
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
return transformFlags & ~TransformFlags.NodeExcludes;
return transformFlags & ~TransformFlags.OuterExpressionExcludes;
}
function computeClassDeclaration(node: ClassDeclaration, subtreeFlags: TransformFlags) {
@ -3203,17 +3195,32 @@ namespace ts {
function computePropertyAccess(node: PropertyAccessExpression, subtreeFlags: TransformFlags) {
let transformFlags = subtreeFlags;
const expression = node.expression;
const expressionKind = expression.kind;
// If a PropertyAccessExpression starts with a super keyword, then it is
// ES6 syntax, and requires a lexical `this` binding.
if (expressionKind === SyntaxKind.SuperKeyword) {
transformFlags |= TransformFlags.ContainsLexicalThis;
if (transformFlags & TransformFlags.Super) {
transformFlags ^= TransformFlags.Super;
transformFlags |= TransformFlags.ContainsSuper;
}
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
return transformFlags & ~TransformFlags.NodeExcludes;
return transformFlags & ~TransformFlags.PropertyAccessExcludes;
}
function computeElementAccess(node: ElementAccessExpression, subtreeFlags: TransformFlags) {
let transformFlags = subtreeFlags;
const expression = node.expression;
const expressionFlags = expression.transformFlags; // We do not want to aggregate flags from the argument expression for super/this capturing
// If an ElementAccessExpression starts with a super keyword, then it is
// ES6 syntax, and requires a lexical `this` binding.
if (expressionFlags & TransformFlags.Super) {
transformFlags &= ~TransformFlags.Super;
transformFlags |= TransformFlags.ContainsSuper;
}
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
return transformFlags & ~TransformFlags.PropertyAccessExcludes;
}
function computeVariableDeclaration(node: VariableDeclaration, subtreeFlags: TransformFlags) {
@ -3333,6 +3340,13 @@ namespace ts {
transformFlags |= TransformFlags.AssertESNext | TransformFlags.AssertES2017;
break;
case SyntaxKind.TypeAssertionExpression:
case SyntaxKind.AsExpression:
case SyntaxKind.PartiallyEmittedExpression:
// These nodes are TypeScript syntax.
transformFlags |= TransformFlags.AssertTypeScript;
excludeFlags = TransformFlags.OuterExpressionExcludes;
break;
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
@ -3341,8 +3355,6 @@ namespace ts {
case SyntaxKind.ConstKeyword:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.EnumMember:
case SyntaxKind.TypeAssertionExpression:
case SyntaxKind.AsExpression:
case SyntaxKind.NonNullExpression:
case SyntaxKind.ReadonlyKeyword:
// These nodes are TypeScript syntax.
@ -3470,7 +3482,8 @@ namespace ts {
case SyntaxKind.SuperKeyword:
// This node is ES6 syntax.
transformFlags |= TransformFlags.AssertES2015;
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.Super;
excludeFlags = TransformFlags.OuterExpressionExcludes; // must be set to persist `Super`
break;
case SyntaxKind.ThisKeyword:
@ -3627,6 +3640,15 @@ namespace ts {
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
return TransformFlags.BindingPatternExcludes;
case SyntaxKind.TypeAssertionExpression:
case SyntaxKind.AsExpression:
case SyntaxKind.PartiallyEmittedExpression:
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.SuperKeyword:
return TransformFlags.OuterExpressionExcludes;
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.ElementAccessExpression:
return TransformFlags.PropertyAccessExcludes;
default:
return TransformFlags.NodeExcludes;
}

View File

@ -4456,6 +4456,8 @@ namespace ts {
ContainsYield = 1 << 24,
ContainsHoistedDeclarationOrCompletion = 1 << 25,
ContainsDynamicImport = 1 << 26,
Super = 1 << 27,
ContainsSuper = 1 << 28,
// Please leave this as 1 << 29.
// It is the maximum bit we can set before we outgrow the size of a v8 small integer (SMI) on an x86 system.
@ -4476,7 +4478,9 @@ namespace ts {
// Scope Exclusions
// - Bitmasks that exclude flags from propagating out of a specific context
// into the subtree flags of their container.
NodeExcludes = TypeScript | ES2015 | DestructuringAssignment | Generator | HasComputedFlags,
OuterExpressionExcludes = TypeScript | ES2015 | DestructuringAssignment | Generator | HasComputedFlags,
PropertyAccessExcludes = OuterExpressionExcludes | Super,
NodeExcludes = PropertyAccessExcludes | ContainsSuper,
ArrowFunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRest,
FunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRest,
ConstructorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRest,

View File

@ -28,7 +28,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
};
var M;
(function (M) {
var _this = this;
var S = /** @class */ (function () {
function S() {
}

View File

@ -35,7 +35,6 @@ var __extends = (this && this.__extends) || (function () {
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var _this = this;
var P = /** @class */ (function () {
function P() {
}

View File

@ -0,0 +1,54 @@
//// [superAccessCastedCall.ts]
class Foo {
bar(): void {}
}
class Bar extends Foo {
x: Number;
constructor() {
super();
this.x = 2;
}
bar() {
super.bar();
(super.bar as any)();
}
}
let b = new Bar();
b.bar()
//// [superAccessCastedCall.js]
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var Foo = /** @class */ (function () {
function Foo() {
}
Foo.prototype.bar = function () { };
return Foo;
}());
var Bar = /** @class */ (function (_super) {
__extends(Bar, _super);
function Bar() {
var _this = _super.call(this) || this;
_this.x = 2;
return _this;
}
Bar.prototype.bar = function () {
_super.prototype.bar.call(this);
_super.prototype.bar.call(this);
};
return Bar;
}(Foo));
var b = new Bar();
b.bar();

View File

@ -0,0 +1,50 @@
=== tests/cases/compiler/superAccessCastedCall.ts ===
class Foo {
>Foo : Symbol(Foo, Decl(superAccessCastedCall.ts, 0, 0))
bar(): void {}
>bar : Symbol(Foo.bar, Decl(superAccessCastedCall.ts, 0, 11))
}
class Bar extends Foo {
>Bar : Symbol(Bar, Decl(superAccessCastedCall.ts, 2, 1))
>Foo : Symbol(Foo, Decl(superAccessCastedCall.ts, 0, 0))
x: Number;
>x : Symbol(Bar.x, Decl(superAccessCastedCall.ts, 4, 23))
>Number : Symbol(Number, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
constructor() {
super();
>super : Symbol(Foo, Decl(superAccessCastedCall.ts, 0, 0))
this.x = 2;
>this.x : Symbol(Bar.x, Decl(superAccessCastedCall.ts, 4, 23))
>this : Symbol(Bar, Decl(superAccessCastedCall.ts, 2, 1))
>x : Symbol(Bar.x, Decl(superAccessCastedCall.ts, 4, 23))
}
bar() {
>bar : Symbol(Bar.bar, Decl(superAccessCastedCall.ts, 10, 5))
super.bar();
>super.bar : Symbol(Foo.bar, Decl(superAccessCastedCall.ts, 0, 11))
>super : Symbol(Foo, Decl(superAccessCastedCall.ts, 0, 0))
>bar : Symbol(Foo.bar, Decl(superAccessCastedCall.ts, 0, 11))
(super.bar as any)();
>super.bar : Symbol(Foo.bar, Decl(superAccessCastedCall.ts, 0, 11))
>super : Symbol(Foo, Decl(superAccessCastedCall.ts, 0, 0))
>bar : Symbol(Foo.bar, Decl(superAccessCastedCall.ts, 0, 11))
}
}
let b = new Bar();
>b : Symbol(b, Decl(superAccessCastedCall.ts, 18, 3))
>Bar : Symbol(Bar, Decl(superAccessCastedCall.ts, 2, 1))
b.bar()
>b.bar : Symbol(Bar.bar, Decl(superAccessCastedCall.ts, 10, 5))
>b : Symbol(b, Decl(superAccessCastedCall.ts, 18, 3))
>bar : Symbol(Bar.bar, Decl(superAccessCastedCall.ts, 10, 5))

View File

@ -0,0 +1,59 @@
=== tests/cases/compiler/superAccessCastedCall.ts ===
class Foo {
>Foo : Foo
bar(): void {}
>bar : () => void
}
class Bar extends Foo {
>Bar : Bar
>Foo : Foo
x: Number;
>x : Number
>Number : Number
constructor() {
super();
>super() : void
>super : typeof Foo
this.x = 2;
>this.x = 2 : 2
>this.x : Number
>this : this
>x : Number
>2 : 2
}
bar() {
>bar : () => void
super.bar();
>super.bar() : void
>super.bar : () => void
>super : Foo
>bar : () => void
(super.bar as any)();
>(super.bar as any)() : any
>(super.bar as any) : any
>super.bar as any : any
>super.bar : () => void
>super : Foo
>bar : () => void
}
}
let b = new Bar();
>b : Bar
>new Bar() : Bar
>Bar : typeof Bar
b.bar()
>b.bar() : void
>b.bar : () => void
>b : Bar
>bar : () => void

View File

@ -0,0 +1,44 @@
tests/cases/compiler/superElementAccess.ts(7,9): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
tests/cases/compiler/superElementAccess.ts(8,9): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
==== tests/cases/compiler/superElementAccess.ts (2 errors) ====
class MyBase {
m1(a: string) { return a; }
private p1() { }
m2: () => void = function () { }
d1: number = 42;
private d2: number = 42;
get value() {return 0 }
~~~~~
!!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
set value(v: number) { }
~~~~~
!!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
}
class MyDerived extends MyBase {
foo() {
super["m1"]("hi"); // Should be allowed, method on base prototype
var l2 = super["m1"].bind(this); // Should be allowed, can access properties as well as invoke
var x: (a: string) => string = super["m1"]; // Should be allowed, can assign to var with compatible signature
super["m2"].bind(this); // Should error, instance property, not a public instance member function
super["p1"](); // Should error, private not public instance member function
var l1 = super["d1"]; // Should error, instance data property not a public instance member function
var l1 = super["d2"]; // Should error, instance data property not a public instance member function
super["m1"] = function (a: string) { return ""; }; // Should be allowed, we will not restrict assignment
super["value"] = 0; // Should error, instance data property not a public instance member function
var z = super["value"]; // Should error, instance data property not a public instance member function
}
}

View File

@ -0,0 +1,84 @@
//// [superElementAccess.ts]
class MyBase {
m1(a: string) { return a; }
private p1() { }
m2: () => void = function () { }
d1: number = 42;
private d2: number = 42;
get value() {return 0 }
set value(v: number) { }
}
class MyDerived extends MyBase {
foo() {
super["m1"]("hi"); // Should be allowed, method on base prototype
var l2 = super["m1"].bind(this); // Should be allowed, can access properties as well as invoke
var x: (a: string) => string = super["m1"]; // Should be allowed, can assign to var with compatible signature
super["m2"].bind(this); // Should error, instance property, not a public instance member function
super["p1"](); // Should error, private not public instance member function
var l1 = super["d1"]; // Should error, instance data property not a public instance member function
var l1 = super["d2"]; // Should error, instance data property not a public instance member function
super["m1"] = function (a: string) { return ""; }; // Should be allowed, we will not restrict assignment
super["value"] = 0; // Should error, instance data property not a public instance member function
var z = super["value"]; // Should error, instance data property not a public instance member function
}
}
//// [superElementAccess.js]
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var MyBase = /** @class */ (function () {
function MyBase() {
this.m2 = function () { };
this.d1 = 42;
this.d2 = 42;
}
MyBase.prototype.m1 = function (a) { return a; };
MyBase.prototype.p1 = function () { };
Object.defineProperty(MyBase.prototype, "value", {
get: function () { return 0; },
set: function (v) { },
enumerable: true,
configurable: true
});
return MyBase;
}());
var MyDerived = /** @class */ (function (_super) {
__extends(MyDerived, _super);
function MyDerived() {
return _super !== null && _super.apply(this, arguments) || this;
}
MyDerived.prototype.foo = function () {
_super.prototype["m1"].call(this, "hi"); // Should be allowed, method on base prototype
var l2 = (_a = _super.prototype["m1"]).bind.call(_a, this); // Should be allowed, can access properties as well as invoke
var x = _super.prototype["m1"]; // Should be allowed, can assign to var with compatible signature
(_b = _super.prototype["m2"]).bind.call(_b, this); // Should error, instance property, not a public instance member function
_super.prototype["p1"].call(this); // Should error, private not public instance member function
var l1 = _super.prototype["d1"]; // Should error, instance data property not a public instance member function
var l1 = _super.prototype["d2"]; // Should error, instance data property not a public instance member function
_super.prototype["m1"] = function (a) { return ""; }; // Should be allowed, we will not restrict assignment
_super.prototype["value"] = 0; // Should error, instance data property not a public instance member function
var z = _super.prototype["value"]; // Should error, instance data property not a public instance member function
var _a, _b;
};
return MyDerived;
}(MyBase));

View File

@ -0,0 +1,91 @@
=== tests/cases/compiler/superElementAccess.ts ===
class MyBase {
>MyBase : Symbol(MyBase, Decl(superElementAccess.ts, 0, 0))
m1(a: string) { return a; }
>m1 : Symbol(MyBase.m1, Decl(superElementAccess.ts, 0, 14))
>a : Symbol(a, Decl(superElementAccess.ts, 1, 7))
>a : Symbol(a, Decl(superElementAccess.ts, 1, 7))
private p1() { }
>p1 : Symbol(MyBase.p1, Decl(superElementAccess.ts, 1, 31))
m2: () => void = function () { }
>m2 : Symbol(MyBase.m2, Decl(superElementAccess.ts, 2, 20))
d1: number = 42;
>d1 : Symbol(MyBase.d1, Decl(superElementAccess.ts, 3, 36))
private d2: number = 42;
>d2 : Symbol(MyBase.d2, Decl(superElementAccess.ts, 4, 20))
get value() {return 0 }
>value : Symbol(MyBase.value, Decl(superElementAccess.ts, 5, 28), Decl(superElementAccess.ts, 6, 27))
set value(v: number) { }
>value : Symbol(MyBase.value, Decl(superElementAccess.ts, 5, 28), Decl(superElementAccess.ts, 6, 27))
>v : Symbol(v, Decl(superElementAccess.ts, 7, 14))
}
class MyDerived extends MyBase {
>MyDerived : Symbol(MyDerived, Decl(superElementAccess.ts, 8, 1))
>MyBase : Symbol(MyBase, Decl(superElementAccess.ts, 0, 0))
foo() {
>foo : Symbol(MyDerived.foo, Decl(superElementAccess.ts, 11, 32))
super["m1"]("hi"); // Should be allowed, method on base prototype
>super : Symbol(MyBase, Decl(superElementAccess.ts, 0, 0))
>"m1" : Symbol(MyBase.m1, Decl(superElementAccess.ts, 0, 14))
var l2 = super["m1"].bind(this); // Should be allowed, can access properties as well as invoke
>l2 : Symbol(l2, Decl(superElementAccess.ts, 16, 11))
>super["m1"].bind : Symbol(Function.bind, Decl(lib.d.ts, --, --))
>super : Symbol(MyBase, Decl(superElementAccess.ts, 0, 0))
>"m1" : Symbol(MyBase.m1, Decl(superElementAccess.ts, 0, 14))
>bind : Symbol(Function.bind, Decl(lib.d.ts, --, --))
>this : Symbol(MyDerived, Decl(superElementAccess.ts, 8, 1))
var x: (a: string) => string = super["m1"]; // Should be allowed, can assign to var with compatible signature
>x : Symbol(x, Decl(superElementAccess.ts, 18, 11))
>a : Symbol(a, Decl(superElementAccess.ts, 18, 16))
>super : Symbol(MyBase, Decl(superElementAccess.ts, 0, 0))
>"m1" : Symbol(MyBase.m1, Decl(superElementAccess.ts, 0, 14))
super["m2"].bind(this); // Should error, instance property, not a public instance member function
>super["m2"].bind : Symbol(Function.bind, Decl(lib.d.ts, --, --))
>super : Symbol(MyBase, Decl(superElementAccess.ts, 0, 0))
>"m2" : Symbol(MyBase.m2, Decl(superElementAccess.ts, 2, 20))
>bind : Symbol(Function.bind, Decl(lib.d.ts, --, --))
>this : Symbol(MyDerived, Decl(superElementAccess.ts, 8, 1))
super["p1"](); // Should error, private not public instance member function
>super : Symbol(MyBase, Decl(superElementAccess.ts, 0, 0))
>"p1" : Symbol(MyBase.p1, Decl(superElementAccess.ts, 1, 31))
var l1 = super["d1"]; // Should error, instance data property not a public instance member function
>l1 : Symbol(l1, Decl(superElementAccess.ts, 24, 11), Decl(superElementAccess.ts, 26, 11))
>super : Symbol(MyBase, Decl(superElementAccess.ts, 0, 0))
>"d1" : Symbol(MyBase.d1, Decl(superElementAccess.ts, 3, 36))
var l1 = super["d2"]; // Should error, instance data property not a public instance member function
>l1 : Symbol(l1, Decl(superElementAccess.ts, 24, 11), Decl(superElementAccess.ts, 26, 11))
>super : Symbol(MyBase, Decl(superElementAccess.ts, 0, 0))
>"d2" : Symbol(MyBase.d2, Decl(superElementAccess.ts, 4, 20))
super["m1"] = function (a: string) { return ""; }; // Should be allowed, we will not restrict assignment
>super : Symbol(MyBase, Decl(superElementAccess.ts, 0, 0))
>"m1" : Symbol(MyBase.m1, Decl(superElementAccess.ts, 0, 14))
>a : Symbol(a, Decl(superElementAccess.ts, 28, 32))
super["value"] = 0; // Should error, instance data property not a public instance member function
>super : Symbol(MyBase, Decl(superElementAccess.ts, 0, 0))
>"value" : Symbol(MyBase.value, Decl(superElementAccess.ts, 5, 28), Decl(superElementAccess.ts, 6, 27))
var z = super["value"]; // Should error, instance data property not a public instance member function
>z : Symbol(z, Decl(superElementAccess.ts, 32, 11))
>super : Symbol(MyBase, Decl(superElementAccess.ts, 0, 0))
>"value" : Symbol(MyBase.value, Decl(superElementAccess.ts, 5, 28), Decl(superElementAccess.ts, 6, 27))
}
}

View File

@ -0,0 +1,115 @@
=== tests/cases/compiler/superElementAccess.ts ===
class MyBase {
>MyBase : MyBase
m1(a: string) { return a; }
>m1 : (a: string) => string
>a : string
>a : string
private p1() { }
>p1 : () => void
m2: () => void = function () { }
>m2 : () => void
>function () { } : () => void
d1: number = 42;
>d1 : number
>42 : 42
private d2: number = 42;
>d2 : number
>42 : 42
get value() {return 0 }
>value : number
>0 : 0
set value(v: number) { }
>value : number
>v : number
}
class MyDerived extends MyBase {
>MyDerived : MyDerived
>MyBase : MyBase
foo() {
>foo : () => void
super["m1"]("hi"); // Should be allowed, method on base prototype
>super["m1"]("hi") : string
>super["m1"] : (a: string) => string
>super : MyBase
>"m1" : "m1"
>"hi" : "hi"
var l2 = super["m1"].bind(this); // Should be allowed, can access properties as well as invoke
>l2 : any
>super["m1"].bind(this) : any
>super["m1"].bind : (this: Function, thisArg: any, ...argArray: any[]) => any
>super["m1"] : (a: string) => string
>super : MyBase
>"m1" : "m1"
>bind : (this: Function, thisArg: any, ...argArray: any[]) => any
>this : this
var x: (a: string) => string = super["m1"]; // Should be allowed, can assign to var with compatible signature
>x : (a: string) => string
>a : string
>super["m1"] : (a: string) => string
>super : MyBase
>"m1" : "m1"
super["m2"].bind(this); // Should error, instance property, not a public instance member function
>super["m2"].bind(this) : any
>super["m2"].bind : (this: Function, thisArg: any, ...argArray: any[]) => any
>super["m2"] : () => void
>super : MyBase
>"m2" : "m2"
>bind : (this: Function, thisArg: any, ...argArray: any[]) => any
>this : this
super["p1"](); // Should error, private not public instance member function
>super["p1"]() : void
>super["p1"] : () => void
>super : MyBase
>"p1" : "p1"
var l1 = super["d1"]; // Should error, instance data property not a public instance member function
>l1 : number
>super["d1"] : number
>super : MyBase
>"d1" : "d1"
var l1 = super["d2"]; // Should error, instance data property not a public instance member function
>l1 : number
>super["d2"] : number
>super : MyBase
>"d2" : "d2"
super["m1"] = function (a: string) { return ""; }; // Should be allowed, we will not restrict assignment
>super["m1"] = function (a: string) { return ""; } : (a: string) => string
>super["m1"] : (a: string) => string
>super : MyBase
>"m1" : "m1"
>function (a: string) { return ""; } : (a: string) => string
>a : string
>"" : ""
super["value"] = 0; // Should error, instance data property not a public instance member function
>super["value"] = 0 : 0
>super["value"] : number
>super : MyBase
>"value" : "value"
>0 : 0
var z = super["value"]; // Should error, instance data property not a public instance member function
>z : number
>super["value"] : number
>super : MyBase
>"value" : "value"
}
}

View File

@ -63,7 +63,6 @@ var __extends = (this && this.__extends) || (function () {
};
})();
function foo() {
var _this = this;
// super in a non class context
var x = _super.;
var y = function () { return _super.; };
@ -93,10 +92,7 @@ var RegisteredUser = /** @class */ (function (_super) {
var x = function () { return _super.sayHello.call(_this); };
}
// super call in a lambda in a function expression in a constructor
(function () {
var _this = this;
return function () { return _super.; };
})();
(function () { return function () { return _super.; }; })();
return _this;
}
RegisteredUser.prototype.sayHello = function () {
@ -108,13 +104,9 @@ var RegisteredUser = /** @class */ (function (_super) {
var x = function () { return _super.sayHello.call(_this); };
}
// super call in a lambda in a function expression in a constructor
(function () {
var _this = this;
return function () { return _super.; };
})();
(function () { return function () { return _super.; }; })();
};
RegisteredUser.staticFunction = function () {
var _this = this;
// super in static functions
var s = _super.;
var x = function () { return _super.; };

View File

@ -133,7 +133,6 @@ var RegisteredUser3 = /** @class */ (function (_super) {
return _this;
}
RegisteredUser3.prototype.sayHello = function () {
var _this = this;
// super property in a nested lambda in a method
var superName = function () { return function () { return function () { return _super.prototype.name; }; }; };
};
@ -149,7 +148,6 @@ var RegisteredUser4 = /** @class */ (function (_super) {
return _this;
}
RegisteredUser4.prototype.sayHello = function () {
var _this = this;
// super in a nested lambda in a method
var x = function () { return function () { return _super.prototype.; }; };
};

View File

@ -69,15 +69,16 @@ var MyDerived = /** @class */ (function (_super) {
}
MyDerived.prototype.foo = function () {
_super.prototype.m1.call(this, "hi"); // Should be allowed, method on base prototype
var l2 = _super.prototype.m1.bind(this); // Should be allowed, can access properties as well as invoke
var l2 = (_a = _super.prototype.m1).bind.call(_a, this); // Should be allowed, can access properties as well as invoke
var x = _super.prototype.m1; // Should be allowed, can assign to var with compatible signature
_super.prototype.m2.bind(this); // Should error, instance property, not a public instance member function
(_b = _super.prototype.m2).bind.call(_b, this); // Should error, instance property, not a public instance member function
_super.prototype.p1.call(this); // Should error, private not public instance member function
var l1 = _super.prototype.d1; // Should error, instance data property not a public instance member function
var l1 = _super.prototype.d2; // Should error, instance data property not a public instance member function
_super.prototype.m1 = function (a) { return ""; }; // Should be allowed, we will not restrict assignment
_super.prototype.value = 0; // Should error, instance data property not a public instance member function
var z = _super.prototype.value; // Should error, instance data property not a public instance member function
var _a, _b;
};
return MyDerived;
}(MyBase));

View File

@ -0,0 +1,53 @@
//// [superPropertyElementNoUnusedLexicalThisCapture.ts]
class A { x() {} }
class B extends A {
constructor() {
super();
}
foo() {
return () => {
super.x;
}
}
bar() {
return () => {
super["x"];
}
}
}
//// [superPropertyElementNoUnusedLexicalThisCapture.js]
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var A = /** @class */ (function () {
function A() {
}
A.prototype.x = function () { };
return A;
}());
var B = /** @class */ (function (_super) {
__extends(B, _super);
function B() {
return _super.call(this) || this;
}
B.prototype.foo = function () {
return function () {
_super.prototype.x;
};
};
B.prototype.bar = function () {
return function () {
_super.prototype["x"];
};
};
return B;
}(A));

View File

@ -0,0 +1,33 @@
=== tests/cases/compiler/superPropertyElementNoUnusedLexicalThisCapture.ts ===
class A { x() {} }
>A : Symbol(A, Decl(superPropertyElementNoUnusedLexicalThisCapture.ts, 0, 0))
>x : Symbol(A.x, Decl(superPropertyElementNoUnusedLexicalThisCapture.ts, 0, 9))
class B extends A {
>B : Symbol(B, Decl(superPropertyElementNoUnusedLexicalThisCapture.ts, 0, 18))
>A : Symbol(A, Decl(superPropertyElementNoUnusedLexicalThisCapture.ts, 0, 0))
constructor() {
super();
>super : Symbol(A, Decl(superPropertyElementNoUnusedLexicalThisCapture.ts, 0, 0))
}
foo() {
>foo : Symbol(B.foo, Decl(superPropertyElementNoUnusedLexicalThisCapture.ts, 5, 5))
return () => {
super.x;
>super.x : Symbol(A.x, Decl(superPropertyElementNoUnusedLexicalThisCapture.ts, 0, 9))
>super : Symbol(A, Decl(superPropertyElementNoUnusedLexicalThisCapture.ts, 0, 0))
>x : Symbol(A.x, Decl(superPropertyElementNoUnusedLexicalThisCapture.ts, 0, 9))
}
}
bar() {
>bar : Symbol(B.bar, Decl(superPropertyElementNoUnusedLexicalThisCapture.ts, 10, 5))
return () => {
super["x"];
>super : Symbol(A, Decl(superPropertyElementNoUnusedLexicalThisCapture.ts, 0, 0))
>"x" : Symbol(A.x, Decl(superPropertyElementNoUnusedLexicalThisCapture.ts, 0, 9))
}
}
}

View File

@ -0,0 +1,39 @@
=== tests/cases/compiler/superPropertyElementNoUnusedLexicalThisCapture.ts ===
class A { x() {} }
>A : A
>x : () => void
class B extends A {
>B : B
>A : A
constructor() {
super();
>super() : void
>super : typeof A
}
foo() {
>foo : () => () => void
return () => {
>() => { super.x; } : () => void
super.x;
>super.x : () => void
>super : A
>x : () => void
}
}
bar() {
>bar : () => () => void
return () => {
>() => { super["x"]; } : () => void
super["x"];
>super["x"] : () => void
>super : A
>"x" : "x"
}
}
}

View File

@ -0,0 +1,20 @@
class Foo {
bar(): void {}
}
class Bar extends Foo {
x: Number;
constructor() {
super();
this.x = 2;
}
bar() {
super.bar();
(super.bar as any)();
}
}
let b = new Bar();
b.bar()

View File

@ -0,0 +1,36 @@
class MyBase {
m1(a: string) { return a; }
private p1() { }
m2: () => void = function () { }
d1: number = 42;
private d2: number = 42;
get value() {return 0 }
set value(v: number) { }
}
class MyDerived extends MyBase {
foo() {
super["m1"]("hi"); // Should be allowed, method on base prototype
var l2 = super["m1"].bind(this); // Should be allowed, can access properties as well as invoke
var x: (a: string) => string = super["m1"]; // Should be allowed, can assign to var with compatible signature
super["m2"].bind(this); // Should error, instance property, not a public instance member function
super["p1"](); // Should error, private not public instance member function
var l1 = super["d1"]; // Should error, instance data property not a public instance member function
var l1 = super["d2"]; // Should error, instance data property not a public instance member function
super["m1"] = function (a: string) { return ""; }; // Should be allowed, we will not restrict assignment
super["value"] = 0; // Should error, instance data property not a public instance member function
var z = super["value"]; // Should error, instance data property not a public instance member function
}
}

View File

@ -0,0 +1,17 @@
class A { x() {} }
class B extends A {
constructor() {
super();
}
foo() {
return () => {
super.x;
}
}
bar() {
return () => {
super["x"];
}
}
}