diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index ff11b09f0fe2a..d9e1778d4dd98 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -278,6 +278,16 @@ namespace ts { Debug.assert(isWellKnownSymbolSyntactically(nameExpression)); return getPropertyNameForKnownSymbolName(idText((nameExpression).name)); } + if (isPrivateName(name)) { + // containingClass exists because private names only allowed inside classes + const containingClass = getContainingClass(name.parent); + if (!containingClass) { + // we're in a case where there's a private name outside a class (invalid) + return undefined; + } + const containingClassSymbol = containingClass.symbol; + return getPropertyNameForPrivateNameDescription(containingClassSymbol, name.escapedText); + } return isPropertyNameLiteral(name) ? getEscapedTextOfIdentifierOrLiteral(name) : undefined; } switch (node.kind) { @@ -334,6 +344,10 @@ namespace ts { const isDefaultExport = hasModifier(node, ModifierFlags.Default); + // need this before getDeclarationName + if (isNamedDeclaration(node)) { + node.name.parent = node; + } // The exported symbol for an export default function/class node is always named "default" const name = isDefaultExport && parent ? InternalSymbolName.Default : getDeclarationName(node); @@ -386,11 +400,6 @@ namespace ts { symbolTable.set(name, symbol = createSymbol(SymbolFlags.None, name)); } else if (!(includes & SymbolFlags.Variable && symbol.flags & SymbolFlags.Assignment)) { - // Assignment declarations are allowed to merge with variables, no matter what other flags they have. - if (isNamedDeclaration(node)) { - node.name.parent = node; - } - // Report errors every position with duplicate declaration // Report errors on previous encountered declarations let message = symbol.flags & SymbolFlags.BlockScopedVariable @@ -1458,7 +1467,7 @@ namespace ts { } if (node.expression.kind === SyntaxKind.PropertyAccessExpression) { const propertyAccess = node.expression; - if (isNarrowableOperand(propertyAccess.expression) && isPushOrUnshiftIdentifier(propertyAccess.name)) { + if (isIdentifier(propertyAccess.name) && isNarrowableOperand(propertyAccess.expression) && isPushOrUnshiftIdentifier(propertyAccess.name)) { currentFlow = createFlowArrayMutation(currentFlow, node); } } @@ -1855,6 +1864,18 @@ namespace ts { return Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode; } + // The binder visits every node, so this is a good place to check for + // the reserved private name (there is only one) + function checkPrivateName(node: PrivateName) { + if (node.escapedText === "#constructor") { + // Report error only if there are no parse errors in file + if (!file.parseDiagnostics.length) { + file.bindDiagnostics.push(createDiagnosticForNode(node, + Diagnostics.constructor_is_a_reserved_word, declarationNameToString(node))); + } + } + } + function checkStrictModeBinaryExpression(node: BinaryExpression) { if (inStrictMode && isLeftHandSideExpression(node.left) && isAssignmentOperator(node.operatorToken.kind)) { // ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an @@ -2127,6 +2148,8 @@ namespace ts { node.flowNode = currentFlow; } return checkStrictModeIdentifier(node); + case SyntaxKind.PrivateName: + return checkPrivateName(node as PrivateName); case SyntaxKind.PropertyAccessExpression: case SyntaxKind.ElementAccessExpression: if (currentFlow && isNarrowableReference(node)) { @@ -2424,7 +2447,7 @@ namespace ts { if (!setCommonJsModuleIndicator(node)) { return; } - const symbol = forEachIdentifierInEntityName(node.arguments[0], /*parent*/ undefined, (id, symbol) => { + const symbol = forEachIdentifierOrPrivateNameInEntityName(node.arguments[0], /*parent*/ undefined, (id, symbol) => { if (symbol) { addDeclarationToSymbol(symbol, id, SymbolFlags.Module | SymbolFlags.Assignment); } @@ -2443,7 +2466,7 @@ namespace ts { return; } const lhs = node.left as PropertyAccessEntityNameExpression; - const symbol = forEachIdentifierInEntityName(lhs.expression, /*parent*/ undefined, (id, symbol) => { + const symbol = forEachIdentifierOrPrivateNameInEntityName(lhs.expression, /*parent*/ undefined, (id, symbol) => { if (symbol) { addDeclarationToSymbol(symbol, id, SymbolFlags.Module | SymbolFlags.Assignment); } @@ -2613,7 +2636,7 @@ namespace ts { // make symbols or add declarations for intermediate containers const flags = SymbolFlags.Module | SymbolFlags.Assignment; const excludeFlags = SymbolFlags.ValueModuleExcludes & ~SymbolFlags.Assignment; - namespaceSymbol = forEachIdentifierInEntityName(entityName, namespaceSymbol, (id, symbol, parent) => { + namespaceSymbol = forEachIdentifierOrPrivateNameInEntityName(entityName, namespaceSymbol, (id, symbol, parent) => { if (symbol) { addDeclarationToSymbol(symbol, id, flags); return symbol; @@ -2701,7 +2724,7 @@ namespace ts { } } - function forEachIdentifierInEntityName(e: EntityNameExpression, parent: Symbol | undefined, action: (e: Identifier, symbol: Symbol | undefined, parent: Symbol | undefined) => Symbol | undefined): Symbol | undefined { + function forEachIdentifierOrPrivateNameInEntityName(e: EntityNameExpression, parent: Symbol | undefined, action: (e: Identifier | PrivateName, symbol: Symbol | undefined, parent: Symbol | undefined) => Symbol | undefined): Symbol | undefined { if (isExportsOrModuleExportsOrAlias(file, e)) { return file.symbol; } @@ -2709,7 +2732,7 @@ namespace ts { return action(e, lookupSymbolForPropertyAccess(e), parent); } else { - const s = forEachIdentifierInEntityName(e.expression, parent, action); + const s = forEachIdentifierOrPrivateNameInEntityName(e.expression, parent, action); if (!s || !s.exports) return Debug.fail(); return action(e.name, s.exports.get(e.name.escapedText), s); } @@ -3231,8 +3254,7 @@ namespace ts { // A ClassDeclaration is ES6 syntax. transformFlags = subtreeFlags | TransformFlags.AssertES2015; - // A class with a parameter property assignment, property initializer, computed property name, or decorator is - // TypeScript syntax. + // A class with a parameter property assignment or decorator is TypeScript syntax. // An exported declaration may be TypeScript syntax, but is handled by the visitor // for a namespace declaration. if ((subtreeFlags & TransformFlags.ContainsTypeScriptClassSyntax) @@ -3249,8 +3271,7 @@ namespace ts { // A ClassExpression is ES6 syntax. let transformFlags = subtreeFlags | TransformFlags.AssertES2015; - // A class with a parameter property assignment, property initializer, or decorator is - // TypeScript syntax. + // A class with a parameter property assignment or decorator is TypeScript syntax. if (subtreeFlags & TransformFlags.ContainsTypeScriptClassSyntax || node.typeParameters) { transformFlags |= TransformFlags.AssertTypeScript; @@ -3340,7 +3361,6 @@ namespace ts { || hasModifier(node, ModifierFlags.TypeScriptModifier) || node.typeParameters || node.type - || (node.name && isComputedPropertyName(node.name)) // While computed method names aren't typescript, the TS transform must visit them to emit property declarations correctly || !node.body) { transformFlags |= TransformFlags.AssertTypeScript; } @@ -3371,7 +3391,6 @@ namespace ts { if (node.decorators || hasModifier(node, ModifierFlags.TypeScriptModifier) || node.type - || (node.name && isComputedPropertyName(node.name)) // While computed accessor names aren't typescript, the TS transform must visit them to emit property declarations correctly || !node.body) { transformFlags |= TransformFlags.AssertTypeScript; } @@ -3386,12 +3405,15 @@ namespace ts { } function computePropertyDeclaration(node: PropertyDeclaration, subtreeFlags: TransformFlags) { - // A PropertyDeclaration is TypeScript syntax. - let transformFlags = subtreeFlags | TransformFlags.AssertTypeScript; + let transformFlags = subtreeFlags; + + // Decorators, TypeScript-specific modifiers, and type annotations are TypeScript syntax. + if (some(node.decorators) || hasModifier(node, ModifierFlags.TypeScriptModifier) || node.type) { + transformFlags |= TransformFlags.AssertTypeScript; + } - // If the PropertyDeclaration has an initializer or a computed name, we need to inform its ancestor - // so that it handle the transformation. - if (node.initializer || isComputedPropertyName(node.name)) { + // Hoisted variables related to class properties should live within the TypeScript class wrapper. + if (isComputedPropertyName(node.name) || (hasStaticModifier(node) && node.initializer)) { transformFlags |= TransformFlags.ContainsTypeScriptClassSyntax; } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ac45866e2db4d..40516ff789958 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -132,6 +132,7 @@ namespace ts { getDeclaredTypeOfSymbol, getPropertiesOfType, getPropertyOfType: (type, name) => getPropertyOfType(type, escapeLeadingUnderscores(name)), + getPropertyForPrivateName, getTypeOfPropertyOfType: (type, name) => getTypeOfPropertyOfType(type, escapeLeadingUnderscores(name)), getIndexInfoOfType, getSignaturesOfType, @@ -1605,8 +1606,8 @@ namespace ts { } } - function diagnosticName(nameArg: __String | Identifier) { - return isString(nameArg) ? unescapeLeadingUnderscores(nameArg as __String) : declarationNameToString(nameArg as Identifier); + function diagnosticName(nameArg: __String | Identifier | PrivateName) { + return isString(nameArg) ? unescapeLeadingUnderscores(nameArg as __String) : declarationNameToString(nameArg as Identifier | PrivateName); } function isTypeParameterSymbolDeclaredInContainer(symbol: Symbol, container: Node) { @@ -2795,15 +2796,16 @@ namespace ts { return type; } - // A reserved member name starts with two underscores, but the third character cannot be an underscore - // or the @ symbol. A third underscore indicates an escaped form of an identifer that started + // A reserved member name starts with two underscores, but the third character cannot be an underscore, + // @, or #. A third underscore indicates an escaped form of an identifer that started // with at least two underscores. The @ character indicates that the name is denoted by a well known ES - // Symbol instance. + // Symbol instance and the # indicates that the name is a PrivateName. function isReservedMemberName(name: __String) { return (name as string).charCodeAt(0) === CharacterCodes._ && (name as string).charCodeAt(1) === CharacterCodes._ && (name as string).charCodeAt(2) !== CharacterCodes._ && - (name as string).charCodeAt(2) !== CharacterCodes.at; + (name as string).charCodeAt(2) !== CharacterCodes.at && + (name as string).charCodeAt(2) !== CharacterCodes.hash; } function getNamedMembers(members: SymbolTable): Symbol[] { @@ -4364,7 +4366,10 @@ namespace ts { context.flags ^= NodeBuilderFlags.InInitialEntityName; } let firstChar = symbolName.charCodeAt(0); - const canUsePropertyAccess = isIdentifierStart(firstChar, languageVersion); + const canUsePropertyAccess = firstChar === CharacterCodes.hash ? + symbolName.length > 1 && isIdentifierStart(symbolName.charCodeAt(1), languageVersion) : + isIdentifierStart(firstChar, languageVersion); + if (index === 0 || canUsePropertyAccess) { const identifier = setEmitFlags(createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); identifier.symbol = symbol; @@ -6507,7 +6512,7 @@ namespace ts { */ function getPropertyNameFromType(type: StringLiteralType | NumberLiteralType | UniqueESSymbolType): __String { if (type.flags & TypeFlags.UniqueESSymbol) { - return (type).escapedName; + return getPropertyNameForUniqueESSymbol(type.symbol); } if (type.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) { return escapeLeadingUnderscores("" + (type).value); @@ -9730,6 +9735,9 @@ namespace ts { } function getLiteralTypeFromPropertyName(name: PropertyName) { + if (isPrivateName(name)) { + return neverType; + } return isIdentifier(name) ? getLiteralType(unescapeLeadingUnderscores(name.escapedText)) : getRegularTypeOfLiteralType(isComputedPropertyName(name) ? checkComputedPropertyName(name) : checkExpression(name)); } @@ -13005,23 +13013,44 @@ namespace ts { const unmatchedProperty = getUnmatchedProperty(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false); if (unmatchedProperty) { if (reportErrors) { - const props = arrayFrom(getUnmatchedProperties(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false)); - if (!headMessage || (headMessage.code !== Diagnostics.Class_0_incorrectly_implements_interface_1.code && - headMessage.code !== Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass.code)) { - suppressNextError = true; // Retain top-level error for interface implementing issues, otherwise omit it - } - if (props.length === 1) { - const propName = symbolToString(unmatchedProperty); - reportError(Diagnostics.Property_0_is_missing_in_type_1_but_required_in_type_2, propName, typeToString(source), typeToString(target)); - if (length(unmatchedProperty.declarations)) { - associateRelatedInfo(createDiagnosticForNode(unmatchedProperty.declarations[0], Diagnostics._0_is_declared_here, propName)); + let hasReported = false; + // give specific error in case where private names have the same description + if ( + unmatchedProperty.valueDeclaration + && isNamedDeclaration(unmatchedProperty.valueDeclaration) + && isPrivateName(unmatchedProperty.valueDeclaration.name) + && isClassDeclaration(source.symbol.valueDeclaration) + ) { + const privateNameDescription = unmatchedProperty.valueDeclaration.name.escapedText; + const symbolTableKey = getPropertyNameForPrivateNameDescription(source.symbol, privateNameDescription); + if (symbolTableKey && !!getPropertyOfType(source, symbolTableKey)) { + reportError( + Diagnostics.Property_0_is_missing_in_type_1_While_type_1_has_a_private_member_with_the_same_spelling_its_declaration_and_accessibility_are_distinct, + diagnosticName(privateNameDescription), + diagnosticName(source.symbol.valueDeclaration.name || ("(anonymous)" as __String)) + ); + hasReported = true; } } - else if (props.length > 5) { // arbitrary cutoff for too-long list form - reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2_and_3_more, typeToString(source), typeToString(target), map(props.slice(0, 4), p => symbolToString(p)).join(", "), props.length - 4); - } - else { - reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2, typeToString(source), typeToString(target), map(props, p => symbolToString(p)).join(", ")); + if (!hasReported) { + const props = arrayFrom(getUnmatchedProperties(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false)); + if (!headMessage || (headMessage.code !== Diagnostics.Class_0_incorrectly_implements_interface_1.code && + headMessage.code !== Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass.code)) { + suppressNextError = true; // Retain top-level error for interface implementing issues, otherwise omit it + } + if (props.length === 1) { + const propName = symbolToString(unmatchedProperty); + reportError(Diagnostics.Property_0_is_missing_in_type_1_but_required_in_type_2, propName, typeToString(source), typeToString(target)); + if (length(unmatchedProperty.declarations)) { + associateRelatedInfo(createDiagnosticForNode(unmatchedProperty.declarations[0], Diagnostics._0_is_declared_here, propName)); + } + } + else if (props.length > 5) { // arbitrary cutoff for too-long list form + reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2_and_3_more, typeToString(source), typeToString(target), map(props.slice(0, 4), p => symbolToString(p)).join(", "), props.length - 4); + } + else { + reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2, typeToString(source), typeToString(target), map(props, p => symbolToString(p)).join(", ")); + } } } return Ternary.False; @@ -15786,8 +15815,10 @@ namespace ts { const root = getReferenceRoot(node); const parent = root.parent; const isLengthPushOrUnshift = parent.kind === SyntaxKind.PropertyAccessExpression && ( - (parent).name.escapedText === "length" || - parent.parent.kind === SyntaxKind.CallExpression && isPushOrUnshiftIdentifier((parent).name)); + (parent).name.escapedText === "length" || ( + parent.parent.kind === SyntaxKind.CallExpression + && isIdentifier((parent as PropertyAccessExpression).name) + && isPushOrUnshiftIdentifier((parent as PropertyAccessExpression).name as Identifier))); const isElementAssignment = parent.kind === SyntaxKind.ElementAccessExpression && (parent).expression === root && parent.parent.kind === SyntaxKind.BinaryExpression && @@ -19488,7 +19519,49 @@ namespace ts { return checkPropertyAccessExpressionOrQualifiedName(node, node.left, node.right); } - function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) { + function getPropertyForPrivateName(apparentType: Type, leftType: Type, right: PrivateName, errorNode: Node | undefined): Symbol | undefined { + let classWithShadowedPrivateName; + let container = getContainingClass(right); + while (container) { + const symbolTableKey = getPropertyNameForPrivateNameDescription(container.symbol, right.escapedText); + if (symbolTableKey) { + const prop = getPropertyOfType(apparentType, symbolTableKey); + if (prop) { + if (classWithShadowedPrivateName) { + if (errorNode) { + error( + errorNode, + Diagnostics.This_usage_of_0_refers_to_the_private_member_declared_in_its_enclosing_class_While_type_1_has_a_private_member_with_the_same_spelling_its_declaration_and_accessibility_are_distinct, + diagnosticName(right), + diagnosticName(classWithShadowedPrivateName.name || ("(anonymous)" as __String)) + ); + } + return undefined; + } + return prop; + } + else { + classWithShadowedPrivateName = container; + } + } + container = getContainingClass(container); + } + // If this isn't a case of shadowing, and the lhs has a property with the same + // private name description, then there is a privacy violation + if (leftType.symbol.members) { + const symbolTableKey = getPropertyNameForPrivateNameDescription(leftType.symbol, right.escapedText); + const prop = getPropertyOfType(apparentType, symbolTableKey); + if (prop) { + if (errorNode) { + error(right, Diagnostics.Property_0_is_not_accessible_outside_class_1_because_it_has_a_private_name, symbolToString(prop), typeToString(getDeclaringClass(prop)!)); + } + } + } + // not found + return undefined; + } + + function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier | PrivateName) { let propType: Type; const leftType = checkNonNullExpression(left); const parentSymbol = getNodeLinks(left).resolvedSymbol; @@ -19500,13 +19573,13 @@ namespace ts { return apparentType; } const assignmentKind = getAssignmentTargetKind(node); - const prop = getPropertyOfType(apparentType, right.escapedText); + const prop = isPrivateName(right) ? getPropertyForPrivateName(apparentType, leftType, right, /* errorNode */ right) : getPropertyOfType(apparentType, right.escapedText); if (isIdentifier(left) && parentSymbol && !(prop && isConstEnumOrConstEnumOnlyModule(prop))) { markAliasReferenced(parentSymbol, node); } if (!prop) { const indexInfo = getIndexInfoOfType(apparentType, IndexKind.String); - if (!(indexInfo && indexInfo.type)) { + if (!(indexInfo && indexInfo.type) || isPrivateName(right)) { if (isJSLiteralType(leftType)) { return anyType; } @@ -19576,7 +19649,7 @@ namespace ts { return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType; } - function checkPropertyNotUsedBeforeDeclaration(prop: Symbol, node: PropertyAccessExpression | QualifiedName, right: Identifier): void { + function checkPropertyNotUsedBeforeDeclaration(prop: Symbol, node: PropertyAccessExpression | QualifiedName, right: Identifier | PrivateName): void { const { valueDeclaration } = prop; if (!valueDeclaration) { return; @@ -19658,7 +19731,7 @@ namespace ts { return getIntersectionType(x); } - function reportNonexistentProperty(propNode: Identifier, containingType: Type) { + function reportNonexistentProperty(propNode: Identifier | PrivateName, containingType: Type) { let errorInfo: DiagnosticMessageChain | undefined; let relatedInfo: Diagnostic | undefined; if (containingType.flags & TypeFlags.Union && !(containingType.flags & TypeFlags.Primitive)) { @@ -19701,11 +19774,11 @@ namespace ts { return prop !== undefined && prop.valueDeclaration && hasModifier(prop.valueDeclaration, ModifierFlags.Static); } - function getSuggestedSymbolForNonexistentProperty(name: Identifier | string, containingType: Type): Symbol | undefined { + function getSuggestedSymbolForNonexistentProperty(name: Identifier | PrivateName | string, containingType: Type): Symbol | undefined { return getSpellingSuggestionForName(isString(name) ? name : idText(name), getPropertiesOfType(containingType), SymbolFlags.Value); } - function getSuggestionForNonexistentProperty(name: Identifier | string, containingType: Type): string | undefined { + function getSuggestionForNonexistentProperty(name: Identifier | PrivateName | string, containingType: Type): string | undefined { const suggestion = getSuggestedSymbolForNonexistentProperty(name, containingType); return suggestion && symbolName(suggestion); } @@ -22517,6 +22590,9 @@ namespace ts { error(expr, Diagnostics.The_operand_of_a_delete_operator_must_be_a_property_reference); return booleanType; } + if (expr.kind === SyntaxKind.PropertyAccessExpression && isPrivateName((expr as PropertyAccessExpression).name)) { + error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_private_name); + } const links = getNodeLinks(expr); const symbol = getExportSymbolOfValueSymbolIfExported(links.resolvedSymbol); if (symbol && isReadonlySymbol(symbol)) { @@ -25499,9 +25575,9 @@ namespace ts { } } - function getIdentifierFromEntityNameExpression(node: Identifier | PropertyAccessExpression): Identifier; - function getIdentifierFromEntityNameExpression(node: Expression): Identifier | undefined; - function getIdentifierFromEntityNameExpression(node: Expression): Identifier | undefined { + function getIdentifierFromEntityNameExpression(node: Identifier | PropertyAccessExpression): Identifier | PrivateName; + function getIdentifierFromEntityNameExpression(node: Expression): Identifier | PrivateName | undefined; + function getIdentifierFromEntityNameExpression(node: Expression): Identifier | PrivateName | undefined { switch (node.kind) { case SyntaxKind.Identifier: return node as Identifier; @@ -30583,6 +30659,9 @@ namespace ts { else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) && (node).dotDotDotToken) { return grammarErrorOnNode(node, Diagnostics.A_parameter_property_cannot_be_declared_using_a_rest_parameter); } + else if (isNamedDeclaration(node) && (flags & ModifierFlags.AccessibilityModifier) && node.name.kind === SyntaxKind.PrivateName) { + return grammarErrorOnNode(node, Diagnostics.Accessibility_modifiers_cannot_be_used_with_private_names); + } if (flags & ModifierFlags.Async) { return checkGrammarAsyncModifier(node, lastAsync!); } @@ -30980,6 +31059,10 @@ namespace ts { return grammarErrorOnNode(prop.equalsToken!, Diagnostics.can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment); } + if (name.kind === SyntaxKind.PrivateName) { + return grammarErrorOnNode(name, Diagnostics.Private_names_are_not_allowed_outside_class_bodies); + } + // Modifiers are never allowed on properties except for 'async' on a method declaration if (prop.modifiers) { for (const mod of prop.modifiers!) { // TODO: GH#19955 diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 9ae3e1ca77eae..bba7863e4701e 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4478,6 +4478,34 @@ "category": "Error", "code": 18003 }, + "Accessibility modifiers cannot be used with private names.": { + "category": "Error", + "code": 18004 + }, + "The operand of a delete operator cannot be a private name.": { + "category": "Error", + "code": 18005 + }, + "'#constructor' is a reserved word.": { + "category": "Error", + "code": 18006 + }, + "Property '{0}' is not accessible outside class '{1}' because it has a private name.": { + "category": "Error", + "code": 18007 + }, + "This usage of '{0}' refers to the private member declared in its enclosing class. While type '{1}' has a private member with the same spelling, its declaration and accessibility are distinct.": { + "category": "Error", + "code": 18008 + }, + "Property '{0}' is missing in type '{1}'. While type '{1}' has a private member with the same spelling, its declaration and accessibility are distinct.": { + "category": "Error", + "code": 18009 + }, + "Private names are not allowed outside class bodies.": { + "category": "Error", + "code": 18010 + }, "File is a CommonJS module; it may be converted to an ES6 module.": { "category": "Suggestion", diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index be867db68fb77..647d888a4fdcc 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1138,6 +1138,10 @@ namespace ts { case SyntaxKind.Identifier: return emitIdentifier(node); + // PrivateNames + case SyntaxKind.PrivateName: + return emitPrivateName(node as PrivateName); + // Parse tree nodes // Names @@ -1437,6 +1441,10 @@ namespace ts { case SyntaxKind.Identifier: return emitIdentifier(node); + // Private Names + case SyntaxKind.PrivateName: + return emitPrivateName(node as PrivateName); + // Reserved words case SyntaxKind.FalseKeyword: case SyntaxKind.NullKeyword: @@ -1695,6 +1703,12 @@ namespace ts { emitList(node, node.typeArguments, ListFormat.TypeParameters); // Call emitList directly since it could be an array of TypeParameterDeclarations _or_ type arguments } + function emitPrivateName(node: PrivateName) { + const writeText = node.symbol ? writeSymbol : write; + writeText(getTextOfNode(node, /*includeTrivia*/ false), node.symbol); + emitList(node, /*typeArguments*/ undefined, ListFormat.TypeParameters); // Call emitList directly since it could be an array of TypeParameterDeclarations _or_ type arguments + } + // // Names // @@ -4175,7 +4189,7 @@ namespace ts { function getLiteralTextOfNode(node: LiteralLikeNode, neverAsciiEscape: boolean | undefined): string { if (node.kind === SyntaxKind.StringLiteral && (node).textSourceNode) { const textSourceNode = (node).textSourceNode!; - if (isIdentifier(textSourceNode)) { + if (isIdentifierOrPrivateName(textSourceNode)) { return neverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? `"${escapeString(getTextOfNode(textSourceNode))}"` : `"${escapeNonAsciiString(getTextOfNode(textSourceNode))}"`; diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 5f4299f1e2021..b394990523e63 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -114,7 +114,7 @@ namespace ts { return node; } - function createLiteralFromNode(sourceNode: PropertyNameLiteral): StringLiteral { + function createLiteralFromNode(sourceNode: Exclude): StringLiteral { const node = createStringLiteral(getTextOfIdentifierOrLiteral(sourceNode)); node.textSourceNode = sourceNode; return node; @@ -1004,7 +1004,7 @@ namespace ts { : node; } - export function createPropertyAccess(expression: Expression, name: string | Identifier | undefined) { + export function createPropertyAccess(expression: Expression, name: string | Identifier | PrivateName | undefined) { const node = createSynthesizedNode(SyntaxKind.PropertyAccessExpression); node.expression = parenthesizeForAccess(expression); node.name = asName(name)!; // TODO: GH#18217 @@ -1012,7 +1012,7 @@ namespace ts { return node; } - export function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier) { + export function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier | PrivateName) { // Because we are updating existed propertyAccess we want to inherit its emitFlags // instead of using the default from createPropertyAccess return node.expression !== expression @@ -3054,7 +3054,7 @@ namespace ts { // Utilities - function asName(name: string | T): T | Identifier { + function asName(name: string | T): T | Identifier { return isString(name) ? createIdentifier(name) : name; } @@ -3439,7 +3439,7 @@ namespace ts { } else { const expression = setTextRange( - isIdentifier(memberName) + (isIdentifier(memberName) || isPrivateName(memberName)) ? createPropertyAccess(target, memberName) : createElementAccess(target, memberName), memberName @@ -3870,7 +3870,7 @@ namespace ts { } } - export function createExpressionForPropertyName(memberName: PropertyName): Expression { + export function createExpressionForPropertyName(memberName: Exclude): Expression { if (isIdentifier(memberName)) { return createLiteral(memberName); } @@ -3882,11 +3882,17 @@ namespace ts { } } + /** + * accessor declaration that can be converted to an expression (`name` field cannot be a `PrivateName`) + */ + type ExpressionableAccessorDeclaration = AccessorDeclaration & {name: Exclude}; + export function createExpressionForObjectLiteralElementLike(node: ObjectLiteralExpression, property: ObjectLiteralElementLike, receiver: Expression): Expression | undefined { switch (property.kind) { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - return createExpressionForAccessorDeclaration(node.properties, property, receiver, !!node.multiLine); + // type assertion `as ExpressionableAccessorDeclaration` is safe because PrivateNames are not allowed in object literals + return createExpressionForAccessorDeclaration(node.properties, property as ExpressionableAccessorDeclaration, receiver, !!node.multiLine); case SyntaxKind.PropertyAssignment: return createExpressionForPropertyAssignment(property, receiver); case SyntaxKind.ShorthandPropertyAssignment: @@ -3896,7 +3902,7 @@ namespace ts { } } - function createExpressionForAccessorDeclaration(properties: NodeArray, property: AccessorDeclaration, receiver: Expression, multiLine: boolean) { + function createExpressionForAccessorDeclaration(properties: NodeArray, property: ExpressionableAccessorDeclaration, receiver: Expression, multiLine: boolean) { const { firstAccessor, getAccessor, setAccessor } = getAllAccessorDeclarations(properties, property); if (property === firstAccessor) { const properties: ObjectLiteralElementLike[] = []; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 03d0f166b81b8..acbab5912025a 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1369,6 +1369,9 @@ namespace ts { if (allowComputedPropertyNames && token() === SyntaxKind.OpenBracketToken) { return parseComputedPropertyName(); } + if (token() === SyntaxKind.PrivateName) { + return parsePrivateName(); + } return parseIdentifierName(); } @@ -1392,6 +1395,17 @@ namespace ts { return finishNode(node); } + function createPrivateName(): PrivateName { + const node = createNode(SyntaxKind.PrivateName) as PrivateName; + node.escapedText = escapeLeadingUnderscores(scanner.getTokenText()); + nextToken(); + return finishNode(node); + } + + function parsePrivateName(): PrivateName { + return createPrivateName(); + } + function parseContextualModifier(t: SyntaxKind): boolean { return token() === t && tryParse(nextTokenCanFollowModifier); } @@ -2149,7 +2163,7 @@ namespace ts { break; } dotPos = scanner.getStartPos(); - entity = createQualifiedName(entity, parseRightSideOfDot(allowReservedWords)); + entity = createQualifiedName(entity, parseRightSideOfDot(allowReservedWords, /* allowPrivateNames */ false) as Identifier); } return entity; } @@ -2161,7 +2175,7 @@ namespace ts { return finishNode(node); } - function parseRightSideOfDot(allowIdentifierNames: boolean): Identifier { + function parseRightSideOfDot(allowIdentifierNames: boolean, allowPrivateNames: boolean): Identifier | PrivateName { // Technically a keyword is valid here as all identifiers and keywords are identifier names. // However, often we'll encounter this in error situations when the identifier or keyword // is actually starting another valid construct. @@ -2192,6 +2206,10 @@ namespace ts { } } + if (allowPrivateNames && token() === SyntaxKind.PrivateName) { + return parsePrivateName(); + } + return allowIdentifierNames ? parseIdentifierName() : parseIdentifier(); } @@ -4196,7 +4214,8 @@ namespace ts { const node = createNode(SyntaxKind.PropertyAccessExpression, expression.pos); node.expression = expression; parseExpectedToken(SyntaxKind.DotToken, Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access); - node.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); + // private names will never work with `super` (`super.#foo`), but that's a semantic error, not syntactic + node.name = parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateNames*/ true); return finishNode(node); } @@ -4367,7 +4386,7 @@ namespace ts { while (parseOptional(SyntaxKind.DotToken)) { const propertyAccess: JsxTagNamePropertyAccess = createNode(SyntaxKind.PropertyAccessExpression, expression.pos); propertyAccess.expression = expression; - propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); + propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateNames*/ true); expression = finishNode(propertyAccess); } return expression; @@ -4470,7 +4489,7 @@ namespace ts { if (dotToken) { const propertyAccess = createNode(SyntaxKind.PropertyAccessExpression, expression.pos); propertyAccess.expression = expression; - propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); + propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateNames*/ true); expression = finishNode(propertyAccess); continue; } diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index e31876962b7da..d15c9312c1a3a 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -1833,6 +1833,20 @@ namespace ts { error(Diagnostics.Invalid_character); pos++; return token = SyntaxKind.Unknown; + case CharacterCodes.hash: + pos++; + if (isIdentifierStart(ch = text.charCodeAt(pos), languageVersion)) { + pos++; + while (pos < end && isIdentifierPart(ch = text.charCodeAt(pos), languageVersion)) pos++; + tokenValue = text.substring(tokenPos, pos); + if (ch === CharacterCodes.backslash) { + tokenValue += scanIdentifierParts(); + } + return token = SyntaxKind.PrivateName; + } + error(Diagnostics.Invalid_character); + // no `pos++` because already advanced at beginning of this `case` statement + return token = SyntaxKind.Unknown; default: if (isIdentifierStart(ch, languageVersion)) { pos++; diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index d8a2848bcc304..1d1895e6ace87 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -33,6 +33,7 @@ namespace ts { addRange(transformers, customTransformers && customTransformers.before); transformers.push(transformTypeScript); + transformers.push(transformClassProperties); if (jsx === JsxEmit.React) { transformers.push(transformJsx); diff --git a/src/compiler/transformers/classProperties.ts b/src/compiler/transformers/classProperties.ts new file mode 100644 index 0000000000000..6787c2baa2236 --- /dev/null +++ b/src/compiler/transformers/classProperties.ts @@ -0,0 +1,900 @@ +/*@internal*/ +namespace ts { + const enum ClassPropertySubstitutionFlags { + /** + * Enables substitutions for class expressions with static fields + * which have initializers that reference the class name. + */ + ClassAliases = 1 << 0, + } + + const enum PrivateNamePlacement { + InstanceField + } + + type PrivateNameInfo = PrivateNamedInstanceField; + + interface PrivateNamedInstanceField { + placement: PrivateNamePlacement.InstanceField; + weakMapName: Identifier; + } + + /** + * A mapping of private names to information needed for transformation. + */ + type PrivateNameEnvironment = UnderscoreEscapedMap; + + /** + * Transforms ECMAScript Class Syntax. + * TypeScript parameter property syntax is transformed in the TypeScript transformer. + * For now, this transforms public field declarations using TypeScript class semantics + * (where the declarations get elided and initializers are transformed as assignments in the constructor). + * Eventually, this transform will change to the ECMAScript semantics (with Object.defineProperty). + */ + export function transformClassProperties(context: TransformationContext) { + const { + hoistVariableDeclaration, + endLexicalEnvironment, + resumeLexicalEnvironment + } = context; + const resolver = context.getEmitResolver(); + + const previousOnSubstituteNode = context.onSubstituteNode; + context.onSubstituteNode = onSubstituteNode; + + let enabledSubstitutions: ClassPropertySubstitutionFlags; + + let classAliases: Identifier[]; + + /** + * Tracks what computed name expressions originating from elided names must be inlined + * at the next execution site, in document order + */ + let pendingExpressions: Expression[] | undefined; + + /** + * Tracks what computed name expression statements and static property initializers must be + * emitted at the next execution site, in document order (for decorated classes). + */ + let pendingStatements: Statement[] | undefined; + + const privateNameEnvironmentStack: PrivateNameEnvironment[] = []; + + return chainBundle(transformSourceFile); + + function transformSourceFile(node: SourceFile) { + if (node.isDeclarationFile) { + return node; + } + const visited = visitEachChild(node, visitor, context); + addEmitHelpers(visited, context.readEmitHelpers()); + return visited; + } + + function visitor(node: Node): VisitResult { + switch (node.kind) { + case SyntaxKind.ClassExpression: + case SyntaxKind.ClassDeclaration: + return visitClassLike(node as ClassLikeDeclaration); + case SyntaxKind.PropertyDeclaration: + return visitPropertyDeclaration(node as PropertyDeclaration); + case SyntaxKind.VariableStatement: + return visitVariableStatement(node as VariableStatement); + case SyntaxKind.ComputedPropertyName: + return visitComputedPropertyName(node as ComputedPropertyName); + case SyntaxKind.PropertyAccessExpression: + return visitPropertyAccessExpression(node as PropertyAccessExpression); + case SyntaxKind.PrefixUnaryExpression: + return visitPrefixUnaryExpression(node as PrefixUnaryExpression); + case SyntaxKind.PostfixUnaryExpression: + return visitPostfixUnaryExpression(node as PostfixUnaryExpression); + case SyntaxKind.CallExpression: + return visitCallExpression(node as CallExpression); + case SyntaxKind.BinaryExpression: + return visitBinaryExpression(node as BinaryExpression); + } + return visitEachChild(node, visitor, context); + } + + /** + * Specialized visitor that visits the immediate children of a class with ESNext syntax. + * + * @param node The node to visit. + */ + function classElementVisitor(node: Node): VisitResult { + switch (node.kind) { + case SyntaxKind.Constructor: + // Constructors for classes using ESNext syntax (like class properties) + // are transformed in `visitClassDeclaration` or `visitClassExpression`. + // We elide them here. The default visitor checks the transformFlags to + // determine whether the node contains ESNext syntax, so it can skip over + // constructors. + return undefined; + + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.IndexSignature: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.MethodDeclaration: + // Fallback to the default visit behavior. + return visitor(node); + + case SyntaxKind.SemicolonClassElement: + return node; + + default: + return Debug.failBadSyntaxKind(node); + } + } + + function visitVariableStatement(node: VariableStatement) { + const savedPendingStatements = pendingStatements; + pendingStatements = []; + + const visitedNode = visitEachChild(node, visitor, context); + const statement = some(pendingStatements) ? + [visitedNode, ...pendingStatements] : + visitedNode; + + pendingStatements = savedPendingStatements; + return statement; + } + + function visitComputedPropertyName(name: ComputedPropertyName) { + let node = visitEachChild(name, visitor, context); + if (some(pendingExpressions)) { + const expressions = pendingExpressions; + expressions.push(name.expression); + pendingExpressions = []; + node = updateComputedPropertyName( + node, + inlineExpressions(expressions) + ); + } + return node; + } + + function visitPropertyDeclaration(node: PropertyDeclaration) { + Debug.assert(!some(node.decorators)); + // Create a temporary variable to store a computed property name (if necessary). + // If it's not inlineable, then we emit an expression after the class which assigns + // the property name to the temporary variable. + const expr = getPropertyNameExpressionIfNeeded(node.name, !!node.initializer); + if (expr && !isSimpleInlineableExpression(expr)) { + (pendingExpressions || (pendingExpressions = [])).push(expr); + } + return undefined; + } + + function visitPropertyAccessExpression(node: PropertyAccessExpression) { + if (isPrivateName(node.name)) { + const privateNameInfo = accessPrivateName(node.name); + if (privateNameInfo) { + switch (privateNameInfo.placement) { + case PrivateNamePlacement.InstanceField: + return setOriginalNode( + setTextRange( + createClassPrivateFieldGetHelper( + context, + visitNode(node.expression, visitor, isExpression), + privateNameInfo.weakMapName + ), + node + ), + node + ); + } + } + } + return visitEachChild(node, visitor, context); + } + + function visitPrefixUnaryExpression(node: PrefixUnaryExpression) { + if (isPrivateNamedPropertyAccessExpression(node.operand)) { + const operator = (node.operator === SyntaxKind.PlusPlusToken) ? + SyntaxKind.PlusEqualsToken : (node.operator === SyntaxKind.MinusMinusToken) ? + SyntaxKind.MinusEqualsToken : undefined; + if (operator) { + const transformedExpr = setOriginalNode( + createBinary( + node.operand, + operator, + createNumericLiteral("1") + ), + node + ); + const visited = visitNode(transformedExpr, visitor); + // If the private name was successfully transformed, + // return the transformed node. Otherwise, leave existing source untouched. + if (visited !== transformedExpr) { + return visited; + } + } + } + return visitEachChild(node, visitor, context); + } + + function visitPostfixUnaryExpression(node: PostfixUnaryExpression) { + if (isPrivateNamedPropertyAccessExpression(node.operand)) { + const operator = (node.operator === SyntaxKind.PlusPlusToken) ? + SyntaxKind.PlusToken : (node.operator === SyntaxKind.MinusMinusToken) ? + SyntaxKind.MinusToken : undefined; + if (operator) { + // Create a temporary variable if the receiver is not inlinable, since we + // will need to access it multiple times. + const receiver = isSimpleInlineableExpression(node.operand.expression) ? + undefined : + getGeneratedNameForNode(node.operand.expression); + // Create a temporary variable to store the value returned by the expression. + const returnValue = createTempVariable(/*recordTempVariable*/ undefined); + + const transformedExpr = createCommaList(compact([ + receiver && createAssignment(receiver, node.operand.expression), + // Store the existing value of the private name in the temporary. + createAssignment(returnValue, receiver ? createPropertyAccess(receiver, node.operand.name) : node.operand), + // Assign to private name. + createAssignment( + receiver ? createPropertyAccess(receiver, node.operand.name) : node.operand, + createBinary( + returnValue, operator, createNumericLiteral("1") + ) + ), + // Return the cached value. + returnValue + ]) as Expression[]); + const visited = visitNode(transformedExpr, visitor); + // If the private name was successfully transformed, + // hoist the temporary variable and return the transformed node. + // Otherwise, leave existing source untouched. + if (visited !== transformedExpr) { + if (receiver) { + hoistVariableDeclaration(receiver); + } + hoistVariableDeclaration(returnValue); + return visited; + } + } + } + return visitEachChild(node, visitor, context); + } + + + function visitCallExpression(node: CallExpression) { + if (isPrivateNamedPropertyAccessExpression(node.expression)) { + // Transform call expressions of private names to properly bind the `this` parameter. + let exprForPropertyAccess: Expression = node.expression.expression; + let receiver = node.expression.expression; + if (!isSimpleInlineableExpression(node.expression.expression)) { + const generatedName = getGeneratedNameForNode(node); + hoistVariableDeclaration(generatedName); + exprForPropertyAccess = setOriginalNode( + createAssignment(generatedName, exprForPropertyAccess), + node.expression.expression + ); + receiver = generatedName; + } + return visitNode( + updateCall( + node, + createPropertyAccess( + updatePropertyAccess( + node.expression, + exprForPropertyAccess, + node.expression.name + ), + "call" + ), + /*typeArguments*/ undefined, + [receiver, ...node.arguments] + ), + visitor + ); + } + return visitEachChild(node, visitor, context); + } + + interface PrivateNameAssignmentExpression extends AssignmentExpression { + left: PrivateNamedPropertyAccessExpression; + } + + function isPrivateNameAssignmentExpression(node: Node): node is PrivateNameAssignmentExpression { + return isAssignmentExpression(node) && isPrivateNamedPropertyAccessExpression(node.left); + } + + function visitBinaryExpression(node: BinaryExpression) { + if (isDestructuringAssignment(node)) { + const left = transformDestructuringAssignmentTarget(node.left); + if (left !== node.left) { + return updateBinary(node, left, node.right, node.operatorToken); + } + } + else if (isPrivateNameAssignmentExpression(node)) { + const privateNameInfo = accessPrivateName(node.left.name); + if (privateNameInfo) { + switch (privateNameInfo.placement) { + case PrivateNamePlacement.InstanceField: { + return transformPrivateNamedInstanceFieldAssignment(privateNameInfo, node); + } + } + } + } + return visitEachChild(node, visitor, context); + } + + function transformPrivateNamedInstanceFieldAssignment(privateNameInfo: PrivateNamedInstanceField, node: PrivateNameAssignmentExpression) { + if (isCompoundAssignment(node.operatorToken.kind)) { + const isReceiverInlineable = isSimpleInlineableExpression(node.left.expression); + const getReceiver = isReceiverInlineable ? node.left.expression : createTempVariable(hoistVariableDeclaration); + const setReceiver = isReceiverInlineable + ? node.left.expression + : createAssignment(getReceiver, node.left.expression); + return setOriginalNode( + createClassPrivateFieldSetHelper( + context, + setReceiver, + privateNameInfo.weakMapName, + createBinary( + createClassPrivateFieldGetHelper( + context, + getReceiver, + privateNameInfo.weakMapName + ), + getOperatorForCompoundAssignment(node.operatorToken.kind), + visitNode(node.right, visitor) + ) + ), + node + ); + } + else { + return setOriginalNode( + createClassPrivateFieldSetHelper( + context, + node.left.expression, + privateNameInfo.weakMapName, + visitNode(node.right, visitor) + ), + node + ); + } + } + + /** + * Set up the environment for a class. + */ + function visitClassLike(node: ClassLikeDeclaration) { + const savedPendingExpressions = pendingExpressions; + pendingExpressions = undefined; + startPrivateNameEnvironment(); + + const result = isClassDeclaration(node) ? + visitClassDeclaration(node) : + visitClassExpression(node); + + endPrivateNameEnvironment(); + pendingExpressions = savedPendingExpressions; + return result; + } + + function visitClassDeclaration(node: ClassDeclaration) { + const extendsClauseElement = getEffectiveBaseTypeNode(node); + const isDerivedClass = !!(extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword); + + const statements: Statement[] = [ + updateClassDeclaration( + node, + node.decorators, + node.modifiers, + node.name, + node.typeParameters, + node.heritageClauses, + transformClassMembers(node, isDerivedClass) + ) + ]; + + // Write any pending expressions from elided or moved computed property names + if (some(pendingExpressions)) { + statements.push(createExpressionStatement(inlineExpressions(pendingExpressions))); + } + + // Emit static property assignment. Because classDeclaration is lexically evaluated, + // it is safe to emit static property assignment after classDeclaration + // From ES6 specification: + // HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using + // a lexical declaration such as a LexicalDeclaration or a ClassDeclaration. + const staticProperties = getInitializedProperties(node, /*isStatic*/ true); + if (some(staticProperties)) { + addInitializedPropertyStatements(statements, staticProperties, getInternalName(node)); + } + + return statements; + } + + function visitClassExpression(node: ClassExpression): Expression { + // If this class expression is a transformation of a decorated class declaration, + // then we want to output the pendingExpressions as statements, not as inlined + // expressions with the class statement. + // + // In this case, we use pendingStatements to produce the same output as the + // class declaration transformation. The VariableStatement visitor will insert + // these statements after the class expression variable statement. + const isDecoratedClassDeclaration = isClassDeclaration(getOriginalNode(node)); + + const staticProperties = getInitializedProperties(node, /*isStatic*/ true); + const extendsClauseElement = getEffectiveBaseTypeNode(node); + const isDerivedClass = !!(extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword); + + const classExpression = updateClassExpression( + node, + node.modifiers, + node.name, + node.typeParameters, + visitNodes(node.heritageClauses, visitor, isHeritageClause), + transformClassMembers(node, isDerivedClass) + ); + + if (some(staticProperties) || some(pendingExpressions)) { + if (isDecoratedClassDeclaration) { + Debug.assertDefined(pendingStatements, "Decorated classes transformed by TypeScript are expected to be within a variable declaration."); + + // Write any pending expressions from elided or moved computed property names + if (pendingStatements && pendingExpressions && some(pendingExpressions)) { + pendingStatements.push(createExpressionStatement(inlineExpressions(pendingExpressions))); + } + + if (pendingStatements && some(staticProperties)) { + addInitializedPropertyStatements(pendingStatements, staticProperties, getInternalName(node)); + } + return classExpression; + } + else { + const expressions: Expression[] = []; + const isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference; + const temp = createTempVariable(hoistVariableDeclaration, !!isClassWithConstructorReference); + if (isClassWithConstructorReference) { + // record an alias as the class name is not in scope for statics. + enableSubstitutionForClassAliases(); + const alias = getSynthesizedClone(temp); + alias.autoGenerateFlags &= ~GeneratedIdentifierFlags.ReservedInNestedScopes; + classAliases[getOriginalNodeId(node)] = alias; + } + + // To preserve the behavior of the old emitter, we explicitly indent + // the body of a class with static initializers. + setEmitFlags(classExpression, EmitFlags.Indented | getEmitFlags(classExpression)); + expressions.push(startOnNewLine(createAssignment(temp, classExpression))); + // Add any pending expressions leftover from elided or relocated computed property names + addRange(expressions, map(pendingExpressions, startOnNewLine)); + addRange(expressions, generateInitializedPropertyExpressions(staticProperties, temp)); + expressions.push(startOnNewLine(temp)); + + return inlineExpressions(expressions); + } + } + + return classExpression; + } + + function transformClassMembers(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { + // Declare private names. + node.members.forEach(member => { + if (isPrivateNamedPropertyDeclaration(member)) { + addPrivateNameToEnvironment(member.name); + } + }); + + const members: ClassElement[] = []; + const constructor = transformConstructor(node, isDerivedClass); + if (constructor) { + members.push(constructor); + } + addRange(members, visitNodes(node.members, classElementVisitor, isClassElement)); + return setTextRange(createNodeArray(members), /*location*/ node.members); + } + + function transformConstructor(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { + const constructor = visitNode(getFirstConstructorWithBody(node), visitor, isConstructorDeclaration); + const containsPropertyInitializerOrPrivateName = forEach( + node.members, + member => isInitializedProperty(member) || isPrivateNamedPropertyDeclaration(member) + ); + if (!containsPropertyInitializerOrPrivateName) { + return constructor; + } + const parameters = visitParameterList(constructor ? constructor.parameters : undefined, visitor, context); + const body = transformConstructorBody(node, constructor, isDerivedClass); + if (!body) { + return undefined; + } + return startOnNewLine( + setOriginalNode( + setTextRange( + createConstructor( + /*decorators*/ undefined, + /*modifiers*/ undefined, + parameters, + body + ), + constructor || node + ), + constructor + ) + ); + } + + function transformConstructorBody(node: ClassDeclaration | ClassExpression, constructor: ConstructorDeclaration | undefined, isDerivedClass: boolean) { + const properties = node.members.filter( + (node): node is PropertyDeclaration => isPropertyDeclaration(node) && !hasStaticModifier(node) + ); + + // Only generate synthetic constructor when there are property initializers to move. + if (!constructor && !some(properties)) { + return visitFunctionBody(/*node*/ undefined, visitor, context); + } + + resumeLexicalEnvironment(); + + let indexOfFirstStatement = 0; + let statements: Statement[] = []; + + if (!constructor && isDerivedClass) { + // Add a synthetic `super` call: + // + // super(...arguments); + // + statements.push( + createExpressionStatement( + createCall( + createSuper(), + /*typeArguments*/ undefined, + [createSpread(createIdentifier("arguments"))] + ) + ) + ); + } + + if (constructor) { + indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements, visitor); + } + + // Add the property initializers. Transforms this: + // + // public x = 1; + // + // Into this: + // + // constructor() { + // this.x = 1; + // } + // + addInitializedPropertyStatements(statements, properties, createThis()); + + // Add existing statements, skipping the initial super call. + if (constructor) { + addRange(statements, visitNodes(constructor.body!.statements, visitor, isStatement, indexOfFirstStatement)); + } + + statements = mergeLexicalEnvironment(statements, endLexicalEnvironment()); + + return setTextRange( + createBlock( + setTextRange( + createNodeArray(statements), + /*location*/ constructor ? constructor.body!.statements : node.members + ), + /*multiLine*/ true + ), + /*location*/ constructor ? constructor.body : undefined + ); + } + + /** + * Generates assignment statements for property initializers. + * + * @param properties An array of property declarations to transform. + * @param receiver The receiver on which each property should be assigned. + */ + function addInitializedPropertyStatements(statements: Statement[], properties: ReadonlyArray, receiver: LeftHandSideExpression) { + for (const property of properties) { + const expression = transformProperty(property, receiver); + if (!expression) { + continue; + } + const statement = createExpressionStatement(expression); + setSourceMapRange(statement, moveRangePastModifiers(property)); + setCommentRange(statement, property); + setOriginalNode(statement, property); + statements.push(statement); + } + } + + /** + * Generates assignment expressions for property initializers. + * + * @param properties An array of property declarations to transform. + * @param receiver The receiver on which each property should be assigned. + */ + function generateInitializedPropertyExpressions(properties: ReadonlyArray, receiver: LeftHandSideExpression) { + const expressions: Expression[] = []; + for (const property of properties) { + const expression = transformProperty(property, receiver); + if (!expression) { + continue; + } + startOnNewLine(expression); + setSourceMapRange(expression, moveRangePastModifiers(property)); + setCommentRange(expression, property); + setOriginalNode(expression, property); + expressions.push(expression); + } + + return expressions; + } + + /** + * Transforms a property initializer into an assignment statement. + * + * @param property The property declaration. + * @param receiver The object receiving the property assignment. + */ + function transformProperty(property: PropertyDeclaration, receiver: LeftHandSideExpression) { + // We generate a name here in order to reuse the value cached by the relocated computed name expression (which uses the same generated name) + const propertyName = isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression) + ? updateComputedPropertyName(property.name, getGeneratedNameForNode(property.name)) + : property.name; + const initializer = visitNode(property.initializer, visitor, isExpression); + + if (isPrivateName(propertyName)) { + const privateNameInfo = accessPrivateName(propertyName); + if (privateNameInfo) { + switch (privateNameInfo.placement) { + case PrivateNamePlacement.InstanceField: { + return createPrivateInstanceFieldInitializer( + receiver, + initializer, + privateNameInfo.weakMapName + ); + } + } + } + } + if (!initializer) { + return undefined; + } + + const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName); + + return createAssignment(memberAccess, initializer); + } + + function enableSubstitutionForClassAliases() { + if ((enabledSubstitutions & ClassPropertySubstitutionFlags.ClassAliases) === 0) { + enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassAliases; + + // We need to enable substitutions for identifiers. This allows us to + // substitute class names inside of a class declaration. + context.enableSubstitution(SyntaxKind.Identifier); + + // Keep track of class aliases. + classAliases = []; + } + } + + /** + * Hooks node substitutions. + * + * @param hint The context for the emitter. + * @param node The node to substitute. + */ + function onSubstituteNode(hint: EmitHint, node: Node) { + node = previousOnSubstituteNode(hint, node); + if (hint === EmitHint.Expression) { + return substituteExpression(node as Expression); + } + return node; + } + + function substituteExpression(node: Expression) { + switch (node.kind) { + case SyntaxKind.Identifier: + return substituteExpressionIdentifier(node as Identifier); + } + return node; + } + + function substituteExpressionIdentifier(node: Identifier): Expression { + return trySubstituteClassAlias(node) || node; + } + + function trySubstituteClassAlias(node: Identifier): Expression | undefined { + if (enabledSubstitutions & ClassPropertySubstitutionFlags.ClassAliases) { + if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ConstructorReferenceInClass) { + // Due to the emit for class decorators, any reference to the class from inside of the class body + // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind + // behavior of class names in ES6. + // Also, when emitting statics for class expressions, we must substitute a class alias for + // constructor references in static property initializers. + const declaration = resolver.getReferencedValueDeclaration(node); + if (declaration) { + const classAlias = classAliases[declaration.id!]; // TODO: GH#18217 + if (classAlias) { + const clone = getSynthesizedClone(classAlias); + setSourceMapRange(clone, node); + setCommentRange(clone, node); + return clone; + } + } + } + } + + return undefined; + } + + + /** + * If the name is a computed property, this function transforms it, then either returns an expression which caches the + * value of the result or the expression itself if the value is either unused or safe to inline into multiple locations + * @param shouldHoist Does the expression need to be reused? (ie, for an initializer or a decorator) + */ + function getPropertyNameExpressionIfNeeded(name: PropertyName, shouldHoist: boolean): Expression | undefined { + if (isComputedPropertyName(name)) { + const expression = visitNode(name.expression, visitor, isExpression); + const innerExpression = skipPartiallyEmittedExpressions(expression); + const inlinable = isSimpleInlineableExpression(innerExpression); + const alreadyTransformed = isAssignmentExpression(innerExpression) && isGeneratedIdentifier(innerExpression.left); + if (!alreadyTransformed && !inlinable && shouldHoist) { + const generatedName = getGeneratedNameForNode(name); + hoistVariableDeclaration(generatedName); + return createAssignment(generatedName, expression); + } + return (inlinable || isIdentifier(innerExpression)) ? undefined : expression; + } + } + + function startPrivateNameEnvironment() { + const env: PrivateNameEnvironment = createUnderscoreEscapedMap(); + privateNameEnvironmentStack.push(env); + return env; + } + + function endPrivateNameEnvironment() { + privateNameEnvironmentStack.pop(); + } + + function addPrivateNameToEnvironment(name: PrivateName) { + const env = last(privateNameEnvironmentStack); + const text = getTextOfPropertyName(name) as string; + const weakMapName = createOptimisticUniqueName("_" + text.substring(1)); + weakMapName.autoGenerateFlags |= GeneratedIdentifierFlags.ReservedInNestedScopes; + hoistVariableDeclaration(weakMapName); + env.set(name.escapedText, { placement: PrivateNamePlacement.InstanceField, weakMapName }); + (pendingExpressions || (pendingExpressions = [])).push( + createAssignment( + weakMapName, + createNew( + createIdentifier("WeakMap"), + /*typeArguments*/ undefined, + [] + ) + ) + ); + } + + function accessPrivateName(name: PrivateName) { + for (let i = privateNameEnvironmentStack.length - 1; i >= 0; --i) { + const env = privateNameEnvironmentStack[i]; + if (env.has(name.escapedText)) { + return env.get(name.escapedText); + } + } + return undefined; + } + + + function wrapPrivateNameForDestructuringTarget(node: PrivateNamedPropertyAccessExpression) { + return createPropertyAccess( + createObjectLiteral([ + createSetAccessor( + /*decorators*/ undefined, + /*modifiers*/ undefined, + "value", + [createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, "x", + /*questionToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined + )], + createBlock( + [createExpressionStatement( + visitNode( + createAssignment(node, createIdentifier("x")), + visitor + ) + )] + ) + ) + ]), + "value" + ); + } + + function transformDestructuringAssignmentTarget(node: ArrayLiteralExpression | ObjectLiteralExpression) { + const hasPrivateNames = isArrayLiteralExpression(node) ? + forEach(node.elements, isPrivateNamedPropertyAccessExpression) : + forEach(node.properties, property => isPropertyAssignment(property) && isPrivateNamedPropertyAccessExpression(property.initializer)); + if (!hasPrivateNames) { + return node; + } + if (isArrayLiteralExpression(node)) { + // Transforms private names in destructuring assignment array bindings. + // + // Source: + // ([ this.#myProp ] = [ "hello" ]); + // + // Transformation: + // [ { set value(x) { this.#myProp = x; } }.value ] = [ "hello" ]; + return updateArrayLiteral( + node, + node.elements.map( + expr => isPrivateNamedPropertyAccessExpression(expr) ? + wrapPrivateNameForDestructuringTarget(expr) : + expr + ) + ); + } + else { + // Transforms private names in destructuring assignment object bindings. + // + // Source: + // ({ stringProperty: this.#myProp } = { stringProperty: "hello" }); + // + // Transformation: + // ({ stringProperty: { set value(x) { this.#myProp = x; } }.value }) = { stringProperty: "hello" }; + return updateObjectLiteral( + node, + node.properties.map( + prop => isPropertyAssignment(prop) && isPrivateNamedPropertyAccessExpression(prop.initializer) ? + updatePropertyAssignment( + prop, + prop.name, + wrapPrivateNameForDestructuringTarget(prop.initializer) + ) : + prop + ) + ); + } + } + } + + function createPrivateInstanceFieldInitializer(receiver: LeftHandSideExpression, initializer: Expression | undefined, weakMapName: Identifier) { + return createCall( + createPropertyAccess(weakMapName, "set"), + /*typeArguments*/ undefined, + [receiver, initializer || createVoidZero()] + ); + } + + const classPrivateFieldGetHelper: EmitHelper = { + name: "typescript:classPrivateFieldGet", + scoped: false, + text: `var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); };` + }; + + function createClassPrivateFieldGetHelper(context: TransformationContext, receiver: Expression, privateField: Identifier) { + context.requestEmitHelper(classPrivateFieldGetHelper); + return createCall(getHelperName("_classPrivateFieldGet"), /* typeArguments */ undefined, [receiver, privateField]); + } + + const classPrivateFieldSetHelper: EmitHelper = { + name: "typescript:classPrivateFieldSet", + scoped: false, + text: `var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; };` + }; + + function createClassPrivateFieldSetHelper(context: TransformationContext, receiver: Expression, privateField: Identifier, value: Expression) { + context.requestEmitHelper(classPrivateFieldSetHelper); + return createCall(getHelperName("_classPrivateFieldSet"), /* typeArguments */ undefined, [receiver, privateField, value]); + } +} diff --git a/src/compiler/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index b5e829ee6839d..0d1125762ce53 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -535,7 +535,8 @@ namespace ts { const propertyNames: Expression[] = []; let computedTempVariableOffset = 0; for (let i = 0; i < elements.length - 1; i++) { - const propertyName = getPropertyNameOfBindingOrAssignmentElement(elements[i]); + // can safely assume property name is not a PrivateName because PrivateNames are not allowed in object literals + const propertyName = getPropertyNameOfBindingOrAssignmentElement(elements[i]) as Exclude; if (propertyName) { if (isComputedPropertyName(propertyName)) { const temp = computedTempVariables[computedTempVariableOffset]; diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 31916cbb684c1..b735a3eed1b79 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -1641,7 +1641,8 @@ namespace ts { setEmitFlags(target, EmitFlags.NoComments | EmitFlags.NoTrailingSourceMap); setSourceMapRange(target, firstAccessor.name); // TODO: GH#18217 - const propertyName = createExpressionForPropertyName(visitNode(firstAccessor.name, visitor, isPropertyName)); + // TODO: GH#9950 get rid of this type assertion and handle private names + const propertyName = createExpressionForPropertyName(visitNode(firstAccessor.name, visitor, isPropertyName) as Exclude); setEmitFlags(propertyName, EmitFlags.NoComments | EmitFlags.NoLeadingSourceMap); setSourceMapRange(propertyName, firstAccessor.name); diff --git a/src/compiler/transformers/es5.ts b/src/compiler/transformers/es5.ts index 1c85e684e8cba..36ff996dca594 100644 --- a/src/compiler/transformers/es5.ts +++ b/src/compiler/transformers/es5.ts @@ -82,7 +82,10 @@ namespace ts { * @param node A PropertyAccessExpression */ function substitutePropertyAccessExpression(node: PropertyAccessExpression): Expression { - const literalName = trySubstituteReservedName(node.name); + if (isPrivateName(node)) { + return node; + } + const literalName = trySubstituteReservedName(node.name as Identifier); if (literalName) { return setTextRange(createElementAccess(node.expression, literalName), node); } diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 154b09dc93d55..b2a188cf2ff65 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -667,28 +667,6 @@ namespace ts { } } - function isCompoundAssignment(kind: BinaryOperator): kind is CompoundAssignmentOperator { - return kind >= SyntaxKind.FirstCompoundAssignment - && kind <= SyntaxKind.LastCompoundAssignment; - } - - function getOperatorForCompoundAssignment(kind: CompoundAssignmentOperator): BitwiseOperatorOrHigher { - switch (kind) { - case SyntaxKind.PlusEqualsToken: return SyntaxKind.PlusToken; - case SyntaxKind.MinusEqualsToken: return SyntaxKind.MinusToken; - case SyntaxKind.AsteriskEqualsToken: return SyntaxKind.AsteriskToken; - case SyntaxKind.AsteriskAsteriskEqualsToken: return SyntaxKind.AsteriskAsteriskToken; - case SyntaxKind.SlashEqualsToken: return SyntaxKind.SlashToken; - case SyntaxKind.PercentEqualsToken: return SyntaxKind.PercentToken; - case SyntaxKind.LessThanLessThanEqualsToken: return SyntaxKind.LessThanLessThanToken; - case SyntaxKind.GreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanToken; - case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanGreaterThanToken; - case SyntaxKind.AmpersandEqualsToken: return SyntaxKind.AmpersandToken; - case SyntaxKind.BarEqualsToken: return SyntaxKind.BarToken; - case SyntaxKind.CaretEqualsToken: return SyntaxKind.CaretToken; - } - } - /** * Visits a right-associative binary expression containing `yield`. * diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 4a127f3236dfd..e051deb37db52 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -64,6 +64,7 @@ namespace ts { let currentLexicalScope: SourceFile | Block | ModuleBlock | CaseBlock; let currentNameScope: ClassDeclaration | undefined; let currentScopeFirstDeclarationsOfName: UnderscoreEscapedMap | undefined; + let currentClassHasParameterProperties: boolean | undefined; /** * Keeps track of whether expression substitution has been enabled for specific edge cases. @@ -83,12 +84,6 @@ namespace ts { */ let applicableSubstitutions: TypeScriptSubstitutionFlags; - /** - * Tracks what computed name expressions originating from elided names must be inlined - * at the next execution site, in document order - */ - let pendingExpressions: Expression[] | undefined; - return transformSourceFileOrBundle; function transformSourceFileOrBundle(node: SourceFile | Bundle) { @@ -136,6 +131,7 @@ namespace ts { const savedCurrentScope = currentLexicalScope; const savedCurrentNameScope = currentNameScope; const savedCurrentScopeFirstDeclarationsOfName = currentScopeFirstDeclarationsOfName; + const savedCurrentClassHasParameterProperties = currentClassHasParameterProperties; // Handle state changes before visiting a node. onBeforeVisitNode(node); @@ -149,6 +145,7 @@ namespace ts { currentLexicalScope = savedCurrentScope; currentNameScope = savedCurrentNameScope; + currentClassHasParameterProperties = savedCurrentClassHasParameterProperties; return visited; } @@ -321,6 +318,9 @@ namespace ts { return undefined; case SyntaxKind.PropertyDeclaration: + // Property declarations are not TypeScript syntax, but they must be visited + // for the decorator transformation. + return visitPropertyDeclaration(node as PropertyDeclaration); case SyntaxKind.IndexSignature: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: @@ -437,7 +437,6 @@ namespace ts { // - decorators // - optional `implements` heritage clause // - parameter property assignments in the constructor - // - property declarations // - index signatures // - method overload signatures return visitClassDeclaration(node); @@ -449,7 +448,6 @@ namespace ts { // - decorators // - optional `implements` heritage clause // - parameter property assignments in the constructor - // - property declarations // - index signatures // - method overload signatures return visitClassExpression(node); @@ -611,10 +609,6 @@ namespace ts { if (!isClassLikeDeclarationWithTypeScriptSyntax(node) && !(currentNamespace && hasModifier(node, ModifierFlags.Export))) { return visitEachChild(node, visitor, context); } - - const savedPendingExpressions = pendingExpressions; - pendingExpressions = undefined; - const staticProperties = getInitializedProperties(node, /*isStatic*/ true); const facts = getClassFacts(node, staticProperties); @@ -624,25 +618,11 @@ namespace ts { const name = node.name || (facts & ClassFacts.NeedsName ? getGeneratedNameForNode(node) : undefined); const classStatement = facts & ClassFacts.HasConstructorDecorators - ? createClassDeclarationHeadWithDecorators(node, name, facts) + ? createClassDeclarationHeadWithDecorators(node, name) : createClassDeclarationHeadWithoutDecorators(node, name, facts); let statements: Statement[] = [classStatement]; - // Write any pending expressions from elided or moved computed property names - if (some(pendingExpressions)) { - statements.push(createExpressionStatement(inlineExpressions(pendingExpressions!))); - } - pendingExpressions = savedPendingExpressions; - - // Emit static property assignment. Because classDeclaration is lexically evaluated, - // it is safe to emit static property assignment after classDeclaration - // From ES6 specification: - // HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using - // a lexical declaration such as a LexicalDeclaration or a ClassDeclaration. - if (facts & ClassFacts.HasStaticInitializedProperties) { - addInitializedPropertyStatements(statements, staticProperties, facts & ClassFacts.UseImmediatelyInvokedFunctionExpression ? getInternalName(node) : getLocalName(node)); - } // Write any decorators of the node. addClassElementDecorationStatements(statements, node, /*isStatic*/ false); @@ -745,7 +725,7 @@ namespace ts { name, /*typeParameters*/ undefined, visitNodes(node.heritageClauses, visitor, isHeritageClause), - transformClassMembers(node, (facts & ClassFacts.IsDerivedClass) !== 0) + transformClassMembers(node) ); // To better align with the old emitter, we should not emit a trailing source map @@ -765,7 +745,7 @@ namespace ts { * Transforms a decorated class declaration and appends the resulting statements. If * the class requires an alias to avoid issues with double-binding, the alias is returned. */ - function createClassDeclarationHeadWithDecorators(node: ClassDeclaration, name: Identifier | undefined, facts: ClassFacts) { + function createClassDeclarationHeadWithDecorators(node: ClassDeclaration, name: Identifier | undefined) { // When we emit an ES6 class that has a class decorator, we must tailor the // emit to certain specific cases. // @@ -860,7 +840,7 @@ namespace ts { // ${members} // } const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause); - const members = transformClassMembers(node, (facts & ClassFacts.IsDerivedClass) !== 0); + const members = transformClassMembers(node); const classExpression = createClassExpression(/*modifiers*/ undefined, name, /*typeParameters*/ undefined, heritageClauses, members); setOriginalNode(classExpression, node); setTextRange(classExpression, location); @@ -888,49 +868,19 @@ namespace ts { return visitEachChild(node, visitor, context); } - const savedPendingExpressions = pendingExpressions; - pendingExpressions = undefined; - - const staticProperties = getInitializedProperties(node, /*isStatic*/ true); - const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause); - const members = transformClassMembers(node, some(heritageClauses, c => c.token === SyntaxKind.ExtendsKeyword)); + const members = transformClassMembers(node); const classExpression = createClassExpression( /*modifiers*/ undefined, node.name, /*typeParameters*/ undefined, - heritageClauses, + node.heritageClauses, members ); setOriginalNode(classExpression, node); setTextRange(classExpression, node); - if (some(staticProperties) || some(pendingExpressions)) { - const expressions: Expression[] = []; - const isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference; - const temp = createTempVariable(hoistVariableDeclaration, !!isClassWithConstructorReference); - if (isClassWithConstructorReference) { - // record an alias as the class name is not in scope for statics. - enableSubstitutionForClassAliases(); - const alias = getSynthesizedClone(temp); - alias.autoGenerateFlags &= ~GeneratedIdentifierFlags.ReservedInNestedScopes; - classAliases[getOriginalNodeId(node)] = alias; - } - - // To preserve the behavior of the old emitter, we explicitly indent - // the body of a class with static initializers. - setEmitFlags(classExpression, EmitFlags.Indented | getEmitFlags(classExpression)); - expressions.push(startOnNewLine(createAssignment(temp, classExpression))); - // Add any pending expressions leftover from elided or relocated computed property names - addRange(expressions, map(pendingExpressions, startOnNewLine)); - pendingExpressions = savedPendingExpressions; - addRange(expressions, generateInitializedPropertyExpressions(staticProperties, temp)); - expressions.push(startOnNewLine(temp)); - return inlineExpressions(expressions); - } - - pendingExpressions = savedPendingExpressions; return classExpression; } @@ -938,61 +888,81 @@ namespace ts { * Transforms the members of a class. * * @param node The current class. - * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. */ - function transformClassMembers(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { + function transformClassMembers(node: ClassDeclaration | ClassExpression) { const members: ClassElement[] = []; - const constructor = transformConstructor(node, isDerivedClass); - if (constructor) { - members.push(constructor); - } - - addRange(members, visitNodes(node.members, classElementVisitor, isClassElement)); - return setTextRange(createNodeArray(members), /*location*/ node.members); - } - - /** - * Transforms (or creates) a constructor for a class. - * - * @param node The current class. - * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. - */ - function transformConstructor(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { - // Check if we have property assignment inside class declaration. - // If there is a property assignment, we need to emit constructor whether users define it or not - // If there is no property assignment, we can omit constructor if users do not define it + const existingMembers = visitNodes(node.members, classElementVisitor, isClassElement); const constructor = getFirstConstructorWithBody(node); - const hasInstancePropertyWithInitializer = forEach(node.members, isInstanceInitializedProperty); - const hasParameterPropertyAssignments = constructor && - constructor.transformFlags & TransformFlags.ContainsTypeScriptClassSyntax && - forEach(constructor.parameters, isParameterWithPropertyAssignment); - - // If the class does not contain nodes that require a synthesized constructor, - // accept the current constructor if it exists. - if (!hasInstancePropertyWithInitializer && !hasParameterPropertyAssignments) { - return visitEachChild(constructor, visitor, context); - } - - const parameters = transformConstructorParameters(constructor); - const body = transformConstructorBody(node, constructor, isDerivedClass); + const parametersWithPropertyAssignments = + constructor && hasTypeScriptClassSyntax(constructor) + ? filter(constructor.parameters, isParameterPropertyDeclaration) + : undefined; + if (some(parametersWithPropertyAssignments) && constructor) { + currentClassHasParameterProperties = true; + + // Create property declarations for constructor parameter properties. + addRange( + members, + parametersWithPropertyAssignments.map(param => + createProperty( + /*decorators*/ undefined, + /*modifiers*/ undefined, + param.name, + /*questionOrExclamationToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined + ) + ) + ); - // constructor(${parameters}) { - // ${body} - // } - return startOnNewLine( - setOriginalNode( - setTextRange( - createConstructor( + const parameters = transformConstructorParameters(constructor); + const body = transformConstructorBody(node.members, constructor, parametersWithPropertyAssignments); + members.push(startOnNewLine( + setOriginalNode( + setTextRange( + createConstructor( /*decorators*/ undefined, /*modifiers*/ undefined, - parameters, - body + parameters, + body + ), + constructor ), - constructor || node - ), - constructor - ) - ); + constructor + ) + )); + addRange( + members, + visitNodes( + existingMembers, + member => { + if (isPropertyDeclaration(member) && !hasStaticModifier(member) && !!member.initializer) { + const updated = updateProperty( + member, + member.decorators, + member.modifiers, + member.name, + member.questionToken, + member.type, + /*initializer*/ undefined + ); + setCommentRange(updated, node); + setSourceMapRange(updated, node); + return updated; + } + return member; + }, + isClassElement + ) + ); + } + else { + if (constructor) { + members.push(visitEachChild(constructor, visitor, context)); + } + addRange(members, existingMembers); + } + return setTextRange(createNodeArray(members), /*location*/ node.members); } /** @@ -1001,7 +971,7 @@ namespace ts { * * @param constructor The constructor declaration. */ - function transformConstructorParameters(constructor: ConstructorDeclaration | undefined) { + function transformConstructorParameters(constructor: ConstructorDeclaration) { // The ES2015 spec specifies in 14.5.14. Runtime Semantics: ClassDefinitionEvaluation: // If constructor is empty, then // If ClassHeritag_eopt is present and protoParent is not null, then @@ -1022,70 +992,54 @@ namespace ts { } /** - * Transforms (or creates) a constructor body for a class with parameter property - * assignments or instance property initializers. + * Transforms (or creates) a constructor body for a class with parameter property assignments. * * @param node The current class. * @param constructor The current class constructor. - * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. */ - function transformConstructorBody(node: ClassExpression | ClassDeclaration, constructor: ConstructorDeclaration | undefined, isDerivedClass: boolean) { + function transformConstructorBody(members: NodeArray, constructor: ConstructorDeclaration, propertyAssignments: ReadonlyArray) { let statements: Statement[] = []; let indexOfFirstStatement = 0; resumeLexicalEnvironment(); - if (constructor) { - indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements); - - // Add parameters with property assignments. Transforms this: - // - // constructor (public x, public y) { - // } - // - // Into this: - // - // constructor (x, y) { - // this.x = x; - // this.y = y; - // } - // - const propertyAssignments = getParametersWithPropertyAssignments(constructor); - addRange(statements, map(propertyAssignments, transformParameterWithPropertyAssignment)); - } - else if (isDerivedClass) { - // Add a synthetic `super` call: - // - // super(...arguments); - // - statements.push( - createExpressionStatement( - createCall( - createSuper(), - /*typeArguments*/ undefined, - [createSpread(createIdentifier("arguments"))] - ) - ) - ); - } + indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements, visitor); - // Add the property initializers. Transforms this: + // Add parameters with property assignments. Transforms this: // - // public x = 1; + // constructor (public x, public y) { + // } // // Into this: // - // constructor() { - // this.x = 1; + // constructor (x, y) { + // this.x = x; + // this.y = y; // } // - const properties = getInitializedProperties(node, /*isStatic*/ false); - addInitializedPropertyStatements(statements, properties, createThis()); + addRange(statements, map(propertyAssignments, transformParameterWithPropertyAssignment)); + + // Get property initializers. + const classBodyProperties = members.filter(member => isPropertyDeclaration(member) && !hasStaticModifier(member) && !!member.initializer) as PropertyDeclaration[]; + addRange(statements, classBodyProperties.map( + prop => { + const name = prop.name; + const lhs = (!isComputedPropertyName(name) || isSimpleInlineableExpression(name.expression)) ? + createMemberAccessForPropertyName(createThis(), name, prop) : + createElementAccess(createThis(), getGeneratedNameForNode(name)); + const initializerNode = createExpressionStatement( + createAssignment(lhs, prop.initializer!) + ); + setOriginalNode(initializerNode, prop); + setTextRange(initializerNode, prop); + setCommentRange(initializerNode, prop); + setSourceMapRange(initializerNode, prop); + return initializerNode; + } + )); - if (constructor) { - // The class already had a constructor, so we should add the existing statements, skipping the initial super call. - addRange(statements, visitNodes(constructor.body!.statements, visitor, isStatement, indexOfFirstStatement)); - } + // Add the existing statements, skipping the initial super call. + addRange(statements, visitNodes(constructor.body!.statements, visitor, isStatement, indexOfFirstStatement)); // End the lexical environment. statements = mergeLexicalEnvironment(statements, endLexicalEnvironment()); @@ -1093,7 +1047,7 @@ namespace ts { createBlock( setTextRange( createNodeArray(statements), - /*location*/ constructor ? constructor.body!.statements : node.members + /*location*/ constructor ? constructor.body!.statements : members ), /*multiLine*/ true ), @@ -1101,61 +1055,16 @@ namespace ts { ); } - /** - * Adds super call and preceding prologue directives into the list of statements. - * - * @param ctor The constructor node. - * @returns index of the statement that follows super call - */ - function addPrologueDirectivesAndInitialSuperCall(ctor: ConstructorDeclaration, result: Statement[]): number { - if (ctor.body) { - const statements = ctor.body.statements; - // add prologue directives to the list (if any) - const index = addPrologue(result, statements, /*ensureUseStrict*/ false, visitor); - if (index === statements.length) { - // list contains nothing but prologue directives (or empty) - exit - return index; - } - - const statement = statements[index]; - if (statement.kind === SyntaxKind.ExpressionStatement && isSuperCall((statement).expression)) { - result.push(visitNode(statement, visitor, isStatement)); - return index + 1; - } - - return index; - } - - return 0; - } - - /** - * Gets all parameters of a constructor that should be transformed into property assignments. - * - * @param node The constructor node. - */ - function getParametersWithPropertyAssignments(node: ConstructorDeclaration): ReadonlyArray { - return filter(node.parameters, isParameterWithPropertyAssignment); - } - - /** - * Determines whether a parameter should be transformed into a property assignment. - * - * @param parameter The parameter node. - */ - function isParameterWithPropertyAssignment(parameter: ParameterDeclaration) { - return hasModifier(parameter, ModifierFlags.ParameterPropertyModifier) - && isIdentifier(parameter.name); - } - /** * Transforms a parameter into a property assignment statement. * * @param node The parameter declaration. */ - function transformParameterWithPropertyAssignment(node: ParameterDeclaration) { - Debug.assert(isIdentifier(node.name)); - const name = node.name as Identifier; + function transformParameterWithPropertyAssignment(node: ParameterPropertyDeclaration) { + const name = node.name; + if (!isIdentifier(name)) { + return undefined; + } const propertyName = getMutableClone(name); setEmitFlags(propertyName, EmitFlags.NoComments | EmitFlags.NoSourceMap); @@ -1184,99 +1093,6 @@ namespace ts { ); } - /** - * Gets all property declarations with initializers on either the static or instance side of a class. - * - * @param node The class node. - * @param isStatic A value indicating whether to get properties from the static or instance side of the class. - */ - function getInitializedProperties(node: ClassExpression | ClassDeclaration, isStatic: boolean): ReadonlyArray { - return filter(node.members, isStatic ? isStaticInitializedProperty : isInstanceInitializedProperty); - } - - /** - * Gets a value indicating whether a class element is a static property declaration with an initializer. - * - * @param member The class element node. - */ - function isStaticInitializedProperty(member: ClassElement): member is PropertyDeclaration { - return isInitializedProperty(member, /*isStatic*/ true); - } - - /** - * Gets a value indicating whether a class element is an instance property declaration with an initializer. - * - * @param member The class element node. - */ - function isInstanceInitializedProperty(member: ClassElement): member is PropertyDeclaration { - return isInitializedProperty(member, /*isStatic*/ false); - } - - /** - * Gets a value indicating whether a class element is either a static or an instance property declaration with an initializer. - * - * @param member The class element node. - * @param isStatic A value indicating whether the member should be a static or instance member. - */ - function isInitializedProperty(member: ClassElement, isStatic: boolean) { - return member.kind === SyntaxKind.PropertyDeclaration - && isStatic === hasModifier(member, ModifierFlags.Static) - && (member).initializer !== undefined; - } - - /** - * Generates assignment statements for property initializers. - * - * @param properties An array of property declarations to transform. - * @param receiver The receiver on which each property should be assigned. - */ - function addInitializedPropertyStatements(statements: Statement[], properties: ReadonlyArray, receiver: LeftHandSideExpression) { - for (const property of properties) { - const statement = createExpressionStatement(transformInitializedProperty(property, receiver)); - setSourceMapRange(statement, moveRangePastModifiers(property)); - setCommentRange(statement, property); - setOriginalNode(statement, property); - statements.push(statement); - } - } - - /** - * Generates assignment expressions for property initializers. - * - * @param properties An array of property declarations to transform. - * @param receiver The receiver on which each property should be assigned. - */ - function generateInitializedPropertyExpressions(properties: ReadonlyArray, receiver: LeftHandSideExpression) { - const expressions: Expression[] = []; - for (const property of properties) { - const expression = transformInitializedProperty(property, receiver); - startOnNewLine(expression); - setSourceMapRange(expression, moveRangePastModifiers(property)); - setCommentRange(expression, property); - setOriginalNode(expression, property); - expressions.push(expression); - } - - return expressions; - } - - /** - * Transforms a property initializer into an assignment statement. - * - * @param property The property declaration. - * @param receiver The object receiving the property assignment. - */ - function transformInitializedProperty(property: PropertyDeclaration, receiver: LeftHandSideExpression) { - // We generate a name here in order to reuse the value cached by the relocated computed name expression (which uses the same generated name) - const propertyName = isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression) - ? updateComputedPropertyName(property.name, getGeneratedNameForNode(property.name)) - : property.name; - const initializer = visitNode(property.initializer!, visitor, isExpression); - const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName); - - return createAssignment(memberAccess, initializer); - } - /** * Gets either the static or instance members of a class that are decorated, or have * parameters that are decorated. @@ -2141,16 +1957,6 @@ namespace ts { : createIdentifier("BigInt"); } - /** - * A simple inlinable expression is an expression which can be copied into multiple locations - * without risk of repeating any sideeffects and whose value could not possibly change between - * any such locations - */ - function isSimpleInlineableExpression(expression: Expression) { - return !isIdentifier(expression) && isSimpleCopiableExpression(expression) || - isWellKnownSymbolSyntactically(expression); - } - /** * Gets an expression that represents a property name. For a computed property, a * name is generated for the node. @@ -2164,7 +1970,7 @@ namespace ts { ? getGeneratedNameForNode(name) : name.expression; } - else if (isIdentifier(name)) { + else if (isIdentifier(name) || isPrivateName(name)) { return createLiteral(idText(name)); } else { @@ -2172,26 +1978,6 @@ namespace ts { } } - /** - * If the name is a computed property, this function transforms it, then either returns an expression which caches the - * value of the result or the expression itself if the value is either unused or safe to inline into multiple locations - * @param shouldHoist Does the expression need to be reused? (ie, for an initializer or a decorator) - * @param omitSimple Should expressions with no observable side-effects be elided? (ie, the expression is not hoisted for a decorator or initializer and is a literal) - */ - function getPropertyNameExpressionIfNeeded(name: PropertyName, shouldHoist: boolean, omitSimple: boolean): Expression | undefined { - if (isComputedPropertyName(name)) { - const expression = visitNode(name.expression, visitor, isExpression); - const innerExpression = skipPartiallyEmittedExpressions(expression); - const inlinable = isSimpleInlineableExpression(innerExpression); - if (!inlinable && shouldHoist) { - const generatedName = getGeneratedNameForNode(name); - hoistVariableDeclaration(generatedName); - return createAssignment(generatedName, expression); - } - return (omitSimple && (inlinable || isIdentifier(innerExpression))) ? undefined : expression; - } - } - /** * Visits the property name of a class element, for use when emitting property * initializers. For a computed property on a node with decorators, a temporary @@ -2201,18 +1987,20 @@ namespace ts { */ function visitPropertyNameOfClassElement(member: ClassElement): PropertyName { const name = member.name!; - let expr = getPropertyNameExpressionIfNeeded(name, some(member.decorators), /*omitSimple*/ false); - if (expr) { // expr only exists if `name` is a computed property name - // Inline any pending expressions from previous elided or relocated computed property name expressions in order to preserve execution order - if (some(pendingExpressions)) { - expr = inlineExpressions([...pendingExpressions, expr]); - pendingExpressions.length = 0; + // Computed property names need to be transformed into a hoisted variable when they are used more than once. + // The names are used more than once when: + // - the property is non-static and its initializer is moved to the constructor (when there are parameter property assignments). + // - the property has a decorator. + if (isComputedPropertyName(name) && ((!hasStaticModifier(member) && currentClassHasParameterProperties) || some(member.decorators))) { + const expression = visitNode(name.expression, visitor, isExpression); + const innerExpression = skipPartiallyEmittedExpressions(expression); + if (!isSimpleInlineableExpression(innerExpression)) { + const generatedName = getGeneratedNameForNode(name); + hoistVariableDeclaration(generatedName); + return updateComputedPropertyName(name, createAssignment(generatedName, expression)); } - return updateComputedPropertyName(name as ComputedPropertyName, expr); - } - else { - return name; } + return visitNode(name, visitor, isPropertyName); } /** @@ -2258,12 +2046,23 @@ namespace ts { return !nodeIsMissing(node.body); } - function visitPropertyDeclaration(node: PropertyDeclaration): undefined { - const expr = getPropertyNameExpressionIfNeeded(node.name, some(node.decorators) || !!node.initializer, /*omitSimple*/ true); - if (expr && !isSimpleInlineableExpression(expr)) { - (pendingExpressions || (pendingExpressions = [])).push(expr); + function visitPropertyDeclaration(node: PropertyDeclaration) { + const updated = updateProperty( + node, + /*decorators*/ undefined, + visitNodes(node.modifiers, visitor, isModifier), + visitPropertyNameOfClassElement(node), + /*questionOrExclamationToken*/ undefined, + /*type*/ undefined, + visitNode(node.initializer, visitor) + ); + if (updated !== node) { + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. + setCommentRange(updated, node); + setSourceMapRange(updated, moveRangePastDecorators(node)); } - return undefined; + return updated; } function visitConstructor(node: ConstructorDeclaration) { diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index 09239d7765fd9..54c54771a0ff3 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -240,6 +240,69 @@ namespace ts { isIdentifier(expression); } + /** + * A simple inlinable expression is an expression which can be copied into multiple locations + * without risk of repeating any sideeffects and whose value could not possibly change between + * any such locations + */ + export function isSimpleInlineableExpression(expression: Expression) { + return !isIdentifier(expression) && isSimpleCopiableExpression(expression) || + isWellKnownSymbolSyntactically(expression); + } + + export function isCompoundAssignment(kind: BinaryOperator): kind is CompoundAssignmentOperator { + return kind >= SyntaxKind.FirstCompoundAssignment + && kind <= SyntaxKind.LastCompoundAssignment; + } + + export function getOperatorForCompoundAssignment(kind: CompoundAssignmentOperator): BitwiseOperatorOrHigher { + switch (kind) { + case SyntaxKind.PlusEqualsToken: return SyntaxKind.PlusToken; + case SyntaxKind.MinusEqualsToken: return SyntaxKind.MinusToken; + case SyntaxKind.AsteriskEqualsToken: return SyntaxKind.AsteriskToken; + case SyntaxKind.AsteriskAsteriskEqualsToken: return SyntaxKind.AsteriskAsteriskToken; + case SyntaxKind.SlashEqualsToken: return SyntaxKind.SlashToken; + case SyntaxKind.PercentEqualsToken: return SyntaxKind.PercentToken; + case SyntaxKind.LessThanLessThanEqualsToken: return SyntaxKind.LessThanLessThanToken; + case SyntaxKind.GreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanToken; + case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanGreaterThanToken; + case SyntaxKind.AmpersandEqualsToken: return SyntaxKind.AmpersandToken; + case SyntaxKind.BarEqualsToken: return SyntaxKind.BarToken; + case SyntaxKind.CaretEqualsToken: return SyntaxKind.CaretToken; + } + } + + /** + * Adds super call and preceding prologue directives into the list of statements. + * + * @param ctor The constructor node. + * @param result The list of statements. + * @param visitor The visitor to apply to each node added to the result array. + * @returns index of the statement that follows super call + */ + export function addPrologueDirectivesAndInitialSuperCall(ctor: ConstructorDeclaration, result: Statement[], visitor: Visitor): number { + if (ctor.body) { + const statements = ctor.body.statements; + // add prologue directives to the list (if any) + const index = addPrologue(result, statements, /*ensureUseStrict*/ false, visitor); + if (index === statements.length) { + // list contains nothing but prologue directives (or empty) - exit + return index; + } + + const statement = statements[index]; + if (statement.kind === SyntaxKind.ExpressionStatement && isSuperCall((statement).expression)) { + result.push(visitNode(statement, visitor, isStatement)); + return index + 1; + } + + return index; + } + + return 0; + } + + /** * @param input Template string input strings * @param args Names which need to be made file-level unique @@ -255,4 +318,43 @@ namespace ts { return result; }; } + + /** + * Gets all property declarations with initializers on either the static or instance side of a class. + * + * @param node The class node. + * @param isStatic A value indicating whether to get properties from the static or instance side of the class. + */ + export function getInitializedProperties(node: ClassExpression | ClassDeclaration, isStatic: boolean): ReadonlyArray { + return filter(node.members, isStatic ? isStaticInitializedProperty : isInstanceInitializedProperty); + } + + /** + * Gets a value indicating whether a class element is a static property declaration with an initializer. + * + * @param member The class element node. + */ + export function isStaticInitializedProperty(member: ClassElement): member is PropertyDeclaration & { initializer: Expression; } { + return isInitializedProperty(member) && hasStaticModifier(member); + } + + /** + * Gets a value indicating whether a class element is an instance property declaration with an initializer. + * + * @param member The class element node. + */ + export function isInstanceInitializedProperty(member: ClassElement): member is PropertyDeclaration & { initializer: Expression; } { + return isInitializedProperty(member) && !hasStaticModifier(member); + } + + /** + * Gets a value indicating whether a class element is either a static or an instance property declaration with an initializer. + * + * @param member The class element node. + * @param isStatic A value indicating whether the member should be a static or instance member. + */ + export function isInitializedProperty(member: ClassElement): member is PropertyDeclaration & { initializer: Expression; } { + return member.kind === SyntaxKind.PropertyDeclaration + && (member).initializer !== undefined; + } } \ No newline at end of file diff --git a/src/compiler/tsconfig.json b/src/compiler/tsconfig.json index 84bedb34b7cee..fe0c3250ed172 100644 --- a/src/compiler/tsconfig.json +++ b/src/compiler/tsconfig.json @@ -29,6 +29,7 @@ "transformers/utilities.ts", "transformers/destructuring.ts", "transformers/ts.ts", + "transformers/classProperties.ts", "transformers/es2017.ts", "transformers/es2018.ts", "transformers/es2019.ts", diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 088ae34ee34bf..2dfe5196a1ce6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -195,8 +195,9 @@ namespace ts { AmpersandEqualsToken, BarEqualsToken, CaretEqualsToken, - // Identifiers + // Identifiers and PrivateNames Identifier, + PrivateName, // Reserved words BreakKeyword, CaseKeyword, @@ -797,9 +798,9 @@ namespace ts { export type EntityName = Identifier | QualifiedName; - export type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName; + export type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | PrivateName; - export type DeclarationName = Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern; + export type DeclarationName = Identifier | PrivateName | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern; export interface Declaration extends Node { _declarationBrand: any; @@ -830,6 +831,13 @@ namespace ts { expression: Expression; } + export interface PrivateName extends PrimaryExpression, Declaration { + kind: SyntaxKind.PrivateName; + // escaping not strictly necessary + // avoids gotchas in transforms and utils + escapedText: __String; + } + /* @internal */ // A name that supports late-binding (used in checker) export interface LateBoundName extends ComputedPropertyName { @@ -943,6 +951,11 @@ namespace ts { initializer?: Expression; // Optional initializer } + /*@internal*/ + export interface PrivateNamedPropertyDeclaration extends PropertyDeclaration { + name: PrivateName; + } + export interface ObjectLiteralElement extends NamedDeclaration { _objectLiteralBrandBrand: any; name?: PropertyName; @@ -1270,7 +1283,7 @@ namespace ts { export interface StringLiteral extends LiteralExpression { kind: SyntaxKind.StringLiteral; - /* @internal */ textSourceNode?: Identifier | StringLiteralLike | NumericLiteral; // Allows a StringLiteral to get its text from another node (used by transforms). + /* @internal */ textSourceNode?: Identifier | PrivateName | StringLiteralLike | NumericLiteral; // Allows a StringLiteral to get its text from another node (used by transforms). /** Note: this is only set when synthesizing a node, not during parsing. */ /* @internal */ singleQuote?: boolean; } @@ -1764,7 +1777,12 @@ namespace ts { export interface PropertyAccessExpression extends MemberExpression, NamedDeclaration { kind: SyntaxKind.PropertyAccessExpression; expression: LeftHandSideExpression; - name: Identifier; + name: Identifier | PrivateName; + } + + /*@internal*/ + export interface PrivateNamedPropertyAccessExpression extends PropertyAccessExpression { + name: PrivateName; } export interface SuperPropertyAccessExpression extends PropertyAccessExpression { @@ -3083,6 +3101,7 @@ namespace ts { getDeclaredTypeOfSymbol(symbol: Symbol): Type; getPropertiesOfType(type: Type): Symbol[]; getPropertyOfType(type: Type, propertyName: string): Symbol | undefined; + getPropertyForPrivateName(apparentType: Type, leftType: Type, right: PrivateName, errorNode: Node | undefined): Symbol | undefined; /* @internal */ getTypeOfPropertyOfType(type: Type, propertyName: string): Type | undefined; getIndexInfoOfType(type: Type, kind: IndexKind): IndexInfo | undefined; getSignaturesOfType(type: Type, kind: SignatureKind): ReadonlyArray; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 73e32241f813b..281f3d4d64c17 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -809,6 +809,7 @@ namespace ts { export function getTextOfPropertyName(name: PropertyName | NoSubstitutionTemplateLiteral): __String { switch (name.kind) { case SyntaxKind.Identifier: + case SyntaxKind.PrivateName: return name.escapedText; case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: @@ -829,7 +830,15 @@ namespace ts { case SyntaxKind.QualifiedName: return entityNameToString(name.left) + "." + entityNameToString(name.right); case SyntaxKind.PropertyAccessExpression: - return entityNameToString(name.expression) + "." + entityNameToString(name.name); + if (isIdentifier(name.name)) { + return entityNameToString(name.expression) + "." + entityNameToString(name.name); + } + else if (isPrivateName(name.name)) { + return getTextOfNode(name); + } + else { + throw Debug.assertNever(name.name); + } default: throw Debug.assertNever(name); } @@ -1530,6 +1539,10 @@ namespace ts { export function nodeCanBeDecorated(node: ClassElement, parent: Node): boolean; export function nodeCanBeDecorated(node: Node, parent: Node, grandparent: Node): boolean; export function nodeCanBeDecorated(node: Node, parent?: Node, grandparent?: Node): boolean { + // private names cannot be used with decorators yet + if (isNamedDeclaration(node) && isPrivateName(node.name)) { + return false; + } switch (node.kind) { case SyntaxKind.ClassDeclaration: // classes are valid targets @@ -1940,7 +1953,7 @@ namespace ts { (initializer.expression.escapedText === "window" as __String || initializer.expression.escapedText === "self" as __String || initializer.expression.escapedText === "global" as __String)) && - isSameEntityName(name, initializer.name); + isSameEntityName(name, initializer.name as Identifier); } if (isPropertyAccessExpression(name) && isPropertyAccessExpression(initializer)) { return name.name.escapedText === initializer.name.escapedText && isSameEntityName(name.expression, initializer.expression); @@ -2732,6 +2745,7 @@ namespace ts { export function getPropertyNameForPropertyNameNode(name: PropertyName): __String | undefined { switch (name.kind) { case SyntaxKind.Identifier: + case SyntaxKind.PrivateName: return name.escapedText; case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: @@ -2750,10 +2764,12 @@ namespace ts { } } - export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral; + export type PropertyNameLiteral = Identifier | PrivateName | StringLiteralLike | NumericLiteral; export function isPropertyNameLiteral(node: Node): node is PropertyNameLiteral { switch (node.kind) { case SyntaxKind.Identifier: + // TODO: should this be here? + case SyntaxKind.PrivateName: case SyntaxKind.StringLiteral: case SyntaxKind.NoSubstitutionTemplateLiteral: case SyntaxKind.NumericLiteral: @@ -2763,17 +2779,25 @@ namespace ts { } } export function getTextOfIdentifierOrLiteral(node: PropertyNameLiteral): string { - return node.kind === SyntaxKind.Identifier ? idText(node) : node.text; + return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.PrivateName ? idText(node) : node.text; } export function getEscapedTextOfIdentifierOrLiteral(node: PropertyNameLiteral): __String { - return node.kind === SyntaxKind.Identifier ? node.escapedText : escapeLeadingUnderscores(node.text); + return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.PrivateName ? node.escapedText : escapeLeadingUnderscores(node.text); + } + + export function getPropertyNameForUniqueESSymbol(symbol: Symbol): __String { + return `__@${getSymbolId(symbol)}@${symbol.escapedName}` as __String; } export function getPropertyNameForKnownSymbolName(symbolName: string): __String { return "__@" + symbolName as __String; } + export function getPropertyNameForPrivateNameDescription(containingClassSymbol: Symbol, description: __String): __String { + return `__#${getSymbolId(containingClassSymbol)}@${description}` as __String; + } + export function isKnownSymbol(symbol: Symbol): boolean { return startsWith(symbol.escapedName as string, "__@"); } @@ -3506,7 +3530,7 @@ namespace ts { } export function isThisIdentifier(node: Node | undefined): boolean { - return !!node && node.kind === SyntaxKind.Identifier && identifierIsThisKeyword(node as Identifier); + return !!node && isIdentifier(node) && identifierIsThisKeyword(node); } export function identifierIsThisKeyword(id: Identifier): boolean { @@ -5106,8 +5130,8 @@ namespace ts { return id.length >= 3 && id.charCodeAt(0) === CharacterCodes._ && id.charCodeAt(1) === CharacterCodes._ && id.charCodeAt(2) === CharacterCodes._ ? id.substr(1) : id; } - export function idText(identifier: Identifier): string { - return unescapeLeadingUnderscores(identifier.escapedText); + export function idText(identifierOrPrivateName: Identifier | PrivateName): string { + return unescapeLeadingUnderscores(identifierOrPrivateName.escapedText); } export function symbolName(symbol: Symbol): string { return unescapeLeadingUnderscores(symbol.escapedName); @@ -5118,7 +5142,7 @@ namespace ts { * attempt to draw the name from the node the declaration is on (as that declaration is what its' symbol * will be merged with) */ - function nameForNamelessJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined { + function nameForNamelessJSDocTypedef(declaration: JSDocTypedefTag): Identifier | PrivateName | undefined { const hostNode = declaration.parent.parent; if (!hostNode) { return undefined; @@ -5163,7 +5187,7 @@ namespace ts { return name && isIdentifier(name) ? name : undefined; } - export function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined { + export function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | PrivateName | undefined { return declaration.name || nameForNamelessJSDocTypedef(declaration); } @@ -5479,6 +5503,10 @@ namespace ts { return node.kind === SyntaxKind.Identifier; } + export function isIdentifierOrPrivateName(node: Node): node is Identifier | PrivateName { + return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.PrivateName; + } + // Names export function isQualifiedName(node: Node): node is QualifiedName { @@ -5489,6 +5517,10 @@ namespace ts { return node.kind === SyntaxKind.ComputedPropertyName; } + export function isPrivateName(node: Node): node is PrivateName { + return node.kind === SyntaxKind.PrivateName; + } + // Signature elements export function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration { @@ -6305,6 +6337,16 @@ namespace ts { || kind === SyntaxKind.ArrayBindingPattern; } + /*@internal*/ + export function isPrivateNamedPropertyDeclaration(node: Node): node is PrivateNamedPropertyDeclaration { + return isPropertyDeclaration(node) && isPrivateName(node.name); + } + + /*@internal*/ + export function isPrivateNamedPropertyAccessExpression(node: Node): node is PrivateNamedPropertyAccessExpression { + return isPropertyAccessExpression(node) && isPrivateName(node.name); + } + // Functions export function isFunctionLike(node: Node): node is SignatureDeclaration { diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 0d4d0d9482d6a..714a2adc34787 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -464,7 +464,7 @@ namespace ts { case SyntaxKind.PropertyAccessExpression: return updatePropertyAccess(node, visitNode((node).expression, visitor, isExpression), - visitNode((node).name, visitor, isIdentifier)); + visitNode((node).name, visitor, isIdentifierOrPrivateName)); case SyntaxKind.ElementAccessExpression: return updateElementAccess(node, diff --git a/src/services/codefixes/convertToEs6Module.ts b/src/services/codefixes/convertToEs6Module.ts index 65ea757d06098..2ea58be1e9f1d 100644 --- a/src/services/codefixes/convertToEs6Module.ts +++ b/src/services/codefixes/convertToEs6Module.ts @@ -65,7 +65,7 @@ namespace ts.codefix { function collectExportRenames(sourceFile: SourceFile, checker: TypeChecker, identifiers: Identifiers): ExportRenames { const res = createMap(); forEachExportReference(sourceFile, node => { - const { text, originalKeywordKind } = node.name; + const { text, originalKeywordKind } = node.name as Identifier; if (!res.has(text) && (originalKeywordKind !== undefined && isNonContextualKeyword(originalKeywordKind) || checker.resolveName(node.name.text, node, SymbolFlags.Value, /*excludeGlobals*/ true))) { // Unconditionally add an underscore in case `text` is a keyword. diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index ecf2841e249ef..6c5610829549f 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -310,7 +310,7 @@ namespace ts.codefix { entry.kind !== FindAllReferences.EntryKind.Span ? tryCast(entry.node, isIdentifier) : undefined); } - function inferTypeForVariableFromUsage(token: Identifier, program: Program, cancellationToken: CancellationToken): Type { + function inferTypeForVariableFromUsage(token: Identifier | PrivateName, program: Program, cancellationToken: CancellationToken): Type { const references = getReferences(token, program, cancellationToken); const checker = program.getTypeChecker(); const types = InferFromReference.inferTypesFromReferences(references, checker, cancellationToken); diff --git a/src/services/refactors/moveToNewFile.ts b/src/services/refactors/moveToNewFile.ts index ad60a6da5fc5e..a87f4972b8407 100644 --- a/src/services/refactors/moveToNewFile.ts +++ b/src/services/refactors/moveToNewFile.ts @@ -704,7 +704,7 @@ namespace ts.refactor { } function nameOfTopLevelDeclaration(d: TopLevelDeclaration): Identifier | undefined { - return isExpressionStatement(d) ? d.expression.left.name : tryCast(d.name, isIdentifier); + return isExpressionStatement(d) ? d.expression.left.name as Identifier : tryCast(d.name, isIdentifier); } function getTopLevelDeclarationStatement(d: TopLevelDeclaration): TopLevelDeclarationStatement { diff --git a/src/services/types.ts b/src/services/types.ts index 3502e3e06712f..98d496288cf02 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -28,6 +28,10 @@ namespace ts { readonly text: string; } + export interface PrivateName { + readonly text: string; + } + export interface Symbol { readonly name: string; getFlags(): SymbolFlags; diff --git a/tests/baselines/reference/MemberFunctionDeclaration8_es6.errors.txt b/tests/baselines/reference/MemberFunctionDeclaration8_es6.errors.txt index 94198b36c9033..00b2ae4b02942 100644 --- a/tests/baselines/reference/MemberFunctionDeclaration8_es6.errors.txt +++ b/tests/baselines/reference/MemberFunctionDeclaration8_es6.errors.txt @@ -9,7 +9,7 @@ tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration class C { foo() { // Make sure we don't think of *bar as the start of a generator method. - if (a) # * bar; + if (a) ¬ * bar; ~ !!! error TS2304: Cannot find name 'a'. @@ -22,4 +22,5 @@ tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration ~~~ !!! error TS2304: Cannot find name 'bar'. } - } \ No newline at end of file + } + \ No newline at end of file diff --git a/tests/baselines/reference/MemberFunctionDeclaration8_es6.js b/tests/baselines/reference/MemberFunctionDeclaration8_es6.js index 853310e5a3efe..4fba30e9659b8 100644 --- a/tests/baselines/reference/MemberFunctionDeclaration8_es6.js +++ b/tests/baselines/reference/MemberFunctionDeclaration8_es6.js @@ -2,10 +2,11 @@ class C { foo() { // Make sure we don't think of *bar as the start of a generator method. - if (a) # * bar; + if (a) ¬ * bar; return bar; } -} +} + //// [MemberFunctionDeclaration8_es6.js] class C { diff --git a/tests/baselines/reference/MemberFunctionDeclaration8_es6.symbols b/tests/baselines/reference/MemberFunctionDeclaration8_es6.symbols index 0229450477c63..35041420d6aa5 100644 --- a/tests/baselines/reference/MemberFunctionDeclaration8_es6.symbols +++ b/tests/baselines/reference/MemberFunctionDeclaration8_es6.symbols @@ -6,7 +6,8 @@ class C { >foo : Symbol(C.foo, Decl(MemberFunctionDeclaration8_es6.ts, 0, 9)) // Make sure we don't think of *bar as the start of a generator method. - if (a) # * bar; + if (a) ¬ * bar; return bar; } } + diff --git a/tests/baselines/reference/MemberFunctionDeclaration8_es6.types b/tests/baselines/reference/MemberFunctionDeclaration8_es6.types index b0234b4135ee3..9eacffd080c9d 100644 --- a/tests/baselines/reference/MemberFunctionDeclaration8_es6.types +++ b/tests/baselines/reference/MemberFunctionDeclaration8_es6.types @@ -6,7 +6,7 @@ class C { >foo : () => any // Make sure we don't think of *bar as the start of a generator method. - if (a) # * bar; + if (a) ¬ * bar; >a : any > : any >* bar : number @@ -17,3 +17,4 @@ class C { >bar : any } } + diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 59ae825a8dc80..c13593dd67a2d 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -149,267 +149,268 @@ declare namespace ts { BarEqualsToken = 70, CaretEqualsToken = 71, Identifier = 72, - BreakKeyword = 73, - CaseKeyword = 74, - CatchKeyword = 75, - ClassKeyword = 76, - ConstKeyword = 77, - ContinueKeyword = 78, - DebuggerKeyword = 79, - DefaultKeyword = 80, - DeleteKeyword = 81, - DoKeyword = 82, - ElseKeyword = 83, - EnumKeyword = 84, - ExportKeyword = 85, - ExtendsKeyword = 86, - FalseKeyword = 87, - FinallyKeyword = 88, - ForKeyword = 89, - FunctionKeyword = 90, - IfKeyword = 91, - ImportKeyword = 92, - InKeyword = 93, - InstanceOfKeyword = 94, - NewKeyword = 95, - NullKeyword = 96, - ReturnKeyword = 97, - SuperKeyword = 98, - SwitchKeyword = 99, - ThisKeyword = 100, - ThrowKeyword = 101, - TrueKeyword = 102, - TryKeyword = 103, - TypeOfKeyword = 104, - VarKeyword = 105, - VoidKeyword = 106, - WhileKeyword = 107, - WithKeyword = 108, - ImplementsKeyword = 109, - InterfaceKeyword = 110, - LetKeyword = 111, - PackageKeyword = 112, - PrivateKeyword = 113, - ProtectedKeyword = 114, - PublicKeyword = 115, - StaticKeyword = 116, - YieldKeyword = 117, - AbstractKeyword = 118, - AsKeyword = 119, - AnyKeyword = 120, - AsyncKeyword = 121, - AwaitKeyword = 122, - BooleanKeyword = 123, - ConstructorKeyword = 124, - DeclareKeyword = 125, - GetKeyword = 126, - InferKeyword = 127, - IsKeyword = 128, - KeyOfKeyword = 129, - ModuleKeyword = 130, - NamespaceKeyword = 131, - NeverKeyword = 132, - ReadonlyKeyword = 133, - RequireKeyword = 134, - NumberKeyword = 135, - ObjectKeyword = 136, - SetKeyword = 137, - StringKeyword = 138, - SymbolKeyword = 139, - TypeKeyword = 140, - UndefinedKeyword = 141, - UniqueKeyword = 142, - UnknownKeyword = 143, - FromKeyword = 144, - GlobalKeyword = 145, - BigIntKeyword = 146, - OfKeyword = 147, - QualifiedName = 148, - ComputedPropertyName = 149, - TypeParameter = 150, - Parameter = 151, - Decorator = 152, - PropertySignature = 153, - PropertyDeclaration = 154, - MethodSignature = 155, - MethodDeclaration = 156, - Constructor = 157, - GetAccessor = 158, - SetAccessor = 159, - CallSignature = 160, - ConstructSignature = 161, - IndexSignature = 162, - TypePredicate = 163, - TypeReference = 164, - FunctionType = 165, - ConstructorType = 166, - TypeQuery = 167, - TypeLiteral = 168, - ArrayType = 169, - TupleType = 170, - OptionalType = 171, - RestType = 172, - UnionType = 173, - IntersectionType = 174, - ConditionalType = 175, - InferType = 176, - ParenthesizedType = 177, - ThisType = 178, - TypeOperator = 179, - IndexedAccessType = 180, - MappedType = 181, - LiteralType = 182, - ImportType = 183, - ObjectBindingPattern = 184, - ArrayBindingPattern = 185, - BindingElement = 186, - ArrayLiteralExpression = 187, - ObjectLiteralExpression = 188, - PropertyAccessExpression = 189, - ElementAccessExpression = 190, - CallExpression = 191, - NewExpression = 192, - TaggedTemplateExpression = 193, - TypeAssertionExpression = 194, - ParenthesizedExpression = 195, - FunctionExpression = 196, - ArrowFunction = 197, - DeleteExpression = 198, - TypeOfExpression = 199, - VoidExpression = 200, - AwaitExpression = 201, - PrefixUnaryExpression = 202, - PostfixUnaryExpression = 203, - BinaryExpression = 204, - ConditionalExpression = 205, - TemplateExpression = 206, - YieldExpression = 207, - SpreadElement = 208, - ClassExpression = 209, - OmittedExpression = 210, - ExpressionWithTypeArguments = 211, - AsExpression = 212, - NonNullExpression = 213, - MetaProperty = 214, - SyntheticExpression = 215, - TemplateSpan = 216, - SemicolonClassElement = 217, - Block = 218, - VariableStatement = 219, - EmptyStatement = 220, - ExpressionStatement = 221, - IfStatement = 222, - DoStatement = 223, - WhileStatement = 224, - ForStatement = 225, - ForInStatement = 226, - ForOfStatement = 227, - ContinueStatement = 228, - BreakStatement = 229, - ReturnStatement = 230, - WithStatement = 231, - SwitchStatement = 232, - LabeledStatement = 233, - ThrowStatement = 234, - TryStatement = 235, - DebuggerStatement = 236, - VariableDeclaration = 237, - VariableDeclarationList = 238, - FunctionDeclaration = 239, - ClassDeclaration = 240, - InterfaceDeclaration = 241, - TypeAliasDeclaration = 242, - EnumDeclaration = 243, - ModuleDeclaration = 244, - ModuleBlock = 245, - CaseBlock = 246, - NamespaceExportDeclaration = 247, - ImportEqualsDeclaration = 248, - ImportDeclaration = 249, - ImportClause = 250, - NamespaceImport = 251, - NamedImports = 252, - ImportSpecifier = 253, - ExportAssignment = 254, - ExportDeclaration = 255, - NamedExports = 256, - ExportSpecifier = 257, - MissingDeclaration = 258, - ExternalModuleReference = 259, - JsxElement = 260, - JsxSelfClosingElement = 261, - JsxOpeningElement = 262, - JsxClosingElement = 263, - JsxFragment = 264, - JsxOpeningFragment = 265, - JsxClosingFragment = 266, - JsxAttribute = 267, - JsxAttributes = 268, - JsxSpreadAttribute = 269, - JsxExpression = 270, - CaseClause = 271, - DefaultClause = 272, - HeritageClause = 273, - CatchClause = 274, - PropertyAssignment = 275, - ShorthandPropertyAssignment = 276, - SpreadAssignment = 277, - EnumMember = 278, - UnparsedPrologue = 279, - UnparsedPrepend = 280, - UnparsedText = 281, - UnparsedInternalText = 282, - UnparsedSyntheticReference = 283, - SourceFile = 284, - Bundle = 285, - UnparsedSource = 286, - InputFiles = 287, - JSDocTypeExpression = 288, - JSDocAllType = 289, - JSDocUnknownType = 290, - JSDocNullableType = 291, - JSDocNonNullableType = 292, - JSDocOptionalType = 293, - JSDocFunctionType = 294, - JSDocVariadicType = 295, - JSDocComment = 296, - JSDocTypeLiteral = 297, - JSDocSignature = 298, - JSDocTag = 299, - JSDocAugmentsTag = 300, - JSDocClassTag = 301, - JSDocCallbackTag = 302, - JSDocEnumTag = 303, - JSDocParameterTag = 304, - JSDocReturnTag = 305, - JSDocThisTag = 306, - JSDocTypeTag = 307, - JSDocTemplateTag = 308, - JSDocTypedefTag = 309, - JSDocPropertyTag = 310, - SyntaxList = 311, - NotEmittedStatement = 312, - PartiallyEmittedExpression = 313, - CommaListExpression = 314, - MergeDeclarationMarker = 315, - EndOfDeclarationMarker = 316, - Count = 317, + PrivateName = 73, + BreakKeyword = 74, + CaseKeyword = 75, + CatchKeyword = 76, + ClassKeyword = 77, + ConstKeyword = 78, + ContinueKeyword = 79, + DebuggerKeyword = 80, + DefaultKeyword = 81, + DeleteKeyword = 82, + DoKeyword = 83, + ElseKeyword = 84, + EnumKeyword = 85, + ExportKeyword = 86, + ExtendsKeyword = 87, + FalseKeyword = 88, + FinallyKeyword = 89, + ForKeyword = 90, + FunctionKeyword = 91, + IfKeyword = 92, + ImportKeyword = 93, + InKeyword = 94, + InstanceOfKeyword = 95, + NewKeyword = 96, + NullKeyword = 97, + ReturnKeyword = 98, + SuperKeyword = 99, + SwitchKeyword = 100, + ThisKeyword = 101, + ThrowKeyword = 102, + TrueKeyword = 103, + TryKeyword = 104, + TypeOfKeyword = 105, + VarKeyword = 106, + VoidKeyword = 107, + WhileKeyword = 108, + WithKeyword = 109, + ImplementsKeyword = 110, + InterfaceKeyword = 111, + LetKeyword = 112, + PackageKeyword = 113, + PrivateKeyword = 114, + ProtectedKeyword = 115, + PublicKeyword = 116, + StaticKeyword = 117, + YieldKeyword = 118, + AbstractKeyword = 119, + AsKeyword = 120, + AnyKeyword = 121, + AsyncKeyword = 122, + AwaitKeyword = 123, + BooleanKeyword = 124, + ConstructorKeyword = 125, + DeclareKeyword = 126, + GetKeyword = 127, + InferKeyword = 128, + IsKeyword = 129, + KeyOfKeyword = 130, + ModuleKeyword = 131, + NamespaceKeyword = 132, + NeverKeyword = 133, + ReadonlyKeyword = 134, + RequireKeyword = 135, + NumberKeyword = 136, + ObjectKeyword = 137, + SetKeyword = 138, + StringKeyword = 139, + SymbolKeyword = 140, + TypeKeyword = 141, + UndefinedKeyword = 142, + UniqueKeyword = 143, + UnknownKeyword = 144, + FromKeyword = 145, + GlobalKeyword = 146, + BigIntKeyword = 147, + OfKeyword = 148, + QualifiedName = 149, + ComputedPropertyName = 150, + TypeParameter = 151, + Parameter = 152, + Decorator = 153, + PropertySignature = 154, + PropertyDeclaration = 155, + MethodSignature = 156, + MethodDeclaration = 157, + Constructor = 158, + GetAccessor = 159, + SetAccessor = 160, + CallSignature = 161, + ConstructSignature = 162, + IndexSignature = 163, + TypePredicate = 164, + TypeReference = 165, + FunctionType = 166, + ConstructorType = 167, + TypeQuery = 168, + TypeLiteral = 169, + ArrayType = 170, + TupleType = 171, + OptionalType = 172, + RestType = 173, + UnionType = 174, + IntersectionType = 175, + ConditionalType = 176, + InferType = 177, + ParenthesizedType = 178, + ThisType = 179, + TypeOperator = 180, + IndexedAccessType = 181, + MappedType = 182, + LiteralType = 183, + ImportType = 184, + ObjectBindingPattern = 185, + ArrayBindingPattern = 186, + BindingElement = 187, + ArrayLiteralExpression = 188, + ObjectLiteralExpression = 189, + PropertyAccessExpression = 190, + ElementAccessExpression = 191, + CallExpression = 192, + NewExpression = 193, + TaggedTemplateExpression = 194, + TypeAssertionExpression = 195, + ParenthesizedExpression = 196, + FunctionExpression = 197, + ArrowFunction = 198, + DeleteExpression = 199, + TypeOfExpression = 200, + VoidExpression = 201, + AwaitExpression = 202, + PrefixUnaryExpression = 203, + PostfixUnaryExpression = 204, + BinaryExpression = 205, + ConditionalExpression = 206, + TemplateExpression = 207, + YieldExpression = 208, + SpreadElement = 209, + ClassExpression = 210, + OmittedExpression = 211, + ExpressionWithTypeArguments = 212, + AsExpression = 213, + NonNullExpression = 214, + MetaProperty = 215, + SyntheticExpression = 216, + TemplateSpan = 217, + SemicolonClassElement = 218, + Block = 219, + VariableStatement = 220, + EmptyStatement = 221, + ExpressionStatement = 222, + IfStatement = 223, + DoStatement = 224, + WhileStatement = 225, + ForStatement = 226, + ForInStatement = 227, + ForOfStatement = 228, + ContinueStatement = 229, + BreakStatement = 230, + ReturnStatement = 231, + WithStatement = 232, + SwitchStatement = 233, + LabeledStatement = 234, + ThrowStatement = 235, + TryStatement = 236, + DebuggerStatement = 237, + VariableDeclaration = 238, + VariableDeclarationList = 239, + FunctionDeclaration = 240, + ClassDeclaration = 241, + InterfaceDeclaration = 242, + TypeAliasDeclaration = 243, + EnumDeclaration = 244, + ModuleDeclaration = 245, + ModuleBlock = 246, + CaseBlock = 247, + NamespaceExportDeclaration = 248, + ImportEqualsDeclaration = 249, + ImportDeclaration = 250, + ImportClause = 251, + NamespaceImport = 252, + NamedImports = 253, + ImportSpecifier = 254, + ExportAssignment = 255, + ExportDeclaration = 256, + NamedExports = 257, + ExportSpecifier = 258, + MissingDeclaration = 259, + ExternalModuleReference = 260, + JsxElement = 261, + JsxSelfClosingElement = 262, + JsxOpeningElement = 263, + JsxClosingElement = 264, + JsxFragment = 265, + JsxOpeningFragment = 266, + JsxClosingFragment = 267, + JsxAttribute = 268, + JsxAttributes = 269, + JsxSpreadAttribute = 270, + JsxExpression = 271, + CaseClause = 272, + DefaultClause = 273, + HeritageClause = 274, + CatchClause = 275, + PropertyAssignment = 276, + ShorthandPropertyAssignment = 277, + SpreadAssignment = 278, + EnumMember = 279, + UnparsedPrologue = 280, + UnparsedPrepend = 281, + UnparsedText = 282, + UnparsedInternalText = 283, + UnparsedSyntheticReference = 284, + SourceFile = 285, + Bundle = 286, + UnparsedSource = 287, + InputFiles = 288, + JSDocTypeExpression = 289, + JSDocAllType = 290, + JSDocUnknownType = 291, + JSDocNullableType = 292, + JSDocNonNullableType = 293, + JSDocOptionalType = 294, + JSDocFunctionType = 295, + JSDocVariadicType = 296, + JSDocComment = 297, + JSDocTypeLiteral = 298, + JSDocSignature = 299, + JSDocTag = 300, + JSDocAugmentsTag = 301, + JSDocClassTag = 302, + JSDocCallbackTag = 303, + JSDocEnumTag = 304, + JSDocParameterTag = 305, + JSDocReturnTag = 306, + JSDocThisTag = 307, + JSDocTypeTag = 308, + JSDocTemplateTag = 309, + JSDocTypedefTag = 310, + JSDocPropertyTag = 311, + SyntaxList = 312, + NotEmittedStatement = 313, + PartiallyEmittedExpression = 314, + CommaListExpression = 315, + MergeDeclarationMarker = 316, + EndOfDeclarationMarker = 317, + Count = 318, FirstAssignment = 59, LastAssignment = 71, FirstCompoundAssignment = 60, LastCompoundAssignment = 71, - FirstReservedWord = 73, - LastReservedWord = 108, - FirstKeyword = 73, - LastKeyword = 147, - FirstFutureReservedWord = 109, - LastFutureReservedWord = 117, - FirstTypeNode = 163, - LastTypeNode = 183, + FirstReservedWord = 74, + LastReservedWord = 109, + FirstKeyword = 74, + LastKeyword = 148, + FirstFutureReservedWord = 110, + LastFutureReservedWord = 118, + FirstTypeNode = 164, + LastTypeNode = 184, FirstPunctuation = 18, LastPunctuation = 71, FirstToken = 0, - LastToken = 147, + LastToken = 148, FirstTriviaToken = 2, LastTriviaToken = 7, FirstLiteralToken = 8, @@ -418,11 +419,11 @@ declare namespace ts { LastTemplateToken = 17, FirstBinaryOperator = 28, LastBinaryOperator = 71, - FirstNode = 148, - FirstJSDocNode = 288, - LastJSDocNode = 310, - FirstJSDocTagNode = 299, - LastJSDocTagNode = 310, + FirstNode = 149, + FirstJSDocNode = 289, + LastJSDocNode = 311, + FirstJSDocTagNode = 300, + LastJSDocTagNode = 311, } enum NodeFlags { None = 0, @@ -534,8 +535,8 @@ declare namespace ts { right: Identifier; } type EntityName = Identifier | QualifiedName; - type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName; - type DeclarationName = Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern; + type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | PrivateName; + type DeclarationName = Identifier | PrivateName | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern; interface Declaration extends Node { _declarationBrand: any; } @@ -550,6 +551,10 @@ declare namespace ts { kind: SyntaxKind.ComputedPropertyName; expression: Expression; } + interface PrivateName extends PrimaryExpression, Declaration { + kind: SyntaxKind.PrivateName; + escapedText: __String; + } interface Decorator extends Node { kind: SyntaxKind.Decorator; parent: NamedDeclaration; @@ -1070,7 +1075,7 @@ declare namespace ts { interface PropertyAccessExpression extends MemberExpression, NamedDeclaration { kind: SyntaxKind.PropertyAccessExpression; expression: LeftHandSideExpression; - name: Identifier; + name: Identifier | PrivateName; } interface SuperPropertyAccessExpression extends PropertyAccessExpression { expression: SuperExpression; @@ -1916,6 +1921,7 @@ declare namespace ts { getDeclaredTypeOfSymbol(symbol: Symbol): Type; getPropertiesOfType(type: Type): Symbol[]; getPropertyOfType(type: Type, propertyName: string): Symbol | undefined; + getPropertyForPrivateName(apparentType: Type, leftType: Type, right: PrivateName, errorNode: Node | undefined): Symbol | undefined; getIndexInfoOfType(type: Type, kind: IndexKind): IndexInfo | undefined; getSignaturesOfType(type: Type, kind: SignatureKind): ReadonlyArray; getIndexTypeOfType(type: Type, kind: IndexKind): Type | undefined; @@ -3280,9 +3286,9 @@ declare namespace ts { * @returns The unescaped identifier text. */ function unescapeLeadingUnderscores(identifier: __String): string; - function idText(identifier: Identifier): string; + function idText(identifierOrPrivateName: Identifier | PrivateName): string; function symbolName(symbol: Symbol): string; - function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined; + function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | PrivateName | undefined; function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName | undefined; /** * Gets the JSDoc parameter tags for the node if present. @@ -3370,8 +3376,10 @@ declare namespace ts { function isTemplateMiddle(node: Node): node is TemplateMiddle; function isTemplateTail(node: Node): node is TemplateTail; function isIdentifier(node: Node): node is Identifier; + function isIdentifierOrPrivateName(node: Node): node is Identifier | PrivateName; function isQualifiedName(node: Node): node is QualifiedName; function isComputedPropertyName(node: Node): node is ComputedPropertyName; + function isPrivateName(node: Node): node is PrivateName; function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration; function isParameter(node: Node): node is ParameterDeclaration; function isDecorator(node: Node): node is Decorator; @@ -3837,8 +3845,8 @@ declare namespace ts { function updateArrayLiteral(node: ArrayLiteralExpression, elements: ReadonlyArray): ArrayLiteralExpression; function createObjectLiteral(properties?: ReadonlyArray, multiLine?: boolean): ObjectLiteralExpression; function updateObjectLiteral(node: ObjectLiteralExpression, properties: ReadonlyArray): ObjectLiteralExpression; - function createPropertyAccess(expression: Expression, name: string | Identifier | undefined): PropertyAccessExpression; - function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier): PropertyAccessExpression; + function createPropertyAccess(expression: Expression, name: string | Identifier | PrivateName | undefined): PropertyAccessExpression; + function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier | PrivateName): PropertyAccessExpression; function createElementAccess(expression: Expression, index: number | Expression): ElementAccessExpression; function updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression): ElementAccessExpression; function createCall(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): CallExpression; @@ -4629,6 +4637,9 @@ declare namespace ts { interface Identifier { readonly text: string; } + interface PrivateName { + readonly text: string; + } interface Symbol { readonly name: string; getFlags(): SymbolFlags; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 2b8056735a476..50f9dd5767ab2 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -149,267 +149,268 @@ declare namespace ts { BarEqualsToken = 70, CaretEqualsToken = 71, Identifier = 72, - BreakKeyword = 73, - CaseKeyword = 74, - CatchKeyword = 75, - ClassKeyword = 76, - ConstKeyword = 77, - ContinueKeyword = 78, - DebuggerKeyword = 79, - DefaultKeyword = 80, - DeleteKeyword = 81, - DoKeyword = 82, - ElseKeyword = 83, - EnumKeyword = 84, - ExportKeyword = 85, - ExtendsKeyword = 86, - FalseKeyword = 87, - FinallyKeyword = 88, - ForKeyword = 89, - FunctionKeyword = 90, - IfKeyword = 91, - ImportKeyword = 92, - InKeyword = 93, - InstanceOfKeyword = 94, - NewKeyword = 95, - NullKeyword = 96, - ReturnKeyword = 97, - SuperKeyword = 98, - SwitchKeyword = 99, - ThisKeyword = 100, - ThrowKeyword = 101, - TrueKeyword = 102, - TryKeyword = 103, - TypeOfKeyword = 104, - VarKeyword = 105, - VoidKeyword = 106, - WhileKeyword = 107, - WithKeyword = 108, - ImplementsKeyword = 109, - InterfaceKeyword = 110, - LetKeyword = 111, - PackageKeyword = 112, - PrivateKeyword = 113, - ProtectedKeyword = 114, - PublicKeyword = 115, - StaticKeyword = 116, - YieldKeyword = 117, - AbstractKeyword = 118, - AsKeyword = 119, - AnyKeyword = 120, - AsyncKeyword = 121, - AwaitKeyword = 122, - BooleanKeyword = 123, - ConstructorKeyword = 124, - DeclareKeyword = 125, - GetKeyword = 126, - InferKeyword = 127, - IsKeyword = 128, - KeyOfKeyword = 129, - ModuleKeyword = 130, - NamespaceKeyword = 131, - NeverKeyword = 132, - ReadonlyKeyword = 133, - RequireKeyword = 134, - NumberKeyword = 135, - ObjectKeyword = 136, - SetKeyword = 137, - StringKeyword = 138, - SymbolKeyword = 139, - TypeKeyword = 140, - UndefinedKeyword = 141, - UniqueKeyword = 142, - UnknownKeyword = 143, - FromKeyword = 144, - GlobalKeyword = 145, - BigIntKeyword = 146, - OfKeyword = 147, - QualifiedName = 148, - ComputedPropertyName = 149, - TypeParameter = 150, - Parameter = 151, - Decorator = 152, - PropertySignature = 153, - PropertyDeclaration = 154, - MethodSignature = 155, - MethodDeclaration = 156, - Constructor = 157, - GetAccessor = 158, - SetAccessor = 159, - CallSignature = 160, - ConstructSignature = 161, - IndexSignature = 162, - TypePredicate = 163, - TypeReference = 164, - FunctionType = 165, - ConstructorType = 166, - TypeQuery = 167, - TypeLiteral = 168, - ArrayType = 169, - TupleType = 170, - OptionalType = 171, - RestType = 172, - UnionType = 173, - IntersectionType = 174, - ConditionalType = 175, - InferType = 176, - ParenthesizedType = 177, - ThisType = 178, - TypeOperator = 179, - IndexedAccessType = 180, - MappedType = 181, - LiteralType = 182, - ImportType = 183, - ObjectBindingPattern = 184, - ArrayBindingPattern = 185, - BindingElement = 186, - ArrayLiteralExpression = 187, - ObjectLiteralExpression = 188, - PropertyAccessExpression = 189, - ElementAccessExpression = 190, - CallExpression = 191, - NewExpression = 192, - TaggedTemplateExpression = 193, - TypeAssertionExpression = 194, - ParenthesizedExpression = 195, - FunctionExpression = 196, - ArrowFunction = 197, - DeleteExpression = 198, - TypeOfExpression = 199, - VoidExpression = 200, - AwaitExpression = 201, - PrefixUnaryExpression = 202, - PostfixUnaryExpression = 203, - BinaryExpression = 204, - ConditionalExpression = 205, - TemplateExpression = 206, - YieldExpression = 207, - SpreadElement = 208, - ClassExpression = 209, - OmittedExpression = 210, - ExpressionWithTypeArguments = 211, - AsExpression = 212, - NonNullExpression = 213, - MetaProperty = 214, - SyntheticExpression = 215, - TemplateSpan = 216, - SemicolonClassElement = 217, - Block = 218, - VariableStatement = 219, - EmptyStatement = 220, - ExpressionStatement = 221, - IfStatement = 222, - DoStatement = 223, - WhileStatement = 224, - ForStatement = 225, - ForInStatement = 226, - ForOfStatement = 227, - ContinueStatement = 228, - BreakStatement = 229, - ReturnStatement = 230, - WithStatement = 231, - SwitchStatement = 232, - LabeledStatement = 233, - ThrowStatement = 234, - TryStatement = 235, - DebuggerStatement = 236, - VariableDeclaration = 237, - VariableDeclarationList = 238, - FunctionDeclaration = 239, - ClassDeclaration = 240, - InterfaceDeclaration = 241, - TypeAliasDeclaration = 242, - EnumDeclaration = 243, - ModuleDeclaration = 244, - ModuleBlock = 245, - CaseBlock = 246, - NamespaceExportDeclaration = 247, - ImportEqualsDeclaration = 248, - ImportDeclaration = 249, - ImportClause = 250, - NamespaceImport = 251, - NamedImports = 252, - ImportSpecifier = 253, - ExportAssignment = 254, - ExportDeclaration = 255, - NamedExports = 256, - ExportSpecifier = 257, - MissingDeclaration = 258, - ExternalModuleReference = 259, - JsxElement = 260, - JsxSelfClosingElement = 261, - JsxOpeningElement = 262, - JsxClosingElement = 263, - JsxFragment = 264, - JsxOpeningFragment = 265, - JsxClosingFragment = 266, - JsxAttribute = 267, - JsxAttributes = 268, - JsxSpreadAttribute = 269, - JsxExpression = 270, - CaseClause = 271, - DefaultClause = 272, - HeritageClause = 273, - CatchClause = 274, - PropertyAssignment = 275, - ShorthandPropertyAssignment = 276, - SpreadAssignment = 277, - EnumMember = 278, - UnparsedPrologue = 279, - UnparsedPrepend = 280, - UnparsedText = 281, - UnparsedInternalText = 282, - UnparsedSyntheticReference = 283, - SourceFile = 284, - Bundle = 285, - UnparsedSource = 286, - InputFiles = 287, - JSDocTypeExpression = 288, - JSDocAllType = 289, - JSDocUnknownType = 290, - JSDocNullableType = 291, - JSDocNonNullableType = 292, - JSDocOptionalType = 293, - JSDocFunctionType = 294, - JSDocVariadicType = 295, - JSDocComment = 296, - JSDocTypeLiteral = 297, - JSDocSignature = 298, - JSDocTag = 299, - JSDocAugmentsTag = 300, - JSDocClassTag = 301, - JSDocCallbackTag = 302, - JSDocEnumTag = 303, - JSDocParameterTag = 304, - JSDocReturnTag = 305, - JSDocThisTag = 306, - JSDocTypeTag = 307, - JSDocTemplateTag = 308, - JSDocTypedefTag = 309, - JSDocPropertyTag = 310, - SyntaxList = 311, - NotEmittedStatement = 312, - PartiallyEmittedExpression = 313, - CommaListExpression = 314, - MergeDeclarationMarker = 315, - EndOfDeclarationMarker = 316, - Count = 317, + PrivateName = 73, + BreakKeyword = 74, + CaseKeyword = 75, + CatchKeyword = 76, + ClassKeyword = 77, + ConstKeyword = 78, + ContinueKeyword = 79, + DebuggerKeyword = 80, + DefaultKeyword = 81, + DeleteKeyword = 82, + DoKeyword = 83, + ElseKeyword = 84, + EnumKeyword = 85, + ExportKeyword = 86, + ExtendsKeyword = 87, + FalseKeyword = 88, + FinallyKeyword = 89, + ForKeyword = 90, + FunctionKeyword = 91, + IfKeyword = 92, + ImportKeyword = 93, + InKeyword = 94, + InstanceOfKeyword = 95, + NewKeyword = 96, + NullKeyword = 97, + ReturnKeyword = 98, + SuperKeyword = 99, + SwitchKeyword = 100, + ThisKeyword = 101, + ThrowKeyword = 102, + TrueKeyword = 103, + TryKeyword = 104, + TypeOfKeyword = 105, + VarKeyword = 106, + VoidKeyword = 107, + WhileKeyword = 108, + WithKeyword = 109, + ImplementsKeyword = 110, + InterfaceKeyword = 111, + LetKeyword = 112, + PackageKeyword = 113, + PrivateKeyword = 114, + ProtectedKeyword = 115, + PublicKeyword = 116, + StaticKeyword = 117, + YieldKeyword = 118, + AbstractKeyword = 119, + AsKeyword = 120, + AnyKeyword = 121, + AsyncKeyword = 122, + AwaitKeyword = 123, + BooleanKeyword = 124, + ConstructorKeyword = 125, + DeclareKeyword = 126, + GetKeyword = 127, + InferKeyword = 128, + IsKeyword = 129, + KeyOfKeyword = 130, + ModuleKeyword = 131, + NamespaceKeyword = 132, + NeverKeyword = 133, + ReadonlyKeyword = 134, + RequireKeyword = 135, + NumberKeyword = 136, + ObjectKeyword = 137, + SetKeyword = 138, + StringKeyword = 139, + SymbolKeyword = 140, + TypeKeyword = 141, + UndefinedKeyword = 142, + UniqueKeyword = 143, + UnknownKeyword = 144, + FromKeyword = 145, + GlobalKeyword = 146, + BigIntKeyword = 147, + OfKeyword = 148, + QualifiedName = 149, + ComputedPropertyName = 150, + TypeParameter = 151, + Parameter = 152, + Decorator = 153, + PropertySignature = 154, + PropertyDeclaration = 155, + MethodSignature = 156, + MethodDeclaration = 157, + Constructor = 158, + GetAccessor = 159, + SetAccessor = 160, + CallSignature = 161, + ConstructSignature = 162, + IndexSignature = 163, + TypePredicate = 164, + TypeReference = 165, + FunctionType = 166, + ConstructorType = 167, + TypeQuery = 168, + TypeLiteral = 169, + ArrayType = 170, + TupleType = 171, + OptionalType = 172, + RestType = 173, + UnionType = 174, + IntersectionType = 175, + ConditionalType = 176, + InferType = 177, + ParenthesizedType = 178, + ThisType = 179, + TypeOperator = 180, + IndexedAccessType = 181, + MappedType = 182, + LiteralType = 183, + ImportType = 184, + ObjectBindingPattern = 185, + ArrayBindingPattern = 186, + BindingElement = 187, + ArrayLiteralExpression = 188, + ObjectLiteralExpression = 189, + PropertyAccessExpression = 190, + ElementAccessExpression = 191, + CallExpression = 192, + NewExpression = 193, + TaggedTemplateExpression = 194, + TypeAssertionExpression = 195, + ParenthesizedExpression = 196, + FunctionExpression = 197, + ArrowFunction = 198, + DeleteExpression = 199, + TypeOfExpression = 200, + VoidExpression = 201, + AwaitExpression = 202, + PrefixUnaryExpression = 203, + PostfixUnaryExpression = 204, + BinaryExpression = 205, + ConditionalExpression = 206, + TemplateExpression = 207, + YieldExpression = 208, + SpreadElement = 209, + ClassExpression = 210, + OmittedExpression = 211, + ExpressionWithTypeArguments = 212, + AsExpression = 213, + NonNullExpression = 214, + MetaProperty = 215, + SyntheticExpression = 216, + TemplateSpan = 217, + SemicolonClassElement = 218, + Block = 219, + VariableStatement = 220, + EmptyStatement = 221, + ExpressionStatement = 222, + IfStatement = 223, + DoStatement = 224, + WhileStatement = 225, + ForStatement = 226, + ForInStatement = 227, + ForOfStatement = 228, + ContinueStatement = 229, + BreakStatement = 230, + ReturnStatement = 231, + WithStatement = 232, + SwitchStatement = 233, + LabeledStatement = 234, + ThrowStatement = 235, + TryStatement = 236, + DebuggerStatement = 237, + VariableDeclaration = 238, + VariableDeclarationList = 239, + FunctionDeclaration = 240, + ClassDeclaration = 241, + InterfaceDeclaration = 242, + TypeAliasDeclaration = 243, + EnumDeclaration = 244, + ModuleDeclaration = 245, + ModuleBlock = 246, + CaseBlock = 247, + NamespaceExportDeclaration = 248, + ImportEqualsDeclaration = 249, + ImportDeclaration = 250, + ImportClause = 251, + NamespaceImport = 252, + NamedImports = 253, + ImportSpecifier = 254, + ExportAssignment = 255, + ExportDeclaration = 256, + NamedExports = 257, + ExportSpecifier = 258, + MissingDeclaration = 259, + ExternalModuleReference = 260, + JsxElement = 261, + JsxSelfClosingElement = 262, + JsxOpeningElement = 263, + JsxClosingElement = 264, + JsxFragment = 265, + JsxOpeningFragment = 266, + JsxClosingFragment = 267, + JsxAttribute = 268, + JsxAttributes = 269, + JsxSpreadAttribute = 270, + JsxExpression = 271, + CaseClause = 272, + DefaultClause = 273, + HeritageClause = 274, + CatchClause = 275, + PropertyAssignment = 276, + ShorthandPropertyAssignment = 277, + SpreadAssignment = 278, + EnumMember = 279, + UnparsedPrologue = 280, + UnparsedPrepend = 281, + UnparsedText = 282, + UnparsedInternalText = 283, + UnparsedSyntheticReference = 284, + SourceFile = 285, + Bundle = 286, + UnparsedSource = 287, + InputFiles = 288, + JSDocTypeExpression = 289, + JSDocAllType = 290, + JSDocUnknownType = 291, + JSDocNullableType = 292, + JSDocNonNullableType = 293, + JSDocOptionalType = 294, + JSDocFunctionType = 295, + JSDocVariadicType = 296, + JSDocComment = 297, + JSDocTypeLiteral = 298, + JSDocSignature = 299, + JSDocTag = 300, + JSDocAugmentsTag = 301, + JSDocClassTag = 302, + JSDocCallbackTag = 303, + JSDocEnumTag = 304, + JSDocParameterTag = 305, + JSDocReturnTag = 306, + JSDocThisTag = 307, + JSDocTypeTag = 308, + JSDocTemplateTag = 309, + JSDocTypedefTag = 310, + JSDocPropertyTag = 311, + SyntaxList = 312, + NotEmittedStatement = 313, + PartiallyEmittedExpression = 314, + CommaListExpression = 315, + MergeDeclarationMarker = 316, + EndOfDeclarationMarker = 317, + Count = 318, FirstAssignment = 59, LastAssignment = 71, FirstCompoundAssignment = 60, LastCompoundAssignment = 71, - FirstReservedWord = 73, - LastReservedWord = 108, - FirstKeyword = 73, - LastKeyword = 147, - FirstFutureReservedWord = 109, - LastFutureReservedWord = 117, - FirstTypeNode = 163, - LastTypeNode = 183, + FirstReservedWord = 74, + LastReservedWord = 109, + FirstKeyword = 74, + LastKeyword = 148, + FirstFutureReservedWord = 110, + LastFutureReservedWord = 118, + FirstTypeNode = 164, + LastTypeNode = 184, FirstPunctuation = 18, LastPunctuation = 71, FirstToken = 0, - LastToken = 147, + LastToken = 148, FirstTriviaToken = 2, LastTriviaToken = 7, FirstLiteralToken = 8, @@ -418,11 +419,11 @@ declare namespace ts { LastTemplateToken = 17, FirstBinaryOperator = 28, LastBinaryOperator = 71, - FirstNode = 148, - FirstJSDocNode = 288, - LastJSDocNode = 310, - FirstJSDocTagNode = 299, - LastJSDocTagNode = 310, + FirstNode = 149, + FirstJSDocNode = 289, + LastJSDocNode = 311, + FirstJSDocTagNode = 300, + LastJSDocTagNode = 311, } enum NodeFlags { None = 0, @@ -534,8 +535,8 @@ declare namespace ts { right: Identifier; } type EntityName = Identifier | QualifiedName; - type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName; - type DeclarationName = Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern; + type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | PrivateName; + type DeclarationName = Identifier | PrivateName | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern; interface Declaration extends Node { _declarationBrand: any; } @@ -550,6 +551,10 @@ declare namespace ts { kind: SyntaxKind.ComputedPropertyName; expression: Expression; } + interface PrivateName extends PrimaryExpression, Declaration { + kind: SyntaxKind.PrivateName; + escapedText: __String; + } interface Decorator extends Node { kind: SyntaxKind.Decorator; parent: NamedDeclaration; @@ -1070,7 +1075,7 @@ declare namespace ts { interface PropertyAccessExpression extends MemberExpression, NamedDeclaration { kind: SyntaxKind.PropertyAccessExpression; expression: LeftHandSideExpression; - name: Identifier; + name: Identifier | PrivateName; } interface SuperPropertyAccessExpression extends PropertyAccessExpression { expression: SuperExpression; @@ -1916,6 +1921,7 @@ declare namespace ts { getDeclaredTypeOfSymbol(symbol: Symbol): Type; getPropertiesOfType(type: Type): Symbol[]; getPropertyOfType(type: Type, propertyName: string): Symbol | undefined; + getPropertyForPrivateName(apparentType: Type, leftType: Type, right: PrivateName, errorNode: Node | undefined): Symbol | undefined; getIndexInfoOfType(type: Type, kind: IndexKind): IndexInfo | undefined; getSignaturesOfType(type: Type, kind: SignatureKind): ReadonlyArray; getIndexTypeOfType(type: Type, kind: IndexKind): Type | undefined; @@ -3280,9 +3286,9 @@ declare namespace ts { * @returns The unescaped identifier text. */ function unescapeLeadingUnderscores(identifier: __String): string; - function idText(identifier: Identifier): string; + function idText(identifierOrPrivateName: Identifier | PrivateName): string; function symbolName(symbol: Symbol): string; - function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined; + function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | PrivateName | undefined; function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName | undefined; /** * Gets the JSDoc parameter tags for the node if present. @@ -3370,8 +3376,10 @@ declare namespace ts { function isTemplateMiddle(node: Node): node is TemplateMiddle; function isTemplateTail(node: Node): node is TemplateTail; function isIdentifier(node: Node): node is Identifier; + function isIdentifierOrPrivateName(node: Node): node is Identifier | PrivateName; function isQualifiedName(node: Node): node is QualifiedName; function isComputedPropertyName(node: Node): node is ComputedPropertyName; + function isPrivateName(node: Node): node is PrivateName; function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration; function isParameter(node: Node): node is ParameterDeclaration; function isDecorator(node: Node): node is Decorator; @@ -3837,8 +3845,8 @@ declare namespace ts { function updateArrayLiteral(node: ArrayLiteralExpression, elements: ReadonlyArray): ArrayLiteralExpression; function createObjectLiteral(properties?: ReadonlyArray, multiLine?: boolean): ObjectLiteralExpression; function updateObjectLiteral(node: ObjectLiteralExpression, properties: ReadonlyArray): ObjectLiteralExpression; - function createPropertyAccess(expression: Expression, name: string | Identifier | undefined): PropertyAccessExpression; - function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier): PropertyAccessExpression; + function createPropertyAccess(expression: Expression, name: string | Identifier | PrivateName | undefined): PropertyAccessExpression; + function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier | PrivateName): PropertyAccessExpression; function createElementAccess(expression: Expression, index: number | Expression): ElementAccessExpression; function updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression): ElementAccessExpression; function createCall(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): CallExpression; @@ -4629,6 +4637,9 @@ declare namespace ts { interface Identifier { readonly text: string; } + interface PrivateName { + readonly text: string; + } interface Symbol { readonly name: string; getFlags(): SymbolFlags; diff --git a/tests/baselines/reference/declarationEmitPrivateSymbolCausesVarDeclarationEmit2.js b/tests/baselines/reference/declarationEmitPrivateSymbolCausesVarDeclarationEmit2.js index b78c104f4682b..51ffc3a02fac7 100644 --- a/tests/baselines/reference/declarationEmitPrivateSymbolCausesVarDeclarationEmit2.js +++ b/tests/baselines/reference/declarationEmitPrivateSymbolCausesVarDeclarationEmit2.js @@ -34,8 +34,8 @@ var C = /** @class */ (function () { } return C; }()); -_a = a_1.x; exports.C = C; +_a = a_1.x; //// [c.js] "use strict"; var __extends = (this && this.__extends) || (function () { @@ -64,8 +64,8 @@ var D = /** @class */ (function (_super) { } return D; }(b_1.C)); -_a = a_1.x; exports.D = D; +_a = a_1.x; //// [a.d.ts] diff --git a/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping.baseline b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping.baseline new file mode 100644 index 0000000000000..5fae8ec8c9914 --- /dev/null +++ b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping.baseline @@ -0,0 +1,34 @@ +EmitSkipped: false +FileName : ./dist/index.js +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Foo = /** @class */ (function () { + function Foo() { + } + Foo.prototype.methodName = function (propName) { }; + Foo.prototype.otherMethod = function () { + if (Math.random() > 0.5) { + return { x: 42 }; + } + return { y: "yes" }; + }; + return Foo; +}()); +exports.Foo = Foo; +FileName : ./dist/index.d.ts.map +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../tests/cases/fourslash/index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts +export declare class Foo { + member: string; + methodName(propName: SomeType): void; + otherMethod(): { + x: number; + y?: undefined; + } | { + y: string; + x?: undefined; + }; +} +export interface SomeType { + member: number; +} +//# sourceMappingURL=index.d.ts.map diff --git a/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping2.baseline b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping2.baseline new file mode 100644 index 0000000000000..151713a03bd45 --- /dev/null +++ b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping2.baseline @@ -0,0 +1,35 @@ +EmitSkipped: false +FileName : ./dist/index.js.map +{"version":3,"file":"index.js","sourceRoot":"/tests/cases/fourslash/","sources":["index.ts"],"names":[],"mappings":";;AAAA;IAAA;IASA,CAAC;IAPG,wBAAU,GAAV,UAAW,QAAkB,IAAS,CAAC;IACvC,yBAAW,GAAX;QACI,IAAI,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,EAAE;YACrB,OAAO,EAAC,CAAC,EAAE,EAAE,EAAC,CAAC;SAClB;QACD,OAAO,EAAC,CAAC,EAAE,KAAK,EAAC,CAAC;IACtB,CAAC;IACL,UAAC;AAAD,CAAC,AATD,IASC;AATY,kBAAG"}FileName : ./dist/index.js +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Foo = /** @class */ (function () { + function Foo() { + } + Foo.prototype.methodName = function (propName) { }; + Foo.prototype.otherMethod = function () { + if (Math.random() > 0.5) { + return { x: 42 }; + } + return { y: "yes" }; + }; + return Foo; +}()); +exports.Foo = Foo; +//# sourceMappingURL=index.js.mapFileName : ./dist/index.d.ts.map +{"version":3,"file":"index.d.ts","sourceRoot":"/tests/cases/fourslash/","sources":["index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts +export declare class Foo { + member: string; + methodName(propName: SomeType): void; + otherMethod(): { + x: number; + y?: undefined; + } | { + y: string; + x?: undefined; + }; +} +export interface SomeType { + member: number; +} +//# sourceMappingURL=index.d.ts.map diff --git a/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping3.baseline b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping3.baseline new file mode 100644 index 0000000000000..f05cbbd4c351b --- /dev/null +++ b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping3.baseline @@ -0,0 +1,34 @@ +EmitSkipped: false +FileName : ./dist/index.js +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Foo = /** @class */ (function () { + function Foo() { + } + Foo.prototype.methodName = function (propName) { }; + Foo.prototype.otherMethod = function () { + if (Math.random() > 0.5) { + return { x: 42 }; + } + return { y: "yes" }; + }; + return Foo; +}()); +exports.Foo = Foo; +FileName : ./dist/index.d.ts.map +{"version":3,"file":"index.d.ts","sourceRoot":"/tests/cases/fourslash/","sources":["index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts +export declare class Foo { + member: string; + methodName(propName: SomeType): void; + otherMethod(): { + x: number; + y?: undefined; + } | { + y: string; + x?: undefined; + }; +} +export interface SomeType { + member: number; +} +//# sourceMappingURL=index.d.ts.map diff --git a/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping_NoInline.baseline b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping_NoInline.baseline new file mode 100644 index 0000000000000..ad51be6ddc0f5 --- /dev/null +++ b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping_NoInline.baseline @@ -0,0 +1,34 @@ +EmitSkipped: false +FileName : ./dist/index.js +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Foo = /** @class */ (function () { + function Foo() { + } + Foo.prototype.methodName = function (propName) { }; + Foo.prototype.otherMethod = function () { + if (Math.random() > 0.5) { + return { x: 42 }; + } + return { y: "yes" }; + }; + return Foo; +}()); +exports.Foo = Foo; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90ZXN0cy9jYXNlcy9mb3Vyc2xhc2gvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQTtJQUFBO0lBU0EsQ0FBQztJQVBHLHdCQUFVLEdBQVYsVUFBVyxRQUFrQixJQUFTLENBQUM7SUFDdkMseUJBQVcsR0FBWDtRQUNJLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEdBQUcsRUFBRTtZQUNyQixPQUFPLEVBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBQyxDQUFDO1NBQ2xCO1FBQ0QsT0FBTyxFQUFDLENBQUMsRUFBRSxLQUFLLEVBQUMsQ0FBQztJQUN0QixDQUFDO0lBQ0wsVUFBQztBQUFELENBQUMsQUFURCxJQVNDO0FBVFksa0JBQUcifQ==FileName : ./dist/index.d.ts.map +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../tests/cases/fourslash/index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts +export declare class Foo { + member: string; + methodName(propName: SomeType): void; + otherMethod(): { + x: number; + y?: undefined; + } | { + y: string; + x?: undefined; + }; +} +export interface SomeType { + member: number; +} +//# sourceMappingURL=index.d.ts.map diff --git a/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping_NoInlineSources.baseline b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping_NoInlineSources.baseline new file mode 100644 index 0000000000000..8f6440b29dc78 --- /dev/null +++ b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping_NoInlineSources.baseline @@ -0,0 +1,34 @@ +EmitSkipped: false +FileName : ./dist/index.js +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Foo = /** @class */ (function () { + function Foo() { + } + Foo.prototype.methodName = function (propName) { }; + Foo.prototype.otherMethod = function () { + if (Math.random() > 0.5) { + return { x: 42 }; + } + return { y: "yes" }; + }; + return Foo; +}()); +exports.Foo = Foo; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90ZXN0cy9jYXNlcy9mb3Vyc2xhc2gvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQTtJQUFBO0lBU0EsQ0FBQztJQVBHLHdCQUFVLEdBQVYsVUFBVyxRQUFrQixJQUFTLENBQUM7SUFDdkMseUJBQVcsR0FBWDtRQUNJLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEdBQUcsRUFBRTtZQUNyQixPQUFPLEVBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBQyxDQUFDO1NBQ2xCO1FBQ0QsT0FBTyxFQUFDLENBQUMsRUFBRSxLQUFLLEVBQUMsQ0FBQztJQUN0QixDQUFDO0lBQ0wsVUFBQztBQUFELENBQUMsQUFURCxJQVNDO0FBVFksa0JBQUciLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgY2xhc3MgRm9vIHtcbiAgICBtZW1iZXI6IHN0cmluZztcbiAgICBtZXRob2ROYW1lKHByb3BOYW1lOiBTb21lVHlwZSk6IHZvaWQge31cbiAgICBvdGhlck1ldGhvZCgpIHtcbiAgICAgICAgaWYgKE1hdGgucmFuZG9tKCkgPiAwLjUpIHtcbiAgICAgICAgICAgIHJldHVybiB7eDogNDJ9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7eTogXCJ5ZXNcIn07XG4gICAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNvbWVUeXBlIHtcbiAgICBtZW1iZXI6IG51bWJlcjtcbn0iXX0=FileName : ./dist/index.d.ts.map +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../tests/cases/fourslash/index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts +export declare class Foo { + member: string; + methodName(propName: SomeType): void; + otherMethod(): { + x: number; + y?: undefined; + } | { + y: string; + x?: undefined; + }; +} +export interface SomeType { + member: number; +} +//# sourceMappingURL=index.d.ts.map diff --git a/tests/baselines/reference/decoratorsOnComputedProperties.js b/tests/baselines/reference/decoratorsOnComputedProperties.js index 2af6b460c0518..3f0444b310aaa 100644 --- a/tests/baselines/reference/decoratorsOnComputedProperties.js +++ b/tests/baselines/reference/decoratorsOnComputedProperties.js @@ -196,7 +196,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; -var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21; +var _a, _b, _c, _d; +var _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21; function x(o, k) { } let i = 0; function foo() { return ++i + ""; } @@ -209,11 +210,11 @@ class A { this[Symbol.iterator] = null; this["property4"] = 2; this[Symbol.match] = null; - this[_b] = null; - this[_d] = null; + this[_f] = null; + this[_h] = null; } } -foo(), _a = foo(), _b = foo(), _c = fieldNameB, _d = fieldNameC; +foo(), _e = foo(), _f = foo(), _g = fieldNameB, _h = fieldNameC; __decorate([ x ], A.prototype, "property", void 0); @@ -228,42 +229,42 @@ __decorate([ ], A.prototype, Symbol.iterator, void 0); __decorate([ x -], A.prototype, _a, void 0); +], A.prototype, _e, void 0); __decorate([ x -], A.prototype, _b, void 0); +], A.prototype, _f, void 0); __decorate([ x -], A.prototype, _c, void 0); +], A.prototype, _g, void 0); __decorate([ x -], A.prototype, _d, void 0); -void (_j = class B { +], A.prototype, _h, void 0); +void (_a = class B { constructor() { this["property2"] = 2; this[Symbol.iterator] = null; this["property4"] = 2; this[Symbol.match] = null; - this[_f] = null; - this[_h] = null; + this[_k] = null; + this[_m] = null; } }, foo(), - _e = foo(), - _f = foo(), - _g = fieldNameB, - _h = fieldNameC, - _j); + _j = foo(), + _k = foo(), + _l = fieldNameB, + _m = fieldNameC, + _a); class C { constructor() { this["property2"] = 2; this[Symbol.iterator] = null; this["property4"] = 2; this[Symbol.match] = null; - this[_l] = null; - this[_o] = null; + this[_p] = null; + this[_r] = null; } - [(foo(), _k = foo(), _l = foo(), _m = fieldNameB, _o = fieldNameC, "some" + "method")]() { } + [(foo(), _o = foo(), _p = foo(), _q = fieldNameB, _r = fieldNameC, "some" + "method")]() { } } __decorate([ x @@ -279,26 +280,26 @@ __decorate([ ], C.prototype, Symbol.iterator, void 0); __decorate([ x -], C.prototype, _k, void 0); +], C.prototype, _o, void 0); __decorate([ x -], C.prototype, _l, void 0); +], C.prototype, _p, void 0); __decorate([ x -], C.prototype, _m, void 0); +], C.prototype, _q, void 0); __decorate([ x -], C.prototype, _o, void 0); +], C.prototype, _r, void 0); void class D { constructor() { this["property2"] = 2; this[Symbol.iterator] = null; this["property4"] = 2; this[Symbol.match] = null; - this[_q] = null; - this[_s] = null; + this[_t] = null; + this[_v] = null; } - [(foo(), _p = foo(), _q = foo(), _r = fieldNameB, _s = fieldNameC, "some" + "method")]() { } + [(foo(), _s = foo(), _t = foo(), _u = fieldNameB, _v = fieldNameC, "some" + "method")]() { } }; class E { constructor() { @@ -306,12 +307,12 @@ class E { this[Symbol.iterator] = null; this["property4"] = 2; this[Symbol.match] = null; - this[_u] = null; - this[_w] = null; + this[_x] = null; + this[_z] = null; } - [(foo(), _t = foo(), _u = foo(), "some" + "method")]() { } + [(foo(), _w = foo(), _x = foo(), "some" + "method")]() { } } -_v = fieldNameB, _w = fieldNameC; +_y = fieldNameB, _z = fieldNameC; __decorate([ x ], E.prototype, "property", void 0); @@ -326,43 +327,43 @@ __decorate([ ], E.prototype, Symbol.iterator, void 0); __decorate([ x -], E.prototype, _t, void 0); +], E.prototype, _w, void 0); __decorate([ x -], E.prototype, _u, void 0); +], E.prototype, _x, void 0); __decorate([ x -], E.prototype, _v, void 0); +], E.prototype, _y, void 0); __decorate([ x -], E.prototype, _w, void 0); -void (_1 = class F { +], E.prototype, _z, void 0); +void (_b = class F { constructor() { this["property2"] = 2; this[Symbol.iterator] = null; this["property4"] = 2; this[Symbol.match] = null; - this[_y] = null; - this[_0] = null; + this[_1] = null; + this[_3] = null; } - [(foo(), _x = foo(), _y = foo(), "some" + "method")]() { } + [(foo(), _0 = foo(), _1 = foo(), "some" + "method")]() { } }, - _z = fieldNameB, - _0 = fieldNameC, - _1); + _2 = fieldNameB, + _3 = fieldNameC, + _b); class G { constructor() { this["property2"] = 2; this[Symbol.iterator] = null; this["property4"] = 2; this[Symbol.match] = null; - this[_3] = null; this[_5] = null; + this[_7] = null; } - [(foo(), _2 = foo(), _3 = foo(), "some" + "method")]() { } - [(_4 = fieldNameB, "some" + "method2")]() { } + [(foo(), _4 = foo(), _5 = foo(), "some" + "method")]() { } + [(_6 = fieldNameB, "some" + "method2")]() { } } -_5 = fieldNameC; +_7 = fieldNameC; __decorate([ x ], G.prototype, "property", void 0); @@ -377,43 +378,43 @@ __decorate([ ], G.prototype, Symbol.iterator, void 0); __decorate([ x -], G.prototype, _2, void 0); +], G.prototype, _4, void 0); __decorate([ x -], G.prototype, _3, void 0); +], G.prototype, _5, void 0); __decorate([ x -], G.prototype, _4, void 0); +], G.prototype, _6, void 0); __decorate([ x -], G.prototype, _5, void 0); -void (_10 = class H { +], G.prototype, _7, void 0); +void (_c = class H { constructor() { this["property2"] = 2; this[Symbol.iterator] = null; this["property4"] = 2; this[Symbol.match] = null; - this[_7] = null; this[_9] = null; + this[_11] = null; } - [(foo(), _6 = foo(), _7 = foo(), "some" + "method")]() { } - [(_8 = fieldNameB, "some" + "method2")]() { } + [(foo(), _8 = foo(), _9 = foo(), "some" + "method")]() { } + [(_10 = fieldNameB, "some" + "method2")]() { } }, - _9 = fieldNameC, - _10); + _11 = fieldNameC, + _c); class I { constructor() { this["property2"] = 2; this[Symbol.iterator] = null; this["property4"] = 2; this[Symbol.match] = null; - this[_12] = null; - this[_15] = null; + this[_13] = null; + this[_16] = null; } - [(foo(), _11 = foo(), _12 = foo(), _13 = "some" + "method")]() { } - [(_14 = fieldNameB, "some" + "method2")]() { } + [(foo(), _12 = foo(), _13 = foo(), _14 = "some" + "method")]() { } + [(_15 = fieldNameB, "some" + "method2")]() { } } -_15 = fieldNameC; +_16 = fieldNameC; __decorate([ x ], I.prototype, "property", void 0); @@ -426,32 +427,32 @@ __decorate([ __decorate([ x ], I.prototype, Symbol.iterator, void 0); -__decorate([ - x -], I.prototype, _11, void 0); __decorate([ x ], I.prototype, _12, void 0); __decorate([ x -], I.prototype, _13, null); +], I.prototype, _13, void 0); __decorate([ x -], I.prototype, _14, void 0); +], I.prototype, _14, null); __decorate([ x ], I.prototype, _15, void 0); -void (_21 = class J { +__decorate([ + x +], I.prototype, _16, void 0); +void (_d = class J { constructor() { this["property2"] = 2; this[Symbol.iterator] = null; this["property4"] = 2; this[Symbol.match] = null; - this[_17] = null; - this[_20] = null; + this[_18] = null; + this[_21] = null; } - [(foo(), _16 = foo(), _17 = foo(), _18 = "some" + "method")]() { } - [(_19 = fieldNameB, "some" + "method2")]() { } + [(foo(), _17 = foo(), _18 = foo(), _19 = "some" + "method")]() { } + [(_20 = fieldNameB, "some" + "method2")]() { } }, - _20 = fieldNameC, - _21); + _21 = fieldNameC, + _d); diff --git a/tests/baselines/reference/parseErrorInHeritageClause1.errors.txt b/tests/baselines/reference/parseErrorInHeritageClause1.errors.txt index 67564442b3abc..722004686f23c 100644 --- a/tests/baselines/reference/parseErrorInHeritageClause1.errors.txt +++ b/tests/baselines/reference/parseErrorInHeritageClause1.errors.txt @@ -3,9 +3,10 @@ tests/cases/compiler/parseErrorInHeritageClause1.ts(1,19): error TS1127: Invalid ==== tests/cases/compiler/parseErrorInHeritageClause1.ts (2 errors) ==== - class C extends A # { + class C extends A ¬ { ~ !!! error TS2304: Cannot find name 'A'. !!! error TS1127: Invalid character. - } \ No newline at end of file + } + \ No newline at end of file diff --git a/tests/baselines/reference/parseErrorInHeritageClause1.js b/tests/baselines/reference/parseErrorInHeritageClause1.js index da02ae9cf2547..8d67383860af2 100644 --- a/tests/baselines/reference/parseErrorInHeritageClause1.js +++ b/tests/baselines/reference/parseErrorInHeritageClause1.js @@ -1,6 +1,7 @@ //// [parseErrorInHeritageClause1.ts] -class C extends A # { -} +class C extends A ¬ { +} + //// [parseErrorInHeritageClause1.js] var __extends = (this && this.__extends) || (function () { diff --git a/tests/baselines/reference/parseErrorInHeritageClause1.symbols b/tests/baselines/reference/parseErrorInHeritageClause1.symbols index 5e0d3d26d38da..45d6ba5f5fac3 100644 --- a/tests/baselines/reference/parseErrorInHeritageClause1.symbols +++ b/tests/baselines/reference/parseErrorInHeritageClause1.symbols @@ -1,4 +1,5 @@ === tests/cases/compiler/parseErrorInHeritageClause1.ts === -class C extends A # { +class C extends A ¬ { >C : Symbol(C, Decl(parseErrorInHeritageClause1.ts, 0, 0)) } + diff --git a/tests/baselines/reference/parseErrorInHeritageClause1.types b/tests/baselines/reference/parseErrorInHeritageClause1.types index 53f0a622054d3..0a8c72e1f8c92 100644 --- a/tests/baselines/reference/parseErrorInHeritageClause1.types +++ b/tests/baselines/reference/parseErrorInHeritageClause1.types @@ -1,5 +1,6 @@ === tests/cases/compiler/parseErrorInHeritageClause1.ts === -class C extends A # { +class C extends A ¬ { >C : C >A : any } + diff --git a/tests/baselines/reference/parserErrorRecovery_Block2.errors.txt b/tests/baselines/reference/parserErrorRecovery_Block2.errors.txt index 53279be443f66..ff29d9389760b 100644 --- a/tests/baselines/reference/parserErrorRecovery_Block2.errors.txt +++ b/tests/baselines/reference/parserErrorRecovery_Block2.errors.txt @@ -3,8 +3,9 @@ tests/cases/conformance/parser/ecmascript5/ErrorRecovery/Blocks/parserErrorRecov ==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/Blocks/parserErrorRecovery_Block2.ts (1 errors) ==== function f() { - # + ¬ !!! error TS1127: Invalid character. return; - } \ No newline at end of file + } + \ No newline at end of file diff --git a/tests/baselines/reference/parserErrorRecovery_Block2.js b/tests/baselines/reference/parserErrorRecovery_Block2.js index 24ddaf0db3f2a..024684a9e2b03 100644 --- a/tests/baselines/reference/parserErrorRecovery_Block2.js +++ b/tests/baselines/reference/parserErrorRecovery_Block2.js @@ -1,8 +1,9 @@ //// [parserErrorRecovery_Block2.ts] function f() { - # + ¬ return; -} +} + //// [parserErrorRecovery_Block2.js] function f() { diff --git a/tests/baselines/reference/parserErrorRecovery_Block2.symbols b/tests/baselines/reference/parserErrorRecovery_Block2.symbols index 3d5a09d567ce6..ce4725e609a64 100644 --- a/tests/baselines/reference/parserErrorRecovery_Block2.symbols +++ b/tests/baselines/reference/parserErrorRecovery_Block2.symbols @@ -2,6 +2,7 @@ function f() { >f : Symbol(f, Decl(parserErrorRecovery_Block2.ts, 0, 0)) - # + ¬ return; } + diff --git a/tests/baselines/reference/parserErrorRecovery_Block2.types b/tests/baselines/reference/parserErrorRecovery_Block2.types index 9850dc1cf0ea2..0a0a0fbec23c8 100644 --- a/tests/baselines/reference/parserErrorRecovery_Block2.types +++ b/tests/baselines/reference/parserErrorRecovery_Block2.types @@ -2,6 +2,7 @@ function f() { >f : () => void - # + ¬ return; } + diff --git a/tests/baselines/reference/parserErrorRecovery_ClassElement3.errors.txt b/tests/baselines/reference/parserErrorRecovery_ClassElement3.errors.txt index 7f81c6114f6d2..52f99265d2c51 100644 --- a/tests/baselines/reference/parserErrorRecovery_ClassElement3.errors.txt +++ b/tests/baselines/reference/parserErrorRecovery_ClassElement3.errors.txt @@ -1,12 +1,12 @@ tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ClassElements/parserErrorRecovery_ClassElement3.ts(2,4): error TS1127: Invalid character. tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ClassElements/parserErrorRecovery_ClassElement3.ts(6,4): error TS1109: Expression expected. tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ClassElements/parserErrorRecovery_ClassElement3.ts(7,4): error TS1127: Invalid character. -tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ClassElements/parserErrorRecovery_ClassElement3.ts(7,5): error TS1005: '}' expected. +tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ClassElements/parserErrorRecovery_ClassElement3.ts(8,1): error TS1005: '}' expected. ==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ClassElements/parserErrorRecovery_ClassElement3.ts (4 errors) ==== module M { - # + ¬ !!! error TS1127: Invalid character. class C { @@ -15,8 +15,9 @@ tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ClassElements/parserErr enum E { ~~~~ !!! error TS1109: Expression expected. - # + ¬ !!! error TS1127: Invalid character. - + + !!! error TS1005: '}' expected. \ No newline at end of file diff --git a/tests/baselines/reference/parserErrorRecovery_ClassElement3.js b/tests/baselines/reference/parserErrorRecovery_ClassElement3.js index 36d98fa54003e..ef9afde66f7f0 100644 --- a/tests/baselines/reference/parserErrorRecovery_ClassElement3.js +++ b/tests/baselines/reference/parserErrorRecovery_ClassElement3.js @@ -1,11 +1,12 @@ //// [parserErrorRecovery_ClassElement3.ts] module M { - # + ¬ class C { } @ enum E { - # + ¬ + //// [parserErrorRecovery_ClassElement3.js] var M; diff --git a/tests/baselines/reference/parserErrorRecovery_ClassElement3.symbols b/tests/baselines/reference/parserErrorRecovery_ClassElement3.symbols index 5c1edc5b8f09f..5ea7444c974c9 100644 --- a/tests/baselines/reference/parserErrorRecovery_ClassElement3.symbols +++ b/tests/baselines/reference/parserErrorRecovery_ClassElement3.symbols @@ -2,7 +2,7 @@ module M { >M : Symbol(M, Decl(parserErrorRecovery_ClassElement3.ts, 0, 0)) - # + ¬ class C { >C : Symbol(C, Decl(parserErrorRecovery_ClassElement3.ts, 1, 4)) } @@ -10,4 +10,5 @@ module M { enum E { >E : Symbol(E, Decl(parserErrorRecovery_ClassElement3.ts, 3, 4)) - # + ¬ + diff --git a/tests/baselines/reference/parserErrorRecovery_ClassElement3.types b/tests/baselines/reference/parserErrorRecovery_ClassElement3.types index 68df4b2bbe22b..f509a0d4fb574 100644 --- a/tests/baselines/reference/parserErrorRecovery_ClassElement3.types +++ b/tests/baselines/reference/parserErrorRecovery_ClassElement3.types @@ -2,7 +2,7 @@ module M { >M : typeof M - # + ¬ class C { >C : C } @@ -11,4 +11,5 @@ module M { > : any >E : E - # + ¬ + diff --git a/tests/baselines/reference/parserErrorRecovery_ParameterList4.errors.txt b/tests/baselines/reference/parserErrorRecovery_ParameterList4.errors.txt index fa97550dd192f..9e404df184199 100644 --- a/tests/baselines/reference/parserErrorRecovery_ParameterList4.errors.txt +++ b/tests/baselines/reference/parserErrorRecovery_ParameterList4.errors.txt @@ -2,7 +2,8 @@ tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ParameterLists/parserEr ==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ParameterLists/parserErrorRecovery_ParameterList4.ts (1 errors) ==== - function f(a,#) { + function f(a,¬) { !!! error TS1127: Invalid character. - } \ No newline at end of file + } + \ No newline at end of file diff --git a/tests/baselines/reference/parserErrorRecovery_ParameterList4.js b/tests/baselines/reference/parserErrorRecovery_ParameterList4.js index 53775cad92ea3..1a1a124eb493d 100644 --- a/tests/baselines/reference/parserErrorRecovery_ParameterList4.js +++ b/tests/baselines/reference/parserErrorRecovery_ParameterList4.js @@ -1,6 +1,7 @@ //// [parserErrorRecovery_ParameterList4.ts] -function f(a,#) { -} +function f(a,¬) { +} + //// [parserErrorRecovery_ParameterList4.js] function f(a) { diff --git a/tests/baselines/reference/parserErrorRecovery_ParameterList4.symbols b/tests/baselines/reference/parserErrorRecovery_ParameterList4.symbols index df48ebfe04dec..7c433c8c3b461 100644 --- a/tests/baselines/reference/parserErrorRecovery_ParameterList4.symbols +++ b/tests/baselines/reference/parserErrorRecovery_ParameterList4.symbols @@ -1,5 +1,6 @@ === tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ParameterLists/parserErrorRecovery_ParameterList4.ts === -function f(a,#) { +function f(a,¬) { >f : Symbol(f, Decl(parserErrorRecovery_ParameterList4.ts, 0, 0)) >a : Symbol(a, Decl(parserErrorRecovery_ParameterList4.ts, 0, 11)) } + diff --git a/tests/baselines/reference/parserErrorRecovery_ParameterList4.types b/tests/baselines/reference/parserErrorRecovery_ParameterList4.types index 77b105f1d4cef..093d99193d21f 100644 --- a/tests/baselines/reference/parserErrorRecovery_ParameterList4.types +++ b/tests/baselines/reference/parserErrorRecovery_ParameterList4.types @@ -1,5 +1,6 @@ === tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ParameterLists/parserErrorRecovery_ParameterList4.ts === -function f(a,#) { +function f(a,¬) { >f : (a: any) => void >a : any } + diff --git a/tests/baselines/reference/parserSkippedTokens16.errors.txt b/tests/baselines/reference/parserSkippedTokens16.errors.txt index c35e013a22852..d27faccd2c9e7 100644 --- a/tests/baselines/reference/parserSkippedTokens16.errors.txt +++ b/tests/baselines/reference/parserSkippedTokens16.errors.txt @@ -19,7 +19,7 @@ tests/cases/conformance/parser/ecmascript5/SkippedTokens/parserSkippedTokens16.t !!! error TS2304: Cannot find name 'Bar'. ~ !!! error TS1005: ';' expected. - function Foo () # { } + function Foo () ¬ { } !!! error TS1127: Invalid character. 4+:5 @@ -33,4 +33,5 @@ tests/cases/conformance/parser/ecmascript5/SkippedTokens/parserSkippedTokens16.t } var x = -!!! error TS1109: Expression expected. \ No newline at end of file +!!! error TS1109: Expression expected. + \ No newline at end of file diff --git a/tests/baselines/reference/parserSkippedTokens16.js b/tests/baselines/reference/parserSkippedTokens16.js index 2c3a9be876df5..cf5b8c55ecc8a 100644 --- a/tests/baselines/reference/parserSkippedTokens16.js +++ b/tests/baselines/reference/parserSkippedTokens16.js @@ -1,12 +1,13 @@ //// [parserSkippedTokens16.ts] foo(): Bar { } -function Foo () # { } +function Foo () ¬ { } 4+:5 module M { function a( : T) { } } -var x = +var x = + //// [parserSkippedTokens16.js] foo(); diff --git a/tests/baselines/reference/parserSkippedTokens16.symbols b/tests/baselines/reference/parserSkippedTokens16.symbols index 213dc9965f98f..576a1dfd97d8d 100644 --- a/tests/baselines/reference/parserSkippedTokens16.symbols +++ b/tests/baselines/reference/parserSkippedTokens16.symbols @@ -1,6 +1,6 @@ === tests/cases/conformance/parser/ecmascript5/SkippedTokens/parserSkippedTokens16.ts === foo(): Bar { } -function Foo () # { } +function Foo () ¬ { } >Foo : Symbol(Foo, Decl(parserSkippedTokens16.ts, 0, 14)) 4+:5 diff --git a/tests/baselines/reference/parserSkippedTokens16.types b/tests/baselines/reference/parserSkippedTokens16.types index b9c24cfafbaf0..cb62505802fe9 100644 --- a/tests/baselines/reference/parserSkippedTokens16.types +++ b/tests/baselines/reference/parserSkippedTokens16.types @@ -4,7 +4,7 @@ foo(): Bar { } >foo : any >Bar : any -function Foo () # { } +function Foo () ¬ { } >Foo : () => any 4+:5 @@ -24,5 +24,6 @@ function a( } var x = >x : any + > : any diff --git a/tests/baselines/reference/privateNameAndIndexSignature.errors.txt b/tests/baselines/reference/privateNameAndIndexSignature.errors.txt new file mode 100644 index 0000000000000..cbe22ffb7c156 --- /dev/null +++ b/tests/baselines/reference/privateNameAndIndexSignature.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts(6,14): error TS2339: Property '#f' does not exist on type 'A'. + + +==== tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts (1 errors) ==== + // @target es6 + + class A { + [k: string]: any; + constructor(message: string) { + this.#f = 3 // Error Property '#f' does not exist on type 'A'. + ~~ +!!! error TS2339: Property '#f' does not exist on type 'A'. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/privateNameAndIndexSignature.js b/tests/baselines/reference/privateNameAndIndexSignature.js new file mode 100644 index 0000000000000..561a0ce1210b3 --- /dev/null +++ b/tests/baselines/reference/privateNameAndIndexSignature.js @@ -0,0 +1,20 @@ +//// [privateNameAndIndexSignature.ts] +// @target es6 + +class A { + [k: string]: any; + constructor(message: string) { + this.#f = 3 // Error Property '#f' does not exist on type 'A'. + } +} + + +//// [privateNameAndIndexSignature.js] +"use strict"; +// @target es6 +var A = /** @class */ (function () { + function A(message) { + this.#f = 3; // Error Property '#f' does not exist on type 'A'. + } + return A; +}()); diff --git a/tests/baselines/reference/privateNameAndIndexSignature.symbols b/tests/baselines/reference/privateNameAndIndexSignature.symbols new file mode 100644 index 0000000000000..609eb3a491779 --- /dev/null +++ b/tests/baselines/reference/privateNameAndIndexSignature.symbols @@ -0,0 +1,17 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNameAndIndexSignature.ts, 0, 0)) + + [k: string]: any; +>k : Symbol(k, Decl(privateNameAndIndexSignature.ts, 3, 5)) + + constructor(message: string) { +>message : Symbol(message, Decl(privateNameAndIndexSignature.ts, 4, 16)) + + this.#f = 3 // Error Property '#f' does not exist on type 'A'. +>this : Symbol(A, Decl(privateNameAndIndexSignature.ts, 0, 0)) + } +} + diff --git a/tests/baselines/reference/privateNameAndIndexSignature.types b/tests/baselines/reference/privateNameAndIndexSignature.types new file mode 100644 index 0000000000000..47015a920bb28 --- /dev/null +++ b/tests/baselines/reference/privateNameAndIndexSignature.types @@ -0,0 +1,20 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts === +// @target es6 + +class A { +>A : A + + [k: string]: any; +>k : string + + constructor(message: string) { +>message : string + + this.#f = 3 // Error Property '#f' does not exist on type 'A'. +>this.#f = 3 : 3 +>this.#f : any +>this : this +>3 : 3 + } +} + diff --git a/tests/baselines/reference/privateNameConstructorReserved.errors.txt b/tests/baselines/reference/privateNameConstructorReserved.errors.txt new file mode 100644 index 0000000000000..ef48440e250a1 --- /dev/null +++ b/tests/baselines/reference/privateNameConstructorReserved.errors.txt @@ -0,0 +1,12 @@ +tests/cases/conformance/classes/members/privateNames/privateNameConstructorReserved.ts(4,5): error TS18006: '#constructor' is a reserved word. + + +==== tests/cases/conformance/classes/members/privateNames/privateNameConstructorReserved.ts (1 errors) ==== + // @target es6 + + class A { + #constructor() {} // Error: `#constructor` is a reserved word. + ~~~~~~~~~~~~ +!!! error TS18006: '#constructor' is a reserved word. + } + \ No newline at end of file diff --git a/tests/baselines/reference/privateNameConstructorReserved.js b/tests/baselines/reference/privateNameConstructorReserved.js new file mode 100644 index 0000000000000..61585bd4eb127 --- /dev/null +++ b/tests/baselines/reference/privateNameConstructorReserved.js @@ -0,0 +1,16 @@ +//// [privateNameConstructorReserved.ts] +// @target es6 + +class A { + #constructor() {} // Error: `#constructor` is a reserved word. +} + + +//// [privateNameConstructorReserved.js] +// @target es6 +var A = /** @class */ (function () { + function A() { + } + A.prototype.#constructor = function () { }; // Error: `#constructor` is a reserved word. + return A; +}()); diff --git a/tests/baselines/reference/privateNameConstructorReserved.symbols b/tests/baselines/reference/privateNameConstructorReserved.symbols new file mode 100644 index 0000000000000..3f3cbc722039f --- /dev/null +++ b/tests/baselines/reference/privateNameConstructorReserved.symbols @@ -0,0 +1,10 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameConstructorReserved.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNameConstructorReserved.ts, 0, 0)) + + #constructor() {} // Error: `#constructor` is a reserved word. +>#constructor : Symbol(A.#constructor, Decl(privateNameConstructorReserved.ts, 2, 9)) +} + diff --git a/tests/baselines/reference/privateNameConstructorReserved.types b/tests/baselines/reference/privateNameConstructorReserved.types new file mode 100644 index 0000000000000..2b75281b7a02e --- /dev/null +++ b/tests/baselines/reference/privateNameConstructorReserved.types @@ -0,0 +1,10 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameConstructorReserved.ts === +// @target es6 + +class A { +>A : A + + #constructor() {} // Error: `#constructor` is a reserved word. +>#constructor : () => void +} + diff --git a/tests/baselines/reference/privateNameDeclaration.js b/tests/baselines/reference/privateNameDeclaration.js new file mode 100644 index 0000000000000..ee7ec86c7b612 --- /dev/null +++ b/tests/baselines/reference/privateNameDeclaration.js @@ -0,0 +1,15 @@ +//// [privateNameDeclaration.ts] +class A { + #name: string; +} + + +//// [privateNameDeclaration.js] +var _name; +var A = /** @class */ (function () { + function A() { + _name.set(this, void 0); + } + return A; +}()); +_name = new WeakMap(); diff --git a/tests/baselines/reference/privateNameDeclaration.symbols b/tests/baselines/reference/privateNameDeclaration.symbols new file mode 100644 index 0000000000000..e34d275f72e67 --- /dev/null +++ b/tests/baselines/reference/privateNameDeclaration.symbols @@ -0,0 +1,8 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameDeclaration.ts === +class A { +>A : Symbol(A, Decl(privateNameDeclaration.ts, 0, 0)) + + #name: string; +>#name : Symbol(A.#name, Decl(privateNameDeclaration.ts, 0, 9)) +} + diff --git a/tests/baselines/reference/privateNameDeclaration.types b/tests/baselines/reference/privateNameDeclaration.types new file mode 100644 index 0000000000000..6de7c4f331104 --- /dev/null +++ b/tests/baselines/reference/privateNameDeclaration.types @@ -0,0 +1,8 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameDeclaration.ts === +class A { +>A : A + + #name: string; +>#name : string +} + diff --git a/tests/baselines/reference/privateNameDuplicateField.errors.txt b/tests/baselines/reference/privateNameDuplicateField.errors.txt new file mode 100644 index 0000000000000..4a8428c6102c2 --- /dev/null +++ b/tests/baselines/reference/privateNameDuplicateField.errors.txt @@ -0,0 +1,13 @@ +tests/cases/conformance/classes/members/privateNames/privateNameDuplicateField.ts(5,5): error TS2300: Duplicate identifier '#foo'. + + +==== tests/cases/conformance/classes/members/privateNames/privateNameDuplicateField.ts (1 errors) ==== + // @target es6 + + class A { + #foo = "foo"; + #foo = "foo"; + ~~~~ +!!! error TS2300: Duplicate identifier '#foo'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/privateNameDuplicateField.js b/tests/baselines/reference/privateNameDuplicateField.js new file mode 100644 index 0000000000000..6ece4be8f032a --- /dev/null +++ b/tests/baselines/reference/privateNameDuplicateField.js @@ -0,0 +1,21 @@ +//// [privateNameDuplicateField.ts] +// @target es6 + +class A { + #foo = "foo"; + #foo = "foo"; +} + + +//// [privateNameDuplicateField.js] +// @target es6 +var _foo, _foo_1; +"use strict"; +var A = /** @class */ (function () { + function A() { + _foo_1.set(this, "foo"); + _foo_1.set(this, "foo"); + } + return A; +}()); +_foo = new WeakMap(), _foo_1 = new WeakMap(); diff --git a/tests/baselines/reference/privateNameDuplicateField.symbols b/tests/baselines/reference/privateNameDuplicateField.symbols new file mode 100644 index 0000000000000..0da02e645ada3 --- /dev/null +++ b/tests/baselines/reference/privateNameDuplicateField.symbols @@ -0,0 +1,13 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameDuplicateField.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNameDuplicateField.ts, 0, 0)) + + #foo = "foo"; +>#foo : Symbol(A.#foo, Decl(privateNameDuplicateField.ts, 2, 9), Decl(privateNameDuplicateField.ts, 3, 17)) + + #foo = "foo"; +>#foo : Symbol(A.#foo, Decl(privateNameDuplicateField.ts, 2, 9), Decl(privateNameDuplicateField.ts, 3, 17)) +} + diff --git a/tests/baselines/reference/privateNameDuplicateField.types b/tests/baselines/reference/privateNameDuplicateField.types new file mode 100644 index 0000000000000..e73152ebd4455 --- /dev/null +++ b/tests/baselines/reference/privateNameDuplicateField.types @@ -0,0 +1,15 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameDuplicateField.ts === +// @target es6 + +class A { +>A : A + + #foo = "foo"; +>#foo : string +>"foo" : "foo" + + #foo = "foo"; +>#foo : string +>"foo" : "foo" +} + diff --git a/tests/baselines/reference/privateNameField.js b/tests/baselines/reference/privateNameField.js new file mode 100644 index 0000000000000..57446748cb668 --- /dev/null +++ b/tests/baselines/reference/privateNameField.js @@ -0,0 +1,23 @@ +//// [privateNameField.ts] +// @target es6 + +class A { + #name: string; + constructor(name: string) { + this.#name = name; + } +} + +//// [privateNameField.js] +// @target es6 +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +var _name; +"use strict"; +var A = /** @class */ (function () { + function A(name) { + _name.set(this, void 0); + _classPrivateFieldSet(this, _name, name); + } + return A; +}()); +_name = new WeakMap(); diff --git a/tests/baselines/reference/privateNameField.symbols b/tests/baselines/reference/privateNameField.symbols new file mode 100644 index 0000000000000..c37ded65bd1a7 --- /dev/null +++ b/tests/baselines/reference/privateNameField.symbols @@ -0,0 +1,18 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameField.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNameField.ts, 0, 0)) + + #name: string; +>#name : Symbol(A.#name, Decl(privateNameField.ts, 2, 9)) + + constructor(name: string) { +>name : Symbol(name, Decl(privateNameField.ts, 4, 16)) + + this.#name = name; +>this.#name : Symbol(A.#name, Decl(privateNameField.ts, 2, 9)) +>this : Symbol(A, Decl(privateNameField.ts, 0, 0)) +>name : Symbol(name, Decl(privateNameField.ts, 4, 16)) + } +} diff --git a/tests/baselines/reference/privateNameField.types b/tests/baselines/reference/privateNameField.types new file mode 100644 index 0000000000000..db7dba04475e8 --- /dev/null +++ b/tests/baselines/reference/privateNameField.types @@ -0,0 +1,19 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameField.ts === +// @target es6 + +class A { +>A : A + + #name: string; +>#name : string + + constructor(name: string) { +>name : string + + this.#name = name; +>this.#name = name : string +>this.#name : string +>this : this +>name : string + } +} diff --git a/tests/baselines/reference/privateNameFieldAccess.js b/tests/baselines/reference/privateNameFieldAccess.js new file mode 100644 index 0000000000000..2f64fc96515fa --- /dev/null +++ b/tests/baselines/reference/privateNameFieldAccess.js @@ -0,0 +1,20 @@ +//// [privateNameFieldAccess.ts] +class A { + #myField = "hello world"; + constructor() { + console.log(this.#myField); + } +} + + +//// [privateNameFieldAccess.js] +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _myField; +var A = /** @class */ (function () { + function A() { + _myField.set(this, "hello world"); + console.log(_classPrivateFieldGet(this, _myField)); + } + return A; +}()); +_myField = new WeakMap(); diff --git a/tests/baselines/reference/privateNameFieldAccess.symbols b/tests/baselines/reference/privateNameFieldAccess.symbols new file mode 100644 index 0000000000000..d69eacd7131f9 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldAccess.symbols @@ -0,0 +1,17 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldAccess.ts === +class A { +>A : Symbol(A, Decl(privateNameFieldAccess.ts, 0, 0)) + + #myField = "hello world"; +>#myField : Symbol(A.#myField, Decl(privateNameFieldAccess.ts, 0, 9)) + + constructor() { + console.log(this.#myField); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>this.#myField : Symbol(A.#myField, Decl(privateNameFieldAccess.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAccess.ts, 0, 0)) + } +} + diff --git a/tests/baselines/reference/privateNameFieldAccess.types b/tests/baselines/reference/privateNameFieldAccess.types new file mode 100644 index 0000000000000..17568587e311d --- /dev/null +++ b/tests/baselines/reference/privateNameFieldAccess.types @@ -0,0 +1,19 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldAccess.ts === +class A { +>A : A + + #myField = "hello world"; +>#myField : string +>"hello world" : "hello world" + + constructor() { + console.log(this.#myField); +>console.log(this.#myField) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>this.#myField : string +>this : this + } +} + diff --git a/tests/baselines/reference/privateNameFieldAssignment.js b/tests/baselines/reference/privateNameFieldAssignment.js new file mode 100644 index 0000000000000..34040558f1f42 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldAssignment.js @@ -0,0 +1,78 @@ +//// [privateNameFieldAssignment.ts] +class A { + #field = 0; + constructor() { + this.#field = 1; + this.#field += 2; + this.#field -= 3; + this.#field /= 4; + this.#field *= 5; + this.#field **= 6; + this.#field %= 7; + this.#field <<= 8; + this.#field >>= 9; + this.#field >>>= 10; + this.#field &= 11; + this.#field |= 12; + this.#field ^= 13; + A.getInstance().#field = 1; + A.getInstance().#field += 2; + A.getInstance().#field -= 3; + A.getInstance().#field /= 4; + A.getInstance().#field *= 5; + A.getInstance().#field **= 6; + A.getInstance().#field %= 7; + A.getInstance().#field <<= 8; + A.getInstance().#field >>= 9; + A.getInstance().#field >>>= 10; + A.getInstance().#field &= 11; + A.getInstance().#field |= 12; + A.getInstance().#field ^= 13; + } + static getInstance() { + return new A(); + } +} + + +//// [privateNameFieldAssignment.js] +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _field; +var A = /** @class */ (function () { + function A() { + _field.set(this, 0); + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m; + _classPrivateFieldSet(this, _field, 1); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) + 2); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) - 3); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) / 4); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) * 5); + _classPrivateFieldSet(this, _field, Math.pow(_classPrivateFieldGet(this, _field), 6)); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) % 7); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) << 8); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) >> 9); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) >>> 10); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) & 11); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) | 12); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) ^ 13); + _classPrivateFieldSet(A.getInstance(), _field, 1); + _classPrivateFieldSet(_a = A.getInstance(), _field, _classPrivateFieldGet(_a, _field) + 2); + _classPrivateFieldSet(_b = A.getInstance(), _field, _classPrivateFieldGet(_b, _field) - 3); + _classPrivateFieldSet(_c = A.getInstance(), _field, _classPrivateFieldGet(_c, _field) / 4); + _classPrivateFieldSet(_d = A.getInstance(), _field, _classPrivateFieldGet(_d, _field) * 5); + _classPrivateFieldSet(_e = A.getInstance(), _field, Math.pow(_classPrivateFieldGet(_e, _field), 6)); + _classPrivateFieldSet(_f = A.getInstance(), _field, _classPrivateFieldGet(_f, _field) % 7); + _classPrivateFieldSet(_g = A.getInstance(), _field, _classPrivateFieldGet(_g, _field) << 8); + _classPrivateFieldSet(_h = A.getInstance(), _field, _classPrivateFieldGet(_h, _field) >> 9); + _classPrivateFieldSet(_j = A.getInstance(), _field, _classPrivateFieldGet(_j, _field) >>> 10); + _classPrivateFieldSet(_k = A.getInstance(), _field, _classPrivateFieldGet(_k, _field) & 11); + _classPrivateFieldSet(_l = A.getInstance(), _field, _classPrivateFieldGet(_l, _field) | 12); + _classPrivateFieldSet(_m = A.getInstance(), _field, _classPrivateFieldGet(_m, _field) ^ 13); + } + A.getInstance = function () { + return new A(); + }; + return A; +}()); +_field = new WeakMap(); diff --git a/tests/baselines/reference/privateNameFieldAssignment.symbols b/tests/baselines/reference/privateNameFieldAssignment.symbols new file mode 100644 index 0000000000000..3f08ea141f07f --- /dev/null +++ b/tests/baselines/reference/privateNameFieldAssignment.symbols @@ -0,0 +1,146 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldAssignment.ts === +class A { +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + #field = 0; +>#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) + + constructor() { + this.#field = 1; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field += 2; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field -= 3; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field /= 4; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field *= 5; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field **= 6; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field %= 7; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field <<= 8; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field >>= 9; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field >>>= 10; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field &= 11; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field |= 12; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field ^= 13; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + A.getInstance().#field = 1; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field += 2; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field -= 3; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field /= 4; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field *= 5; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field **= 6; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field %= 7; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field <<= 8; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field >>= 9; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field >>>= 10; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field &= 11; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field |= 12; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field ^= 13; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + } + static getInstance() { +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + return new A(); +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + } +} + diff --git a/tests/baselines/reference/privateNameFieldAssignment.types b/tests/baselines/reference/privateNameFieldAssignment.types new file mode 100644 index 0000000000000..8a3c507c393f0 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldAssignment.types @@ -0,0 +1,213 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldAssignment.ts === +class A { +>A : A + + #field = 0; +>#field : number +>0 : 0 + + constructor() { + this.#field = 1; +>this.#field = 1 : 1 +>this.#field : number +>this : this +>1 : 1 + + this.#field += 2; +>this.#field += 2 : number +>this.#field : number +>this : this +>2 : 2 + + this.#field -= 3; +>this.#field -= 3 : number +>this.#field : number +>this : this +>3 : 3 + + this.#field /= 4; +>this.#field /= 4 : number +>this.#field : number +>this : this +>4 : 4 + + this.#field *= 5; +>this.#field *= 5 : number +>this.#field : number +>this : this +>5 : 5 + + this.#field **= 6; +>this.#field **= 6 : number +>this.#field : number +>this : this +>6 : 6 + + this.#field %= 7; +>this.#field %= 7 : number +>this.#field : number +>this : this +>7 : 7 + + this.#field <<= 8; +>this.#field <<= 8 : number +>this.#field : number +>this : this +>8 : 8 + + this.#field >>= 9; +>this.#field >>= 9 : number +>this.#field : number +>this : this +>9 : 9 + + this.#field >>>= 10; +>this.#field >>>= 10 : number +>this.#field : number +>this : this +>10 : 10 + + this.#field &= 11; +>this.#field &= 11 : number +>this.#field : number +>this : this +>11 : 11 + + this.#field |= 12; +>this.#field |= 12 : number +>this.#field : number +>this : this +>12 : 12 + + this.#field ^= 13; +>this.#field ^= 13 : number +>this.#field : number +>this : this +>13 : 13 + + A.getInstance().#field = 1; +>A.getInstance().#field = 1 : 1 +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>1 : 1 + + A.getInstance().#field += 2; +>A.getInstance().#field += 2 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>2 : 2 + + A.getInstance().#field -= 3; +>A.getInstance().#field -= 3 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>3 : 3 + + A.getInstance().#field /= 4; +>A.getInstance().#field /= 4 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>4 : 4 + + A.getInstance().#field *= 5; +>A.getInstance().#field *= 5 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>5 : 5 + + A.getInstance().#field **= 6; +>A.getInstance().#field **= 6 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>6 : 6 + + A.getInstance().#field %= 7; +>A.getInstance().#field %= 7 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>7 : 7 + + A.getInstance().#field <<= 8; +>A.getInstance().#field <<= 8 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>8 : 8 + + A.getInstance().#field >>= 9; +>A.getInstance().#field >>= 9 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>9 : 9 + + A.getInstance().#field >>>= 10; +>A.getInstance().#field >>>= 10 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>10 : 10 + + A.getInstance().#field &= 11; +>A.getInstance().#field &= 11 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>11 : 11 + + A.getInstance().#field |= 12; +>A.getInstance().#field |= 12 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>12 : 12 + + A.getInstance().#field ^= 13; +>A.getInstance().#field ^= 13 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>13 : 13 + } + static getInstance() { +>getInstance : () => A + + return new A(); +>new A() : A +>A : typeof A + } +} + diff --git a/tests/baselines/reference/privateNameFieldCallExpression.js b/tests/baselines/reference/privateNameFieldCallExpression.js new file mode 100644 index 0000000000000..b1b1260faee53 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldCallExpression.js @@ -0,0 +1,29 @@ +//// [privateNameFieldCallExpression.ts] +class A { + #fieldFunc = () => this.x = 10; + x = 1; + test() { + this.#fieldFunc(); + const func = this.#fieldFunc; + func(); + } +} + + +//// [privateNameFieldCallExpression.js] +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _fieldFunc; +var A = /** @class */ (function () { + function A() { + var _this = this; + _fieldFunc.set(this, function () { return _this.x = 10; }); + this.x = 1; + } + A.prototype.test = function () { + _classPrivateFieldGet(this, _fieldFunc).call(this); + var func = _classPrivateFieldGet(this, _fieldFunc); + func(); + }; + return A; +}()); +_fieldFunc = new WeakMap(); diff --git a/tests/baselines/reference/privateNameFieldCallExpression.symbols b/tests/baselines/reference/privateNameFieldCallExpression.symbols new file mode 100644 index 0000000000000..692141acb9878 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldCallExpression.symbols @@ -0,0 +1,30 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldCallExpression.ts === +class A { +>A : Symbol(A, Decl(privateNameFieldCallExpression.ts, 0, 0)) + + #fieldFunc = () => this.x = 10; +>#fieldFunc : Symbol(A.#fieldFunc, Decl(privateNameFieldCallExpression.ts, 0, 9)) +>this.x : Symbol(A.x, Decl(privateNameFieldCallExpression.ts, 1, 35)) +>this : Symbol(A, Decl(privateNameFieldCallExpression.ts, 0, 0)) +>x : Symbol(A.x, Decl(privateNameFieldCallExpression.ts, 1, 35)) + + x = 1; +>x : Symbol(A.x, Decl(privateNameFieldCallExpression.ts, 1, 35)) + + test() { +>test : Symbol(A.test, Decl(privateNameFieldCallExpression.ts, 2, 10)) + + this.#fieldFunc(); +>this.#fieldFunc : Symbol(A.#fieldFunc, Decl(privateNameFieldCallExpression.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldCallExpression.ts, 0, 0)) + + const func = this.#fieldFunc; +>func : Symbol(func, Decl(privateNameFieldCallExpression.ts, 5, 13)) +>this.#fieldFunc : Symbol(A.#fieldFunc, Decl(privateNameFieldCallExpression.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldCallExpression.ts, 0, 0)) + + func(); +>func : Symbol(func, Decl(privateNameFieldCallExpression.ts, 5, 13)) + } +} + diff --git a/tests/baselines/reference/privateNameFieldCallExpression.types b/tests/baselines/reference/privateNameFieldCallExpression.types new file mode 100644 index 0000000000000..e9d12b0d1741c --- /dev/null +++ b/tests/baselines/reference/privateNameFieldCallExpression.types @@ -0,0 +1,36 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldCallExpression.ts === +class A { +>A : A + + #fieldFunc = () => this.x = 10; +>#fieldFunc : () => number +>() => this.x = 10 : () => number +>this.x = 10 : 10 +>this.x : number +>this : this +>x : number +>10 : 10 + + x = 1; +>x : number +>1 : 1 + + test() { +>test : () => void + + this.#fieldFunc(); +>this.#fieldFunc() : number +>this.#fieldFunc : () => number +>this : this + + const func = this.#fieldFunc; +>func : () => number +>this.#fieldFunc : () => number +>this : this + + func(); +>func() : number +>func : () => number + } +} + diff --git a/tests/baselines/reference/privateNameFieldDestructuredBinding.js b/tests/baselines/reference/privateNameFieldDestructuredBinding.js new file mode 100644 index 0000000000000..dadf60bab9d08 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldDestructuredBinding.js @@ -0,0 +1,37 @@ +//// [privateNameFieldDestructuredBinding.ts] +class A { + #field = 1; + testObject() { + return { x: 10, y: 6 }; + } + testArray() { + return [10, 11]; + } + constructor() { + let y: number; + ({ x: this.#field, y } = this.testObject()); + ([this.#field, y] = this.testArray()); + } +} + + +//// [privateNameFieldDestructuredBinding.js] +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +var _field; +var A = /** @class */ (function () { + function A() { + var _a, _b; + _field.set(this, 1); + var y; + (_a = this.testObject(), { set value(x) { _classPrivateFieldSet(this, _field, x); } }.value = _a.x, y = _a.y); + (_b = this.testArray(), { set value(x) { _classPrivateFieldSet(this, _field, x); } }.value = _b[0], y = _b[1]); + } + A.prototype.testObject = function () { + return { x: 10, y: 6 }; + }; + A.prototype.testArray = function () { + return [10, 11]; + }; + return A; +}()); +_field = new WeakMap(); diff --git a/tests/baselines/reference/privateNameFieldDestructuredBinding.symbols b/tests/baselines/reference/privateNameFieldDestructuredBinding.symbols new file mode 100644 index 0000000000000..efa03587dfc98 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldDestructuredBinding.symbols @@ -0,0 +1,42 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldDestructuredBinding.ts === +class A { +>A : Symbol(A, Decl(privateNameFieldDestructuredBinding.ts, 0, 0)) + + #field = 1; +>#field : Symbol(A.#field, Decl(privateNameFieldDestructuredBinding.ts, 0, 9)) + + testObject() { +>testObject : Symbol(A.testObject, Decl(privateNameFieldDestructuredBinding.ts, 1, 15)) + + return { x: 10, y: 6 }; +>x : Symbol(x, Decl(privateNameFieldDestructuredBinding.ts, 3, 16)) +>y : Symbol(y, Decl(privateNameFieldDestructuredBinding.ts, 3, 23)) + } + testArray() { +>testArray : Symbol(A.testArray, Decl(privateNameFieldDestructuredBinding.ts, 4, 5)) + + return [10, 11]; + } + constructor() { + let y: number; +>y : Symbol(y, Decl(privateNameFieldDestructuredBinding.ts, 9, 11)) + + ({ x: this.#field, y } = this.testObject()); +>x : Symbol(x, Decl(privateNameFieldDestructuredBinding.ts, 10, 10)) +>this.#field : Symbol(A.#field, Decl(privateNameFieldDestructuredBinding.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldDestructuredBinding.ts, 0, 0)) +>y : Symbol(y, Decl(privateNameFieldDestructuredBinding.ts, 10, 26)) +>this.testObject : Symbol(A.testObject, Decl(privateNameFieldDestructuredBinding.ts, 1, 15)) +>this : Symbol(A, Decl(privateNameFieldDestructuredBinding.ts, 0, 0)) +>testObject : Symbol(A.testObject, Decl(privateNameFieldDestructuredBinding.ts, 1, 15)) + + ([this.#field, y] = this.testArray()); +>this.#field : Symbol(A.#field, Decl(privateNameFieldDestructuredBinding.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldDestructuredBinding.ts, 0, 0)) +>y : Symbol(y, Decl(privateNameFieldDestructuredBinding.ts, 9, 11)) +>this.testArray : Symbol(A.testArray, Decl(privateNameFieldDestructuredBinding.ts, 4, 5)) +>this : Symbol(A, Decl(privateNameFieldDestructuredBinding.ts, 0, 0)) +>testArray : Symbol(A.testArray, Decl(privateNameFieldDestructuredBinding.ts, 4, 5)) + } +} + diff --git a/tests/baselines/reference/privateNameFieldDestructuredBinding.types b/tests/baselines/reference/privateNameFieldDestructuredBinding.types new file mode 100644 index 0000000000000..b948b04e66cd7 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldDestructuredBinding.types @@ -0,0 +1,57 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldDestructuredBinding.ts === +class A { +>A : A + + #field = 1; +>#field : number +>1 : 1 + + testObject() { +>testObject : () => { x: number; y: number; } + + return { x: 10, y: 6 }; +>{ x: 10, y: 6 } : { x: number; y: number; } +>x : number +>10 : 10 +>y : number +>6 : 6 + } + testArray() { +>testArray : () => number[] + + return [10, 11]; +>[10, 11] : number[] +>10 : 10 +>11 : 11 + } + constructor() { + let y: number; +>y : number + + ({ x: this.#field, y } = this.testObject()); +>({ x: this.#field, y } = this.testObject()) : { x: number; y: number; } +>{ x: this.#field, y } = this.testObject() : { x: number; y: number; } +>{ x: this.#field, y } : { x: number; y: number; } +>x : number +>this.#field : number +>this : this +>y : number +>this.testObject() : { x: number; y: number; } +>this.testObject : () => { x: number; y: number; } +>this : this +>testObject : () => { x: number; y: number; } + + ([this.#field, y] = this.testArray()); +>([this.#field, y] = this.testArray()) : number[] +>[this.#field, y] = this.testArray() : number[] +>[this.#field, y] : [number, number] +>this.#field : number +>this : this +>y : number +>this.testArray() : number[] +>this.testArray : () => number[] +>this : this +>testArray : () => number[] + } +} + diff --git a/tests/baselines/reference/privateNameFieldInitializer.js b/tests/baselines/reference/privateNameFieldInitializer.js new file mode 100644 index 0000000000000..8f40b98bb096e --- /dev/null +++ b/tests/baselines/reference/privateNameFieldInitializer.js @@ -0,0 +1,17 @@ +//// [privateNameFieldInitializer.ts] +class A { + #field = 10; + #uninitialized; +} + + +//// [privateNameFieldInitializer.js] +var _field, _uninitialized; +var A = /** @class */ (function () { + function A() { + _field.set(this, 10); + _uninitialized.set(this, void 0); + } + return A; +}()); +_field = new WeakMap(), _uninitialized = new WeakMap(); diff --git a/tests/baselines/reference/privateNameFieldInitializer.symbols b/tests/baselines/reference/privateNameFieldInitializer.symbols new file mode 100644 index 0000000000000..015a4f9ef4aa1 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldInitializer.symbols @@ -0,0 +1,11 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldInitializer.ts === +class A { +>A : Symbol(A, Decl(privateNameFieldInitializer.ts, 0, 0)) + + #field = 10; +>#field : Symbol(A.#field, Decl(privateNameFieldInitializer.ts, 0, 9)) + + #uninitialized; +>#uninitialized : Symbol(A.#uninitialized, Decl(privateNameFieldInitializer.ts, 1, 16)) +} + diff --git a/tests/baselines/reference/privateNameFieldInitializer.types b/tests/baselines/reference/privateNameFieldInitializer.types new file mode 100644 index 0000000000000..e6e701777c80c --- /dev/null +++ b/tests/baselines/reference/privateNameFieldInitializer.types @@ -0,0 +1,12 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldInitializer.ts === +class A { +>A : A + + #field = 10; +>#field : number +>10 : 10 + + #uninitialized; +>#uninitialized : any +} + diff --git a/tests/baselines/reference/privateNameFieldUnaryMutation.js b/tests/baselines/reference/privateNameFieldUnaryMutation.js new file mode 100644 index 0000000000000..e3fb0956b41dd --- /dev/null +++ b/tests/baselines/reference/privateNameFieldUnaryMutation.js @@ -0,0 +1,43 @@ +//// [privateNameFieldUnaryMutation.ts] +class C { + #test: number = 24; + constructor() { + this.#test++; + this.#test--; + ++this.#test; + --this.#test; + } + test() { + this.getInstance().#test++; + this.getInstance().#test--; + ++this.getInstance().#test; + --this.getInstance().#test; + } + getInstance() { return new C(); } +} + + +//// [privateNameFieldUnaryMutation.js] +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +var _test; +var C = /** @class */ (function () { + function C() { + _test.set(this, 24); + var _a, _b; + _a = _classPrivateFieldGet(this, _test), _classPrivateFieldSet(this, _test, _a + 1), _a; + _b = _classPrivateFieldGet(this, _test), _classPrivateFieldSet(this, _test, _b - 1), _b; + _classPrivateFieldSet(this, _test, _classPrivateFieldGet(this, _test) + 1); + _classPrivateFieldSet(this, _test, _classPrivateFieldGet(this, _test) - 1); + } + C.prototype.test = function () { + var _a, _b, _c, _d, _e, _f; + _a = this.getInstance(), _b = _classPrivateFieldGet(_a, _test), _classPrivateFieldSet(_a, _test, _b + 1), _b; + _c = this.getInstance(), _d = _classPrivateFieldGet(_c, _test), _classPrivateFieldSet(_c, _test, _d - 1), _d; + _classPrivateFieldSet(_e = this.getInstance(), _test, _classPrivateFieldGet(_e, _test) + 1); + _classPrivateFieldSet(_f = this.getInstance(), _test, _classPrivateFieldGet(_f, _test) - 1); + }; + C.prototype.getInstance = function () { return new C(); }; + return C; +}()); +_test = new WeakMap(); diff --git a/tests/baselines/reference/privateNameFieldUnaryMutation.symbols b/tests/baselines/reference/privateNameFieldUnaryMutation.symbols new file mode 100644 index 0000000000000..f224ef769c379 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldUnaryMutation.symbols @@ -0,0 +1,56 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldUnaryMutation.ts === +class C { +>C : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) + + #test: number = 24; +>#test : Symbol(C.#test, Decl(privateNameFieldUnaryMutation.ts, 0, 9)) + + constructor() { + this.#test++; +>this.#test : Symbol(C.#test, Decl(privateNameFieldUnaryMutation.ts, 0, 9)) +>this : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) + + this.#test--; +>this.#test : Symbol(C.#test, Decl(privateNameFieldUnaryMutation.ts, 0, 9)) +>this : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) + + ++this.#test; +>this.#test : Symbol(C.#test, Decl(privateNameFieldUnaryMutation.ts, 0, 9)) +>this : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) + + --this.#test; +>this.#test : Symbol(C.#test, Decl(privateNameFieldUnaryMutation.ts, 0, 9)) +>this : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) + } + test() { +>test : Symbol(C.test, Decl(privateNameFieldUnaryMutation.ts, 7, 5)) + + this.getInstance().#test++; +>this.getInstance().#test : Symbol(C.#test, Decl(privateNameFieldUnaryMutation.ts, 0, 9)) +>this.getInstance : Symbol(C.getInstance, Decl(privateNameFieldUnaryMutation.ts, 13, 5)) +>this : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) +>getInstance : Symbol(C.getInstance, Decl(privateNameFieldUnaryMutation.ts, 13, 5)) + + this.getInstance().#test--; +>this.getInstance().#test : Symbol(C.#test, Decl(privateNameFieldUnaryMutation.ts, 0, 9)) +>this.getInstance : Symbol(C.getInstance, Decl(privateNameFieldUnaryMutation.ts, 13, 5)) +>this : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) +>getInstance : Symbol(C.getInstance, Decl(privateNameFieldUnaryMutation.ts, 13, 5)) + + ++this.getInstance().#test; +>this.getInstance().#test : Symbol(C.#test, Decl(privateNameFieldUnaryMutation.ts, 0, 9)) +>this.getInstance : Symbol(C.getInstance, Decl(privateNameFieldUnaryMutation.ts, 13, 5)) +>this : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) +>getInstance : Symbol(C.getInstance, Decl(privateNameFieldUnaryMutation.ts, 13, 5)) + + --this.getInstance().#test; +>this.getInstance().#test : Symbol(C.#test, Decl(privateNameFieldUnaryMutation.ts, 0, 9)) +>this.getInstance : Symbol(C.getInstance, Decl(privateNameFieldUnaryMutation.ts, 13, 5)) +>this : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) +>getInstance : Symbol(C.getInstance, Decl(privateNameFieldUnaryMutation.ts, 13, 5)) + } + getInstance() { return new C(); } +>getInstance : Symbol(C.getInstance, Decl(privateNameFieldUnaryMutation.ts, 13, 5)) +>C : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) +} + diff --git a/tests/baselines/reference/privateNameFieldUnaryMutation.types b/tests/baselines/reference/privateNameFieldUnaryMutation.types new file mode 100644 index 0000000000000..130aa9bf39f82 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldUnaryMutation.types @@ -0,0 +1,70 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldUnaryMutation.ts === +class C { +>C : C + + #test: number = 24; +>#test : number +>24 : 24 + + constructor() { + this.#test++; +>this.#test++ : number +>this.#test : number +>this : this + + this.#test--; +>this.#test-- : number +>this.#test : number +>this : this + + ++this.#test; +>++this.#test : number +>this.#test : number +>this : this + + --this.#test; +>--this.#test : number +>this.#test : number +>this : this + } + test() { +>test : () => void + + this.getInstance().#test++; +>this.getInstance().#test++ : number +>this.getInstance().#test : number +>this.getInstance() : C +>this.getInstance : () => C +>this : this +>getInstance : () => C + + this.getInstance().#test--; +>this.getInstance().#test-- : number +>this.getInstance().#test : number +>this.getInstance() : C +>this.getInstance : () => C +>this : this +>getInstance : () => C + + ++this.getInstance().#test; +>++this.getInstance().#test : number +>this.getInstance().#test : number +>this.getInstance() : C +>this.getInstance : () => C +>this : this +>getInstance : () => C + + --this.getInstance().#test; +>--this.getInstance().#test : number +>this.getInstance().#test : number +>this.getInstance() : C +>this.getInstance : () => C +>this : this +>getInstance : () => C + } + getInstance() { return new C(); } +>getInstance : () => C +>new C() : C +>C : typeof C +} + diff --git a/tests/baselines/reference/privateNameInObjectLiteral-1.errors.txt b/tests/baselines/reference/privateNameInObjectLiteral-1.errors.txt new file mode 100644 index 0000000000000..cd17f4caf1545 --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral-1.errors.txt @@ -0,0 +1,10 @@ +tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-1.ts(2,5): error TS18010: Private names are not allowed outside class bodies. + + +==== tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-1.ts (1 errors) ==== + const obj = { + #foo: 1 + ~~~~ +!!! error TS18010: Private names are not allowed outside class bodies. + }; + \ No newline at end of file diff --git a/tests/baselines/reference/privateNameInObjectLiteral-1.js b/tests/baselines/reference/privateNameInObjectLiteral-1.js new file mode 100644 index 0000000000000..58af5d0ec5158 --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral-1.js @@ -0,0 +1,10 @@ +//// [privateNameInObjectLiteral-1.ts] +const obj = { + #foo: 1 +}; + + +//// [privateNameInObjectLiteral-1.js] +var obj = { + #foo: 1 +}; diff --git a/tests/baselines/reference/privateNameInObjectLiteral-1.symbols b/tests/baselines/reference/privateNameInObjectLiteral-1.symbols new file mode 100644 index 0000000000000..c675ee7cc758c --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral-1.symbols @@ -0,0 +1,9 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-1.ts === +const obj = { +>obj : Symbol(obj, Decl(privateNameInObjectLiteral-1.ts, 0, 5)) + + #foo: 1 +>#foo : Symbol(#foo, Decl(privateNameInObjectLiteral-1.ts, 0, 13)) + +}; + diff --git a/tests/baselines/reference/privateNameInObjectLiteral-1.types b/tests/baselines/reference/privateNameInObjectLiteral-1.types new file mode 100644 index 0000000000000..48de261be2900 --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral-1.types @@ -0,0 +1,11 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-1.ts === +const obj = { +>obj : {} +>{ #foo: 1} : {} + + #foo: 1 +>#foo : number +>1 : 1 + +}; + diff --git a/tests/baselines/reference/privateNameInObjectLiteral-2.errors.txt b/tests/baselines/reference/privateNameInObjectLiteral-2.errors.txt new file mode 100644 index 0000000000000..b79507b32000f --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral-2.errors.txt @@ -0,0 +1,12 @@ +tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-2.ts(2,5): error TS18010: Private names are not allowed outside class bodies. + + +==== tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-2.ts (1 errors) ==== + const obj = { + #foo() { + ~~~~ +!!! error TS18010: Private names are not allowed outside class bodies. + + } + }; + \ No newline at end of file diff --git a/tests/baselines/reference/privateNameInObjectLiteral-2.js b/tests/baselines/reference/privateNameInObjectLiteral-2.js new file mode 100644 index 0000000000000..6bb2c99d4c169 --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral-2.js @@ -0,0 +1,13 @@ +//// [privateNameInObjectLiteral-2.ts] +const obj = { + #foo() { + + } +}; + + +//// [privateNameInObjectLiteral-2.js] +var obj = { + #foo: function () { + } +}; diff --git a/tests/baselines/reference/privateNameInObjectLiteral-2.symbols b/tests/baselines/reference/privateNameInObjectLiteral-2.symbols new file mode 100644 index 0000000000000..b9a25ac870963 --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral-2.symbols @@ -0,0 +1,10 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-2.ts === +const obj = { +>obj : Symbol(obj, Decl(privateNameInObjectLiteral-2.ts, 0, 5)) + + #foo() { +>#foo : Symbol(#foo, Decl(privateNameInObjectLiteral-2.ts, 0, 13)) + + } +}; + diff --git a/tests/baselines/reference/privateNameInObjectLiteral-2.types b/tests/baselines/reference/privateNameInObjectLiteral-2.types new file mode 100644 index 0000000000000..a1e36e82380b1 --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral-2.types @@ -0,0 +1,11 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-2.ts === +const obj = { +>obj : {} +>{ #foo() { }} : {} + + #foo() { +>#foo : () => void + + } +}; + diff --git a/tests/baselines/reference/privateNameInObjectLiteral.errors.txt b/tests/baselines/reference/privateNameInObjectLiteral.errors.txt new file mode 100644 index 0000000000000..2f5101ec98646 --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral.errors.txt @@ -0,0 +1,14 @@ +tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral.ts(2,5): error TS18010: Private names are not allowed outside class bodies. + + +==== tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral.ts (1 errors) ==== + const obj = { + #foo: "#foo", + ~~~~ +!!! error TS18010: Private names are not allowed outside class bodies. + #bar: () => true, + #baz() { + return true; + } + }; + \ No newline at end of file diff --git a/tests/baselines/reference/privateNameInObjectLiteral.js b/tests/baselines/reference/privateNameInObjectLiteral.js new file mode 100644 index 0000000000000..a95d80d4add5f --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral.js @@ -0,0 +1,18 @@ +//// [privateNameInObjectLiteral.ts] +const obj = { + #foo: "#foo", + #bar: () => true, + #baz() { + return true; + } +}; + + +//// [privateNameInObjectLiteral.js] +var obj = { + #foo: "#foo", + #bar: function () { return true; }, + #baz: function () { + return true; + } +}; diff --git a/tests/baselines/reference/privateNameInObjectLiteral.symbols b/tests/baselines/reference/privateNameInObjectLiteral.symbols new file mode 100644 index 0000000000000..f5592c7384305 --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral.symbols @@ -0,0 +1,17 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral.ts === +const obj = { +>obj : Symbol(obj, Decl(privateNameInObjectLiteral.ts, 0, 5)) + + #foo: "#foo", +>#foo : Symbol(#foo, Decl(privateNameInObjectLiteral.ts, 0, 13)) + + #bar: () => true, +>#bar : Symbol(#bar, Decl(privateNameInObjectLiteral.ts, 1, 17)) + + #baz() { +>#baz : Symbol(#baz, Decl(privateNameInObjectLiteral.ts, 2, 21)) + + return true; + } +}; + diff --git a/tests/baselines/reference/privateNameInObjectLiteral.types b/tests/baselines/reference/privateNameInObjectLiteral.types new file mode 100644 index 0000000000000..372dc87bae5c3 --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral.types @@ -0,0 +1,22 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral.ts === +const obj = { +>obj : {} +>{ #foo: "#foo", #bar: () => true, #baz() { return true; }} : {} + + #foo: "#foo", +>#foo : string +>"#foo" : "#foo" + + #bar: () => true, +>#bar : () => boolean +>() => true : () => boolean +>true : true + + #baz() { +>#baz : () => boolean + + return true; +>true : true + } +}; + diff --git a/tests/baselines/reference/privateNameNestedClassNameConflict.js b/tests/baselines/reference/privateNameNestedClassNameConflict.js new file mode 100644 index 0000000000000..d8e0e240a7a6b --- /dev/null +++ b/tests/baselines/reference/privateNameNestedClassNameConflict.js @@ -0,0 +1,28 @@ +//// [privateNameNestedClassNameConflict.ts] +class A { + #foo: string; + constructor() { + class A { + #foo: string; + } + } +} + + +//// [privateNameNestedClassNameConflict.js] +var _foo; +var A = /** @class */ (function () { + function A() { + _foo.set(this, void 0); + var _foo_1; + var A = /** @class */ (function () { + function A() { + _foo_1.set(this, void 0); + } + return A; + }()); + _foo_1 = new WeakMap(); + } + return A; +}()); +_foo = new WeakMap(); diff --git a/tests/baselines/reference/privateNameNestedClassNameConflict.symbols b/tests/baselines/reference/privateNameNestedClassNameConflict.symbols new file mode 100644 index 0000000000000..5fec01b052701 --- /dev/null +++ b/tests/baselines/reference/privateNameNestedClassNameConflict.symbols @@ -0,0 +1,17 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameNestedClassNameConflict.ts === +class A { +>A : Symbol(A, Decl(privateNameNestedClassNameConflict.ts, 0, 0)) + + #foo: string; +>#foo : Symbol(A.#foo, Decl(privateNameNestedClassNameConflict.ts, 0, 9)) + + constructor() { + class A { +>A : Symbol(A, Decl(privateNameNestedClassNameConflict.ts, 2, 19)) + + #foo: string; +>#foo : Symbol(A.#foo, Decl(privateNameNestedClassNameConflict.ts, 3, 17)) + } + } +} + diff --git a/tests/baselines/reference/privateNameNestedClassNameConflict.types b/tests/baselines/reference/privateNameNestedClassNameConflict.types new file mode 100644 index 0000000000000..de6589940da50 --- /dev/null +++ b/tests/baselines/reference/privateNameNestedClassNameConflict.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameNestedClassNameConflict.ts === +class A { +>A : A + + #foo: string; +>#foo : string + + constructor() { + class A { +>A : A + + #foo: string; +>#foo : string + } + } +} + diff --git a/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.errors.txt b/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.errors.txt new file mode 100644 index 0000000000000..41a4d9c277cbf --- /dev/null +++ b/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.errors.txt @@ -0,0 +1,17 @@ +tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts(7,9): error TS2339: Property '#foo' does not exist on type 'A'. +tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts(7,9): error TS18007: Property '#foo' is not accessible outside class 'A' because it has a private name. + + +==== tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts (2 errors) ==== + // @target es6 + + class A { + #foo: number = 3; + } + + new A().#foo = 4; // Error + ~~~~ +!!! error TS2339: Property '#foo' does not exist on type 'A'. + ~~~~ +!!! error TS18007: Property '#foo' is not accessible outside class 'A' because it has a private name. + \ No newline at end of file diff --git a/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.js b/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.js new file mode 100644 index 0000000000000..655f3c7c55d37 --- /dev/null +++ b/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.js @@ -0,0 +1,22 @@ +//// [privateNameNotAccessibleOutsideDefiningClass.ts] +// @target es6 + +class A { + #foo: number = 3; +} + +new A().#foo = 4; // Error + + +//// [privateNameNotAccessibleOutsideDefiningClass.js] +// @target es6 +var _foo; +"use strict"; +var A = /** @class */ (function () { + function A() { + _foo.set(this, 3); + } + return A; +}()); +_foo = new WeakMap(); +new A().#foo = 4; // Error diff --git a/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.symbols b/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.symbols new file mode 100644 index 0000000000000..8d9427fc6d603 --- /dev/null +++ b/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.symbols @@ -0,0 +1,13 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNameNotAccessibleOutsideDefiningClass.ts, 0, 0)) + + #foo: number = 3; +>#foo : Symbol(A.#foo, Decl(privateNameNotAccessibleOutsideDefiningClass.ts, 2, 9)) +} + +new A().#foo = 4; // Error +>A : Symbol(A, Decl(privateNameNotAccessibleOutsideDefiningClass.ts, 0, 0)) + diff --git a/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.types b/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.types new file mode 100644 index 0000000000000..e6a0f5ac8f55b --- /dev/null +++ b/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.types @@ -0,0 +1,18 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts === +// @target es6 + +class A { +>A : A + + #foo: number = 3; +>#foo : number +>3 : 3 +} + +new A().#foo = 4; // Error +>new A().#foo = 4 : 4 +>new A().#foo : any +>new A() : A +>A : typeof A +>4 : 4 + diff --git a/tests/baselines/reference/privateNameNotAllowedOutsideClass.errors.txt b/tests/baselines/reference/privateNameNotAllowedOutsideClass.errors.txt new file mode 100644 index 0000000000000..2e72fffc7ba78 --- /dev/null +++ b/tests/baselines/reference/privateNameNotAllowedOutsideClass.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts(3,7): error TS1134: Variable declaration expected. +tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts(3,12): error TS1134: Variable declaration expected. +tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts(3,14): error TS1134: Variable declaration expected. + + +==== tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts (3 errors) ==== + // @target es6 + + const #foo = 3; + ~~~~ +!!! error TS1134: Variable declaration expected. + ~ +!!! error TS1134: Variable declaration expected. + ~ +!!! error TS1134: Variable declaration expected. \ No newline at end of file diff --git a/tests/baselines/reference/privateNameNotAllowedOutsideClass.js b/tests/baselines/reference/privateNameNotAllowedOutsideClass.js new file mode 100644 index 0000000000000..ff2b64b910ca1 --- /dev/null +++ b/tests/baselines/reference/privateNameNotAllowedOutsideClass.js @@ -0,0 +1,10 @@ +//// [privateNameNotAllowedOutsideClass.ts] +// @target es6 + +const #foo = 3; + +//// [privateNameNotAllowedOutsideClass.js] +"use strict"; +// @target es6 +var ; +3; diff --git a/tests/baselines/reference/privateNameNotAllowedOutsideClass.symbols b/tests/baselines/reference/privateNameNotAllowedOutsideClass.symbols new file mode 100644 index 0000000000000..6d6883e7fdf59 --- /dev/null +++ b/tests/baselines/reference/privateNameNotAllowedOutsideClass.symbols @@ -0,0 +1,5 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts === +// @target es6 +No type information for this code. +No type information for this code.const #foo = 3; +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/privateNameNotAllowedOutsideClass.types b/tests/baselines/reference/privateNameNotAllowedOutsideClass.types new file mode 100644 index 0000000000000..534e5b042580f --- /dev/null +++ b/tests/baselines/reference/privateNameNotAllowedOutsideClass.types @@ -0,0 +1,6 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts === +// @target es6 + +const #foo = 3; +>3 : 3 + diff --git a/tests/baselines/reference/privateNameSneakyRuntimeException.js b/tests/baselines/reference/privateNameSneakyRuntimeException.js new file mode 100644 index 0000000000000..e437f4da29fb5 --- /dev/null +++ b/tests/baselines/reference/privateNameSneakyRuntimeException.js @@ -0,0 +1,40 @@ +//// [privateNameSneakyRuntimeException.ts] +// @target es6 + +function createClass () { + return class { + #foo = 3; + equals(other: any) { + return this.#foo = other.#foo; + } + }; +} + +const a = new (createClass())(); +const b = new (createClass())(); + +console.log(a.equals(b)); // OK at compile time but will be a runtime error + + +//// [privateNameSneakyRuntimeException.js] +"use strict"; +// @target es6 +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +function createClass() { + var _foo, _a; + return _a = /** @class */ (function () { + function class_1() { + _foo.set(this, 3); + } + class_1.prototype.equals = function (other) { + return _classPrivateFieldSet(this, _foo, _classPrivateFieldGet(other, _foo)); + }; + return class_1; + }()), + _foo = new WeakMap(), + _a; +} +var a = new (createClass())(); +var b = new (createClass())(); +console.log(a.equals(b)); // OK at compile time but will be a runtime error diff --git a/tests/baselines/reference/privateNameSneakyRuntimeException.symbols b/tests/baselines/reference/privateNameSneakyRuntimeException.symbols new file mode 100644 index 0000000000000..585bdbf782c43 --- /dev/null +++ b/tests/baselines/reference/privateNameSneakyRuntimeException.symbols @@ -0,0 +1,39 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameSneakyRuntimeException.ts === +// @target es6 + +function createClass () { +>createClass : Symbol(createClass, Decl(privateNameSneakyRuntimeException.ts, 0, 0)) + + return class { + #foo = 3; +>#foo : Symbol((Anonymous class).#foo, Decl(privateNameSneakyRuntimeException.ts, 3, 18)) + + equals(other: any) { +>equals : Symbol((Anonymous class).equals, Decl(privateNameSneakyRuntimeException.ts, 4, 17)) +>other : Symbol(other, Decl(privateNameSneakyRuntimeException.ts, 5, 15)) + + return this.#foo = other.#foo; +>this.#foo : Symbol((Anonymous class).#foo, Decl(privateNameSneakyRuntimeException.ts, 3, 18)) +>this : Symbol((Anonymous class), Decl(privateNameSneakyRuntimeException.ts, 3, 10)) +>other : Symbol(other, Decl(privateNameSneakyRuntimeException.ts, 5, 15)) + } + }; +} + +const a = new (createClass())(); +>a : Symbol(a, Decl(privateNameSneakyRuntimeException.ts, 11, 5)) +>createClass : Symbol(createClass, Decl(privateNameSneakyRuntimeException.ts, 0, 0)) + +const b = new (createClass())(); +>b : Symbol(b, Decl(privateNameSneakyRuntimeException.ts, 12, 5)) +>createClass : Symbol(createClass, Decl(privateNameSneakyRuntimeException.ts, 0, 0)) + +console.log(a.equals(b)); // OK at compile time but will be a runtime error +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>a.equals : Symbol((Anonymous class).equals, Decl(privateNameSneakyRuntimeException.ts, 4, 17)) +>a : Symbol(a, Decl(privateNameSneakyRuntimeException.ts, 11, 5)) +>equals : Symbol((Anonymous class).equals, Decl(privateNameSneakyRuntimeException.ts, 4, 17)) +>b : Symbol(b, Decl(privateNameSneakyRuntimeException.ts, 12, 5)) + diff --git a/tests/baselines/reference/privateNameSneakyRuntimeException.types b/tests/baselines/reference/privateNameSneakyRuntimeException.types new file mode 100644 index 0000000000000..6f080bb585fca --- /dev/null +++ b/tests/baselines/reference/privateNameSneakyRuntimeException.types @@ -0,0 +1,52 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameSneakyRuntimeException.ts === +// @target es6 + +function createClass () { +>createClass : () => typeof (Anonymous class) + + return class { +>class { #foo = 3; equals(other: any) { return this.#foo = other.#foo; } } : typeof (Anonymous class) + + #foo = 3; +>#foo : number +>3 : 3 + + equals(other: any) { +>equals : (other: any) => any +>other : any + + return this.#foo = other.#foo; +>this.#foo = other.#foo : any +>this.#foo : number +>this : this +>other.#foo : any +>other : any + } + }; +} + +const a = new (createClass())(); +>a : (Anonymous class) +>new (createClass())() : (Anonymous class) +>(createClass()) : typeof (Anonymous class) +>createClass() : typeof (Anonymous class) +>createClass : () => typeof (Anonymous class) + +const b = new (createClass())(); +>b : (Anonymous class) +>new (createClass())() : (Anonymous class) +>(createClass()) : typeof (Anonymous class) +>createClass() : typeof (Anonymous class) +>createClass : () => typeof (Anonymous class) + +console.log(a.equals(b)); // OK at compile time but will be a runtime error +>console.log(a.equals(b)) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>a.equals(b) : any +>a.equals : (other: any) => any +>a : (Anonymous class) +>equals : (other: any) => any +>b : (Anonymous class) + diff --git a/tests/baselines/reference/privateNamesAndDecorators.errors.txt b/tests/baselines/reference/privateNamesAndDecorators.errors.txt new file mode 100644 index 0000000000000..a17770c1cb2a7 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndDecorators.errors.txt @@ -0,0 +1,18 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesAndDecorators.ts(4,5): error TS1206: Decorators are not valid here. +tests/cases/conformance/classes/members/privateNames/privateNamesAndDecorators.ts(6,5): error TS1206: Decorators are not valid here. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesAndDecorators.ts (2 errors) ==== + declare function dec(target: T): T; + + class A { + @dec // Error + ~ +!!! error TS1206: Decorators are not valid here. + #foo = 1; + @dec // Error + ~ +!!! error TS1206: Decorators are not valid here. + #bar(): void { } + } + \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesAndDecorators.js b/tests/baselines/reference/privateNamesAndDecorators.js new file mode 100644 index 0000000000000..3e2e760933e12 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndDecorators.js @@ -0,0 +1,21 @@ +//// [privateNamesAndDecorators.ts] +declare function dec(target: T): T; + +class A { + @dec // Error + #foo = 1; + @dec // Error + #bar(): void { } +} + + +//// [privateNamesAndDecorators.js] +var _foo; +var A = /** @class */ (function () { + function A() { + _foo.set(this, 1); + } + A.prototype.#bar = function () { }; + return A; +}()); +_foo = new WeakMap(); diff --git a/tests/baselines/reference/privateNamesAndDecorators.symbols b/tests/baselines/reference/privateNamesAndDecorators.symbols new file mode 100644 index 0000000000000..97463512cd910 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndDecorators.symbols @@ -0,0 +1,24 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndDecorators.ts === +declare function dec(target: T): T; +>dec : Symbol(dec, Decl(privateNamesAndDecorators.ts, 0, 0)) +>T : Symbol(T, Decl(privateNamesAndDecorators.ts, 0, 21)) +>target : Symbol(target, Decl(privateNamesAndDecorators.ts, 0, 24)) +>T : Symbol(T, Decl(privateNamesAndDecorators.ts, 0, 21)) +>T : Symbol(T, Decl(privateNamesAndDecorators.ts, 0, 21)) + +class A { +>A : Symbol(A, Decl(privateNamesAndDecorators.ts, 0, 38)) + + @dec // Error +>dec : Symbol(dec, Decl(privateNamesAndDecorators.ts, 0, 0)) + + #foo = 1; +>#foo : Symbol(A.#foo, Decl(privateNamesAndDecorators.ts, 2, 9)) + + @dec // Error +>dec : Symbol(dec, Decl(privateNamesAndDecorators.ts, 0, 0)) + + #bar(): void { } +>#bar : Symbol(A.#bar, Decl(privateNamesAndDecorators.ts, 4, 13)) +} + diff --git a/tests/baselines/reference/privateNamesAndDecorators.types b/tests/baselines/reference/privateNamesAndDecorators.types new file mode 100644 index 0000000000000..828516f38999b --- /dev/null +++ b/tests/baselines/reference/privateNamesAndDecorators.types @@ -0,0 +1,22 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndDecorators.ts === +declare function dec(target: T): T; +>dec : (target: T) => T +>target : T + +class A { +>A : A + + @dec // Error +>dec : (target: T) => T + + #foo = 1; +>#foo : number +>1 : 1 + + @dec // Error +>dec : (target: T) => T + + #bar(): void { } +>#bar : () => void +} + diff --git a/tests/baselines/reference/privateNamesAndFields.js b/tests/baselines/reference/privateNamesAndFields.js new file mode 100644 index 0000000000000..4af48cfe9b245 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndFields.js @@ -0,0 +1,56 @@ +//// [privateNamesAndFields.ts] +// @target es6 + +class A { + #foo: number; + constructor () { + this.#foo = 3; + } +} + +class B extends A { + #foo: string; + constructor () { + super(); + this.#foo = "some string"; + } +} + + +//// [privateNamesAndFields.js] +// @target es6 +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 (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +var _foo, _foo_1; +"use strict"; +var A = /** @class */ (function () { + function A() { + _foo.set(this, void 0); + _classPrivateFieldSet(this, _foo, 3); + } + return A; +}()); +_foo = new WeakMap(); +var B = /** @class */ (function (_super) { + __extends(B, _super); + function B() { + var _this = _super.call(this) || this; + _foo_1.set(_this, void 0); + _classPrivateFieldSet(_this, _foo_1, "some string"); + return _this; + } + return B; +}(A)); +_foo_1 = new WeakMap(); diff --git a/tests/baselines/reference/privateNamesAndFields.symbols b/tests/baselines/reference/privateNamesAndFields.symbols new file mode 100644 index 0000000000000..5300cd0427ff0 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndFields.symbols @@ -0,0 +1,33 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndFields.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNamesAndFields.ts, 0, 0)) + + #foo: number; +>#foo : Symbol(A.#foo, Decl(privateNamesAndFields.ts, 2, 9)) + + constructor () { + this.#foo = 3; +>this.#foo : Symbol(A.#foo, Decl(privateNamesAndFields.ts, 2, 9)) +>this : Symbol(A, Decl(privateNamesAndFields.ts, 0, 0)) + } +} + +class B extends A { +>B : Symbol(B, Decl(privateNamesAndFields.ts, 7, 1)) +>A : Symbol(A, Decl(privateNamesAndFields.ts, 0, 0)) + + #foo: string; +>#foo : Symbol(B.#foo, Decl(privateNamesAndFields.ts, 9, 19)) + + constructor () { + super(); +>super : Symbol(A, Decl(privateNamesAndFields.ts, 0, 0)) + + this.#foo = "some string"; +>this.#foo : Symbol(B.#foo, Decl(privateNamesAndFields.ts, 9, 19)) +>this : Symbol(B, Decl(privateNamesAndFields.ts, 7, 1)) + } +} + diff --git a/tests/baselines/reference/privateNamesAndFields.types b/tests/baselines/reference/privateNamesAndFields.types new file mode 100644 index 0000000000000..88a48ecd81298 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndFields.types @@ -0,0 +1,38 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndFields.ts === +// @target es6 + +class A { +>A : A + + #foo: number; +>#foo : number + + constructor () { + this.#foo = 3; +>this.#foo = 3 : 3 +>this.#foo : number +>this : this +>3 : 3 + } +} + +class B extends A { +>B : B +>A : A + + #foo: string; +>#foo : string + + constructor () { + super(); +>super() : void +>super : typeof A + + this.#foo = "some string"; +>this.#foo = "some string" : "some string" +>this.#foo : string +>this : this +>"some string" : "some string" + } +} + diff --git a/tests/baselines/reference/privateNamesAndGenericClasses-2.errors.txt b/tests/baselines/reference/privateNamesAndGenericClasses-2.errors.txt new file mode 100644 index 0000000000000..f9b6ebacba805 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndGenericClasses-2.errors.txt @@ -0,0 +1,46 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts(24,3): error TS2339: Property '#foo' does not exist on type 'C'. +tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts(24,3): error TS18007: Property '#foo' is not accessible outside class 'C' because it has a private name. +tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts(25,1): error TS2322: Type 'C' is not assignable to type 'C'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts(26,1): error TS2322: Type 'C' is not assignable to type 'C'. + Type 'number' is not assignable to type 'string'. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts (4 errors) ==== + class C { + #foo: T; + #bar(): T { + return this.#foo; + } + constructor(t: T) { + this.#foo = t; + t = this.#bar(); + } + set baz(t: T) { + this.#foo = t; + + } + get baz(): T { + return this.#foo; + } + } + + let a = new C(3); + let b = new C("hello"); + + a.baz = 5 // OK + const x: number = a.baz // OK + a.#foo; // Error + ~~~~ +!!! error TS2339: Property '#foo' does not exist on type 'C'. + ~~~~ +!!! error TS18007: Property '#foo' is not accessible outside class 'C' because it has a private name. + a = b; // Error + ~ +!!! error TS2322: Type 'C' is not assignable to type 'C'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. + b = a; // Error + ~ +!!! error TS2322: Type 'C' is not assignable to type 'C'. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesAndGenericClasses-2.js b/tests/baselines/reference/privateNamesAndGenericClasses-2.js new file mode 100644 index 0000000000000..972af4a681e20 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndGenericClasses-2.js @@ -0,0 +1,58 @@ +//// [privateNamesAndGenericClasses-2.ts] +class C { + #foo: T; + #bar(): T { + return this.#foo; + } + constructor(t: T) { + this.#foo = t; + t = this.#bar(); + } + set baz(t: T) { + this.#foo = t; + + } + get baz(): T { + return this.#foo; + } +} + +let a = new C(3); +let b = new C("hello"); + +a.baz = 5 // OK +const x: number = a.baz // OK +a.#foo; // Error +a = b; // Error +b = a; // Error + + +//// [privateNamesAndGenericClasses-2.js] +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _foo; +"use strict"; +class C { + constructor(t) { + _foo.set(this, void 0); + _classPrivateFieldSet(this, _foo, t); + t = this.#bar.call(this); + } + #bar() { + return _classPrivateFieldGet(this, _foo); + } + set baz(t) { + _classPrivateFieldSet(this, _foo, t); + } + get baz() { + return _classPrivateFieldGet(this, _foo); + } +} +_foo = new WeakMap(); +let a = new C(3); +let b = new C("hello"); +a.baz = 5; // OK +const x = a.baz; // OK +a.#foo; // Error +a = b; // Error +b = a; // Error diff --git a/tests/baselines/reference/privateNamesAndGenericClasses-2.symbols b/tests/baselines/reference/privateNamesAndGenericClasses-2.symbols new file mode 100644 index 0000000000000..0f84af4a027f0 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndGenericClasses-2.symbols @@ -0,0 +1,82 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts === +class C { +>C : Symbol(C, Decl(privateNamesAndGenericClasses-2.ts, 0, 0)) +>T : Symbol(T, Decl(privateNamesAndGenericClasses-2.ts, 0, 8)) + + #foo: T; +>#foo : Symbol(C.#foo, Decl(privateNamesAndGenericClasses-2.ts, 0, 12)) +>T : Symbol(T, Decl(privateNamesAndGenericClasses-2.ts, 0, 8)) + + #bar(): T { +>#bar : Symbol(C.#bar, Decl(privateNamesAndGenericClasses-2.ts, 1, 12)) +>T : Symbol(T, Decl(privateNamesAndGenericClasses-2.ts, 0, 8)) + + return this.#foo; +>this.#foo : Symbol(C.#foo, Decl(privateNamesAndGenericClasses-2.ts, 0, 12)) +>this : Symbol(C, Decl(privateNamesAndGenericClasses-2.ts, 0, 0)) + } + constructor(t: T) { +>t : Symbol(t, Decl(privateNamesAndGenericClasses-2.ts, 5, 16)) +>T : Symbol(T, Decl(privateNamesAndGenericClasses-2.ts, 0, 8)) + + this.#foo = t; +>this.#foo : Symbol(C.#foo, Decl(privateNamesAndGenericClasses-2.ts, 0, 12)) +>this : Symbol(C, Decl(privateNamesAndGenericClasses-2.ts, 0, 0)) +>t : Symbol(t, Decl(privateNamesAndGenericClasses-2.ts, 5, 16)) + + t = this.#bar(); +>t : Symbol(t, Decl(privateNamesAndGenericClasses-2.ts, 5, 16)) +>this.#bar : Symbol(C.#bar, Decl(privateNamesAndGenericClasses-2.ts, 1, 12)) +>this : Symbol(C, Decl(privateNamesAndGenericClasses-2.ts, 0, 0)) + } + set baz(t: T) { +>baz : Symbol(C.baz, Decl(privateNamesAndGenericClasses-2.ts, 8, 5), Decl(privateNamesAndGenericClasses-2.ts, 12, 5)) +>t : Symbol(t, Decl(privateNamesAndGenericClasses-2.ts, 9, 12)) +>T : Symbol(T, Decl(privateNamesAndGenericClasses-2.ts, 0, 8)) + + this.#foo = t; +>this.#foo : Symbol(C.#foo, Decl(privateNamesAndGenericClasses-2.ts, 0, 12)) +>this : Symbol(C, Decl(privateNamesAndGenericClasses-2.ts, 0, 0)) +>t : Symbol(t, Decl(privateNamesAndGenericClasses-2.ts, 9, 12)) + + } + get baz(): T { +>baz : Symbol(C.baz, Decl(privateNamesAndGenericClasses-2.ts, 8, 5), Decl(privateNamesAndGenericClasses-2.ts, 12, 5)) +>T : Symbol(T, Decl(privateNamesAndGenericClasses-2.ts, 0, 8)) + + return this.#foo; +>this.#foo : Symbol(C.#foo, Decl(privateNamesAndGenericClasses-2.ts, 0, 12)) +>this : Symbol(C, Decl(privateNamesAndGenericClasses-2.ts, 0, 0)) + } +} + +let a = new C(3); +>a : Symbol(a, Decl(privateNamesAndGenericClasses-2.ts, 18, 3)) +>C : Symbol(C, Decl(privateNamesAndGenericClasses-2.ts, 0, 0)) + +let b = new C("hello"); +>b : Symbol(b, Decl(privateNamesAndGenericClasses-2.ts, 19, 3)) +>C : Symbol(C, Decl(privateNamesAndGenericClasses-2.ts, 0, 0)) + +a.baz = 5 // OK +>a.baz : Symbol(C.baz, Decl(privateNamesAndGenericClasses-2.ts, 8, 5), Decl(privateNamesAndGenericClasses-2.ts, 12, 5)) +>a : Symbol(a, Decl(privateNamesAndGenericClasses-2.ts, 18, 3)) +>baz : Symbol(C.baz, Decl(privateNamesAndGenericClasses-2.ts, 8, 5), Decl(privateNamesAndGenericClasses-2.ts, 12, 5)) + +const x: number = a.baz // OK +>x : Symbol(x, Decl(privateNamesAndGenericClasses-2.ts, 22, 5)) +>a.baz : Symbol(C.baz, Decl(privateNamesAndGenericClasses-2.ts, 8, 5), Decl(privateNamesAndGenericClasses-2.ts, 12, 5)) +>a : Symbol(a, Decl(privateNamesAndGenericClasses-2.ts, 18, 3)) +>baz : Symbol(C.baz, Decl(privateNamesAndGenericClasses-2.ts, 8, 5), Decl(privateNamesAndGenericClasses-2.ts, 12, 5)) + +a.#foo; // Error +>a : Symbol(a, Decl(privateNamesAndGenericClasses-2.ts, 18, 3)) + +a = b; // Error +>a : Symbol(a, Decl(privateNamesAndGenericClasses-2.ts, 18, 3)) +>b : Symbol(b, Decl(privateNamesAndGenericClasses-2.ts, 19, 3)) + +b = a; // Error +>b : Symbol(b, Decl(privateNamesAndGenericClasses-2.ts, 19, 3)) +>a : Symbol(a, Decl(privateNamesAndGenericClasses-2.ts, 18, 3)) + diff --git a/tests/baselines/reference/privateNamesAndGenericClasses-2.types b/tests/baselines/reference/privateNamesAndGenericClasses-2.types new file mode 100644 index 0000000000000..42f5b237d06fa --- /dev/null +++ b/tests/baselines/reference/privateNamesAndGenericClasses-2.types @@ -0,0 +1,89 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts === +class C { +>C : C + + #foo: T; +>#foo : T + + #bar(): T { +>#bar : () => T + + return this.#foo; +>this.#foo : T +>this : this + } + constructor(t: T) { +>t : T + + this.#foo = t; +>this.#foo = t : T +>this.#foo : T +>this : this +>t : T + + t = this.#bar(); +>t = this.#bar() : T +>t : T +>this.#bar() : T +>this.#bar : () => T +>this : this + } + set baz(t: T) { +>baz : T +>t : T + + this.#foo = t; +>this.#foo = t : T +>this.#foo : T +>this : this +>t : T + + } + get baz(): T { +>baz : T + + return this.#foo; +>this.#foo : T +>this : this + } +} + +let a = new C(3); +>a : C +>new C(3) : C +>C : typeof C +>3 : 3 + +let b = new C("hello"); +>b : C +>new C("hello") : C +>C : typeof C +>"hello" : "hello" + +a.baz = 5 // OK +>a.baz = 5 : 5 +>a.baz : number +>a : C +>baz : number +>5 : 5 + +const x: number = a.baz // OK +>x : number +>a.baz : number +>a : C +>baz : number + +a.#foo; // Error +>a.#foo : any +>a : C + +a = b; // Error +>a = b : C +>a : C +>b : C + +b = a; // Error +>b = a : C +>b : C +>a : C + diff --git a/tests/baselines/reference/privateNamesAndIndexedAccess.errors.txt b/tests/baselines/reference/privateNamesAndIndexedAccess.errors.txt new file mode 100644 index 0000000000000..95b8ab2a61bf7 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndIndexedAccess.errors.txt @@ -0,0 +1,39 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts(7,28): error TS1005: ']' expected. +tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts(7,28): error TS2300: Duplicate identifier '#bar'. +tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts(7,28): error TS2717: Subsequent property declarations must have the same type. Property '#bar' must be of type 'number', but here has type 'any'. +tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts(7,32): error TS1005: ';' expected. +tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts(7,34): error TS1068: Unexpected token. A constructor, method, accessor, or property was expected. +tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts(7,36): error TS7008: Member '3' implicitly has an 'any' type. +tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts(9,28): error TS2339: Property '#bar' does not exist on type 'C'. +tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts(11,1): error TS1128: Declaration or statement expected. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts (8 errors) ==== + class C { + foo = 3; + #bar = 3; + constructor () { + const ok: C["foo"] = 3; + // not supported yet, could support in future: + const badForNow: C[#bar] = 3; // Error + ~~~~ +!!! error TS1005: ']' expected. + ~~~~ +!!! error TS2300: Duplicate identifier '#bar'. + ~~~~ +!!! error TS2717: Subsequent property declarations must have the same type. Property '#bar' must be of type 'number', but here has type 'any'. + ~ +!!! error TS1005: ';' expected. + ~ +!!! error TS1068: Unexpected token. A constructor, method, accessor, or property was expected. + ~ +!!! error TS7008: Member '3' implicitly has an 'any' type. + // will never use this syntax, already taken: + const badAlways: C["#bar"] = 3; // Error + ~~~~~~ +!!! error TS2339: Property '#bar' does not exist on type 'C'. + } + } + ~ +!!! error TS1128: Declaration or statement expected. + \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesAndIndexedAccess.js b/tests/baselines/reference/privateNamesAndIndexedAccess.js new file mode 100644 index 0000000000000..44dde9629a8c6 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndIndexedAccess.js @@ -0,0 +1,30 @@ +//// [privateNamesAndIndexedAccess.ts] +class C { + foo = 3; + #bar = 3; + constructor () { + const ok: C["foo"] = 3; + // not supported yet, could support in future: + const badForNow: C[#bar] = 3; // Error + // will never use this syntax, already taken: + const badAlways: C["#bar"] = 3; // Error + } +} + + +//// [privateNamesAndIndexedAccess.js] +var _bar, _bar_1; +"use strict"; +class C { + constructor() { + this.foo = 3; + _bar_1.set(this, 3); + _bar_1.set(this, void 0); + // will never use this syntax, already taken: + this.badAlways = 3; // Error + const ok = 3; + // not supported yet, could support in future: + const badForNow; + } +} +_bar = new WeakMap(), _bar_1 = new WeakMap(); diff --git a/tests/baselines/reference/privateNamesAndIndexedAccess.symbols b/tests/baselines/reference/privateNamesAndIndexedAccess.symbols new file mode 100644 index 0000000000000..43a743810dca6 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndIndexedAccess.symbols @@ -0,0 +1,29 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts === +class C { +>C : Symbol(C, Decl(privateNamesAndIndexedAccess.ts, 0, 0)) + + foo = 3; +>foo : Symbol(C.foo, Decl(privateNamesAndIndexedAccess.ts, 0, 9)) + + #bar = 3; +>#bar : Symbol(C.#bar, Decl(privateNamesAndIndexedAccess.ts, 1, 12), Decl(privateNamesAndIndexedAccess.ts, 6, 27)) + + constructor () { + const ok: C["foo"] = 3; +>ok : Symbol(ok, Decl(privateNamesAndIndexedAccess.ts, 4, 13)) +>C : Symbol(C, Decl(privateNamesAndIndexedAccess.ts, 0, 0)) + + // not supported yet, could support in future: + const badForNow: C[#bar] = 3; // Error +>badForNow : Symbol(badForNow, Decl(privateNamesAndIndexedAccess.ts, 6, 13)) +>C : Symbol(C, Decl(privateNamesAndIndexedAccess.ts, 0, 0)) +>#bar : Symbol(C.#bar, Decl(privateNamesAndIndexedAccess.ts, 1, 12), Decl(privateNamesAndIndexedAccess.ts, 6, 27)) +>3 : Symbol(C[3], Decl(privateNamesAndIndexedAccess.ts, 6, 34)) + + // will never use this syntax, already taken: + const badAlways: C["#bar"] = 3; // Error +>badAlways : Symbol(C.badAlways, Decl(privateNamesAndIndexedAccess.ts, 6, 37)) +>C : Symbol(C, Decl(privateNamesAndIndexedAccess.ts, 0, 0)) + } +} + diff --git a/tests/baselines/reference/privateNamesAndIndexedAccess.types b/tests/baselines/reference/privateNamesAndIndexedAccess.types new file mode 100644 index 0000000000000..84ac9d43ffed9 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndIndexedAccess.types @@ -0,0 +1,30 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts === +class C { +>C : C + + foo = 3; +>foo : number +>3 : 3 + + #bar = 3; +>#bar : number +>3 : 3 + + constructor () { + const ok: C["foo"] = 3; +>ok : number +>3 : 3 + + // not supported yet, could support in future: + const badForNow: C[#bar] = 3; // Error +>badForNow : C[] +>#bar : number +>3 : any + + // will never use this syntax, already taken: + const badAlways: C["#bar"] = 3; // Error +>badAlways : any +>3 : 3 + } +} + diff --git a/tests/baselines/reference/privateNamesAndMethods.js b/tests/baselines/reference/privateNamesAndMethods.js new file mode 100644 index 0000000000000..7cb222a061164 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndMethods.js @@ -0,0 +1,65 @@ +//// [privateNamesAndMethods.ts] +class A { + #foo(a: number) {} + async #bar(a: number) {} + async *#baz(a: number) { + return 3; + } + #_quux: number; + get #quux (): number { + return this.#_quux; + } + set #quux (val: number) { + this.#_quux = val; + } + constructor () { + this.#foo(30); + this.#bar(30); + this.#bar(30); + this.#quux = this.#quux + 1; + this.#quux++; + } +} + +class B extends A { + #foo(a: string) {} + constructor () { + super(); + this.#foo("str"); + } +} + + +//// [privateNamesAndMethods.js] +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +var __quux; +class A { + constructor() { + __quux.set(this, void 0); + this.#foo.call(this, 30); + this.#bar.call(this, 30); + this.#bar.call(this, 30); + this.#quux = this.#quux + 1; + this.#quux++; + } + #foo(a) { } + async #bar(a) { } + async *#baz(a) { + return 3; + } + get #quux() { + return _classPrivateFieldGet(this, __quux); + } + set #quux(val) { + _classPrivateFieldSet(this, __quux, val); + } +} +__quux = new WeakMap(); +class B extends A { + constructor() { + super(); + this.#foo.call(this, "str"); + } + #foo(a) { } +} diff --git a/tests/baselines/reference/privateNamesAndMethods.symbols b/tests/baselines/reference/privateNamesAndMethods.symbols new file mode 100644 index 0000000000000..817f1dcd31112 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndMethods.symbols @@ -0,0 +1,80 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndMethods.ts === +class A { +>A : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) + + #foo(a: number) {} +>#foo : Symbol(A.#foo, Decl(privateNamesAndMethods.ts, 0, 9)) +>a : Symbol(a, Decl(privateNamesAndMethods.ts, 1, 9)) + + async #bar(a: number) {} +>#bar : Symbol(A.#bar, Decl(privateNamesAndMethods.ts, 1, 22)) +>a : Symbol(a, Decl(privateNamesAndMethods.ts, 2, 15)) + + async *#baz(a: number) { +>#baz : Symbol(A.#baz, Decl(privateNamesAndMethods.ts, 2, 28)) +>a : Symbol(a, Decl(privateNamesAndMethods.ts, 3, 16)) + + return 3; + } + #_quux: number; +>#_quux : Symbol(A.#_quux, Decl(privateNamesAndMethods.ts, 5, 5)) + + get #quux (): number { +>#quux : Symbol(A.#quux, Decl(privateNamesAndMethods.ts, 6, 19), Decl(privateNamesAndMethods.ts, 9, 5)) + + return this.#_quux; +>this.#_quux : Symbol(A.#_quux, Decl(privateNamesAndMethods.ts, 5, 5)) +>this : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) + } + set #quux (val: number) { +>#quux : Symbol(A.#quux, Decl(privateNamesAndMethods.ts, 6, 19), Decl(privateNamesAndMethods.ts, 9, 5)) +>val : Symbol(val, Decl(privateNamesAndMethods.ts, 10, 15)) + + this.#_quux = val; +>this.#_quux : Symbol(A.#_quux, Decl(privateNamesAndMethods.ts, 5, 5)) +>this : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) +>val : Symbol(val, Decl(privateNamesAndMethods.ts, 10, 15)) + } + constructor () { + this.#foo(30); +>this.#foo : Symbol(A.#foo, Decl(privateNamesAndMethods.ts, 0, 9)) +>this : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) + + this.#bar(30); +>this.#bar : Symbol(A.#bar, Decl(privateNamesAndMethods.ts, 1, 22)) +>this : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) + + this.#bar(30); +>this.#bar : Symbol(A.#bar, Decl(privateNamesAndMethods.ts, 1, 22)) +>this : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) + + this.#quux = this.#quux + 1; +>this.#quux : Symbol(A.#quux, Decl(privateNamesAndMethods.ts, 6, 19), Decl(privateNamesAndMethods.ts, 9, 5)) +>this : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) +>this.#quux : Symbol(A.#quux, Decl(privateNamesAndMethods.ts, 6, 19), Decl(privateNamesAndMethods.ts, 9, 5)) +>this : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) + + this.#quux++; +>this.#quux : Symbol(A.#quux, Decl(privateNamesAndMethods.ts, 6, 19), Decl(privateNamesAndMethods.ts, 9, 5)) +>this : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) + } +} + +class B extends A { +>B : Symbol(B, Decl(privateNamesAndMethods.ts, 20, 1)) +>A : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) + + #foo(a: string) {} +>#foo : Symbol(B.#foo, Decl(privateNamesAndMethods.ts, 22, 19)) +>a : Symbol(a, Decl(privateNamesAndMethods.ts, 23, 9)) + + constructor () { + super(); +>super : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) + + this.#foo("str"); +>this.#foo : Symbol(B.#foo, Decl(privateNamesAndMethods.ts, 22, 19)) +>this : Symbol(B, Decl(privateNamesAndMethods.ts, 20, 1)) + } +} + diff --git a/tests/baselines/reference/privateNamesAndMethods.types b/tests/baselines/reference/privateNamesAndMethods.types new file mode 100644 index 0000000000000..847ee901d527b --- /dev/null +++ b/tests/baselines/reference/privateNamesAndMethods.types @@ -0,0 +1,95 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndMethods.ts === +class A { +>A : A + + #foo(a: number) {} +>#foo : (a: number) => void +>a : number + + async #bar(a: number) {} +>#bar : (a: number) => Promise +>a : number + + async *#baz(a: number) { +>#baz : (a: number) => AsyncIterableIterator +>a : number + + return 3; +>3 : 3 + } + #_quux: number; +>#_quux : number + + get #quux (): number { +>#quux : number + + return this.#_quux; +>this.#_quux : number +>this : this + } + set #quux (val: number) { +>#quux : number +>val : number + + this.#_quux = val; +>this.#_quux = val : number +>this.#_quux : number +>this : this +>val : number + } + constructor () { + this.#foo(30); +>this.#foo(30) : void +>this.#foo : (a: number) => void +>this : this +>30 : 30 + + this.#bar(30); +>this.#bar(30) : Promise +>this.#bar : (a: number) => Promise +>this : this +>30 : 30 + + this.#bar(30); +>this.#bar(30) : Promise +>this.#bar : (a: number) => Promise +>this : this +>30 : 30 + + this.#quux = this.#quux + 1; +>this.#quux = this.#quux + 1 : number +>this.#quux : number +>this : this +>this.#quux + 1 : number +>this.#quux : number +>this : this +>1 : 1 + + this.#quux++; +>this.#quux++ : number +>this.#quux : number +>this : this + } +} + +class B extends A { +>B : B +>A : A + + #foo(a: string) {} +>#foo : (a: string) => void +>a : string + + constructor () { + super(); +>super() : void +>super : typeof A + + this.#foo("str"); +>this.#foo("str") : void +>this.#foo : (a: string) => void +>this : this +>"str" : "str" + } +} + diff --git a/tests/baselines/reference/privateNamesAndStaticFields.js b/tests/baselines/reference/privateNamesAndStaticFields.js new file mode 100644 index 0000000000000..7beaa98bdb674 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndStaticFields.js @@ -0,0 +1,54 @@ +//// [privateNamesAndStaticFields.ts] +// @target es6 + +class A { + static #foo: number; + constructor () { + A.#foo = 3; + } +} + +class B extends A { + static #foo: string; + constructor () { + super(); + B.#foo = "some string"; + } +} + + +//// [privateNamesAndStaticFields.js] +// @target es6 +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 (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +var _foo, _foo_1; +"use strict"; +var A = /** @class */ (function () { + function A() { + _classPrivateFieldSet(A, _foo, 3); + } + return A; +}()); +_foo = new WeakMap(); +var B = /** @class */ (function (_super) { + __extends(B, _super); + function B() { + var _this = _super.call(this) || this; + _classPrivateFieldSet(B, _foo_1, "some string"); + return _this; + } + return B; +}(A)); +_foo_1 = new WeakMap(); diff --git a/tests/baselines/reference/privateNamesAndStaticFields.symbols b/tests/baselines/reference/privateNamesAndStaticFields.symbols new file mode 100644 index 0000000000000..5898928bfb741 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndStaticFields.symbols @@ -0,0 +1,33 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticFields.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNamesAndStaticFields.ts, 0, 0)) + + static #foo: number; +>#foo : Symbol(A.#foo, Decl(privateNamesAndStaticFields.ts, 2, 9)) + + constructor () { + A.#foo = 3; +>A.#foo : Symbol(A.#foo, Decl(privateNamesAndStaticFields.ts, 2, 9)) +>A : Symbol(A, Decl(privateNamesAndStaticFields.ts, 0, 0)) + } +} + +class B extends A { +>B : Symbol(B, Decl(privateNamesAndStaticFields.ts, 7, 1)) +>A : Symbol(A, Decl(privateNamesAndStaticFields.ts, 0, 0)) + + static #foo: string; +>#foo : Symbol(B.#foo, Decl(privateNamesAndStaticFields.ts, 9, 19)) + + constructor () { + super(); +>super : Symbol(A, Decl(privateNamesAndStaticFields.ts, 0, 0)) + + B.#foo = "some string"; +>B.#foo : Symbol(B.#foo, Decl(privateNamesAndStaticFields.ts, 9, 19)) +>B : Symbol(B, Decl(privateNamesAndStaticFields.ts, 7, 1)) + } +} + diff --git a/tests/baselines/reference/privateNamesAndStaticFields.types b/tests/baselines/reference/privateNamesAndStaticFields.types new file mode 100644 index 0000000000000..ba630cbcf7709 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndStaticFields.types @@ -0,0 +1,38 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticFields.ts === +// @target es6 + +class A { +>A : A + + static #foo: number; +>#foo : number + + constructor () { + A.#foo = 3; +>A.#foo = 3 : 3 +>A.#foo : number +>A : typeof A +>3 : 3 + } +} + +class B extends A { +>B : B +>A : A + + static #foo: string; +>#foo : string + + constructor () { + super(); +>super() : void +>super : typeof A + + B.#foo = "some string"; +>B.#foo = "some string" : "some string" +>B.#foo : string +>B : typeof B +>"some string" : "some string" + } +} + diff --git a/tests/baselines/reference/privateNamesAndStaticMethods.js b/tests/baselines/reference/privateNamesAndStaticMethods.js new file mode 100644 index 0000000000000..b021f6a606635 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndStaticMethods.js @@ -0,0 +1,67 @@ +//// [privateNamesAndStaticMethods.ts] +class A { + static #foo(a: number) {} + static async #bar(a: number) {} + static async *#baz(a: number) { + return 3; + } + static #_quux: number; + static get #quux (): number { + return this.#_quux; + } + static set #quux (val: number) { + this.#_quux = val; + } + constructor () { + A.#foo(30); + A.#bar(30); + A.#bar(30); + A.#quux = A.#quux + 1; + A.#quux++; + } +} + +class B extends A { + static #foo(a: string) {} + constructor () { + super(); + B.#foo("str"); + } +} + + +//// [privateNamesAndStaticMethods.js] +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +var __quux; +"use strict"; +class A { + constructor() { + var _a, _b, _c; + (_a = A).#foo.call(_a, 30); + (_b = A).#bar.call(_b, 30); + (_c = A).#bar.call(_c, 30); + A.#quux = A.#quux + 1; + A.#quux++; + } + static #foo(a) { } + static async #bar(a) { } + static async *#baz(a) { + return 3; + } + static get #quux() { + return _classPrivateFieldGet(this, __quux); + } + static set #quux(val) { + _classPrivateFieldSet(this, __quux, val); + } +} +__quux = new WeakMap(); +class B extends A { + constructor() { + var _a; + super(); + (_a = B).#foo.call(_a, "str"); + } + static #foo(a) { } +} diff --git a/tests/baselines/reference/privateNamesAndStaticMethods.symbols b/tests/baselines/reference/privateNamesAndStaticMethods.symbols new file mode 100644 index 0000000000000..57d684a70696d --- /dev/null +++ b/tests/baselines/reference/privateNamesAndStaticMethods.symbols @@ -0,0 +1,80 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticMethods.ts === +class A { +>A : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) + + static #foo(a: number) {} +>#foo : Symbol(A.#foo, Decl(privateNamesAndStaticMethods.ts, 0, 9)) +>a : Symbol(a, Decl(privateNamesAndStaticMethods.ts, 1, 16)) + + static async #bar(a: number) {} +>#bar : Symbol(A.#bar, Decl(privateNamesAndStaticMethods.ts, 1, 29)) +>a : Symbol(a, Decl(privateNamesAndStaticMethods.ts, 2, 22)) + + static async *#baz(a: number) { +>#baz : Symbol(A.#baz, Decl(privateNamesAndStaticMethods.ts, 2, 35)) +>a : Symbol(a, Decl(privateNamesAndStaticMethods.ts, 3, 23)) + + return 3; + } + static #_quux: number; +>#_quux : Symbol(A.#_quux, Decl(privateNamesAndStaticMethods.ts, 5, 5)) + + static get #quux (): number { +>#quux : Symbol(A.#quux, Decl(privateNamesAndStaticMethods.ts, 6, 26), Decl(privateNamesAndStaticMethods.ts, 9, 5)) + + return this.#_quux; +>this.#_quux : Symbol(A.#_quux, Decl(privateNamesAndStaticMethods.ts, 5, 5)) +>this : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) + } + static set #quux (val: number) { +>#quux : Symbol(A.#quux, Decl(privateNamesAndStaticMethods.ts, 6, 26), Decl(privateNamesAndStaticMethods.ts, 9, 5)) +>val : Symbol(val, Decl(privateNamesAndStaticMethods.ts, 10, 22)) + + this.#_quux = val; +>this.#_quux : Symbol(A.#_quux, Decl(privateNamesAndStaticMethods.ts, 5, 5)) +>this : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) +>val : Symbol(val, Decl(privateNamesAndStaticMethods.ts, 10, 22)) + } + constructor () { + A.#foo(30); +>A.#foo : Symbol(A.#foo, Decl(privateNamesAndStaticMethods.ts, 0, 9)) +>A : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) + + A.#bar(30); +>A.#bar : Symbol(A.#bar, Decl(privateNamesAndStaticMethods.ts, 1, 29)) +>A : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) + + A.#bar(30); +>A.#bar : Symbol(A.#bar, Decl(privateNamesAndStaticMethods.ts, 1, 29)) +>A : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) + + A.#quux = A.#quux + 1; +>A.#quux : Symbol(A.#quux, Decl(privateNamesAndStaticMethods.ts, 6, 26), Decl(privateNamesAndStaticMethods.ts, 9, 5)) +>A : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) +>A.#quux : Symbol(A.#quux, Decl(privateNamesAndStaticMethods.ts, 6, 26), Decl(privateNamesAndStaticMethods.ts, 9, 5)) +>A : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) + + A.#quux++; +>A.#quux : Symbol(A.#quux, Decl(privateNamesAndStaticMethods.ts, 6, 26), Decl(privateNamesAndStaticMethods.ts, 9, 5)) +>A : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) + } +} + +class B extends A { +>B : Symbol(B, Decl(privateNamesAndStaticMethods.ts, 20, 1)) +>A : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) + + static #foo(a: string) {} +>#foo : Symbol(B.#foo, Decl(privateNamesAndStaticMethods.ts, 22, 19)) +>a : Symbol(a, Decl(privateNamesAndStaticMethods.ts, 23, 16)) + + constructor () { + super(); +>super : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) + + B.#foo("str"); +>B.#foo : Symbol(B.#foo, Decl(privateNamesAndStaticMethods.ts, 22, 19)) +>B : Symbol(B, Decl(privateNamesAndStaticMethods.ts, 20, 1)) + } +} + diff --git a/tests/baselines/reference/privateNamesAndStaticMethods.types b/tests/baselines/reference/privateNamesAndStaticMethods.types new file mode 100644 index 0000000000000..3a4a89dbd754d --- /dev/null +++ b/tests/baselines/reference/privateNamesAndStaticMethods.types @@ -0,0 +1,95 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticMethods.ts === +class A { +>A : A + + static #foo(a: number) {} +>#foo : (a: number) => void +>a : number + + static async #bar(a: number) {} +>#bar : (a: number) => Promise +>a : number + + static async *#baz(a: number) { +>#baz : (a: number) => AsyncIterableIterator +>a : number + + return 3; +>3 : 3 + } + static #_quux: number; +>#_quux : number + + static get #quux (): number { +>#quux : number + + return this.#_quux; +>this.#_quux : number +>this : typeof A + } + static set #quux (val: number) { +>#quux : number +>val : number + + this.#_quux = val; +>this.#_quux = val : number +>this.#_quux : number +>this : typeof A +>val : number + } + constructor () { + A.#foo(30); +>A.#foo(30) : void +>A.#foo : (a: number) => void +>A : typeof A +>30 : 30 + + A.#bar(30); +>A.#bar(30) : Promise +>A.#bar : (a: number) => Promise +>A : typeof A +>30 : 30 + + A.#bar(30); +>A.#bar(30) : Promise +>A.#bar : (a: number) => Promise +>A : typeof A +>30 : 30 + + A.#quux = A.#quux + 1; +>A.#quux = A.#quux + 1 : number +>A.#quux : number +>A : typeof A +>A.#quux + 1 : number +>A.#quux : number +>A : typeof A +>1 : 1 + + A.#quux++; +>A.#quux++ : number +>A.#quux : number +>A : typeof A + } +} + +class B extends A { +>B : B +>A : A + + static #foo(a: string) {} +>#foo : (a: string) => void +>a : string + + constructor () { + super(); +>super() : void +>super : typeof A + + B.#foo("str"); +>B.#foo("str") : void +>B.#foo : (a: string) => void +>B : typeof B +>"str" : "str" + } +} + diff --git a/tests/baselines/reference/privateNamesAndkeyof.js b/tests/baselines/reference/privateNamesAndkeyof.js new file mode 100644 index 0000000000000..eeaade8458fc7 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndkeyof.js @@ -0,0 +1,25 @@ +//// [privateNamesAndkeyof.ts] +// @target es6 + +class A { + #foo = 3; + bar = 3; + baz = 3; +} + +type T = keyof A // should not include '#foo' + + +//// [privateNamesAndkeyof.js] +// @target es6 +var _foo; +"use strict"; +var A = /** @class */ (function () { + function A() { + _foo.set(this, 3); + this.bar = 3; + this.baz = 3; + } + return A; +}()); +_foo = new WeakMap(); diff --git a/tests/baselines/reference/privateNamesAndkeyof.symbols b/tests/baselines/reference/privateNamesAndkeyof.symbols new file mode 100644 index 0000000000000..3b633505522a1 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndkeyof.symbols @@ -0,0 +1,20 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndkeyof.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNamesAndkeyof.ts, 0, 0)) + + #foo = 3; +>#foo : Symbol(A.#foo, Decl(privateNamesAndkeyof.ts, 2, 9)) + + bar = 3; +>bar : Symbol(A.bar, Decl(privateNamesAndkeyof.ts, 3, 13)) + + baz = 3; +>baz : Symbol(A.baz, Decl(privateNamesAndkeyof.ts, 4, 12)) +} + +type T = keyof A // should not include '#foo' +>T : Symbol(T, Decl(privateNamesAndkeyof.ts, 6, 1)) +>A : Symbol(A, Decl(privateNamesAndkeyof.ts, 0, 0)) + diff --git a/tests/baselines/reference/privateNamesAndkeyof.types b/tests/baselines/reference/privateNamesAndkeyof.types new file mode 100644 index 0000000000000..f8d3d99de7369 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndkeyof.types @@ -0,0 +1,22 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndkeyof.ts === +// @target es6 + +class A { +>A : A + + #foo = 3; +>#foo : number +>3 : 3 + + bar = 3; +>bar : number +>3 : 3 + + baz = 3; +>baz : number +>3 : 3 +} + +type T = keyof A // should not include '#foo' +>T : "bar" | "baz" + diff --git a/tests/baselines/reference/privateNamesInGenericClasses.errors.txt b/tests/baselines/reference/privateNamesInGenericClasses.errors.txt new file mode 100644 index 0000000000000..7e5435ffa2c58 --- /dev/null +++ b/tests/baselines/reference/privateNamesInGenericClasses.errors.txt @@ -0,0 +1,32 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts(10,3): error TS2339: Property '#foo' does not exist on type 'C'. +tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts(10,3): error TS18007: Property '#foo' is not accessible outside class 'C' because it has a private name. +tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts(11,1): error TS2322: Type 'C' is not assignable to type 'C'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts(12,1): error TS2322: Type 'C' is not assignable to type 'C'. + Type 'number' is not assignable to type 'string'. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts (4 errors) ==== + class C { + #foo: T; + bar(x: C) { return x.#foo; } // OK + baz(x: C) { return x.#foo; } // OK + quux(x: C) { return x.#foo; } // OK + } + + declare let a: C; + declare let b: C; + a.#foo; // Error + ~~~~ +!!! error TS2339: Property '#foo' does not exist on type 'C'. + ~~~~ +!!! error TS18007: Property '#foo' is not accessible outside class 'C' because it has a private name. + a = b; // Error + ~ +!!! error TS2322: Type 'C' is not assignable to type 'C'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. + b = a; // Error + ~ +!!! error TS2322: Type 'C' is not assignable to type 'C'. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesInGenericClasses.js b/tests/baselines/reference/privateNamesInGenericClasses.js new file mode 100644 index 0000000000000..e92f777e3b673 --- /dev/null +++ b/tests/baselines/reference/privateNamesInGenericClasses.js @@ -0,0 +1,31 @@ +//// [privateNamesInGenericClasses.ts] +class C { + #foo: T; + bar(x: C) { return x.#foo; } // OK + baz(x: C) { return x.#foo; } // OK + quux(x: C) { return x.#foo; } // OK +} + +declare let a: C; +declare let b: C; +a.#foo; // Error +a = b; // Error +b = a; // Error + + +//// [privateNamesInGenericClasses.js] +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _foo; +"use strict"; +class C { + constructor() { + _foo.set(this, void 0); + } + bar(x) { return _classPrivateFieldGet(x, _foo); } // OK + baz(x) { return _classPrivateFieldGet(x, _foo); } // OK + quux(x) { return _classPrivateFieldGet(x, _foo); } // OK +} +_foo = new WeakMap(); +a.#foo; // Error +a = b; // Error +b = a; // Error diff --git a/tests/baselines/reference/privateNamesInGenericClasses.symbols b/tests/baselines/reference/privateNamesInGenericClasses.symbols new file mode 100644 index 0000000000000..c697c06390869 --- /dev/null +++ b/tests/baselines/reference/privateNamesInGenericClasses.symbols @@ -0,0 +1,51 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts === +class C { +>C : Symbol(C, Decl(privateNamesInGenericClasses.ts, 0, 0)) +>T : Symbol(T, Decl(privateNamesInGenericClasses.ts, 0, 8)) + + #foo: T; +>#foo : Symbol(C.#foo, Decl(privateNamesInGenericClasses.ts, 0, 12)) +>T : Symbol(T, Decl(privateNamesInGenericClasses.ts, 0, 8)) + + bar(x: C) { return x.#foo; } // OK +>bar : Symbol(C.bar, Decl(privateNamesInGenericClasses.ts, 1, 12)) +>x : Symbol(x, Decl(privateNamesInGenericClasses.ts, 2, 8)) +>C : Symbol(C, Decl(privateNamesInGenericClasses.ts, 0, 0)) +>T : Symbol(T, Decl(privateNamesInGenericClasses.ts, 0, 8)) +>x.#foo : Symbol(C.#foo, Decl(privateNamesInGenericClasses.ts, 0, 12)) +>x : Symbol(x, Decl(privateNamesInGenericClasses.ts, 2, 8)) + + baz(x: C) { return x.#foo; } // OK +>baz : Symbol(C.baz, Decl(privateNamesInGenericClasses.ts, 2, 35)) +>x : Symbol(x, Decl(privateNamesInGenericClasses.ts, 3, 8)) +>C : Symbol(C, Decl(privateNamesInGenericClasses.ts, 0, 0)) +>x.#foo : Symbol(C.#foo, Decl(privateNamesInGenericClasses.ts, 0, 12)) +>x : Symbol(x, Decl(privateNamesInGenericClasses.ts, 3, 8)) + + quux(x: C) { return x.#foo; } // OK +>quux : Symbol(C.quux, Decl(privateNamesInGenericClasses.ts, 3, 40)) +>x : Symbol(x, Decl(privateNamesInGenericClasses.ts, 4, 9)) +>C : Symbol(C, Decl(privateNamesInGenericClasses.ts, 0, 0)) +>x.#foo : Symbol(C.#foo, Decl(privateNamesInGenericClasses.ts, 0, 12)) +>x : Symbol(x, Decl(privateNamesInGenericClasses.ts, 4, 9)) +} + +declare let a: C; +>a : Symbol(a, Decl(privateNamesInGenericClasses.ts, 7, 11)) +>C : Symbol(C, Decl(privateNamesInGenericClasses.ts, 0, 0)) + +declare let b: C; +>b : Symbol(b, Decl(privateNamesInGenericClasses.ts, 8, 11)) +>C : Symbol(C, Decl(privateNamesInGenericClasses.ts, 0, 0)) + +a.#foo; // Error +>a : Symbol(a, Decl(privateNamesInGenericClasses.ts, 7, 11)) + +a = b; // Error +>a : Symbol(a, Decl(privateNamesInGenericClasses.ts, 7, 11)) +>b : Symbol(b, Decl(privateNamesInGenericClasses.ts, 8, 11)) + +b = a; // Error +>b : Symbol(b, Decl(privateNamesInGenericClasses.ts, 8, 11)) +>a : Symbol(a, Decl(privateNamesInGenericClasses.ts, 7, 11)) + diff --git a/tests/baselines/reference/privateNamesInGenericClasses.types b/tests/baselines/reference/privateNamesInGenericClasses.types new file mode 100644 index 0000000000000..e0a29a45492c1 --- /dev/null +++ b/tests/baselines/reference/privateNamesInGenericClasses.types @@ -0,0 +1,46 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts === +class C { +>C : C + + #foo: T; +>#foo : T + + bar(x: C) { return x.#foo; } // OK +>bar : (x: C) => T +>x : C +>x.#foo : T +>x : C + + baz(x: C) { return x.#foo; } // OK +>baz : (x: C) => number +>x : C +>x.#foo : number +>x : C + + quux(x: C) { return x.#foo; } // OK +>quux : (x: C) => string +>x : C +>x.#foo : string +>x : C +} + +declare let a: C; +>a : C + +declare let b: C; +>b : C + +a.#foo; // Error +>a.#foo : any +>a : C + +a = b; // Error +>a = b : C +>a : C +>b : C + +b = a; // Error +>b = a : C +>b : C +>a : C + diff --git a/tests/baselines/reference/privateNamesInNestedClasses.errors.txt b/tests/baselines/reference/privateNamesInNestedClasses.errors.txt new file mode 100644 index 0000000000000..3f6efdf5155f8 --- /dev/null +++ b/tests/baselines/reference/privateNamesInNestedClasses.errors.txt @@ -0,0 +1,36 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesInNestedClasses.ts(13,18): error TS2339: Property '#foo' does not exist on type 'A'. +tests/cases/conformance/classes/members/privateNames/privateNamesInNestedClasses.ts(13,18): error TS18008: This usage of '#foo' refers to the private member declared in its enclosing class. While type 'B' has a private member with the same spelling, its declaration and accessibility are distinct. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesInNestedClasses.ts (2 errors) ==== + // @target es6 + + class A { + #foo = "A's #foo"; + #bar = "A's #bar"; + method () { + class B { + #foo = "B's #foo"; + bar (a: any) { + a.#foo; // OK, no compile-time error, don't know what `a` is + } + baz (a: A) { + a.#foo; // compile-time error, shadowed + ~~~~ +!!! error TS2339: Property '#foo' does not exist on type 'A'. + ~~~~ +!!! error TS18008: This usage of '#foo' refers to the private member declared in its enclosing class. While type 'B' has a private member with the same spelling, its declaration and accessibility are distinct. + } + quux (b: B) { + b.#foo; // OK + } + } + const a = new A(); + new B().bar(a); + new B().baz(a); + const b = new B(); + new B().quux(b); + } + } + + new A().method(); \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesInNestedClasses.js b/tests/baselines/reference/privateNamesInNestedClasses.js new file mode 100644 index 0000000000000..021528ae47be5 --- /dev/null +++ b/tests/baselines/reference/privateNamesInNestedClasses.js @@ -0,0 +1,67 @@ +//// [privateNamesInNestedClasses.ts] +// @target es6 + +class A { + #foo = "A's #foo"; + #bar = "A's #bar"; + method () { + class B { + #foo = "B's #foo"; + bar (a: any) { + a.#foo; // OK, no compile-time error, don't know what `a` is + } + baz (a: A) { + a.#foo; // compile-time error, shadowed + } + quux (b: B) { + b.#foo; // OK + } + } + const a = new A(); + new B().bar(a); + new B().baz(a); + const b = new B(); + new B().quux(b); + } +} + +new A().method(); + +//// [privateNamesInNestedClasses.js] +// @target es6 +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _foo, _bar; +"use strict"; +var A = /** @class */ (function () { + function A() { + _foo.set(this, "A's #foo"); + _bar.set(this, "A's #bar"); + } + A.prototype.method = function () { + var _foo_1; + var B = /** @class */ (function () { + function B() { + _foo_1.set(this, "B's #foo"); + } + B.prototype.bar = function (a) { + _classPrivateFieldGet(a, _foo_1); // OK, no compile-time error, don't know what `a` is + }; + B.prototype.baz = function (a) { + _classPrivateFieldGet(a, _foo_1); // compile-time error, shadowed + }; + B.prototype.quux = function (b) { + _classPrivateFieldGet(b, _foo_1); // OK + }; + return B; + }()); + _foo_1 = new WeakMap(); + var a = new A(); + new B().bar(a); + new B().baz(a); + var b = new B(); + new B().quux(b); + }; + return A; +}()); +_foo = new WeakMap(), _bar = new WeakMap(); +new A().method(); diff --git a/tests/baselines/reference/privateNamesInNestedClasses.symbols b/tests/baselines/reference/privateNamesInNestedClasses.symbols new file mode 100644 index 0000000000000..14eaae87aa402 --- /dev/null +++ b/tests/baselines/reference/privateNamesInNestedClasses.symbols @@ -0,0 +1,79 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesInNestedClasses.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNamesInNestedClasses.ts, 0, 0)) + + #foo = "A's #foo"; +>#foo : Symbol(A.#foo, Decl(privateNamesInNestedClasses.ts, 2, 9)) + + #bar = "A's #bar"; +>#bar : Symbol(A.#bar, Decl(privateNamesInNestedClasses.ts, 3, 21)) + + method () { +>method : Symbol(A.method, Decl(privateNamesInNestedClasses.ts, 4, 21)) + + class B { +>B : Symbol(B, Decl(privateNamesInNestedClasses.ts, 5, 14)) + + #foo = "B's #foo"; +>#foo : Symbol(B.#foo, Decl(privateNamesInNestedClasses.ts, 6, 16)) + + bar (a: any) { +>bar : Symbol(B.bar, Decl(privateNamesInNestedClasses.ts, 7, 29)) +>a : Symbol(a, Decl(privateNamesInNestedClasses.ts, 8, 16)) + + a.#foo; // OK, no compile-time error, don't know what `a` is +>a : Symbol(a, Decl(privateNamesInNestedClasses.ts, 8, 16)) + } + baz (a: A) { +>baz : Symbol(B.baz, Decl(privateNamesInNestedClasses.ts, 10, 12)) +>a : Symbol(a, Decl(privateNamesInNestedClasses.ts, 11, 16)) +>A : Symbol(A, Decl(privateNamesInNestedClasses.ts, 0, 0)) + + a.#foo; // compile-time error, shadowed +>a : Symbol(a, Decl(privateNamesInNestedClasses.ts, 11, 16)) + } + quux (b: B) { +>quux : Symbol(B.quux, Decl(privateNamesInNestedClasses.ts, 13, 12)) +>b : Symbol(b, Decl(privateNamesInNestedClasses.ts, 14, 17)) +>B : Symbol(B, Decl(privateNamesInNestedClasses.ts, 5, 14)) + + b.#foo; // OK +>b.#foo : Symbol(B.#foo, Decl(privateNamesInNestedClasses.ts, 6, 16)) +>b : Symbol(b, Decl(privateNamesInNestedClasses.ts, 14, 17)) + } + } + const a = new A(); +>a : Symbol(a, Decl(privateNamesInNestedClasses.ts, 18, 12)) +>A : Symbol(A, Decl(privateNamesInNestedClasses.ts, 0, 0)) + + new B().bar(a); +>new B().bar : Symbol(B.bar, Decl(privateNamesInNestedClasses.ts, 7, 29)) +>B : Symbol(B, Decl(privateNamesInNestedClasses.ts, 5, 14)) +>bar : Symbol(B.bar, Decl(privateNamesInNestedClasses.ts, 7, 29)) +>a : Symbol(a, Decl(privateNamesInNestedClasses.ts, 18, 12)) + + new B().baz(a); +>new B().baz : Symbol(B.baz, Decl(privateNamesInNestedClasses.ts, 10, 12)) +>B : Symbol(B, Decl(privateNamesInNestedClasses.ts, 5, 14)) +>baz : Symbol(B.baz, Decl(privateNamesInNestedClasses.ts, 10, 12)) +>a : Symbol(a, Decl(privateNamesInNestedClasses.ts, 18, 12)) + + const b = new B(); +>b : Symbol(b, Decl(privateNamesInNestedClasses.ts, 21, 12)) +>B : Symbol(B, Decl(privateNamesInNestedClasses.ts, 5, 14)) + + new B().quux(b); +>new B().quux : Symbol(B.quux, Decl(privateNamesInNestedClasses.ts, 13, 12)) +>B : Symbol(B, Decl(privateNamesInNestedClasses.ts, 5, 14)) +>quux : Symbol(B.quux, Decl(privateNamesInNestedClasses.ts, 13, 12)) +>b : Symbol(b, Decl(privateNamesInNestedClasses.ts, 21, 12)) + } +} + +new A().method(); +>new A().method : Symbol(A.method, Decl(privateNamesInNestedClasses.ts, 4, 21)) +>A : Symbol(A, Decl(privateNamesInNestedClasses.ts, 0, 0)) +>method : Symbol(A.method, Decl(privateNamesInNestedClasses.ts, 4, 21)) + diff --git a/tests/baselines/reference/privateNamesInNestedClasses.types b/tests/baselines/reference/privateNamesInNestedClasses.types new file mode 100644 index 0000000000000..12986429358da --- /dev/null +++ b/tests/baselines/reference/privateNamesInNestedClasses.types @@ -0,0 +1,92 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesInNestedClasses.ts === +// @target es6 + +class A { +>A : A + + #foo = "A's #foo"; +>#foo : string +>"A's #foo" : "A's #foo" + + #bar = "A's #bar"; +>#bar : string +>"A's #bar" : "A's #bar" + + method () { +>method : () => void + + class B { +>B : B + + #foo = "B's #foo"; +>#foo : string +>"B's #foo" : "B's #foo" + + bar (a: any) { +>bar : (a: any) => void +>a : any + + a.#foo; // OK, no compile-time error, don't know what `a` is +>a.#foo : any +>a : any + } + baz (a: A) { +>baz : (a: A) => void +>a : A + + a.#foo; // compile-time error, shadowed +>a.#foo : any +>a : A + } + quux (b: B) { +>quux : (b: B) => void +>b : B + + b.#foo; // OK +>b.#foo : string +>b : B + } + } + const a = new A(); +>a : A +>new A() : A +>A : typeof A + + new B().bar(a); +>new B().bar(a) : void +>new B().bar : (a: any) => void +>new B() : B +>B : typeof B +>bar : (a: any) => void +>a : A + + new B().baz(a); +>new B().baz(a) : void +>new B().baz : (a: A) => void +>new B() : B +>B : typeof B +>baz : (a: A) => void +>a : A + + const b = new B(); +>b : B +>new B() : B +>B : typeof B + + new B().quux(b); +>new B().quux(b) : void +>new B().quux : (b: B) => void +>new B() : B +>B : typeof B +>quux : (b: B) => void +>b : B + } +} + +new A().method(); +>new A().method() : void +>new A().method : () => void +>new A() : A +>A : typeof A +>method : () => void + diff --git a/tests/baselines/reference/privateNamesNoAccessibilityModifiers.errors.txt b/tests/baselines/reference/privateNamesNoAccessibilityModifiers.errors.txt new file mode 100644 index 0000000000000..751ddafa1c669 --- /dev/null +++ b/tests/baselines/reference/privateNamesNoAccessibilityModifiers.errors.txt @@ -0,0 +1,21 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts(4,12): error TS18004: Accessibility modifiers cannot be used with private names. +tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts(5,13): error TS18004: Accessibility modifiers cannot be used with private names. +tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts(6,15): error TS18004: Accessibility modifiers cannot be used with private names. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts (3 errors) ==== + // @target es6 + + class A { + public #foo = 3; // Error + ~~~~ +!!! error TS18004: Accessibility modifiers cannot be used with private names. + private #bar = 3; // Error + ~~~~ +!!! error TS18004: Accessibility modifiers cannot be used with private names. + protected #baz = 3; // Error + ~~~~ +!!! error TS18004: Accessibility modifiers cannot be used with private names. + readonly #qux = 3; // OK + } + \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesNoAccessibilityModifiers.js b/tests/baselines/reference/privateNamesNoAccessibilityModifiers.js new file mode 100644 index 0000000000000..23e102b0fa7d7 --- /dev/null +++ b/tests/baselines/reference/privateNamesNoAccessibilityModifiers.js @@ -0,0 +1,25 @@ +//// [privateNamesNoAccessibilityModifiers.ts] +// @target es6 + +class A { + public #foo = 3; // Error + private #bar = 3; // Error + protected #baz = 3; // Error + readonly #qux = 3; // OK +} + + +//// [privateNamesNoAccessibilityModifiers.js] +// @target es6 +var _foo, _bar, _baz, _qux; +"use strict"; +var A = /** @class */ (function () { + function A() { + _foo.set(this, 3); // Error + _bar.set(this, 3); // Error + _baz.set(this, 3); // Error + _qux.set(this, 3); // OK + } + return A; +}()); +_foo = new WeakMap(), _bar = new WeakMap(), _baz = new WeakMap(), _qux = new WeakMap(); diff --git a/tests/baselines/reference/privateNamesNoAccessibilityModifiers.symbols b/tests/baselines/reference/privateNamesNoAccessibilityModifiers.symbols new file mode 100644 index 0000000000000..49bd89a39842a --- /dev/null +++ b/tests/baselines/reference/privateNamesNoAccessibilityModifiers.symbols @@ -0,0 +1,19 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNamesNoAccessibilityModifiers.ts, 0, 0)) + + public #foo = 3; // Error +>#foo : Symbol(A.#foo, Decl(privateNamesNoAccessibilityModifiers.ts, 2, 9)) + + private #bar = 3; // Error +>#bar : Symbol(A.#bar, Decl(privateNamesNoAccessibilityModifiers.ts, 3, 20)) + + protected #baz = 3; // Error +>#baz : Symbol(A.#baz, Decl(privateNamesNoAccessibilityModifiers.ts, 4, 21)) + + readonly #qux = 3; // OK +>#qux : Symbol(A.#qux, Decl(privateNamesNoAccessibilityModifiers.ts, 5, 23)) +} + diff --git a/tests/baselines/reference/privateNamesNoAccessibilityModifiers.types b/tests/baselines/reference/privateNamesNoAccessibilityModifiers.types new file mode 100644 index 0000000000000..d727c9a2f2dc3 --- /dev/null +++ b/tests/baselines/reference/privateNamesNoAccessibilityModifiers.types @@ -0,0 +1,23 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts === +// @target es6 + +class A { +>A : A + + public #foo = 3; // Error +>#foo : number +>3 : 3 + + private #bar = 3; // Error +>#bar : number +>3 : 3 + + protected #baz = 3; // Error +>#baz : number +>3 : 3 + + readonly #qux = 3; // OK +>#qux : 3 +>3 : 3 +} + diff --git a/tests/baselines/reference/privateNamesNoConflictWhenInheriting.js b/tests/baselines/reference/privateNamesNoConflictWhenInheriting.js new file mode 100644 index 0000000000000..f54b9d2f8cd6d --- /dev/null +++ b/tests/baselines/reference/privateNamesNoConflictWhenInheriting.js @@ -0,0 +1,49 @@ +//// [privateNamesNoConflictWhenInheriting.ts] +// @target es6 + +class A { + #foo: number; +} + +class B extends A { + #foo: string; // OK: private names are unique to each class +} + +const b: A = new B() // OK + + +//// [privateNamesNoConflictWhenInheriting.js] +// @target es6 +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 (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var _foo, _foo_1; +"use strict"; +var A = /** @class */ (function () { + function A() { + _foo.set(this, void 0); + } + return A; +}()); +_foo = new WeakMap(); +var B = /** @class */ (function (_super) { + __extends(B, _super); + function B() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _foo_1.set(_this, void 0); // OK: private names are unique to each class + return _this; + } + return B; +}(A)); +_foo_1 = new WeakMap(); +var b = new B(); // OK diff --git a/tests/baselines/reference/privateNamesNoConflictWhenInheriting.symbols b/tests/baselines/reference/privateNamesNoConflictWhenInheriting.symbols new file mode 100644 index 0000000000000..d1442d5750cd5 --- /dev/null +++ b/tests/baselines/reference/privateNamesNoConflictWhenInheriting.symbols @@ -0,0 +1,23 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNoConflictWhenInheriting.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNamesNoConflictWhenInheriting.ts, 0, 0)) + + #foo: number; +>#foo : Symbol(A.#foo, Decl(privateNamesNoConflictWhenInheriting.ts, 2, 9)) +} + +class B extends A { +>B : Symbol(B, Decl(privateNamesNoConflictWhenInheriting.ts, 4, 1)) +>A : Symbol(A, Decl(privateNamesNoConflictWhenInheriting.ts, 0, 0)) + + #foo: string; // OK: private names are unique to each class +>#foo : Symbol(B.#foo, Decl(privateNamesNoConflictWhenInheriting.ts, 6, 19)) +} + +const b: A = new B() // OK +>b : Symbol(b, Decl(privateNamesNoConflictWhenInheriting.ts, 10, 5)) +>A : Symbol(A, Decl(privateNamesNoConflictWhenInheriting.ts, 0, 0)) +>B : Symbol(B, Decl(privateNamesNoConflictWhenInheriting.ts, 4, 1)) + diff --git a/tests/baselines/reference/privateNamesNoConflictWhenInheriting.types b/tests/baselines/reference/privateNamesNoConflictWhenInheriting.types new file mode 100644 index 0000000000000..fd88a20816e15 --- /dev/null +++ b/tests/baselines/reference/privateNamesNoConflictWhenInheriting.types @@ -0,0 +1,23 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNoConflictWhenInheriting.ts === +// @target es6 + +class A { +>A : A + + #foo: number; +>#foo : number +} + +class B extends A { +>B : B +>A : A + + #foo: string; // OK: private names are unique to each class +>#foo : string +} + +const b: A = new B() // OK +>b : A +>new B() : B +>B : typeof B + diff --git a/tests/baselines/reference/privateNamesNoDelete.errors.txt b/tests/baselines/reference/privateNamesNoDelete.errors.txt new file mode 100644 index 0000000000000..f490c83c6bffb --- /dev/null +++ b/tests/baselines/reference/privateNamesNoDelete.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts(6,16): error TS18005: The operand of a delete operator cannot be a private name. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts (1 errors) ==== + // @target es6 + + class A { + #v = 1; + constructor() { + delete this.#v; // Error: The operand of a delete operator cannot be a private name. + ~~~~~~~ +!!! error TS18005: The operand of a delete operator cannot be a private name. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesNoDelete.js b/tests/baselines/reference/privateNamesNoDelete.js new file mode 100644 index 0000000000000..b7826b3aea2f4 --- /dev/null +++ b/tests/baselines/reference/privateNamesNoDelete.js @@ -0,0 +1,24 @@ +//// [privateNamesNoDelete.ts] +// @target es6 + +class A { + #v = 1; + constructor() { + delete this.#v; // Error: The operand of a delete operator cannot be a private name. + } +} + + +//// [privateNamesNoDelete.js] +// @target es6 +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _v; +"use strict"; +var A = /** @class */ (function () { + function A() { + _v.set(this, 1); + delete _classPrivateFieldGet(this, _v); // Error: The operand of a delete operator cannot be a private name. + } + return A; +}()); +_v = new WeakMap(); diff --git a/tests/baselines/reference/privateNamesNoDelete.symbols b/tests/baselines/reference/privateNamesNoDelete.symbols new file mode 100644 index 0000000000000..50e2542c07877 --- /dev/null +++ b/tests/baselines/reference/privateNamesNoDelete.symbols @@ -0,0 +1,16 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNamesNoDelete.ts, 0, 0)) + + #v = 1; +>#v : Symbol(A.#v, Decl(privateNamesNoDelete.ts, 2, 9)) + + constructor() { + delete this.#v; // Error: The operand of a delete operator cannot be a private name. +>this.#v : Symbol(A.#v, Decl(privateNamesNoDelete.ts, 2, 9)) +>this : Symbol(A, Decl(privateNamesNoDelete.ts, 0, 0)) + } +} + diff --git a/tests/baselines/reference/privateNamesNoDelete.types b/tests/baselines/reference/privateNamesNoDelete.types new file mode 100644 index 0000000000000..681651a4f770a --- /dev/null +++ b/tests/baselines/reference/privateNamesNoDelete.types @@ -0,0 +1,18 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts === +// @target es6 + +class A { +>A : A + + #v = 1; +>#v : number +>1 : 1 + + constructor() { + delete this.#v; // Error: The operand of a delete operator cannot be a private name. +>delete this.#v : boolean +>this.#v : number +>this : this + } +} + diff --git a/tests/baselines/reference/privateNamesNotAllowedAsParameters.errors.txt b/tests/baselines/reference/privateNamesNotAllowedAsParameters.errors.txt new file mode 100644 index 0000000000000..942bea1e251a8 --- /dev/null +++ b/tests/baselines/reference/privateNamesNotAllowedAsParameters.errors.txt @@ -0,0 +1,21 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts(4,12): error TS1138: Parameter declaration expected. +tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts(4,24): error TS1005: ';' expected. +tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts(4,26): error TS1068: Unexpected token. A constructor, method, accessor, or property was expected. +tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts(5,1): error TS1128: Declaration or statement expected. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts (4 errors) ==== + // @target es6 + + class A { + setFoo(#foo: string) {} + ~~~~ +!!! error TS1138: Parameter declaration expected. + ~ +!!! error TS1005: ';' expected. + ~ +!!! error TS1068: Unexpected token. A constructor, method, accessor, or property was expected. + } + ~ +!!! error TS1128: Declaration or statement expected. + \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesNotAllowedAsParameters.js b/tests/baselines/reference/privateNamesNotAllowedAsParameters.js new file mode 100644 index 0000000000000..ab41d7579b42d --- /dev/null +++ b/tests/baselines/reference/privateNamesNotAllowedAsParameters.js @@ -0,0 +1,20 @@ +//// [privateNamesNotAllowedAsParameters.ts] +// @target es6 + +class A { + setFoo(#foo: string) {} +} + + +//// [privateNamesNotAllowedAsParameters.js] +// @target es6 +var _foo; +var A = /** @class */ (function () { + function A() { + _foo.set(this, void 0); + } + A.prototype.setFoo = function () { }; + return A; +}()); +_foo = new WeakMap(); +{ } diff --git a/tests/baselines/reference/privateNamesNotAllowedAsParameters.symbols b/tests/baselines/reference/privateNamesNotAllowedAsParameters.symbols new file mode 100644 index 0000000000000..b7ea0b4850fb9 --- /dev/null +++ b/tests/baselines/reference/privateNamesNotAllowedAsParameters.symbols @@ -0,0 +1,11 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNamesNotAllowedAsParameters.ts, 0, 0)) + + setFoo(#foo: string) {} +>setFoo : Symbol(A.setFoo, Decl(privateNamesNotAllowedAsParameters.ts, 2, 9)) +>#foo : Symbol(A.#foo, Decl(privateNamesNotAllowedAsParameters.ts, 3, 11)) +} + diff --git a/tests/baselines/reference/privateNamesNotAllowedAsParameters.types b/tests/baselines/reference/privateNamesNotAllowedAsParameters.types new file mode 100644 index 0000000000000..effe8726a9470 --- /dev/null +++ b/tests/baselines/reference/privateNamesNotAllowedAsParameters.types @@ -0,0 +1,11 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts === +// @target es6 + +class A { +>A : A + + setFoo(#foo: string) {} +>setFoo : () => any +>#foo : string +} + diff --git a/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.errors.txt b/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.errors.txt new file mode 100644 index 0000000000000..5d79de2754392 --- /dev/null +++ b/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts(3,7): error TS1134: Variable declaration expected. +tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts(3,12): error TS1134: Variable declaration expected. +tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts(3,14): error TS1134: Variable declaration expected. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts (3 errors) ==== + // @target es6 + + const #foo = 3; + ~~~~ +!!! error TS1134: Variable declaration expected. + ~ +!!! error TS1134: Variable declaration expected. + ~ +!!! error TS1134: Variable declaration expected. \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.js b/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.js new file mode 100644 index 0000000000000..3a5f19724d38e --- /dev/null +++ b/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.js @@ -0,0 +1,10 @@ +//// [privateNamesNotAllowedInVariableDeclarations.ts] +// @target es6 + +const #foo = 3; + +//// [privateNamesNotAllowedInVariableDeclarations.js] +"use strict"; +// @target es6 +var ; +3; diff --git a/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.symbols b/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.symbols new file mode 100644 index 0000000000000..8a90d43a114c9 --- /dev/null +++ b/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.symbols @@ -0,0 +1,5 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts === +// @target es6 +No type information for this code. +No type information for this code.const #foo = 3; +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.types b/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.types new file mode 100644 index 0000000000000..1def5f332d291 --- /dev/null +++ b/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.types @@ -0,0 +1,6 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts === +// @target es6 + +const #foo = 3; +>3 : 3 + diff --git a/tests/baselines/reference/privateNamesUnique.errors.txt b/tests/baselines/reference/privateNamesUnique.errors.txt new file mode 100644 index 0000000000000..0c3b1ef188c17 --- /dev/null +++ b/tests/baselines/reference/privateNamesUnique.errors.txt @@ -0,0 +1,20 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesUnique.ts(11,7): error TS2322: Type 'B' is not assignable to type 'A'. + Property '#foo' is missing in type 'B'. While type 'B' has a private member with the same spelling, its declaration and accessibility are distinct. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesUnique.ts (1 errors) ==== + // @target es6 + + class A { + #foo: number; + } + + class B { + #foo: number; + } + + const b: A = new B(); // Error: Property #foo is missing + ~ +!!! error TS2322: Type 'B' is not assignable to type 'A'. +!!! error TS2322: Property '#foo' is missing in type 'B'. While type 'B' has a private member with the same spelling, its declaration and accessibility are distinct. + \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesUnique.js b/tests/baselines/reference/privateNamesUnique.js new file mode 100644 index 0000000000000..a55fe8af1faa1 --- /dev/null +++ b/tests/baselines/reference/privateNamesUnique.js @@ -0,0 +1,33 @@ +//// [privateNamesUnique.ts] +// @target es6 + +class A { + #foo: number; +} + +class B { + #foo: number; +} + +const b: A = new B(); // Error: Property #foo is missing + + +//// [privateNamesUnique.js] +// @target es6 +var _foo, _foo_1; +"use strict"; +var A = /** @class */ (function () { + function A() { + _foo.set(this, void 0); + } + return A; +}()); +_foo = new WeakMap(); +var B = /** @class */ (function () { + function B() { + _foo_1.set(this, void 0); + } + return B; +}()); +_foo_1 = new WeakMap(); +var b = new B(); // Error: Property #foo is missing diff --git a/tests/baselines/reference/privateNamesUnique.symbols b/tests/baselines/reference/privateNamesUnique.symbols new file mode 100644 index 0000000000000..5266e47918187 --- /dev/null +++ b/tests/baselines/reference/privateNamesUnique.symbols @@ -0,0 +1,22 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesUnique.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNamesUnique.ts, 0, 0)) + + #foo: number; +>#foo : Symbol(A.#foo, Decl(privateNamesUnique.ts, 2, 9)) +} + +class B { +>B : Symbol(B, Decl(privateNamesUnique.ts, 4, 1)) + + #foo: number; +>#foo : Symbol(B.#foo, Decl(privateNamesUnique.ts, 6, 9)) +} + +const b: A = new B(); // Error: Property #foo is missing +>b : Symbol(b, Decl(privateNamesUnique.ts, 10, 5)) +>A : Symbol(A, Decl(privateNamesUnique.ts, 0, 0)) +>B : Symbol(B, Decl(privateNamesUnique.ts, 4, 1)) + diff --git a/tests/baselines/reference/privateNamesUnique.types b/tests/baselines/reference/privateNamesUnique.types new file mode 100644 index 0000000000000..a9d738ee0ca5b --- /dev/null +++ b/tests/baselines/reference/privateNamesUnique.types @@ -0,0 +1,22 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesUnique.ts === +// @target es6 + +class A { +>A : A + + #foo: number; +>#foo : number +} + +class B { +>B : B + + #foo: number; +>#foo : number +} + +const b: A = new B(); // Error: Property #foo is missing +>b : A +>new B() : B +>B : typeof B + diff --git a/tests/baselines/reference/shebangError.errors.txt b/tests/baselines/reference/shebangError.errors.txt index cba74ceaed75e..ecfc0ac5eab6e 100644 --- a/tests/baselines/reference/shebangError.errors.txt +++ b/tests/baselines/reference/shebangError.errors.txt @@ -1,14 +1,17 @@ -tests/cases/compiler/shebangError.ts(2,1): error TS1127: Invalid character. +tests/cases/compiler/shebangError.ts(2,1): error TS1128: Declaration or statement expected. +tests/cases/compiler/shebangError.ts(2,2): error TS1127: Invalid character. tests/cases/compiler/shebangError.ts(2,2): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type. tests/cases/compiler/shebangError.ts(2,12): error TS2304: Cannot find name 'env'. tests/cases/compiler/shebangError.ts(2,16): error TS1005: ';' expected. tests/cases/compiler/shebangError.ts(2,16): error TS2304: Cannot find name 'node'. -==== tests/cases/compiler/shebangError.ts (5 errors) ==== +==== tests/cases/compiler/shebangError.ts (6 errors) ==== var foo = 'Shebang is only allowed on the first line'; #!/usr/bin/env node - + ~ +!!! error TS1128: Declaration or statement expected. + !!! error TS1127: Invalid character. ~~~~~~~~~ !!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type. diff --git a/tests/baselines/reference/systemModuleTargetES6.js b/tests/baselines/reference/systemModuleTargetES6.js index 943e57ff742ac..0df2835683e82 100644 --- a/tests/baselines/reference/systemModuleTargetES6.js +++ b/tests/baselines/reference/systemModuleTargetES6.js @@ -35,8 +35,8 @@ System.register([], function (exports_1, context_1) { MyClass2 = class MyClass2 { static getInstance() { return MyClass2.value; } }; - MyClass2.value = 42; exports_1("MyClass2", MyClass2); + MyClass2.value = 42; } }; }); diff --git a/tests/baselines/reference/variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.js b/tests/baselines/reference/variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.js index f2a1df5e7072a..4bb3c19f9c890 100644 --- a/tests/baselines/reference/variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.js +++ b/tests/baselines/reference/variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.js @@ -16,8 +16,8 @@ var Foo = /** @class */ (function () { } return Foo; }()); -_a = key; exports.Foo = Foo; +_a = key; //// [variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.d.ts] diff --git a/tests/cases/compiler/parseErrorInHeritageClause1.ts b/tests/cases/compiler/parseErrorInHeritageClause1.ts index 84223192c7ad1..5c4a21e4f9371 100644 --- a/tests/cases/compiler/parseErrorInHeritageClause1.ts +++ b/tests/cases/compiler/parseErrorInHeritageClause1.ts @@ -1,2 +1,2 @@ -class C extends A # { -} \ No newline at end of file +class C extends A ¬ { +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts b/tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts new file mode 100644 index 0000000000000..1f5da9ab9171e --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts @@ -0,0 +1,9 @@ +// @strict: true +// @target es6 + +class A { + [k: string]: any; + constructor(message: string) { + this.#f = 3 // Error Property '#f' does not exist on type 'A'. + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameConstructorReserved.ts b/tests/cases/conformance/classes/members/privateNames/privateNameConstructorReserved.ts new file mode 100644 index 0000000000000..1421db99944d8 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameConstructorReserved.ts @@ -0,0 +1,5 @@ +// @target es6 + +class A { + #constructor() {} // Error: `#constructor` is a reserved word. +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameDeclaration.ts b/tests/cases/conformance/classes/members/privateNames/privateNameDeclaration.ts new file mode 100644 index 0000000000000..e111e4af3d614 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameDeclaration.ts @@ -0,0 +1,3 @@ +class A { + #name: string; +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameDuplicateField.ts b/tests/cases/conformance/classes/members/privateNames/privateNameDuplicateField.ts new file mode 100644 index 0000000000000..ba8160cb122ab --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameDuplicateField.ts @@ -0,0 +1,7 @@ +// @strict: true +// @target es6 + +class A { + #foo = "foo"; + #foo = "foo"; +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameField.ts b/tests/cases/conformance/classes/members/privateNames/privateNameField.ts new file mode 100644 index 0000000000000..d4b823c49da63 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameField.ts @@ -0,0 +1,9 @@ +// @strict: true +// @target es6 + +class A { + #name: string; + constructor(name: string) { + this.#name = name; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameFieldAccess.ts b/tests/cases/conformance/classes/members/privateNames/privateNameFieldAccess.ts new file mode 100644 index 0000000000000..42b30a058dc03 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameFieldAccess.ts @@ -0,0 +1,6 @@ +class A { + #myField = "hello world"; + constructor() { + console.log(this.#myField); + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameFieldAssignment.ts b/tests/cases/conformance/classes/members/privateNames/privateNameFieldAssignment.ts new file mode 100644 index 0000000000000..c4551908427b9 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameFieldAssignment.ts @@ -0,0 +1,34 @@ +class A { + #field = 0; + constructor() { + this.#field = 1; + this.#field += 2; + this.#field -= 3; + this.#field /= 4; + this.#field *= 5; + this.#field **= 6; + this.#field %= 7; + this.#field <<= 8; + this.#field >>= 9; + this.#field >>>= 10; + this.#field &= 11; + this.#field |= 12; + this.#field ^= 13; + A.getInstance().#field = 1; + A.getInstance().#field += 2; + A.getInstance().#field -= 3; + A.getInstance().#field /= 4; + A.getInstance().#field *= 5; + A.getInstance().#field **= 6; + A.getInstance().#field %= 7; + A.getInstance().#field <<= 8; + A.getInstance().#field >>= 9; + A.getInstance().#field >>>= 10; + A.getInstance().#field &= 11; + A.getInstance().#field |= 12; + A.getInstance().#field ^= 13; + } + static getInstance() { + return new A(); + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameFieldCallExpression.ts b/tests/cases/conformance/classes/members/privateNames/privateNameFieldCallExpression.ts new file mode 100644 index 0000000000000..8feb41dbeb081 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameFieldCallExpression.ts @@ -0,0 +1,9 @@ +class A { + #fieldFunc = () => this.x = 10; + x = 1; + test() { + this.#fieldFunc(); + const func = this.#fieldFunc; + func(); + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameFieldDestructuredBinding.ts b/tests/cases/conformance/classes/members/privateNames/privateNameFieldDestructuredBinding.ts new file mode 100644 index 0000000000000..e68d32e8bdb56 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameFieldDestructuredBinding.ts @@ -0,0 +1,14 @@ +class A { + #field = 1; + testObject() { + return { x: 10, y: 6 }; + } + testArray() { + return [10, 11]; + } + constructor() { + let y: number; + ({ x: this.#field, y } = this.testObject()); + ([this.#field, y] = this.testArray()); + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameFieldInitializer.ts b/tests/cases/conformance/classes/members/privateNames/privateNameFieldInitializer.ts new file mode 100644 index 0000000000000..fa58a79d9f993 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameFieldInitializer.ts @@ -0,0 +1,4 @@ +class A { + #field = 10; + #uninitialized; +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameFieldUnaryMutation.ts b/tests/cases/conformance/classes/members/privateNames/privateNameFieldUnaryMutation.ts new file mode 100644 index 0000000000000..84dd6da2ec4d9 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameFieldUnaryMutation.ts @@ -0,0 +1,16 @@ +class C { + #test: number = 24; + constructor() { + this.#test++; + this.#test--; + ++this.#test; + --this.#test; + } + test() { + this.getInstance().#test++; + this.getInstance().#test--; + ++this.getInstance().#test; + --this.getInstance().#test; + } + getInstance() { return new C(); } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-1.ts b/tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-1.ts new file mode 100644 index 0000000000000..04c75fda5f841 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-1.ts @@ -0,0 +1,3 @@ +const obj = { + #foo: 1 +}; diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-2.ts b/tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-2.ts new file mode 100644 index 0000000000000..3356e7a957b1f --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-2.ts @@ -0,0 +1,5 @@ +const obj = { + #foo() { + + } +}; diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameNestedClassNameConflict.ts b/tests/cases/conformance/classes/members/privateNames/privateNameNestedClassNameConflict.ts new file mode 100644 index 0000000000000..ba0bbe1b8c7f9 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameNestedClassNameConflict.ts @@ -0,0 +1,8 @@ +class A { + #foo: string; + constructor() { + class A { + #foo: string; + } + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts b/tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts new file mode 100644 index 0000000000000..6f14d0ec8d72e --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts @@ -0,0 +1,8 @@ +// @strict: true +// @target es6 + +class A { + #foo: number = 3; +} + +new A().#foo = 4; // Error diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts b/tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts new file mode 100644 index 0000000000000..26aacc421a19a --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts @@ -0,0 +1,4 @@ +// @strict: true +// @target es6 + +const #foo = 3; \ No newline at end of file diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameSneakyRuntimeException.ts b/tests/cases/conformance/classes/members/privateNames/privateNameSneakyRuntimeException.ts new file mode 100644 index 0000000000000..f4450f031ab75 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameSneakyRuntimeException.ts @@ -0,0 +1,16 @@ +// @strict: true +// @target es6 + +function createClass () { + return class { + #foo = 3; + equals(other: any) { + return this.#foo = other.#foo; + } + }; +} + +const a = new (createClass())(); +const b = new (createClass())(); + +console.log(a.equals(b)); // OK at compile time but will be a runtime error diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesAndDecorators.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesAndDecorators.ts new file mode 100644 index 0000000000000..d82e05ef9735e --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesAndDecorators.ts @@ -0,0 +1,8 @@ +declare function dec(target: T): T; + +class A { + @dec // Error + #foo = 1; + @dec // Error + #bar(): void { } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesAndFields.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesAndFields.ts new file mode 100644 index 0000000000000..ebf44118093aa --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesAndFields.ts @@ -0,0 +1,17 @@ +// @strict: true +// @target es6 + +class A { + #foo: number; + constructor () { + this.#foo = 3; + } +} + +class B extends A { + #foo: string; + constructor () { + super(); + this.#foo = "some string"; + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts new file mode 100644 index 0000000000000..fb515e4bb023a --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts @@ -0,0 +1,29 @@ +// @strict: true +// @target: es6 + +class C { + #foo: T; + #bar(): T { + return this.#foo; + } + constructor(t: T) { + this.#foo = t; + t = this.#bar(); + } + set baz(t: T) { + this.#foo = t; + + } + get baz(): T { + return this.#foo; + } +} + +let a = new C(3); +let b = new C("hello"); + +a.baz = 5 // OK +const x: number = a.baz // OK +a.#foo; // Error +a = b; // Error +b = a; // Error diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts new file mode 100644 index 0000000000000..0673430ce272c --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts @@ -0,0 +1,14 @@ +// @strict: true +// @target: es6 + +class C { + foo = 3; + #bar = 3; + constructor () { + const ok: C["foo"] = 3; + // not supported yet, could support in future: + const badForNow: C[#bar] = 3; // Error + // will never use this syntax, already taken: + const badAlways: C["#bar"] = 3; // Error + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesAndMethods.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesAndMethods.ts new file mode 100644 index 0000000000000..d564860b56e97 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesAndMethods.ts @@ -0,0 +1,32 @@ +// @target: esnext +// @lib: esnext + +class A { + #foo(a: number) {} + async #bar(a: number) {} + async *#baz(a: number) { + return 3; + } + #_quux: number; + get #quux (): number { + return this.#_quux; + } + set #quux (val: number) { + this.#_quux = val; + } + constructor () { + this.#foo(30); + this.#bar(30); + this.#bar(30); + this.#quux = this.#quux + 1; + this.#quux++; + } +} + +class B extends A { + #foo(a: string) {} + constructor () { + super(); + this.#foo("str"); + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticFields.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticFields.ts new file mode 100644 index 0000000000000..ec9906a8ef00d --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticFields.ts @@ -0,0 +1,17 @@ +// @strict: true +// @target es6 + +class A { + static #foo: number; + constructor () { + A.#foo = 3; + } +} + +class B extends A { + static #foo: string; + constructor () { + super(); + B.#foo = "some string"; + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticMethods.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticMethods.ts new file mode 100644 index 0000000000000..7cbf9f8f9992b --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticMethods.ts @@ -0,0 +1,33 @@ +// @strict: true +// @target: esnext +// @lib: esnext + +class A { + static #foo(a: number) {} + static async #bar(a: number) {} + static async *#baz(a: number) { + return 3; + } + static #_quux: number; + static get #quux (): number { + return this.#_quux; + } + static set #quux (val: number) { + this.#_quux = val; + } + constructor () { + A.#foo(30); + A.#bar(30); + A.#bar(30); + A.#quux = A.#quux + 1; + A.#quux++; + } +} + +class B extends A { + static #foo(a: string) {} + constructor () { + super(); + B.#foo("str"); + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesAndkeyof.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesAndkeyof.ts new file mode 100644 index 0000000000000..1e178092c7e8d --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesAndkeyof.ts @@ -0,0 +1,10 @@ +// @strict: true +// @target es6 + +class A { + #foo = 3; + bar = 3; + baz = 3; +} + +type T = keyof A // should not include '#foo' diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts new file mode 100644 index 0000000000000..fbf667d82f921 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts @@ -0,0 +1,15 @@ +// @strict: true +// @target: es6 + +class C { + #foo: T; + bar(x: C) { return x.#foo; } // OK + baz(x: C) { return x.#foo; } // OK + quux(x: C) { return x.#foo; } // OK +} + +declare let a: C; +declare let b: C; +a.#foo; // Error +a = b; // Error +b = a; // Error diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesInNestedClasses.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesInNestedClasses.ts new file mode 100644 index 0000000000000..dc6076ffbe096 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesInNestedClasses.ts @@ -0,0 +1,28 @@ +// @strict: true +// @target es6 + +class A { + #foo = "A's #foo"; + #bar = "A's #bar"; + method () { + class B { + #foo = "B's #foo"; + bar (a: any) { + a.#foo; // OK, no compile-time error, don't know what `a` is + } + baz (a: A) { + a.#foo; // compile-time error, shadowed + } + quux (b: B) { + b.#foo; // OK + } + } + const a = new A(); + new B().bar(a); + new B().baz(a); + const b = new B(); + new B().quux(b); + } +} + +new A().method(); \ No newline at end of file diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts new file mode 100644 index 0000000000000..a70c8acd143ac --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts @@ -0,0 +1,9 @@ +// @strict: true +// @target es6 + +class A { + public #foo = 3; // Error + private #bar = 3; // Error + protected #baz = 3; // Error + readonly #qux = 3; // OK +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesNoConflictWhenInheriting.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesNoConflictWhenInheriting.ts new file mode 100644 index 0000000000000..937ed9c4c3cfa --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesNoConflictWhenInheriting.ts @@ -0,0 +1,12 @@ +// @strict: true +// @target es6 + +class A { + #foo: number; +} + +class B extends A { + #foo: string; // OK: private names are unique to each class +} + +const b: A = new B() // OK diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts new file mode 100644 index 0000000000000..70b099a0e5397 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts @@ -0,0 +1,9 @@ +// @strict: true +// @target es6 + +class A { + #v = 1; + constructor() { + delete this.#v; // Error: The operand of a delete operator cannot be a private name. + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts new file mode 100644 index 0000000000000..5a71fc00803c2 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts @@ -0,0 +1,5 @@ +// @target es6 + +class A { + setFoo(#foo: string) {} +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts new file mode 100644 index 0000000000000..26aacc421a19a --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts @@ -0,0 +1,4 @@ +// @strict: true +// @target es6 + +const #foo = 3; \ No newline at end of file diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesUnique.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesUnique.ts new file mode 100644 index 0000000000000..1e9891095512d --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesUnique.ts @@ -0,0 +1,12 @@ +// @strict: true +// @target es6 + +class A { + #foo: number; +} + +class B { + #foo: number; +} + +const b: A = new B(); // Error: Property #foo is missing diff --git a/tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration8_es6.ts b/tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration8_es6.ts index e698257e94068..f75eaaa1aca5c 100644 --- a/tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration8_es6.ts +++ b/tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration8_es6.ts @@ -2,7 +2,7 @@ class C { foo() { // Make sure we don't think of *bar as the start of a generator method. - if (a) # * bar; + if (a) ¬ * bar; return bar; } -} \ No newline at end of file +} diff --git a/tests/cases/conformance/parser/ecmascript5/ErrorRecovery/Blocks/parserErrorRecovery_Block2.ts b/tests/cases/conformance/parser/ecmascript5/ErrorRecovery/Blocks/parserErrorRecovery_Block2.ts index 2473a9d1ffb1c..2652211f3ea50 100644 --- a/tests/cases/conformance/parser/ecmascript5/ErrorRecovery/Blocks/parserErrorRecovery_Block2.ts +++ b/tests/cases/conformance/parser/ecmascript5/ErrorRecovery/Blocks/parserErrorRecovery_Block2.ts @@ -1,4 +1,4 @@ function f() { - # + ¬ return; -} \ No newline at end of file +} diff --git a/tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ClassElements/parserErrorRecovery_ClassElement3.ts b/tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ClassElements/parserErrorRecovery_ClassElement3.ts index d4ea9d6078719..0f81401c1b8b2 100644 --- a/tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ClassElements/parserErrorRecovery_ClassElement3.ts +++ b/tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ClassElements/parserErrorRecovery_ClassElement3.ts @@ -1,7 +1,7 @@ module M { - # + ¬ class C { } @ enum E { - # \ No newline at end of file + ¬ diff --git a/tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ParameterLists/parserErrorRecovery_ParameterList4.ts b/tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ParameterLists/parserErrorRecovery_ParameterList4.ts index f46e46951454e..9eb5c87804e11 100644 --- a/tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ParameterLists/parserErrorRecovery_ParameterList4.ts +++ b/tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ParameterLists/parserErrorRecovery_ParameterList4.ts @@ -1,2 +1,2 @@ -function f(a,#) { -} \ No newline at end of file +function f(a,¬) { +} diff --git a/tests/cases/conformance/parser/ecmascript5/SkippedTokens/parserSkippedTokens16.ts b/tests/cases/conformance/parser/ecmascript5/SkippedTokens/parserSkippedTokens16.ts index c583fc13d8229..a12294be4bb9e 100644 --- a/tests/cases/conformance/parser/ecmascript5/SkippedTokens/parserSkippedTokens16.ts +++ b/tests/cases/conformance/parser/ecmascript5/SkippedTokens/parserSkippedTokens16.ts @@ -1,8 +1,8 @@ foo(): Bar { } -function Foo () # { } +function Foo () ¬ { } 4+:5 module M { function a( : T) { } } -var x = \ No newline at end of file +var x = diff --git a/tests/cases/fourslash/hoverOverPrivateName.ts b/tests/cases/fourslash/hoverOverPrivateName.ts new file mode 100644 index 0000000000000..28e748b9aa43c --- /dev/null +++ b/tests/cases/fourslash/hoverOverPrivateName.ts @@ -0,0 +1,15 @@ +/// + +////class A { +//// #foo: number; +//// +//// constructor () { +//// this./**/#foo = 3; +//// } +//// +////} + +goTo.marker(); +verify.quickInfoIs(""); +verify.goToDefinitionIs([]); +verify.noReferences(); \ No newline at end of file