Fix crash when this is typed as a generic T with no type constraints (#47991)

* fix this type validations for protected fields

* update previous baselines

* add new tests and baselines

* ClassOrInterface can be returned as enclosingClass

* inline function code and remove unnecessary blank lines

* refactor enclosingClass checks
This commit is contained in:
jihndai 2022-03-04 21:08:44 -04:00 committed by GitHub
parent 82fc9b19ba
commit 857889a4e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 1177 additions and 12 deletions

View File

@ -20644,7 +20644,7 @@ namespace ts {
// Return true if the given class derives from each of the declaring classes of the protected
// constituents of the given property.
function isClassDerivedFromDeclaringClasses(checkClass: Type, prop: Symbol, writing: boolean) {
function isClassDerivedFromDeclaringClasses<T extends Type>(checkClass: T, prop: Symbol, writing: boolean) {
return forEachProperty(prop, p => getDeclarationModifierFlagsFromSymbol(p, writing) & ModifierFlags.Protected ?
!hasBaseType(checkClass, getDeclaringClass(p)) : false) ? undefined : checkClass;
}
@ -28396,14 +28396,15 @@ namespace ts {
// of the property as base classes
let enclosingClass = forEachEnclosingClass(location, enclosingDeclaration => {
const enclosingClass = getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingDeclaration)!) as InterfaceType;
return isClassDerivedFromDeclaringClasses(enclosingClass, prop, writing) ? enclosingClass : undefined;
return isClassDerivedFromDeclaringClasses(enclosingClass, prop, writing);
});
// A protected property is accessible if the property is within the declaring class or classes derived from it
if (!enclosingClass) {
// allow PropertyAccessibility if context is in function with this parameter
// static member access is disallow
let thisParameter: ParameterDeclaration | undefined;
if (flags & ModifierFlags.Static || !(thisParameter = getThisParameterFromNodeContext(location)) || !thisParameter.type) {
// static member access is disallowed
enclosingClass = getEnclosingClassFromThisParameter(location);
enclosingClass = enclosingClass && isClassDerivedFromDeclaringClasses(enclosingClass, prop, writing);
if (flags & ModifierFlags.Static || !enclosingClass) {
if (errorNode) {
error(errorNode,
Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses,
@ -28412,9 +28413,6 @@ namespace ts {
}
return false;
}
const thisType = getTypeFromTypeNode(thisParameter.type);
enclosingClass = (((thisType.flags & TypeFlags.TypeParameter) ? getConstraintOfTypeParameter(thisType as TypeParameter) : thisType) as TypeReference).target;
}
// No further restrictions for static properties
if (flags & ModifierFlags.Static) {
@ -28435,6 +28433,18 @@ namespace ts {
return true;
}
function getEnclosingClassFromThisParameter(node: Node): InterfaceType | undefined {
const thisParameter = getThisParameterFromNodeContext(node);
let thisType = thisParameter?.type && getTypeFromTypeNode(thisParameter.type);
if (thisType && thisType.flags & TypeFlags.TypeParameter) {
thisType = getConstraintOfTypeParameter(thisType as TypeParameter);
}
if (thisType && getObjectFlags(thisType) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference)) {
return getTargetType(thisType) as InterfaceType;
}
return undefined;
}
function getThisParameterFromNodeContext(node: Node) {
const thisContainer = getThisContainer(node, /* includeArrowFunctions */ false);
return thisContainer && isFunctionLike(thisContainer) ? getThisParameter(thisContainer) : undefined;

View File

@ -0,0 +1,147 @@
tests/cases/compiler/protectedMembersThisParameter.ts(9,9): error TS2445: Property 'secret' is protected and only accessible within class 'Message' and its subclasses.
tests/cases/compiler/protectedMembersThisParameter.ts(30,7): error TS2445: Property 'b' is protected and only accessible within class 'B' and its subclasses.
tests/cases/compiler/protectedMembersThisParameter.ts(41,7): error TS2446: Property 'a' is protected and only accessible through an instance of class 'C'. This is an instance of class 'B'.
tests/cases/compiler/protectedMembersThisParameter.ts(42,7): error TS2445: Property 'b' is protected and only accessible within class 'B' and its subclasses.
tests/cases/compiler/protectedMembersThisParameter.ts(46,7): error TS2445: Property 'a' is protected and only accessible within class 'A' and its subclasses.
tests/cases/compiler/protectedMembersThisParameter.ts(47,7): error TS2445: Property 'b' is protected and only accessible within class 'B' and its subclasses.
tests/cases/compiler/protectedMembersThisParameter.ts(51,7): error TS2445: Property 'a' is protected and only accessible within class 'A' and its subclasses.
tests/cases/compiler/protectedMembersThisParameter.ts(52,7): error TS2445: Property 'b' is protected and only accessible within class 'B' and its subclasses.
tests/cases/compiler/protectedMembersThisParameter.ts(55,7): error TS2445: Property 'a' is protected and only accessible within class 'A' and its subclasses.
tests/cases/compiler/protectedMembersThisParameter.ts(56,7): error TS2445: Property 'b' is protected and only accessible within class 'B' and its subclasses.
tests/cases/compiler/protectedMembersThisParameter.ts(64,9): error TS2445: Property 'd1' is protected and only accessible within class 'D1' and its subclasses.
tests/cases/compiler/protectedMembersThisParameter.ts(68,9): error TS2445: Property 'd1' is protected and only accessible within class 'D1' and its subclasses.
tests/cases/compiler/protectedMembersThisParameter.ts(76,9): error TS2445: Property 'd' is protected and only accessible within class 'D2' and its subclasses.
tests/cases/compiler/protectedMembersThisParameter.ts(77,9): error TS2445: Property 'd2' is protected and only accessible within class 'D2' and its subclasses.
tests/cases/compiler/protectedMembersThisParameter.ts(80,9): error TS2445: Property 'd' is protected and only accessible within class 'D2' and its subclasses.
tests/cases/compiler/protectedMembersThisParameter.ts(81,9): error TS2445: Property 'd2' is protected and only accessible within class 'D2' and its subclasses.
==== tests/cases/compiler/protectedMembersThisParameter.ts (16 errors) ====
class Message {
protected secret(): void {}
}
class MessageWrapper {
message: Message = new Message();
wrap<T>() {
let m = this.message;
let f = function(this: T) {
m.secret(); // should error
~~~~~~
!!! error TS2445: Property 'secret' is protected and only accessible within class 'Message' and its subclasses.
}
}
}
class A {
protected a() {}
}
class B extends A {
protected b() {}
}
class C extends A {
protected c() {}
}
class Z {
protected z() {}
}
function bA<T extends A>(this: T, arg: B) {
this.a();
arg.a();
arg.b(); // should error to avoid cross-hierarchy protected access https://www.typescriptlang.org/docs/handbook/2/classes.html#cross-hierarchy-protected-access
~
!!! error TS2445: Property 'b' is protected and only accessible within class 'B' and its subclasses.
}
function bB<T extends B>(this: T, arg: B) {
this.a();
this.b();
arg.a();
arg.b();
}
function bC<T extends C>(this: T, arg: B) {
this.a();
this.c();
arg.a(); // should error
~
!!! error TS2446: Property 'a' is protected and only accessible through an instance of class 'C'. This is an instance of class 'B'.
arg.b(); // should error
~
!!! error TS2445: Property 'b' is protected and only accessible within class 'B' and its subclasses.
}
function bZ<T extends Z>(this: T, arg: B) {
this.z();
arg.a(); // should error
~
!!! error TS2445: Property 'a' is protected and only accessible within class 'A' and its subclasses.
arg.b(); // should error
~
!!! error TS2445: Property 'b' is protected and only accessible within class 'B' and its subclasses.
}
function bString<T extends string>(this: T, arg: B) {
this.toLowerCase();
arg.a(); // should error
~
!!! error TS2445: Property 'a' is protected and only accessible within class 'A' and its subclasses.
arg.b(); // should error
~
!!! error TS2445: Property 'b' is protected and only accessible within class 'B' and its subclasses.
}
function bAny<T>(this: T, arg: B) {
arg.a(); // should error
~
!!! error TS2445: Property 'a' is protected and only accessible within class 'A' and its subclasses.
arg.b(); // should error
~
!!! error TS2445: Property 'b' is protected and only accessible within class 'B' and its subclasses.
}
class D {
protected d() {}
derived1(arg: D1) {
arg.d();
arg.d1(); // should error
~~
!!! error TS2445: Property 'd1' is protected and only accessible within class 'D1' and its subclasses.
}
derived1ThisD(this: D, arg: D1) {
arg.d();
arg.d1(); // should error
~~
!!! error TS2445: Property 'd1' is protected and only accessible within class 'D1' and its subclasses.
}
derived1ThisD1(this: D1, arg: D1) {
arg.d();
arg.d1();
}
derived2(arg: D2) {
arg.d(); // should error because of overridden method in D2
~
!!! error TS2445: Property 'd' is protected and only accessible within class 'D2' and its subclasses.
arg.d2(); // should error
~~
!!! error TS2445: Property 'd2' is protected and only accessible within class 'D2' and its subclasses.
}
derived2ThisD(this: D, arg: D2) {
arg.d(); // should error because of overridden method in D2
~
!!! error TS2445: Property 'd' is protected and only accessible within class 'D2' and its subclasses.
arg.d2(); // should error
~~
!!! error TS2445: Property 'd2' is protected and only accessible within class 'D2' and its subclasses.
}
derived2ThisD2(this: D2, arg: D2) {
arg.d();
arg.d2();
}
}
class D1 extends D {
protected d1() {}
}
class D2 extends D {
protected d() {}
protected d2() {}
}

View File

@ -0,0 +1,238 @@
//// [protectedMembersThisParameter.ts]
class Message {
protected secret(): void {}
}
class MessageWrapper {
message: Message = new Message();
wrap<T>() {
let m = this.message;
let f = function(this: T) {
m.secret(); // should error
}
}
}
class A {
protected a() {}
}
class B extends A {
protected b() {}
}
class C extends A {
protected c() {}
}
class Z {
protected z() {}
}
function bA<T extends A>(this: T, arg: B) {
this.a();
arg.a();
arg.b(); // should error to avoid cross-hierarchy protected access https://www.typescriptlang.org/docs/handbook/2/classes.html#cross-hierarchy-protected-access
}
function bB<T extends B>(this: T, arg: B) {
this.a();
this.b();
arg.a();
arg.b();
}
function bC<T extends C>(this: T, arg: B) {
this.a();
this.c();
arg.a(); // should error
arg.b(); // should error
}
function bZ<T extends Z>(this: T, arg: B) {
this.z();
arg.a(); // should error
arg.b(); // should error
}
function bString<T extends string>(this: T, arg: B) {
this.toLowerCase();
arg.a(); // should error
arg.b(); // should error
}
function bAny<T>(this: T, arg: B) {
arg.a(); // should error
arg.b(); // should error
}
class D {
protected d() {}
derived1(arg: D1) {
arg.d();
arg.d1(); // should error
}
derived1ThisD(this: D, arg: D1) {
arg.d();
arg.d1(); // should error
}
derived1ThisD1(this: D1, arg: D1) {
arg.d();
arg.d1();
}
derived2(arg: D2) {
arg.d(); // should error because of overridden method in D2
arg.d2(); // should error
}
derived2ThisD(this: D, arg: D2) {
arg.d(); // should error because of overridden method in D2
arg.d2(); // should error
}
derived2ThisD2(this: D2, arg: D2) {
arg.d();
arg.d2();
}
}
class D1 extends D {
protected d1() {}
}
class D2 extends D {
protected d() {}
protected d2() {}
}
//// [protectedMembersThisParameter.js]
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var Message = /** @class */ (function () {
function Message() {
}
Message.prototype.secret = function () { };
return Message;
}());
var MessageWrapper = /** @class */ (function () {
function MessageWrapper() {
this.message = new Message();
}
MessageWrapper.prototype.wrap = function () {
var m = this.message;
var f = function () {
m.secret(); // should error
};
};
return MessageWrapper;
}());
var A = /** @class */ (function () {
function A() {
}
A.prototype.a = function () { };
return A;
}());
var B = /** @class */ (function (_super) {
__extends(B, _super);
function B() {
return _super !== null && _super.apply(this, arguments) || this;
}
B.prototype.b = function () { };
return B;
}(A));
var C = /** @class */ (function (_super) {
__extends(C, _super);
function C() {
return _super !== null && _super.apply(this, arguments) || this;
}
C.prototype.c = function () { };
return C;
}(A));
var Z = /** @class */ (function () {
function Z() {
}
Z.prototype.z = function () { };
return Z;
}());
function bA(arg) {
this.a();
arg.a();
arg.b(); // should error to avoid cross-hierarchy protected access https://www.typescriptlang.org/docs/handbook/2/classes.html#cross-hierarchy-protected-access
}
function bB(arg) {
this.a();
this.b();
arg.a();
arg.b();
}
function bC(arg) {
this.a();
this.c();
arg.a(); // should error
arg.b(); // should error
}
function bZ(arg) {
this.z();
arg.a(); // should error
arg.b(); // should error
}
function bString(arg) {
this.toLowerCase();
arg.a(); // should error
arg.b(); // should error
}
function bAny(arg) {
arg.a(); // should error
arg.b(); // should error
}
var D = /** @class */ (function () {
function D() {
}
D.prototype.d = function () { };
D.prototype.derived1 = function (arg) {
arg.d();
arg.d1(); // should error
};
D.prototype.derived1ThisD = function (arg) {
arg.d();
arg.d1(); // should error
};
D.prototype.derived1ThisD1 = function (arg) {
arg.d();
arg.d1();
};
D.prototype.derived2 = function (arg) {
arg.d(); // should error because of overridden method in D2
arg.d2(); // should error
};
D.prototype.derived2ThisD = function (arg) {
arg.d(); // should error because of overridden method in D2
arg.d2(); // should error
};
D.prototype.derived2ThisD2 = function (arg) {
arg.d();
arg.d2();
};
return D;
}());
var D1 = /** @class */ (function (_super) {
__extends(D1, _super);
function D1() {
return _super !== null && _super.apply(this, arguments) || this;
}
D1.prototype.d1 = function () { };
return D1;
}(D));
var D2 = /** @class */ (function (_super) {
__extends(D2, _super);
function D2() {
return _super !== null && _super.apply(this, arguments) || this;
}
D2.prototype.d = function () { };
D2.prototype.d2 = function () { };
return D2;
}(D));

View File

@ -0,0 +1,338 @@
=== tests/cases/compiler/protectedMembersThisParameter.ts ===
class Message {
>Message : Symbol(Message, Decl(protectedMembersThisParameter.ts, 0, 0))
protected secret(): void {}
>secret : Symbol(Message.secret, Decl(protectedMembersThisParameter.ts, 0, 15))
}
class MessageWrapper {
>MessageWrapper : Symbol(MessageWrapper, Decl(protectedMembersThisParameter.ts, 2, 1))
message: Message = new Message();
>message : Symbol(MessageWrapper.message, Decl(protectedMembersThisParameter.ts, 3, 22))
>Message : Symbol(Message, Decl(protectedMembersThisParameter.ts, 0, 0))
>Message : Symbol(Message, Decl(protectedMembersThisParameter.ts, 0, 0))
wrap<T>() {
>wrap : Symbol(MessageWrapper.wrap, Decl(protectedMembersThisParameter.ts, 4, 35))
>T : Symbol(T, Decl(protectedMembersThisParameter.ts, 5, 7))
let m = this.message;
>m : Symbol(m, Decl(protectedMembersThisParameter.ts, 6, 7))
>this.message : Symbol(MessageWrapper.message, Decl(protectedMembersThisParameter.ts, 3, 22))
>this : Symbol(MessageWrapper, Decl(protectedMembersThisParameter.ts, 2, 1))
>message : Symbol(MessageWrapper.message, Decl(protectedMembersThisParameter.ts, 3, 22))
let f = function(this: T) {
>f : Symbol(f, Decl(protectedMembersThisParameter.ts, 7, 7))
>this : Symbol(this, Decl(protectedMembersThisParameter.ts, 7, 21))
>T : Symbol(T, Decl(protectedMembersThisParameter.ts, 5, 7))
m.secret(); // should error
>m.secret : Symbol(Message.secret, Decl(protectedMembersThisParameter.ts, 0, 15))
>m : Symbol(m, Decl(protectedMembersThisParameter.ts, 6, 7))
>secret : Symbol(Message.secret, Decl(protectedMembersThisParameter.ts, 0, 15))
}
}
}
class A {
>A : Symbol(A, Decl(protectedMembersThisParameter.ts, 11, 1))
protected a() {}
>a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
}
class B extends A {
>B : Symbol(B, Decl(protectedMembersThisParameter.ts, 15, 1))
>A : Symbol(A, Decl(protectedMembersThisParameter.ts, 11, 1))
protected b() {}
>b : Symbol(B.b, Decl(protectedMembersThisParameter.ts, 16, 19))
}
class C extends A {
>C : Symbol(C, Decl(protectedMembersThisParameter.ts, 18, 1))
>A : Symbol(A, Decl(protectedMembersThisParameter.ts, 11, 1))
protected c() {}
>c : Symbol(C.c, Decl(protectedMembersThisParameter.ts, 19, 19))
}
class Z {
>Z : Symbol(Z, Decl(protectedMembersThisParameter.ts, 21, 1))
protected z() {}
>z : Symbol(Z.z, Decl(protectedMembersThisParameter.ts, 22, 9))
}
function bA<T extends A>(this: T, arg: B) {
>bA : Symbol(bA, Decl(protectedMembersThisParameter.ts, 24, 1))
>T : Symbol(T, Decl(protectedMembersThisParameter.ts, 26, 12))
>A : Symbol(A, Decl(protectedMembersThisParameter.ts, 11, 1))
>this : Symbol(this, Decl(protectedMembersThisParameter.ts, 26, 25))
>T : Symbol(T, Decl(protectedMembersThisParameter.ts, 26, 12))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 26, 33))
>B : Symbol(B, Decl(protectedMembersThisParameter.ts, 15, 1))
this.a();
>this.a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
>this : Symbol(this, Decl(protectedMembersThisParameter.ts, 26, 25))
>a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
arg.a();
>arg.a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 26, 33))
>a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
arg.b(); // should error to avoid cross-hierarchy protected access https://www.typescriptlang.org/docs/handbook/2/classes.html#cross-hierarchy-protected-access
>arg.b : Symbol(B.b, Decl(protectedMembersThisParameter.ts, 16, 19))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 26, 33))
>b : Symbol(B.b, Decl(protectedMembersThisParameter.ts, 16, 19))
}
function bB<T extends B>(this: T, arg: B) {
>bB : Symbol(bB, Decl(protectedMembersThisParameter.ts, 30, 1))
>T : Symbol(T, Decl(protectedMembersThisParameter.ts, 31, 12))
>B : Symbol(B, Decl(protectedMembersThisParameter.ts, 15, 1))
>this : Symbol(this, Decl(protectedMembersThisParameter.ts, 31, 25))
>T : Symbol(T, Decl(protectedMembersThisParameter.ts, 31, 12))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 31, 33))
>B : Symbol(B, Decl(protectedMembersThisParameter.ts, 15, 1))
this.a();
>this.a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
>this : Symbol(this, Decl(protectedMembersThisParameter.ts, 31, 25))
>a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
this.b();
>this.b : Symbol(B.b, Decl(protectedMembersThisParameter.ts, 16, 19))
>this : Symbol(this, Decl(protectedMembersThisParameter.ts, 31, 25))
>b : Symbol(B.b, Decl(protectedMembersThisParameter.ts, 16, 19))
arg.a();
>arg.a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 31, 33))
>a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
arg.b();
>arg.b : Symbol(B.b, Decl(protectedMembersThisParameter.ts, 16, 19))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 31, 33))
>b : Symbol(B.b, Decl(protectedMembersThisParameter.ts, 16, 19))
}
function bC<T extends C>(this: T, arg: B) {
>bC : Symbol(bC, Decl(protectedMembersThisParameter.ts, 36, 1))
>T : Symbol(T, Decl(protectedMembersThisParameter.ts, 37, 12))
>C : Symbol(C, Decl(protectedMembersThisParameter.ts, 18, 1))
>this : Symbol(this, Decl(protectedMembersThisParameter.ts, 37, 25))
>T : Symbol(T, Decl(protectedMembersThisParameter.ts, 37, 12))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 37, 33))
>B : Symbol(B, Decl(protectedMembersThisParameter.ts, 15, 1))
this.a();
>this.a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
>this : Symbol(this, Decl(protectedMembersThisParameter.ts, 37, 25))
>a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
this.c();
>this.c : Symbol(C.c, Decl(protectedMembersThisParameter.ts, 19, 19))
>this : Symbol(this, Decl(protectedMembersThisParameter.ts, 37, 25))
>c : Symbol(C.c, Decl(protectedMembersThisParameter.ts, 19, 19))
arg.a(); // should error
>arg.a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 37, 33))
>a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
arg.b(); // should error
>arg.b : Symbol(B.b, Decl(protectedMembersThisParameter.ts, 16, 19))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 37, 33))
>b : Symbol(B.b, Decl(protectedMembersThisParameter.ts, 16, 19))
}
function bZ<T extends Z>(this: T, arg: B) {
>bZ : Symbol(bZ, Decl(protectedMembersThisParameter.ts, 42, 1))
>T : Symbol(T, Decl(protectedMembersThisParameter.ts, 43, 12))
>Z : Symbol(Z, Decl(protectedMembersThisParameter.ts, 21, 1))
>this : Symbol(this, Decl(protectedMembersThisParameter.ts, 43, 25))
>T : Symbol(T, Decl(protectedMembersThisParameter.ts, 43, 12))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 43, 33))
>B : Symbol(B, Decl(protectedMembersThisParameter.ts, 15, 1))
this.z();
>this.z : Symbol(Z.z, Decl(protectedMembersThisParameter.ts, 22, 9))
>this : Symbol(this, Decl(protectedMembersThisParameter.ts, 43, 25))
>z : Symbol(Z.z, Decl(protectedMembersThisParameter.ts, 22, 9))
arg.a(); // should error
>arg.a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 43, 33))
>a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
arg.b(); // should error
>arg.b : Symbol(B.b, Decl(protectedMembersThisParameter.ts, 16, 19))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 43, 33))
>b : Symbol(B.b, Decl(protectedMembersThisParameter.ts, 16, 19))
}
function bString<T extends string>(this: T, arg: B) {
>bString : Symbol(bString, Decl(protectedMembersThisParameter.ts, 47, 1))
>T : Symbol(T, Decl(protectedMembersThisParameter.ts, 48, 17))
>this : Symbol(this, Decl(protectedMembersThisParameter.ts, 48, 35))
>T : Symbol(T, Decl(protectedMembersThisParameter.ts, 48, 17))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 48, 43))
>B : Symbol(B, Decl(protectedMembersThisParameter.ts, 15, 1))
this.toLowerCase();
>this.toLowerCase : Symbol(String.toLowerCase, Decl(lib.es5.d.ts, --, --))
>this : Symbol(this, Decl(protectedMembersThisParameter.ts, 48, 35))
>toLowerCase : Symbol(String.toLowerCase, Decl(lib.es5.d.ts, --, --))
arg.a(); // should error
>arg.a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 48, 43))
>a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
arg.b(); // should error
>arg.b : Symbol(B.b, Decl(protectedMembersThisParameter.ts, 16, 19))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 48, 43))
>b : Symbol(B.b, Decl(protectedMembersThisParameter.ts, 16, 19))
}
function bAny<T>(this: T, arg: B) {
>bAny : Symbol(bAny, Decl(protectedMembersThisParameter.ts, 52, 1))
>T : Symbol(T, Decl(protectedMembersThisParameter.ts, 53, 14))
>this : Symbol(this, Decl(protectedMembersThisParameter.ts, 53, 17))
>T : Symbol(T, Decl(protectedMembersThisParameter.ts, 53, 14))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 53, 25))
>B : Symbol(B, Decl(protectedMembersThisParameter.ts, 15, 1))
arg.a(); // should error
>arg.a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 53, 25))
>a : Symbol(A.a, Decl(protectedMembersThisParameter.ts, 13, 9))
arg.b(); // should error
>arg.b : Symbol(B.b, Decl(protectedMembersThisParameter.ts, 16, 19))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 53, 25))
>b : Symbol(B.b, Decl(protectedMembersThisParameter.ts, 16, 19))
}
class D {
>D : Symbol(D, Decl(protectedMembersThisParameter.ts, 56, 1))
protected d() {}
>d : Symbol(D.d, Decl(protectedMembersThisParameter.ts, 58, 9))
derived1(arg: D1) {
>derived1 : Symbol(D.derived1, Decl(protectedMembersThisParameter.ts, 59, 18))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 61, 11))
>D1 : Symbol(D1, Decl(protectedMembersThisParameter.ts, 86, 1))
arg.d();
>arg.d : Symbol(D.d, Decl(protectedMembersThisParameter.ts, 58, 9))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 61, 11))
>d : Symbol(D.d, Decl(protectedMembersThisParameter.ts, 58, 9))
arg.d1(); // should error
>arg.d1 : Symbol(D1.d1, Decl(protectedMembersThisParameter.ts, 87, 20))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 61, 11))
>d1 : Symbol(D1.d1, Decl(protectedMembersThisParameter.ts, 87, 20))
}
derived1ThisD(this: D, arg: D1) {
>derived1ThisD : Symbol(D.derived1ThisD, Decl(protectedMembersThisParameter.ts, 64, 3))
>this : Symbol(this, Decl(protectedMembersThisParameter.ts, 65, 16))
>D : Symbol(D, Decl(protectedMembersThisParameter.ts, 56, 1))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 65, 24))
>D1 : Symbol(D1, Decl(protectedMembersThisParameter.ts, 86, 1))
arg.d();
>arg.d : Symbol(D.d, Decl(protectedMembersThisParameter.ts, 58, 9))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 65, 24))
>d : Symbol(D.d, Decl(protectedMembersThisParameter.ts, 58, 9))
arg.d1(); // should error
>arg.d1 : Symbol(D1.d1, Decl(protectedMembersThisParameter.ts, 87, 20))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 65, 24))
>d1 : Symbol(D1.d1, Decl(protectedMembersThisParameter.ts, 87, 20))
}
derived1ThisD1(this: D1, arg: D1) {
>derived1ThisD1 : Symbol(D.derived1ThisD1, Decl(protectedMembersThisParameter.ts, 68, 3))
>this : Symbol(this, Decl(protectedMembersThisParameter.ts, 69, 17))
>D1 : Symbol(D1, Decl(protectedMembersThisParameter.ts, 86, 1))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 69, 26))
>D1 : Symbol(D1, Decl(protectedMembersThisParameter.ts, 86, 1))
arg.d();
>arg.d : Symbol(D.d, Decl(protectedMembersThisParameter.ts, 58, 9))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 69, 26))
>d : Symbol(D.d, Decl(protectedMembersThisParameter.ts, 58, 9))
arg.d1();
>arg.d1 : Symbol(D1.d1, Decl(protectedMembersThisParameter.ts, 87, 20))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 69, 26))
>d1 : Symbol(D1.d1, Decl(protectedMembersThisParameter.ts, 87, 20))
}
derived2(arg: D2) {
>derived2 : Symbol(D.derived2, Decl(protectedMembersThisParameter.ts, 72, 3))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 74, 11))
>D2 : Symbol(D2, Decl(protectedMembersThisParameter.ts, 89, 1))
arg.d(); // should error because of overridden method in D2
>arg.d : Symbol(D2.d, Decl(protectedMembersThisParameter.ts, 90, 20))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 74, 11))
>d : Symbol(D2.d, Decl(protectedMembersThisParameter.ts, 90, 20))
arg.d2(); // should error
>arg.d2 : Symbol(D2.d2, Decl(protectedMembersThisParameter.ts, 91, 18))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 74, 11))
>d2 : Symbol(D2.d2, Decl(protectedMembersThisParameter.ts, 91, 18))
}
derived2ThisD(this: D, arg: D2) {
>derived2ThisD : Symbol(D.derived2ThisD, Decl(protectedMembersThisParameter.ts, 77, 3))
>this : Symbol(this, Decl(protectedMembersThisParameter.ts, 78, 16))
>D : Symbol(D, Decl(protectedMembersThisParameter.ts, 56, 1))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 78, 24))
>D2 : Symbol(D2, Decl(protectedMembersThisParameter.ts, 89, 1))
arg.d(); // should error because of overridden method in D2
>arg.d : Symbol(D2.d, Decl(protectedMembersThisParameter.ts, 90, 20))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 78, 24))
>d : Symbol(D2.d, Decl(protectedMembersThisParameter.ts, 90, 20))
arg.d2(); // should error
>arg.d2 : Symbol(D2.d2, Decl(protectedMembersThisParameter.ts, 91, 18))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 78, 24))
>d2 : Symbol(D2.d2, Decl(protectedMembersThisParameter.ts, 91, 18))
}
derived2ThisD2(this: D2, arg: D2) {
>derived2ThisD2 : Symbol(D.derived2ThisD2, Decl(protectedMembersThisParameter.ts, 81, 3))
>this : Symbol(this, Decl(protectedMembersThisParameter.ts, 82, 17))
>D2 : Symbol(D2, Decl(protectedMembersThisParameter.ts, 89, 1))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 82, 26))
>D2 : Symbol(D2, Decl(protectedMembersThisParameter.ts, 89, 1))
arg.d();
>arg.d : Symbol(D2.d, Decl(protectedMembersThisParameter.ts, 90, 20))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 82, 26))
>d : Symbol(D2.d, Decl(protectedMembersThisParameter.ts, 90, 20))
arg.d2();
>arg.d2 : Symbol(D2.d2, Decl(protectedMembersThisParameter.ts, 91, 18))
>arg : Symbol(arg, Decl(protectedMembersThisParameter.ts, 82, 26))
>d2 : Symbol(D2.d2, Decl(protectedMembersThisParameter.ts, 91, 18))
}
}
class D1 extends D {
>D1 : Symbol(D1, Decl(protectedMembersThisParameter.ts, 86, 1))
>D : Symbol(D, Decl(protectedMembersThisParameter.ts, 56, 1))
protected d1() {}
>d1 : Symbol(D1.d1, Decl(protectedMembersThisParameter.ts, 87, 20))
}
class D2 extends D {
>D2 : Symbol(D2, Decl(protectedMembersThisParameter.ts, 89, 1))
>D : Symbol(D, Decl(protectedMembersThisParameter.ts, 56, 1))
protected d() {}
>d : Symbol(D2.d, Decl(protectedMembersThisParameter.ts, 90, 20))
protected d2() {}
>d2 : Symbol(D2.d2, Decl(protectedMembersThisParameter.ts, 91, 18))
}

