Skip to content

Commit 5e53ba0

Browse files
committed
Merge pull request #7262 from Microsoft/stop-destructuring-private-properties
Stop destructuring private properties
2 parents e579d17 + 5c6a007 commit 5e53ba0

File tree

38 files changed

+366
-239
lines changed

38 files changed

+366
-239
lines changed

src/compiler/checker.ts

+16-9
Original file line numberDiff line numberDiff line change
@@ -8971,15 +8971,13 @@ namespace ts {
89718971
* @param type The type of left.
89728972
* @param prop The symbol for the right hand side of the property access.
89738973
*/
8974-
function checkClassPropertyAccess(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, type: Type, prop: Symbol): boolean {
8974+
function checkClassPropertyAccess(node: PropertyAccessExpression | QualifiedName | VariableLikeDeclaration, left: Expression | QualifiedName, type: Type, prop: Symbol): boolean {
89758975
const flags = getDeclarationFlagsFromSymbol(prop);
89768976
const declaringClass = <InterfaceType>getDeclaredTypeOfSymbol(getParentOfSymbol(prop));
8977-
8977+
const errorNode = node.kind === SyntaxKind.PropertyAccessExpression || node.kind === SyntaxKind.VariableDeclaration ?
8978+
(<PropertyAccessExpression | VariableDeclaration>node).name :
8979+
(<QualifiedName>node).right;
89788980
if (left.kind === SyntaxKind.SuperKeyword) {
8979-
const errorNode = node.kind === SyntaxKind.PropertyAccessExpression ?
8980-
(<PropertyAccessExpression>node).name :
8981-
(<QualifiedName>node).right;
8982-
89838981
// TS 1.0 spec (April 2014): 4.8.2
89848982
// - In a constructor, instance member function, instance member accessor, or
89858983
// instance member variable initializer where this references a derived class instance,
@@ -9020,7 +9018,7 @@ namespace ts {
90209018
// Private property is accessible if declaring and enclosing class are the same
90219019
if (flags & NodeFlags.Private) {
90229020
if (declaringClass !== enclosingClass) {
9023-
error(node, Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(declaringClass));
9021+
error(errorNode, Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(declaringClass));
90249022
return false;
90259023
}
90269024
return true;
@@ -9034,7 +9032,7 @@ namespace ts {
90349032
}
90359033
// A protected property is accessible in the declaring class and classes derived from it
90369034
if (!enclosingClass || !hasBaseType(enclosingClass, declaringClass)) {
9037-
error(node, Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, symbolToString(prop), typeToString(declaringClass));
9035+
error(errorNode, Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, symbolToString(prop), typeToString(declaringClass));
90389036
return false;
90399037
}
90409038
// No further restrictions for static properties
@@ -9049,7 +9047,7 @@ namespace ts {
90499047

90509048
// TODO: why is the first part of this check here?
90519049
if (!(getTargetType(type).flags & (TypeFlags.Class | TypeFlags.Interface) && hasBaseType(<InterfaceType>type, enclosingClass))) {
9052-
error(node, Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1, symbolToString(prop), typeToString(enclosingClass));
9050+
error(errorNode, Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1, symbolToString(prop), typeToString(enclosingClass));
90539051
return false;
90549052
}
90559053
return true;
@@ -13310,6 +13308,15 @@ namespace ts {
1331013308
if (node.propertyName && node.propertyName.kind === SyntaxKind.ComputedPropertyName) {
1331113309
checkComputedPropertyName(<ComputedPropertyName>node.propertyName);
1331213310
}
13311+
13312+
// check private/protected variable access
13313+
const parent = <VariableLikeDeclaration>(<BindingPattern>node.parent).parent;
13314+
const parentType = getTypeForBindingElementParent(parent);
13315+
const name = node.propertyName || <Identifier>node.name;
13316+
const property = getPropertyOfType(parentType, getTextOfPropertyName(name));
13317+
if (parent.initializer && property && getParentOfSymbol(property)) {
13318+
checkClassPropertyAccess(parent, parent.initializer, parentType, property);
13319+
}
1331313320
}
1331413321

1331513322
// For a binding pattern, check contained binding elements

tests/baselines/reference/ClassAndModuleThatMergeWithModulesExportedStaticFunctionUsingClassPrivateStatics.errors.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModulesExportedStaticFunctionUsingClassPrivateStatics.ts(11,16): error TS2341: Property 'sfn' is private and only accessible within class 'clodule<T>'.
1+
tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModulesExportedStaticFunctionUsingClassPrivateStatics.ts(11,24): error TS2341: Property 'sfn' is private and only accessible within class 'clodule<T>'.
22

33

44
==== tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithModulesExportedStaticFunctionUsingClassPrivateStatics.ts (1 errors) ====
@@ -13,7 +13,7 @@ tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMer
1313
// error: duplicate identifier expected
1414
export function fn<T>(x: T, y: T): number {
1515
return clodule.sfn('a');
16-
~~~~~~~~~~~
16+
~~~
1717
!!! error TS2341: Property 'sfn' is private and only accessible within class 'clodule<T>'.
1818
}
1919
}

tests/baselines/reference/classConstructorParametersAccessibility.errors.txt

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
tests/cases/conformance/classes/constructorDeclarations/classConstructorParametersAccessibility.ts(12,1): error TS2341: Property 'p' is private and only accessible within class 'C2'.
2-
tests/cases/conformance/classes/constructorDeclarations/classConstructorParametersAccessibility.ts(19,1): error TS2445: Property 'p' is protected and only accessible within class 'C3' and its subclasses.
1+
tests/cases/conformance/classes/constructorDeclarations/classConstructorParametersAccessibility.ts(12,4): error TS2341: Property 'p' is private and only accessible within class 'C2'.
2+
tests/cases/conformance/classes/constructorDeclarations/classConstructorParametersAccessibility.ts(19,4): error TS2445: Property 'p' is protected and only accessible within class 'C3' and its subclasses.
33

44

55
==== tests/cases/conformance/classes/constructorDeclarations/classConstructorParametersAccessibility.ts (2 errors) ====
@@ -15,7 +15,7 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorParamete
1515
}
1616
var c2: C2;
1717
c2.p // private, error
18-
~~~~
18+
~
1919
!!! error TS2341: Property 'p' is private and only accessible within class 'C2'.
2020

2121

@@ -24,7 +24,7 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorParamete
2424
}
2525
var c3: C3;
2626
c3.p // protected, error
27-
~~~~
27+
~
2828
!!! error TS2445: Property 'p' is protected and only accessible within class 'C3' and its subclasses.
2929
class Derived extends C3 {
3030
constructor(p: number) {

tests/baselines/reference/classConstructorParametersAccessibility2.errors.txt

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
tests/cases/conformance/classes/constructorDeclarations/classConstructorParametersAccessibility2.ts(12,1): error TS2341: Property 'p' is private and only accessible within class 'C2'.
2-
tests/cases/conformance/classes/constructorDeclarations/classConstructorParametersAccessibility2.ts(19,1): error TS2445: Property 'p' is protected and only accessible within class 'C3' and its subclasses.
1+
tests/cases/conformance/classes/constructorDeclarations/classConstructorParametersAccessibility2.ts(12,4): error TS2341: Property 'p' is private and only accessible within class 'C2'.
2+
tests/cases/conformance/classes/constructorDeclarations/classConstructorParametersAccessibility2.ts(19,4): error TS2445: Property 'p' is protected and only accessible within class 'C3' and its subclasses.
33

44

55
==== tests/cases/conformance/classes/constructorDeclarations/classConstructorParametersAccessibility2.ts (2 errors) ====
@@ -15,7 +15,7 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorParamete
1515
}
1616
var c2: C2;
1717
c2.p // private, error
18-
~~~~
18+
~
1919
!!! error TS2341: Property 'p' is private and only accessible within class 'C2'.
2020

2121

@@ -24,7 +24,7 @@ tests/cases/conformance/classes/constructorDeclarations/classConstructorParamete
2424
}
2525
var c3: C3;
2626
c3.p // protected, error
27-
~~~~
27+
~
2828
!!! error TS2445: Property 'p' is protected and only accessible within class 'C3' and its subclasses.
2929
class Derived extends C3 {
3030
constructor(p: number) {

tests/baselines/reference/classPropertyAsPrivate.errors.txt

+16-16
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(
22
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(4,17): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
33
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(8,24): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
44
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(9,24): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
5-
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(15,1): error TS2341: Property 'x' is private and only accessible within class 'C'.
6-
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(16,1): error TS2341: Property 'y' is private and only accessible within class 'C'.
7-
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(17,1): error TS2341: Property 'y' is private and only accessible within class 'C'.
8-
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(18,1): error TS2341: Property 'foo' is private and only accessible within class 'C'.
9-
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(20,1): error TS2341: Property 'a' is private and only accessible within class 'C'.
10-
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(21,1): error TS2341: Property 'b' is private and only accessible within class 'C'.
11-
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(22,1): error TS2341: Property 'b' is private and only accessible within class 'C'.
12-
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(23,1): error TS2341: Property 'foo' is private and only accessible within class 'C'.
5+
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(15,3): error TS2341: Property 'x' is private and only accessible within class 'C'.
6+
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(16,3): error TS2341: Property 'y' is private and only accessible within class 'C'.
7+
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(17,3): error TS2341: Property 'y' is private and only accessible within class 'C'.
8+
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(18,3): error TS2341: Property 'foo' is private and only accessible within class 'C'.
9+
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(20,3): error TS2341: Property 'a' is private and only accessible within class 'C'.
10+
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(21,3): error TS2341: Property 'b' is private and only accessible within class 'C'.
11+
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(22,3): error TS2341: Property 'b' is private and only accessible within class 'C'.
12+
tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(23,3): error TS2341: Property 'foo' is private and only accessible within class 'C'.
1313

1414

1515
==== tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts (12 errors) ====
@@ -36,27 +36,27 @@ tests/cases/conformance/classes/members/accessibility/classPropertyAsPrivate.ts(
3636
var c: C;
3737
// all errors
3838
c.x;
39-
~~~
39+
~
4040
!!! error TS2341: Property 'x' is private and only accessible within class 'C'.
4141
c.y;
42-
~~~
42+
~
4343
!!! error TS2341: Property 'y' is private and only accessible within class 'C'.
4444
c.y = 1;
45-
~~~
45+
~
4646
!!! error TS2341: Property 'y' is private and only accessible within class 'C'.
4747
c.foo();
48-
~~~~~
48+
~~~
4949
!!! error TS2341: Property 'foo' is private and only accessible within class 'C'.
5050

5151
C.a;
52-
~~~
52+
~
5353
!!! error TS2341: Property 'a' is private and only accessible within class 'C'.
5454
C.b();
55-
~~~
55+
~
5656
!!! error TS2341: Property 'b' is private and only accessible within class 'C'.
5757
C.b = 1;
58-
~~~
58+
~
5959
!!! error TS2341: Property 'b' is private and only accessible within class 'C'.
6060
C.foo();
61-
~~~~~
61+
~~~
6262
!!! error TS2341: Property 'foo' is private and only accessible within class 'C'.

tests/baselines/reference/classPropertyAsProtected.errors.txt

+16-16
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.t
22
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(4,19): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
33
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(8,26): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
44
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(9,26): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
5-
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(15,1): error TS2445: Property 'x' is protected and only accessible within class 'C' and its subclasses.
6-
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(16,1): error TS2445: Property 'y' is protected and only accessible within class 'C' and its subclasses.
7-
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(17,1): error TS2445: Property 'y' is protected and only accessible within class 'C' and its subclasses.
8-
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(18,1): error TS2445: Property 'foo' is protected and only accessible within class 'C' and its subclasses.
9-
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(20,1): error TS2445: Property 'a' is protected and only accessible within class 'C' and its subclasses.
10-
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(21,1): error TS2445: Property 'b' is protected and only accessible within class 'C' and its subclasses.
11-
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(22,1): error TS2445: Property 'b' is protected and only accessible within class 'C' and its subclasses.
12-
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(23,1): error TS2445: Property 'foo' is protected and only accessible within class 'C' and its subclasses.
5+
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(15,3): error TS2445: Property 'x' is protected and only accessible within class 'C' and its subclasses.
6+
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(16,3): error TS2445: Property 'y' is protected and only accessible within class 'C' and its subclasses.
7+
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(17,3): error TS2445: Property 'y' is protected and only accessible within class 'C' and its subclasses.
8+
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(18,3): error TS2445: Property 'foo' is protected and only accessible within class 'C' and its subclasses.
9+
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(20,3): error TS2445: Property 'a' is protected and only accessible within class 'C' and its subclasses.
10+
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(21,3): error TS2445: Property 'b' is protected and only accessible within class 'C' and its subclasses.
11+
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(22,3): error TS2445: Property 'b' is protected and only accessible within class 'C' and its subclasses.
12+
tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts(23,3): error TS2445: Property 'foo' is protected and only accessible within class 'C' and its subclasses.
1313

1414

1515
==== tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.ts (12 errors) ====
@@ -36,27 +36,27 @@ tests/cases/conformance/classes/members/accessibility/classPropertyAsProtected.t
3636
var c: C;
3737
// all errors
3838
c.x;
39-
~~~
39+
~
4040
!!! error TS2445: Property 'x' is protected and only accessible within class 'C' and its subclasses.
4141
c.y;
42-
~~~
42+
~
4343
!!! error TS2445: Property 'y' is protected and only accessible within class 'C' and its subclasses.
4444
c.y = 1;
45-
~~~
45+
~
4646
!!! error TS2445: Property 'y' is protected and only accessible within class 'C' and its subclasses.
4747
c.foo();
48-
~~~~~
48+
~~~
4949
!!! error TS2445: Property 'foo' is protected and only accessible within class 'C' and its subclasses.
5050

5151
C.a;
52-
~~~
52+
~
5353
!!! error TS2445: Property 'a' is protected and only accessible within class 'C' and its subclasses.
5454
C.b();
55-
~~~
55+
~
5656
!!! error TS2445: Property 'b' is protected and only accessible within class 'C' and its subclasses.
5757
C.b = 1;
58-
~~~
58+
~
5959
!!! error TS2445: Property 'b' is protected and only accessible within class 'C' and its subclasses.
6060
C.foo();
61-
~~~~~
61+
~~~
6262
!!! error TS2445: Property 'foo' is protected and only accessible within class 'C' and its subclasses.

0 commit comments

Comments
 (0)