mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
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:
parent
6f28b0ac25
commit
64305edbce
@ -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;
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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() {
|
||||
}
|
||||
|
||||
@ -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() {
|
||||
}
|
||||
|
||||
54
tests/baselines/reference/superAccessCastedCall.js
Normal file
54
tests/baselines/reference/superAccessCastedCall.js
Normal 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();
|
||||
50
tests/baselines/reference/superAccessCastedCall.symbols
Normal file
50
tests/baselines/reference/superAccessCastedCall.symbols
Normal 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))
|
||||
|
||||
59
tests/baselines/reference/superAccessCastedCall.types
Normal file
59
tests/baselines/reference/superAccessCastedCall.types
Normal 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
|
||||
|
||||
44
tests/baselines/reference/superElementAccess.errors.txt
Normal file
44
tests/baselines/reference/superElementAccess.errors.txt
Normal 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
|
||||
}
|
||||
}
|
||||
84
tests/baselines/reference/superElementAccess.js
Normal file
84
tests/baselines/reference/superElementAccess.js
Normal 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));
|
||||
91
tests/baselines/reference/superElementAccess.symbols
Normal file
91
tests/baselines/reference/superElementAccess.symbols
Normal 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))
|
||||
}
|
||||
}
|
||||
115
tests/baselines/reference/superElementAccess.types
Normal file
115
tests/baselines/reference/superElementAccess.types
Normal 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"
|
||||
}
|
||||
}
|
||||
@ -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.; };
|
||||
|
||||
@ -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.; }; };
|
||||
};
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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));
|
||||
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
20
tests/cases/compiler/superAccessCastedCall.ts
Normal file
20
tests/cases/compiler/superAccessCastedCall.ts
Normal 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()
|
||||
36
tests/cases/compiler/superElementAccess.ts
Normal file
36
tests/cases/compiler/superElementAccess.ts
Normal 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
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
class A { x() {} }
|
||||
|
||||
class B extends A {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
foo() {
|
||||
return () => {
|
||||
super.x;
|
||||
}
|
||||
}
|
||||
bar() {
|
||||
return () => {
|
||||
super["x"];
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user