View File

@ -0,0 +1,337 @@
=== tests/cases/compiler/protectedMembersThisParameter.ts ===
class Message {
>Message : Message
protected secret(): void {}
>secret : () => void
}
class MessageWrapper {
>MessageWrapper : MessageWrapper
message: Message = new Message();
>message : Message
>new Message() : Message
>Message : typeof Message
wrap<T>() {
>wrap : <T>() => void
let m = this.message;
>m : Message
>this.message : Message
>this : this
>message : Message
let f = function(this: T) {
>f : (this: T) => void
>function(this: T) { m.secret(); // should error } : (this: T) => void
>this : T
m.secret(); // should error
>m.secret() : void
>m.secret : () => void
>m : Message
>secret : () => void
}
}
}
class A {
>A : A
protected a() {}
>a : () => void
}
class B extends A {
>B : B
>A : A
protected b() {}
>b : () => void
}
class C extends A {
>C : C
>A : A
protected c() {}
>c : () => void
}
class Z {
>Z : Z
protected z() {}
>z : () => void
}
function bA<T extends A>(this: T, arg: B) {
>bA : <T extends A>(this: T, arg: B) => void
>this : T
>arg : B
this.a();
>this.a() : void
>this.a : () => void
>this : T
>a : () => void
arg.a();
>arg.a() : void
>arg.a : () => void
>arg : B
>a : () => void
arg.b(); // should error to avoid cross-hierarchy protected access https://www.typescriptlang.org/docs/handbook/2/classes.html#cross-hierarchy-protected-access
>arg.b() : void
>arg.b : () => void
>arg : B
>b : () => void
}
function bB<T extends B>(this: T, arg: B) {
>bB : <T extends B>(this: T, arg: B) => void
>this : T
>arg : B
this.a();
>this.a() : void
>this.a : () => void
>this : T
>a : () => void
this.b();
>this.b() : void
>this.b : () => void
>this : T
>b : () => void
arg.a();
>arg.a() : void
>arg.a : () => void
>arg : B
>a : () => void
arg.b();
>arg.b() : void
>arg.b : () => void
>arg : B
>b : () => void
}
function bC<T extends C>(this: T, arg: B) {
>bC : <T extends C>(this: T, arg: B) => void
>this : T
>arg : B
this.a();
>this.a() : void
>this.a : () => void
>this : T
>a : () => void
this.c();
>this.c() : void
>this.c : () => void
>this : T
>c : () => void
arg.a(); // should error
>arg.a() : void
>arg.a : () => void
>arg : B
>a : () => void
arg.b(); // should error
>arg.b() : void
>arg.b : () => void
>arg : B
>b : () => void
}
function bZ<T extends Z>(this: T, arg: B) {
>bZ : <T extends Z>(this: T, arg: B) => void
>this : T
>arg : B
this.z();
>this.z() : void
>this.z : () => void
>this : T
>z : () => void
arg.a(); // should error
>arg.a() : void
>arg.a : () => void
>arg : B
>a : () => void
arg.b(); // should error
>arg.b() : void
>arg.b : () => void
>arg : B
>b : () => void
}
function bString<T extends string>(this: T, arg: B) {
>bString : <T extends string>(this: T, arg: B) => void
>this : T
>arg : B
this.toLowerCase();
>this.toLowerCase() : string
>this.toLowerCase : () => string
>this : T
>toLowerCase : () => string
arg.a(); // should error
>arg.a() : void
>arg.a : () => void
>arg : B
>a : () => void
arg.b(); // should error
>arg.b() : void
>arg.b : () => void
>arg : B
>b : () => void
}
function bAny<T>(this: T, arg: B) {
>bAny : <T>(this: T, arg: B) => void
>this : T
>arg : B
arg.a(); // should error
>arg.a() : void
>arg.a : () => void
>arg : B
>a : () => void
arg.b(); // should error
>arg.b() : void
>arg.b : () => void
>arg : B
>b : () => void
}
class D {
>D : D
protected d() {}
>d : () => void
derived1(arg: D1) {
>derived1 : (arg: D1) => void
>arg : D1
arg.d();
>arg.d() : void
>arg.d : () => void
>arg : D1
>d : () => void
arg.d1(); // should error
>arg.d1() : void
>arg.d1 : () => void
>arg : D1
>d1 : () => void
}
derived1ThisD(this: D, arg: D1) {
>derived1ThisD : (this: D, arg: D1) => void
>this : D
>arg : D1
arg.d();
>arg.d() : void
>arg.d : () => void
>arg : D1
>d : () => void
arg.d1(); // should error
>arg.d1() : void
>arg.d1 : () => void
>arg : D1
>d1 : () => void
}
derived1ThisD1(this: D1, arg: D1) {
>derived1ThisD1 : (this: D1, arg: D1) => void
>this : D1
>arg : D1
arg.d();
>arg.d() : void
>arg.d : () => void
>arg : D1
>d : () => void
arg.d1();
>arg.d1() : void
>arg.d1 : () => void
>arg : D1
>d1 : () => void
}
derived2(arg: D2) {
>derived2 : (arg: D2) => void
>arg : D2
arg.d(); // should error because of overridden method in D2
>arg.d() : void
>arg.d : () => void
>arg : D2
>d : () => void
arg.d2(); // should error
>arg.d2() : void
>arg.d2 : () => void
>arg : D2
>d2 : () => void
}
derived2ThisD(this: D, arg: D2) {
>derived2ThisD : (this: D, arg: D2) => void
>this : D
>arg : D2
arg.d(); // should error because of overridden method in D2
>arg.d() : void
>arg.d : () => void
>arg : D2
>d : () => void
arg.d2(); // should error
>arg.d2() : void
>arg.d2 : () => void
>arg : D2
>d2 : () => void
}
derived2ThisD2(this: D2, arg: D2) {
>derived2ThisD2 : (this: D2, arg: D2) => void
>this : D2
>arg : D2
arg.d();
>arg.d() : void
>arg.d : () => void
>arg : D2
>d : () => void
arg.d2();
>arg.d2() : void
>arg.d2 : () => void
>arg : D2
>d2 : () => void
}
}
class D1 extends D {
>D1 : D1
>D : D
protected d1() {}
>d1 : () => void
}
class D2 extends D {
>D2 : D2
>D : D
protected d() {}
>d : () => void
protected d2() {}
>d2 : () => void
}

View File

@ -1,5 +1,5 @@
tests/cases/compiler/publicGetterProtectedSetterFromThisParameter.ts(33,7): error TS2446: Property 'q' is protected and only accessible through an instance of class 'A'. This is an instance of class 'B'.
tests/cases/compiler/publicGetterProtectedSetterFromThisParameter.ts(34,7): error TS2446: Property 'u' is protected and only accessible through an instance of class 'A'. This is an instance of class 'B'.
tests/cases/compiler/publicGetterProtectedSetterFromThisParameter.ts(33,7): error TS2445: Property 'q' is protected and only accessible within class 'B' and its subclasses.
tests/cases/compiler/publicGetterProtectedSetterFromThisParameter.ts(34,7): error TS2445: Property 'u' is protected and only accessible within class 'B' and its subclasses.
==== tests/cases/compiler/publicGetterProtectedSetterFromThisParameter.ts (2 errors) ====
@ -37,9 +37,9 @@ tests/cases/compiler/publicGetterProtectedSetterFromThisParameter.ts(34,7): erro
// These should error
b.q = 0;
~
!!! error TS2446: Property 'q' is protected and only accessible through an instance of class 'A'. This is an instance of class 'B'.
!!! error TS2445: Property 'q' is protected and only accessible within class 'B' and its subclasses.
b.u = 0;
~
!!! error TS2446: Property 'u' is protected and only accessible through an instance of class 'A'. This is an instance of class 'B'.
!!! error TS2445: Property 'u' is protected and only accessible within class 'B' and its subclasses.
}

