diff --git a/.travis.yml b/.travis.yml index 6d000dd716591..b2880174e294f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,12 +15,7 @@ matrix: branches: only: - - master - - release-2.7 - - release-2.8 - - release-2.9 - - release-3.0 - - release-3.1 + - es-private-fields install: - npm uninstall typescript --no-save diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 292bfe51340db..693a3833ff1bb 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -271,6 +271,9 @@ namespace ts { Debug.assert(isWellKnownSymbolSyntactically(nameExpression)); return getPropertyNameForKnownSymbolName(idText((nameExpression).name)); } + if (isPrivateName(node)) { + return nodePosToString(node) as __String; + } return isPropertyNameLiteral(name) ? getEscapedTextOfIdentifierOrLiteral(name) : undefined; } switch (node.kind) { @@ -1402,7 +1405,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); } } @@ -2358,7 +2361,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); } @@ -2516,7 +2519,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(propertyAccess.expression, namespaceSymbol, (id, symbol, parent) => { + namespaceSymbol = forEachIdentifierOrPrivateNameInEntityName(propertyAccess.expression, namespaceSymbol, (id, symbol, parent) => { if (symbol) { addDeclarationToSymbol(symbol, id, flags); return symbol; @@ -2588,7 +2591,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; } @@ -2596,7 +2599,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); } @@ -3134,8 +3137,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) @@ -3158,8 +3160,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; @@ -3255,7 +3256,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; } @@ -3286,7 +3286,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; } @@ -3301,12 +3300,16 @@ namespace ts { } function computePropertyDeclaration(node: PropertyDeclaration, subtreeFlags: TransformFlags) { - // A PropertyDeclaration is TypeScript syntax. - let transformFlags = subtreeFlags | TransformFlags.AssertTypeScript; + // A PropertyDeclaration is ESnext syntax. + let transformFlags = subtreeFlags | TransformFlags.AssertESNext; + + // 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; } @@ -3582,6 +3585,10 @@ namespace ts { let excludeFlags = TransformFlags.NodeExcludes; switch (kind) { + case SyntaxKind.PrivateName: + // Private names are ESNext syntax. + transformFlags |= TransformFlags.AssertESNext; + break; case SyntaxKind.AsyncKeyword: case SyntaxKind.AwaitExpression: // async/await is ES2017 syntax, but may be ESNext syntax (for async generators) @@ -3707,6 +3714,8 @@ namespace ts { break; case SyntaxKind.ComputedPropertyName: + // Computed property names are transformed by the ESNext transformer. + transformFlags |= TransformFlags.AssertESNext; // Even though computed property names are ES6, we don't treat them as such. // This is so that they can flow through PropertyName transforms unaffected. // Instead, we mark the container as ES6, so that it can properly handle the transform. diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b00073557caa9..9faf08016d0c2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14773,8 +14773,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 && @@ -18619,7 +18621,7 @@ namespace ts { return checkPropertyAccessExpressionOrQualifiedName(node, node.left, node.right); } - function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) { + function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier | PrivateName) { let propType: Type; const leftType = checkNonNullExpression(left); const parentSymbol = getNodeLinks(left).resolvedSymbol; @@ -18637,7 +18639,7 @@ namespace ts { } if (!prop) { const indexInfo = getIndexInfoOfType(apparentType, IndexKind.String); - if (!(indexInfo && indexInfo.type)) { + if (!(indexInfo && indexInfo.type) || isPrivateName(right)) { if (isJSLiteralType(leftType)) { return anyType; } @@ -18701,7 +18703,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; @@ -18771,7 +18773,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)) { @@ -18814,11 +18816,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); } @@ -22640,6 +22642,9 @@ namespace ts { checkGrammarDecoratorsAndModifiers(node); checkVariableLikeDeclaration(node); + if (node.name && isIdentifier(node.name) && node.name.originalKeywordKind === SyntaxKind.PrivateName) { + error(node, Diagnostics.Private_names_cannot_be_used_as_parameters); + } const func = getContainingFunction(node)!; if (hasModifier(node, ModifierFlags.ParameterPropertyModifier)) { if (!(func.kind === SyntaxKind.Constructor && nodeIsPresent(func.body))) { @@ -24287,9 +24292,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; @@ -30141,6 +30146,10 @@ namespace ts { checkESModuleMarker(node.name); } + if (isIdentifier(node.name) && node.name.originalKeywordKind === SyntaxKind.PrivateName) { + return grammarErrorOnNode(node.name, Diagnostics.Private_names_are_not_allowed_in_variable_declarations); + } + const checkLetConstNames = (isLet(node) || isVarConst(node)); // 1. LexicalDeclaration : LetOrConst BindingList ; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 65a9e4bafb2f8..6b0dea39a514b 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4262,6 +4262,14 @@ "category": "Error", "code": 18003 }, + "Private names are not allowed in variable declarations.": { + "category": "Error", + "code": 18004 + }, + "Private names cannot be used as parameters": { + "category": "Error", + "code": 18005 + }, "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 8617c8fccdeeb..c14602a0f2fab 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -620,6 +620,10 @@ namespace ts { case SyntaxKind.Identifier: return emitIdentifier(node); + // PrivateNames + case SyntaxKind.PrivateName: + return emitPrivateName(node as PrivateName); + // Parse tree nodes // Names @@ -889,6 +893,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: @@ -1078,6 +1086,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 // @@ -3320,7 +3334,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 4b2855790a985..7b5637791f9fb 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -105,7 +105,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; @@ -995,7 +995,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 @@ -1003,7 +1003,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 @@ -2714,7 +2714,7 @@ namespace ts { // Utilities - function asName(name: string | T): T | Identifier { + function asName(name: string | T): T | Identifier { return isString(name) ? createIdentifier(name) : name; } @@ -3099,7 +3099,7 @@ namespace ts { } else { const expression = setTextRange( - isIdentifier(memberName) + (isIdentifier(memberName) || isPrivateName(memberName)) ? createPropertyAccess(target, memberName) : createElementAccess(target, memberName), memberName @@ -3529,7 +3529,7 @@ namespace ts { } } - export function createExpressionForPropertyName(memberName: PropertyName): Expression { + export function createExpressionForPropertyName(memberName: Exclude): Expression { if (isIdentifier(memberName)) { return createLiteral(memberName); } @@ -3541,11 +3541,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: @@ -3555,7 +3561,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 c88aebe799f32..76e5a3086687c 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1371,6 +1371,9 @@ namespace ts { if (allowComputedPropertyNames && token() === SyntaxKind.OpenBracketToken) { return parseComputedPropertyName(); } + if (token() === SyntaxKind.PrivateName) { + return parsePrivateName(); + } return parseIdentifierName(); } @@ -1394,6 +1397,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); } @@ -2145,7 +2159,7 @@ namespace ts { break; } dotPos = scanner.getStartPos(); - entity = createQualifiedName(entity, parseRightSideOfDot(allowReservedWords)); + entity = createQualifiedName(entity, parseRightSideOfDot(allowReservedWords, /* allowPrivateNames */ false) as Identifier); } return entity; } @@ -2157,7 +2171,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. @@ -2188,6 +2202,10 @@ namespace ts { } } + if (allowPrivateNames && token() === SyntaxKind.PrivateName) { + return parsePrivateName(); + } + return allowIdentifierNames ? parseIdentifierName() : parseIdentifier(); } @@ -4185,7 +4203,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); } @@ -4355,7 +4374,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; @@ -4458,7 +4477,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 1a5c4336b6334..642bb95996476 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -1758,6 +1758,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/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index cde5ee290a357..a975c22ac44ea 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 66f635a31e9cd..db028fd25a820 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -1652,7 +1652,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/esnext.ts b/src/compiler/transformers/esnext.ts index cd62cca2c9dfb..8e13c704c240f 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -2,7 +2,37 @@ namespace ts { const enum ESNextSubstitutionFlags { /** Enables substitutions for async methods with `super` calls. */ - AsyncMethodsWithSuper = 1 << 0 + AsyncMethodsWithSuper = 1 << 0, + /** + * Enables substitutions for class expressions with static fields + * which have initializers that reference the class name. + */ + ClassAliases = 1 << 1, + } + + /** + * A mapping of private names to information needed for transformation. + */ + type PrivateNameEnvironment = UnderscoreEscapedMap; + + /** + * Identifies the type of private name. + */ + const enum PrivateNamePlacement { + InstanceField, + InstanceMethod + } + + interface PrivateNamedInstanceField { + placement: PrivateNamePlacement.InstanceField; + accumulator: Identifier; + } + + interface PrivateNamedInstanceMethod { + placement: PrivateNamePlacement.InstanceMethod; + accumulator: Identifier; + origFunc: MethodDeclaration; + funcName: Identifier; } export function transformESNext(context: TransformationContext) { @@ -33,6 +63,22 @@ namespace ts { /** A set of node IDs for generated super accessors. */ const substitutedSuperAccessors: boolean[] = []; + 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) { @@ -111,17 +157,635 @@ namespace ts { if (capturedSuperProperties && isPropertyAccessExpression(node) && node.expression.kind === SyntaxKind.SuperKeyword) { capturedSuperProperties.set(node.name.escapedText, true); } - return visitEachChild(node, visitor, context); + return visitPropertyAccessExpression(node as PropertyAccessExpression); case SyntaxKind.ElementAccessExpression: if (capturedSuperProperties && (node).expression.kind === SyntaxKind.SuperKeyword) { hasSuperElementAccess = true; } return visitEachChild(node, visitor, context); + case SyntaxKind.ClassExpression: + return visitClassExpression(node as ClassExpression); + case SyntaxKind.ClassDeclaration: + return visitClassDeclaration(node as ClassDeclaration); + 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.CallExpression: + return visitCallExpression(node as CallExpression); default: 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); + } + } + /** + * 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 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 visitClassDeclaration(node: ClassDeclaration) { + const savedPendingExpressions = pendingExpressions; + pendingExpressions = undefined; + startPrivateNameEnvironment(); + + 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!))); + } + endPrivateNameEnvironment(); + 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. + const staticProperties = getInitializedProperties(node, /*isStatic*/ true); + if (some(staticProperties)) { + addInitializedPropertyStatements(statements, staticProperties, getInternalName(node)); + } + + return statements; + } + + function visitClassExpression(node: ClassExpression): Expression { + const savedPendingExpressions = pendingExpressions; + pendingExpressions = undefined; + startPrivateNameEnvironment(); + + // 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 or private names + if (some(pendingExpressions)) { + pendingStatements!.push(createExpressionStatement(inlineExpressions(pendingExpressions!))); + } + pendingExpressions = savedPendingExpressions; + + if (some(staticProperties)) { + addInitializedPropertyStatements(pendingStatements!, staticProperties, getInternalName(node)); + } + endPrivateNameEnvironment(); + 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)); + + pendingExpressions = savedPendingExpressions; + endPrivateNameEnvironment(); + return inlineExpressions(expressions); + } + } + + pendingExpressions = savedPendingExpressions; + endPrivateNameEnvironment(); + return classExpression; + } + + function transformClassMembers(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { + // Declare private names. + const privateNamedMembers = node.members + .filter(element => isNamedDeclaration(element) && isPrivateName(element.name)); + privateNamedMembers.forEach(addPrivateName); + + pendingExpressions = pendingExpressions || []; + last(privateNameEnvironmentStack).forEach(entry => { + const { placement } = entry; + switch (placement) { + case PrivateNamePlacement.InstanceField: + break; + case PrivateNamePlacement.InstanceMethod: + entry = entry as PrivateNamedInstanceMethod; + const func = privateNamedMethodToFunction(entry.origFunc, entry.funcName, entry.accumulator); + (pendingExpressions = pendingExpressions || []).push(createAssignment( + entry.funcName, + func + )); + break; + default: + Debug.assertNever(placement, "unexpected Private Name Placement"); + } + }); + const members: ClassElement[] = []; + const constructor = transformConstructor(node, isDerivedClass, !!privateNamedMembers.length); + 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, declaresPrivateNames: boolean) { + const constructor = visitNode(getFirstConstructorWithBody(node), visitor, isConstructorDeclaration); + const containsPropertyInitializer = forEach(node.members, isInitializedProperty); + let body = constructor ? constructor.body : undefined; + let parameters = constructor ? constructor.parameters : undefined; + const shouldTransformConstructorBody = containsPropertyInitializer || declaresPrivateNames; + if (shouldTransformConstructorBody) { + if (containsPropertyInitializer) { + parameters = visitParameterList(constructor ? constructor.parameters : undefined, visitor, context); + } + else { + // provide a scope for hoisted declarations for WeakSet or WeakMap for private name brand checks + // not needed if `visitParameterList` was called, because that starts/suspends the lexical environment + context.startLexicalEnvironment(); + context.suspendLexicalEnvironment(); + } + body = transformConstructorBody(node, constructor, isDerivedClass, declaresPrivateNames); + } + 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, + classDeclaresPrivateNames: boolean, + ) { + const properties = filter(node.members, (node): node is PropertyDeclaration => isPropertyDeclaration(node) && !hasStaticModifier(node)); + + // Only generate synthetic constructor when there are property or private name declarations to move + if (!constructor && !some(properties) && !classDeclaresPrivateNames) { + return visitFunctionBody(/*node*/ undefined, visitor, context); + } + + let statements: Statement[] = []; + + // was suspended to provide a scope for parameter properties and/or private names + resumeLexicalEnvironment(); + + let indexOfFirstStatement = 0; + + 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()); + if (classDeclaresPrivateNames) { + last(privateNameEnvironmentStack).forEach(({ placement, accumulator }) => { + switch (placement) { + case PrivateNamePlacement.InstanceField: + // TODO: instance field add accumulator + break; + case PrivateNamePlacement.InstanceMethod: + statements.push( + createExpressionStatement( + createCall( + createPropertyAccess(accumulator, "add"), + /* typeArguments */ undefined, + [createThis()] + ) + ) + ); + break; + } + }); + } + + // 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 createCall( + createPropertyAccess(privateNameInfo.accumulator, "set"), + /*typeArguments*/ undefined, + [receiver, initializer || createVoidZero()] + ); + } + } + } + } + if (!initializer) { + return undefined; + } + const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName); + + return createAssignment(memberAccess, initializer); + } + + function startPrivateNameEnvironment() { + const env: PrivateNameEnvironment = createUnderscoreEscapedMap(); + privateNameEnvironmentStack.push(env); + return env; + } + + function endPrivateNameEnvironment() { + privateNameEnvironmentStack.pop(); + } + + function privateNamedMethodToFunction (declaration: MethodDeclaration, funcName: Identifier, accumulator: Identifier): FunctionExpression { + const params = declaration.parameters; + let body = getMutableClone(declaration.body || createBlock([], true)); + body = visitEachChild(body, visitor, context); + const toPrepend = startOnNewLine( + createStatement( + createClassPrivateNamedCallCheckHelper(context, accumulator) + ) + ); + body.statements = setTextRange( + createNodeArray([ + toPrepend, + ...body.statements + ]), + body.statements + ); + const func = createFunctionExpression( + /* modifiers */ undefined, + /* asteriskToken */ undefined, + funcName, + /* typeParameters */ undefined, + params, + /* type */ undefined, + body); + return func; + } + + + function addPrivateName(element: ClassElement & { name: PrivateName }) { + const env = last(privateNameEnvironmentStack); + const text = getTextOfPropertyName(element.name) as string; + const accumulator = createFileLevelUniqueName(`_${text.substring(1)}Private`); + const { escapedText } = element.name; + hoistVariableDeclaration(accumulator); + + let identifierName: string; + if (hasModifier(element, ModifierFlags.Static)) { + // statics not supported yet + return; + } + if (isPropertyDeclaration(element)) { + identifierName = "WeakMap"; + env.set(escapedText, { placement: PrivateNamePlacement.InstanceField, accumulator }); + } + else if (isMethodDeclaration(element)) { + identifierName = "WeakSet"; + const escapedText = element.name.escapedText; + const escapedTextNoHash = `_${`${escapedText}`.slice(1)}`; + const funcName: Identifier = createFileLevelUniqueName(escapedTextNoHash); + env.set(escapedText, { placement: PrivateNamePlacement.InstanceMethod, accumulator, funcName, origFunc: element }); + hoistVariableDeclaration(funcName); // todo: hoist in lexical, not func scope + } + else { + return; + } + (pendingExpressions = pendingExpressions || []).push( + createAssignment( + accumulator, + createNew( + createIdentifier(identifierName), + /*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 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.accumulator + ), + node + ), + node + ); + } + } + } + return visitEachChild(node, visitor, context); + } + + function visitCallExpression(node: CallExpression) { + if (isPrivateNamedPropertyAccess(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; + } + const privateNameEntry = last(privateNameEnvironmentStack).get(node.expression.name.escapedText); + if (privateNameEntry && privateNameEntry.placement === PrivateNamePlacement.InstanceMethod) { + return setOriginalNode( + setTextRange( + createCall( + createPropertyAccess( + privateNameEntry.funcName, + "call" + ), + /*typeArguments*/ undefined, + [createThis(), ...node.arguments] + ), + /* location */ node + ), + node + ); + } + return visitNode( + updateCall( + node, + createPropertyAccess( + updatePropertyAccess( + node.expression, + exprForPropertyAccess, + node.expression.name + ), + "call" + ), + /*typeArguments*/ undefined, + [receiver, ...node.arguments] + ), + visitor + ); + } + return visitEachChild(node, visitor, context); + } + + function enableSubstitutionForClassAliases() { + if ((enabledSubstitutions & ESNextSubstitutionFlags.ClassAliases) === 0) { + enabledSubstitutions |= ESNextSubstitutionFlags.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 = []; + } + } + + function visitAwaitExpression(node: AwaitExpression): Expression { if (enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator) { return setOriginalNode( @@ -260,20 +924,105 @@ namespace ts { return visitEachChild(node, visitor, context); } + function wrapPrivateNameForDestructuringTarget(node: PrivateNamedPropertyAccess) { + 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( + createAssignment( + visitNode(node, visitor), + createIdentifier("x") + ) + )] + ) + ) + ]), + "value" + ); + } + + function transformDestructuringAssignmentTarget(node: ArrayLiteralExpression | ObjectLiteralExpression) { + const hasPrivateNames = isArrayLiteralExpression(node) ? + forEach(node.elements, isPrivateNamedPropertyAccess) : + forEach(node.properties, property => isPropertyAssignment(property) && isPrivateNamedPropertyAccess(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 => isPrivateNamedPropertyAccess(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) && isPrivateNamedPropertyAccess(prop.initializer) ? + updatePropertyAssignment( + prop, + prop.name, + wrapPrivateNameForDestructuringTarget(prop.initializer) + ) : + prop + ) + ); + } + } + /** * Visits a BinaryExpression that contains a destructuring assignment. * * @param node A BinaryExpression node. */ function visitBinaryExpression(node: BinaryExpression, noDestructuringValue: boolean): Expression { - if (isDestructuringAssignment(node) && node.left.transformFlags & TransformFlags.ContainsObjectRestOrSpread) { - return flattenDestructuringAssignment( - node, - visitor, - context, - FlattenLevel.ObjectRest, - !noDestructuringValue - ); + if (isDestructuringAssignment(node)) { + const left = transformDestructuringAssignmentTarget(node.left); + if (left !== node.left || node.left.transformFlags & TransformFlags.ContainsObjectRestOrSpread) { + return flattenDestructuringAssignment( + left === node.left ? node : updateBinary( + node, + left, + node.right, + node.operatorToken.kind + ) as DestructuringAssignment, + visitor, + context, + node.left.transformFlags & TransformFlags.ContainsObjectRestOrSpread + ? FlattenLevel.ObjectRest : FlattenLevel.All, + !noDestructuringValue + ); + } } else if (node.operatorToken.kind === SyntaxKind.CommaToken) { return updateBinary( @@ -282,6 +1031,46 @@ namespace ts { visitNode(node.right, noDestructuringValue ? visitorNoDestructuringValue : visitor, isExpression) ); } + else if (isAssignmentExpression(node) && isPropertyAccessExpression(node.left) && isPrivateName(node.left.name)) { + const privateNameInfo = accessPrivateName(node.left.name); + if (privateNameInfo && privateNameInfo.placement === PrivateNamePlacement.InstanceField) { + 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.accumulator, + createBinary( + createClassPrivateFieldGetHelper( + context, + getReceiver, + privateNameInfo.accumulator + ), + getOperatorForCompoundAssignment(node.operatorToken.kind), + visitNode(node.right, visitor) + ) + ), + node + ); + } + else { + return setOriginalNode( + createClassPrivateFieldSetHelper( + context, + node.left.expression, + privateNameInfo.accumulator, + visitNode(node.right, visitor) + ), + node + ); + } + } + } return visitEachChild(node, visitor, context); } @@ -303,6 +1092,19 @@ namespace ts { return visitEachChild(node, visitor, context); } + 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 visitForStatement(node: ForStatement): VisitResult { return updateFor( node, @@ -580,6 +1382,9 @@ namespace ts { function visitMethodDeclaration(node: MethodDeclaration) { const savedEnclosingFunctionFlags = enclosingFunctionFlags; enclosingFunctionFlags = getFunctionFlags(node); + if (isPrivateName(node.name)) { + return []; + } const updated = updateMethod( node, /*decorators*/ undefined, @@ -728,6 +1533,12 @@ namespace ts { function transformFunctionBody(node: FunctionDeclaration | FunctionExpression | ConstructorDeclaration | MethodDeclaration | AccessorDeclaration): FunctionBody; function transformFunctionBody(node: ArrowFunction): ConciseBody; function transformFunctionBody(node: FunctionLikeDeclaration): ConciseBody { + // The function only needs to be transformed if there are object rest parameters. + // It's not enough to rely on the ContainsESNext transform flag check to transform function bodies + // because any function containing PropertyDeclaration nodes will contain ESNext syntax. + if (!(node.transformFlags & TransformFlags.ContainsObjectRestOrSpread)) { + return (node.body && visitFunctionBody(node.body, visitor, context)) || createBlock([]); + } resumeLexicalEnvironment(); let statementOffset = 0; const statements: Statement[] = []; @@ -835,7 +1646,7 @@ namespace ts { */ function onSubstituteNode(hint: EmitHint, node: Node) { node = previousOnSubstituteNode(hint, node); - if (hint === EmitHint.Expression && enclosingSuperContainerFlags) { + if (hint === EmitHint.Expression) { return substituteExpression(node); } return node; @@ -849,12 +1660,14 @@ namespace ts { return substituteElementAccessExpression(node); case SyntaxKind.CallExpression: return substituteCallExpression(node); + case SyntaxKind.Identifier: + return substituteExpressionIdentifier(node as Identifier); } return node; } function substitutePropertyAccessExpression(node: PropertyAccessExpression) { - if (node.expression.kind === SyntaxKind.SuperKeyword) { + if (enclosingSuperContainerFlags && node.expression.kind === SyntaxKind.SuperKeyword) { return setTextRange( createPropertyAccess( createFileLevelUniqueName("_super"), @@ -866,7 +1679,7 @@ namespace ts { } function substituteElementAccessExpression(node: ElementAccessExpression) { - if (node.expression.kind === SyntaxKind.SuperKeyword) { + if (enclosingSuperContainerFlags && node.expression.kind === SyntaxKind.SuperKeyword) { return createSuperElementAccessInAsyncMethod( node.argumentExpression, node @@ -876,6 +1689,9 @@ namespace ts { } function substituteCallExpression(node: CallExpression): Expression { + if (!enclosingSuperContainerFlags) { + return node; + } const expression = node.expression; if (isSuperProperty(expression)) { const argumentExpression = isPropertyAccessExpression(expression) @@ -893,6 +1709,34 @@ namespace ts { return node; } + function substituteExpressionIdentifier(node: Identifier): Expression { + return trySubstituteClassAlias(node) || node; + } + + function trySubstituteClassAlias(node: Identifier): Expression | undefined { + if (enabledSubstitutions & ESNextSubstitutionFlags.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; + } + function isSuperContainer(node: Node) { const kind = node.kind; return kind === SyntaxKind.ClassDeclaration @@ -1056,4 +1900,37 @@ namespace ts { location ); } + + 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]); + } + const classPrivateNamedCallCheckHelper: EmitHelper = { + name: "typescript:classPrivateNamedCallCheck", + scoped: false, + text: `var _classPrivateNamedCallCheck = function (receiver, privateSet) { if (!privateSet.has(receiver)) { throw new TypeError("attempted to get weak field on non-instance"); }};` + }; + + function createClassPrivateNamedCallCheckHelper(context: TransformationContext, weakSet: Identifier) { + context.requestEmitHelper(classPrivateNamedCallCheckHelper); + return createCall(getHelperName("_classPrivateNamedCallCheck"), /* typeArguments */ undefined, [ createThis(), weakSet ]); + } + } diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 5778b47a4f8b4..66089c15388d3 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 a5ab1e8475feb..343f64be48361 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; } @@ -333,6 +330,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: @@ -449,7 +449,6 @@ namespace ts { // - decorators // - optional `implements` heritage clause // - parameter property assignments in the constructor - // - property declarations // - index signatures // - method overload signatures return visitClassDeclaration(node); @@ -461,7 +460,6 @@ namespace ts { // - decorators // - optional `implements` heritage clause // - parameter property assignments in the constructor - // - property declarations // - index signatures // - method overload signatures return visitClassExpression(node); @@ -612,16 +610,12 @@ namespace ts { * * This function will only be called when one of the following conditions are met: * - The class has decorators. - * - The class has property declarations with initializers. * - The class contains a constructor that contains parameters with accessibility modifiers. * - The class is an export in a TypeScript namespace. * * @param node The node to transform. */ function visitClassDeclaration(node: ClassDeclaration): VisitResult { - const savedPendingExpressions = pendingExpressions; - pendingExpressions = undefined; - const staticProperties = getInitializedProperties(node, /*isStatic*/ true); const facts = getClassFacts(node, staticProperties); @@ -631,25 +625,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); @@ -752,7 +732,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 @@ -772,7 +752,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. // @@ -867,7 +847,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); @@ -894,55 +874,24 @@ namespace ts { * Transforms a class expression with TypeScript syntax into compatible ES6. * * This function will only be called when one of the following conditions are met: - * - The class has property declarations with initializers. * - The class contains a constructor that contains parameters with accessibility modifiers. * * @param node The node to transform. */ function visitClassExpression(node: ClassExpression): Expression { - 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; } @@ -950,61 +899,76 @@ 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); - - // constructor(${parameters}) { - // ${body} - // } - return startOnNewLine( - setOriginalNode( - setTextRange( - createConstructor( + const parametersWithPropertyAssignments = + constructor && !!(constructor.transformFlags & TransformFlags.ContainsTypeScriptClassSyntax) + ? 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, - parameters, - body - ), - constructor || node - ), - constructor - ) - ); + param.name, + /*questionOrExclamationToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined + ) + ) + ); + + const parameters = transformConstructorParameters(constructor); + const body = transformConstructorBody(node.members, constructor, parametersWithPropertyAssignments); + members.push(startOnNewLine( + updateConstructor( + constructor, + /*decorators*/ undefined, + /*modifiers*/ undefined, + parameters, + body + ) + )); + 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); } /** @@ -1013,7 +977,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 @@ -1034,70 +998,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()); @@ -1105,7 +1053,7 @@ namespace ts { createBlock( setTextRange( createNodeArray(statements), - /*location*/ constructor ? constructor.body!.statements : node.members + /*location*/ constructor ? constructor.body!.statements : members ), /*multiLine*/ true ), @@ -1113,61 +1061,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); @@ -1196,99 +1099,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. @@ -2115,15 +1925,6 @@ namespace ts { ); } - /** - * 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 @@ -2138,7 +1939,7 @@ namespace ts { ? getGeneratedNameForNode(name) : name.expression; } - else if (isIdentifier(name)) { + else if (isIdentifier(name) || isPrivateName(name)) { return createLiteral(idText(name)); } else { @@ -2146,26 +1947,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 @@ -2175,18 +1956,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 paramerty 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); } /** @@ -2239,12 +2022,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..26cd44609e70b 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -240,6 +240,47 @@ 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); + } + + /** + * 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 +296,65 @@ 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; + } + + 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; + } + } } \ No newline at end of file diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3bd103579f1b3..202ee73e874c7 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -193,8 +193,9 @@ namespace ts { AmpersandEqualsToken, BarEqualsToken, CaretEqualsToken, - // Identifiers + // Identifiers and PrivateNames Identifier, + PrivateName, // Reserved words BreakKeyword, CaseKeyword, @@ -788,9 +789,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 | StringLiteral | NumericLiteral | ComputedPropertyName | BindingPattern; + export type DeclarationName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | PrivateName | BindingPattern; export interface Declaration extends Node { _declarationBrand: any; @@ -821,6 +822,13 @@ namespace ts { expression: Expression; } + export interface PrivateName extends 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 { @@ -934,6 +942,10 @@ namespace ts { initializer?: Expression; // Optional initializer } + export interface PrivatePropertyDeclaration extends PropertyDeclaration { + name: PrivateName; + } + export interface ObjectLiteralElement extends NamedDeclaration { _objectLiteralBrandBrand: any; name?: PropertyName; @@ -1260,7 +1272,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; } @@ -1741,7 +1753,11 @@ namespace ts { export interface PropertyAccessExpression extends MemberExpression, NamedDeclaration { kind: SyntaxKind.PropertyAccessExpression; expression: LeftHandSideExpression; - name: Identifier; + name: Identifier | PrivateName; + } + + export interface PrivateNamedPropertyAccess extends PropertyAccessExpression { + name: PrivateName; } export interface SuperPropertyAccessExpression extends PropertyAccessExpression { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index acaabdab9c7be..41d12fc64e639 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -768,6 +768,7 @@ namespace ts { export function getTextOfPropertyName(name: PropertyName): __String { switch (name.kind) { case SyntaxKind.Identifier: + case SyntaxKind.PrivateName: return name.escapedText; case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: @@ -786,7 +787,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); } @@ -1880,7 +1889,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); @@ -2644,6 +2653,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: @@ -2662,10 +2672,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: @@ -2675,11 +2687,11 @@ 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 getPropertyNameForKnownSymbolName(symbolName: string): __String { @@ -3339,7 +3351,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 { @@ -4898,8 +4910,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); @@ -4910,7 +4922,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; @@ -4955,7 +4967,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); } @@ -5262,6 +5274,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 { @@ -5272,6 +5288,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 { @@ -6052,6 +6072,14 @@ namespace ts { || kind === SyntaxKind.ComputedPropertyName; } + export function isPrivatePropertyDeclaration(node: Node): node is PrivatePropertyDeclaration { + return isPropertyDeclaration(node) && isPrivateName(node.name); + } + + export function isPrivateNamedPropertyAccess(node: Node): node is PrivateNamedPropertyAccess { + return isPropertyAccessExpression(node) && isPrivateName(node.name); + } + export function isBindingName(node: Node): node is BindingName { const kind = node.kind; return kind === SyntaxKind.Identifier diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 2cfb469f15296..f4cfacda7d87a 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 62f73df9f80b8..6e4242ffa1c07 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -239,7 +239,7 @@ namespace ts.codefix { entry.kind !== FindAllReferences.EntryKind.Span ? tryCast(entry.node, isIdentifier) : undefined); } - function inferTypeForVariableFromUsage(token: Identifier, program: Program, cancellationToken: CancellationToken): Type | undefined { + function inferTypeForVariableFromUsage(token: Identifier | PrivateName, program: Program, cancellationToken: CancellationToken): Type | undefined { return InferFromReference.inferTypeFromReferences(getReferences(token, program, cancellationToken), program.getTypeChecker(), cancellationToken); } diff --git a/src/services/refactors/moveToNewFile.ts b/src/services/refactors/moveToNewFile.ts index 693cdd9c6cb3d..d3c5a3a9dadcc 100644 --- a/src/services/refactors/moveToNewFile.ts +++ b/src/services/refactors/moveToNewFile.ts @@ -665,7 +665,7 @@ namespace ts.refactor { } function nameOfTopLevelDeclaration(d: TopLevelDeclaration): Identifier | undefined { - return d.kind === SyntaxKind.ExpressionStatement ? d.expression.left.name : tryCast(d.name, isIdentifier); + return d.kind === SyntaxKind.ExpressionStatement ? 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 011c98f9da698..d26293a851302 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 d83065599869e..4609642e6a3d9 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -145,261 +145,262 @@ declare namespace ts { BarEqualsToken = 69, CaretEqualsToken = 70, Identifier = 71, - BreakKeyword = 72, - CaseKeyword = 73, - CatchKeyword = 74, - ClassKeyword = 75, - ConstKeyword = 76, - ContinueKeyword = 77, - DebuggerKeyword = 78, - DefaultKeyword = 79, - DeleteKeyword = 80, - DoKeyword = 81, - ElseKeyword = 82, - EnumKeyword = 83, - ExportKeyword = 84, - ExtendsKeyword = 85, - FalseKeyword = 86, - FinallyKeyword = 87, - ForKeyword = 88, - FunctionKeyword = 89, - IfKeyword = 90, - ImportKeyword = 91, - InKeyword = 92, - InstanceOfKeyword = 93, - NewKeyword = 94, - NullKeyword = 95, - ReturnKeyword = 96, - SuperKeyword = 97, - SwitchKeyword = 98, - ThisKeyword = 99, - ThrowKeyword = 100, - TrueKeyword = 101, - TryKeyword = 102, - TypeOfKeyword = 103, - VarKeyword = 104, - VoidKeyword = 105, - WhileKeyword = 106, - WithKeyword = 107, - ImplementsKeyword = 108, - InterfaceKeyword = 109, - LetKeyword = 110, - PackageKeyword = 111, - PrivateKeyword = 112, - ProtectedKeyword = 113, - PublicKeyword = 114, - StaticKeyword = 115, - YieldKeyword = 116, - AbstractKeyword = 117, - AsKeyword = 118, - AnyKeyword = 119, - AsyncKeyword = 120, - AwaitKeyword = 121, - BooleanKeyword = 122, - ConstructorKeyword = 123, - DeclareKeyword = 124, - GetKeyword = 125, - InferKeyword = 126, - IsKeyword = 127, - KeyOfKeyword = 128, - ModuleKeyword = 129, - NamespaceKeyword = 130, - NeverKeyword = 131, - ReadonlyKeyword = 132, - RequireKeyword = 133, - NumberKeyword = 134, - ObjectKeyword = 135, - SetKeyword = 136, - StringKeyword = 137, - SymbolKeyword = 138, - TypeKeyword = 139, - UndefinedKeyword = 140, - UniqueKeyword = 141, - UnknownKeyword = 142, - FromKeyword = 143, - GlobalKeyword = 144, - OfKeyword = 145, - QualifiedName = 146, - ComputedPropertyName = 147, - TypeParameter = 148, - Parameter = 149, - Decorator = 150, - PropertySignature = 151, - PropertyDeclaration = 152, - MethodSignature = 153, - MethodDeclaration = 154, - Constructor = 155, - GetAccessor = 156, - SetAccessor = 157, - CallSignature = 158, - ConstructSignature = 159, - IndexSignature = 160, - TypePredicate = 161, - TypeReference = 162, - FunctionType = 163, - ConstructorType = 164, - TypeQuery = 165, - TypeLiteral = 166, - ArrayType = 167, - TupleType = 168, - OptionalType = 169, - RestType = 170, - UnionType = 171, - IntersectionType = 172, - ConditionalType = 173, - InferType = 174, - ParenthesizedType = 175, - ThisType = 176, - TypeOperator = 177, - IndexedAccessType = 178, - MappedType = 179, - LiteralType = 180, - ImportType = 181, - ObjectBindingPattern = 182, - ArrayBindingPattern = 183, - BindingElement = 184, - ArrayLiteralExpression = 185, - ObjectLiteralExpression = 186, - PropertyAccessExpression = 187, - ElementAccessExpression = 188, - CallExpression = 189, - NewExpression = 190, - TaggedTemplateExpression = 191, - TypeAssertionExpression = 192, - ParenthesizedExpression = 193, - FunctionExpression = 194, - ArrowFunction = 195, - DeleteExpression = 196, - TypeOfExpression = 197, - VoidExpression = 198, - AwaitExpression = 199, - PrefixUnaryExpression = 200, - PostfixUnaryExpression = 201, - BinaryExpression = 202, - ConditionalExpression = 203, - TemplateExpression = 204, - YieldExpression = 205, - SpreadElement = 206, - ClassExpression = 207, - OmittedExpression = 208, - ExpressionWithTypeArguments = 209, - AsExpression = 210, - NonNullExpression = 211, - MetaProperty = 212, - SyntheticExpression = 213, - TemplateSpan = 214, - SemicolonClassElement = 215, - Block = 216, - VariableStatement = 217, - EmptyStatement = 218, - ExpressionStatement = 219, - IfStatement = 220, - DoStatement = 221, - WhileStatement = 222, - ForStatement = 223, - ForInStatement = 224, - ForOfStatement = 225, - ContinueStatement = 226, - BreakStatement = 227, - ReturnStatement = 228, - WithStatement = 229, - SwitchStatement = 230, - LabeledStatement = 231, - ThrowStatement = 232, - TryStatement = 233, - DebuggerStatement = 234, - VariableDeclaration = 235, - VariableDeclarationList = 236, - FunctionDeclaration = 237, - ClassDeclaration = 238, - InterfaceDeclaration = 239, - TypeAliasDeclaration = 240, - EnumDeclaration = 241, - ModuleDeclaration = 242, - ModuleBlock = 243, - CaseBlock = 244, - NamespaceExportDeclaration = 245, - ImportEqualsDeclaration = 246, - ImportDeclaration = 247, - ImportClause = 248, - NamespaceImport = 249, - NamedImports = 250, - ImportSpecifier = 251, - ExportAssignment = 252, - ExportDeclaration = 253, - NamedExports = 254, - ExportSpecifier = 255, - MissingDeclaration = 256, - ExternalModuleReference = 257, - JsxElement = 258, - JsxSelfClosingElement = 259, - JsxOpeningElement = 260, - JsxClosingElement = 261, - JsxFragment = 262, - JsxOpeningFragment = 263, - JsxClosingFragment = 264, - JsxAttribute = 265, - JsxAttributes = 266, - JsxSpreadAttribute = 267, - JsxExpression = 268, - CaseClause = 269, - DefaultClause = 270, - HeritageClause = 271, - CatchClause = 272, - PropertyAssignment = 273, - ShorthandPropertyAssignment = 274, - SpreadAssignment = 275, - EnumMember = 276, - SourceFile = 277, - Bundle = 278, - UnparsedSource = 279, - InputFiles = 280, - JSDocTypeExpression = 281, - JSDocAllType = 282, - JSDocUnknownType = 283, - JSDocNullableType = 284, - JSDocNonNullableType = 285, - JSDocOptionalType = 286, - JSDocFunctionType = 287, - JSDocVariadicType = 288, - JSDocComment = 289, - JSDocTypeLiteral = 290, - JSDocSignature = 291, - JSDocTag = 292, - JSDocAugmentsTag = 293, - JSDocClassTag = 294, - JSDocCallbackTag = 295, - JSDocEnumTag = 296, - JSDocParameterTag = 297, - JSDocReturnTag = 298, - JSDocThisTag = 299, - JSDocTypeTag = 300, - JSDocTemplateTag = 301, - JSDocTypedefTag = 302, - JSDocPropertyTag = 303, - SyntaxList = 304, - NotEmittedStatement = 305, - PartiallyEmittedExpression = 306, - CommaListExpression = 307, - MergeDeclarationMarker = 308, - EndOfDeclarationMarker = 309, - Count = 310, + PrivateName = 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, + OfKeyword = 146, + QualifiedName = 147, + ComputedPropertyName = 148, + TypeParameter = 149, + Parameter = 150, + Decorator = 151, + PropertySignature = 152, + PropertyDeclaration = 153, + MethodSignature = 154, + MethodDeclaration = 155, + Constructor = 156, + GetAccessor = 157, + SetAccessor = 158, + CallSignature = 159, + ConstructSignature = 160, + IndexSignature = 161, + TypePredicate = 162, + TypeReference = 163, + FunctionType = 164, + ConstructorType = 165, + TypeQuery = 166, + TypeLiteral = 167, + ArrayType = 168, + TupleType = 169, + OptionalType = 170, + RestType = 171, + UnionType = 172, + IntersectionType = 173, + ConditionalType = 174, + InferType = 175, + ParenthesizedType = 176, + ThisType = 177, + TypeOperator = 178, + IndexedAccessType = 179, + MappedType = 180, + LiteralType = 181, + ImportType = 182, + ObjectBindingPattern = 183, + ArrayBindingPattern = 184, + BindingElement = 185, + ArrayLiteralExpression = 186, + ObjectLiteralExpression = 187, + PropertyAccessExpression = 188, + ElementAccessExpression = 189, + CallExpression = 190, + NewExpression = 191, + TaggedTemplateExpression = 192, + TypeAssertionExpression = 193, + ParenthesizedExpression = 194, + FunctionExpression = 195, + ArrowFunction = 196, + DeleteExpression = 197, + TypeOfExpression = 198, + VoidExpression = 199, + AwaitExpression = 200, + PrefixUnaryExpression = 201, + PostfixUnaryExpression = 202, + BinaryExpression = 203, + ConditionalExpression = 204, + TemplateExpression = 205, + YieldExpression = 206, + SpreadElement = 207, + ClassExpression = 208, + OmittedExpression = 209, + ExpressionWithTypeArguments = 210, + AsExpression = 211, + NonNullExpression = 212, + MetaProperty = 213, + SyntheticExpression = 214, + TemplateSpan = 215, + SemicolonClassElement = 216, + Block = 217, + VariableStatement = 218, + EmptyStatement = 219, + ExpressionStatement = 220, + IfStatement = 221, + DoStatement = 222, + WhileStatement = 223, + ForStatement = 224, + ForInStatement = 225, + ForOfStatement = 226, + ContinueStatement = 227, + BreakStatement = 228, + ReturnStatement = 229, + WithStatement = 230, + SwitchStatement = 231, + LabeledStatement = 232, + ThrowStatement = 233, + TryStatement = 234, + DebuggerStatement = 235, + VariableDeclaration = 236, + VariableDeclarationList = 237, + FunctionDeclaration = 238, + ClassDeclaration = 239, + InterfaceDeclaration = 240, + TypeAliasDeclaration = 241, + EnumDeclaration = 242, + ModuleDeclaration = 243, + ModuleBlock = 244, + CaseBlock = 245, + NamespaceExportDeclaration = 246, + ImportEqualsDeclaration = 247, + ImportDeclaration = 248, + ImportClause = 249, + NamespaceImport = 250, + NamedImports = 251, + ImportSpecifier = 252, + ExportAssignment = 253, + ExportDeclaration = 254, + NamedExports = 255, + ExportSpecifier = 256, + MissingDeclaration = 257, + ExternalModuleReference = 258, + JsxElement = 259, + JsxSelfClosingElement = 260, + JsxOpeningElement = 261, + JsxClosingElement = 262, + JsxFragment = 263, + JsxOpeningFragment = 264, + JsxClosingFragment = 265, + JsxAttribute = 266, + JsxAttributes = 267, + JsxSpreadAttribute = 268, + JsxExpression = 269, + CaseClause = 270, + DefaultClause = 271, + HeritageClause = 272, + CatchClause = 273, + PropertyAssignment = 274, + ShorthandPropertyAssignment = 275, + SpreadAssignment = 276, + EnumMember = 277, + SourceFile = 278, + Bundle = 279, + UnparsedSource = 280, + InputFiles = 281, + JSDocTypeExpression = 282, + JSDocAllType = 283, + JSDocUnknownType = 284, + JSDocNullableType = 285, + JSDocNonNullableType = 286, + JSDocOptionalType = 287, + JSDocFunctionType = 288, + JSDocVariadicType = 289, + JSDocComment = 290, + JSDocTypeLiteral = 291, + JSDocSignature = 292, + JSDocTag = 293, + JSDocAugmentsTag = 294, + JSDocClassTag = 295, + JSDocCallbackTag = 296, + JSDocEnumTag = 297, + JSDocParameterTag = 298, + JSDocReturnTag = 299, + JSDocThisTag = 300, + JSDocTypeTag = 301, + JSDocTemplateTag = 302, + JSDocTypedefTag = 303, + JSDocPropertyTag = 304, + SyntaxList = 305, + NotEmittedStatement = 306, + PartiallyEmittedExpression = 307, + CommaListExpression = 308, + MergeDeclarationMarker = 309, + EndOfDeclarationMarker = 310, + Count = 311, FirstAssignment = 58, LastAssignment = 70, FirstCompoundAssignment = 59, LastCompoundAssignment = 70, - FirstReservedWord = 72, - LastReservedWord = 107, - FirstKeyword = 72, - LastKeyword = 145, - FirstFutureReservedWord = 108, - LastFutureReservedWord = 116, - FirstTypeNode = 161, - LastTypeNode = 181, + FirstReservedWord = 73, + LastReservedWord = 108, + FirstKeyword = 73, + LastKeyword = 146, + FirstFutureReservedWord = 109, + LastFutureReservedWord = 117, + FirstTypeNode = 162, + LastTypeNode = 182, FirstPunctuation = 17, LastPunctuation = 70, FirstToken = 0, - LastToken = 145, + LastToken = 146, FirstTriviaToken = 2, LastTriviaToken = 7, FirstLiteralToken = 8, @@ -408,11 +409,11 @@ declare namespace ts { LastTemplateToken = 16, FirstBinaryOperator = 27, LastBinaryOperator = 70, - FirstNode = 146, - FirstJSDocNode = 281, - LastJSDocNode = 303, - FirstJSDocTagNode = 292, - LastJSDocTagNode = 303 + FirstNode = 147, + FirstJSDocNode = 282, + LastJSDocNode = 304, + FirstJSDocTagNode = 293, + LastJSDocTagNode = 304 } enum NodeFlags { None = 0, @@ -525,8 +526,8 @@ declare namespace ts { right: Identifier; } type EntityName = Identifier | QualifiedName; - type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName; - type DeclarationName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | BindingPattern; + type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | PrivateName; + type DeclarationName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | PrivateName | BindingPattern; interface Declaration extends Node { _declarationBrand: any; } @@ -541,6 +542,10 @@ declare namespace ts { kind: SyntaxKind.ComputedPropertyName; expression: Expression; } + interface PrivateName extends Declaration { + kind: SyntaxKind.PrivateName; + escapedText: __String; + } interface Decorator extends Node { kind: SyntaxKind.Decorator; parent: NamedDeclaration; @@ -616,6 +621,9 @@ declare namespace ts { type?: TypeNode; initializer?: Expression; } + interface PrivatePropertyDeclaration extends PropertyDeclaration { + name: PrivateName; + } interface ObjectLiteralElement extends NamedDeclaration { _objectLiteralBrandBrand: any; name?: PropertyName; @@ -1050,7 +1058,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; @@ -3206,9 +3214,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. @@ -3295,8 +3303,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; @@ -3468,6 +3478,7 @@ declare namespace ts { function isModifier(node: Node): node is Modifier; function isEntityName(node: Node): node is EntityName; function isPropertyName(node: Node): node is PropertyName; + function isPrivatePropertyDeclaration(node: Node): node is PrivatePropertyDeclaration; function isBindingName(node: Node): node is BindingName; function isFunctionLike(node: Node): node is SignatureDeclaration; function isClassElement(node: Node): node is ClassElement; @@ -3756,8 +3767,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; @@ -4539,6 +4550,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 fdd11aa3484ec..843acf786c2fc 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -145,261 +145,262 @@ declare namespace ts { BarEqualsToken = 69, CaretEqualsToken = 70, Identifier = 71, - BreakKeyword = 72, - CaseKeyword = 73, - CatchKeyword = 74, - ClassKeyword = 75, - ConstKeyword = 76, - ContinueKeyword = 77, - DebuggerKeyword = 78, - DefaultKeyword = 79, - DeleteKeyword = 80, - DoKeyword = 81, - ElseKeyword = 82, - EnumKeyword = 83, - ExportKeyword = 84, - ExtendsKeyword = 85, - FalseKeyword = 86, - FinallyKeyword = 87, - ForKeyword = 88, - FunctionKeyword = 89, - IfKeyword = 90, - ImportKeyword = 91, - InKeyword = 92, - InstanceOfKeyword = 93, - NewKeyword = 94, - NullKeyword = 95, - ReturnKeyword = 96, - SuperKeyword = 97, - SwitchKeyword = 98, - ThisKeyword = 99, - ThrowKeyword = 100, - TrueKeyword = 101, - TryKeyword = 102, - TypeOfKeyword = 103, - VarKeyword = 104, - VoidKeyword = 105, - WhileKeyword = 106, - WithKeyword = 107, - ImplementsKeyword = 108, - InterfaceKeyword = 109, - LetKeyword = 110, - PackageKeyword = 111, - PrivateKeyword = 112, - ProtectedKeyword = 113, - PublicKeyword = 114, - StaticKeyword = 115, - YieldKeyword = 116, - AbstractKeyword = 117, - AsKeyword = 118, - AnyKeyword = 119, - AsyncKeyword = 120, - AwaitKeyword = 121, - BooleanKeyword = 122, - ConstructorKeyword = 123, - DeclareKeyword = 124, - GetKeyword = 125, - InferKeyword = 126, - IsKeyword = 127, - KeyOfKeyword = 128, - ModuleKeyword = 129, - NamespaceKeyword = 130, - NeverKeyword = 131, - ReadonlyKeyword = 132, - RequireKeyword = 133, - NumberKeyword = 134, - ObjectKeyword = 135, - SetKeyword = 136, - StringKeyword = 137, - SymbolKeyword = 138, - TypeKeyword = 139, - UndefinedKeyword = 140, - UniqueKeyword = 141, - UnknownKeyword = 142, - FromKeyword = 143, - GlobalKeyword = 144, - OfKeyword = 145, - QualifiedName = 146, - ComputedPropertyName = 147, - TypeParameter = 148, - Parameter = 149, - Decorator = 150, - PropertySignature = 151, - PropertyDeclaration = 152, - MethodSignature = 153, - MethodDeclaration = 154, - Constructor = 155, - GetAccessor = 156, - SetAccessor = 157, - CallSignature = 158, - ConstructSignature = 159, - IndexSignature = 160, - TypePredicate = 161, - TypeReference = 162, - FunctionType = 163, - ConstructorType = 164, - TypeQuery = 165, - TypeLiteral = 166, - ArrayType = 167, - TupleType = 168, - OptionalType = 169, - RestType = 170, - UnionType = 171, - IntersectionType = 172, - ConditionalType = 173, - InferType = 174, - ParenthesizedType = 175, - ThisType = 176, - TypeOperator = 177, - IndexedAccessType = 178, - MappedType = 179, - LiteralType = 180, - ImportType = 181, - ObjectBindingPattern = 182, - ArrayBindingPattern = 183, - BindingElement = 184, - ArrayLiteralExpression = 185, - ObjectLiteralExpression = 186, - PropertyAccessExpression = 187, - ElementAccessExpression = 188, - CallExpression = 189, - NewExpression = 190, - TaggedTemplateExpression = 191, - TypeAssertionExpression = 192, - ParenthesizedExpression = 193, - FunctionExpression = 194, - ArrowFunction = 195, - DeleteExpression = 196, - TypeOfExpression = 197, - VoidExpression = 198, - AwaitExpression = 199, - PrefixUnaryExpression = 200, - PostfixUnaryExpression = 201, - BinaryExpression = 202, - ConditionalExpression = 203, - TemplateExpression = 204, - YieldExpression = 205, - SpreadElement = 206, - ClassExpression = 207, - OmittedExpression = 208, - ExpressionWithTypeArguments = 209, - AsExpression = 210, - NonNullExpression = 211, - MetaProperty = 212, - SyntheticExpression = 213, - TemplateSpan = 214, - SemicolonClassElement = 215, - Block = 216, - VariableStatement = 217, - EmptyStatement = 218, - ExpressionStatement = 219, - IfStatement = 220, - DoStatement = 221, - WhileStatement = 222, - ForStatement = 223, - ForInStatement = 224, - ForOfStatement = 225, - ContinueStatement = 226, - BreakStatement = 227, - ReturnStatement = 228, - WithStatement = 229, - SwitchStatement = 230, - LabeledStatement = 231, - ThrowStatement = 232, - TryStatement = 233, - DebuggerStatement = 234, - VariableDeclaration = 235, - VariableDeclarationList = 236, - FunctionDeclaration = 237, - ClassDeclaration = 238, - InterfaceDeclaration = 239, - TypeAliasDeclaration = 240, - EnumDeclaration = 241, - ModuleDeclaration = 242, - ModuleBlock = 243, - CaseBlock = 244, - NamespaceExportDeclaration = 245, - ImportEqualsDeclaration = 246, - ImportDeclaration = 247, - ImportClause = 248, - NamespaceImport = 249, - NamedImports = 250, - ImportSpecifier = 251, - ExportAssignment = 252, - ExportDeclaration = 253, - NamedExports = 254, - ExportSpecifier = 255, - MissingDeclaration = 256, - ExternalModuleReference = 257, - JsxElement = 258, - JsxSelfClosingElement = 259, - JsxOpeningElement = 260, - JsxClosingElement = 261, - JsxFragment = 262, - JsxOpeningFragment = 263, - JsxClosingFragment = 264, - JsxAttribute = 265, - JsxAttributes = 266, - JsxSpreadAttribute = 267, - JsxExpression = 268, - CaseClause = 269, - DefaultClause = 270, - HeritageClause = 271, - CatchClause = 272, - PropertyAssignment = 273, - ShorthandPropertyAssignment = 274, - SpreadAssignment = 275, - EnumMember = 276, - SourceFile = 277, - Bundle = 278, - UnparsedSource = 279, - InputFiles = 280, - JSDocTypeExpression = 281, - JSDocAllType = 282, - JSDocUnknownType = 283, - JSDocNullableType = 284, - JSDocNonNullableType = 285, - JSDocOptionalType = 286, - JSDocFunctionType = 287, - JSDocVariadicType = 288, - JSDocComment = 289, - JSDocTypeLiteral = 290, - JSDocSignature = 291, - JSDocTag = 292, - JSDocAugmentsTag = 293, - JSDocClassTag = 294, - JSDocCallbackTag = 295, - JSDocEnumTag = 296, - JSDocParameterTag = 297, - JSDocReturnTag = 298, - JSDocThisTag = 299, - JSDocTypeTag = 300, - JSDocTemplateTag = 301, - JSDocTypedefTag = 302, - JSDocPropertyTag = 303, - SyntaxList = 304, - NotEmittedStatement = 305, - PartiallyEmittedExpression = 306, - CommaListExpression = 307, - MergeDeclarationMarker = 308, - EndOfDeclarationMarker = 309, - Count = 310, + PrivateName = 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, + OfKeyword = 146, + QualifiedName = 147, + ComputedPropertyName = 148, + TypeParameter = 149, + Parameter = 150, + Decorator = 151, + PropertySignature = 152, + PropertyDeclaration = 153, + MethodSignature = 154, + MethodDeclaration = 155, + Constructor = 156, + GetAccessor = 157, + SetAccessor = 158, + CallSignature = 159, + ConstructSignature = 160, + IndexSignature = 161, + TypePredicate = 162, + TypeReference = 163, + FunctionType = 164, + ConstructorType = 165, + TypeQuery = 166, + TypeLiteral = 167, + ArrayType = 168, + TupleType = 169, + OptionalType = 170, + RestType = 171, + UnionType = 172, + IntersectionType = 173, + ConditionalType = 174, + InferType = 175, + ParenthesizedType = 176, + ThisType = 177, + TypeOperator = 178, + IndexedAccessType = 179, + MappedType = 180, + LiteralType = 181, + ImportType = 182, + ObjectBindingPattern = 183, + ArrayBindingPattern = 184, + BindingElement = 185, + ArrayLiteralExpression = 186, + ObjectLiteralExpression = 187, + PropertyAccessExpression = 188, + ElementAccessExpression = 189, + CallExpression = 190, + NewExpression = 191, + TaggedTemplateExpression = 192, + TypeAssertionExpression = 193, + ParenthesizedExpression = 194, + FunctionExpression = 195, + ArrowFunction = 196, + DeleteExpression = 197, + TypeOfExpression = 198, + VoidExpression = 199, + AwaitExpression = 200, + PrefixUnaryExpression = 201, + PostfixUnaryExpression = 202, + BinaryExpression = 203, + ConditionalExpression = 204, + TemplateExpression = 205, + YieldExpression = 206, + SpreadElement = 207, + ClassExpression = 208, + OmittedExpression = 209, + ExpressionWithTypeArguments = 210, + AsExpression = 211, + NonNullExpression = 212, + MetaProperty = 213, + SyntheticExpression = 214, + TemplateSpan = 215, + SemicolonClassElement = 216, + Block = 217, + VariableStatement = 218, + EmptyStatement = 219, + ExpressionStatement = 220, + IfStatement = 221, + DoStatement = 222, + WhileStatement = 223, + ForStatement = 224, + ForInStatement = 225, + ForOfStatement = 226, + ContinueStatement = 227, + BreakStatement = 228, + ReturnStatement = 229, + WithStatement = 230, + SwitchStatement = 231, + LabeledStatement = 232, + ThrowStatement = 233, + TryStatement = 234, + DebuggerStatement = 235, + VariableDeclaration = 236, + VariableDeclarationList = 237, + FunctionDeclaration = 238, + ClassDeclaration = 239, + InterfaceDeclaration = 240, + TypeAliasDeclaration = 241, + EnumDeclaration = 242, + ModuleDeclaration = 243, + ModuleBlock = 244, + CaseBlock = 245, + NamespaceExportDeclaration = 246, + ImportEqualsDeclaration = 247, + ImportDeclaration = 248, + ImportClause = 249, + NamespaceImport = 250, + NamedImports = 251, + ImportSpecifier = 252, + ExportAssignment = 253, + ExportDeclaration = 254, + NamedExports = 255, + ExportSpecifier = 256, + MissingDeclaration = 257, + ExternalModuleReference = 258, + JsxElement = 259, + JsxSelfClosingElement = 260, + JsxOpeningElement = 261, + JsxClosingElement = 262, + JsxFragment = 263, + JsxOpeningFragment = 264, + JsxClosingFragment = 265, + JsxAttribute = 266, + JsxAttributes = 267, + JsxSpreadAttribute = 268, + JsxExpression = 269, + CaseClause = 270, + DefaultClause = 271, + HeritageClause = 272, + CatchClause = 273, + PropertyAssignment = 274, + ShorthandPropertyAssignment = 275, + SpreadAssignment = 276, + EnumMember = 277, + SourceFile = 278, + Bundle = 279, + UnparsedSource = 280, + InputFiles = 281, + JSDocTypeExpression = 282, + JSDocAllType = 283, + JSDocUnknownType = 284, + JSDocNullableType = 285, + JSDocNonNullableType = 286, + JSDocOptionalType = 287, + JSDocFunctionType = 288, + JSDocVariadicType = 289, + JSDocComment = 290, + JSDocTypeLiteral = 291, + JSDocSignature = 292, + JSDocTag = 293, + JSDocAugmentsTag = 294, + JSDocClassTag = 295, + JSDocCallbackTag = 296, + JSDocEnumTag = 297, + JSDocParameterTag = 298, + JSDocReturnTag = 299, + JSDocThisTag = 300, + JSDocTypeTag = 301, + JSDocTemplateTag = 302, + JSDocTypedefTag = 303, + JSDocPropertyTag = 304, + SyntaxList = 305, + NotEmittedStatement = 306, + PartiallyEmittedExpression = 307, + CommaListExpression = 308, + MergeDeclarationMarker = 309, + EndOfDeclarationMarker = 310, + Count = 311, FirstAssignment = 58, LastAssignment = 70, FirstCompoundAssignment = 59, LastCompoundAssignment = 70, - FirstReservedWord = 72, - LastReservedWord = 107, - FirstKeyword = 72, - LastKeyword = 145, - FirstFutureReservedWord = 108, - LastFutureReservedWord = 116, - FirstTypeNode = 161, - LastTypeNode = 181, + FirstReservedWord = 73, + LastReservedWord = 108, + FirstKeyword = 73, + LastKeyword = 146, + FirstFutureReservedWord = 109, + LastFutureReservedWord = 117, + FirstTypeNode = 162, + LastTypeNode = 182, FirstPunctuation = 17, LastPunctuation = 70, FirstToken = 0, - LastToken = 145, + LastToken = 146, FirstTriviaToken = 2, LastTriviaToken = 7, FirstLiteralToken = 8, @@ -408,11 +409,11 @@ declare namespace ts { LastTemplateToken = 16, FirstBinaryOperator = 27, LastBinaryOperator = 70, - FirstNode = 146, - FirstJSDocNode = 281, - LastJSDocNode = 303, - FirstJSDocTagNode = 292, - LastJSDocTagNode = 303 + FirstNode = 147, + FirstJSDocNode = 282, + LastJSDocNode = 304, + FirstJSDocTagNode = 293, + LastJSDocTagNode = 304 } enum NodeFlags { None = 0, @@ -525,8 +526,8 @@ declare namespace ts { right: Identifier; } type EntityName = Identifier | QualifiedName; - type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName; - type DeclarationName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | BindingPattern; + type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | PrivateName; + type DeclarationName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | PrivateName | BindingPattern; interface Declaration extends Node { _declarationBrand: any; } @@ -541,6 +542,10 @@ declare namespace ts { kind: SyntaxKind.ComputedPropertyName; expression: Expression; } + interface PrivateName extends Declaration { + kind: SyntaxKind.PrivateName; + escapedText: __String; + } interface Decorator extends Node { kind: SyntaxKind.Decorator; parent: NamedDeclaration; @@ -616,6 +621,9 @@ declare namespace ts { type?: TypeNode; initializer?: Expression; } + interface PrivatePropertyDeclaration extends PropertyDeclaration { + name: PrivateName; + } interface ObjectLiteralElement extends NamedDeclaration { _objectLiteralBrandBrand: any; name?: PropertyName; @@ -1050,7 +1058,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; @@ -3206,9 +3214,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. @@ -3295,8 +3303,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; @@ -3468,6 +3478,7 @@ declare namespace ts { function isModifier(node: Node): node is Modifier; function isEntityName(node: Node): node is EntityName; function isPropertyName(node: Node): node is PropertyName; + function isPrivatePropertyDeclaration(node: Node): node is PrivatePropertyDeclaration; function isBindingName(node: Node): node is BindingName; function isFunctionLike(node: Node): node is SignatureDeclaration; function isClassElement(node: Node): node is ClassElement; @@ -3756,8 +3767,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; @@ -4539,6 +4550,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/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/dynamicNamesErrors.js b/tests/baselines/reference/dynamicNamesErrors.js index ff6bdec604f31..f2b610de875e0 100644 --- a/tests/baselines/reference/dynamicNamesErrors.js +++ b/tests/baselines/reference/dynamicNamesErrors.js @@ -73,9 +73,11 @@ const y = Symbol(); const z = Symbol(); const w = Symbol(); class ClassMemberVisibility { + static [x]; static [y]() { return 0; } static get [z]() { return 0; } static set [w](value) { } + [x]; [y]() { return 0; } get [z]() { return 0; } set [w](value) { } diff --git a/tests/baselines/reference/importCallExpression4ESNext.js b/tests/baselines/reference/importCallExpression4ESNext.js index d5d4a51d69f0b..656f63cf3f21f 100644 --- a/tests/baselines/reference/importCallExpression4ESNext.js +++ b/tests/baselines/reference/importCallExpression4ESNext.js @@ -35,9 +35,7 @@ export function foo() { return "foo"; } export function backup() { return "backup"; } //// [2.js] class C { - constructor() { - this.myModule = import("./0"); - } + myModule = import("./0"); method() { const loadAsync = import("./0"); this.myModule.then(Zero => { diff --git a/tests/baselines/reference/importCallExpressionAsyncESNext.js b/tests/baselines/reference/importCallExpressionAsyncESNext.js index 7d5f2b0ed25a7..8c7b34c00745c 100644 --- a/tests/baselines/reference/importCallExpressionAsyncESNext.js +++ b/tests/baselines/reference/importCallExpressionAsyncESNext.js @@ -43,13 +43,11 @@ export const obj = { } }; export class cl2 { - constructor() { - this.p = { - m: async () => { - const req = await import('./test'); // FOUR - } - }; - } + p = { + m: async () => { + const req = await import('./test'); // FOUR + } + }; } export const l = async () => { const req = await import('./test'); // FIVE diff --git a/tests/baselines/reference/importCallExpressionInAMD4.js b/tests/baselines/reference/importCallExpressionInAMD4.js index 2fe29e5ae065a..64c6be888939e 100644 --- a/tests/baselines/reference/importCallExpressionInAMD4.js +++ b/tests/baselines/reference/importCallExpressionInAMD4.js @@ -63,9 +63,7 @@ define(["require", "exports"], function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class C { - constructor() { - this.myModule = new Promise((resolve_1, reject_1) => { require(["./0"], resolve_1, reject_1); }); - } + myModule = new Promise((resolve_1, reject_1) => { require(["./0"], resolve_1, reject_1); }); method() { const loadAsync = new Promise((resolve_2, reject_2) => { require(["./0"], resolve_2, reject_2); }); this.myModule.then(Zero => { @@ -78,9 +76,7 @@ define(["require", "exports"], function (require, exports) { } } class D { - constructor() { - this.myModule = new Promise((resolve_4, reject_4) => { require(["./0"], resolve_4, reject_4); }); - } + myModule = new Promise((resolve_4, reject_4) => { require(["./0"], resolve_4, reject_4); }); method() { const loadAsync = new Promise((resolve_5, reject_5) => { require(["./0"], resolve_5, reject_5); }); this.myModule.then(Zero => { diff --git a/tests/baselines/reference/importCallExpressionInCJS5.js b/tests/baselines/reference/importCallExpressionInCJS5.js index b32b0e52c50f7..4e53f73ce1237 100644 --- a/tests/baselines/reference/importCallExpressionInCJS5.js +++ b/tests/baselines/reference/importCallExpressionInCJS5.js @@ -58,9 +58,7 @@ exports.backup = backup; "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class C { - constructor() { - this.myModule = Promise.resolve().then(() => require("./0")); - } + myModule = Promise.resolve().then(() => require("./0")); method() { const loadAsync = Promise.resolve().then(() => require("./0")); this.myModule.then(Zero => { @@ -73,9 +71,7 @@ class C { } } class D { - constructor() { - this.myModule = Promise.resolve().then(() => require("./0")); - } + myModule = Promise.resolve().then(() => require("./0")); method() { const loadAsync = Promise.resolve().then(() => require("./0")); this.myModule.then(Zero => { diff --git a/tests/baselines/reference/importCallExpressionInSystem4.js b/tests/baselines/reference/importCallExpressionInSystem4.js index 55af57174bdf3..7f9430bbc2962 100644 --- a/tests/baselines/reference/importCallExpressionInSystem4.js +++ b/tests/baselines/reference/importCallExpressionInSystem4.js @@ -78,9 +78,7 @@ System.register([], function (exports_1, context_1) { setters: [], execute: function () { C = class C { - constructor() { - this.myModule = context_1.import("./0"); - } + myModule = context_1.import("./0"); method() { const loadAsync = context_1.import("./0"); this.myModule.then(Zero => { @@ -93,9 +91,7 @@ System.register([], function (exports_1, context_1) { } }; D = class D { - constructor() { - this.myModule = context_1.import("./0"); - } + myModule = context_1.import("./0"); method() { const loadAsync = context_1.import("./0"); this.myModule.then(Zero => { diff --git a/tests/baselines/reference/importCallExpressionInUMD4.js b/tests/baselines/reference/importCallExpressionInUMD4.js index 70a574f03028e..9ecfa77eb45d9 100644 --- a/tests/baselines/reference/importCallExpressionInUMD4.js +++ b/tests/baselines/reference/importCallExpressionInUMD4.js @@ -88,9 +88,7 @@ export class D { var __syncRequire = typeof module === "object" && typeof module.exports === "object"; Object.defineProperty(exports, "__esModule", { value: true }); class C { - constructor() { - this.myModule = __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_1, reject_1) => { require(["./0"], resolve_1, reject_1); }); - } + myModule = __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_1, reject_1) => { require(["./0"], resolve_1, reject_1); }); method() { const loadAsync = __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_2, reject_2) => { require(["./0"], resolve_2, reject_2); }); this.myModule.then(Zero => { @@ -103,9 +101,7 @@ export class D { } } class D { - constructor() { - this.myModule = __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_4, reject_4) => { require(["./0"], resolve_4, reject_4); }); - } + myModule = __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_4, reject_4) => { require(["./0"], resolve_4, reject_4); }); method() { const loadAsync = __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_5, reject_5) => { require(["./0"], resolve_5, reject_5); }); this.myModule.then(Zero => { 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/potentiallyUncalledDecorators.js b/tests/baselines/reference/potentiallyUncalledDecorators.js index b69f848a8c933..eb099ba9d5f0c 100644 --- a/tests/baselines/reference/potentiallyUncalledDecorators.js +++ b/tests/baselines/reference/potentiallyUncalledDecorators.js @@ -86,16 +86,20 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, return c > 3 && r && Object.defineProperty(target, key, r), r; }; class FooComponent { + foo; } __decorate([ Input ], FooComponent.prototype, "foo", void 0); class Person { + person; + any; } __decorate([ tracked ], Person.prototype, "person", void 0); class MultiplyByTwo { + args; get multiplied() { return this.args.number * 2; } @@ -104,6 +108,7 @@ __decorate([ tracked('args') ], MultiplyByTwo.prototype, "multiplied", null); let A = class A { + foo; bar() { } }; __decorate([ @@ -116,6 +121,7 @@ A = __decorate([ noArgs ], A); let B = class B { + foo; bar() { } }; __decorate([ @@ -128,6 +134,7 @@ B = __decorate([ allRest ], B); let C = class C { + foo; bar() { } }; __decorate([ @@ -140,6 +147,7 @@ C = __decorate([ oneOptional ], C); let D = class D { + foo; bar() { } }; __decorate([ @@ -152,6 +160,7 @@ D = __decorate([ twoOptional ], D); let E = class E { + foo; bar() { } }; __decorate([ @@ -164,6 +173,7 @@ E = __decorate([ threeOptional ], E); let F = class F { + foo; bar() { } }; __decorate([ @@ -176,6 +186,7 @@ F = __decorate([ oneOptionalWithRest ], F); let G = class G { + foo; bar() { } }; __decorate([ diff --git a/tests/baselines/reference/privateNameAndIndexSignature.errors.txt b/tests/baselines/reference/privateNameAndIndexSignature.errors.txt new file mode 100644 index 0000000000000..1b4895bf23d64 --- /dev/null +++ b/tests/baselines/reference/privateNameAndIndexSignature.errors.txt @@ -0,0 +1,13 @@ +tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts(4,14): error TS2339: Property '#f' does not exist on type 'A'. + + +==== tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts (1 errors) ==== + 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..d1271acca8ce9 --- /dev/null +++ b/tests/baselines/reference/privateNameAndIndexSignature.js @@ -0,0 +1,16 @@ +//// [privateNameAndIndexSignature.ts] +class A { + [k: string]: any; + constructor(message: string) { + this.#f = 3 // Error Property '#f' does not exist on type 'A'. + } +} + + +//// [privateNameAndIndexSignature.js] +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..d8a153c04270e --- /dev/null +++ b/tests/baselines/reference/privateNameAndIndexSignature.symbols @@ -0,0 +1,15 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts === +class A { +>A : Symbol(A, Decl(privateNameAndIndexSignature.ts, 0, 0)) + + [k: string]: any; +>k : Symbol(k, Decl(privateNameAndIndexSignature.ts, 1, 5)) + + constructor(message: string) { +>message : Symbol(message, Decl(privateNameAndIndexSignature.ts, 2, 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..d663d5b9517cc --- /dev/null +++ b/tests/baselines/reference/privateNameAndIndexSignature.types @@ -0,0 +1,18 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts === +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/privateNameField.js b/tests/baselines/reference/privateNameField.js new file mode 100644 index 0000000000000..5fc6e5b50c648 --- /dev/null +++ b/tests/baselines/reference/privateNameField.js @@ -0,0 +1,18 @@ +//// [privateNameField.ts] +class A { + #name: string; + constructor(name: string) { + this.#name = name; + } +} + +//// [privateNameField.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 _name; +var A = /** @class */ (function () { + function A(name) { + _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..a9ab08325a0e1 --- /dev/null +++ b/tests/baselines/reference/privateNameField.symbols @@ -0,0 +1,16 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameField.ts === +class A { +>A : Symbol(A, Decl(privateNameField.ts, 0, 0)) + + #name: string; +>#name : Symbol(A[#name], Decl(privateNameField.ts, 0, 9)) + + constructor(name: string) { +>name : Symbol(name, Decl(privateNameField.ts, 2, 16)) + + this.#name = name; +>this.#name : Symbol(A[#name], Decl(privateNameField.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameField.ts, 0, 0)) +>name : Symbol(name, Decl(privateNameField.ts, 2, 16)) + } +} diff --git a/tests/baselines/reference/privateNameField.types b/tests/baselines/reference/privateNameField.types new file mode 100644 index 0000000000000..1eb30eda52590 --- /dev/null +++ b/tests/baselines/reference/privateNameField.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameField.ts === +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..ea011b99d9a27 --- /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..2440403e75921 --- /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..726a63187e70b --- /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/privateNameFieldDeclaration.js b/tests/baselines/reference/privateNameFieldDeclaration.js new file mode 100644 index 0000000000000..7b7060bdcbfb5 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldDeclaration.js @@ -0,0 +1,14 @@ +//// [privateNameFieldDeclaration.ts] +class A { + #name: string; +} + + +//// [privateNameFieldDeclaration.js] +var _name; +var A = /** @class */ (function () { + function A() { + } + return A; +}()); +_name = new WeakMap(); diff --git a/tests/baselines/reference/privateNameFieldDeclaration.symbols b/tests/baselines/reference/privateNameFieldDeclaration.symbols new file mode 100644 index 0000000000000..bf24e84102a75 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldDeclaration.symbols @@ -0,0 +1,8 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldDeclaration.ts === +class A { +>A : Symbol(A, Decl(privateNameFieldDeclaration.ts, 0, 0)) + + #name: string; +>#name : Symbol(A[#name], Decl(privateNameFieldDeclaration.ts, 0, 9)) +} + diff --git a/tests/baselines/reference/privateNameFieldDeclaration.types b/tests/baselines/reference/privateNameFieldDeclaration.types new file mode 100644 index 0000000000000..ce6312a793ea6 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldDeclaration.types @@ -0,0 +1,8 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldDeclaration.ts === +class A { +>A : A + + #name: string; +>#name : string +} + diff --git a/tests/baselines/reference/privateNameFieldDestructuredBinding.js b/tests/baselines/reference/privateNameFieldDestructuredBinding.js new file mode 100644 index 0000000000000..e76d7978b8d4a --- /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 _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, 1); + var _a, _b; + var y; + (_a = this.testObject(), { set value(x) { _classPrivateFieldGet(this, _field) = x; } }.value = _a.x, y = _a.y); + (_b = this.testArray(), { set value(x) { _classPrivateFieldGet(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..ced97920fca56 --- /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..8a51e8b990997 --- /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/shebangError.errors.txt b/tests/baselines/reference/shebangError.errors.txt index e8197d8bc5f53..894739d5a4170 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' 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' or an enum type. diff --git a/tests/baselines/reference/spreadMethods.js b/tests/baselines/reference/spreadMethods.js index b35619361f1f0..e49bc557961b7 100644 --- a/tests/baselines/reference/spreadMethods.js +++ b/tests/baselines/reference/spreadMethods.js @@ -43,9 +43,7 @@ sso.g; // ok //// [spreadMethods.js] class K { - constructor() { - this.p = 12; - } + p = 12; m() { } get g() { return 0; } } 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/taggedTemplatesWithTypeArguments2.js b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js index bc170467fa8be..84817451a6d79 100644 --- a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js @@ -53,6 +53,9 @@ const d = (new tag `${"hello"} ${"world"}`)(100, 200); */ const e = new tag `hello`(); class SomeBase { + a; + b; + c; } class SomeDerived extends SomeBase { constructor() { diff --git a/tests/baselines/reference/transformApi/transformsCorrectly.rewrittenNamespaceFollowingClass.js b/tests/baselines/reference/transformApi/transformsCorrectly.rewrittenNamespaceFollowingClass.js index 3f2dd6cdb56fb..0698fbf19d14e 100644 --- a/tests/baselines/reference/transformApi/transformsCorrectly.rewrittenNamespaceFollowingClass.js +++ b/tests/baselines/reference/transformApi/transformsCorrectly.rewrittenNamespaceFollowingClass.js @@ -1,9 +1,7 @@ class C { - constructor() { - this.foo = 10; - } + foo = 10; + static bar = 20; } -C.bar = 20; (function (C) { C.x = 10; })(C || (C = {})); diff --git a/tests/baselines/reference/uniqueSymbols.js b/tests/baselines/reference/uniqueSymbols.js index 0e6bde4fe474c..62a8a3ab69e05 100644 --- a/tests/baselines/reference/uniqueSymbols.js +++ b/tests/baselines/reference/uniqueSymbols.js @@ -308,14 +308,13 @@ async function* asyncGenFuncYieldLetCall() { yield letCall; } async function* asyncGenFuncYieldVarCall() { yield varCall; } // classes class C { - constructor() { - this.readonlyCall = Symbol(); - this.readwriteCall = Symbol(); - } + static readonlyStaticCall = Symbol(); + static readonlyStaticType; + static readonlyStaticTypeAndCall = Symbol(); + static readwriteStaticCall = Symbol(); + readonlyCall = Symbol(); + readwriteCall = Symbol(); } -C.readonlyStaticCall = Symbol(); -C.readonlyStaticTypeAndCall = Symbol(); -C.readwriteStaticCall = Symbol(); const constInitToCReadonlyStaticCall = C.readonlyStaticCall; const constInitToCReadonlyStaticType = C.readonlyStaticType; const constInitToCReadonlyStaticTypeAndCall = C.readonlyStaticTypeAndCall; @@ -364,26 +363,24 @@ const o2 = { }; // property initializers class C0 { - constructor() { - this.a = s; - this.b = N.s; - this.c = N["s"]; - this.d = s; - this.e = N.s; - this.f = N["s"]; - } + static a = s; + static b = N.s; + static c = N["s"]; + static d = s; + static e = N.s; + static f = N["s"]; + a = s; + b = N.s; + c = N["s"]; + d = s; + e = N.s; + f = N["s"]; method1() { return s; } async method2() { return s; } async *method3() { yield s; } *method4() { yield s; } method5(p = s) { return p; } } -C0.a = s; -C0.b = N.s; -C0.c = N["s"]; -C0.d = s; -C0.e = N.s; -C0.f = N["s"]; // non-widening positions // element access o[s]; @@ -410,8 +407,11 @@ Math.random() * 2 ? N["s"] : "a"; [N.s]: "b", }); class C1 { + static [s]; + static [N.s]; + [s]; + [N.s]; } -N.s, N.s; const o3 = { method1() { return s; // return type should not widen due to contextual type diff --git a/tests/baselines/reference/uniqueSymbolsDeclarations.js b/tests/baselines/reference/uniqueSymbolsDeclarations.js index 02a692aa9ff63..af3b56f106da4 100644 --- a/tests/baselines/reference/uniqueSymbolsDeclarations.js +++ b/tests/baselines/reference/uniqueSymbolsDeclarations.js @@ -283,14 +283,13 @@ async function* asyncGenFuncYieldLetCall() { yield letCall; } async function* asyncGenFuncYieldVarCall() { yield varCall; } // classes class C { - constructor() { - this.readonlyCall = Symbol(); - this.readwriteCall = Symbol(); - } + static readonlyStaticCall = Symbol(); + static readonlyStaticType; + static readonlyStaticTypeAndCall = Symbol(); + static readwriteStaticCall = Symbol(); + readonlyCall = Symbol(); + readwriteCall = Symbol(); } -C.readonlyStaticCall = Symbol(); -C.readonlyStaticTypeAndCall = Symbol(); -C.readwriteStaticCall = Symbol(); const constInitToCReadonlyStaticCall = C.readonlyStaticCall; const constInitToCReadonlyStaticType = C.readonlyStaticType; const constInitToCReadonlyStaticTypeAndCall = C.readonlyStaticTypeAndCall; @@ -339,26 +338,24 @@ const o2 = { }; // property initializers class C0 { - constructor() { - this.a = s; - this.b = N.s; - this.c = N["s"]; - this.d = s; - this.e = N.s; - this.f = N["s"]; - } + static a = s; + static b = N.s; + static c = N["s"]; + static d = s; + static e = N.s; + static f = N["s"]; + a = s; + b = N.s; + c = N["s"]; + d = s; + e = N.s; + f = N["s"]; method1() { return s; } async method2() { return s; } async *method3() { yield s; } *method4() { yield s; } method5(p = s) { return p; } } -C0.a = s; -C0.b = N.s; -C0.c = N["s"]; -C0.d = s; -C0.e = N.s; -C0.f = N["s"]; // non-widening positions // element access o[s]; @@ -385,8 +382,11 @@ Math.random() * 2 ? N["s"] : "a"; [N.s]: "b", }); class C1 { + static [s]; + static [N.s]; + [s]; + [N.s]; } -N.s, N.s; const o4 = { method1() { return s; // return type should not widen due to contextual type diff --git a/tests/baselines/reference/uniqueSymbolsDeclarationsErrors.js b/tests/baselines/reference/uniqueSymbolsDeclarationsErrors.js index 871d8977a9de2..46227ddf8e782 100644 --- a/tests/baselines/reference/uniqueSymbolsDeclarationsErrors.js +++ b/tests/baselines/reference/uniqueSymbolsDeclarationsErrors.js @@ -84,6 +84,8 @@ function funcInferredReturnType(obj) { } exports.funcInferredReturnType = funcInferredReturnType; class ClassWithPrivateNamedProperties { + [s]; + static [s]; } exports.ClassWithPrivateNamedProperties = ClassWithPrivateNamedProperties; class ClassWithPrivateNamedMethods { diff --git a/tests/baselines/reference/uniqueSymbolsErrors.js b/tests/baselines/reference/uniqueSymbolsErrors.js index ad3c5c2006538..ed17e52719a0e 100644 --- a/tests/baselines/reference/uniqueSymbolsErrors.js +++ b/tests/baselines/reference/uniqueSymbolsErrors.js @@ -91,6 +91,8 @@ const shouldNotBeAssignable: string = Symbol(); // classes class InvalidClass { constructor(invalidConstructorArgType) { } + invalidReadonlyPropertyType; + invalidPropertyType; invalidArgType(arg) { return; } invalidRestArgType(...args) { return; } invalidReturnType() { return; } @@ -100,6 +102,7 @@ class InvalidClass { invalidTypeParameterDefault() { return; } get invalidGetter() { return; } set invalidSetter(arg) { return; } + static invalidStaticPropertyType; static invalidStaticArgType(arg) { return; } static invalidStaticRestArgType(...args) { return; } static invalidStaticReturnType() { return; } 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..d4c0b8ad46efb --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts @@ -0,0 +1,6 @@ +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/privateNameField.ts b/tests/cases/conformance/classes/members/privateNames/privateNameField.ts new file mode 100644 index 0000000000000..02e449fb3e002 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameField.ts @@ -0,0 +1,6 @@ +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..2237195ddc9ec --- /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..02047baa6c4ad --- /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..2d0240340bfdf --- /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/privateNameFieldDeclaration.ts b/tests/cases/conformance/classes/members/privateNames/privateNameFieldDeclaration.ts new file mode 100644 index 0000000000000..e66fe5d894b64 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameFieldDeclaration.ts @@ -0,0 +1,3 @@ +class A { + #name: string; +} 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..4c746be2cd67a --- /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..2e3715f43bc90 --- /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/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