@@ -1523,8 +1523,8 @@ namespace ts {
1523
1523
}
1524
1524
}
1525
1525
1526
- function diagnosticName(nameArg: __String | Identifier) {
1527
- return isString(nameArg) ? unescapeLeadingUnderscores(nameArg as __String) : declarationNameToString(nameArg as Identifier);
1526
+ function diagnosticName(nameArg: __String | Identifier | PrivateName ) {
1527
+ return isString(nameArg) ? unescapeLeadingUnderscores(nameArg as __String) : declarationNameToString(nameArg as Identifier | PrivateName );
1528
1528
}
1529
1529
1530
1530
function isTypeParameterSymbolDeclaredInContainer(symbol: Symbol, container: Node) {
@@ -2594,15 +2594,16 @@ namespace ts {
2594
2594
return getUnionType(arrayFrom(typeofEQFacts.keys(), getLiteralType));
2595
2595
}
2596
2596
2597
- // A reserved member name starts with two underscores, but the third character cannot be an underscore
2598
- // or the @ symbol . A third underscore indicates an escaped form of an identifer that started
2597
+ // A reserved member name starts with two underscores, but the third character cannot be an underscore,
2598
+ // @ or # . A third underscore indicates an escaped form of an identifer that started
2599
2599
// with at least two underscores. The @ character indicates that the name is denoted by a well known ES
2600
- // Symbol instance.
2600
+ // Symbol instance and the # indicates that the name is a PrivateName .
2601
2601
function isReservedMemberName(name: __String) {
2602
2602
return (name as string).charCodeAt(0) === CharacterCodes._ &&
2603
2603
(name as string).charCodeAt(1) === CharacterCodes._ &&
2604
2604
(name as string).charCodeAt(2) !== CharacterCodes._ &&
2605
- (name as string).charCodeAt(2) !== CharacterCodes.at;
2605
+ (name as string).charCodeAt(2) !== CharacterCodes.at &&
2606
+ (name as string).charCodeAt(2) !== CharacterCodes.hash;
2606
2607
}
2607
2608
2608
2609
function getNamedMembers(members: SymbolTable): Symbol[] {
@@ -9042,7 +9043,9 @@ namespace ts {
9042
9043
}
9043
9044
9044
9045
function getLiteralTypeFromPropertyName(prop: Symbol, include: TypeFlags) {
9045
- if (!(getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier)) {
9046
+ const hasNonPublicModifier = !!(getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier);
9047
+ const hasPrivateName = prop.valueDeclaration && isNamedDeclaration(prop.valueDeclaration) && isPrivateName(prop.valueDeclaration.name);
9048
+ if (!hasNonPublicModifier && !hasPrivateName) {
9046
9049
let type = getLateBoundSymbol(prop).nameType;
9047
9050
if (!type && !isKnownSymbol(prop)) {
9048
9051
const name = prop.valueDeclaration && getNameOfDeclaration(prop.valueDeclaration);
@@ -17974,6 +17977,46 @@ namespace ts {
17974
17977
return checkPropertyAccessExpressionOrQualifiedName(node, node.left, node.right);
17975
17978
}
17976
17979
17980
+ function getPropertyByPrivateName(apparentType: Type, leftType: Type, right: PrivateName): Symbol | undefined {
17981
+ let classWithShadowedPrivateName;
17982
+ let klass = getContainingClass(right);
17983
+ while (klass) {
17984
+ const symbolTableKey = getPropertyNameForPrivateNameDescription(klass.symbol, right.escapedText);
17985
+ if (symbolTableKey) {
17986
+ const prop = getPropertyOfType(apparentType, symbolTableKey);
17987
+ if (prop) {
17988
+ if (classWithShadowedPrivateName) {
17989
+ error(
17990
+ right,
17991
+ Diagnostics.This_usage_of_0_refers_to_the_private_member_declared_in_its_enclosing_class_While_type_1_has_a_private_member_of_the_same_name_its_declaration_and_accessibility_is_distinct,
17992
+ diagnosticName(right),
17993
+ diagnosticName(classWithShadowedPrivateName.name || ("anonymous" as __String))
17994
+ );
17995
+ return undefined;
17996
+ }
17997
+ return prop;
17998
+ }
17999
+ else {
18000
+ classWithShadowedPrivateName = klass;
18001
+ }
18002
+ }
18003
+ klass = getContainingClass(klass);
18004
+ }
18005
+ // If this isn't a case of shadowing, and the lhs has a property with the same
18006
+ // private name description, then there is a privacy violation
18007
+ if (leftType.symbol.members) {
18008
+ const symbolTableKey = getPropertyNameForPrivateNameDescription(leftType.symbol, right.escapedText);
18009
+ if (symbolTableKey) {
18010
+ const prop = getPropertyOfType(apparentType, symbolTableKey);
18011
+ if (prop) {
18012
+ error(right, Diagnostics.Property_0_is_not_accessible_outside_class_1_because_it_has_a_private_name, symbolToString(prop), typeToString(getDeclaringClass(prop)!));
18013
+ }
18014
+ }
18015
+ }
18016
+ // not found
18017
+ return undefined;
18018
+ }
18019
+
17977
18020
function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier | PrivateName) {
17978
18021
let propType: Type;
17979
18022
const leftType = checkNonNullExpression(left);
@@ -17986,7 +18029,7 @@ namespace ts {
17986
18029
return apparentType;
17987
18030
}
17988
18031
const assignmentKind = getAssignmentTargetKind(node);
17989
- const prop = getPropertyOfType(apparentType, right.escapedText);
18032
+ const prop = isPrivateName(right) ? getPropertyByPrivateName(apparentType, leftType, right) : getPropertyOfType(apparentType, right.escapedText);
17990
18033
if (isIdentifier(left) && parentSymbol && !(prop && isConstEnumOrConstEnumOnlyModule(prop))) {
17991
18034
markAliasReferenced(parentSymbol, node);
17992
18035
}
@@ -20725,10 +20768,16 @@ namespace ts {
20725
20768
error(expr, Diagnostics.The_operand_of_a_delete_operator_must_be_a_property_reference);
20726
20769
return booleanType;
20727
20770
}
20771
+ if (expr.kind === SyntaxKind.PropertyAccessExpression && isPrivateName((expr as PropertyAccessExpression).name)) {
20772
+ error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_private_name);
20773
+
20774
+ }
20728
20775
const links = getNodeLinks(expr);
20729
20776
const symbol = getExportSymbolOfValueSymbolIfExported(links.resolvedSymbol);
20730
- if (symbol && isReadonlySymbol(symbol)) {
20731
- error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property);
20777
+ if (symbol) {
20778
+ if (isReadonlySymbol(symbol)) {
20779
+ error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property);
20780
+ }
20732
20781
}
20733
20782
return booleanType;
20734
20783
}
@@ -21878,9 +21927,6 @@ namespace ts {
21878
21927
checkGrammarDecoratorsAndModifiers(node);
21879
21928
21880
21929
checkVariableLikeDeclaration(node);
21881
- if (node.name && isIdentifier(node.name) && node.name.originalKeywordKind === SyntaxKind.PrivateName) {
21882
- error(node, Diagnostics.Private_names_cannot_be_used_as_parameters);
21883
- }
21884
21930
const func = getContainingFunction(node)!;
21885
21931
if (hasModifier(node, ModifierFlags.ParameterPropertyModifier)) {
21886
21932
if (!(func.kind === SyntaxKind.Constructor && nodeIsPresent(func.body))) {
@@ -28515,6 +28561,9 @@ namespace ts {
28515
28561
else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) && (<ParameterDeclaration>node).dotDotDotToken) {
28516
28562
return grammarErrorOnNode(node, Diagnostics.A_parameter_property_cannot_be_declared_using_a_rest_parameter);
28517
28563
}
28564
+ else if (isNamedDeclaration(node) && (flags & ModifierFlags.AccessibilityModifier) && node.name.kind === SyntaxKind.PrivateName) {
28565
+ return grammarErrorOnNode(node, Diagnostics.Accessibility_modifiers_cannot_be_used_with_private_names);
28566
+ }
28518
28567
if (flags & ModifierFlags.Async) {
28519
28568
return checkGrammarAsyncModifier(node, lastAsync!);
28520
28569
}
@@ -29293,10 +29342,6 @@ namespace ts {
29293
29342
checkESModuleMarker(node.name);
29294
29343
}
29295
29344
29296
- if (isIdentifier(node.name) && node.name.originalKeywordKind === SyntaxKind.PrivateName) {
29297
- return grammarErrorOnNode(node.name, Diagnostics.Private_names_are_not_allowed_in_variable_declarations);
29298
- }
29299
-
29300
29345
const checkLetConstNames = (isLet(node) || isVarConst(node));
29301
29346
29302
29347
// 1. LexicalDeclaration : LetOrConst BindingList ;
0 commit comments