View File

@ -0,0 +1,95 @@
class Message {
protected secret(): void {}
}
class MessageWrapper {
message: Message = new Message();
wrap<T>() {
let m = this.message;
let f = function(this: T) {
m.secret(); // should error
}
}
}
class A {
protected a() {}
}
class B extends A {
protected b() {}
}
class C extends A {
protected c() {}
}
class Z {
protected z() {}
}
function bA<T extends A>(this: T, arg: B) {
this.a();
arg.a();
arg.b(); // should error to avoid cross-hierarchy protected access https://www.typescriptlang.org/docs/handbook/2/classes.html#cross-hierarchy-protected-access
}
function bB<T extends B>(this: T, arg: B) {
this.a();
this.b();
arg.a();
arg.b();
}
function bC<T extends C>(this: T, arg: B) {
this.a();
this.c();
arg.a(); // should error
arg.b(); // should error
}
function bZ<T extends Z>(this: T, arg: B) {
this.z();
arg.a(); // should error
arg.b(); // should error
}
function bString<T extends string>(this: T, arg: B) {
this.toLowerCase();
arg.a(); // should error
arg.b(); // should error
}
function bAny<T>(this: T, arg: B) {
arg.a(); // should error
arg.b(); // should error
}
class D {
protected d() {}
derived1(arg: D1) {
arg.d();
arg.d1(); // should error
}
derived1ThisD(this: D, arg: D1) {
arg.d();
arg.d1(); // should error
}
derived1ThisD1(this: D1, arg: D1) {
arg.d();
arg.d1();
}
derived2(arg: D2) {
arg.d(); // should error because of overridden method in D2
arg.d2(); // should error
}
derived2ThisD(this: D, arg: D2) {
arg.d(); // should error because of overridden method in D2
arg.d2(); // should error
}
derived2ThisD2(this: D2, arg: D2) {
arg.d();
arg.d2();
}
}
class D1 extends D {
protected d1() {}
}
class D2 extends D {
protected d() {}
protected d2() {}
}