Skip to content

fix(55899): Indexing/element access on super avoids instance property checks #55903

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33621,7 +33621,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
* @param prop The symbol for the property being accessed.
*/
function checkPropertyAccessibility(
node: PropertyAccessExpression | QualifiedName | PropertyAccessExpression | VariableDeclaration | ParameterDeclaration | ImportTypeNode | PropertyAssignment | ShorthandPropertyAssignment | BindingElement,
node: PropertyAccessExpression | QualifiedName | ElementAccessExpression | VariableDeclaration | ParameterDeclaration | ImportTypeNode | PropertyAssignment | ShorthandPropertyAssignment | BindingElement,
isSuper: boolean,
writing: boolean,
type: Type,
Expand All @@ -33631,7 +33631,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const errorNode = !reportError ? undefined :
node.kind === SyntaxKind.QualifiedName ? node.right :
node.kind === SyntaxKind.ImportType ? node :
node.kind === SyntaxKind.BindingElement && node.propertyName ? node.propertyName : node.name;
node.kind === SyntaxKind.BindingElement && node.propertyName ? node.propertyName :
node.kind === SyntaxKind.ElementAccessExpression ? node.expression : node.name;

return checkPropertyAccessibilityAtLocation(node, isSuper, writing, type, prop, errorNode);
}
Expand Down Expand Up @@ -34740,7 +34741,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
const indexedAccessType = getIndexedAccessTypeOrUndefined(objectType, effectiveIndexType, accessFlags, node) || errorType;
return checkIndexedAccessIndexType(getFlowTypeOfAccessExpression(node, getNodeLinks(node).resolvedSymbol, indexedAccessType, indexExpression, checkMode), node);
const symbol = getNodeLinks(node).resolvedSymbol;
if (symbol) {
const apparentType = getApparentType(objectType);
checkPropertyAccessibility(node, node.expression.kind === SyntaxKind.SuperKeyword, !!(accessFlags & AccessFlags.Writing), apparentType, symbol);
}
return checkIndexedAccessIndexType(getFlowTypeOfAccessExpression(node, symbol, indexedAccessType, indexExpression, checkMode), node);
}

function callLikeExpressionMayHaveTypeArguments(node: CallLikeExpression): node is CallExpression | NewExpression | TaggedTemplateExpression | JsxOpeningElement {
Expand Down
8 changes: 7 additions & 1 deletion tests/baselines/reference/keyofAndIndexedAccess.errors.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
keyofAndIndexedAccess.ts(176,16): error TS2445: Property 'y' is protected and only accessible within class 'C' and its subclasses.
keyofAndIndexedAccess.ts(177,16): error TS2341: Property 'z' is private and only accessible within class 'C'.
keyofAndIndexedAccess.ts(205,24): error TS2322: Type 'T[keyof T]' is not assignable to type 'object'.
Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'object'.
Type 'T[string]' is not assignable to type 'object'.
Expand All @@ -15,7 +17,7 @@ keyofAndIndexedAccess.ts(318,5): error TS2322: Type 'T[K]' is not assignable to
Type 'T[string]' is not assignable to type '{}'.


==== keyofAndIndexedAccess.ts (5 errors) ====
==== keyofAndIndexedAccess.ts (7 errors) ====
class Shape {
name: string;
width: number;
Expand Down Expand Up @@ -192,7 +194,11 @@ keyofAndIndexedAccess.ts(318,5): error TS2322: Type 'T[K]' is not assignable to
type Z = C["z"];
let x: X = c["x"];
let y: Y = c["y"];
~
!!! error TS2445: Property 'y' is protected and only accessible within class 'C' and its subclasses.
let z: Z = c["z"];
~
!!! error TS2341: Property 'z' is private and only accessible within class 'C'.
}

function f50<T>(k: keyof T, s: string) {
Expand Down
56 changes: 56 additions & 0 deletions tests/baselines/reference/superElementAccess.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
superElementAccess.ts(21,9): error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword.
superElementAccess.ts(23,9): error TS2341: Property 'p1' is private and only accessible within class 'MyBase'.
superElementAccess.ts(25,18): error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword.
superElementAccess.ts(27,18): error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword.
superElementAccess.ts(31,9): error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword.
superElementAccess.ts(33,17): error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword.


==== superElementAccess.ts (6 errors) ====
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
~~~~~
!!! error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword.

super["p1"](); // Should error, private not public instance member function
~~~~~
!!! error TS2341: Property 'p1' is private and only accessible within class 'MyBase'.

var l1 = super["d1"]; // Should error, instance data property not a public instance member function
~~~~~
!!! error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword.

var l1 = super["d2"]; // Should error, instance data property not a public instance member function
~~~~~
!!! error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword.

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
~~~~~
!!! error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword.

var z = super["value"]; // Should error, instance data property not a public instance member function
~~~~~
!!! error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword.
}
}
3 changes: 3 additions & 0 deletions tests/baselines/reference/superElementAccess.types
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ class MyDerived extends MyBase {

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
Expand Down Expand Up @@ -101,6 +103,7 @@ class MyDerived extends MyBase {

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
Expand Down