From a641b1eb9256059c01c98f40b5c5bf59c35c86ec Mon Sep 17 00:00:00 2001 From: jihndai <73680880+jihndai@users.noreply.github.com> Date: Mon, 28 Feb 2022 00:05:44 -0400 Subject: [PATCH 1/6] fix this type validations for protected fields --- src/compiler/checker.ts | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9dfb4a7e112c2..f3b91197787f2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20621,7 +20621,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(checkClass: T, prop: Symbol, writing: boolean) { return forEachProperty(prop, p => getDeclarationModifierFlagsFromSymbol(p, writing) & ModifierFlags.Protected ? !hasBaseType(checkClass, getDeclaringClass(p)) : false) ? undefined : checkClass; } @@ -28315,14 +28315,17 @@ 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 + if ( + flags & ModifierFlags.Static + || !(enclosingClass = getEnclosingClassFromThisParameter(location)) + || !(enclosingClass = isClassDerivedFromDeclaringClasses(enclosingClass, prop, writing)) + ) { if (errorNode) { error(errorNode, Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, @@ -28331,9 +28334,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) { @@ -28354,6 +28354,25 @@ namespace ts { return true; } + function getEnclosingClassFromThisParameter(node: Node) { + let thisType = getThisTypeFromNodeContext(node); + + if (thisType && thisType.flags & TypeFlags.TypeParameter) { + thisType = getConstraintOfTypeParameter(thisType as TypeParameter); + } + + if (thisType && getObjectFlags(thisType) & ObjectFlags.Reference) { + return (thisType as TypeReference).target; + } + + return undefined; + } + + function getThisTypeFromNodeContext(node: Node) { + const thisParameter = getThisParameterFromNodeContext(node); + return thisParameter?.type && getTypeFromTypeNode(thisParameter.type); + } + function getThisParameterFromNodeContext(node: Node) { const thisContainer = getThisContainer(node, /* includeArrowFunctions */ false); return thisContainer && isFunctionLike(thisContainer) ? getThisParameter(thisContainer) : undefined; From cf64c78917e8ab1bf83ec624b6fef6dc6126f889 Mon Sep 17 00:00:00 2001 From: jihndai <73680880+jihndai@users.noreply.github.com> Date: Mon, 28 Feb 2022 00:15:31 -0400 Subject: [PATCH 2/6] update previous baselines --- ...ublicGetterProtectedSetterFromThisParameter.errors.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/baselines/reference/publicGetterProtectedSetterFromThisParameter.errors.txt b/tests/baselines/reference/publicGetterProtectedSetterFromThisParameter.errors.txt index afe32e1150c5d..c97ccc3b07401 100644 --- a/tests/baselines/reference/publicGetterProtectedSetterFromThisParameter.errors.txt +++ b/tests/baselines/reference/publicGetterProtectedSetterFromThisParameter.errors.txt @@ -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. } \ No newline at end of file From 3fa162996346fe7107fa69e0c7a548ad374a2a72 Mon Sep 17 00:00:00 2001 From: jihndai <73680880+jihndai@users.noreply.github.com> Date: Mon, 28 Feb 2022 00:25:36 -0400 Subject: [PATCH 3/6] add new tests and baselines --- .../protectedMembersThisParameter.errors.txt | 147 ++++++++ .../protectedMembersThisParameter.js | 238 ++++++++++++ .../protectedMembersThisParameter.symbols | 338 ++++++++++++++++++ .../protectedMembersThisParameter.types | 337 +++++++++++++++++ .../compiler/protectedMembersThisParameter.ts | 95 +++++ 5 files changed, 1155 insertions(+) create mode 100644 tests/baselines/reference/protectedMembersThisParameter.errors.txt create mode 100644 tests/baselines/reference/protectedMembersThisParameter.js create mode 100644 tests/baselines/reference/protectedMembersThisParameter.symbols create mode 100644 tests/baselines/reference/protectedMembersThisParameter.types create mode 100644 tests/cases/compiler/protectedMembersThisParameter.ts diff --git a/tests/baselines/reference/protectedMembersThisParameter.errors.txt b/tests/baselines/reference/protectedMembersThisParameter.errors.txt new file mode 100644 index 0000000000000..526b8a487cd4f --- /dev/null +++ b/tests/baselines/reference/protectedMembersThisParameter.errors.txt @@ -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() { + 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(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(this: T, arg: B) { + this.a(); + this.b(); + arg.a(); + arg.b(); + } + function bC(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(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(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(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() {} + } + + \ No newline at end of file diff --git a/tests/baselines/reference/protectedMembersThisParameter.js b/tests/baselines/reference/protectedMembersThisParameter.js new file mode 100644 index 0000000000000..96b331a453f92 --- /dev/null +++ b/tests/baselines/reference/protectedMembersThisParameter.js @@ -0,0 +1,238 @@ +//// [protectedMembersThisParameter.ts] +class Message { + protected secret(): void {} +} +class MessageWrapper { + message: Message = new Message(); + wrap() { + 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(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(this: T, arg: B) { + this.a(); + this.b(); + arg.a(); + arg.b(); +} +function bC(this: T, arg: B) { + this.a(); + this.c(); + arg.a(); // should error + arg.b(); // should error +} +function bZ(this: T, arg: B) { + this.z(); + arg.a(); // should error + arg.b(); // should error +} +function bString(this: T, arg: B) { + this.toLowerCase(); + arg.a(); // should error + arg.b(); // should error +} +function bAny(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)); diff --git a/tests/baselines/reference/protectedMembersThisParameter.symbols b/tests/baselines/reference/protectedMembersThisParameter.symbols new file mode 100644 index 0000000000000..77090ac764e69 --- /dev/null +++ b/tests/baselines/reference/protectedMembersThisParameter.symbols @@ -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() { +>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(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(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(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(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(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(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)) +} + + diff --git a/tests/baselines/reference/protectedMembersThisParameter.types b/tests/baselines/reference/protectedMembersThisParameter.types new file mode 100644 index 0000000000000..5ecbd9bf1011e --- /dev/null +++ b/tests/baselines/reference/protectedMembersThisParameter.types @@ -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() { +>wrap : () => 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(this: T, arg: B) { +>bA : (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(this: T, arg: B) { +>bB : (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(this: T, arg: B) { +>bC : (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(this: T, arg: B) { +>bZ : (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(this: T, arg: B) { +>bString : (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(this: T, arg: B) { +>bAny : (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 +} + + diff --git a/tests/cases/compiler/protectedMembersThisParameter.ts b/tests/cases/compiler/protectedMembersThisParameter.ts new file mode 100644 index 0000000000000..7a1e3123f597a --- /dev/null +++ b/tests/cases/compiler/protectedMembersThisParameter.ts @@ -0,0 +1,95 @@ +class Message { + protected secret(): void {} +} +class MessageWrapper { + message: Message = new Message(); + wrap() { + 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(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(this: T, arg: B) { + this.a(); + this.b(); + arg.a(); + arg.b(); +} +function bC(this: T, arg: B) { + this.a(); + this.c(); + arg.a(); // should error + arg.b(); // should error +} +function bZ(this: T, arg: B) { + this.z(); + arg.a(); // should error + arg.b(); // should error +} +function bString(this: T, arg: B) { + this.toLowerCase(); + arg.a(); // should error + arg.b(); // should error +} +function bAny(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() {} +} + From 4d415c980d3b74d1c1463129779db4c339bac3c0 Mon Sep 17 00:00:00 2001 From: jihndai <73680880+jihndai@users.noreply.github.com> Date: Tue, 1 Mar 2022 16:31:42 -0400 Subject: [PATCH 4/6] ClassOrInterface can be returned as enclosingClass --- src/compiler/checker.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f3b91197787f2..bb7e03905f753 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -28354,15 +28354,15 @@ namespace ts { return true; } - function getEnclosingClassFromThisParameter(node: Node) { + function getEnclosingClassFromThisParameter(node: Node): InterfaceType | undefined { let thisType = getThisTypeFromNodeContext(node); if (thisType && thisType.flags & TypeFlags.TypeParameter) { thisType = getConstraintOfTypeParameter(thisType as TypeParameter); } - if (thisType && getObjectFlags(thisType) & ObjectFlags.Reference) { - return (thisType as TypeReference).target; + if (thisType && getObjectFlags(thisType) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference)) { + return getTargetType(thisType) as InterfaceType; } return undefined; From ffe5d646dd0066c5e9944213a1cecf485c6f8062 Mon Sep 17 00:00:00 2001 From: jihndai <73680880+jihndai@users.noreply.github.com> Date: Thu, 3 Mar 2022 14:43:36 -0400 Subject: [PATCH 5/6] inline function code and remove unnecessary blank lines --- src/compiler/checker.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bb7e03905f753..e8813c9243677 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -28355,24 +28355,17 @@ namespace ts { } function getEnclosingClassFromThisParameter(node: Node): InterfaceType | undefined { - let thisType = getThisTypeFromNodeContext(node); - + 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 getThisTypeFromNodeContext(node: Node) { - const thisParameter = getThisParameterFromNodeContext(node); - return thisParameter?.type && getTypeFromTypeNode(thisParameter.type); - } - function getThisParameterFromNodeContext(node: Node) { const thisContainer = getThisContainer(node, /* includeArrowFunctions */ false); return thisContainer && isFunctionLike(thisContainer) ? getThisParameter(thisContainer) : undefined; From bf6b7455f81d6961aa0eb7652e09e6351385dbd2 Mon Sep 17 00:00:00 2001 From: jihndai <73680880+jihndai@users.noreply.github.com> Date: Thu, 3 Mar 2022 14:58:38 -0400 Subject: [PATCH 6/6] refactor enclosingClass checks --- src/compiler/checker.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e8813c9243677..db7b33c9dd95f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -28321,11 +28321,9 @@ namespace ts { if (!enclosingClass) { // allow PropertyAccessibility if context is in function with this parameter // static member access is disallowed - if ( - flags & ModifierFlags.Static - || !(enclosingClass = getEnclosingClassFromThisParameter(location)) - || !(enclosingClass = isClassDerivedFromDeclaringClasses(enclosingClass, prop, writing)) - ) { + 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,