From b0b5d4483f5042a0f246ce2d2449760966d59089 Mon Sep 17 00:00:00 2001 From: Joseph Watts Date: Thu, 20 Sep 2018 04:14:56 -0400 Subject: [PATCH 1/6] Move class property transformation into new transformer. Signed-off-by: Joseph Watts --- src/compiler/binder.ts | 21 +- src/compiler/transformer.ts | 1 + src/compiler/transformers/classProperties.ts | 489 +++++++++++++++++ src/compiler/transformers/ts.ts | 493 ++++++------------ src/compiler/transformers/utilities.ts | 80 +++ src/compiler/tsconfig.json | 1 + ...tPrivateSymbolCausesVarDeclarationEmit2.js | 4 +- .../decoratorsOnComputedProperties.js | 145 +++--- .../reference/systemModuleTargetES6.js | 2 +- ...arationEmitUniqueSymbolPartialStatement.js | 2 +- 10 files changed, 804 insertions(+), 434 deletions(-) create mode 100644 src/compiler/transformers/classProperties.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index ff11b09f0fe2a..2c76f9838633d 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -3231,8 +3231,7 @@ namespace ts { // A ClassDeclaration is ES6 syntax. transformFlags = subtreeFlags | TransformFlags.AssertES2015; - // A class with a parameter property assignment, property initializer, computed property name, or decorator is - // TypeScript syntax. + // A class with a parameter property assignment or decorator is TypeScript syntax. // An exported declaration may be TypeScript syntax, but is handled by the visitor // for a namespace declaration. if ((subtreeFlags & TransformFlags.ContainsTypeScriptClassSyntax) @@ -3249,8 +3248,7 @@ namespace ts { // A ClassExpression is ES6 syntax. let transformFlags = subtreeFlags | TransformFlags.AssertES2015; - // A class with a parameter property assignment, property initializer, or decorator is - // TypeScript syntax. + // A class with a parameter property assignment or decorator is TypeScript syntax. if (subtreeFlags & TransformFlags.ContainsTypeScriptClassSyntax || node.typeParameters) { transformFlags |= TransformFlags.AssertTypeScript; @@ -3340,7 +3338,6 @@ namespace ts { || hasModifier(node, ModifierFlags.TypeScriptModifier) || node.typeParameters || node.type - || (node.name && isComputedPropertyName(node.name)) // While computed method names aren't typescript, the TS transform must visit them to emit property declarations correctly || !node.body) { transformFlags |= TransformFlags.AssertTypeScript; } @@ -3371,7 +3368,6 @@ namespace ts { if (node.decorators || hasModifier(node, ModifierFlags.TypeScriptModifier) || node.type - || (node.name && isComputedPropertyName(node.name)) // While computed accessor names aren't typescript, the TS transform must visit them to emit property declarations correctly || !node.body) { transformFlags |= TransformFlags.AssertTypeScript; } @@ -3386,12 +3382,15 @@ namespace ts { } function computePropertyDeclaration(node: PropertyDeclaration, subtreeFlags: TransformFlags) { - // A PropertyDeclaration is TypeScript syntax. - let transformFlags = subtreeFlags | TransformFlags.AssertTypeScript; + let transformFlags = subtreeFlags; + + // Decorators, TypeScript-specific modifiers, and type annotations are TypeScript syntax. + if (some(node.decorators) || hasModifier(node, ModifierFlags.TypeScriptModifier) || node.type) { + transformFlags |= TransformFlags.AssertTypeScript; + } - // If the PropertyDeclaration has an initializer or a computed name, we need to inform its ancestor - // so that it handle the transformation. - if (node.initializer || isComputedPropertyName(node.name)) { + // Hoisted variables related to class properties should live within the TypeScript class wrapper. + if (isComputedPropertyName(node.name) || (hasStaticModifier(node) && node.initializer)) { transformFlags |= TransformFlags.ContainsTypeScriptClassSyntax; } diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index d8a2848bcc304..1d1895e6ace87 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -33,6 +33,7 @@ namespace ts { addRange(transformers, customTransformers && customTransformers.before); transformers.push(transformTypeScript); + transformers.push(transformClassProperties); if (jsx === JsxEmit.React) { transformers.push(transformJsx); diff --git a/src/compiler/transformers/classProperties.ts b/src/compiler/transformers/classProperties.ts new file mode 100644 index 0000000000000..df05710475ab9 --- /dev/null +++ b/src/compiler/transformers/classProperties.ts @@ -0,0 +1,489 @@ +/*@internal*/ +namespace ts { + const enum ClassPropertySubstitutionFlags { + /** + * Enables substitutions for class expressions with static fields + * which have initializers that reference the class name. + */ + ClassAliases = 1 << 0, + } + /** + * Transforms ECMAScript Class Syntax. + * TypeScript parameter property syntax is transformed in the TypeScript transformer. + * For now, this transforms public field declarations using TypeScript class semantics + * (where the declarations get elided and initializers are transformed as assignments in the constructor). + * Eventually, this transform will change to the ECMAScript semantics (with Object.defineProperty). + */ + export function transformClassProperties(context: TransformationContext) { + const { + hoistVariableDeclaration, + endLexicalEnvironment, + resumeLexicalEnvironment + } = context; + const resolver = context.getEmitResolver(); + + const previousOnSubstituteNode = context.onSubstituteNode; + context.onSubstituteNode = onSubstituteNode; + + let enabledSubstitutions: ClassPropertySubstitutionFlags; + + let classAliases: Identifier[]; + + /** + * Tracks what computed name expressions originating from elided names must be inlined + * at the next execution site, in document order + */ + let pendingExpressions: Expression[] | undefined; + + /** + * Tracks what computed name expression statements and static property initializers must be + * emitted at the next execution site, in document order (for decorated classes). + */ + let pendingStatements: Statement[] | undefined; + + return chainBundle(transformSourceFile); + + function transformSourceFile(node: SourceFile) { + if (node.isDeclarationFile) { + return node; + } + const visited = visitEachChild(node, visitor, context); + addEmitHelpers(visited, context.readEmitHelpers()); + return visited; + } + + function visitor(node: Node): VisitResult { + switch (node.kind) { + case SyntaxKind.ClassExpression: + 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); + } + return visitEachChild(node, visitor, context); + } + + /** + * Specialized visitor that visits the immediate children of a class with ESNext syntax. + * + * @param node The node to visit. + */ + function classElementVisitor(node: Node): VisitResult { + switch (node.kind) { + case SyntaxKind.Constructor: + // Constructors for classes using ESNext syntax (like class properties) + // are transformed in `visitClassDeclaration` or `visitClassExpression`. + // We elide them here. The default visitor checks the transformFlags to + // determine whether the node contains ESNext syntax, so it can skip over + // constructors. + return undefined; + + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.IndexSignature: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.MethodDeclaration: + // Fallback to the default visit behavior. + return visitor(node); + + case SyntaxKind.SemicolonClassElement: + return node; + + default: + return Debug.failBadSyntaxKind(node); + } + } + + function visitVariableStatement(node: VariableStatement) { + const savedPendingStatements = pendingStatements; + pendingStatements = []; + + const visitedNode = visitEachChild(node, visitor, context); + const statement = some(pendingStatements) ? + [visitedNode, ...pendingStatements] : + visitedNode; + + pendingStatements = savedPendingStatements; + return statement; + } + + function visitComputedPropertyName(name: ComputedPropertyName) { + let node = visitEachChild(name, visitor, context); + if (some(pendingExpressions)) { + const expressions = pendingExpressions; + expressions.push(name.expression); + pendingExpressions = []; + node = updateComputedPropertyName( + node, + inlineExpressions(expressions) + ); + } + return node; + } + + function visitPropertyDeclaration(node: PropertyDeclaration) { + Debug.assert(!some(node.decorators)); + // Create a temporary variable to store a computed property name (if necessary). + // If it's not inlineable, then we emit an expression after the class which assigns + // the property name to the temporary variable. + const expr = getPropertyNameExpressionIfNeeded(node.name, !!node.initializer); + if (expr && !isSimpleInlineableExpression(expr)) { + (pendingExpressions || (pendingExpressions = [])).push(expr); + } + return undefined; + } + + function visitClassDeclaration(node: ClassDeclaration) { + const savedPendingExpressions = pendingExpressions; + pendingExpressions = undefined; + + 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))); + } + 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; + + // If this class expression is a transformation of a decorated class declaration, + // then we want to output the pendingExpressions as statements, not as inlined + // expressions with the class statement. + // + // In this case, we use pendingStatements to produce the same output as the + // class declaration transformation. The VariableStatement visitor will insert + // these statements after the class expression variable statement. + const isDecoratedClassDeclaration = isClassDeclaration(getOriginalNode(node)); + + const staticProperties = getInitializedProperties(node, /*isStatic*/ true); + const extendsClauseElement = getEffectiveBaseTypeNode(node); + const isDerivedClass = !!(extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword); + + const classExpression = updateClassExpression( + node, + node.modifiers, + node.name, + node.typeParameters, + visitNodes(node.heritageClauses, visitor, isHeritageClause), + transformClassMembers(node, isDerivedClass) + ); + + if (some(staticProperties) || some(pendingExpressions)) { + if (isDecoratedClassDeclaration) { + Debug.assertDefined(pendingStatements, "Decorated classes transformed by TypeScript are expected to be within a variable declaration."); + + // Write any pending expressions from elided or moved computed property names + if (pendingStatements && pendingExpressions && some(pendingExpressions)) { + pendingStatements.push(createExpressionStatement(inlineExpressions(pendingExpressions))); + } + pendingExpressions = savedPendingExpressions; + + if (pendingStatements && some(staticProperties)) { + addInitializedPropertyStatements(pendingStatements, staticProperties, getInternalName(node)); + } + return classExpression; + } + else { + const expressions: Expression[] = []; + const isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference; + const temp = createTempVariable(hoistVariableDeclaration, !!isClassWithConstructorReference); + if (isClassWithConstructorReference) { + // record an alias as the class name is not in scope for statics. + enableSubstitutionForClassAliases(); + const alias = getSynthesizedClone(temp); + alias.autoGenerateFlags &= ~GeneratedIdentifierFlags.ReservedInNestedScopes; + classAliases[getOriginalNodeId(node)] = alias; + } + + // To preserve the behavior of the old emitter, we explicitly indent + // the body of a class with static initializers. + setEmitFlags(classExpression, EmitFlags.Indented | getEmitFlags(classExpression)); + expressions.push(startOnNewLine(createAssignment(temp, classExpression))); + // Add any pending expressions leftover from elided or relocated computed property names + addRange(expressions, map(pendingExpressions, startOnNewLine)); + addRange(expressions, generateInitializedPropertyExpressions(staticProperties, temp)); + expressions.push(startOnNewLine(temp)); + + pendingExpressions = savedPendingExpressions; + return inlineExpressions(expressions); + } + } + + pendingExpressions = savedPendingExpressions; + return classExpression; + } + + function transformClassMembers(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { + const members: ClassElement[] = []; + const constructor = transformConstructor(node, isDerivedClass); + if (constructor) { + members.push(constructor); + } + addRange(members, visitNodes(node.members, classElementVisitor, isClassElement)); + return setTextRange(createNodeArray(members), /*location*/ node.members); + } + + function transformConstructor(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { + const constructor = visitNode(getFirstConstructorWithBody(node), visitor, isConstructorDeclaration); + const containsPropertyInitializer = forEach(node.members, isInitializedProperty); + if (!containsPropertyInitializer) { + return constructor; + } + const parameters = visitParameterList(constructor ? constructor.parameters : undefined, visitor, context); + const body = transformConstructorBody(node, constructor, isDerivedClass); + if (!body) { + return undefined; + } + return startOnNewLine( + setOriginalNode( + setTextRange( + createConstructor( + /*decorators*/ undefined, + /*modifiers*/ undefined, + parameters, + body + ), + constructor || node + ), + constructor + ) + ); + } + + function transformConstructorBody(node: ClassDeclaration | ClassExpression, constructor: ConstructorDeclaration | undefined, isDerivedClass: boolean) { + const properties = getInitializedProperties(node, /*isStatic*/ false); + + // Only generate synthetic constructor when there are property initializers to move. + if (!constructor && !some(properties)) { + return visitFunctionBody(/*node*/ undefined, visitor, context); + } + + resumeLexicalEnvironment(); + + let indexOfFirstStatement = 0; + let statements: Statement[] = []; + + if (!constructor && isDerivedClass) { + // Add a synthetic `super` call: + // + // super(...arguments); + // + statements.push( + createExpressionStatement( + createCall( + createSuper(), + /*typeArguments*/ undefined, + [createSpread(createIdentifier("arguments"))] + ) + ) + ); + } + + if (constructor) { + indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements, visitor); + } + + // Add the property initializers. Transforms this: + // + // public x = 1; + // + // Into this: + // + // constructor() { + // this.x = 1; + // } + // + addInitializedPropertyStatements(statements, properties, createThis()); + + // Add existing statements, skipping the initial super call. + if (constructor) { + addRange(statements, visitNodes(constructor.body!.statements, visitor, isStatement, indexOfFirstStatement)); + } + + statements = mergeLexicalEnvironment(statements, endLexicalEnvironment()); + + return setTextRange( + createBlock( + setTextRange( + createNodeArray(statements), + /*location*/ constructor ? constructor.body!.statements : node.members + ), + /*multiLine*/ true + ), + /*location*/ constructor ? constructor.body : undefined + ); + } + + /** + * Generates assignment statements for property initializers. + * + * @param properties An array of property declarations to transform. + * @param receiver The receiver on which each property should be assigned. + */ + function addInitializedPropertyStatements(statements: Statement[], properties: ReadonlyArray, receiver: LeftHandSideExpression) { + for (const property of properties) { + const 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); + } + + function enableSubstitutionForClassAliases() { + if ((enabledSubstitutions & ClassPropertySubstitutionFlags.ClassAliases) === 0) { + enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassAliases; + + // We need to enable substitutions for identifiers. This allows us to + // substitute class names inside of a class declaration. + context.enableSubstitution(SyntaxKind.Identifier); + + // Keep track of class aliases. + classAliases = []; + } + } + + /** + * Hooks node substitutions. + * + * @param hint The context for the emitter. + * @param node The node to substitute. + */ + function onSubstituteNode(hint: EmitHint, node: Node) { + node = previousOnSubstituteNode(hint, node); + if (hint === EmitHint.Expression) { + return substituteExpression(node as Expression); + } + return node; + } + + function substituteExpression(node: Expression) { + switch (node.kind) { + case SyntaxKind.Identifier: + return substituteExpressionIdentifier(node as Identifier); + } + return node; + } + + function substituteExpressionIdentifier(node: Identifier): Expression { + return trySubstituteClassAlias(node) || node; + } + + function trySubstituteClassAlias(node: Identifier): Expression | undefined { + if (enabledSubstitutions & ClassPropertySubstitutionFlags.ClassAliases) { + if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ConstructorReferenceInClass) { + // Due to the emit for class decorators, any reference to the class from inside of the class body + // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind + // behavior of class names in ES6. + // Also, when emitting statics for class expressions, we must substitute a class alias for + // constructor references in static property initializers. + const declaration = resolver.getReferencedValueDeclaration(node); + if (declaration) { + const classAlias = classAliases[declaration.id!]; // TODO: GH#18217 + if (classAlias) { + const clone = getSynthesizedClone(classAlias); + setSourceMapRange(clone, node); + setCommentRange(clone, node); + return clone; + } + } + } + } + + return undefined; + } + + + /** + * If the name is a computed property, this function transforms it, then either returns an expression which caches the + * value of the result or the expression itself if the value is either unused or safe to inline into multiple locations + * @param shouldHoist Does the expression need to be reused? (ie, for an initializer or a decorator) + */ + function getPropertyNameExpressionIfNeeded(name: PropertyName, shouldHoist: boolean): Expression | undefined { + if (isComputedPropertyName(name)) { + const expression = visitNode(name.expression, visitor, isExpression); + const innerExpression = skipPartiallyEmittedExpressions(expression); + const inlinable = isSimpleInlineableExpression(innerExpression); + const alreadyTransformed = isAssignmentExpression(innerExpression) && isGeneratedIdentifier(innerExpression.left); + if (!alreadyTransformed && !inlinable && shouldHoist) { + const generatedName = getGeneratedNameForNode(name); + hoistVariableDeclaration(generatedName); + return createAssignment(generatedName, expression); + } + return (inlinable || isIdentifier(innerExpression)) ? undefined : expression; + } + } + } + +} diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 4a127f3236dfd..ad267adb64dc6 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -64,6 +64,7 @@ namespace ts { let currentLexicalScope: SourceFile | Block | ModuleBlock | CaseBlock; let currentNameScope: ClassDeclaration | undefined; let currentScopeFirstDeclarationsOfName: UnderscoreEscapedMap | undefined; + let currentClassHasParameterProperties: boolean | undefined; /** * Keeps track of whether expression substitution has been enabled for specific edge cases. @@ -83,12 +84,6 @@ namespace ts { */ let applicableSubstitutions: TypeScriptSubstitutionFlags; - /** - * Tracks what computed name expressions originating from elided names must be inlined - * at the next execution site, in document order - */ - let pendingExpressions: Expression[] | undefined; - return transformSourceFileOrBundle; function transformSourceFileOrBundle(node: SourceFile | Bundle) { @@ -136,6 +131,7 @@ namespace ts { const savedCurrentScope = currentLexicalScope; const savedCurrentNameScope = currentNameScope; const savedCurrentScopeFirstDeclarationsOfName = currentScopeFirstDeclarationsOfName; + const savedCurrentClassHasParameterProperties = currentClassHasParameterProperties; // Handle state changes before visiting a node. onBeforeVisitNode(node); @@ -149,6 +145,7 @@ namespace ts { currentLexicalScope = savedCurrentScope; currentNameScope = savedCurrentNameScope; + currentClassHasParameterProperties = savedCurrentClassHasParameterProperties; return visited; } @@ -321,6 +318,9 @@ namespace ts { return undefined; case SyntaxKind.PropertyDeclaration: + // Property declarations are not TypeScript syntax, but they must be visited + // for the decorator transformation. + return visitPropertyDeclaration(node as PropertyDeclaration); case SyntaxKind.IndexSignature: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: @@ -437,7 +437,6 @@ namespace ts { // - decorators // - optional `implements` heritage clause // - parameter property assignments in the constructor - // - property declarations // - index signatures // - method overload signatures return visitClassDeclaration(node); @@ -449,7 +448,6 @@ namespace ts { // - decorators // - optional `implements` heritage clause // - parameter property assignments in the constructor - // - property declarations // - index signatures // - method overload signatures return visitClassExpression(node); @@ -611,10 +609,6 @@ namespace ts { if (!isClassLikeDeclarationWithTypeScriptSyntax(node) && !(currentNamespace && hasModifier(node, ModifierFlags.Export))) { return visitEachChild(node, visitor, context); } - - const savedPendingExpressions = pendingExpressions; - pendingExpressions = undefined; - const staticProperties = getInitializedProperties(node, /*isStatic*/ true); const facts = getClassFacts(node, staticProperties); @@ -624,25 +618,11 @@ namespace ts { const name = node.name || (facts & ClassFacts.NeedsName ? getGeneratedNameForNode(node) : undefined); const classStatement = facts & ClassFacts.HasConstructorDecorators - ? createClassDeclarationHeadWithDecorators(node, name, facts) + ? createClassDeclarationHeadWithDecorators(node, name) : createClassDeclarationHeadWithoutDecorators(node, name, facts); let statements: Statement[] = [classStatement]; - // Write any pending expressions from elided or moved computed property names - if (some(pendingExpressions)) { - statements.push(createExpressionStatement(inlineExpressions(pendingExpressions!))); - } - pendingExpressions = savedPendingExpressions; - - // Emit static property assignment. Because classDeclaration is lexically evaluated, - // it is safe to emit static property assignment after classDeclaration - // From ES6 specification: - // HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using - // a lexical declaration such as a LexicalDeclaration or a ClassDeclaration. - if (facts & ClassFacts.HasStaticInitializedProperties) { - addInitializedPropertyStatements(statements, staticProperties, facts & ClassFacts.UseImmediatelyInvokedFunctionExpression ? getInternalName(node) : getLocalName(node)); - } // Write any decorators of the node. addClassElementDecorationStatements(statements, node, /*isStatic*/ false); @@ -745,7 +725,7 @@ namespace ts { name, /*typeParameters*/ undefined, visitNodes(node.heritageClauses, visitor, isHeritageClause), - transformClassMembers(node, (facts & ClassFacts.IsDerivedClass) !== 0) + transformClassMembers(node) ); // To better align with the old emitter, we should not emit a trailing source map @@ -765,7 +745,7 @@ namespace ts { * Transforms a decorated class declaration and appends the resulting statements. If * the class requires an alias to avoid issues with double-binding, the alias is returned. */ - function createClassDeclarationHeadWithDecorators(node: ClassDeclaration, name: Identifier | undefined, facts: ClassFacts) { + function createClassDeclarationHeadWithDecorators(node: ClassDeclaration, name: Identifier | undefined) { // When we emit an ES6 class that has a class decorator, we must tailor the // emit to certain specific cases. // @@ -860,7 +840,7 @@ namespace ts { // ${members} // } const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause); - const members = transformClassMembers(node, (facts & ClassFacts.IsDerivedClass) !== 0); + const members = transformClassMembers(node); const classExpression = createClassExpression(/*modifiers*/ undefined, name, /*typeParameters*/ undefined, heritageClauses, members); setOriginalNode(classExpression, node); setTextRange(classExpression, location); @@ -888,49 +868,19 @@ namespace ts { return visitEachChild(node, visitor, context); } - const savedPendingExpressions = pendingExpressions; - pendingExpressions = undefined; - - const staticProperties = getInitializedProperties(node, /*isStatic*/ true); - const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause); - const members = transformClassMembers(node, some(heritageClauses, c => c.token === SyntaxKind.ExtendsKeyword)); + const members = transformClassMembers(node); const classExpression = createClassExpression( /*modifiers*/ undefined, node.name, /*typeParameters*/ undefined, - heritageClauses, + node.heritageClauses, members ); setOriginalNode(classExpression, node); setTextRange(classExpression, node); - if (some(staticProperties) || some(pendingExpressions)) { - const expressions: Expression[] = []; - const isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference; - const temp = createTempVariable(hoistVariableDeclaration, !!isClassWithConstructorReference); - if (isClassWithConstructorReference) { - // record an alias as the class name is not in scope for statics. - enableSubstitutionForClassAliases(); - const alias = getSynthesizedClone(temp); - alias.autoGenerateFlags &= ~GeneratedIdentifierFlags.ReservedInNestedScopes; - classAliases[getOriginalNodeId(node)] = alias; - } - - // To preserve the behavior of the old emitter, we explicitly indent - // the body of a class with static initializers. - setEmitFlags(classExpression, EmitFlags.Indented | getEmitFlags(classExpression)); - expressions.push(startOnNewLine(createAssignment(temp, classExpression))); - // Add any pending expressions leftover from elided or relocated computed property names - addRange(expressions, map(pendingExpressions, startOnNewLine)); - pendingExpressions = savedPendingExpressions; - addRange(expressions, generateInitializedPropertyExpressions(staticProperties, temp)); - expressions.push(startOnNewLine(temp)); - return inlineExpressions(expressions); - } - - pendingExpressions = savedPendingExpressions; return classExpression; } @@ -938,61 +888,81 @@ namespace ts { * Transforms the members of a class. * * @param node The current class. - * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. */ - function transformClassMembers(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { + function transformClassMembers(node: ClassDeclaration | ClassExpression) { const members: ClassElement[] = []; - const constructor = transformConstructor(node, isDerivedClass); - if (constructor) { - members.push(constructor); - } - - addRange(members, visitNodes(node.members, classElementVisitor, isClassElement)); - return setTextRange(createNodeArray(members), /*location*/ node.members); - } - - /** - * Transforms (or creates) a constructor for a class. - * - * @param node The current class. - * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. - */ - function transformConstructor(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { - // Check if we have property assignment inside class declaration. - // If there is a property assignment, we need to emit constructor whether users define it or not - // If there is no property assignment, we can omit constructor if users do not define it + const existingMembers = visitNodes(node.members, classElementVisitor, isClassElement); const constructor = getFirstConstructorWithBody(node); - const hasInstancePropertyWithInitializer = forEach(node.members, isInstanceInitializedProperty); - const hasParameterPropertyAssignments = constructor && - constructor.transformFlags & TransformFlags.ContainsTypeScriptClassSyntax && - forEach(constructor.parameters, isParameterWithPropertyAssignment); - - // If the class does not contain nodes that require a synthesized constructor, - // accept the current constructor if it exists. - if (!hasInstancePropertyWithInitializer && !hasParameterPropertyAssignments) { - return visitEachChild(constructor, visitor, context); - } - - const parameters = transformConstructorParameters(constructor); - const body = transformConstructorBody(node, constructor, isDerivedClass); + const parametersWithPropertyAssignments = + constructor && hasTypeScriptClassSyntax(constructor) + ? filter(constructor.parameters, isParameterPropertyDeclaration) + : undefined; + if (some(parametersWithPropertyAssignments) && constructor) { + currentClassHasParameterProperties = true; + + // Create property declarations for constructor parameter properties. + addRange( + members, + parametersWithPropertyAssignments.map(param => + createProperty( + /*decorators*/ undefined, + /*modifiers*/ undefined, + param.name, + /*questionOrExclamationToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined + ) + ) + ); - // constructor(${parameters}) { - // ${body} - // } - return startOnNewLine( - setOriginalNode( - setTextRange( - createConstructor( + const parameters = transformConstructorParameters(constructor); + const body = transformConstructorBody(node.members, constructor, parametersWithPropertyAssignments); + members.push(startOnNewLine( + setOriginalNode( + setTextRange( + createConstructor( /*decorators*/ undefined, /*modifiers*/ undefined, - parameters, - body + parameters, + body + ), + constructor ), - constructor || node - ), - constructor - ) - ); + constructor + ) + )); + addRange( + members, + visitNodes( + existingMembers, + member => { + if (isPropertyDeclaration(member) && !hasStaticModifier(member) && !!member.initializer) { + const updated = updateProperty( + member, + member.decorators, + member.modifiers, + member.name, + member.questionToken, + member.type, + /*initializer*/ undefined + ); + setCommentRange(updated, node); + setSourceMapRange(updated, node); + return updated; + } + return member; + }, + isClassElement + ) + ); + } + else { + if (constructor) { + members.push(visitEachChild(constructor, visitor, context)); + } + addRange(members, existingMembers); + } + return setTextRange(createNodeArray(members), /*location*/ node.members); } /** @@ -1001,7 +971,7 @@ namespace ts { * * @param constructor The constructor declaration. */ - function transformConstructorParameters(constructor: ConstructorDeclaration | undefined) { + function transformConstructorParameters(constructor: ConstructorDeclaration) { // The ES2015 spec specifies in 14.5.14. Runtime Semantics: ClassDefinitionEvaluation: // If constructor is empty, then // If ClassHeritag_eopt is present and protoParent is not null, then @@ -1022,70 +992,54 @@ namespace ts { } /** - * Transforms (or creates) a constructor body for a class with parameter property - * assignments or instance property initializers. + * Transforms (or creates) a constructor body for a class with parameter property assignments. * * @param node The current class. * @param constructor The current class constructor. - * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. */ - function transformConstructorBody(node: ClassExpression | ClassDeclaration, constructor: ConstructorDeclaration | undefined, isDerivedClass: boolean) { + function transformConstructorBody(members: NodeArray, constructor: ConstructorDeclaration, propertyAssignments: ReadonlyArray) { let statements: Statement[] = []; let indexOfFirstStatement = 0; resumeLexicalEnvironment(); - if (constructor) { - indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements); - - // Add parameters with property assignments. Transforms this: - // - // constructor (public x, public y) { - // } - // - // Into this: - // - // constructor (x, y) { - // this.x = x; - // this.y = y; - // } - // - const propertyAssignments = getParametersWithPropertyAssignments(constructor); - addRange(statements, map(propertyAssignments, transformParameterWithPropertyAssignment)); - } - else if (isDerivedClass) { - // Add a synthetic `super` call: - // - // super(...arguments); - // - statements.push( - createExpressionStatement( - createCall( - createSuper(), - /*typeArguments*/ undefined, - [createSpread(createIdentifier("arguments"))] - ) - ) - ); - } + indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements, visitor); - // Add the property initializers. Transforms this: + // Add parameters with property assignments. Transforms this: // - // public x = 1; + // constructor (public x, public y) { + // } // // Into this: // - // constructor() { - // this.x = 1; + // constructor (x, y) { + // this.x = x; + // this.y = y; // } // - const properties = getInitializedProperties(node, /*isStatic*/ false); - addInitializedPropertyStatements(statements, properties, createThis()); + addRange(statements, map(propertyAssignments, transformParameterWithPropertyAssignment)); + + // Get property initializers. + const classBodyProperties = members.filter(member => isPropertyDeclaration(member) && !hasStaticModifier(member) && !!member.initializer) as PropertyDeclaration[]; + addRange(statements, classBodyProperties.map( + prop => { + const name = prop.name; + const lhs = (!isComputedPropertyName(name) || isSimpleInlineableExpression(name.expression)) ? + createMemberAccessForPropertyName(createThis(), name, prop) : + createElementAccess(createThis(), getGeneratedNameForNode(name)); + const initializerNode = createExpressionStatement( + createAssignment(lhs, prop.initializer!) + ); + setOriginalNode(initializerNode, prop); + setTextRange(initializerNode, prop); + setCommentRange(initializerNode, prop); + setSourceMapRange(initializerNode, prop); + return initializerNode; + } + )); - if (constructor) { - // The class already had a constructor, so we should add the existing statements, skipping the initial super call. - addRange(statements, visitNodes(constructor.body!.statements, visitor, isStatement, indexOfFirstStatement)); - } + // Add the existing statements, skipping the initial super call. + addRange(statements, visitNodes(constructor.body!.statements, visitor, isStatement, indexOfFirstStatement)); // End the lexical environment. statements = mergeLexicalEnvironment(statements, endLexicalEnvironment()); @@ -1093,7 +1047,7 @@ namespace ts { createBlock( setTextRange( createNodeArray(statements), - /*location*/ constructor ? constructor.body!.statements : node.members + /*location*/ constructor ? constructor.body!.statements : members ), /*multiLine*/ true ), @@ -1101,61 +1055,16 @@ namespace ts { ); } - /** - * Adds super call and preceding prologue directives into the list of statements. - * - * @param ctor The constructor node. - * @returns index of the statement that follows super call - */ - function addPrologueDirectivesAndInitialSuperCall(ctor: ConstructorDeclaration, result: Statement[]): number { - if (ctor.body) { - const statements = ctor.body.statements; - // add prologue directives to the list (if any) - const index = addPrologue(result, statements, /*ensureUseStrict*/ false, visitor); - if (index === statements.length) { - // list contains nothing but prologue directives (or empty) - exit - return index; - } - - const statement = statements[index]; - if (statement.kind === SyntaxKind.ExpressionStatement && isSuperCall((statement).expression)) { - result.push(visitNode(statement, visitor, isStatement)); - return index + 1; - } - - return index; - } - - return 0; - } - - /** - * Gets all parameters of a constructor that should be transformed into property assignments. - * - * @param node The constructor node. - */ - function getParametersWithPropertyAssignments(node: ConstructorDeclaration): ReadonlyArray { - return filter(node.parameters, isParameterWithPropertyAssignment); - } - - /** - * Determines whether a parameter should be transformed into a property assignment. - * - * @param parameter The parameter node. - */ - function isParameterWithPropertyAssignment(parameter: ParameterDeclaration) { - return hasModifier(parameter, ModifierFlags.ParameterPropertyModifier) - && isIdentifier(parameter.name); - } - /** * Transforms a parameter into a property assignment statement. * * @param node The parameter declaration. */ - function transformParameterWithPropertyAssignment(node: ParameterDeclaration) { - Debug.assert(isIdentifier(node.name)); - const name = node.name as Identifier; + function transformParameterWithPropertyAssignment(node: ParameterPropertyDeclaration) { + const name = node.name; + if (!isIdentifier(name)) { + return undefined; + } const propertyName = getMutableClone(name); setEmitFlags(propertyName, EmitFlags.NoComments | EmitFlags.NoSourceMap); @@ -1184,99 +1093,6 @@ namespace ts { ); } - /** - * Gets all property declarations with initializers on either the static or instance side of a class. - * - * @param node The class node. - * @param isStatic A value indicating whether to get properties from the static or instance side of the class. - */ - function getInitializedProperties(node: ClassExpression | ClassDeclaration, isStatic: boolean): ReadonlyArray { - return filter(node.members, isStatic ? isStaticInitializedProperty : isInstanceInitializedProperty); - } - - /** - * Gets a value indicating whether a class element is a static property declaration with an initializer. - * - * @param member The class element node. - */ - function isStaticInitializedProperty(member: ClassElement): member is PropertyDeclaration { - return isInitializedProperty(member, /*isStatic*/ true); - } - - /** - * Gets a value indicating whether a class element is an instance property declaration with an initializer. - * - * @param member The class element node. - */ - function isInstanceInitializedProperty(member: ClassElement): member is PropertyDeclaration { - return isInitializedProperty(member, /*isStatic*/ false); - } - - /** - * Gets a value indicating whether a class element is either a static or an instance property declaration with an initializer. - * - * @param member The class element node. - * @param isStatic A value indicating whether the member should be a static or instance member. - */ - function isInitializedProperty(member: ClassElement, isStatic: boolean) { - return member.kind === SyntaxKind.PropertyDeclaration - && isStatic === hasModifier(member, ModifierFlags.Static) - && (member).initializer !== undefined; - } - - /** - * Generates assignment statements for property initializers. - * - * @param properties An array of property declarations to transform. - * @param receiver The receiver on which each property should be assigned. - */ - function addInitializedPropertyStatements(statements: Statement[], properties: ReadonlyArray, receiver: LeftHandSideExpression) { - for (const property of properties) { - const statement = createExpressionStatement(transformInitializedProperty(property, receiver)); - setSourceMapRange(statement, moveRangePastModifiers(property)); - setCommentRange(statement, property); - setOriginalNode(statement, property); - statements.push(statement); - } - } - - /** - * Generates assignment expressions for property initializers. - * - * @param properties An array of property declarations to transform. - * @param receiver The receiver on which each property should be assigned. - */ - function generateInitializedPropertyExpressions(properties: ReadonlyArray, receiver: LeftHandSideExpression) { - const expressions: Expression[] = []; - for (const property of properties) { - const expression = transformInitializedProperty(property, receiver); - startOnNewLine(expression); - setSourceMapRange(expression, moveRangePastModifiers(property)); - setCommentRange(expression, property); - setOriginalNode(expression, property); - expressions.push(expression); - } - - return expressions; - } - - /** - * Transforms a property initializer into an assignment statement. - * - * @param property The property declaration. - * @param receiver The object receiving the property assignment. - */ - function transformInitializedProperty(property: PropertyDeclaration, receiver: LeftHandSideExpression) { - // We generate a name here in order to reuse the value cached by the relocated computed name expression (which uses the same generated name) - const propertyName = isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression) - ? updateComputedPropertyName(property.name, getGeneratedNameForNode(property.name)) - : property.name; - const initializer = visitNode(property.initializer!, visitor, isExpression); - const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName); - - return createAssignment(memberAccess, initializer); - } - /** * Gets either the static or instance members of a class that are decorated, or have * parameters that are decorated. @@ -2141,16 +1957,6 @@ namespace ts { : createIdentifier("BigInt"); } - /** - * A simple inlinable expression is an expression which can be copied into multiple locations - * without risk of repeating any sideeffects and whose value could not possibly change between - * any such locations - */ - function isSimpleInlineableExpression(expression: Expression) { - return !isIdentifier(expression) && isSimpleCopiableExpression(expression) || - isWellKnownSymbolSyntactically(expression); - } - /** * Gets an expression that represents a property name. For a computed property, a * name is generated for the node. @@ -2172,26 +1978,6 @@ namespace ts { } } - /** - * If the name is a computed property, this function transforms it, then either returns an expression which caches the - * value of the result or the expression itself if the value is either unused or safe to inline into multiple locations - * @param shouldHoist Does the expression need to be reused? (ie, for an initializer or a decorator) - * @param omitSimple Should expressions with no observable side-effects be elided? (ie, the expression is not hoisted for a decorator or initializer and is a literal) - */ - function getPropertyNameExpressionIfNeeded(name: PropertyName, shouldHoist: boolean, omitSimple: boolean): Expression | undefined { - if (isComputedPropertyName(name)) { - const expression = visitNode(name.expression, visitor, isExpression); - const innerExpression = skipPartiallyEmittedExpressions(expression); - const inlinable = isSimpleInlineableExpression(innerExpression); - if (!inlinable && shouldHoist) { - const generatedName = getGeneratedNameForNode(name); - hoistVariableDeclaration(generatedName); - return createAssignment(generatedName, expression); - } - return (omitSimple && (inlinable || isIdentifier(innerExpression))) ? undefined : expression; - } - } - /** * Visits the property name of a class element, for use when emitting property * initializers. For a computed property on a node with decorators, a temporary @@ -2201,18 +1987,20 @@ namespace ts { */ function visitPropertyNameOfClassElement(member: ClassElement): PropertyName { const name = member.name!; - let expr = getPropertyNameExpressionIfNeeded(name, some(member.decorators), /*omitSimple*/ false); - if (expr) { // expr only exists if `name` is a computed property name - // Inline any pending expressions from previous elided or relocated computed property name expressions in order to preserve execution order - if (some(pendingExpressions)) { - expr = inlineExpressions([...pendingExpressions, expr]); - pendingExpressions.length = 0; + // Computed property names need to be transformed into a hoisted variable when they are used more than once. + // The names are used more than once when: + // - the property is non-static and its initializer is moved to the constructor (when there are parameter property assignments). + // - the property has a decorator. + if (isComputedPropertyName(name) && ((!hasStaticModifier(member) && currentClassHasParameterProperties) || some(member.decorators))) { + const expression = visitNode(name.expression, visitor, isExpression); + const innerExpression = skipPartiallyEmittedExpressions(expression); + if (!isSimpleInlineableExpression(innerExpression)) { + const generatedName = getGeneratedNameForNode(name); + hoistVariableDeclaration(generatedName); + return updateComputedPropertyName(name, createAssignment(generatedName, expression)); } - return updateComputedPropertyName(name as ComputedPropertyName, expr); - } - else { - return name; } + return visitNode(name, visitor, isPropertyName); } /** @@ -2258,12 +2046,23 @@ namespace ts { return !nodeIsMissing(node.body); } - function visitPropertyDeclaration(node: PropertyDeclaration): undefined { - const expr = getPropertyNameExpressionIfNeeded(node.name, some(node.decorators) || !!node.initializer, /*omitSimple*/ true); - if (expr && !isSimpleInlineableExpression(expr)) { - (pendingExpressions || (pendingExpressions = [])).push(expr); + function visitPropertyDeclaration(node: PropertyDeclaration) { + const updated = updateProperty( + node, + /*decorators*/ undefined, + visitNodes(node.modifiers, visitor, isModifier), + visitPropertyNameOfClassElement(node), + /*questionOrExclamationToken*/ undefined, + /*type*/ undefined, + visitNode(node.initializer, visitor) + ); + if (updated !== node) { + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. + setCommentRange(updated, node); + setSourceMapRange(updated, moveRangePastDecorators(node)); } - return undefined; + return updated; } function visitConstructor(node: ConstructorDeclaration) { diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index 09239d7765fd9..f5f8a298a490b 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,43 @@ namespace ts { return result; }; } + + /** + * Gets all property declarations with initializers on either the static or instance side of a class. + * + * @param node The class node. + * @param isStatic A value indicating whether to get properties from the static or instance side of the class. + */ + export function getInitializedProperties(node: ClassExpression | ClassDeclaration, isStatic: boolean): ReadonlyArray { + return filter(node.members, isStatic ? isStaticInitializedProperty : isInstanceInitializedProperty); + } + + /** + * Gets a value indicating whether a class element is a static property declaration with an initializer. + * + * @param member The class element node. + */ + export function isStaticInitializedProperty(member: ClassElement): member is PropertyDeclaration & { initializer: Expression; } { + return isInitializedProperty(member) && hasStaticModifier(member); + } + + /** + * Gets a value indicating whether a class element is an instance property declaration with an initializer. + * + * @param member The class element node. + */ + export function isInstanceInitializedProperty(member: ClassElement): member is PropertyDeclaration & { initializer: Expression; } { + return isInitializedProperty(member) && !hasStaticModifier(member); + } + + /** + * Gets a value indicating whether a class element is either a static or an instance property declaration with an initializer. + * + * @param member The class element node. + * @param isStatic A value indicating whether the member should be a static or instance member. + */ + export function isInitializedProperty(member: ClassElement): member is PropertyDeclaration & { initializer: Expression; } { + return member.kind === SyntaxKind.PropertyDeclaration + && (member).initializer !== undefined; + } } \ No newline at end of file diff --git a/src/compiler/tsconfig.json b/src/compiler/tsconfig.json index 84bedb34b7cee..fe0c3250ed172 100644 --- a/src/compiler/tsconfig.json +++ b/src/compiler/tsconfig.json @@ -29,6 +29,7 @@ "transformers/utilities.ts", "transformers/destructuring.ts", "transformers/ts.ts", + "transformers/classProperties.ts", "transformers/es2017.ts", "transformers/es2018.ts", "transformers/es2019.ts", diff --git a/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/systemModuleTargetES6.js b/tests/baselines/reference/systemModuleTargetES6.js index 943e57ff742ac..0df2835683e82 100644 --- a/tests/baselines/reference/systemModuleTargetES6.js +++ b/tests/baselines/reference/systemModuleTargetES6.js @@ -35,8 +35,8 @@ System.register([], function (exports_1, context_1) { MyClass2 = class MyClass2 { static getInstance() { return MyClass2.value; } }; - MyClass2.value = 42; exports_1("MyClass2", MyClass2); + MyClass2.value = 42; } }; }); diff --git a/tests/baselines/reference/variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.js b/tests/baselines/reference/variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.js index f2a1df5e7072a..4bb3c19f9c890 100644 --- a/tests/baselines/reference/variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.js +++ b/tests/baselines/reference/variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.js @@ -16,8 +16,8 @@ var Foo = /** @class */ (function () { } return Foo; }()); -_a = key; exports.Foo = Foo; +_a = key; //// [variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.d.ts] From 256bb91943c7d8f551176cdca012de8aa435ec5a Mon Sep 17 00:00:00 2001 From: Max Heiber Date: Sun, 8 Jul 2018 17:53:36 -0400 Subject: [PATCH 2/6] Parse Private Names and check that private names not used in parameters Signed-off-by: Max Heiber --- src/compiler/binder.ts | 15 +- src/compiler/checker.ts | 31 +- src/compiler/diagnosticMessages.json | 8 + src/compiler/emitter.ts | 16 +- src/compiler/factory.ts | 22 +- src/compiler/parser.ts | 29 +- src/compiler/scanner.ts | 14 + src/compiler/transformers/destructuring.ts | 3 +- src/compiler/transformers/es2015.ts | 3 +- src/compiler/transformers/es5.ts | 5 +- src/compiler/transformers/ts.ts | 2 +- src/compiler/types.ts | 18 +- src/compiler/utilities.ts | 40 +- src/compiler/visitor.ts | 2 +- src/services/codefixes/convertToEs6Module.ts | 2 +- src/services/codefixes/inferFromUsage.ts | 2 +- src/services/refactors/moveToNewFile.ts | 2 +- src/services/types.ts | 4 + .../MemberFunctionDeclaration8_es6.errors.txt | 5 +- .../MemberFunctionDeclaration8_es6.js | 5 +- .../MemberFunctionDeclaration8_es6.symbols | 3 +- .../MemberFunctionDeclaration8_es6.types | 3 +- .../reference/api/tsserverlibrary.d.ts | 542 +++++++++--------- tests/baselines/reference/api/typescript.d.ts | 542 +++++++++--------- .../parseErrorInHeritageClause1.errors.txt | 5 +- .../reference/parseErrorInHeritageClause1.js | 5 +- .../parseErrorInHeritageClause1.symbols | 3 +- .../parseErrorInHeritageClause1.types | 3 +- .../parserErrorRecovery_Block2.errors.txt | 5 +- .../reference/parserErrorRecovery_Block2.js | 5 +- .../parserErrorRecovery_Block2.symbols | 3 +- .../parserErrorRecovery_Block2.types | 3 +- ...rserErrorRecovery_ClassElement3.errors.txt | 9 +- .../parserErrorRecovery_ClassElement3.js | 5 +- .../parserErrorRecovery_ClassElement3.symbols | 5 +- .../parserErrorRecovery_ClassElement3.types | 5 +- ...serErrorRecovery_ParameterList4.errors.txt | 5 +- .../parserErrorRecovery_ParameterList4.js | 5 +- ...parserErrorRecovery_ParameterList4.symbols | 3 +- .../parserErrorRecovery_ParameterList4.types | 3 +- .../parserSkippedTokens16.errors.txt | 5 +- .../reference/parserSkippedTokens16.js | 5 +- .../reference/parserSkippedTokens16.symbols | 2 +- .../reference/parserSkippedTokens16.types | 3 +- .../privateNameAndIndexSignature.errors.txt | 13 + .../reference/privateNameAndIndexSignature.js | 16 + .../privateNameAndIndexSignature.symbols | 15 + .../privateNameAndIndexSignature.types | 18 + tests/baselines/reference/privateNameField.js | 15 + .../reference/privateNameField.symbols | 16 + .../reference/privateNameField.types | 17 + .../reference/shebangError.errors.txt | 9 +- .../compiler/parseErrorInHeritageClause1.ts | 4 +- .../privateNameAndIndexSignature.ts | 6 + .../members/privateNames/privateNameField.ts | 6 + .../MemberFunctionDeclaration8_es6.ts | 4 +- .../Blocks/parserErrorRecovery_Block2.ts | 4 +- .../parserErrorRecovery_ClassElement3.ts | 4 +- .../parserErrorRecovery_ParameterList4.ts | 4 +- .../SkippedTokens/parserSkippedTokens16.ts | 4 +- tests/cases/fourslash/hoverOverPrivateName.ts | 15 + 61 files changed, 934 insertions(+), 641 deletions(-) create mode 100644 tests/baselines/reference/privateNameAndIndexSignature.errors.txt create mode 100644 tests/baselines/reference/privateNameAndIndexSignature.js create mode 100644 tests/baselines/reference/privateNameAndIndexSignature.symbols create mode 100644 tests/baselines/reference/privateNameAndIndexSignature.types create mode 100644 tests/baselines/reference/privateNameField.js create mode 100644 tests/baselines/reference/privateNameField.symbols create mode 100644 tests/baselines/reference/privateNameField.types create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameField.ts create mode 100644 tests/cases/fourslash/hoverOverPrivateName.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 2c76f9838633d..8154ea52e6f42 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -278,6 +278,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) { @@ -1458,7 +1461,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); } } @@ -2424,7 +2427,7 @@ namespace ts { if (!setCommonJsModuleIndicator(node)) { return; } - const symbol = forEachIdentifierInEntityName(node.arguments[0], /*parent*/ undefined, (id, symbol) => { + const symbol = forEachIdentifierOrPrivateNameInEntityName(node.arguments[0], /*parent*/ undefined, (id, symbol) => { if (symbol) { addDeclarationToSymbol(symbol, id, SymbolFlags.Module | SymbolFlags.Assignment); } @@ -2443,7 +2446,7 @@ namespace ts { return; } const lhs = node.left as PropertyAccessEntityNameExpression; - const symbol = forEachIdentifierInEntityName(lhs.expression, /*parent*/ undefined, (id, symbol) => { + const symbol = forEachIdentifierOrPrivateNameInEntityName(lhs.expression, /*parent*/ undefined, (id, symbol) => { if (symbol) { addDeclarationToSymbol(symbol, id, SymbolFlags.Module | SymbolFlags.Assignment); } @@ -2613,7 +2616,7 @@ namespace ts { // make symbols or add declarations for intermediate containers const flags = SymbolFlags.Module | SymbolFlags.Assignment; const excludeFlags = SymbolFlags.ValueModuleExcludes & ~SymbolFlags.Assignment; - namespaceSymbol = forEachIdentifierInEntityName(entityName, namespaceSymbol, (id, symbol, parent) => { + namespaceSymbol = forEachIdentifierOrPrivateNameInEntityName(entityName, namespaceSymbol, (id, symbol, parent) => { if (symbol) { addDeclarationToSymbol(symbol, id, flags); return symbol; @@ -2701,7 +2704,7 @@ namespace ts { } } - function forEachIdentifierInEntityName(e: EntityNameExpression, parent: Symbol | undefined, action: (e: Identifier, symbol: Symbol | undefined, parent: Symbol | undefined) => Symbol | undefined): Symbol | undefined { + function forEachIdentifierOrPrivateNameInEntityName(e: EntityNameExpression, parent: Symbol | undefined, action: (e: Identifier | PrivateName, symbol: Symbol | undefined, parent: Symbol | undefined) => Symbol | undefined): Symbol | undefined { if (isExportsOrModuleExportsOrAlias(file, e)) { return file.symbol; } @@ -2709,7 +2712,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); } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ac45866e2db4d..3825372085213 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15786,8 +15786,10 @@ namespace ts { const root = getReferenceRoot(node); const parent = root.parent; const isLengthPushOrUnshift = parent.kind === SyntaxKind.PropertyAccessExpression && ( - (parent).name.escapedText === "length" || - parent.parent.kind === SyntaxKind.CallExpression && isPushOrUnshiftIdentifier((parent).name)); + (parent).name.escapedText === "length" || ( + parent.parent.kind === SyntaxKind.CallExpression + && isIdentifier((parent as PropertyAccessExpression).name) + && isPushOrUnshiftIdentifier((parent as PropertyAccessExpression).name as Identifier))); const isElementAssignment = parent.kind === SyntaxKind.ElementAccessExpression && (parent).expression === root && parent.parent.kind === SyntaxKind.BinaryExpression && @@ -19488,7 +19490,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; @@ -19506,7 +19508,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; } @@ -19576,7 +19578,7 @@ namespace ts { return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType; } - function checkPropertyNotUsedBeforeDeclaration(prop: Symbol, node: PropertyAccessExpression | QualifiedName, right: Identifier): void { + function checkPropertyNotUsedBeforeDeclaration(prop: Symbol, node: PropertyAccessExpression | QualifiedName, right: Identifier | PrivateName): void { const { valueDeclaration } = prop; if (!valueDeclaration) { return; @@ -19658,7 +19660,7 @@ namespace ts { return getIntersectionType(x); } - function reportNonexistentProperty(propNode: Identifier, containingType: Type) { + function reportNonexistentProperty(propNode: Identifier | PrivateName, containingType: Type) { let errorInfo: DiagnosticMessageChain | undefined; let relatedInfo: Diagnostic | undefined; if (containingType.flags & TypeFlags.Union && !(containingType.flags & TypeFlags.Primitive)) { @@ -19701,11 +19703,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); } @@ -23828,6 +23830,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))) { @@ -25499,9 +25504,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; @@ -31421,6 +31426,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 9ae3e1ca77eae..b95e3e8fae98e 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4478,6 +4478,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 be867db68fb77..647d888a4fdcc 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1138,6 +1138,10 @@ namespace ts { case SyntaxKind.Identifier: return emitIdentifier(node); + // PrivateNames + case SyntaxKind.PrivateName: + return emitPrivateName(node as PrivateName); + // Parse tree nodes // Names @@ -1437,6 +1441,10 @@ namespace ts { case SyntaxKind.Identifier: return emitIdentifier(node); + // Private Names + case SyntaxKind.PrivateName: + return emitPrivateName(node as PrivateName); + // Reserved words case SyntaxKind.FalseKeyword: case SyntaxKind.NullKeyword: @@ -1695,6 +1703,12 @@ namespace ts { emitList(node, node.typeArguments, ListFormat.TypeParameters); // Call emitList directly since it could be an array of TypeParameterDeclarations _or_ type arguments } + function emitPrivateName(node: PrivateName) { + const writeText = node.symbol ? writeSymbol : write; + writeText(getTextOfNode(node, /*includeTrivia*/ false), node.symbol); + emitList(node, /*typeArguments*/ undefined, ListFormat.TypeParameters); // Call emitList directly since it could be an array of TypeParameterDeclarations _or_ type arguments + } + // // Names // @@ -4175,7 +4189,7 @@ namespace ts { function getLiteralTextOfNode(node: LiteralLikeNode, neverAsciiEscape: boolean | undefined): string { if (node.kind === SyntaxKind.StringLiteral && (node).textSourceNode) { const textSourceNode = (node).textSourceNode!; - if (isIdentifier(textSourceNode)) { + if (isIdentifierOrPrivateName(textSourceNode)) { return neverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? `"${escapeString(getTextOfNode(textSourceNode))}"` : `"${escapeNonAsciiString(getTextOfNode(textSourceNode))}"`; diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 5f4299f1e2021..b394990523e63 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -114,7 +114,7 @@ namespace ts { return node; } - function createLiteralFromNode(sourceNode: PropertyNameLiteral): StringLiteral { + function createLiteralFromNode(sourceNode: Exclude): StringLiteral { const node = createStringLiteral(getTextOfIdentifierOrLiteral(sourceNode)); node.textSourceNode = sourceNode; return node; @@ -1004,7 +1004,7 @@ namespace ts { : node; } - export function createPropertyAccess(expression: Expression, name: string | Identifier | undefined) { + export function createPropertyAccess(expression: Expression, name: string | Identifier | PrivateName | undefined) { const node = createSynthesizedNode(SyntaxKind.PropertyAccessExpression); node.expression = parenthesizeForAccess(expression); node.name = asName(name)!; // TODO: GH#18217 @@ -1012,7 +1012,7 @@ namespace ts { return node; } - export function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier) { + export function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier | PrivateName) { // Because we are updating existed propertyAccess we want to inherit its emitFlags // instead of using the default from createPropertyAccess return node.expression !== expression @@ -3054,7 +3054,7 @@ namespace ts { // Utilities - function asName(name: string | T): T | Identifier { + function asName(name: string | T): T | Identifier { return isString(name) ? createIdentifier(name) : name; } @@ -3439,7 +3439,7 @@ namespace ts { } else { const expression = setTextRange( - isIdentifier(memberName) + (isIdentifier(memberName) || isPrivateName(memberName)) ? createPropertyAccess(target, memberName) : createElementAccess(target, memberName), memberName @@ -3870,7 +3870,7 @@ namespace ts { } } - export function createExpressionForPropertyName(memberName: PropertyName): Expression { + export function createExpressionForPropertyName(memberName: Exclude): Expression { if (isIdentifier(memberName)) { return createLiteral(memberName); } @@ -3882,11 +3882,17 @@ namespace ts { } } + /** + * accessor declaration that can be converted to an expression (`name` field cannot be a `PrivateName`) + */ + type ExpressionableAccessorDeclaration = AccessorDeclaration & {name: Exclude}; + export function createExpressionForObjectLiteralElementLike(node: ObjectLiteralExpression, property: ObjectLiteralElementLike, receiver: Expression): Expression | undefined { switch (property.kind) { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - return createExpressionForAccessorDeclaration(node.properties, property, receiver, !!node.multiLine); + // type assertion `as ExpressionableAccessorDeclaration` is safe because PrivateNames are not allowed in object literals + return createExpressionForAccessorDeclaration(node.properties, property as ExpressionableAccessorDeclaration, receiver, !!node.multiLine); case SyntaxKind.PropertyAssignment: return createExpressionForPropertyAssignment(property, receiver); case SyntaxKind.ShorthandPropertyAssignment: @@ -3896,7 +3902,7 @@ namespace ts { } } - function createExpressionForAccessorDeclaration(properties: NodeArray, property: AccessorDeclaration, receiver: Expression, multiLine: boolean) { + function createExpressionForAccessorDeclaration(properties: NodeArray, property: ExpressionableAccessorDeclaration, receiver: Expression, multiLine: boolean) { const { firstAccessor, getAccessor, setAccessor } = getAllAccessorDeclarations(properties, property); if (property === firstAccessor) { const properties: ObjectLiteralElementLike[] = []; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 03d0f166b81b8..acbab5912025a 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1369,6 +1369,9 @@ namespace ts { if (allowComputedPropertyNames && token() === SyntaxKind.OpenBracketToken) { return parseComputedPropertyName(); } + if (token() === SyntaxKind.PrivateName) { + return parsePrivateName(); + } return parseIdentifierName(); } @@ -1392,6 +1395,17 @@ namespace ts { return finishNode(node); } + function createPrivateName(): PrivateName { + const node = createNode(SyntaxKind.PrivateName) as PrivateName; + node.escapedText = escapeLeadingUnderscores(scanner.getTokenText()); + nextToken(); + return finishNode(node); + } + + function parsePrivateName(): PrivateName { + return createPrivateName(); + } + function parseContextualModifier(t: SyntaxKind): boolean { return token() === t && tryParse(nextTokenCanFollowModifier); } @@ -2149,7 +2163,7 @@ namespace ts { break; } dotPos = scanner.getStartPos(); - entity = createQualifiedName(entity, parseRightSideOfDot(allowReservedWords)); + entity = createQualifiedName(entity, parseRightSideOfDot(allowReservedWords, /* allowPrivateNames */ false) as Identifier); } return entity; } @@ -2161,7 +2175,7 @@ namespace ts { return finishNode(node); } - function parseRightSideOfDot(allowIdentifierNames: boolean): Identifier { + function parseRightSideOfDot(allowIdentifierNames: boolean, allowPrivateNames: boolean): Identifier | PrivateName { // Technically a keyword is valid here as all identifiers and keywords are identifier names. // However, often we'll encounter this in error situations when the identifier or keyword // is actually starting another valid construct. @@ -2192,6 +2206,10 @@ namespace ts { } } + if (allowPrivateNames && token() === SyntaxKind.PrivateName) { + return parsePrivateName(); + } + return allowIdentifierNames ? parseIdentifierName() : parseIdentifier(); } @@ -4196,7 +4214,8 @@ namespace ts { const node = createNode(SyntaxKind.PropertyAccessExpression, expression.pos); node.expression = expression; parseExpectedToken(SyntaxKind.DotToken, Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access); - node.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); + // private names will never work with `super` (`super.#foo`), but that's a semantic error, not syntactic + node.name = parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateNames*/ true); return finishNode(node); } @@ -4367,7 +4386,7 @@ namespace ts { while (parseOptional(SyntaxKind.DotToken)) { const propertyAccess: JsxTagNamePropertyAccess = createNode(SyntaxKind.PropertyAccessExpression, expression.pos); propertyAccess.expression = expression; - propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); + propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateNames*/ true); expression = finishNode(propertyAccess); } return expression; @@ -4470,7 +4489,7 @@ namespace ts { if (dotToken) { const propertyAccess = createNode(SyntaxKind.PropertyAccessExpression, expression.pos); propertyAccess.expression = expression; - propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); + propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateNames*/ true); expression = finishNode(propertyAccess); continue; } diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index e31876962b7da..d15c9312c1a3a 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -1833,6 +1833,20 @@ namespace ts { error(Diagnostics.Invalid_character); pos++; return token = SyntaxKind.Unknown; + case CharacterCodes.hash: + pos++; + if (isIdentifierStart(ch = text.charCodeAt(pos), languageVersion)) { + pos++; + while (pos < end && isIdentifierPart(ch = text.charCodeAt(pos), languageVersion)) pos++; + tokenValue = text.substring(tokenPos, pos); + if (ch === CharacterCodes.backslash) { + tokenValue += scanIdentifierParts(); + } + return token = SyntaxKind.PrivateName; + } + error(Diagnostics.Invalid_character); + // no `pos++` because already advanced at beginning of this `case` statement + return token = SyntaxKind.Unknown; default: if (isIdentifierStart(ch, languageVersion)) { pos++; diff --git a/src/compiler/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index b5e829ee6839d..0d1125762ce53 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -535,7 +535,8 @@ namespace ts { const propertyNames: Expression[] = []; let computedTempVariableOffset = 0; for (let i = 0; i < elements.length - 1; i++) { - const propertyName = getPropertyNameOfBindingOrAssignmentElement(elements[i]); + // can safely assume property name is not a PrivateName because PrivateNames are not allowed in object literals + const propertyName = getPropertyNameOfBindingOrAssignmentElement(elements[i]) as Exclude; if (propertyName) { if (isComputedPropertyName(propertyName)) { const temp = computedTempVariables[computedTempVariableOffset]; diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 31916cbb684c1..b735a3eed1b79 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -1641,7 +1641,8 @@ namespace ts { setEmitFlags(target, EmitFlags.NoComments | EmitFlags.NoTrailingSourceMap); setSourceMapRange(target, firstAccessor.name); // TODO: GH#18217 - const propertyName = createExpressionForPropertyName(visitNode(firstAccessor.name, visitor, isPropertyName)); + // TODO: GH#9950 get rid of this type assertion and handle private names + const propertyName = createExpressionForPropertyName(visitNode(firstAccessor.name, visitor, isPropertyName) as Exclude); setEmitFlags(propertyName, EmitFlags.NoComments | EmitFlags.NoLeadingSourceMap); setSourceMapRange(propertyName, firstAccessor.name); diff --git a/src/compiler/transformers/es5.ts b/src/compiler/transformers/es5.ts index 1c85e684e8cba..36ff996dca594 100644 --- a/src/compiler/transformers/es5.ts +++ b/src/compiler/transformers/es5.ts @@ -82,7 +82,10 @@ namespace ts { * @param node A PropertyAccessExpression */ function substitutePropertyAccessExpression(node: PropertyAccessExpression): Expression { - const literalName = trySubstituteReservedName(node.name); + if (isPrivateName(node)) { + return node; + } + const literalName = trySubstituteReservedName(node.name as Identifier); if (literalName) { return setTextRange(createElementAccess(node.expression, literalName), node); } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index ad267adb64dc6..e051deb37db52 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -1970,7 +1970,7 @@ namespace ts { ? getGeneratedNameForNode(name) : name.expression; } - else if (isIdentifier(name)) { + else if (isIdentifier(name) || isPrivateName(name)) { return createLiteral(idText(name)); } else { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 088ae34ee34bf..02779b30d151f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -195,8 +195,9 @@ namespace ts { AmpersandEqualsToken, BarEqualsToken, CaretEqualsToken, - // Identifiers + // Identifiers and PrivateNames Identifier, + PrivateName, // Reserved words BreakKeyword, CaseKeyword, @@ -797,9 +798,9 @@ namespace ts { export type EntityName = Identifier | QualifiedName; - export type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName; + export type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | PrivateName; - export type DeclarationName = Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern; + export type DeclarationName = Identifier | PrivateName | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern; export interface Declaration extends Node { _declarationBrand: any; @@ -830,6 +831,13 @@ namespace ts { expression: Expression; } + export interface PrivateName extends PrimaryExpression, Declaration { + kind: SyntaxKind.PrivateName; + // escaping not strictly necessary + // avoids gotchas in transforms and utils + escapedText: __String; + } + /* @internal */ // A name that supports late-binding (used in checker) export interface LateBoundName extends ComputedPropertyName { @@ -1270,7 +1278,7 @@ namespace ts { export interface StringLiteral extends LiteralExpression { kind: SyntaxKind.StringLiteral; - /* @internal */ textSourceNode?: Identifier | StringLiteralLike | NumericLiteral; // Allows a StringLiteral to get its text from another node (used by transforms). + /* @internal */ textSourceNode?: Identifier | PrivateName | StringLiteralLike | NumericLiteral; // Allows a StringLiteral to get its text from another node (used by transforms). /** Note: this is only set when synthesizing a node, not during parsing. */ /* @internal */ singleQuote?: boolean; } @@ -1764,7 +1772,7 @@ namespace ts { export interface PropertyAccessExpression extends MemberExpression, NamedDeclaration { kind: SyntaxKind.PropertyAccessExpression; expression: LeftHandSideExpression; - name: Identifier; + name: Identifier | PrivateName; } export interface SuperPropertyAccessExpression extends PropertyAccessExpression { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 73e32241f813b..dd3f458e0119b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -809,6 +809,7 @@ namespace ts { export function getTextOfPropertyName(name: PropertyName | NoSubstitutionTemplateLiteral): __String { switch (name.kind) { case SyntaxKind.Identifier: + case SyntaxKind.PrivateName: return name.escapedText; case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: @@ -829,7 +830,15 @@ namespace ts { case SyntaxKind.QualifiedName: return entityNameToString(name.left) + "." + entityNameToString(name.right); case SyntaxKind.PropertyAccessExpression: - return entityNameToString(name.expression) + "." + entityNameToString(name.name); + if (isIdentifier(name.name)) { + return entityNameToString(name.expression) + "." + entityNameToString(name.name); + } + else if (isPrivateName(name.name)) { + return getTextOfNode(name); + } + else { + throw Debug.assertNever(name.name); + } default: throw Debug.assertNever(name); } @@ -1940,7 +1949,7 @@ namespace ts { (initializer.expression.escapedText === "window" as __String || initializer.expression.escapedText === "self" as __String || initializer.expression.escapedText === "global" as __String)) && - isSameEntityName(name, initializer.name); + isSameEntityName(name, initializer.name as Identifier); } if (isPropertyAccessExpression(name) && isPropertyAccessExpression(initializer)) { return name.name.escapedText === initializer.name.escapedText && isSameEntityName(name.expression, initializer.expression); @@ -2732,6 +2741,7 @@ namespace ts { export function getPropertyNameForPropertyNameNode(name: PropertyName): __String | undefined { switch (name.kind) { case SyntaxKind.Identifier: + case SyntaxKind.PrivateName: return name.escapedText; case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: @@ -2750,10 +2760,12 @@ namespace ts { } } - export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral; + export type PropertyNameLiteral = Identifier | PrivateName | StringLiteralLike | NumericLiteral; export function isPropertyNameLiteral(node: Node): node is PropertyNameLiteral { switch (node.kind) { case SyntaxKind.Identifier: + // TODO: should this be here? + case SyntaxKind.PrivateName: case SyntaxKind.StringLiteral: case SyntaxKind.NoSubstitutionTemplateLiteral: case SyntaxKind.NumericLiteral: @@ -2763,11 +2775,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 { @@ -3506,7 +3518,7 @@ namespace ts { } export function isThisIdentifier(node: Node | undefined): boolean { - return !!node && node.kind === SyntaxKind.Identifier && identifierIsThisKeyword(node as Identifier); + return !!node && isIdentifier(node) && identifierIsThisKeyword(node); } export function identifierIsThisKeyword(id: Identifier): boolean { @@ -5106,8 +5118,8 @@ namespace ts { return id.length >= 3 && id.charCodeAt(0) === CharacterCodes._ && id.charCodeAt(1) === CharacterCodes._ && id.charCodeAt(2) === CharacterCodes._ ? id.substr(1) : id; } - export function idText(identifier: Identifier): string { - return unescapeLeadingUnderscores(identifier.escapedText); + export function idText(identifierOrPrivateName: Identifier | PrivateName): string { + return unescapeLeadingUnderscores(identifierOrPrivateName.escapedText); } export function symbolName(symbol: Symbol): string { return unescapeLeadingUnderscores(symbol.escapedName); @@ -5118,7 +5130,7 @@ namespace ts { * attempt to draw the name from the node the declaration is on (as that declaration is what its' symbol * will be merged with) */ - function nameForNamelessJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined { + function nameForNamelessJSDocTypedef(declaration: JSDocTypedefTag): Identifier | PrivateName | undefined { const hostNode = declaration.parent.parent; if (!hostNode) { return undefined; @@ -5163,7 +5175,7 @@ namespace ts { return name && isIdentifier(name) ? name : undefined; } - export function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined { + export function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | PrivateName | undefined { return declaration.name || nameForNamelessJSDocTypedef(declaration); } @@ -5479,6 +5491,10 @@ namespace ts { return node.kind === SyntaxKind.Identifier; } + export function isIdentifierOrPrivateName(node: Node): node is Identifier | PrivateName { + return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.PrivateName; + } + // Names export function isQualifiedName(node: Node): node is QualifiedName { @@ -5489,6 +5505,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 { diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 0d4d0d9482d6a..714a2adc34787 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -464,7 +464,7 @@ namespace ts { case SyntaxKind.PropertyAccessExpression: return updatePropertyAccess(node, visitNode((node).expression, visitor, isExpression), - visitNode((node).name, visitor, isIdentifier)); + visitNode((node).name, visitor, isIdentifierOrPrivateName)); case SyntaxKind.ElementAccessExpression: return updateElementAccess(node, diff --git a/src/services/codefixes/convertToEs6Module.ts b/src/services/codefixes/convertToEs6Module.ts index 65ea757d06098..2ea58be1e9f1d 100644 --- a/src/services/codefixes/convertToEs6Module.ts +++ b/src/services/codefixes/convertToEs6Module.ts @@ -65,7 +65,7 @@ namespace ts.codefix { function collectExportRenames(sourceFile: SourceFile, checker: TypeChecker, identifiers: Identifiers): ExportRenames { const res = createMap(); forEachExportReference(sourceFile, node => { - const { text, originalKeywordKind } = node.name; + const { text, originalKeywordKind } = node.name as Identifier; if (!res.has(text) && (originalKeywordKind !== undefined && isNonContextualKeyword(originalKeywordKind) || checker.resolveName(node.name.text, node, SymbolFlags.Value, /*excludeGlobals*/ true))) { // Unconditionally add an underscore in case `text` is a keyword. diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index ecf2841e249ef..6c5610829549f 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -310,7 +310,7 @@ namespace ts.codefix { entry.kind !== FindAllReferences.EntryKind.Span ? tryCast(entry.node, isIdentifier) : undefined); } - function inferTypeForVariableFromUsage(token: Identifier, program: Program, cancellationToken: CancellationToken): Type { + function inferTypeForVariableFromUsage(token: Identifier | PrivateName, program: Program, cancellationToken: CancellationToken): Type { const references = getReferences(token, program, cancellationToken); const checker = program.getTypeChecker(); const types = InferFromReference.inferTypesFromReferences(references, checker, cancellationToken); diff --git a/src/services/refactors/moveToNewFile.ts b/src/services/refactors/moveToNewFile.ts index ad60a6da5fc5e..a87f4972b8407 100644 --- a/src/services/refactors/moveToNewFile.ts +++ b/src/services/refactors/moveToNewFile.ts @@ -704,7 +704,7 @@ namespace ts.refactor { } function nameOfTopLevelDeclaration(d: TopLevelDeclaration): Identifier | undefined { - return isExpressionStatement(d) ? d.expression.left.name : tryCast(d.name, isIdentifier); + return isExpressionStatement(d) ? d.expression.left.name as Identifier : tryCast(d.name, isIdentifier); } function getTopLevelDeclarationStatement(d: TopLevelDeclaration): TopLevelDeclarationStatement { diff --git a/src/services/types.ts b/src/services/types.ts index 3502e3e06712f..98d496288cf02 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -28,6 +28,10 @@ namespace ts { readonly text: string; } + export interface PrivateName { + readonly text: string; + } + export interface Symbol { readonly name: string; getFlags(): SymbolFlags; diff --git a/tests/baselines/reference/MemberFunctionDeclaration8_es6.errors.txt b/tests/baselines/reference/MemberFunctionDeclaration8_es6.errors.txt index 94198b36c9033..00b2ae4b02942 100644 --- a/tests/baselines/reference/MemberFunctionDeclaration8_es6.errors.txt +++ b/tests/baselines/reference/MemberFunctionDeclaration8_es6.errors.txt @@ -9,7 +9,7 @@ tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration class C { foo() { // Make sure we don't think of *bar as the start of a generator method. - if (a) # * bar; + if (a) ¬ * bar; ~ !!! error TS2304: Cannot find name 'a'. @@ -22,4 +22,5 @@ tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration ~~~ !!! error TS2304: Cannot find name 'bar'. } - } \ No newline at end of file + } + \ No newline at end of file diff --git a/tests/baselines/reference/MemberFunctionDeclaration8_es6.js b/tests/baselines/reference/MemberFunctionDeclaration8_es6.js index 853310e5a3efe..4fba30e9659b8 100644 --- a/tests/baselines/reference/MemberFunctionDeclaration8_es6.js +++ b/tests/baselines/reference/MemberFunctionDeclaration8_es6.js @@ -2,10 +2,11 @@ class C { foo() { // Make sure we don't think of *bar as the start of a generator method. - if (a) # * bar; + if (a) ¬ * bar; return bar; } -} +} + //// [MemberFunctionDeclaration8_es6.js] class C { diff --git a/tests/baselines/reference/MemberFunctionDeclaration8_es6.symbols b/tests/baselines/reference/MemberFunctionDeclaration8_es6.symbols index 0229450477c63..35041420d6aa5 100644 --- a/tests/baselines/reference/MemberFunctionDeclaration8_es6.symbols +++ b/tests/baselines/reference/MemberFunctionDeclaration8_es6.symbols @@ -6,7 +6,8 @@ class C { >foo : Symbol(C.foo, Decl(MemberFunctionDeclaration8_es6.ts, 0, 9)) // Make sure we don't think of *bar as the start of a generator method. - if (a) # * bar; + if (a) ¬ * bar; return bar; } } + diff --git a/tests/baselines/reference/MemberFunctionDeclaration8_es6.types b/tests/baselines/reference/MemberFunctionDeclaration8_es6.types index b0234b4135ee3..9eacffd080c9d 100644 --- a/tests/baselines/reference/MemberFunctionDeclaration8_es6.types +++ b/tests/baselines/reference/MemberFunctionDeclaration8_es6.types @@ -6,7 +6,7 @@ class C { >foo : () => any // Make sure we don't think of *bar as the start of a generator method. - if (a) # * bar; + if (a) ¬ * bar; >a : any > : any >* bar : number @@ -17,3 +17,4 @@ class C { >bar : any } } + diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 59ae825a8dc80..23c1a4f2f4b9c 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -149,267 +149,268 @@ declare namespace ts { BarEqualsToken = 70, CaretEqualsToken = 71, Identifier = 72, - BreakKeyword = 73, - CaseKeyword = 74, - CatchKeyword = 75, - ClassKeyword = 76, - ConstKeyword = 77, - ContinueKeyword = 78, - DebuggerKeyword = 79, - DefaultKeyword = 80, - DeleteKeyword = 81, - DoKeyword = 82, - ElseKeyword = 83, - EnumKeyword = 84, - ExportKeyword = 85, - ExtendsKeyword = 86, - FalseKeyword = 87, - FinallyKeyword = 88, - ForKeyword = 89, - FunctionKeyword = 90, - IfKeyword = 91, - ImportKeyword = 92, - InKeyword = 93, - InstanceOfKeyword = 94, - NewKeyword = 95, - NullKeyword = 96, - ReturnKeyword = 97, - SuperKeyword = 98, - SwitchKeyword = 99, - ThisKeyword = 100, - ThrowKeyword = 101, - TrueKeyword = 102, - TryKeyword = 103, - TypeOfKeyword = 104, - VarKeyword = 105, - VoidKeyword = 106, - WhileKeyword = 107, - WithKeyword = 108, - ImplementsKeyword = 109, - InterfaceKeyword = 110, - LetKeyword = 111, - PackageKeyword = 112, - PrivateKeyword = 113, - ProtectedKeyword = 114, - PublicKeyword = 115, - StaticKeyword = 116, - YieldKeyword = 117, - AbstractKeyword = 118, - AsKeyword = 119, - AnyKeyword = 120, - AsyncKeyword = 121, - AwaitKeyword = 122, - BooleanKeyword = 123, - ConstructorKeyword = 124, - DeclareKeyword = 125, - GetKeyword = 126, - InferKeyword = 127, - IsKeyword = 128, - KeyOfKeyword = 129, - ModuleKeyword = 130, - NamespaceKeyword = 131, - NeverKeyword = 132, - ReadonlyKeyword = 133, - RequireKeyword = 134, - NumberKeyword = 135, - ObjectKeyword = 136, - SetKeyword = 137, - StringKeyword = 138, - SymbolKeyword = 139, - TypeKeyword = 140, - UndefinedKeyword = 141, - UniqueKeyword = 142, - UnknownKeyword = 143, - FromKeyword = 144, - GlobalKeyword = 145, - BigIntKeyword = 146, - OfKeyword = 147, - QualifiedName = 148, - ComputedPropertyName = 149, - TypeParameter = 150, - Parameter = 151, - Decorator = 152, - PropertySignature = 153, - PropertyDeclaration = 154, - MethodSignature = 155, - MethodDeclaration = 156, - Constructor = 157, - GetAccessor = 158, - SetAccessor = 159, - CallSignature = 160, - ConstructSignature = 161, - IndexSignature = 162, - TypePredicate = 163, - TypeReference = 164, - FunctionType = 165, - ConstructorType = 166, - TypeQuery = 167, - TypeLiteral = 168, - ArrayType = 169, - TupleType = 170, - OptionalType = 171, - RestType = 172, - UnionType = 173, - IntersectionType = 174, - ConditionalType = 175, - InferType = 176, - ParenthesizedType = 177, - ThisType = 178, - TypeOperator = 179, - IndexedAccessType = 180, - MappedType = 181, - LiteralType = 182, - ImportType = 183, - ObjectBindingPattern = 184, - ArrayBindingPattern = 185, - BindingElement = 186, - ArrayLiteralExpression = 187, - ObjectLiteralExpression = 188, - PropertyAccessExpression = 189, - ElementAccessExpression = 190, - CallExpression = 191, - NewExpression = 192, - TaggedTemplateExpression = 193, - TypeAssertionExpression = 194, - ParenthesizedExpression = 195, - FunctionExpression = 196, - ArrowFunction = 197, - DeleteExpression = 198, - TypeOfExpression = 199, - VoidExpression = 200, - AwaitExpression = 201, - PrefixUnaryExpression = 202, - PostfixUnaryExpression = 203, - BinaryExpression = 204, - ConditionalExpression = 205, - TemplateExpression = 206, - YieldExpression = 207, - SpreadElement = 208, - ClassExpression = 209, - OmittedExpression = 210, - ExpressionWithTypeArguments = 211, - AsExpression = 212, - NonNullExpression = 213, - MetaProperty = 214, - SyntheticExpression = 215, - TemplateSpan = 216, - SemicolonClassElement = 217, - Block = 218, - VariableStatement = 219, - EmptyStatement = 220, - ExpressionStatement = 221, - IfStatement = 222, - DoStatement = 223, - WhileStatement = 224, - ForStatement = 225, - ForInStatement = 226, - ForOfStatement = 227, - ContinueStatement = 228, - BreakStatement = 229, - ReturnStatement = 230, - WithStatement = 231, - SwitchStatement = 232, - LabeledStatement = 233, - ThrowStatement = 234, - TryStatement = 235, - DebuggerStatement = 236, - VariableDeclaration = 237, - VariableDeclarationList = 238, - FunctionDeclaration = 239, - ClassDeclaration = 240, - InterfaceDeclaration = 241, - TypeAliasDeclaration = 242, - EnumDeclaration = 243, - ModuleDeclaration = 244, - ModuleBlock = 245, - CaseBlock = 246, - NamespaceExportDeclaration = 247, - ImportEqualsDeclaration = 248, - ImportDeclaration = 249, - ImportClause = 250, - NamespaceImport = 251, - NamedImports = 252, - ImportSpecifier = 253, - ExportAssignment = 254, - ExportDeclaration = 255, - NamedExports = 256, - ExportSpecifier = 257, - MissingDeclaration = 258, - ExternalModuleReference = 259, - JsxElement = 260, - JsxSelfClosingElement = 261, - JsxOpeningElement = 262, - JsxClosingElement = 263, - JsxFragment = 264, - JsxOpeningFragment = 265, - JsxClosingFragment = 266, - JsxAttribute = 267, - JsxAttributes = 268, - JsxSpreadAttribute = 269, - JsxExpression = 270, - CaseClause = 271, - DefaultClause = 272, - HeritageClause = 273, - CatchClause = 274, - PropertyAssignment = 275, - ShorthandPropertyAssignment = 276, - SpreadAssignment = 277, - EnumMember = 278, - UnparsedPrologue = 279, - UnparsedPrepend = 280, - UnparsedText = 281, - UnparsedInternalText = 282, - UnparsedSyntheticReference = 283, - SourceFile = 284, - Bundle = 285, - UnparsedSource = 286, - InputFiles = 287, - JSDocTypeExpression = 288, - JSDocAllType = 289, - JSDocUnknownType = 290, - JSDocNullableType = 291, - JSDocNonNullableType = 292, - JSDocOptionalType = 293, - JSDocFunctionType = 294, - JSDocVariadicType = 295, - JSDocComment = 296, - JSDocTypeLiteral = 297, - JSDocSignature = 298, - JSDocTag = 299, - JSDocAugmentsTag = 300, - JSDocClassTag = 301, - JSDocCallbackTag = 302, - JSDocEnumTag = 303, - JSDocParameterTag = 304, - JSDocReturnTag = 305, - JSDocThisTag = 306, - JSDocTypeTag = 307, - JSDocTemplateTag = 308, - JSDocTypedefTag = 309, - JSDocPropertyTag = 310, - SyntaxList = 311, - NotEmittedStatement = 312, - PartiallyEmittedExpression = 313, - CommaListExpression = 314, - MergeDeclarationMarker = 315, - EndOfDeclarationMarker = 316, - Count = 317, + PrivateName = 73, + BreakKeyword = 74, + CaseKeyword = 75, + CatchKeyword = 76, + ClassKeyword = 77, + ConstKeyword = 78, + ContinueKeyword = 79, + DebuggerKeyword = 80, + DefaultKeyword = 81, + DeleteKeyword = 82, + DoKeyword = 83, + ElseKeyword = 84, + EnumKeyword = 85, + ExportKeyword = 86, + ExtendsKeyword = 87, + FalseKeyword = 88, + FinallyKeyword = 89, + ForKeyword = 90, + FunctionKeyword = 91, + IfKeyword = 92, + ImportKeyword = 93, + InKeyword = 94, + InstanceOfKeyword = 95, + NewKeyword = 96, + NullKeyword = 97, + ReturnKeyword = 98, + SuperKeyword = 99, + SwitchKeyword = 100, + ThisKeyword = 101, + ThrowKeyword = 102, + TrueKeyword = 103, + TryKeyword = 104, + TypeOfKeyword = 105, + VarKeyword = 106, + VoidKeyword = 107, + WhileKeyword = 108, + WithKeyword = 109, + ImplementsKeyword = 110, + InterfaceKeyword = 111, + LetKeyword = 112, + PackageKeyword = 113, + PrivateKeyword = 114, + ProtectedKeyword = 115, + PublicKeyword = 116, + StaticKeyword = 117, + YieldKeyword = 118, + AbstractKeyword = 119, + AsKeyword = 120, + AnyKeyword = 121, + AsyncKeyword = 122, + AwaitKeyword = 123, + BooleanKeyword = 124, + ConstructorKeyword = 125, + DeclareKeyword = 126, + GetKeyword = 127, + InferKeyword = 128, + IsKeyword = 129, + KeyOfKeyword = 130, + ModuleKeyword = 131, + NamespaceKeyword = 132, + NeverKeyword = 133, + ReadonlyKeyword = 134, + RequireKeyword = 135, + NumberKeyword = 136, + ObjectKeyword = 137, + SetKeyword = 138, + StringKeyword = 139, + SymbolKeyword = 140, + TypeKeyword = 141, + UndefinedKeyword = 142, + UniqueKeyword = 143, + UnknownKeyword = 144, + FromKeyword = 145, + GlobalKeyword = 146, + BigIntKeyword = 147, + OfKeyword = 148, + QualifiedName = 149, + ComputedPropertyName = 150, + TypeParameter = 151, + Parameter = 152, + Decorator = 153, + PropertySignature = 154, + PropertyDeclaration = 155, + MethodSignature = 156, + MethodDeclaration = 157, + Constructor = 158, + GetAccessor = 159, + SetAccessor = 160, + CallSignature = 161, + ConstructSignature = 162, + IndexSignature = 163, + TypePredicate = 164, + TypeReference = 165, + FunctionType = 166, + ConstructorType = 167, + TypeQuery = 168, + TypeLiteral = 169, + ArrayType = 170, + TupleType = 171, + OptionalType = 172, + RestType = 173, + UnionType = 174, + IntersectionType = 175, + ConditionalType = 176, + InferType = 177, + ParenthesizedType = 178, + ThisType = 179, + TypeOperator = 180, + IndexedAccessType = 181, + MappedType = 182, + LiteralType = 183, + ImportType = 184, + ObjectBindingPattern = 185, + ArrayBindingPattern = 186, + BindingElement = 187, + ArrayLiteralExpression = 188, + ObjectLiteralExpression = 189, + PropertyAccessExpression = 190, + ElementAccessExpression = 191, + CallExpression = 192, + NewExpression = 193, + TaggedTemplateExpression = 194, + TypeAssertionExpression = 195, + ParenthesizedExpression = 196, + FunctionExpression = 197, + ArrowFunction = 198, + DeleteExpression = 199, + TypeOfExpression = 200, + VoidExpression = 201, + AwaitExpression = 202, + PrefixUnaryExpression = 203, + PostfixUnaryExpression = 204, + BinaryExpression = 205, + ConditionalExpression = 206, + TemplateExpression = 207, + YieldExpression = 208, + SpreadElement = 209, + ClassExpression = 210, + OmittedExpression = 211, + ExpressionWithTypeArguments = 212, + AsExpression = 213, + NonNullExpression = 214, + MetaProperty = 215, + SyntheticExpression = 216, + TemplateSpan = 217, + SemicolonClassElement = 218, + Block = 219, + VariableStatement = 220, + EmptyStatement = 221, + ExpressionStatement = 222, + IfStatement = 223, + DoStatement = 224, + WhileStatement = 225, + ForStatement = 226, + ForInStatement = 227, + ForOfStatement = 228, + ContinueStatement = 229, + BreakStatement = 230, + ReturnStatement = 231, + WithStatement = 232, + SwitchStatement = 233, + LabeledStatement = 234, + ThrowStatement = 235, + TryStatement = 236, + DebuggerStatement = 237, + VariableDeclaration = 238, + VariableDeclarationList = 239, + FunctionDeclaration = 240, + ClassDeclaration = 241, + InterfaceDeclaration = 242, + TypeAliasDeclaration = 243, + EnumDeclaration = 244, + ModuleDeclaration = 245, + ModuleBlock = 246, + CaseBlock = 247, + NamespaceExportDeclaration = 248, + ImportEqualsDeclaration = 249, + ImportDeclaration = 250, + ImportClause = 251, + NamespaceImport = 252, + NamedImports = 253, + ImportSpecifier = 254, + ExportAssignment = 255, + ExportDeclaration = 256, + NamedExports = 257, + ExportSpecifier = 258, + MissingDeclaration = 259, + ExternalModuleReference = 260, + JsxElement = 261, + JsxSelfClosingElement = 262, + JsxOpeningElement = 263, + JsxClosingElement = 264, + JsxFragment = 265, + JsxOpeningFragment = 266, + JsxClosingFragment = 267, + JsxAttribute = 268, + JsxAttributes = 269, + JsxSpreadAttribute = 270, + JsxExpression = 271, + CaseClause = 272, + DefaultClause = 273, + HeritageClause = 274, + CatchClause = 275, + PropertyAssignment = 276, + ShorthandPropertyAssignment = 277, + SpreadAssignment = 278, + EnumMember = 279, + UnparsedPrologue = 280, + UnparsedPrepend = 281, + UnparsedText = 282, + UnparsedInternalText = 283, + UnparsedSyntheticReference = 284, + SourceFile = 285, + Bundle = 286, + UnparsedSource = 287, + InputFiles = 288, + JSDocTypeExpression = 289, + JSDocAllType = 290, + JSDocUnknownType = 291, + JSDocNullableType = 292, + JSDocNonNullableType = 293, + JSDocOptionalType = 294, + JSDocFunctionType = 295, + JSDocVariadicType = 296, + JSDocComment = 297, + JSDocTypeLiteral = 298, + JSDocSignature = 299, + JSDocTag = 300, + JSDocAugmentsTag = 301, + JSDocClassTag = 302, + JSDocCallbackTag = 303, + JSDocEnumTag = 304, + JSDocParameterTag = 305, + JSDocReturnTag = 306, + JSDocThisTag = 307, + JSDocTypeTag = 308, + JSDocTemplateTag = 309, + JSDocTypedefTag = 310, + JSDocPropertyTag = 311, + SyntaxList = 312, + NotEmittedStatement = 313, + PartiallyEmittedExpression = 314, + CommaListExpression = 315, + MergeDeclarationMarker = 316, + EndOfDeclarationMarker = 317, + Count = 318, FirstAssignment = 59, LastAssignment = 71, FirstCompoundAssignment = 60, LastCompoundAssignment = 71, - FirstReservedWord = 73, - LastReservedWord = 108, - FirstKeyword = 73, - LastKeyword = 147, - FirstFutureReservedWord = 109, - LastFutureReservedWord = 117, - FirstTypeNode = 163, - LastTypeNode = 183, + FirstReservedWord = 74, + LastReservedWord = 109, + FirstKeyword = 74, + LastKeyword = 148, + FirstFutureReservedWord = 110, + LastFutureReservedWord = 118, + FirstTypeNode = 164, + LastTypeNode = 184, FirstPunctuation = 18, LastPunctuation = 71, FirstToken = 0, - LastToken = 147, + LastToken = 148, FirstTriviaToken = 2, LastTriviaToken = 7, FirstLiteralToken = 8, @@ -418,11 +419,11 @@ declare namespace ts { LastTemplateToken = 17, FirstBinaryOperator = 28, LastBinaryOperator = 71, - FirstNode = 148, - FirstJSDocNode = 288, - LastJSDocNode = 310, - FirstJSDocTagNode = 299, - LastJSDocTagNode = 310, + FirstNode = 149, + FirstJSDocNode = 289, + LastJSDocNode = 311, + FirstJSDocTagNode = 300, + LastJSDocTagNode = 311, } enum NodeFlags { None = 0, @@ -534,8 +535,8 @@ declare namespace ts { right: Identifier; } type EntityName = Identifier | QualifiedName; - type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName; - type DeclarationName = Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern; + type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | PrivateName; + type DeclarationName = Identifier | PrivateName | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern; interface Declaration extends Node { _declarationBrand: any; } @@ -550,6 +551,10 @@ declare namespace ts { kind: SyntaxKind.ComputedPropertyName; expression: Expression; } + interface PrivateName extends PrimaryExpression, Declaration { + kind: SyntaxKind.PrivateName; + escapedText: __String; + } interface Decorator extends Node { kind: SyntaxKind.Decorator; parent: NamedDeclaration; @@ -1070,7 +1075,7 @@ declare namespace ts { interface PropertyAccessExpression extends MemberExpression, NamedDeclaration { kind: SyntaxKind.PropertyAccessExpression; expression: LeftHandSideExpression; - name: Identifier; + name: Identifier | PrivateName; } interface SuperPropertyAccessExpression extends PropertyAccessExpression { expression: SuperExpression; @@ -3280,9 +3285,9 @@ declare namespace ts { * @returns The unescaped identifier text. */ function unescapeLeadingUnderscores(identifier: __String): string; - function idText(identifier: Identifier): string; + function idText(identifierOrPrivateName: Identifier | PrivateName): string; function symbolName(symbol: Symbol): string; - function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined; + function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | PrivateName | undefined; function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName | undefined; /** * Gets the JSDoc parameter tags for the node if present. @@ -3370,8 +3375,10 @@ declare namespace ts { function isTemplateMiddle(node: Node): node is TemplateMiddle; function isTemplateTail(node: Node): node is TemplateTail; function isIdentifier(node: Node): node is Identifier; + function isIdentifierOrPrivateName(node: Node): node is Identifier | PrivateName; function isQualifiedName(node: Node): node is QualifiedName; function isComputedPropertyName(node: Node): node is ComputedPropertyName; + function isPrivateName(node: Node): node is PrivateName; function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration; function isParameter(node: Node): node is ParameterDeclaration; function isDecorator(node: Node): node is Decorator; @@ -3837,8 +3844,8 @@ declare namespace ts { function updateArrayLiteral(node: ArrayLiteralExpression, elements: ReadonlyArray): ArrayLiteralExpression; function createObjectLiteral(properties?: ReadonlyArray, multiLine?: boolean): ObjectLiteralExpression; function updateObjectLiteral(node: ObjectLiteralExpression, properties: ReadonlyArray): ObjectLiteralExpression; - function createPropertyAccess(expression: Expression, name: string | Identifier | undefined): PropertyAccessExpression; - function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier): PropertyAccessExpression; + function createPropertyAccess(expression: Expression, name: string | Identifier | PrivateName | undefined): PropertyAccessExpression; + function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier | PrivateName): PropertyAccessExpression; function createElementAccess(expression: Expression, index: number | Expression): ElementAccessExpression; function updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression): ElementAccessExpression; function createCall(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): CallExpression; @@ -4629,6 +4636,9 @@ declare namespace ts { interface Identifier { readonly text: string; } + interface PrivateName { + readonly text: string; + } interface Symbol { readonly name: string; getFlags(): SymbolFlags; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 2b8056735a476..3ee850633e9d0 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -149,267 +149,268 @@ declare namespace ts { BarEqualsToken = 70, CaretEqualsToken = 71, Identifier = 72, - BreakKeyword = 73, - CaseKeyword = 74, - CatchKeyword = 75, - ClassKeyword = 76, - ConstKeyword = 77, - ContinueKeyword = 78, - DebuggerKeyword = 79, - DefaultKeyword = 80, - DeleteKeyword = 81, - DoKeyword = 82, - ElseKeyword = 83, - EnumKeyword = 84, - ExportKeyword = 85, - ExtendsKeyword = 86, - FalseKeyword = 87, - FinallyKeyword = 88, - ForKeyword = 89, - FunctionKeyword = 90, - IfKeyword = 91, - ImportKeyword = 92, - InKeyword = 93, - InstanceOfKeyword = 94, - NewKeyword = 95, - NullKeyword = 96, - ReturnKeyword = 97, - SuperKeyword = 98, - SwitchKeyword = 99, - ThisKeyword = 100, - ThrowKeyword = 101, - TrueKeyword = 102, - TryKeyword = 103, - TypeOfKeyword = 104, - VarKeyword = 105, - VoidKeyword = 106, - WhileKeyword = 107, - WithKeyword = 108, - ImplementsKeyword = 109, - InterfaceKeyword = 110, - LetKeyword = 111, - PackageKeyword = 112, - PrivateKeyword = 113, - ProtectedKeyword = 114, - PublicKeyword = 115, - StaticKeyword = 116, - YieldKeyword = 117, - AbstractKeyword = 118, - AsKeyword = 119, - AnyKeyword = 120, - AsyncKeyword = 121, - AwaitKeyword = 122, - BooleanKeyword = 123, - ConstructorKeyword = 124, - DeclareKeyword = 125, - GetKeyword = 126, - InferKeyword = 127, - IsKeyword = 128, - KeyOfKeyword = 129, - ModuleKeyword = 130, - NamespaceKeyword = 131, - NeverKeyword = 132, - ReadonlyKeyword = 133, - RequireKeyword = 134, - NumberKeyword = 135, - ObjectKeyword = 136, - SetKeyword = 137, - StringKeyword = 138, - SymbolKeyword = 139, - TypeKeyword = 140, - UndefinedKeyword = 141, - UniqueKeyword = 142, - UnknownKeyword = 143, - FromKeyword = 144, - GlobalKeyword = 145, - BigIntKeyword = 146, - OfKeyword = 147, - QualifiedName = 148, - ComputedPropertyName = 149, - TypeParameter = 150, - Parameter = 151, - Decorator = 152, - PropertySignature = 153, - PropertyDeclaration = 154, - MethodSignature = 155, - MethodDeclaration = 156, - Constructor = 157, - GetAccessor = 158, - SetAccessor = 159, - CallSignature = 160, - ConstructSignature = 161, - IndexSignature = 162, - TypePredicate = 163, - TypeReference = 164, - FunctionType = 165, - ConstructorType = 166, - TypeQuery = 167, - TypeLiteral = 168, - ArrayType = 169, - TupleType = 170, - OptionalType = 171, - RestType = 172, - UnionType = 173, - IntersectionType = 174, - ConditionalType = 175, - InferType = 176, - ParenthesizedType = 177, - ThisType = 178, - TypeOperator = 179, - IndexedAccessType = 180, - MappedType = 181, - LiteralType = 182, - ImportType = 183, - ObjectBindingPattern = 184, - ArrayBindingPattern = 185, - BindingElement = 186, - ArrayLiteralExpression = 187, - ObjectLiteralExpression = 188, - PropertyAccessExpression = 189, - ElementAccessExpression = 190, - CallExpression = 191, - NewExpression = 192, - TaggedTemplateExpression = 193, - TypeAssertionExpression = 194, - ParenthesizedExpression = 195, - FunctionExpression = 196, - ArrowFunction = 197, - DeleteExpression = 198, - TypeOfExpression = 199, - VoidExpression = 200, - AwaitExpression = 201, - PrefixUnaryExpression = 202, - PostfixUnaryExpression = 203, - BinaryExpression = 204, - ConditionalExpression = 205, - TemplateExpression = 206, - YieldExpression = 207, - SpreadElement = 208, - ClassExpression = 209, - OmittedExpression = 210, - ExpressionWithTypeArguments = 211, - AsExpression = 212, - NonNullExpression = 213, - MetaProperty = 214, - SyntheticExpression = 215, - TemplateSpan = 216, - SemicolonClassElement = 217, - Block = 218, - VariableStatement = 219, - EmptyStatement = 220, - ExpressionStatement = 221, - IfStatement = 222, - DoStatement = 223, - WhileStatement = 224, - ForStatement = 225, - ForInStatement = 226, - ForOfStatement = 227, - ContinueStatement = 228, - BreakStatement = 229, - ReturnStatement = 230, - WithStatement = 231, - SwitchStatement = 232, - LabeledStatement = 233, - ThrowStatement = 234, - TryStatement = 235, - DebuggerStatement = 236, - VariableDeclaration = 237, - VariableDeclarationList = 238, - FunctionDeclaration = 239, - ClassDeclaration = 240, - InterfaceDeclaration = 241, - TypeAliasDeclaration = 242, - EnumDeclaration = 243, - ModuleDeclaration = 244, - ModuleBlock = 245, - CaseBlock = 246, - NamespaceExportDeclaration = 247, - ImportEqualsDeclaration = 248, - ImportDeclaration = 249, - ImportClause = 250, - NamespaceImport = 251, - NamedImports = 252, - ImportSpecifier = 253, - ExportAssignment = 254, - ExportDeclaration = 255, - NamedExports = 256, - ExportSpecifier = 257, - MissingDeclaration = 258, - ExternalModuleReference = 259, - JsxElement = 260, - JsxSelfClosingElement = 261, - JsxOpeningElement = 262, - JsxClosingElement = 263, - JsxFragment = 264, - JsxOpeningFragment = 265, - JsxClosingFragment = 266, - JsxAttribute = 267, - JsxAttributes = 268, - JsxSpreadAttribute = 269, - JsxExpression = 270, - CaseClause = 271, - DefaultClause = 272, - HeritageClause = 273, - CatchClause = 274, - PropertyAssignment = 275, - ShorthandPropertyAssignment = 276, - SpreadAssignment = 277, - EnumMember = 278, - UnparsedPrologue = 279, - UnparsedPrepend = 280, - UnparsedText = 281, - UnparsedInternalText = 282, - UnparsedSyntheticReference = 283, - SourceFile = 284, - Bundle = 285, - UnparsedSource = 286, - InputFiles = 287, - JSDocTypeExpression = 288, - JSDocAllType = 289, - JSDocUnknownType = 290, - JSDocNullableType = 291, - JSDocNonNullableType = 292, - JSDocOptionalType = 293, - JSDocFunctionType = 294, - JSDocVariadicType = 295, - JSDocComment = 296, - JSDocTypeLiteral = 297, - JSDocSignature = 298, - JSDocTag = 299, - JSDocAugmentsTag = 300, - JSDocClassTag = 301, - JSDocCallbackTag = 302, - JSDocEnumTag = 303, - JSDocParameterTag = 304, - JSDocReturnTag = 305, - JSDocThisTag = 306, - JSDocTypeTag = 307, - JSDocTemplateTag = 308, - JSDocTypedefTag = 309, - JSDocPropertyTag = 310, - SyntaxList = 311, - NotEmittedStatement = 312, - PartiallyEmittedExpression = 313, - CommaListExpression = 314, - MergeDeclarationMarker = 315, - EndOfDeclarationMarker = 316, - Count = 317, + PrivateName = 73, + BreakKeyword = 74, + CaseKeyword = 75, + CatchKeyword = 76, + ClassKeyword = 77, + ConstKeyword = 78, + ContinueKeyword = 79, + DebuggerKeyword = 80, + DefaultKeyword = 81, + DeleteKeyword = 82, + DoKeyword = 83, + ElseKeyword = 84, + EnumKeyword = 85, + ExportKeyword = 86, + ExtendsKeyword = 87, + FalseKeyword = 88, + FinallyKeyword = 89, + ForKeyword = 90, + FunctionKeyword = 91, + IfKeyword = 92, + ImportKeyword = 93, + InKeyword = 94, + InstanceOfKeyword = 95, + NewKeyword = 96, + NullKeyword = 97, + ReturnKeyword = 98, + SuperKeyword = 99, + SwitchKeyword = 100, + ThisKeyword = 101, + ThrowKeyword = 102, + TrueKeyword = 103, + TryKeyword = 104, + TypeOfKeyword = 105, + VarKeyword = 106, + VoidKeyword = 107, + WhileKeyword = 108, + WithKeyword = 109, + ImplementsKeyword = 110, + InterfaceKeyword = 111, + LetKeyword = 112, + PackageKeyword = 113, + PrivateKeyword = 114, + ProtectedKeyword = 115, + PublicKeyword = 116, + StaticKeyword = 117, + YieldKeyword = 118, + AbstractKeyword = 119, + AsKeyword = 120, + AnyKeyword = 121, + AsyncKeyword = 122, + AwaitKeyword = 123, + BooleanKeyword = 124, + ConstructorKeyword = 125, + DeclareKeyword = 126, + GetKeyword = 127, + InferKeyword = 128, + IsKeyword = 129, + KeyOfKeyword = 130, + ModuleKeyword = 131, + NamespaceKeyword = 132, + NeverKeyword = 133, + ReadonlyKeyword = 134, + RequireKeyword = 135, + NumberKeyword = 136, + ObjectKeyword = 137, + SetKeyword = 138, + StringKeyword = 139, + SymbolKeyword = 140, + TypeKeyword = 141, + UndefinedKeyword = 142, + UniqueKeyword = 143, + UnknownKeyword = 144, + FromKeyword = 145, + GlobalKeyword = 146, + BigIntKeyword = 147, + OfKeyword = 148, + QualifiedName = 149, + ComputedPropertyName = 150, + TypeParameter = 151, + Parameter = 152, + Decorator = 153, + PropertySignature = 154, + PropertyDeclaration = 155, + MethodSignature = 156, + MethodDeclaration = 157, + Constructor = 158, + GetAccessor = 159, + SetAccessor = 160, + CallSignature = 161, + ConstructSignature = 162, + IndexSignature = 163, + TypePredicate = 164, + TypeReference = 165, + FunctionType = 166, + ConstructorType = 167, + TypeQuery = 168, + TypeLiteral = 169, + ArrayType = 170, + TupleType = 171, + OptionalType = 172, + RestType = 173, + UnionType = 174, + IntersectionType = 175, + ConditionalType = 176, + InferType = 177, + ParenthesizedType = 178, + ThisType = 179, + TypeOperator = 180, + IndexedAccessType = 181, + MappedType = 182, + LiteralType = 183, + ImportType = 184, + ObjectBindingPattern = 185, + ArrayBindingPattern = 186, + BindingElement = 187, + ArrayLiteralExpression = 188, + ObjectLiteralExpression = 189, + PropertyAccessExpression = 190, + ElementAccessExpression = 191, + CallExpression = 192, + NewExpression = 193, + TaggedTemplateExpression = 194, + TypeAssertionExpression = 195, + ParenthesizedExpression = 196, + FunctionExpression = 197, + ArrowFunction = 198, + DeleteExpression = 199, + TypeOfExpression = 200, + VoidExpression = 201, + AwaitExpression = 202, + PrefixUnaryExpression = 203, + PostfixUnaryExpression = 204, + BinaryExpression = 205, + ConditionalExpression = 206, + TemplateExpression = 207, + YieldExpression = 208, + SpreadElement = 209, + ClassExpression = 210, + OmittedExpression = 211, + ExpressionWithTypeArguments = 212, + AsExpression = 213, + NonNullExpression = 214, + MetaProperty = 215, + SyntheticExpression = 216, + TemplateSpan = 217, + SemicolonClassElement = 218, + Block = 219, + VariableStatement = 220, + EmptyStatement = 221, + ExpressionStatement = 222, + IfStatement = 223, + DoStatement = 224, + WhileStatement = 225, + ForStatement = 226, + ForInStatement = 227, + ForOfStatement = 228, + ContinueStatement = 229, + BreakStatement = 230, + ReturnStatement = 231, + WithStatement = 232, + SwitchStatement = 233, + LabeledStatement = 234, + ThrowStatement = 235, + TryStatement = 236, + DebuggerStatement = 237, + VariableDeclaration = 238, + VariableDeclarationList = 239, + FunctionDeclaration = 240, + ClassDeclaration = 241, + InterfaceDeclaration = 242, + TypeAliasDeclaration = 243, + EnumDeclaration = 244, + ModuleDeclaration = 245, + ModuleBlock = 246, + CaseBlock = 247, + NamespaceExportDeclaration = 248, + ImportEqualsDeclaration = 249, + ImportDeclaration = 250, + ImportClause = 251, + NamespaceImport = 252, + NamedImports = 253, + ImportSpecifier = 254, + ExportAssignment = 255, + ExportDeclaration = 256, + NamedExports = 257, + ExportSpecifier = 258, + MissingDeclaration = 259, + ExternalModuleReference = 260, + JsxElement = 261, + JsxSelfClosingElement = 262, + JsxOpeningElement = 263, + JsxClosingElement = 264, + JsxFragment = 265, + JsxOpeningFragment = 266, + JsxClosingFragment = 267, + JsxAttribute = 268, + JsxAttributes = 269, + JsxSpreadAttribute = 270, + JsxExpression = 271, + CaseClause = 272, + DefaultClause = 273, + HeritageClause = 274, + CatchClause = 275, + PropertyAssignment = 276, + ShorthandPropertyAssignment = 277, + SpreadAssignment = 278, + EnumMember = 279, + UnparsedPrologue = 280, + UnparsedPrepend = 281, + UnparsedText = 282, + UnparsedInternalText = 283, + UnparsedSyntheticReference = 284, + SourceFile = 285, + Bundle = 286, + UnparsedSource = 287, + InputFiles = 288, + JSDocTypeExpression = 289, + JSDocAllType = 290, + JSDocUnknownType = 291, + JSDocNullableType = 292, + JSDocNonNullableType = 293, + JSDocOptionalType = 294, + JSDocFunctionType = 295, + JSDocVariadicType = 296, + JSDocComment = 297, + JSDocTypeLiteral = 298, + JSDocSignature = 299, + JSDocTag = 300, + JSDocAugmentsTag = 301, + JSDocClassTag = 302, + JSDocCallbackTag = 303, + JSDocEnumTag = 304, + JSDocParameterTag = 305, + JSDocReturnTag = 306, + JSDocThisTag = 307, + JSDocTypeTag = 308, + JSDocTemplateTag = 309, + JSDocTypedefTag = 310, + JSDocPropertyTag = 311, + SyntaxList = 312, + NotEmittedStatement = 313, + PartiallyEmittedExpression = 314, + CommaListExpression = 315, + MergeDeclarationMarker = 316, + EndOfDeclarationMarker = 317, + Count = 318, FirstAssignment = 59, LastAssignment = 71, FirstCompoundAssignment = 60, LastCompoundAssignment = 71, - FirstReservedWord = 73, - LastReservedWord = 108, - FirstKeyword = 73, - LastKeyword = 147, - FirstFutureReservedWord = 109, - LastFutureReservedWord = 117, - FirstTypeNode = 163, - LastTypeNode = 183, + FirstReservedWord = 74, + LastReservedWord = 109, + FirstKeyword = 74, + LastKeyword = 148, + FirstFutureReservedWord = 110, + LastFutureReservedWord = 118, + FirstTypeNode = 164, + LastTypeNode = 184, FirstPunctuation = 18, LastPunctuation = 71, FirstToken = 0, - LastToken = 147, + LastToken = 148, FirstTriviaToken = 2, LastTriviaToken = 7, FirstLiteralToken = 8, @@ -418,11 +419,11 @@ declare namespace ts { LastTemplateToken = 17, FirstBinaryOperator = 28, LastBinaryOperator = 71, - FirstNode = 148, - FirstJSDocNode = 288, - LastJSDocNode = 310, - FirstJSDocTagNode = 299, - LastJSDocTagNode = 310, + FirstNode = 149, + FirstJSDocNode = 289, + LastJSDocNode = 311, + FirstJSDocTagNode = 300, + LastJSDocTagNode = 311, } enum NodeFlags { None = 0, @@ -534,8 +535,8 @@ declare namespace ts { right: Identifier; } type EntityName = Identifier | QualifiedName; - type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName; - type DeclarationName = Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern; + type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | PrivateName; + type DeclarationName = Identifier | PrivateName | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern; interface Declaration extends Node { _declarationBrand: any; } @@ -550,6 +551,10 @@ declare namespace ts { kind: SyntaxKind.ComputedPropertyName; expression: Expression; } + interface PrivateName extends PrimaryExpression, Declaration { + kind: SyntaxKind.PrivateName; + escapedText: __String; + } interface Decorator extends Node { kind: SyntaxKind.Decorator; parent: NamedDeclaration; @@ -1070,7 +1075,7 @@ declare namespace ts { interface PropertyAccessExpression extends MemberExpression, NamedDeclaration { kind: SyntaxKind.PropertyAccessExpression; expression: LeftHandSideExpression; - name: Identifier; + name: Identifier | PrivateName; } interface SuperPropertyAccessExpression extends PropertyAccessExpression { expression: SuperExpression; @@ -3280,9 +3285,9 @@ declare namespace ts { * @returns The unescaped identifier text. */ function unescapeLeadingUnderscores(identifier: __String): string; - function idText(identifier: Identifier): string; + function idText(identifierOrPrivateName: Identifier | PrivateName): string; function symbolName(symbol: Symbol): string; - function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined; + function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | PrivateName | undefined; function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName | undefined; /** * Gets the JSDoc parameter tags for the node if present. @@ -3370,8 +3375,10 @@ declare namespace ts { function isTemplateMiddle(node: Node): node is TemplateMiddle; function isTemplateTail(node: Node): node is TemplateTail; function isIdentifier(node: Node): node is Identifier; + function isIdentifierOrPrivateName(node: Node): node is Identifier | PrivateName; function isQualifiedName(node: Node): node is QualifiedName; function isComputedPropertyName(node: Node): node is ComputedPropertyName; + function isPrivateName(node: Node): node is PrivateName; function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration; function isParameter(node: Node): node is ParameterDeclaration; function isDecorator(node: Node): node is Decorator; @@ -3837,8 +3844,8 @@ declare namespace ts { function updateArrayLiteral(node: ArrayLiteralExpression, elements: ReadonlyArray): ArrayLiteralExpression; function createObjectLiteral(properties?: ReadonlyArray, multiLine?: boolean): ObjectLiteralExpression; function updateObjectLiteral(node: ObjectLiteralExpression, properties: ReadonlyArray): ObjectLiteralExpression; - function createPropertyAccess(expression: Expression, name: string | Identifier | undefined): PropertyAccessExpression; - function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier): PropertyAccessExpression; + function createPropertyAccess(expression: Expression, name: string | Identifier | PrivateName | undefined): PropertyAccessExpression; + function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier | PrivateName): PropertyAccessExpression; function createElementAccess(expression: Expression, index: number | Expression): ElementAccessExpression; function updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression): ElementAccessExpression; function createCall(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): CallExpression; @@ -4629,6 +4636,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/parseErrorInHeritageClause1.errors.txt b/tests/baselines/reference/parseErrorInHeritageClause1.errors.txt index 67564442b3abc..722004686f23c 100644 --- a/tests/baselines/reference/parseErrorInHeritageClause1.errors.txt +++ b/tests/baselines/reference/parseErrorInHeritageClause1.errors.txt @@ -3,9 +3,10 @@ tests/cases/compiler/parseErrorInHeritageClause1.ts(1,19): error TS1127: Invalid ==== tests/cases/compiler/parseErrorInHeritageClause1.ts (2 errors) ==== - class C extends A # { + class C extends A ¬ { ~ !!! error TS2304: Cannot find name 'A'. !!! error TS1127: Invalid character. - } \ No newline at end of file + } + \ No newline at end of file diff --git a/tests/baselines/reference/parseErrorInHeritageClause1.js b/tests/baselines/reference/parseErrorInHeritageClause1.js index da02ae9cf2547..8d67383860af2 100644 --- a/tests/baselines/reference/parseErrorInHeritageClause1.js +++ b/tests/baselines/reference/parseErrorInHeritageClause1.js @@ -1,6 +1,7 @@ //// [parseErrorInHeritageClause1.ts] -class C extends A # { -} +class C extends A ¬ { +} + //// [parseErrorInHeritageClause1.js] var __extends = (this && this.__extends) || (function () { diff --git a/tests/baselines/reference/parseErrorInHeritageClause1.symbols b/tests/baselines/reference/parseErrorInHeritageClause1.symbols index 5e0d3d26d38da..45d6ba5f5fac3 100644 --- a/tests/baselines/reference/parseErrorInHeritageClause1.symbols +++ b/tests/baselines/reference/parseErrorInHeritageClause1.symbols @@ -1,4 +1,5 @@ === tests/cases/compiler/parseErrorInHeritageClause1.ts === -class C extends A # { +class C extends A ¬ { >C : Symbol(C, Decl(parseErrorInHeritageClause1.ts, 0, 0)) } + diff --git a/tests/baselines/reference/parseErrorInHeritageClause1.types b/tests/baselines/reference/parseErrorInHeritageClause1.types index 53f0a622054d3..0a8c72e1f8c92 100644 --- a/tests/baselines/reference/parseErrorInHeritageClause1.types +++ b/tests/baselines/reference/parseErrorInHeritageClause1.types @@ -1,5 +1,6 @@ === tests/cases/compiler/parseErrorInHeritageClause1.ts === -class C extends A # { +class C extends A ¬ { >C : C >A : any } + diff --git a/tests/baselines/reference/parserErrorRecovery_Block2.errors.txt b/tests/baselines/reference/parserErrorRecovery_Block2.errors.txt index 53279be443f66..ff29d9389760b 100644 --- a/tests/baselines/reference/parserErrorRecovery_Block2.errors.txt +++ b/tests/baselines/reference/parserErrorRecovery_Block2.errors.txt @@ -3,8 +3,9 @@ tests/cases/conformance/parser/ecmascript5/ErrorRecovery/Blocks/parserErrorRecov ==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/Blocks/parserErrorRecovery_Block2.ts (1 errors) ==== function f() { - # + ¬ !!! error TS1127: Invalid character. return; - } \ No newline at end of file + } + \ No newline at end of file diff --git a/tests/baselines/reference/parserErrorRecovery_Block2.js b/tests/baselines/reference/parserErrorRecovery_Block2.js index 24ddaf0db3f2a..024684a9e2b03 100644 --- a/tests/baselines/reference/parserErrorRecovery_Block2.js +++ b/tests/baselines/reference/parserErrorRecovery_Block2.js @@ -1,8 +1,9 @@ //// [parserErrorRecovery_Block2.ts] function f() { - # + ¬ return; -} +} + //// [parserErrorRecovery_Block2.js] function f() { diff --git a/tests/baselines/reference/parserErrorRecovery_Block2.symbols b/tests/baselines/reference/parserErrorRecovery_Block2.symbols index 3d5a09d567ce6..ce4725e609a64 100644 --- a/tests/baselines/reference/parserErrorRecovery_Block2.symbols +++ b/tests/baselines/reference/parserErrorRecovery_Block2.symbols @@ -2,6 +2,7 @@ function f() { >f : Symbol(f, Decl(parserErrorRecovery_Block2.ts, 0, 0)) - # + ¬ return; } + diff --git a/tests/baselines/reference/parserErrorRecovery_Block2.types b/tests/baselines/reference/parserErrorRecovery_Block2.types index 9850dc1cf0ea2..0a0a0fbec23c8 100644 --- a/tests/baselines/reference/parserErrorRecovery_Block2.types +++ b/tests/baselines/reference/parserErrorRecovery_Block2.types @@ -2,6 +2,7 @@ function f() { >f : () => void - # + ¬ return; } + diff --git a/tests/baselines/reference/parserErrorRecovery_ClassElement3.errors.txt b/tests/baselines/reference/parserErrorRecovery_ClassElement3.errors.txt index 7f81c6114f6d2..52f99265d2c51 100644 --- a/tests/baselines/reference/parserErrorRecovery_ClassElement3.errors.txt +++ b/tests/baselines/reference/parserErrorRecovery_ClassElement3.errors.txt @@ -1,12 +1,12 @@ tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ClassElements/parserErrorRecovery_ClassElement3.ts(2,4): error TS1127: Invalid character. tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ClassElements/parserErrorRecovery_ClassElement3.ts(6,4): error TS1109: Expression expected. tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ClassElements/parserErrorRecovery_ClassElement3.ts(7,4): error TS1127: Invalid character. -tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ClassElements/parserErrorRecovery_ClassElement3.ts(7,5): error TS1005: '}' expected. +tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ClassElements/parserErrorRecovery_ClassElement3.ts(8,1): error TS1005: '}' expected. ==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ClassElements/parserErrorRecovery_ClassElement3.ts (4 errors) ==== module M { - # + ¬ !!! error TS1127: Invalid character. class C { @@ -15,8 +15,9 @@ tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ClassElements/parserErr enum E { ~~~~ !!! error TS1109: Expression expected. - # + ¬ !!! error TS1127: Invalid character. - + + !!! error TS1005: '}' expected. \ No newline at end of file diff --git a/tests/baselines/reference/parserErrorRecovery_ClassElement3.js b/tests/baselines/reference/parserErrorRecovery_ClassElement3.js index 36d98fa54003e..ef9afde66f7f0 100644 --- a/tests/baselines/reference/parserErrorRecovery_ClassElement3.js +++ b/tests/baselines/reference/parserErrorRecovery_ClassElement3.js @@ -1,11 +1,12 @@ //// [parserErrorRecovery_ClassElement3.ts] module M { - # + ¬ class C { } @ enum E { - # + ¬ + //// [parserErrorRecovery_ClassElement3.js] var M; diff --git a/tests/baselines/reference/parserErrorRecovery_ClassElement3.symbols b/tests/baselines/reference/parserErrorRecovery_ClassElement3.symbols index 5c1edc5b8f09f..5ea7444c974c9 100644 --- a/tests/baselines/reference/parserErrorRecovery_ClassElement3.symbols +++ b/tests/baselines/reference/parserErrorRecovery_ClassElement3.symbols @@ -2,7 +2,7 @@ module M { >M : Symbol(M, Decl(parserErrorRecovery_ClassElement3.ts, 0, 0)) - # + ¬ class C { >C : Symbol(C, Decl(parserErrorRecovery_ClassElement3.ts, 1, 4)) } @@ -10,4 +10,5 @@ module M { enum E { >E : Symbol(E, Decl(parserErrorRecovery_ClassElement3.ts, 3, 4)) - # + ¬ + diff --git a/tests/baselines/reference/parserErrorRecovery_ClassElement3.types b/tests/baselines/reference/parserErrorRecovery_ClassElement3.types index 68df4b2bbe22b..f509a0d4fb574 100644 --- a/tests/baselines/reference/parserErrorRecovery_ClassElement3.types +++ b/tests/baselines/reference/parserErrorRecovery_ClassElement3.types @@ -2,7 +2,7 @@ module M { >M : typeof M - # + ¬ class C { >C : C } @@ -11,4 +11,5 @@ module M { > : any >E : E - # + ¬ + diff --git a/tests/baselines/reference/parserErrorRecovery_ParameterList4.errors.txt b/tests/baselines/reference/parserErrorRecovery_ParameterList4.errors.txt index fa97550dd192f..9e404df184199 100644 --- a/tests/baselines/reference/parserErrorRecovery_ParameterList4.errors.txt +++ b/tests/baselines/reference/parserErrorRecovery_ParameterList4.errors.txt @@ -2,7 +2,8 @@ tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ParameterLists/parserEr ==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ParameterLists/parserErrorRecovery_ParameterList4.ts (1 errors) ==== - function f(a,#) { + function f(a,¬) { !!! error TS1127: Invalid character. - } \ No newline at end of file + } + \ No newline at end of file diff --git a/tests/baselines/reference/parserErrorRecovery_ParameterList4.js b/tests/baselines/reference/parserErrorRecovery_ParameterList4.js index 53775cad92ea3..1a1a124eb493d 100644 --- a/tests/baselines/reference/parserErrorRecovery_ParameterList4.js +++ b/tests/baselines/reference/parserErrorRecovery_ParameterList4.js @@ -1,6 +1,7 @@ //// [parserErrorRecovery_ParameterList4.ts] -function f(a,#) { -} +function f(a,¬) { +} + //// [parserErrorRecovery_ParameterList4.js] function f(a) { diff --git a/tests/baselines/reference/parserErrorRecovery_ParameterList4.symbols b/tests/baselines/reference/parserErrorRecovery_ParameterList4.symbols index df48ebfe04dec..7c433c8c3b461 100644 --- a/tests/baselines/reference/parserErrorRecovery_ParameterList4.symbols +++ b/tests/baselines/reference/parserErrorRecovery_ParameterList4.symbols @@ -1,5 +1,6 @@ === tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ParameterLists/parserErrorRecovery_ParameterList4.ts === -function f(a,#) { +function f(a,¬) { >f : Symbol(f, Decl(parserErrorRecovery_ParameterList4.ts, 0, 0)) >a : Symbol(a, Decl(parserErrorRecovery_ParameterList4.ts, 0, 11)) } + diff --git a/tests/baselines/reference/parserErrorRecovery_ParameterList4.types b/tests/baselines/reference/parserErrorRecovery_ParameterList4.types index 77b105f1d4cef..093d99193d21f 100644 --- a/tests/baselines/reference/parserErrorRecovery_ParameterList4.types +++ b/tests/baselines/reference/parserErrorRecovery_ParameterList4.types @@ -1,5 +1,6 @@ === tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ParameterLists/parserErrorRecovery_ParameterList4.ts === -function f(a,#) { +function f(a,¬) { >f : (a: any) => void >a : any } + diff --git a/tests/baselines/reference/parserSkippedTokens16.errors.txt b/tests/baselines/reference/parserSkippedTokens16.errors.txt index c35e013a22852..d27faccd2c9e7 100644 --- a/tests/baselines/reference/parserSkippedTokens16.errors.txt +++ b/tests/baselines/reference/parserSkippedTokens16.errors.txt @@ -19,7 +19,7 @@ tests/cases/conformance/parser/ecmascript5/SkippedTokens/parserSkippedTokens16.t !!! error TS2304: Cannot find name 'Bar'. ~ !!! error TS1005: ';' expected. - function Foo () # { } + function Foo () ¬ { } !!! error TS1127: Invalid character. 4+:5 @@ -33,4 +33,5 @@ tests/cases/conformance/parser/ecmascript5/SkippedTokens/parserSkippedTokens16.t } var x = -!!! error TS1109: Expression expected. \ No newline at end of file +!!! error TS1109: Expression expected. + \ No newline at end of file diff --git a/tests/baselines/reference/parserSkippedTokens16.js b/tests/baselines/reference/parserSkippedTokens16.js index 2c3a9be876df5..cf5b8c55ecc8a 100644 --- a/tests/baselines/reference/parserSkippedTokens16.js +++ b/tests/baselines/reference/parserSkippedTokens16.js @@ -1,12 +1,13 @@ //// [parserSkippedTokens16.ts] foo(): Bar { } -function Foo () # { } +function Foo () ¬ { } 4+:5 module M { function a( : T) { } } -var x = +var x = + //// [parserSkippedTokens16.js] foo(); diff --git a/tests/baselines/reference/parserSkippedTokens16.symbols b/tests/baselines/reference/parserSkippedTokens16.symbols index 213dc9965f98f..576a1dfd97d8d 100644 --- a/tests/baselines/reference/parserSkippedTokens16.symbols +++ b/tests/baselines/reference/parserSkippedTokens16.symbols @@ -1,6 +1,6 @@ === tests/cases/conformance/parser/ecmascript5/SkippedTokens/parserSkippedTokens16.ts === foo(): Bar { } -function Foo () # { } +function Foo () ¬ { } >Foo : Symbol(Foo, Decl(parserSkippedTokens16.ts, 0, 14)) 4+:5 diff --git a/tests/baselines/reference/parserSkippedTokens16.types b/tests/baselines/reference/parserSkippedTokens16.types index b9c24cfafbaf0..cb62505802fe9 100644 --- a/tests/baselines/reference/parserSkippedTokens16.types +++ b/tests/baselines/reference/parserSkippedTokens16.types @@ -4,7 +4,7 @@ foo(): Bar { } >foo : any >Bar : any -function Foo () # { } +function Foo () ¬ { } >Foo : () => any 4+:5 @@ -24,5 +24,6 @@ function a( } var x = >x : any + > : any diff --git a/tests/baselines/reference/privateNameAndIndexSignature.errors.txt b/tests/baselines/reference/privateNameAndIndexSignature.errors.txt new file mode 100644 index 0000000000000..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..f432be2b3d336 --- /dev/null +++ b/tests/baselines/reference/privateNameField.js @@ -0,0 +1,15 @@ +//// [privateNameField.ts] +class A { + #name: string; + constructor(name: string) { + this.#name = name; + } +} + +//// [privateNameField.js] +var A = /** @class */ (function () { + function A(name) { + this.#name = name; + } + return A; +}()); 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/shebangError.errors.txt b/tests/baselines/reference/shebangError.errors.txt index cba74ceaed75e..ecfc0ac5eab6e 100644 --- a/tests/baselines/reference/shebangError.errors.txt +++ b/tests/baselines/reference/shebangError.errors.txt @@ -1,14 +1,17 @@ -tests/cases/compiler/shebangError.ts(2,1): error TS1127: Invalid character. +tests/cases/compiler/shebangError.ts(2,1): error TS1128: Declaration or statement expected. +tests/cases/compiler/shebangError.ts(2,2): error TS1127: Invalid character. tests/cases/compiler/shebangError.ts(2,2): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type. tests/cases/compiler/shebangError.ts(2,12): error TS2304: Cannot find name 'env'. tests/cases/compiler/shebangError.ts(2,16): error TS1005: ';' expected. tests/cases/compiler/shebangError.ts(2,16): error TS2304: Cannot find name 'node'. -==== tests/cases/compiler/shebangError.ts (5 errors) ==== +==== tests/cases/compiler/shebangError.ts (6 errors) ==== var foo = 'Shebang is only allowed on the first line'; #!/usr/bin/env node - + ~ +!!! error TS1128: Declaration or statement expected. + !!! error TS1127: Invalid character. ~~~~~~~~~ !!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type. diff --git a/tests/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/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 From 159d511fe29651bdc60da2f5b2e4f73b2b1493f4 Mon Sep 17 00:00:00 2001 From: Joseph Watts Date: Tue, 9 Oct 2018 13:20:01 -0400 Subject: [PATCH 3/6] Fix display of private names in language server Signed-off-by: Joseph Watts --- src/compiler/checker.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3825372085213..da6d52254dd9d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4364,7 +4364,10 @@ namespace ts { context.flags ^= NodeBuilderFlags.InInitialEntityName; } let firstChar = symbolName.charCodeAt(0); - const canUsePropertyAccess = isIdentifierStart(firstChar, languageVersion); + const canUsePropertyAccess = firstChar === CharacterCodes.hash ? + symbolName.length > 1 && isIdentifierStart(symbolName.charCodeAt(1), languageVersion) : + isIdentifierStart(firstChar, languageVersion); + if (index === 0 || canUsePropertyAccess) { const identifier = setEmitFlags(createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); identifier.symbol = symbol; From 2902c73ee2f09e9f4be078726caad73adc53f752 Mon Sep 17 00:00:00 2001 From: Joseph Watts Date: Tue, 9 Oct 2018 14:16:34 -0400 Subject: [PATCH 4/6] Accept baseline changes Signed-off-by: Joseph Watts --- tests/baselines/reference/privateNameField.symbols | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/privateNameField.symbols b/tests/baselines/reference/privateNameField.symbols index a9ab08325a0e1..cbaedbc596caf 100644 --- a/tests/baselines/reference/privateNameField.symbols +++ b/tests/baselines/reference/privateNameField.symbols @@ -3,13 +3,13 @@ class A { >A : Symbol(A, Decl(privateNameField.ts, 0, 0)) #name: string; ->#name : Symbol(A[#name], Decl(privateNameField.ts, 0, 9)) +>#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.#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)) } From 72978c8166f859d34d3d4865028f292632255b5c Mon Sep 17 00:00:00 2001 From: Max Heiber Date: Mon, 28 Jan 2019 15:23:47 -0500 Subject: [PATCH 5/6] Private Name Support in the Checker (#5) - [x] treat private names as unique: - case 1: cannot say that a variable is of a class type unless the variable points to an instance of the class - see [test](https://github.com/mheiber/TypeScript/tree/checker/tests/cases/conformance/classes/members/privateNames/privateNamesUnique.ts) - case 2: private names in class hierarchies do not conflict - see [test](https://github.com/mheiber/TypeScript/tree/checker/tests/cases/conformance/classes/members/privateNames/privateNamesNoConflictWhenInheriting.ts) - [x] `#constructor` is reserved - see [test](https://github.com/mheiber/TypeScript/tree/checker/tests/cases/conformance/classes/members/privateNames/privateNameConstructorReserved.ts) - check in `bindWorker`, where every node is visited - [x] Accessibility modifiers can't be used with private names - see [test](https://github.com/mheiber/TypeScript/tree/checker/tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts) - implemented in `checkAccessibilityModifiers`, using `ModifierFlags.AccessibilityModifier` - [x] `delete #foo` not allowed - [x] Private name accesses not allowed outside of the defining class - see test: https://github.com/mheiber/TypeScript/tree/checker/tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts - see [test](https://github.com/mheiber/TypeScript/tree/checker/tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts) - implemented in `checkDeleteExpression` - [x] Do [the right thing](https://gist.github.com/mheiber/b6fc7adb426c2e1cdaceb5d7786fc630) for nested classes mv private name tests together more checker tests for private names update naming and cleanup for check private names for private name support in the checker: - make names more consistent - remove unnecessary checks - add utility function to public API - other small cleanup Move getPropertyNameForUniqueESSymbol to utility for consistency with other calculation of special property names (starting with __), move the calculation of property names for unique es symbols to `utilities.ts`. private name tests strict+es6 Update private name tests to use 'strict' type checking and to target es6 instead of default. Makes the js output easier to read and tests more surface area with other checker features. error message for private names in obj literals Disallow decorating private-named properties because the spec is still in flux. Signed-off-by: Max Heiber --- src/compiler/binder.ts | 34 ++++- src/compiler/checker.ts | 131 ++++++++++++++---- src/compiler/diagnosticMessages.json | 24 +++- src/compiler/types.ts | 1 + src/compiler/utilities.ts | 12 ++ .../reference/api/tsserverlibrary.d.ts | 1 + tests/baselines/reference/api/typescript.d.ts | 1 + ...ionMapsGeneratedMapsEnableMapping.baseline | 34 +++++ ...onMapsGeneratedMapsEnableMapping2.baseline | 35 +++++ ...onMapsGeneratedMapsEnableMapping3.baseline | 34 +++++ ...neratedMapsEnableMapping_NoInline.baseline | 34 +++++ ...MapsEnableMapping_NoInlineSources.baseline | 34 +++++ .../privateNameAndIndexSignature.errors.txt | 4 +- .../reference/privateNameAndIndexSignature.js | 4 + .../privateNameAndIndexSignature.symbols | 6 +- .../privateNameAndIndexSignature.types | 2 + .../privateNameConstructorReserved.errors.txt | 12 ++ .../privateNameConstructorReserved.js | 16 +++ .../privateNameConstructorReserved.symbols | 10 ++ .../privateNameConstructorReserved.types | 10 ++ .../privateNameDuplicateField.errors.txt | 13 ++ .../reference/privateNameDuplicateField.js | 19 +++ .../privateNameDuplicateField.symbols | 13 ++ .../reference/privateNameDuplicateField.types | 15 ++ tests/baselines/reference/privateNameField.js | 4 + .../reference/privateNameField.symbols | 10 +- .../reference/privateNameField.types | 2 + .../privateNameInObjectLiteral-1.errors.txt | 10 ++ .../reference/privateNameInObjectLiteral-1.js | 10 ++ .../privateNameInObjectLiteral-1.symbols | 9 ++ .../privateNameInObjectLiteral-1.types | 11 ++ .../privateNameInObjectLiteral-2.errors.txt | 12 ++ .../reference/privateNameInObjectLiteral-2.js | 13 ++ .../privateNameInObjectLiteral-2.symbols | 10 ++ .../privateNameInObjectLiteral-2.types | 11 ++ .../privateNameInObjectLiteral.errors.txt | 14 ++ .../reference/privateNameInObjectLiteral.js | 18 +++ .../privateNameInObjectLiteral.symbols | 17 +++ .../privateNameInObjectLiteral.types | 22 +++ ...tAccessibleOutsideDefiningClass.errors.txt | 17 +++ ...teNameNotAccessibleOutsideDefiningClass.js | 20 +++ ...eNotAccessibleOutsideDefiningClass.symbols | 13 ++ ...ameNotAccessibleOutsideDefiningClass.types | 18 +++ ...ivateNameNotAllowedOutsideClass.errors.txt | 15 ++ .../privateNameNotAllowedOutsideClass.js | 10 ++ .../privateNameNotAllowedOutsideClass.symbols | 5 + .../privateNameNotAllowedOutsideClass.types | 6 + .../privateNameSneakyRuntimeException.js | 35 +++++ .../privateNameSneakyRuntimeException.symbols | 39 ++++++ .../privateNameSneakyRuntimeException.types | 52 +++++++ .../privateNamesAndDecorators.errors.txt | 18 +++ .../reference/privateNamesAndDecorators.js | 19 +++ .../privateNamesAndDecorators.symbols | 24 ++++ .../reference/privateNamesAndDecorators.types | 22 +++ .../reference/privateNamesAndFields.js | 50 +++++++ .../reference/privateNamesAndFields.symbols | 33 +++++ .../reference/privateNamesAndFields.types | 38 +++++ ...privateNamesAndGenericClasses-2.errors.txt | 46 ++++++ .../privateNamesAndGenericClasses-2.js | 53 +++++++ .../privateNamesAndGenericClasses-2.symbols | 82 +++++++++++ .../privateNamesAndGenericClasses-2.types | 89 ++++++++++++ .../privateNamesAndIndexedAccess.errors.txt | 39 ++++++ .../reference/privateNamesAndIndexedAccess.js | 27 ++++ .../privateNamesAndIndexedAccess.symbols | 29 ++++ .../privateNamesAndIndexedAccess.types | 30 ++++ .../reference/privateNamesAndMethods.js | 60 ++++++++ .../reference/privateNamesAndMethods.symbols | 80 +++++++++++ .../reference/privateNamesAndMethods.types | 95 +++++++++++++ .../reference/privateNamesAndStaticFields.js | 50 +++++++ .../privateNamesAndStaticFields.symbols | 33 +++++ .../privateNamesAndStaticFields.types | 38 +++++ .../reference/privateNamesAndStaticMethods.js | 61 ++++++++ .../privateNamesAndStaticMethods.symbols | 80 +++++++++++ .../privateNamesAndStaticMethods.types | 95 +++++++++++++ .../reference/privateNamesAndkeyof.js | 23 +++ .../reference/privateNamesAndkeyof.symbols | 20 +++ .../reference/privateNamesAndkeyof.types | 22 +++ .../privateNamesInGenericClasses.errors.txt | 32 +++++ .../reference/privateNamesInGenericClasses.js | 25 ++++ .../privateNamesInGenericClasses.symbols | 51 +++++++ .../privateNamesInGenericClasses.types | 46 ++++++ .../privateNamesInNestedClasses.errors.txt | 36 +++++ .../reference/privateNamesInNestedClasses.js | 62 +++++++++ .../privateNamesInNestedClasses.symbols | 79 +++++++++++ .../privateNamesInNestedClasses.types | 92 ++++++++++++ ...teNamesNoAccessibilityModifiers.errors.txt | 21 +++ .../privateNamesNoAccessibilityModifiers.js | 23 +++ ...ivateNamesNoAccessibilityModifiers.symbols | 19 +++ ...privateNamesNoAccessibilityModifiers.types | 23 +++ .../privateNamesNoConflictWhenInheriting.js | 43 ++++++ ...ivateNamesNoConflictWhenInheriting.symbols | 23 +++ ...privateNamesNoConflictWhenInheriting.types | 23 +++ .../reference/privateNamesNoDelete.errors.txt | 15 ++ .../reference/privateNamesNoDelete.js | 21 +++ .../reference/privateNamesNoDelete.symbols | 16 +++ .../reference/privateNamesNoDelete.types | 18 +++ ...vateNamesNotAllowedAsParameters.errors.txt | 21 +++ .../privateNamesNotAllowedAsParameters.js | 17 +++ ...privateNamesNotAllowedAsParameters.symbols | 11 ++ .../privateNamesNotAllowedAsParameters.types | 11 ++ ...otAllowedInVariableDeclarations.errors.txt | 15 ++ ...teNamesNotAllowedInVariableDeclarations.js | 10 ++ ...esNotAllowedInVariableDeclarations.symbols | 5 + ...amesNotAllowedInVariableDeclarations.types | 6 + .../reference/privateNamesUnique.errors.txt | 20 +++ .../baselines/reference/privateNamesUnique.js | 28 ++++ .../reference/privateNamesUnique.symbols | 22 +++ .../reference/privateNamesUnique.types | 22 +++ .../privateNameAndIndexSignature.ts | 15 +- .../privateNameConstructorReserved.ts | 5 + .../privateNames/privateNameDuplicateField.ts | 7 + .../members/privateNames/privateNameField.ts | 13 +- .../privateNameInObjectLiteral-1.ts | 3 + .../privateNameInObjectLiteral-2.ts | 5 + ...teNameNotAccessibleOutsideDefiningClass.ts | 8 ++ .../privateNameNotAllowedOutsideClass.ts | 4 + .../privateNameSneakyRuntimeException.ts | 16 +++ .../privateNames/privateNamesAndDecorators.ts | 8 ++ .../privateNames/privateNamesAndFields.ts | 17 +++ .../privateNamesAndGenericClasses-2.ts | 29 ++++ .../privateNamesAndIndexedAccess.ts | 14 ++ .../privateNames/privateNamesAndMethods.ts | 32 +++++ .../privateNamesAndStaticFields.ts | 17 +++ .../privateNamesAndStaticMethods.ts | 33 +++++ .../privateNames/privateNamesAndkeyof.ts | 10 ++ .../privateNamesInGenericClasses.ts | 15 ++ .../privateNamesInNestedClasses.ts | 28 ++++ .../privateNamesNoAccessibilityModifiers.ts | 9 ++ .../privateNamesNoConflictWhenInheriting.ts | 12 ++ .../privateNames/privateNamesNoDelete.ts | 9 ++ .../privateNamesNotAllowedAsParameters.ts | 5 + ...teNamesNotAllowedInVariableDeclarations.ts | 4 + .../privateNames/privateNamesUnique.ts | 12 ++ 133 files changed, 3287 insertions(+), 57 deletions(-) create mode 100644 tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping.baseline create mode 100644 tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping2.baseline create mode 100644 tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping3.baseline create mode 100644 tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping_NoInline.baseline create mode 100644 tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping_NoInlineSources.baseline create mode 100644 tests/baselines/reference/privateNameConstructorReserved.errors.txt create mode 100644 tests/baselines/reference/privateNameConstructorReserved.js create mode 100644 tests/baselines/reference/privateNameConstructorReserved.symbols create mode 100644 tests/baselines/reference/privateNameConstructorReserved.types create mode 100644 tests/baselines/reference/privateNameDuplicateField.errors.txt create mode 100644 tests/baselines/reference/privateNameDuplicateField.js create mode 100644 tests/baselines/reference/privateNameDuplicateField.symbols create mode 100644 tests/baselines/reference/privateNameDuplicateField.types create mode 100644 tests/baselines/reference/privateNameInObjectLiteral-1.errors.txt create mode 100644 tests/baselines/reference/privateNameInObjectLiteral-1.js create mode 100644 tests/baselines/reference/privateNameInObjectLiteral-1.symbols create mode 100644 tests/baselines/reference/privateNameInObjectLiteral-1.types create mode 100644 tests/baselines/reference/privateNameInObjectLiteral-2.errors.txt create mode 100644 tests/baselines/reference/privateNameInObjectLiteral-2.js create mode 100644 tests/baselines/reference/privateNameInObjectLiteral-2.symbols create mode 100644 tests/baselines/reference/privateNameInObjectLiteral-2.types create mode 100644 tests/baselines/reference/privateNameInObjectLiteral.errors.txt create mode 100644 tests/baselines/reference/privateNameInObjectLiteral.js create mode 100644 tests/baselines/reference/privateNameInObjectLiteral.symbols create mode 100644 tests/baselines/reference/privateNameInObjectLiteral.types create mode 100644 tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.errors.txt create mode 100644 tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.js create mode 100644 tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.symbols create mode 100644 tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.types create mode 100644 tests/baselines/reference/privateNameNotAllowedOutsideClass.errors.txt create mode 100644 tests/baselines/reference/privateNameNotAllowedOutsideClass.js create mode 100644 tests/baselines/reference/privateNameNotAllowedOutsideClass.symbols create mode 100644 tests/baselines/reference/privateNameNotAllowedOutsideClass.types create mode 100644 tests/baselines/reference/privateNameSneakyRuntimeException.js create mode 100644 tests/baselines/reference/privateNameSneakyRuntimeException.symbols create mode 100644 tests/baselines/reference/privateNameSneakyRuntimeException.types create mode 100644 tests/baselines/reference/privateNamesAndDecorators.errors.txt create mode 100644 tests/baselines/reference/privateNamesAndDecorators.js create mode 100644 tests/baselines/reference/privateNamesAndDecorators.symbols create mode 100644 tests/baselines/reference/privateNamesAndDecorators.types create mode 100644 tests/baselines/reference/privateNamesAndFields.js create mode 100644 tests/baselines/reference/privateNamesAndFields.symbols create mode 100644 tests/baselines/reference/privateNamesAndFields.types create mode 100644 tests/baselines/reference/privateNamesAndGenericClasses-2.errors.txt create mode 100644 tests/baselines/reference/privateNamesAndGenericClasses-2.js create mode 100644 tests/baselines/reference/privateNamesAndGenericClasses-2.symbols create mode 100644 tests/baselines/reference/privateNamesAndGenericClasses-2.types create mode 100644 tests/baselines/reference/privateNamesAndIndexedAccess.errors.txt create mode 100644 tests/baselines/reference/privateNamesAndIndexedAccess.js create mode 100644 tests/baselines/reference/privateNamesAndIndexedAccess.symbols create mode 100644 tests/baselines/reference/privateNamesAndIndexedAccess.types create mode 100644 tests/baselines/reference/privateNamesAndMethods.js create mode 100644 tests/baselines/reference/privateNamesAndMethods.symbols create mode 100644 tests/baselines/reference/privateNamesAndMethods.types create mode 100644 tests/baselines/reference/privateNamesAndStaticFields.js create mode 100644 tests/baselines/reference/privateNamesAndStaticFields.symbols create mode 100644 tests/baselines/reference/privateNamesAndStaticFields.types create mode 100644 tests/baselines/reference/privateNamesAndStaticMethods.js create mode 100644 tests/baselines/reference/privateNamesAndStaticMethods.symbols create mode 100644 tests/baselines/reference/privateNamesAndStaticMethods.types create mode 100644 tests/baselines/reference/privateNamesAndkeyof.js create mode 100644 tests/baselines/reference/privateNamesAndkeyof.symbols create mode 100644 tests/baselines/reference/privateNamesAndkeyof.types create mode 100644 tests/baselines/reference/privateNamesInGenericClasses.errors.txt create mode 100644 tests/baselines/reference/privateNamesInGenericClasses.js create mode 100644 tests/baselines/reference/privateNamesInGenericClasses.symbols create mode 100644 tests/baselines/reference/privateNamesInGenericClasses.types create mode 100644 tests/baselines/reference/privateNamesInNestedClasses.errors.txt create mode 100644 tests/baselines/reference/privateNamesInNestedClasses.js create mode 100644 tests/baselines/reference/privateNamesInNestedClasses.symbols create mode 100644 tests/baselines/reference/privateNamesInNestedClasses.types create mode 100644 tests/baselines/reference/privateNamesNoAccessibilityModifiers.errors.txt create mode 100644 tests/baselines/reference/privateNamesNoAccessibilityModifiers.js create mode 100644 tests/baselines/reference/privateNamesNoAccessibilityModifiers.symbols create mode 100644 tests/baselines/reference/privateNamesNoAccessibilityModifiers.types create mode 100644 tests/baselines/reference/privateNamesNoConflictWhenInheriting.js create mode 100644 tests/baselines/reference/privateNamesNoConflictWhenInheriting.symbols create mode 100644 tests/baselines/reference/privateNamesNoConflictWhenInheriting.types create mode 100644 tests/baselines/reference/privateNamesNoDelete.errors.txt create mode 100644 tests/baselines/reference/privateNamesNoDelete.js create mode 100644 tests/baselines/reference/privateNamesNoDelete.symbols create mode 100644 tests/baselines/reference/privateNamesNoDelete.types create mode 100644 tests/baselines/reference/privateNamesNotAllowedAsParameters.errors.txt create mode 100644 tests/baselines/reference/privateNamesNotAllowedAsParameters.js create mode 100644 tests/baselines/reference/privateNamesNotAllowedAsParameters.symbols create mode 100644 tests/baselines/reference/privateNamesNotAllowedAsParameters.types create mode 100644 tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.errors.txt create mode 100644 tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.js create mode 100644 tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.symbols create mode 100644 tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.types create mode 100644 tests/baselines/reference/privateNamesUnique.errors.txt create mode 100644 tests/baselines/reference/privateNamesUnique.js create mode 100644 tests/baselines/reference/privateNamesUnique.symbols create mode 100644 tests/baselines/reference/privateNamesUnique.types create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameConstructorReserved.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameDuplicateField.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-1.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-2.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameSneakyRuntimeException.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNamesAndDecorators.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNamesAndFields.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNamesAndMethods.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticFields.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticMethods.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNamesAndkeyof.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNamesInNestedClasses.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNamesNoConflictWhenInheriting.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNamesUnique.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 8154ea52e6f42..d9e1778d4dd98 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -278,8 +278,15 @@ namespace ts { Debug.assert(isWellKnownSymbolSyntactically(nameExpression)); return getPropertyNameForKnownSymbolName(idText((nameExpression).name)); } - if (isPrivateName(node)) { - return nodePosToString(node) as __String; + if (isPrivateName(name)) { + // containingClass exists because private names only allowed inside classes + const containingClass = getContainingClass(name.parent); + if (!containingClass) { + // we're in a case where there's a private name outside a class (invalid) + return undefined; + } + const containingClassSymbol = containingClass.symbol; + return getPropertyNameForPrivateNameDescription(containingClassSymbol, name.escapedText); } return isPropertyNameLiteral(name) ? getEscapedTextOfIdentifierOrLiteral(name) : undefined; } @@ -337,6 +344,10 @@ namespace ts { const isDefaultExport = hasModifier(node, ModifierFlags.Default); + // need this before getDeclarationName + if (isNamedDeclaration(node)) { + node.name.parent = node; + } // The exported symbol for an export default function/class node is always named "default" const name = isDefaultExport && parent ? InternalSymbolName.Default : getDeclarationName(node); @@ -389,11 +400,6 @@ namespace ts { symbolTable.set(name, symbol = createSymbol(SymbolFlags.None, name)); } else if (!(includes & SymbolFlags.Variable && symbol.flags & SymbolFlags.Assignment)) { - // Assignment declarations are allowed to merge with variables, no matter what other flags they have. - if (isNamedDeclaration(node)) { - node.name.parent = node; - } - // Report errors every position with duplicate declaration // Report errors on previous encountered declarations let message = symbol.flags & SymbolFlags.BlockScopedVariable @@ -1858,6 +1864,18 @@ namespace ts { return Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode; } + // The binder visits every node, so this is a good place to check for + // the reserved private name (there is only one) + function checkPrivateName(node: PrivateName) { + if (node.escapedText === "#constructor") { + // Report error only if there are no parse errors in file + if (!file.parseDiagnostics.length) { + file.bindDiagnostics.push(createDiagnosticForNode(node, + Diagnostics.constructor_is_a_reserved_word, declarationNameToString(node))); + } + } + } + function checkStrictModeBinaryExpression(node: BinaryExpression) { if (inStrictMode && isLeftHandSideExpression(node.left) && isAssignmentOperator(node.operatorToken.kind)) { // ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an @@ -2130,6 +2148,8 @@ namespace ts { node.flowNode = currentFlow; } return checkStrictModeIdentifier(node); + case SyntaxKind.PrivateName: + return checkPrivateName(node as PrivateName); case SyntaxKind.PropertyAccessExpression: case SyntaxKind.ElementAccessExpression: if (currentFlow && isNarrowableReference(node)) { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index da6d52254dd9d..40516ff789958 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -132,6 +132,7 @@ namespace ts { getDeclaredTypeOfSymbol, getPropertiesOfType, getPropertyOfType: (type, name) => getPropertyOfType(type, escapeLeadingUnderscores(name)), + getPropertyForPrivateName, getTypeOfPropertyOfType: (type, name) => getTypeOfPropertyOfType(type, escapeLeadingUnderscores(name)), getIndexInfoOfType, getSignaturesOfType, @@ -1605,8 +1606,8 @@ namespace ts { } } - function diagnosticName(nameArg: __String | Identifier) { - return isString(nameArg) ? unescapeLeadingUnderscores(nameArg as __String) : declarationNameToString(nameArg as Identifier); + function diagnosticName(nameArg: __String | Identifier | PrivateName) { + return isString(nameArg) ? unescapeLeadingUnderscores(nameArg as __String) : declarationNameToString(nameArg as Identifier | PrivateName); } function isTypeParameterSymbolDeclaredInContainer(symbol: Symbol, container: Node) { @@ -2795,15 +2796,16 @@ namespace ts { return type; } - // A reserved member name starts with two underscores, but the third character cannot be an underscore - // or the @ symbol. A third underscore indicates an escaped form of an identifer that started + // A reserved member name starts with two underscores, but the third character cannot be an underscore, + // @, or #. A third underscore indicates an escaped form of an identifer that started // with at least two underscores. The @ character indicates that the name is denoted by a well known ES - // Symbol instance. + // Symbol instance and the # indicates that the name is a PrivateName. function isReservedMemberName(name: __String) { return (name as string).charCodeAt(0) === CharacterCodes._ && (name as string).charCodeAt(1) === CharacterCodes._ && (name as string).charCodeAt(2) !== CharacterCodes._ && - (name as string).charCodeAt(2) !== CharacterCodes.at; + (name as string).charCodeAt(2) !== CharacterCodes.at && + (name as string).charCodeAt(2) !== CharacterCodes.hash; } function getNamedMembers(members: SymbolTable): Symbol[] { @@ -6510,7 +6512,7 @@ namespace ts { */ function getPropertyNameFromType(type: StringLiteralType | NumberLiteralType | UniqueESSymbolType): __String { if (type.flags & TypeFlags.UniqueESSymbol) { - return (type).escapedName; + return getPropertyNameForUniqueESSymbol(type.symbol); } if (type.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) { return escapeLeadingUnderscores("" + (type).value); @@ -9733,6 +9735,9 @@ namespace ts { } function getLiteralTypeFromPropertyName(name: PropertyName) { + if (isPrivateName(name)) { + return neverType; + } return isIdentifier(name) ? getLiteralType(unescapeLeadingUnderscores(name.escapedText)) : getRegularTypeOfLiteralType(isComputedPropertyName(name) ? checkComputedPropertyName(name) : checkExpression(name)); } @@ -13008,23 +13013,44 @@ namespace ts { const unmatchedProperty = getUnmatchedProperty(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false); if (unmatchedProperty) { if (reportErrors) { - const props = arrayFrom(getUnmatchedProperties(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false)); - if (!headMessage || (headMessage.code !== Diagnostics.Class_0_incorrectly_implements_interface_1.code && - headMessage.code !== Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass.code)) { - suppressNextError = true; // Retain top-level error for interface implementing issues, otherwise omit it - } - if (props.length === 1) { - const propName = symbolToString(unmatchedProperty); - reportError(Diagnostics.Property_0_is_missing_in_type_1_but_required_in_type_2, propName, typeToString(source), typeToString(target)); - if (length(unmatchedProperty.declarations)) { - associateRelatedInfo(createDiagnosticForNode(unmatchedProperty.declarations[0], Diagnostics._0_is_declared_here, propName)); + let hasReported = false; + // give specific error in case where private names have the same description + if ( + unmatchedProperty.valueDeclaration + && isNamedDeclaration(unmatchedProperty.valueDeclaration) + && isPrivateName(unmatchedProperty.valueDeclaration.name) + && isClassDeclaration(source.symbol.valueDeclaration) + ) { + const privateNameDescription = unmatchedProperty.valueDeclaration.name.escapedText; + const symbolTableKey = getPropertyNameForPrivateNameDescription(source.symbol, privateNameDescription); + if (symbolTableKey && !!getPropertyOfType(source, symbolTableKey)) { + reportError( + Diagnostics.Property_0_is_missing_in_type_1_While_type_1_has_a_private_member_with_the_same_spelling_its_declaration_and_accessibility_are_distinct, + diagnosticName(privateNameDescription), + diagnosticName(source.symbol.valueDeclaration.name || ("(anonymous)" as __String)) + ); + hasReported = true; } } - else if (props.length > 5) { // arbitrary cutoff for too-long list form - reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2_and_3_more, typeToString(source), typeToString(target), map(props.slice(0, 4), p => symbolToString(p)).join(", "), props.length - 4); - } - else { - reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2, typeToString(source), typeToString(target), map(props, p => symbolToString(p)).join(", ")); + if (!hasReported) { + const props = arrayFrom(getUnmatchedProperties(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false)); + if (!headMessage || (headMessage.code !== Diagnostics.Class_0_incorrectly_implements_interface_1.code && + headMessage.code !== Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass.code)) { + suppressNextError = true; // Retain top-level error for interface implementing issues, otherwise omit it + } + if (props.length === 1) { + const propName = symbolToString(unmatchedProperty); + reportError(Diagnostics.Property_0_is_missing_in_type_1_but_required_in_type_2, propName, typeToString(source), typeToString(target)); + if (length(unmatchedProperty.declarations)) { + associateRelatedInfo(createDiagnosticForNode(unmatchedProperty.declarations[0], Diagnostics._0_is_declared_here, propName)); + } + } + else if (props.length > 5) { // arbitrary cutoff for too-long list form + reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2_and_3_more, typeToString(source), typeToString(target), map(props.slice(0, 4), p => symbolToString(p)).join(", "), props.length - 4); + } + else { + reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2, typeToString(source), typeToString(target), map(props, p => symbolToString(p)).join(", ")); + } } } return Ternary.False; @@ -19493,6 +19519,48 @@ namespace ts { return checkPropertyAccessExpressionOrQualifiedName(node, node.left, node.right); } + function getPropertyForPrivateName(apparentType: Type, leftType: Type, right: PrivateName, errorNode: Node | undefined): Symbol | undefined { + let classWithShadowedPrivateName; + let container = getContainingClass(right); + while (container) { + const symbolTableKey = getPropertyNameForPrivateNameDescription(container.symbol, right.escapedText); + if (symbolTableKey) { + const prop = getPropertyOfType(apparentType, symbolTableKey); + if (prop) { + if (classWithShadowedPrivateName) { + if (errorNode) { + error( + errorNode, + Diagnostics.This_usage_of_0_refers_to_the_private_member_declared_in_its_enclosing_class_While_type_1_has_a_private_member_with_the_same_spelling_its_declaration_and_accessibility_are_distinct, + diagnosticName(right), + diagnosticName(classWithShadowedPrivateName.name || ("(anonymous)" as __String)) + ); + } + return undefined; + } + return prop; + } + else { + classWithShadowedPrivateName = container; + } + } + container = getContainingClass(container); + } + // If this isn't a case of shadowing, and the lhs has a property with the same + // private name description, then there is a privacy violation + if (leftType.symbol.members) { + const symbolTableKey = getPropertyNameForPrivateNameDescription(leftType.symbol, right.escapedText); + const prop = getPropertyOfType(apparentType, symbolTableKey); + if (prop) { + if (errorNode) { + error(right, Diagnostics.Property_0_is_not_accessible_outside_class_1_because_it_has_a_private_name, symbolToString(prop), typeToString(getDeclaringClass(prop)!)); + } + } + } + // not found + return undefined; + } + function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier | PrivateName) { let propType: Type; const leftType = checkNonNullExpression(left); @@ -19505,7 +19573,7 @@ namespace ts { return apparentType; } const assignmentKind = getAssignmentTargetKind(node); - const prop = getPropertyOfType(apparentType, right.escapedText); + const prop = isPrivateName(right) ? getPropertyForPrivateName(apparentType, leftType, right, /* errorNode */ right) : getPropertyOfType(apparentType, right.escapedText); if (isIdentifier(left) && parentSymbol && !(prop && isConstEnumOrConstEnumOnlyModule(prop))) { markAliasReferenced(parentSymbol, node); } @@ -22522,6 +22590,9 @@ namespace ts { error(expr, Diagnostics.The_operand_of_a_delete_operator_must_be_a_property_reference); return booleanType; } + if (expr.kind === SyntaxKind.PropertyAccessExpression && isPrivateName((expr as PropertyAccessExpression).name)) { + error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_private_name); + } const links = getNodeLinks(expr); const symbol = getExportSymbolOfValueSymbolIfExported(links.resolvedSymbol); if (symbol && isReadonlySymbol(symbol)) { @@ -23833,9 +23904,6 @@ 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))) { @@ -30591,6 +30659,9 @@ namespace ts { else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) && (node).dotDotDotToken) { return grammarErrorOnNode(node, Diagnostics.A_parameter_property_cannot_be_declared_using_a_rest_parameter); } + else if (isNamedDeclaration(node) && (flags & ModifierFlags.AccessibilityModifier) && node.name.kind === SyntaxKind.PrivateName) { + return grammarErrorOnNode(node, Diagnostics.Accessibility_modifiers_cannot_be_used_with_private_names); + } if (flags & ModifierFlags.Async) { return checkGrammarAsyncModifier(node, lastAsync!); } @@ -30988,6 +31059,10 @@ namespace ts { return grammarErrorOnNode(prop.equalsToken!, Diagnostics.can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment); } + if (name.kind === SyntaxKind.PrivateName) { + return grammarErrorOnNode(name, Diagnostics.Private_names_are_not_allowed_outside_class_bodies); + } + // Modifiers are never allowed on properties except for 'async' on a method declaration if (prop.modifiers) { for (const mod of prop.modifiers!) { // TODO: GH#19955 @@ -31429,10 +31504,6 @@ 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 b95e3e8fae98e..bba7863e4701e 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4478,14 +4478,34 @@ "category": "Error", "code": 18003 }, - "Private names are not allowed in variable declarations.": { + "Accessibility modifiers cannot be used with private names.": { "category": "Error", "code": 18004 }, - "Private names cannot be used as parameters": { + "The operand of a delete operator cannot be a private name.": { "category": "Error", "code": 18005 }, + "'#constructor' is a reserved word.": { + "category": "Error", + "code": 18006 + }, + "Property '{0}' is not accessible outside class '{1}' because it has a private name.": { + "category": "Error", + "code": 18007 + }, + "This usage of '{0}' refers to the private member declared in its enclosing class. While type '{1}' has a private member with the same spelling, its declaration and accessibility are distinct.": { + "category": "Error", + "code": 18008 + }, + "Property '{0}' is missing in type '{1}'. While type '{1}' has a private member with the same spelling, its declaration and accessibility are distinct.": { + "category": "Error", + "code": 18009 + }, + "Private names are not allowed outside class bodies.": { + "category": "Error", + "code": 18010 + }, "File is a CommonJS module; it may be converted to an ES6 module.": { "category": "Suggestion", diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 02779b30d151f..251f04fb974f2 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3091,6 +3091,7 @@ namespace ts { getDeclaredTypeOfSymbol(symbol: Symbol): Type; getPropertiesOfType(type: Type): Symbol[]; getPropertyOfType(type: Type, propertyName: string): Symbol | undefined; + getPropertyForPrivateName(apparentType: Type, leftType: Type, right: PrivateName, errorNode: Node | undefined): Symbol | undefined; /* @internal */ getTypeOfPropertyOfType(type: Type, propertyName: string): Type | undefined; getIndexInfoOfType(type: Type, kind: IndexKind): IndexInfo | undefined; getSignaturesOfType(type: Type, kind: SignatureKind): ReadonlyArray; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index dd3f458e0119b..7ad07f0f1f5ca 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1539,6 +1539,10 @@ namespace ts { export function nodeCanBeDecorated(node: ClassElement, parent: Node): boolean; export function nodeCanBeDecorated(node: Node, parent: Node, grandparent: Node): boolean; export function nodeCanBeDecorated(node: Node, parent?: Node, grandparent?: Node): boolean { + // private names cannot be used with decorators yet + if (isNamedDeclaration(node) && isPrivateName(node.name)) { + return false; + } switch (node.kind) { case SyntaxKind.ClassDeclaration: // classes are valid targets @@ -2782,10 +2786,18 @@ namespace ts { return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.PrivateName ? node.escapedText : escapeLeadingUnderscores(node.text); } + export function getPropertyNameForUniqueESSymbol(symbol: Symbol): __String { + return `__@${getSymbolId(symbol)}@${symbol.escapedName}` as __String; + } + export function getPropertyNameForKnownSymbolName(symbolName: string): __String { return "__@" + symbolName as __String; } + export function getPropertyNameForPrivateNameDescription(containingClassSymbol: Symbol, description: __String): __String { + return `__#${getSymbolId(containingClassSymbol)}@${description}` as __String; + } + export function isKnownSymbol(symbol: Symbol): boolean { return startsWith(symbol.escapedName as string, "__@"); } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 23c1a4f2f4b9c..c13593dd67a2d 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1921,6 +1921,7 @@ declare namespace ts { getDeclaredTypeOfSymbol(symbol: Symbol): Type; getPropertiesOfType(type: Type): Symbol[]; getPropertyOfType(type: Type, propertyName: string): Symbol | undefined; + getPropertyForPrivateName(apparentType: Type, leftType: Type, right: PrivateName, errorNode: Node | undefined): Symbol | undefined; getIndexInfoOfType(type: Type, kind: IndexKind): IndexInfo | undefined; getSignaturesOfType(type: Type, kind: SignatureKind): ReadonlyArray; getIndexTypeOfType(type: Type, kind: IndexKind): Type | undefined; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 3ee850633e9d0..50f9dd5767ab2 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1921,6 +1921,7 @@ declare namespace ts { getDeclaredTypeOfSymbol(symbol: Symbol): Type; getPropertiesOfType(type: Type): Symbol[]; getPropertyOfType(type: Type, propertyName: string): Symbol | undefined; + getPropertyForPrivateName(apparentType: Type, leftType: Type, right: PrivateName, errorNode: Node | undefined): Symbol | undefined; getIndexInfoOfType(type: Type, kind: IndexKind): IndexInfo | undefined; getSignaturesOfType(type: Type, kind: SignatureKind): ReadonlyArray; getIndexTypeOfType(type: Type, kind: IndexKind): Type | undefined; diff --git a/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping.baseline b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping.baseline new file mode 100644 index 0000000000000..5fae8ec8c9914 --- /dev/null +++ b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping.baseline @@ -0,0 +1,34 @@ +EmitSkipped: false +FileName : ./dist/index.js +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Foo = /** @class */ (function () { + function Foo() { + } + Foo.prototype.methodName = function (propName) { }; + Foo.prototype.otherMethod = function () { + if (Math.random() > 0.5) { + return { x: 42 }; + } + return { y: "yes" }; + }; + return Foo; +}()); +exports.Foo = Foo; +FileName : ./dist/index.d.ts.map +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../tests/cases/fourslash/index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts +export declare class Foo { + member: string; + methodName(propName: SomeType): void; + otherMethod(): { + x: number; + y?: undefined; + } | { + y: string; + x?: undefined; + }; +} +export interface SomeType { + member: number; +} +//# sourceMappingURL=index.d.ts.map diff --git a/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping2.baseline b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping2.baseline new file mode 100644 index 0000000000000..151713a03bd45 --- /dev/null +++ b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping2.baseline @@ -0,0 +1,35 @@ +EmitSkipped: false +FileName : ./dist/index.js.map +{"version":3,"file":"index.js","sourceRoot":"/tests/cases/fourslash/","sources":["index.ts"],"names":[],"mappings":";;AAAA;IAAA;IASA,CAAC;IAPG,wBAAU,GAAV,UAAW,QAAkB,IAAS,CAAC;IACvC,yBAAW,GAAX;QACI,IAAI,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,EAAE;YACrB,OAAO,EAAC,CAAC,EAAE,EAAE,EAAC,CAAC;SAClB;QACD,OAAO,EAAC,CAAC,EAAE,KAAK,EAAC,CAAC;IACtB,CAAC;IACL,UAAC;AAAD,CAAC,AATD,IASC;AATY,kBAAG"}FileName : ./dist/index.js +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Foo = /** @class */ (function () { + function Foo() { + } + Foo.prototype.methodName = function (propName) { }; + Foo.prototype.otherMethod = function () { + if (Math.random() > 0.5) { + return { x: 42 }; + } + return { y: "yes" }; + }; + return Foo; +}()); +exports.Foo = Foo; +//# sourceMappingURL=index.js.mapFileName : ./dist/index.d.ts.map +{"version":3,"file":"index.d.ts","sourceRoot":"/tests/cases/fourslash/","sources":["index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts +export declare class Foo { + member: string; + methodName(propName: SomeType): void; + otherMethod(): { + x: number; + y?: undefined; + } | { + y: string; + x?: undefined; + }; +} +export interface SomeType { + member: number; +} +//# sourceMappingURL=index.d.ts.map diff --git a/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping3.baseline b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping3.baseline new file mode 100644 index 0000000000000..f05cbbd4c351b --- /dev/null +++ b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping3.baseline @@ -0,0 +1,34 @@ +EmitSkipped: false +FileName : ./dist/index.js +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Foo = /** @class */ (function () { + function Foo() { + } + Foo.prototype.methodName = function (propName) { }; + Foo.prototype.otherMethod = function () { + if (Math.random() > 0.5) { + return { x: 42 }; + } + return { y: "yes" }; + }; + return Foo; +}()); +exports.Foo = Foo; +FileName : ./dist/index.d.ts.map +{"version":3,"file":"index.d.ts","sourceRoot":"/tests/cases/fourslash/","sources":["index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts +export declare class Foo { + member: string; + methodName(propName: SomeType): void; + otherMethod(): { + x: number; + y?: undefined; + } | { + y: string; + x?: undefined; + }; +} +export interface SomeType { + member: number; +} +//# sourceMappingURL=index.d.ts.map diff --git a/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping_NoInline.baseline b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping_NoInline.baseline new file mode 100644 index 0000000000000..ad51be6ddc0f5 --- /dev/null +++ b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping_NoInline.baseline @@ -0,0 +1,34 @@ +EmitSkipped: false +FileName : ./dist/index.js +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Foo = /** @class */ (function () { + function Foo() { + } + Foo.prototype.methodName = function (propName) { }; + Foo.prototype.otherMethod = function () { + if (Math.random() > 0.5) { + return { x: 42 }; + } + return { y: "yes" }; + }; + return Foo; +}()); +exports.Foo = Foo; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90ZXN0cy9jYXNlcy9mb3Vyc2xhc2gvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQTtJQUFBO0lBU0EsQ0FBQztJQVBHLHdCQUFVLEdBQVYsVUFBVyxRQUFrQixJQUFTLENBQUM7SUFDdkMseUJBQVcsR0FBWDtRQUNJLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEdBQUcsRUFBRTtZQUNyQixPQUFPLEVBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBQyxDQUFDO1NBQ2xCO1FBQ0QsT0FBTyxFQUFDLENBQUMsRUFBRSxLQUFLLEVBQUMsQ0FBQztJQUN0QixDQUFDO0lBQ0wsVUFBQztBQUFELENBQUMsQUFURCxJQVNDO0FBVFksa0JBQUcifQ==FileName : ./dist/index.d.ts.map +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../tests/cases/fourslash/index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts +export declare class Foo { + member: string; + methodName(propName: SomeType): void; + otherMethod(): { + x: number; + y?: undefined; + } | { + y: string; + x?: undefined; + }; +} +export interface SomeType { + member: number; +} +//# sourceMappingURL=index.d.ts.map diff --git a/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping_NoInlineSources.baseline b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping_NoInlineSources.baseline new file mode 100644 index 0000000000000..8f6440b29dc78 --- /dev/null +++ b/tests/baselines/reference/declarationMapsGeneratedMapsEnableMapping_NoInlineSources.baseline @@ -0,0 +1,34 @@ +EmitSkipped: false +FileName : ./dist/index.js +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Foo = /** @class */ (function () { + function Foo() { + } + Foo.prototype.methodName = function (propName) { }; + Foo.prototype.otherMethod = function () { + if (Math.random() > 0.5) { + return { x: 42 }; + } + return { y: "yes" }; + }; + return Foo; +}()); +exports.Foo = Foo; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90ZXN0cy9jYXNlcy9mb3Vyc2xhc2gvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQTtJQUFBO0lBU0EsQ0FBQztJQVBHLHdCQUFVLEdBQVYsVUFBVyxRQUFrQixJQUFTLENBQUM7SUFDdkMseUJBQVcsR0FBWDtRQUNJLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEdBQUcsRUFBRTtZQUNyQixPQUFPLEVBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBQyxDQUFDO1NBQ2xCO1FBQ0QsT0FBTyxFQUFDLENBQUMsRUFBRSxLQUFLLEVBQUMsQ0FBQztJQUN0QixDQUFDO0lBQ0wsVUFBQztBQUFELENBQUMsQUFURCxJQVNDO0FBVFksa0JBQUciLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgY2xhc3MgRm9vIHtcbiAgICBtZW1iZXI6IHN0cmluZztcbiAgICBtZXRob2ROYW1lKHByb3BOYW1lOiBTb21lVHlwZSk6IHZvaWQge31cbiAgICBvdGhlck1ldGhvZCgpIHtcbiAgICAgICAgaWYgKE1hdGgucmFuZG9tKCkgPiAwLjUpIHtcbiAgICAgICAgICAgIHJldHVybiB7eDogNDJ9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7eTogXCJ5ZXNcIn07XG4gICAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNvbWVUeXBlIHtcbiAgICBtZW1iZXI6IG51bWJlcjtcbn0iXX0=FileName : ./dist/index.d.ts.map +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../tests/cases/fourslash/index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts +export declare class Foo { + member: string; + methodName(propName: SomeType): void; + otherMethod(): { + x: number; + y?: undefined; + } | { + y: string; + x?: undefined; + }; +} +export interface SomeType { + member: number; +} +//# sourceMappingURL=index.d.ts.map diff --git a/tests/baselines/reference/privateNameAndIndexSignature.errors.txt b/tests/baselines/reference/privateNameAndIndexSignature.errors.txt index 1b4895bf23d64..cbe22ffb7c156 100644 --- a/tests/baselines/reference/privateNameAndIndexSignature.errors.txt +++ b/tests/baselines/reference/privateNameAndIndexSignature.errors.txt @@ -1,7 +1,9 @@ -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(6,14): error TS2339: Property '#f' does not exist on type 'A'. ==== tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts (1 errors) ==== + // @target es6 + class A { [k: string]: any; constructor(message: string) { diff --git a/tests/baselines/reference/privateNameAndIndexSignature.js b/tests/baselines/reference/privateNameAndIndexSignature.js index d1271acca8ce9..561a0ce1210b3 100644 --- a/tests/baselines/reference/privateNameAndIndexSignature.js +++ b/tests/baselines/reference/privateNameAndIndexSignature.js @@ -1,4 +1,6 @@ //// [privateNameAndIndexSignature.ts] +// @target es6 + class A { [k: string]: any; constructor(message: string) { @@ -8,6 +10,8 @@ class A { //// [privateNameAndIndexSignature.js] +"use strict"; +// @target es6 var A = /** @class */ (function () { function A(message) { this.#f = 3; // Error Property '#f' does not exist on type 'A'. diff --git a/tests/baselines/reference/privateNameAndIndexSignature.symbols b/tests/baselines/reference/privateNameAndIndexSignature.symbols index d8a153c04270e..609eb3a491779 100644 --- a/tests/baselines/reference/privateNameAndIndexSignature.symbols +++ b/tests/baselines/reference/privateNameAndIndexSignature.symbols @@ -1,12 +1,14 @@ === tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts === +// @target es6 + class A { >A : Symbol(A, Decl(privateNameAndIndexSignature.ts, 0, 0)) [k: string]: any; ->k : Symbol(k, Decl(privateNameAndIndexSignature.ts, 1, 5)) +>k : Symbol(k, Decl(privateNameAndIndexSignature.ts, 3, 5)) constructor(message: string) { ->message : Symbol(message, Decl(privateNameAndIndexSignature.ts, 2, 16)) +>message : Symbol(message, Decl(privateNameAndIndexSignature.ts, 4, 16)) this.#f = 3 // Error Property '#f' does not exist on type 'A'. >this : Symbol(A, Decl(privateNameAndIndexSignature.ts, 0, 0)) diff --git a/tests/baselines/reference/privateNameAndIndexSignature.types b/tests/baselines/reference/privateNameAndIndexSignature.types index d663d5b9517cc..47015a920bb28 100644 --- a/tests/baselines/reference/privateNameAndIndexSignature.types +++ b/tests/baselines/reference/privateNameAndIndexSignature.types @@ -1,4 +1,6 @@ === tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts === +// @target es6 + class A { >A : A diff --git a/tests/baselines/reference/privateNameConstructorReserved.errors.txt b/tests/baselines/reference/privateNameConstructorReserved.errors.txt new file mode 100644 index 0000000000000..ef48440e250a1 --- /dev/null +++ b/tests/baselines/reference/privateNameConstructorReserved.errors.txt @@ -0,0 +1,12 @@ +tests/cases/conformance/classes/members/privateNames/privateNameConstructorReserved.ts(4,5): error TS18006: '#constructor' is a reserved word. + + +==== tests/cases/conformance/classes/members/privateNames/privateNameConstructorReserved.ts (1 errors) ==== + // @target es6 + + class A { + #constructor() {} // Error: `#constructor` is a reserved word. + ~~~~~~~~~~~~ +!!! error TS18006: '#constructor' is a reserved word. + } + \ No newline at end of file diff --git a/tests/baselines/reference/privateNameConstructorReserved.js b/tests/baselines/reference/privateNameConstructorReserved.js new file mode 100644 index 0000000000000..61585bd4eb127 --- /dev/null +++ b/tests/baselines/reference/privateNameConstructorReserved.js @@ -0,0 +1,16 @@ +//// [privateNameConstructorReserved.ts] +// @target es6 + +class A { + #constructor() {} // Error: `#constructor` is a reserved word. +} + + +//// [privateNameConstructorReserved.js] +// @target es6 +var A = /** @class */ (function () { + function A() { + } + A.prototype.#constructor = function () { }; // Error: `#constructor` is a reserved word. + return A; +}()); diff --git a/tests/baselines/reference/privateNameConstructorReserved.symbols b/tests/baselines/reference/privateNameConstructorReserved.symbols new file mode 100644 index 0000000000000..3f3cbc722039f --- /dev/null +++ b/tests/baselines/reference/privateNameConstructorReserved.symbols @@ -0,0 +1,10 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameConstructorReserved.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNameConstructorReserved.ts, 0, 0)) + + #constructor() {} // Error: `#constructor` is a reserved word. +>#constructor : Symbol(A.#constructor, Decl(privateNameConstructorReserved.ts, 2, 9)) +} + diff --git a/tests/baselines/reference/privateNameConstructorReserved.types b/tests/baselines/reference/privateNameConstructorReserved.types new file mode 100644 index 0000000000000..2b75281b7a02e --- /dev/null +++ b/tests/baselines/reference/privateNameConstructorReserved.types @@ -0,0 +1,10 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameConstructorReserved.ts === +// @target es6 + +class A { +>A : A + + #constructor() {} // Error: `#constructor` is a reserved word. +>#constructor : () => void +} + diff --git a/tests/baselines/reference/privateNameDuplicateField.errors.txt b/tests/baselines/reference/privateNameDuplicateField.errors.txt new file mode 100644 index 0000000000000..4a8428c6102c2 --- /dev/null +++ b/tests/baselines/reference/privateNameDuplicateField.errors.txt @@ -0,0 +1,13 @@ +tests/cases/conformance/classes/members/privateNames/privateNameDuplicateField.ts(5,5): error TS2300: Duplicate identifier '#foo'. + + +==== tests/cases/conformance/classes/members/privateNames/privateNameDuplicateField.ts (1 errors) ==== + // @target es6 + + class A { + #foo = "foo"; + #foo = "foo"; + ~~~~ +!!! error TS2300: Duplicate identifier '#foo'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/privateNameDuplicateField.js b/tests/baselines/reference/privateNameDuplicateField.js new file mode 100644 index 0000000000000..3fda0374540d1 --- /dev/null +++ b/tests/baselines/reference/privateNameDuplicateField.js @@ -0,0 +1,19 @@ +//// [privateNameDuplicateField.ts] +// @target es6 + +class A { + #foo = "foo"; + #foo = "foo"; +} + + +//// [privateNameDuplicateField.js] +"use strict"; +// @target es6 +var A = /** @class */ (function () { + function A() { + this.#foo = "foo"; + this.#foo = "foo"; + } + return A; +}()); diff --git a/tests/baselines/reference/privateNameDuplicateField.symbols b/tests/baselines/reference/privateNameDuplicateField.symbols new file mode 100644 index 0000000000000..0da02e645ada3 --- /dev/null +++ b/tests/baselines/reference/privateNameDuplicateField.symbols @@ -0,0 +1,13 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameDuplicateField.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNameDuplicateField.ts, 0, 0)) + + #foo = "foo"; +>#foo : Symbol(A.#foo, Decl(privateNameDuplicateField.ts, 2, 9), Decl(privateNameDuplicateField.ts, 3, 17)) + + #foo = "foo"; +>#foo : Symbol(A.#foo, Decl(privateNameDuplicateField.ts, 2, 9), Decl(privateNameDuplicateField.ts, 3, 17)) +} + diff --git a/tests/baselines/reference/privateNameDuplicateField.types b/tests/baselines/reference/privateNameDuplicateField.types new file mode 100644 index 0000000000000..e73152ebd4455 --- /dev/null +++ b/tests/baselines/reference/privateNameDuplicateField.types @@ -0,0 +1,15 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameDuplicateField.ts === +// @target es6 + +class A { +>A : A + + #foo = "foo"; +>#foo : string +>"foo" : "foo" + + #foo = "foo"; +>#foo : string +>"foo" : "foo" +} + diff --git a/tests/baselines/reference/privateNameField.js b/tests/baselines/reference/privateNameField.js index f432be2b3d336..254f6833afa2f 100644 --- a/tests/baselines/reference/privateNameField.js +++ b/tests/baselines/reference/privateNameField.js @@ -1,4 +1,6 @@ //// [privateNameField.ts] +// @target es6 + class A { #name: string; constructor(name: string) { @@ -7,6 +9,8 @@ class A { } //// [privateNameField.js] +"use strict"; +// @target es6 var A = /** @class */ (function () { function A(name) { this.#name = name; diff --git a/tests/baselines/reference/privateNameField.symbols b/tests/baselines/reference/privateNameField.symbols index cbaedbc596caf..c37ded65bd1a7 100644 --- a/tests/baselines/reference/privateNameField.symbols +++ b/tests/baselines/reference/privateNameField.symbols @@ -1,16 +1,18 @@ === tests/cases/conformance/classes/members/privateNames/privateNameField.ts === +// @target es6 + class A { >A : Symbol(A, Decl(privateNameField.ts, 0, 0)) #name: string; ->#name : Symbol(A.#name, Decl(privateNameField.ts, 0, 9)) +>#name : Symbol(A.#name, Decl(privateNameField.ts, 2, 9)) constructor(name: string) { ->name : Symbol(name, Decl(privateNameField.ts, 2, 16)) +>name : Symbol(name, Decl(privateNameField.ts, 4, 16)) this.#name = name; ->this.#name : Symbol(A.#name, Decl(privateNameField.ts, 0, 9)) +>this.#name : Symbol(A.#name, Decl(privateNameField.ts, 2, 9)) >this : Symbol(A, Decl(privateNameField.ts, 0, 0)) ->name : Symbol(name, Decl(privateNameField.ts, 2, 16)) +>name : Symbol(name, Decl(privateNameField.ts, 4, 16)) } } diff --git a/tests/baselines/reference/privateNameField.types b/tests/baselines/reference/privateNameField.types index 1eb30eda52590..db7dba04475e8 100644 --- a/tests/baselines/reference/privateNameField.types +++ b/tests/baselines/reference/privateNameField.types @@ -1,4 +1,6 @@ === tests/cases/conformance/classes/members/privateNames/privateNameField.ts === +// @target es6 + class A { >A : A diff --git a/tests/baselines/reference/privateNameInObjectLiteral-1.errors.txt b/tests/baselines/reference/privateNameInObjectLiteral-1.errors.txt new file mode 100644 index 0000000000000..cd17f4caf1545 --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral-1.errors.txt @@ -0,0 +1,10 @@ +tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-1.ts(2,5): error TS18010: Private names are not allowed outside class bodies. + + +==== tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-1.ts (1 errors) ==== + const obj = { + #foo: 1 + ~~~~ +!!! error TS18010: Private names are not allowed outside class bodies. + }; + \ No newline at end of file diff --git a/tests/baselines/reference/privateNameInObjectLiteral-1.js b/tests/baselines/reference/privateNameInObjectLiteral-1.js new file mode 100644 index 0000000000000..58af5d0ec5158 --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral-1.js @@ -0,0 +1,10 @@ +//// [privateNameInObjectLiteral-1.ts] +const obj = { + #foo: 1 +}; + + +//// [privateNameInObjectLiteral-1.js] +var obj = { + #foo: 1 +}; diff --git a/tests/baselines/reference/privateNameInObjectLiteral-1.symbols b/tests/baselines/reference/privateNameInObjectLiteral-1.symbols new file mode 100644 index 0000000000000..c675ee7cc758c --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral-1.symbols @@ -0,0 +1,9 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-1.ts === +const obj = { +>obj : Symbol(obj, Decl(privateNameInObjectLiteral-1.ts, 0, 5)) + + #foo: 1 +>#foo : Symbol(#foo, Decl(privateNameInObjectLiteral-1.ts, 0, 13)) + +}; + diff --git a/tests/baselines/reference/privateNameInObjectLiteral-1.types b/tests/baselines/reference/privateNameInObjectLiteral-1.types new file mode 100644 index 0000000000000..48de261be2900 --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral-1.types @@ -0,0 +1,11 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-1.ts === +const obj = { +>obj : {} +>{ #foo: 1} : {} + + #foo: 1 +>#foo : number +>1 : 1 + +}; + diff --git a/tests/baselines/reference/privateNameInObjectLiteral-2.errors.txt b/tests/baselines/reference/privateNameInObjectLiteral-2.errors.txt new file mode 100644 index 0000000000000..b79507b32000f --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral-2.errors.txt @@ -0,0 +1,12 @@ +tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-2.ts(2,5): error TS18010: Private names are not allowed outside class bodies. + + +==== tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-2.ts (1 errors) ==== + const obj = { + #foo() { + ~~~~ +!!! error TS18010: Private names are not allowed outside class bodies. + + } + }; + \ No newline at end of file diff --git a/tests/baselines/reference/privateNameInObjectLiteral-2.js b/tests/baselines/reference/privateNameInObjectLiteral-2.js new file mode 100644 index 0000000000000..6bb2c99d4c169 --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral-2.js @@ -0,0 +1,13 @@ +//// [privateNameInObjectLiteral-2.ts] +const obj = { + #foo() { + + } +}; + + +//// [privateNameInObjectLiteral-2.js] +var obj = { + #foo: function () { + } +}; diff --git a/tests/baselines/reference/privateNameInObjectLiteral-2.symbols b/tests/baselines/reference/privateNameInObjectLiteral-2.symbols new file mode 100644 index 0000000000000..b9a25ac870963 --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral-2.symbols @@ -0,0 +1,10 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-2.ts === +const obj = { +>obj : Symbol(obj, Decl(privateNameInObjectLiteral-2.ts, 0, 5)) + + #foo() { +>#foo : Symbol(#foo, Decl(privateNameInObjectLiteral-2.ts, 0, 13)) + + } +}; + diff --git a/tests/baselines/reference/privateNameInObjectLiteral-2.types b/tests/baselines/reference/privateNameInObjectLiteral-2.types new file mode 100644 index 0000000000000..a1e36e82380b1 --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral-2.types @@ -0,0 +1,11 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-2.ts === +const obj = { +>obj : {} +>{ #foo() { }} : {} + + #foo() { +>#foo : () => void + + } +}; + diff --git a/tests/baselines/reference/privateNameInObjectLiteral.errors.txt b/tests/baselines/reference/privateNameInObjectLiteral.errors.txt new file mode 100644 index 0000000000000..2f5101ec98646 --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral.errors.txt @@ -0,0 +1,14 @@ +tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral.ts(2,5): error TS18010: Private names are not allowed outside class bodies. + + +==== tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral.ts (1 errors) ==== + const obj = { + #foo: "#foo", + ~~~~ +!!! error TS18010: Private names are not allowed outside class bodies. + #bar: () => true, + #baz() { + return true; + } + }; + \ No newline at end of file diff --git a/tests/baselines/reference/privateNameInObjectLiteral.js b/tests/baselines/reference/privateNameInObjectLiteral.js new file mode 100644 index 0000000000000..a95d80d4add5f --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral.js @@ -0,0 +1,18 @@ +//// [privateNameInObjectLiteral.ts] +const obj = { + #foo: "#foo", + #bar: () => true, + #baz() { + return true; + } +}; + + +//// [privateNameInObjectLiteral.js] +var obj = { + #foo: "#foo", + #bar: function () { return true; }, + #baz: function () { + return true; + } +}; diff --git a/tests/baselines/reference/privateNameInObjectLiteral.symbols b/tests/baselines/reference/privateNameInObjectLiteral.symbols new file mode 100644 index 0000000000000..f5592c7384305 --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral.symbols @@ -0,0 +1,17 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral.ts === +const obj = { +>obj : Symbol(obj, Decl(privateNameInObjectLiteral.ts, 0, 5)) + + #foo: "#foo", +>#foo : Symbol(#foo, Decl(privateNameInObjectLiteral.ts, 0, 13)) + + #bar: () => true, +>#bar : Symbol(#bar, Decl(privateNameInObjectLiteral.ts, 1, 17)) + + #baz() { +>#baz : Symbol(#baz, Decl(privateNameInObjectLiteral.ts, 2, 21)) + + return true; + } +}; + diff --git a/tests/baselines/reference/privateNameInObjectLiteral.types b/tests/baselines/reference/privateNameInObjectLiteral.types new file mode 100644 index 0000000000000..372dc87bae5c3 --- /dev/null +++ b/tests/baselines/reference/privateNameInObjectLiteral.types @@ -0,0 +1,22 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral.ts === +const obj = { +>obj : {} +>{ #foo: "#foo", #bar: () => true, #baz() { return true; }} : {} + + #foo: "#foo", +>#foo : string +>"#foo" : "#foo" + + #bar: () => true, +>#bar : () => boolean +>() => true : () => boolean +>true : true + + #baz() { +>#baz : () => boolean + + return true; +>true : true + } +}; + diff --git a/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.errors.txt b/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.errors.txt new file mode 100644 index 0000000000000..41a4d9c277cbf --- /dev/null +++ b/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.errors.txt @@ -0,0 +1,17 @@ +tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts(7,9): error TS2339: Property '#foo' does not exist on type 'A'. +tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts(7,9): error TS18007: Property '#foo' is not accessible outside class 'A' because it has a private name. + + +==== tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts (2 errors) ==== + // @target es6 + + class A { + #foo: number = 3; + } + + new A().#foo = 4; // Error + ~~~~ +!!! error TS2339: Property '#foo' does not exist on type 'A'. + ~~~~ +!!! error TS18007: Property '#foo' is not accessible outside class 'A' because it has a private name. + \ No newline at end of file diff --git a/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.js b/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.js new file mode 100644 index 0000000000000..7ea7a6b5f370c --- /dev/null +++ b/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.js @@ -0,0 +1,20 @@ +//// [privateNameNotAccessibleOutsideDefiningClass.ts] +// @target es6 + +class A { + #foo: number = 3; +} + +new A().#foo = 4; // Error + + +//// [privateNameNotAccessibleOutsideDefiningClass.js] +"use strict"; +// @target es6 +var A = /** @class */ (function () { + function A() { + this.#foo = 3; + } + return A; +}()); +new A().#foo = 4; // Error diff --git a/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.symbols b/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.symbols new file mode 100644 index 0000000000000..8d9427fc6d603 --- /dev/null +++ b/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.symbols @@ -0,0 +1,13 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNameNotAccessibleOutsideDefiningClass.ts, 0, 0)) + + #foo: number = 3; +>#foo : Symbol(A.#foo, Decl(privateNameNotAccessibleOutsideDefiningClass.ts, 2, 9)) +} + +new A().#foo = 4; // Error +>A : Symbol(A, Decl(privateNameNotAccessibleOutsideDefiningClass.ts, 0, 0)) + diff --git a/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.types b/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.types new file mode 100644 index 0000000000000..e6a0f5ac8f55b --- /dev/null +++ b/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.types @@ -0,0 +1,18 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts === +// @target es6 + +class A { +>A : A + + #foo: number = 3; +>#foo : number +>3 : 3 +} + +new A().#foo = 4; // Error +>new A().#foo = 4 : 4 +>new A().#foo : any +>new A() : A +>A : typeof A +>4 : 4 + diff --git a/tests/baselines/reference/privateNameNotAllowedOutsideClass.errors.txt b/tests/baselines/reference/privateNameNotAllowedOutsideClass.errors.txt new file mode 100644 index 0000000000000..2e72fffc7ba78 --- /dev/null +++ b/tests/baselines/reference/privateNameNotAllowedOutsideClass.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts(3,7): error TS1134: Variable declaration expected. +tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts(3,12): error TS1134: Variable declaration expected. +tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts(3,14): error TS1134: Variable declaration expected. + + +==== tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts (3 errors) ==== + // @target es6 + + const #foo = 3; + ~~~~ +!!! error TS1134: Variable declaration expected. + ~ +!!! error TS1134: Variable declaration expected. + ~ +!!! error TS1134: Variable declaration expected. \ No newline at end of file diff --git a/tests/baselines/reference/privateNameNotAllowedOutsideClass.js b/tests/baselines/reference/privateNameNotAllowedOutsideClass.js new file mode 100644 index 0000000000000..ff2b64b910ca1 --- /dev/null +++ b/tests/baselines/reference/privateNameNotAllowedOutsideClass.js @@ -0,0 +1,10 @@ +//// [privateNameNotAllowedOutsideClass.ts] +// @target es6 + +const #foo = 3; + +//// [privateNameNotAllowedOutsideClass.js] +"use strict"; +// @target es6 +var ; +3; diff --git a/tests/baselines/reference/privateNameNotAllowedOutsideClass.symbols b/tests/baselines/reference/privateNameNotAllowedOutsideClass.symbols new file mode 100644 index 0000000000000..6d6883e7fdf59 --- /dev/null +++ b/tests/baselines/reference/privateNameNotAllowedOutsideClass.symbols @@ -0,0 +1,5 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts === +// @target es6 +No type information for this code. +No type information for this code.const #foo = 3; +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/privateNameNotAllowedOutsideClass.types b/tests/baselines/reference/privateNameNotAllowedOutsideClass.types new file mode 100644 index 0000000000000..534e5b042580f --- /dev/null +++ b/tests/baselines/reference/privateNameNotAllowedOutsideClass.types @@ -0,0 +1,6 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts === +// @target es6 + +const #foo = 3; +>3 : 3 + diff --git a/tests/baselines/reference/privateNameSneakyRuntimeException.js b/tests/baselines/reference/privateNameSneakyRuntimeException.js new file mode 100644 index 0000000000000..11914013c8af0 --- /dev/null +++ b/tests/baselines/reference/privateNameSneakyRuntimeException.js @@ -0,0 +1,35 @@ +//// [privateNameSneakyRuntimeException.ts] +// @target es6 + +function createClass () { + return class { + #foo = 3; + equals(other: any) { + return this.#foo = other.#foo; + } + }; +} + +const a = new (createClass())(); +const b = new (createClass())(); + +console.log(a.equals(b)); // OK at compile time but will be a runtime error + + +//// [privateNameSneakyRuntimeException.js] +"use strict"; +// @target es6 +function createClass() { + return /** @class */ (function () { + function class_1() { + this.#foo = 3; + } + class_1.prototype.equals = function (other) { + return this.#foo = other.#foo; + }; + return class_1; + }()); +} +var a = new (createClass())(); +var b = new (createClass())(); +console.log(a.equals(b)); // OK at compile time but will be a runtime error diff --git a/tests/baselines/reference/privateNameSneakyRuntimeException.symbols b/tests/baselines/reference/privateNameSneakyRuntimeException.symbols new file mode 100644 index 0000000000000..585bdbf782c43 --- /dev/null +++ b/tests/baselines/reference/privateNameSneakyRuntimeException.symbols @@ -0,0 +1,39 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameSneakyRuntimeException.ts === +// @target es6 + +function createClass () { +>createClass : Symbol(createClass, Decl(privateNameSneakyRuntimeException.ts, 0, 0)) + + return class { + #foo = 3; +>#foo : Symbol((Anonymous class).#foo, Decl(privateNameSneakyRuntimeException.ts, 3, 18)) + + equals(other: any) { +>equals : Symbol((Anonymous class).equals, Decl(privateNameSneakyRuntimeException.ts, 4, 17)) +>other : Symbol(other, Decl(privateNameSneakyRuntimeException.ts, 5, 15)) + + return this.#foo = other.#foo; +>this.#foo : Symbol((Anonymous class).#foo, Decl(privateNameSneakyRuntimeException.ts, 3, 18)) +>this : Symbol((Anonymous class), Decl(privateNameSneakyRuntimeException.ts, 3, 10)) +>other : Symbol(other, Decl(privateNameSneakyRuntimeException.ts, 5, 15)) + } + }; +} + +const a = new (createClass())(); +>a : Symbol(a, Decl(privateNameSneakyRuntimeException.ts, 11, 5)) +>createClass : Symbol(createClass, Decl(privateNameSneakyRuntimeException.ts, 0, 0)) + +const b = new (createClass())(); +>b : Symbol(b, Decl(privateNameSneakyRuntimeException.ts, 12, 5)) +>createClass : Symbol(createClass, Decl(privateNameSneakyRuntimeException.ts, 0, 0)) + +console.log(a.equals(b)); // OK at compile time but will be a runtime error +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>a.equals : Symbol((Anonymous class).equals, Decl(privateNameSneakyRuntimeException.ts, 4, 17)) +>a : Symbol(a, Decl(privateNameSneakyRuntimeException.ts, 11, 5)) +>equals : Symbol((Anonymous class).equals, Decl(privateNameSneakyRuntimeException.ts, 4, 17)) +>b : Symbol(b, Decl(privateNameSneakyRuntimeException.ts, 12, 5)) + diff --git a/tests/baselines/reference/privateNameSneakyRuntimeException.types b/tests/baselines/reference/privateNameSneakyRuntimeException.types new file mode 100644 index 0000000000000..6f080bb585fca --- /dev/null +++ b/tests/baselines/reference/privateNameSneakyRuntimeException.types @@ -0,0 +1,52 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameSneakyRuntimeException.ts === +// @target es6 + +function createClass () { +>createClass : () => typeof (Anonymous class) + + return class { +>class { #foo = 3; equals(other: any) { return this.#foo = other.#foo; } } : typeof (Anonymous class) + + #foo = 3; +>#foo : number +>3 : 3 + + equals(other: any) { +>equals : (other: any) => any +>other : any + + return this.#foo = other.#foo; +>this.#foo = other.#foo : any +>this.#foo : number +>this : this +>other.#foo : any +>other : any + } + }; +} + +const a = new (createClass())(); +>a : (Anonymous class) +>new (createClass())() : (Anonymous class) +>(createClass()) : typeof (Anonymous class) +>createClass() : typeof (Anonymous class) +>createClass : () => typeof (Anonymous class) + +const b = new (createClass())(); +>b : (Anonymous class) +>new (createClass())() : (Anonymous class) +>(createClass()) : typeof (Anonymous class) +>createClass() : typeof (Anonymous class) +>createClass : () => typeof (Anonymous class) + +console.log(a.equals(b)); // OK at compile time but will be a runtime error +>console.log(a.equals(b)) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>a.equals(b) : any +>a.equals : (other: any) => any +>a : (Anonymous class) +>equals : (other: any) => any +>b : (Anonymous class) + diff --git a/tests/baselines/reference/privateNamesAndDecorators.errors.txt b/tests/baselines/reference/privateNamesAndDecorators.errors.txt new file mode 100644 index 0000000000000..a17770c1cb2a7 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndDecorators.errors.txt @@ -0,0 +1,18 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesAndDecorators.ts(4,5): error TS1206: Decorators are not valid here. +tests/cases/conformance/classes/members/privateNames/privateNamesAndDecorators.ts(6,5): error TS1206: Decorators are not valid here. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesAndDecorators.ts (2 errors) ==== + declare function dec(target: T): T; + + class A { + @dec // Error + ~ +!!! error TS1206: Decorators are not valid here. + #foo = 1; + @dec // Error + ~ +!!! error TS1206: Decorators are not valid here. + #bar(): void { } + } + \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesAndDecorators.js b/tests/baselines/reference/privateNamesAndDecorators.js new file mode 100644 index 0000000000000..57ab082f418bb --- /dev/null +++ b/tests/baselines/reference/privateNamesAndDecorators.js @@ -0,0 +1,19 @@ +//// [privateNamesAndDecorators.ts] +declare function dec(target: T): T; + +class A { + @dec // Error + #foo = 1; + @dec // Error + #bar(): void { } +} + + +//// [privateNamesAndDecorators.js] +var A = /** @class */ (function () { + function A() { + this.#foo = 1; + } + A.prototype.#bar = function () { }; + return A; +}()); diff --git a/tests/baselines/reference/privateNamesAndDecorators.symbols b/tests/baselines/reference/privateNamesAndDecorators.symbols new file mode 100644 index 0000000000000..97463512cd910 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndDecorators.symbols @@ -0,0 +1,24 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndDecorators.ts === +declare function dec(target: T): T; +>dec : Symbol(dec, Decl(privateNamesAndDecorators.ts, 0, 0)) +>T : Symbol(T, Decl(privateNamesAndDecorators.ts, 0, 21)) +>target : Symbol(target, Decl(privateNamesAndDecorators.ts, 0, 24)) +>T : Symbol(T, Decl(privateNamesAndDecorators.ts, 0, 21)) +>T : Symbol(T, Decl(privateNamesAndDecorators.ts, 0, 21)) + +class A { +>A : Symbol(A, Decl(privateNamesAndDecorators.ts, 0, 38)) + + @dec // Error +>dec : Symbol(dec, Decl(privateNamesAndDecorators.ts, 0, 0)) + + #foo = 1; +>#foo : Symbol(A.#foo, Decl(privateNamesAndDecorators.ts, 2, 9)) + + @dec // Error +>dec : Symbol(dec, Decl(privateNamesAndDecorators.ts, 0, 0)) + + #bar(): void { } +>#bar : Symbol(A.#bar, Decl(privateNamesAndDecorators.ts, 4, 13)) +} + diff --git a/tests/baselines/reference/privateNamesAndDecorators.types b/tests/baselines/reference/privateNamesAndDecorators.types new file mode 100644 index 0000000000000..828516f38999b --- /dev/null +++ b/tests/baselines/reference/privateNamesAndDecorators.types @@ -0,0 +1,22 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndDecorators.ts === +declare function dec(target: T): T; +>dec : (target: T) => T +>target : T + +class A { +>A : A + + @dec // Error +>dec : (target: T) => T + + #foo = 1; +>#foo : number +>1 : 1 + + @dec // Error +>dec : (target: T) => T + + #bar(): void { } +>#bar : () => void +} + diff --git a/tests/baselines/reference/privateNamesAndFields.js b/tests/baselines/reference/privateNamesAndFields.js new file mode 100644 index 0000000000000..dc5a000d32a1b --- /dev/null +++ b/tests/baselines/reference/privateNamesAndFields.js @@ -0,0 +1,50 @@ +//// [privateNamesAndFields.ts] +// @target es6 + +class A { + #foo: number; + constructor () { + this.#foo = 3; + } +} + +class B extends A { + #foo: string; + constructor () { + super(); + this.#foo = "some string"; + } +} + + +//// [privateNamesAndFields.js] +"use strict"; +// @target es6 +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var A = /** @class */ (function () { + function A() { + this.#foo = 3; + } + return A; +}()); +var B = /** @class */ (function (_super) { + __extends(B, _super); + function B() { + var _this = _super.call(this) || this; + _this.#foo = "some string"; + return _this; + } + return B; +}(A)); diff --git a/tests/baselines/reference/privateNamesAndFields.symbols b/tests/baselines/reference/privateNamesAndFields.symbols new file mode 100644 index 0000000000000..5300cd0427ff0 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndFields.symbols @@ -0,0 +1,33 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndFields.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNamesAndFields.ts, 0, 0)) + + #foo: number; +>#foo : Symbol(A.#foo, Decl(privateNamesAndFields.ts, 2, 9)) + + constructor () { + this.#foo = 3; +>this.#foo : Symbol(A.#foo, Decl(privateNamesAndFields.ts, 2, 9)) +>this : Symbol(A, Decl(privateNamesAndFields.ts, 0, 0)) + } +} + +class B extends A { +>B : Symbol(B, Decl(privateNamesAndFields.ts, 7, 1)) +>A : Symbol(A, Decl(privateNamesAndFields.ts, 0, 0)) + + #foo: string; +>#foo : Symbol(B.#foo, Decl(privateNamesAndFields.ts, 9, 19)) + + constructor () { + super(); +>super : Symbol(A, Decl(privateNamesAndFields.ts, 0, 0)) + + this.#foo = "some string"; +>this.#foo : Symbol(B.#foo, Decl(privateNamesAndFields.ts, 9, 19)) +>this : Symbol(B, Decl(privateNamesAndFields.ts, 7, 1)) + } +} + diff --git a/tests/baselines/reference/privateNamesAndFields.types b/tests/baselines/reference/privateNamesAndFields.types new file mode 100644 index 0000000000000..88a48ecd81298 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndFields.types @@ -0,0 +1,38 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndFields.ts === +// @target es6 + +class A { +>A : A + + #foo: number; +>#foo : number + + constructor () { + this.#foo = 3; +>this.#foo = 3 : 3 +>this.#foo : number +>this : this +>3 : 3 + } +} + +class B extends A { +>B : B +>A : A + + #foo: string; +>#foo : string + + constructor () { + super(); +>super() : void +>super : typeof A + + this.#foo = "some string"; +>this.#foo = "some string" : "some string" +>this.#foo : string +>this : this +>"some string" : "some string" + } +} + diff --git a/tests/baselines/reference/privateNamesAndGenericClasses-2.errors.txt b/tests/baselines/reference/privateNamesAndGenericClasses-2.errors.txt new file mode 100644 index 0000000000000..f9b6ebacba805 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndGenericClasses-2.errors.txt @@ -0,0 +1,46 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts(24,3): error TS2339: Property '#foo' does not exist on type 'C'. +tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts(24,3): error TS18007: Property '#foo' is not accessible outside class 'C' because it has a private name. +tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts(25,1): error TS2322: Type 'C' is not assignable to type 'C'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts(26,1): error TS2322: Type 'C' is not assignable to type 'C'. + Type 'number' is not assignable to type 'string'. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts (4 errors) ==== + class C { + #foo: T; + #bar(): T { + return this.#foo; + } + constructor(t: T) { + this.#foo = t; + t = this.#bar(); + } + set baz(t: T) { + this.#foo = t; + + } + get baz(): T { + return this.#foo; + } + } + + let a = new C(3); + let b = new C("hello"); + + a.baz = 5 // OK + const x: number = a.baz // OK + a.#foo; // Error + ~~~~ +!!! error TS2339: Property '#foo' does not exist on type 'C'. + ~~~~ +!!! error TS18007: Property '#foo' is not accessible outside class 'C' because it has a private name. + a = b; // Error + ~ +!!! error TS2322: Type 'C' is not assignable to type 'C'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. + b = a; // Error + ~ +!!! error TS2322: Type 'C' is not assignable to type 'C'. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesAndGenericClasses-2.js b/tests/baselines/reference/privateNamesAndGenericClasses-2.js new file mode 100644 index 0000000000000..69ef447e71d1d --- /dev/null +++ b/tests/baselines/reference/privateNamesAndGenericClasses-2.js @@ -0,0 +1,53 @@ +//// [privateNamesAndGenericClasses-2.ts] +class C { + #foo: T; + #bar(): T { + return this.#foo; + } + constructor(t: T) { + this.#foo = t; + t = this.#bar(); + } + set baz(t: T) { + this.#foo = t; + + } + get baz(): T { + return this.#foo; + } +} + +let a = new C(3); +let b = new C("hello"); + +a.baz = 5 // OK +const x: number = a.baz // OK +a.#foo; // Error +a = b; // Error +b = a; // Error + + +//// [privateNamesAndGenericClasses-2.js] +"use strict"; +class C { + constructor(t) { + this.#foo = t; + t = this.#bar(); + } + #bar() { + return this.#foo; + } + set baz(t) { + this.#foo = t; + } + get baz() { + return this.#foo; + } +} +let a = new C(3); +let b = new C("hello"); +a.baz = 5; // OK +const x = a.baz; // OK +a.#foo; // Error +a = b; // Error +b = a; // Error diff --git a/tests/baselines/reference/privateNamesAndGenericClasses-2.symbols b/tests/baselines/reference/privateNamesAndGenericClasses-2.symbols new file mode 100644 index 0000000000000..0f84af4a027f0 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndGenericClasses-2.symbols @@ -0,0 +1,82 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts === +class C { +>C : Symbol(C, Decl(privateNamesAndGenericClasses-2.ts, 0, 0)) +>T : Symbol(T, Decl(privateNamesAndGenericClasses-2.ts, 0, 8)) + + #foo: T; +>#foo : Symbol(C.#foo, Decl(privateNamesAndGenericClasses-2.ts, 0, 12)) +>T : Symbol(T, Decl(privateNamesAndGenericClasses-2.ts, 0, 8)) + + #bar(): T { +>#bar : Symbol(C.#bar, Decl(privateNamesAndGenericClasses-2.ts, 1, 12)) +>T : Symbol(T, Decl(privateNamesAndGenericClasses-2.ts, 0, 8)) + + return this.#foo; +>this.#foo : Symbol(C.#foo, Decl(privateNamesAndGenericClasses-2.ts, 0, 12)) +>this : Symbol(C, Decl(privateNamesAndGenericClasses-2.ts, 0, 0)) + } + constructor(t: T) { +>t : Symbol(t, Decl(privateNamesAndGenericClasses-2.ts, 5, 16)) +>T : Symbol(T, Decl(privateNamesAndGenericClasses-2.ts, 0, 8)) + + this.#foo = t; +>this.#foo : Symbol(C.#foo, Decl(privateNamesAndGenericClasses-2.ts, 0, 12)) +>this : Symbol(C, Decl(privateNamesAndGenericClasses-2.ts, 0, 0)) +>t : Symbol(t, Decl(privateNamesAndGenericClasses-2.ts, 5, 16)) + + t = this.#bar(); +>t : Symbol(t, Decl(privateNamesAndGenericClasses-2.ts, 5, 16)) +>this.#bar : Symbol(C.#bar, Decl(privateNamesAndGenericClasses-2.ts, 1, 12)) +>this : Symbol(C, Decl(privateNamesAndGenericClasses-2.ts, 0, 0)) + } + set baz(t: T) { +>baz : Symbol(C.baz, Decl(privateNamesAndGenericClasses-2.ts, 8, 5), Decl(privateNamesAndGenericClasses-2.ts, 12, 5)) +>t : Symbol(t, Decl(privateNamesAndGenericClasses-2.ts, 9, 12)) +>T : Symbol(T, Decl(privateNamesAndGenericClasses-2.ts, 0, 8)) + + this.#foo = t; +>this.#foo : Symbol(C.#foo, Decl(privateNamesAndGenericClasses-2.ts, 0, 12)) +>this : Symbol(C, Decl(privateNamesAndGenericClasses-2.ts, 0, 0)) +>t : Symbol(t, Decl(privateNamesAndGenericClasses-2.ts, 9, 12)) + + } + get baz(): T { +>baz : Symbol(C.baz, Decl(privateNamesAndGenericClasses-2.ts, 8, 5), Decl(privateNamesAndGenericClasses-2.ts, 12, 5)) +>T : Symbol(T, Decl(privateNamesAndGenericClasses-2.ts, 0, 8)) + + return this.#foo; +>this.#foo : Symbol(C.#foo, Decl(privateNamesAndGenericClasses-2.ts, 0, 12)) +>this : Symbol(C, Decl(privateNamesAndGenericClasses-2.ts, 0, 0)) + } +} + +let a = new C(3); +>a : Symbol(a, Decl(privateNamesAndGenericClasses-2.ts, 18, 3)) +>C : Symbol(C, Decl(privateNamesAndGenericClasses-2.ts, 0, 0)) + +let b = new C("hello"); +>b : Symbol(b, Decl(privateNamesAndGenericClasses-2.ts, 19, 3)) +>C : Symbol(C, Decl(privateNamesAndGenericClasses-2.ts, 0, 0)) + +a.baz = 5 // OK +>a.baz : Symbol(C.baz, Decl(privateNamesAndGenericClasses-2.ts, 8, 5), Decl(privateNamesAndGenericClasses-2.ts, 12, 5)) +>a : Symbol(a, Decl(privateNamesAndGenericClasses-2.ts, 18, 3)) +>baz : Symbol(C.baz, Decl(privateNamesAndGenericClasses-2.ts, 8, 5), Decl(privateNamesAndGenericClasses-2.ts, 12, 5)) + +const x: number = a.baz // OK +>x : Symbol(x, Decl(privateNamesAndGenericClasses-2.ts, 22, 5)) +>a.baz : Symbol(C.baz, Decl(privateNamesAndGenericClasses-2.ts, 8, 5), Decl(privateNamesAndGenericClasses-2.ts, 12, 5)) +>a : Symbol(a, Decl(privateNamesAndGenericClasses-2.ts, 18, 3)) +>baz : Symbol(C.baz, Decl(privateNamesAndGenericClasses-2.ts, 8, 5), Decl(privateNamesAndGenericClasses-2.ts, 12, 5)) + +a.#foo; // Error +>a : Symbol(a, Decl(privateNamesAndGenericClasses-2.ts, 18, 3)) + +a = b; // Error +>a : Symbol(a, Decl(privateNamesAndGenericClasses-2.ts, 18, 3)) +>b : Symbol(b, Decl(privateNamesAndGenericClasses-2.ts, 19, 3)) + +b = a; // Error +>b : Symbol(b, Decl(privateNamesAndGenericClasses-2.ts, 19, 3)) +>a : Symbol(a, Decl(privateNamesAndGenericClasses-2.ts, 18, 3)) + diff --git a/tests/baselines/reference/privateNamesAndGenericClasses-2.types b/tests/baselines/reference/privateNamesAndGenericClasses-2.types new file mode 100644 index 0000000000000..42f5b237d06fa --- /dev/null +++ b/tests/baselines/reference/privateNamesAndGenericClasses-2.types @@ -0,0 +1,89 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts === +class C { +>C : C + + #foo: T; +>#foo : T + + #bar(): T { +>#bar : () => T + + return this.#foo; +>this.#foo : T +>this : this + } + constructor(t: T) { +>t : T + + this.#foo = t; +>this.#foo = t : T +>this.#foo : T +>this : this +>t : T + + t = this.#bar(); +>t = this.#bar() : T +>t : T +>this.#bar() : T +>this.#bar : () => T +>this : this + } + set baz(t: T) { +>baz : T +>t : T + + this.#foo = t; +>this.#foo = t : T +>this.#foo : T +>this : this +>t : T + + } + get baz(): T { +>baz : T + + return this.#foo; +>this.#foo : T +>this : this + } +} + +let a = new C(3); +>a : C +>new C(3) : C +>C : typeof C +>3 : 3 + +let b = new C("hello"); +>b : C +>new C("hello") : C +>C : typeof C +>"hello" : "hello" + +a.baz = 5 // OK +>a.baz = 5 : 5 +>a.baz : number +>a : C +>baz : number +>5 : 5 + +const x: number = a.baz // OK +>x : number +>a.baz : number +>a : C +>baz : number + +a.#foo; // Error +>a.#foo : any +>a : C + +a = b; // Error +>a = b : C +>a : C +>b : C + +b = a; // Error +>b = a : C +>b : C +>a : C + diff --git a/tests/baselines/reference/privateNamesAndIndexedAccess.errors.txt b/tests/baselines/reference/privateNamesAndIndexedAccess.errors.txt new file mode 100644 index 0000000000000..95b8ab2a61bf7 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndIndexedAccess.errors.txt @@ -0,0 +1,39 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts(7,28): error TS1005: ']' expected. +tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts(7,28): error TS2300: Duplicate identifier '#bar'. +tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts(7,28): error TS2717: Subsequent property declarations must have the same type. Property '#bar' must be of type 'number', but here has type 'any'. +tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts(7,32): error TS1005: ';' expected. +tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts(7,34): error TS1068: Unexpected token. A constructor, method, accessor, or property was expected. +tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts(7,36): error TS7008: Member '3' implicitly has an 'any' type. +tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts(9,28): error TS2339: Property '#bar' does not exist on type 'C'. +tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts(11,1): error TS1128: Declaration or statement expected. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts (8 errors) ==== + class C { + foo = 3; + #bar = 3; + constructor () { + const ok: C["foo"] = 3; + // not supported yet, could support in future: + const badForNow: C[#bar] = 3; // Error + ~~~~ +!!! error TS1005: ']' expected. + ~~~~ +!!! error TS2300: Duplicate identifier '#bar'. + ~~~~ +!!! error TS2717: Subsequent property declarations must have the same type. Property '#bar' must be of type 'number', but here has type 'any'. + ~ +!!! error TS1005: ';' expected. + ~ +!!! error TS1068: Unexpected token. A constructor, method, accessor, or property was expected. + ~ +!!! error TS7008: Member '3' implicitly has an 'any' type. + // will never use this syntax, already taken: + const badAlways: C["#bar"] = 3; // Error + ~~~~~~ +!!! error TS2339: Property '#bar' does not exist on type 'C'. + } + } + ~ +!!! error TS1128: Declaration or statement expected. + \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesAndIndexedAccess.js b/tests/baselines/reference/privateNamesAndIndexedAccess.js new file mode 100644 index 0000000000000..b03c0f9ececeb --- /dev/null +++ b/tests/baselines/reference/privateNamesAndIndexedAccess.js @@ -0,0 +1,27 @@ +//// [privateNamesAndIndexedAccess.ts] +class C { + foo = 3; + #bar = 3; + constructor () { + const ok: C["foo"] = 3; + // not supported yet, could support in future: + const badForNow: C[#bar] = 3; // Error + // will never use this syntax, already taken: + const badAlways: C["#bar"] = 3; // Error + } +} + + +//// [privateNamesAndIndexedAccess.js] +"use strict"; +class C { + constructor() { + this.foo = 3; + this.#bar = 3; + // will never use this syntax, already taken: + this.badAlways = 3; // Error + const ok = 3; + // not supported yet, could support in future: + const badForNow; + } +} diff --git a/tests/baselines/reference/privateNamesAndIndexedAccess.symbols b/tests/baselines/reference/privateNamesAndIndexedAccess.symbols new file mode 100644 index 0000000000000..43a743810dca6 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndIndexedAccess.symbols @@ -0,0 +1,29 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts === +class C { +>C : Symbol(C, Decl(privateNamesAndIndexedAccess.ts, 0, 0)) + + foo = 3; +>foo : Symbol(C.foo, Decl(privateNamesAndIndexedAccess.ts, 0, 9)) + + #bar = 3; +>#bar : Symbol(C.#bar, Decl(privateNamesAndIndexedAccess.ts, 1, 12), Decl(privateNamesAndIndexedAccess.ts, 6, 27)) + + constructor () { + const ok: C["foo"] = 3; +>ok : Symbol(ok, Decl(privateNamesAndIndexedAccess.ts, 4, 13)) +>C : Symbol(C, Decl(privateNamesAndIndexedAccess.ts, 0, 0)) + + // not supported yet, could support in future: + const badForNow: C[#bar] = 3; // Error +>badForNow : Symbol(badForNow, Decl(privateNamesAndIndexedAccess.ts, 6, 13)) +>C : Symbol(C, Decl(privateNamesAndIndexedAccess.ts, 0, 0)) +>#bar : Symbol(C.#bar, Decl(privateNamesAndIndexedAccess.ts, 1, 12), Decl(privateNamesAndIndexedAccess.ts, 6, 27)) +>3 : Symbol(C[3], Decl(privateNamesAndIndexedAccess.ts, 6, 34)) + + // will never use this syntax, already taken: + const badAlways: C["#bar"] = 3; // Error +>badAlways : Symbol(C.badAlways, Decl(privateNamesAndIndexedAccess.ts, 6, 37)) +>C : Symbol(C, Decl(privateNamesAndIndexedAccess.ts, 0, 0)) + } +} + diff --git a/tests/baselines/reference/privateNamesAndIndexedAccess.types b/tests/baselines/reference/privateNamesAndIndexedAccess.types new file mode 100644 index 0000000000000..84ac9d43ffed9 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndIndexedAccess.types @@ -0,0 +1,30 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts === +class C { +>C : C + + foo = 3; +>foo : number +>3 : 3 + + #bar = 3; +>#bar : number +>3 : 3 + + constructor () { + const ok: C["foo"] = 3; +>ok : number +>3 : 3 + + // not supported yet, could support in future: + const badForNow: C[#bar] = 3; // Error +>badForNow : C[] +>#bar : number +>3 : any + + // will never use this syntax, already taken: + const badAlways: C["#bar"] = 3; // Error +>badAlways : any +>3 : 3 + } +} + diff --git a/tests/baselines/reference/privateNamesAndMethods.js b/tests/baselines/reference/privateNamesAndMethods.js new file mode 100644 index 0000000000000..8ca4192b12fd0 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndMethods.js @@ -0,0 +1,60 @@ +//// [privateNamesAndMethods.ts] +class A { + #foo(a: number) {} + async #bar(a: number) {} + async *#baz(a: number) { + return 3; + } + #_quux: number; + get #quux (): number { + return this.#_quux; + } + set #quux (val: number) { + this.#_quux = val; + } + constructor () { + this.#foo(30); + this.#bar(30); + this.#bar(30); + this.#quux = this.#quux + 1; + this.#quux++; + } +} + +class B extends A { + #foo(a: string) {} + constructor () { + super(); + this.#foo("str"); + } +} + + +//// [privateNamesAndMethods.js] +class A { + #foo(a) { } + async #bar(a) { } + async *#baz(a) { + return 3; + } + get #quux() { + return this.#_quux; + } + set #quux(val) { + this.#_quux = val; + } + constructor() { + this.#foo(30); + this.#bar(30); + this.#bar(30); + this.#quux = this.#quux + 1; + this.#quux++; + } +} +class B extends A { + #foo(a) { } + constructor() { + super(); + this.#foo("str"); + } +} diff --git a/tests/baselines/reference/privateNamesAndMethods.symbols b/tests/baselines/reference/privateNamesAndMethods.symbols new file mode 100644 index 0000000000000..817f1dcd31112 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndMethods.symbols @@ -0,0 +1,80 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndMethods.ts === +class A { +>A : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) + + #foo(a: number) {} +>#foo : Symbol(A.#foo, Decl(privateNamesAndMethods.ts, 0, 9)) +>a : Symbol(a, Decl(privateNamesAndMethods.ts, 1, 9)) + + async #bar(a: number) {} +>#bar : Symbol(A.#bar, Decl(privateNamesAndMethods.ts, 1, 22)) +>a : Symbol(a, Decl(privateNamesAndMethods.ts, 2, 15)) + + async *#baz(a: number) { +>#baz : Symbol(A.#baz, Decl(privateNamesAndMethods.ts, 2, 28)) +>a : Symbol(a, Decl(privateNamesAndMethods.ts, 3, 16)) + + return 3; + } + #_quux: number; +>#_quux : Symbol(A.#_quux, Decl(privateNamesAndMethods.ts, 5, 5)) + + get #quux (): number { +>#quux : Symbol(A.#quux, Decl(privateNamesAndMethods.ts, 6, 19), Decl(privateNamesAndMethods.ts, 9, 5)) + + return this.#_quux; +>this.#_quux : Symbol(A.#_quux, Decl(privateNamesAndMethods.ts, 5, 5)) +>this : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) + } + set #quux (val: number) { +>#quux : Symbol(A.#quux, Decl(privateNamesAndMethods.ts, 6, 19), Decl(privateNamesAndMethods.ts, 9, 5)) +>val : Symbol(val, Decl(privateNamesAndMethods.ts, 10, 15)) + + this.#_quux = val; +>this.#_quux : Symbol(A.#_quux, Decl(privateNamesAndMethods.ts, 5, 5)) +>this : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) +>val : Symbol(val, Decl(privateNamesAndMethods.ts, 10, 15)) + } + constructor () { + this.#foo(30); +>this.#foo : Symbol(A.#foo, Decl(privateNamesAndMethods.ts, 0, 9)) +>this : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) + + this.#bar(30); +>this.#bar : Symbol(A.#bar, Decl(privateNamesAndMethods.ts, 1, 22)) +>this : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) + + this.#bar(30); +>this.#bar : Symbol(A.#bar, Decl(privateNamesAndMethods.ts, 1, 22)) +>this : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) + + this.#quux = this.#quux + 1; +>this.#quux : Symbol(A.#quux, Decl(privateNamesAndMethods.ts, 6, 19), Decl(privateNamesAndMethods.ts, 9, 5)) +>this : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) +>this.#quux : Symbol(A.#quux, Decl(privateNamesAndMethods.ts, 6, 19), Decl(privateNamesAndMethods.ts, 9, 5)) +>this : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) + + this.#quux++; +>this.#quux : Symbol(A.#quux, Decl(privateNamesAndMethods.ts, 6, 19), Decl(privateNamesAndMethods.ts, 9, 5)) +>this : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) + } +} + +class B extends A { +>B : Symbol(B, Decl(privateNamesAndMethods.ts, 20, 1)) +>A : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) + + #foo(a: string) {} +>#foo : Symbol(B.#foo, Decl(privateNamesAndMethods.ts, 22, 19)) +>a : Symbol(a, Decl(privateNamesAndMethods.ts, 23, 9)) + + constructor () { + super(); +>super : Symbol(A, Decl(privateNamesAndMethods.ts, 0, 0)) + + this.#foo("str"); +>this.#foo : Symbol(B.#foo, Decl(privateNamesAndMethods.ts, 22, 19)) +>this : Symbol(B, Decl(privateNamesAndMethods.ts, 20, 1)) + } +} + diff --git a/tests/baselines/reference/privateNamesAndMethods.types b/tests/baselines/reference/privateNamesAndMethods.types new file mode 100644 index 0000000000000..847ee901d527b --- /dev/null +++ b/tests/baselines/reference/privateNamesAndMethods.types @@ -0,0 +1,95 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndMethods.ts === +class A { +>A : A + + #foo(a: number) {} +>#foo : (a: number) => void +>a : number + + async #bar(a: number) {} +>#bar : (a: number) => Promise +>a : number + + async *#baz(a: number) { +>#baz : (a: number) => AsyncIterableIterator +>a : number + + return 3; +>3 : 3 + } + #_quux: number; +>#_quux : number + + get #quux (): number { +>#quux : number + + return this.#_quux; +>this.#_quux : number +>this : this + } + set #quux (val: number) { +>#quux : number +>val : number + + this.#_quux = val; +>this.#_quux = val : number +>this.#_quux : number +>this : this +>val : number + } + constructor () { + this.#foo(30); +>this.#foo(30) : void +>this.#foo : (a: number) => void +>this : this +>30 : 30 + + this.#bar(30); +>this.#bar(30) : Promise +>this.#bar : (a: number) => Promise +>this : this +>30 : 30 + + this.#bar(30); +>this.#bar(30) : Promise +>this.#bar : (a: number) => Promise +>this : this +>30 : 30 + + this.#quux = this.#quux + 1; +>this.#quux = this.#quux + 1 : number +>this.#quux : number +>this : this +>this.#quux + 1 : number +>this.#quux : number +>this : this +>1 : 1 + + this.#quux++; +>this.#quux++ : number +>this.#quux : number +>this : this + } +} + +class B extends A { +>B : B +>A : A + + #foo(a: string) {} +>#foo : (a: string) => void +>a : string + + constructor () { + super(); +>super() : void +>super : typeof A + + this.#foo("str"); +>this.#foo("str") : void +>this.#foo : (a: string) => void +>this : this +>"str" : "str" + } +} + diff --git a/tests/baselines/reference/privateNamesAndStaticFields.js b/tests/baselines/reference/privateNamesAndStaticFields.js new file mode 100644 index 0000000000000..00f1c5fbe5a0a --- /dev/null +++ b/tests/baselines/reference/privateNamesAndStaticFields.js @@ -0,0 +1,50 @@ +//// [privateNamesAndStaticFields.ts] +// @target es6 + +class A { + static #foo: number; + constructor () { + A.#foo = 3; + } +} + +class B extends A { + static #foo: string; + constructor () { + super(); + B.#foo = "some string"; + } +} + + +//// [privateNamesAndStaticFields.js] +"use strict"; +// @target es6 +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var A = /** @class */ (function () { + function A() { + A.#foo = 3; + } + return A; +}()); +var B = /** @class */ (function (_super) { + __extends(B, _super); + function B() { + var _this = _super.call(this) || this; + B.#foo = "some string"; + return _this; + } + return B; +}(A)); diff --git a/tests/baselines/reference/privateNamesAndStaticFields.symbols b/tests/baselines/reference/privateNamesAndStaticFields.symbols new file mode 100644 index 0000000000000..5898928bfb741 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndStaticFields.symbols @@ -0,0 +1,33 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticFields.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNamesAndStaticFields.ts, 0, 0)) + + static #foo: number; +>#foo : Symbol(A.#foo, Decl(privateNamesAndStaticFields.ts, 2, 9)) + + constructor () { + A.#foo = 3; +>A.#foo : Symbol(A.#foo, Decl(privateNamesAndStaticFields.ts, 2, 9)) +>A : Symbol(A, Decl(privateNamesAndStaticFields.ts, 0, 0)) + } +} + +class B extends A { +>B : Symbol(B, Decl(privateNamesAndStaticFields.ts, 7, 1)) +>A : Symbol(A, Decl(privateNamesAndStaticFields.ts, 0, 0)) + + static #foo: string; +>#foo : Symbol(B.#foo, Decl(privateNamesAndStaticFields.ts, 9, 19)) + + constructor () { + super(); +>super : Symbol(A, Decl(privateNamesAndStaticFields.ts, 0, 0)) + + B.#foo = "some string"; +>B.#foo : Symbol(B.#foo, Decl(privateNamesAndStaticFields.ts, 9, 19)) +>B : Symbol(B, Decl(privateNamesAndStaticFields.ts, 7, 1)) + } +} + diff --git a/tests/baselines/reference/privateNamesAndStaticFields.types b/tests/baselines/reference/privateNamesAndStaticFields.types new file mode 100644 index 0000000000000..ba630cbcf7709 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndStaticFields.types @@ -0,0 +1,38 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticFields.ts === +// @target es6 + +class A { +>A : A + + static #foo: number; +>#foo : number + + constructor () { + A.#foo = 3; +>A.#foo = 3 : 3 +>A.#foo : number +>A : typeof A +>3 : 3 + } +} + +class B extends A { +>B : B +>A : A + + static #foo: string; +>#foo : string + + constructor () { + super(); +>super() : void +>super : typeof A + + B.#foo = "some string"; +>B.#foo = "some string" : "some string" +>B.#foo : string +>B : typeof B +>"some string" : "some string" + } +} + diff --git a/tests/baselines/reference/privateNamesAndStaticMethods.js b/tests/baselines/reference/privateNamesAndStaticMethods.js new file mode 100644 index 0000000000000..7de87a421fe9d --- /dev/null +++ b/tests/baselines/reference/privateNamesAndStaticMethods.js @@ -0,0 +1,61 @@ +//// [privateNamesAndStaticMethods.ts] +class A { + static #foo(a: number) {} + static async #bar(a: number) {} + static async *#baz(a: number) { + return 3; + } + static #_quux: number; + static get #quux (): number { + return this.#_quux; + } + static set #quux (val: number) { + this.#_quux = val; + } + constructor () { + A.#foo(30); + A.#bar(30); + A.#bar(30); + A.#quux = A.#quux + 1; + A.#quux++; + } +} + +class B extends A { + static #foo(a: string) {} + constructor () { + super(); + B.#foo("str"); + } +} + + +//// [privateNamesAndStaticMethods.js] +"use strict"; +class A { + static #foo(a) { } + static async #bar(a) { } + static async *#baz(a) { + return 3; + } + static get #quux() { + return this.#_quux; + } + static set #quux(val) { + this.#_quux = val; + } + constructor() { + A.#foo(30); + A.#bar(30); + A.#bar(30); + A.#quux = A.#quux + 1; + A.#quux++; + } +} +class B extends A { + static #foo(a) { } + constructor() { + super(); + B.#foo("str"); + } +} diff --git a/tests/baselines/reference/privateNamesAndStaticMethods.symbols b/tests/baselines/reference/privateNamesAndStaticMethods.symbols new file mode 100644 index 0000000000000..57d684a70696d --- /dev/null +++ b/tests/baselines/reference/privateNamesAndStaticMethods.symbols @@ -0,0 +1,80 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticMethods.ts === +class A { +>A : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) + + static #foo(a: number) {} +>#foo : Symbol(A.#foo, Decl(privateNamesAndStaticMethods.ts, 0, 9)) +>a : Symbol(a, Decl(privateNamesAndStaticMethods.ts, 1, 16)) + + static async #bar(a: number) {} +>#bar : Symbol(A.#bar, Decl(privateNamesAndStaticMethods.ts, 1, 29)) +>a : Symbol(a, Decl(privateNamesAndStaticMethods.ts, 2, 22)) + + static async *#baz(a: number) { +>#baz : Symbol(A.#baz, Decl(privateNamesAndStaticMethods.ts, 2, 35)) +>a : Symbol(a, Decl(privateNamesAndStaticMethods.ts, 3, 23)) + + return 3; + } + static #_quux: number; +>#_quux : Symbol(A.#_quux, Decl(privateNamesAndStaticMethods.ts, 5, 5)) + + static get #quux (): number { +>#quux : Symbol(A.#quux, Decl(privateNamesAndStaticMethods.ts, 6, 26), Decl(privateNamesAndStaticMethods.ts, 9, 5)) + + return this.#_quux; +>this.#_quux : Symbol(A.#_quux, Decl(privateNamesAndStaticMethods.ts, 5, 5)) +>this : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) + } + static set #quux (val: number) { +>#quux : Symbol(A.#quux, Decl(privateNamesAndStaticMethods.ts, 6, 26), Decl(privateNamesAndStaticMethods.ts, 9, 5)) +>val : Symbol(val, Decl(privateNamesAndStaticMethods.ts, 10, 22)) + + this.#_quux = val; +>this.#_quux : Symbol(A.#_quux, Decl(privateNamesAndStaticMethods.ts, 5, 5)) +>this : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) +>val : Symbol(val, Decl(privateNamesAndStaticMethods.ts, 10, 22)) + } + constructor () { + A.#foo(30); +>A.#foo : Symbol(A.#foo, Decl(privateNamesAndStaticMethods.ts, 0, 9)) +>A : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) + + A.#bar(30); +>A.#bar : Symbol(A.#bar, Decl(privateNamesAndStaticMethods.ts, 1, 29)) +>A : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) + + A.#bar(30); +>A.#bar : Symbol(A.#bar, Decl(privateNamesAndStaticMethods.ts, 1, 29)) +>A : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) + + A.#quux = A.#quux + 1; +>A.#quux : Symbol(A.#quux, Decl(privateNamesAndStaticMethods.ts, 6, 26), Decl(privateNamesAndStaticMethods.ts, 9, 5)) +>A : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) +>A.#quux : Symbol(A.#quux, Decl(privateNamesAndStaticMethods.ts, 6, 26), Decl(privateNamesAndStaticMethods.ts, 9, 5)) +>A : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) + + A.#quux++; +>A.#quux : Symbol(A.#quux, Decl(privateNamesAndStaticMethods.ts, 6, 26), Decl(privateNamesAndStaticMethods.ts, 9, 5)) +>A : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) + } +} + +class B extends A { +>B : Symbol(B, Decl(privateNamesAndStaticMethods.ts, 20, 1)) +>A : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) + + static #foo(a: string) {} +>#foo : Symbol(B.#foo, Decl(privateNamesAndStaticMethods.ts, 22, 19)) +>a : Symbol(a, Decl(privateNamesAndStaticMethods.ts, 23, 16)) + + constructor () { + super(); +>super : Symbol(A, Decl(privateNamesAndStaticMethods.ts, 0, 0)) + + B.#foo("str"); +>B.#foo : Symbol(B.#foo, Decl(privateNamesAndStaticMethods.ts, 22, 19)) +>B : Symbol(B, Decl(privateNamesAndStaticMethods.ts, 20, 1)) + } +} + diff --git a/tests/baselines/reference/privateNamesAndStaticMethods.types b/tests/baselines/reference/privateNamesAndStaticMethods.types new file mode 100644 index 0000000000000..3a4a89dbd754d --- /dev/null +++ b/tests/baselines/reference/privateNamesAndStaticMethods.types @@ -0,0 +1,95 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticMethods.ts === +class A { +>A : A + + static #foo(a: number) {} +>#foo : (a: number) => void +>a : number + + static async #bar(a: number) {} +>#bar : (a: number) => Promise +>a : number + + static async *#baz(a: number) { +>#baz : (a: number) => AsyncIterableIterator +>a : number + + return 3; +>3 : 3 + } + static #_quux: number; +>#_quux : number + + static get #quux (): number { +>#quux : number + + return this.#_quux; +>this.#_quux : number +>this : typeof A + } + static set #quux (val: number) { +>#quux : number +>val : number + + this.#_quux = val; +>this.#_quux = val : number +>this.#_quux : number +>this : typeof A +>val : number + } + constructor () { + A.#foo(30); +>A.#foo(30) : void +>A.#foo : (a: number) => void +>A : typeof A +>30 : 30 + + A.#bar(30); +>A.#bar(30) : Promise +>A.#bar : (a: number) => Promise +>A : typeof A +>30 : 30 + + A.#bar(30); +>A.#bar(30) : Promise +>A.#bar : (a: number) => Promise +>A : typeof A +>30 : 30 + + A.#quux = A.#quux + 1; +>A.#quux = A.#quux + 1 : number +>A.#quux : number +>A : typeof A +>A.#quux + 1 : number +>A.#quux : number +>A : typeof A +>1 : 1 + + A.#quux++; +>A.#quux++ : number +>A.#quux : number +>A : typeof A + } +} + +class B extends A { +>B : B +>A : A + + static #foo(a: string) {} +>#foo : (a: string) => void +>a : string + + constructor () { + super(); +>super() : void +>super : typeof A + + B.#foo("str"); +>B.#foo("str") : void +>B.#foo : (a: string) => void +>B : typeof B +>"str" : "str" + } +} + diff --git a/tests/baselines/reference/privateNamesAndkeyof.js b/tests/baselines/reference/privateNamesAndkeyof.js new file mode 100644 index 0000000000000..d6dbd5d92f796 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndkeyof.js @@ -0,0 +1,23 @@ +//// [privateNamesAndkeyof.ts] +// @target es6 + +class A { + #foo = 3; + bar = 3; + baz = 3; +} + +type T = keyof A // should not include '#foo' + + +//// [privateNamesAndkeyof.js] +"use strict"; +// @target es6 +var A = /** @class */ (function () { + function A() { + this.#foo = 3; + this.bar = 3; + this.baz = 3; + } + return A; +}()); diff --git a/tests/baselines/reference/privateNamesAndkeyof.symbols b/tests/baselines/reference/privateNamesAndkeyof.symbols new file mode 100644 index 0000000000000..3b633505522a1 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndkeyof.symbols @@ -0,0 +1,20 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndkeyof.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNamesAndkeyof.ts, 0, 0)) + + #foo = 3; +>#foo : Symbol(A.#foo, Decl(privateNamesAndkeyof.ts, 2, 9)) + + bar = 3; +>bar : Symbol(A.bar, Decl(privateNamesAndkeyof.ts, 3, 13)) + + baz = 3; +>baz : Symbol(A.baz, Decl(privateNamesAndkeyof.ts, 4, 12)) +} + +type T = keyof A // should not include '#foo' +>T : Symbol(T, Decl(privateNamesAndkeyof.ts, 6, 1)) +>A : Symbol(A, Decl(privateNamesAndkeyof.ts, 0, 0)) + diff --git a/tests/baselines/reference/privateNamesAndkeyof.types b/tests/baselines/reference/privateNamesAndkeyof.types new file mode 100644 index 0000000000000..f8d3d99de7369 --- /dev/null +++ b/tests/baselines/reference/privateNamesAndkeyof.types @@ -0,0 +1,22 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAndkeyof.ts === +// @target es6 + +class A { +>A : A + + #foo = 3; +>#foo : number +>3 : 3 + + bar = 3; +>bar : number +>3 : 3 + + baz = 3; +>baz : number +>3 : 3 +} + +type T = keyof A // should not include '#foo' +>T : "bar" | "baz" + diff --git a/tests/baselines/reference/privateNamesInGenericClasses.errors.txt b/tests/baselines/reference/privateNamesInGenericClasses.errors.txt new file mode 100644 index 0000000000000..7e5435ffa2c58 --- /dev/null +++ b/tests/baselines/reference/privateNamesInGenericClasses.errors.txt @@ -0,0 +1,32 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts(10,3): error TS2339: Property '#foo' does not exist on type 'C'. +tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts(10,3): error TS18007: Property '#foo' is not accessible outside class 'C' because it has a private name. +tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts(11,1): error TS2322: Type 'C' is not assignable to type 'C'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts(12,1): error TS2322: Type 'C' is not assignable to type 'C'. + Type 'number' is not assignable to type 'string'. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts (4 errors) ==== + class C { + #foo: T; + bar(x: C) { return x.#foo; } // OK + baz(x: C) { return x.#foo; } // OK + quux(x: C) { return x.#foo; } // OK + } + + declare let a: C; + declare let b: C; + a.#foo; // Error + ~~~~ +!!! error TS2339: Property '#foo' does not exist on type 'C'. + ~~~~ +!!! error TS18007: Property '#foo' is not accessible outside class 'C' because it has a private name. + a = b; // Error + ~ +!!! error TS2322: Type 'C' is not assignable to type 'C'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. + b = a; // Error + ~ +!!! error TS2322: Type 'C' is not assignable to type 'C'. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesInGenericClasses.js b/tests/baselines/reference/privateNamesInGenericClasses.js new file mode 100644 index 0000000000000..8f547b1a659a8 --- /dev/null +++ b/tests/baselines/reference/privateNamesInGenericClasses.js @@ -0,0 +1,25 @@ +//// [privateNamesInGenericClasses.ts] +class C { + #foo: T; + bar(x: C) { return x.#foo; } // OK + baz(x: C) { return x.#foo; } // OK + quux(x: C) { return x.#foo; } // OK +} + +declare let a: C; +declare let b: C; +a.#foo; // Error +a = b; // Error +b = a; // Error + + +//// [privateNamesInGenericClasses.js] +"use strict"; +class C { + bar(x) { return x.#foo; } // OK + baz(x) { return x.#foo; } // OK + quux(x) { return x.#foo; } // OK +} +a.#foo; // Error +a = b; // Error +b = a; // Error diff --git a/tests/baselines/reference/privateNamesInGenericClasses.symbols b/tests/baselines/reference/privateNamesInGenericClasses.symbols new file mode 100644 index 0000000000000..c697c06390869 --- /dev/null +++ b/tests/baselines/reference/privateNamesInGenericClasses.symbols @@ -0,0 +1,51 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts === +class C { +>C : Symbol(C, Decl(privateNamesInGenericClasses.ts, 0, 0)) +>T : Symbol(T, Decl(privateNamesInGenericClasses.ts, 0, 8)) + + #foo: T; +>#foo : Symbol(C.#foo, Decl(privateNamesInGenericClasses.ts, 0, 12)) +>T : Symbol(T, Decl(privateNamesInGenericClasses.ts, 0, 8)) + + bar(x: C) { return x.#foo; } // OK +>bar : Symbol(C.bar, Decl(privateNamesInGenericClasses.ts, 1, 12)) +>x : Symbol(x, Decl(privateNamesInGenericClasses.ts, 2, 8)) +>C : Symbol(C, Decl(privateNamesInGenericClasses.ts, 0, 0)) +>T : Symbol(T, Decl(privateNamesInGenericClasses.ts, 0, 8)) +>x.#foo : Symbol(C.#foo, Decl(privateNamesInGenericClasses.ts, 0, 12)) +>x : Symbol(x, Decl(privateNamesInGenericClasses.ts, 2, 8)) + + baz(x: C) { return x.#foo; } // OK +>baz : Symbol(C.baz, Decl(privateNamesInGenericClasses.ts, 2, 35)) +>x : Symbol(x, Decl(privateNamesInGenericClasses.ts, 3, 8)) +>C : Symbol(C, Decl(privateNamesInGenericClasses.ts, 0, 0)) +>x.#foo : Symbol(C.#foo, Decl(privateNamesInGenericClasses.ts, 0, 12)) +>x : Symbol(x, Decl(privateNamesInGenericClasses.ts, 3, 8)) + + quux(x: C) { return x.#foo; } // OK +>quux : Symbol(C.quux, Decl(privateNamesInGenericClasses.ts, 3, 40)) +>x : Symbol(x, Decl(privateNamesInGenericClasses.ts, 4, 9)) +>C : Symbol(C, Decl(privateNamesInGenericClasses.ts, 0, 0)) +>x.#foo : Symbol(C.#foo, Decl(privateNamesInGenericClasses.ts, 0, 12)) +>x : Symbol(x, Decl(privateNamesInGenericClasses.ts, 4, 9)) +} + +declare let a: C; +>a : Symbol(a, Decl(privateNamesInGenericClasses.ts, 7, 11)) +>C : Symbol(C, Decl(privateNamesInGenericClasses.ts, 0, 0)) + +declare let b: C; +>b : Symbol(b, Decl(privateNamesInGenericClasses.ts, 8, 11)) +>C : Symbol(C, Decl(privateNamesInGenericClasses.ts, 0, 0)) + +a.#foo; // Error +>a : Symbol(a, Decl(privateNamesInGenericClasses.ts, 7, 11)) + +a = b; // Error +>a : Symbol(a, Decl(privateNamesInGenericClasses.ts, 7, 11)) +>b : Symbol(b, Decl(privateNamesInGenericClasses.ts, 8, 11)) + +b = a; // Error +>b : Symbol(b, Decl(privateNamesInGenericClasses.ts, 8, 11)) +>a : Symbol(a, Decl(privateNamesInGenericClasses.ts, 7, 11)) + diff --git a/tests/baselines/reference/privateNamesInGenericClasses.types b/tests/baselines/reference/privateNamesInGenericClasses.types new file mode 100644 index 0000000000000..e0a29a45492c1 --- /dev/null +++ b/tests/baselines/reference/privateNamesInGenericClasses.types @@ -0,0 +1,46 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts === +class C { +>C : C + + #foo: T; +>#foo : T + + bar(x: C) { return x.#foo; } // OK +>bar : (x: C) => T +>x : C +>x.#foo : T +>x : C + + baz(x: C) { return x.#foo; } // OK +>baz : (x: C) => number +>x : C +>x.#foo : number +>x : C + + quux(x: C) { return x.#foo; } // OK +>quux : (x: C) => string +>x : C +>x.#foo : string +>x : C +} + +declare let a: C; +>a : C + +declare let b: C; +>b : C + +a.#foo; // Error +>a.#foo : any +>a : C + +a = b; // Error +>a = b : C +>a : C +>b : C + +b = a; // Error +>b = a : C +>b : C +>a : C + diff --git a/tests/baselines/reference/privateNamesInNestedClasses.errors.txt b/tests/baselines/reference/privateNamesInNestedClasses.errors.txt new file mode 100644 index 0000000000000..3f6efdf5155f8 --- /dev/null +++ b/tests/baselines/reference/privateNamesInNestedClasses.errors.txt @@ -0,0 +1,36 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesInNestedClasses.ts(13,18): error TS2339: Property '#foo' does not exist on type 'A'. +tests/cases/conformance/classes/members/privateNames/privateNamesInNestedClasses.ts(13,18): error TS18008: This usage of '#foo' refers to the private member declared in its enclosing class. While type 'B' has a private member with the same spelling, its declaration and accessibility are distinct. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesInNestedClasses.ts (2 errors) ==== + // @target es6 + + class A { + #foo = "A's #foo"; + #bar = "A's #bar"; + method () { + class B { + #foo = "B's #foo"; + bar (a: any) { + a.#foo; // OK, no compile-time error, don't know what `a` is + } + baz (a: A) { + a.#foo; // compile-time error, shadowed + ~~~~ +!!! error TS2339: Property '#foo' does not exist on type 'A'. + ~~~~ +!!! error TS18008: This usage of '#foo' refers to the private member declared in its enclosing class. While type 'B' has a private member with the same spelling, its declaration and accessibility are distinct. + } + quux (b: B) { + b.#foo; // OK + } + } + const a = new A(); + new B().bar(a); + new B().baz(a); + const b = new B(); + new B().quux(b); + } + } + + new A().method(); \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesInNestedClasses.js b/tests/baselines/reference/privateNamesInNestedClasses.js new file mode 100644 index 0000000000000..acf6099d96c11 --- /dev/null +++ b/tests/baselines/reference/privateNamesInNestedClasses.js @@ -0,0 +1,62 @@ +//// [privateNamesInNestedClasses.ts] +// @target es6 + +class A { + #foo = "A's #foo"; + #bar = "A's #bar"; + method () { + class B { + #foo = "B's #foo"; + bar (a: any) { + a.#foo; // OK, no compile-time error, don't know what `a` is + } + baz (a: A) { + a.#foo; // compile-time error, shadowed + } + quux (b: B) { + b.#foo; // OK + } + } + const a = new A(); + new B().bar(a); + new B().baz(a); + const b = new B(); + new B().quux(b); + } +} + +new A().method(); + +//// [privateNamesInNestedClasses.js] +"use strict"; +// @target es6 +var A = /** @class */ (function () { + function A() { + this.#foo = "A's #foo"; + this.#bar = "A's #bar"; + } + A.prototype.method = function () { + var B = /** @class */ (function () { + function B() { + this.#foo = "B's #foo"; + } + B.prototype.bar = function (a) { + a.#foo; // OK, no compile-time error, don't know what `a` is + }; + B.prototype.baz = function (a) { + a.#foo; // compile-time error, shadowed + }; + B.prototype.quux = function (b) { + b.#foo; // OK + }; + return B; + }()); + var a = new A(); + new B().bar(a); + new B().baz(a); + var b = new B(); + new B().quux(b); + }; + return A; +}()); +new A().method(); diff --git a/tests/baselines/reference/privateNamesInNestedClasses.symbols b/tests/baselines/reference/privateNamesInNestedClasses.symbols new file mode 100644 index 0000000000000..14eaae87aa402 --- /dev/null +++ b/tests/baselines/reference/privateNamesInNestedClasses.symbols @@ -0,0 +1,79 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesInNestedClasses.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNamesInNestedClasses.ts, 0, 0)) + + #foo = "A's #foo"; +>#foo : Symbol(A.#foo, Decl(privateNamesInNestedClasses.ts, 2, 9)) + + #bar = "A's #bar"; +>#bar : Symbol(A.#bar, Decl(privateNamesInNestedClasses.ts, 3, 21)) + + method () { +>method : Symbol(A.method, Decl(privateNamesInNestedClasses.ts, 4, 21)) + + class B { +>B : Symbol(B, Decl(privateNamesInNestedClasses.ts, 5, 14)) + + #foo = "B's #foo"; +>#foo : Symbol(B.#foo, Decl(privateNamesInNestedClasses.ts, 6, 16)) + + bar (a: any) { +>bar : Symbol(B.bar, Decl(privateNamesInNestedClasses.ts, 7, 29)) +>a : Symbol(a, Decl(privateNamesInNestedClasses.ts, 8, 16)) + + a.#foo; // OK, no compile-time error, don't know what `a` is +>a : Symbol(a, Decl(privateNamesInNestedClasses.ts, 8, 16)) + } + baz (a: A) { +>baz : Symbol(B.baz, Decl(privateNamesInNestedClasses.ts, 10, 12)) +>a : Symbol(a, Decl(privateNamesInNestedClasses.ts, 11, 16)) +>A : Symbol(A, Decl(privateNamesInNestedClasses.ts, 0, 0)) + + a.#foo; // compile-time error, shadowed +>a : Symbol(a, Decl(privateNamesInNestedClasses.ts, 11, 16)) + } + quux (b: B) { +>quux : Symbol(B.quux, Decl(privateNamesInNestedClasses.ts, 13, 12)) +>b : Symbol(b, Decl(privateNamesInNestedClasses.ts, 14, 17)) +>B : Symbol(B, Decl(privateNamesInNestedClasses.ts, 5, 14)) + + b.#foo; // OK +>b.#foo : Symbol(B.#foo, Decl(privateNamesInNestedClasses.ts, 6, 16)) +>b : Symbol(b, Decl(privateNamesInNestedClasses.ts, 14, 17)) + } + } + const a = new A(); +>a : Symbol(a, Decl(privateNamesInNestedClasses.ts, 18, 12)) +>A : Symbol(A, Decl(privateNamesInNestedClasses.ts, 0, 0)) + + new B().bar(a); +>new B().bar : Symbol(B.bar, Decl(privateNamesInNestedClasses.ts, 7, 29)) +>B : Symbol(B, Decl(privateNamesInNestedClasses.ts, 5, 14)) +>bar : Symbol(B.bar, Decl(privateNamesInNestedClasses.ts, 7, 29)) +>a : Symbol(a, Decl(privateNamesInNestedClasses.ts, 18, 12)) + + new B().baz(a); +>new B().baz : Symbol(B.baz, Decl(privateNamesInNestedClasses.ts, 10, 12)) +>B : Symbol(B, Decl(privateNamesInNestedClasses.ts, 5, 14)) +>baz : Symbol(B.baz, Decl(privateNamesInNestedClasses.ts, 10, 12)) +>a : Symbol(a, Decl(privateNamesInNestedClasses.ts, 18, 12)) + + const b = new B(); +>b : Symbol(b, Decl(privateNamesInNestedClasses.ts, 21, 12)) +>B : Symbol(B, Decl(privateNamesInNestedClasses.ts, 5, 14)) + + new B().quux(b); +>new B().quux : Symbol(B.quux, Decl(privateNamesInNestedClasses.ts, 13, 12)) +>B : Symbol(B, Decl(privateNamesInNestedClasses.ts, 5, 14)) +>quux : Symbol(B.quux, Decl(privateNamesInNestedClasses.ts, 13, 12)) +>b : Symbol(b, Decl(privateNamesInNestedClasses.ts, 21, 12)) + } +} + +new A().method(); +>new A().method : Symbol(A.method, Decl(privateNamesInNestedClasses.ts, 4, 21)) +>A : Symbol(A, Decl(privateNamesInNestedClasses.ts, 0, 0)) +>method : Symbol(A.method, Decl(privateNamesInNestedClasses.ts, 4, 21)) + diff --git a/tests/baselines/reference/privateNamesInNestedClasses.types b/tests/baselines/reference/privateNamesInNestedClasses.types new file mode 100644 index 0000000000000..12986429358da --- /dev/null +++ b/tests/baselines/reference/privateNamesInNestedClasses.types @@ -0,0 +1,92 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesInNestedClasses.ts === +// @target es6 + +class A { +>A : A + + #foo = "A's #foo"; +>#foo : string +>"A's #foo" : "A's #foo" + + #bar = "A's #bar"; +>#bar : string +>"A's #bar" : "A's #bar" + + method () { +>method : () => void + + class B { +>B : B + + #foo = "B's #foo"; +>#foo : string +>"B's #foo" : "B's #foo" + + bar (a: any) { +>bar : (a: any) => void +>a : any + + a.#foo; // OK, no compile-time error, don't know what `a` is +>a.#foo : any +>a : any + } + baz (a: A) { +>baz : (a: A) => void +>a : A + + a.#foo; // compile-time error, shadowed +>a.#foo : any +>a : A + } + quux (b: B) { +>quux : (b: B) => void +>b : B + + b.#foo; // OK +>b.#foo : string +>b : B + } + } + const a = new A(); +>a : A +>new A() : A +>A : typeof A + + new B().bar(a); +>new B().bar(a) : void +>new B().bar : (a: any) => void +>new B() : B +>B : typeof B +>bar : (a: any) => void +>a : A + + new B().baz(a); +>new B().baz(a) : void +>new B().baz : (a: A) => void +>new B() : B +>B : typeof B +>baz : (a: A) => void +>a : A + + const b = new B(); +>b : B +>new B() : B +>B : typeof B + + new B().quux(b); +>new B().quux(b) : void +>new B().quux : (b: B) => void +>new B() : B +>B : typeof B +>quux : (b: B) => void +>b : B + } +} + +new A().method(); +>new A().method() : void +>new A().method : () => void +>new A() : A +>A : typeof A +>method : () => void + diff --git a/tests/baselines/reference/privateNamesNoAccessibilityModifiers.errors.txt b/tests/baselines/reference/privateNamesNoAccessibilityModifiers.errors.txt new file mode 100644 index 0000000000000..751ddafa1c669 --- /dev/null +++ b/tests/baselines/reference/privateNamesNoAccessibilityModifiers.errors.txt @@ -0,0 +1,21 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts(4,12): error TS18004: Accessibility modifiers cannot be used with private names. +tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts(5,13): error TS18004: Accessibility modifiers cannot be used with private names. +tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts(6,15): error TS18004: Accessibility modifiers cannot be used with private names. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts (3 errors) ==== + // @target es6 + + class A { + public #foo = 3; // Error + ~~~~ +!!! error TS18004: Accessibility modifiers cannot be used with private names. + private #bar = 3; // Error + ~~~~ +!!! error TS18004: Accessibility modifiers cannot be used with private names. + protected #baz = 3; // Error + ~~~~ +!!! error TS18004: Accessibility modifiers cannot be used with private names. + readonly #qux = 3; // OK + } + \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesNoAccessibilityModifiers.js b/tests/baselines/reference/privateNamesNoAccessibilityModifiers.js new file mode 100644 index 0000000000000..081090dbf645f --- /dev/null +++ b/tests/baselines/reference/privateNamesNoAccessibilityModifiers.js @@ -0,0 +1,23 @@ +//// [privateNamesNoAccessibilityModifiers.ts] +// @target es6 + +class A { + public #foo = 3; // Error + private #bar = 3; // Error + protected #baz = 3; // Error + readonly #qux = 3; // OK +} + + +//// [privateNamesNoAccessibilityModifiers.js] +"use strict"; +// @target es6 +var A = /** @class */ (function () { + function A() { + this.#foo = 3; // Error + this.#bar = 3; // Error + this.#baz = 3; // Error + this.#qux = 3; // OK + } + return A; +}()); diff --git a/tests/baselines/reference/privateNamesNoAccessibilityModifiers.symbols b/tests/baselines/reference/privateNamesNoAccessibilityModifiers.symbols new file mode 100644 index 0000000000000..49bd89a39842a --- /dev/null +++ b/tests/baselines/reference/privateNamesNoAccessibilityModifiers.symbols @@ -0,0 +1,19 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNamesNoAccessibilityModifiers.ts, 0, 0)) + + public #foo = 3; // Error +>#foo : Symbol(A.#foo, Decl(privateNamesNoAccessibilityModifiers.ts, 2, 9)) + + private #bar = 3; // Error +>#bar : Symbol(A.#bar, Decl(privateNamesNoAccessibilityModifiers.ts, 3, 20)) + + protected #baz = 3; // Error +>#baz : Symbol(A.#baz, Decl(privateNamesNoAccessibilityModifiers.ts, 4, 21)) + + readonly #qux = 3; // OK +>#qux : Symbol(A.#qux, Decl(privateNamesNoAccessibilityModifiers.ts, 5, 23)) +} + diff --git a/tests/baselines/reference/privateNamesNoAccessibilityModifiers.types b/tests/baselines/reference/privateNamesNoAccessibilityModifiers.types new file mode 100644 index 0000000000000..d727c9a2f2dc3 --- /dev/null +++ b/tests/baselines/reference/privateNamesNoAccessibilityModifiers.types @@ -0,0 +1,23 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts === +// @target es6 + +class A { +>A : A + + public #foo = 3; // Error +>#foo : number +>3 : 3 + + private #bar = 3; // Error +>#bar : number +>3 : 3 + + protected #baz = 3; // Error +>#baz : number +>3 : 3 + + readonly #qux = 3; // OK +>#qux : 3 +>3 : 3 +} + diff --git a/tests/baselines/reference/privateNamesNoConflictWhenInheriting.js b/tests/baselines/reference/privateNamesNoConflictWhenInheriting.js new file mode 100644 index 0000000000000..e25509c4c843a --- /dev/null +++ b/tests/baselines/reference/privateNamesNoConflictWhenInheriting.js @@ -0,0 +1,43 @@ +//// [privateNamesNoConflictWhenInheriting.ts] +// @target es6 + +class A { + #foo: number; +} + +class B extends A { + #foo: string; // OK: private names are unique to each class +} + +const b: A = new B() // OK + + +//// [privateNamesNoConflictWhenInheriting.js] +"use strict"; +// @target es6 +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var A = /** @class */ (function () { + function A() { + } + return A; +}()); +var B = /** @class */ (function (_super) { + __extends(B, _super); + function B() { + return _super !== null && _super.apply(this, arguments) || this; + } + return B; +}(A)); +var b = new B(); // OK diff --git a/tests/baselines/reference/privateNamesNoConflictWhenInheriting.symbols b/tests/baselines/reference/privateNamesNoConflictWhenInheriting.symbols new file mode 100644 index 0000000000000..d1442d5750cd5 --- /dev/null +++ b/tests/baselines/reference/privateNamesNoConflictWhenInheriting.symbols @@ -0,0 +1,23 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNoConflictWhenInheriting.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNamesNoConflictWhenInheriting.ts, 0, 0)) + + #foo: number; +>#foo : Symbol(A.#foo, Decl(privateNamesNoConflictWhenInheriting.ts, 2, 9)) +} + +class B extends A { +>B : Symbol(B, Decl(privateNamesNoConflictWhenInheriting.ts, 4, 1)) +>A : Symbol(A, Decl(privateNamesNoConflictWhenInheriting.ts, 0, 0)) + + #foo: string; // OK: private names are unique to each class +>#foo : Symbol(B.#foo, Decl(privateNamesNoConflictWhenInheriting.ts, 6, 19)) +} + +const b: A = new B() // OK +>b : Symbol(b, Decl(privateNamesNoConflictWhenInheriting.ts, 10, 5)) +>A : Symbol(A, Decl(privateNamesNoConflictWhenInheriting.ts, 0, 0)) +>B : Symbol(B, Decl(privateNamesNoConflictWhenInheriting.ts, 4, 1)) + diff --git a/tests/baselines/reference/privateNamesNoConflictWhenInheriting.types b/tests/baselines/reference/privateNamesNoConflictWhenInheriting.types new file mode 100644 index 0000000000000..fd88a20816e15 --- /dev/null +++ b/tests/baselines/reference/privateNamesNoConflictWhenInheriting.types @@ -0,0 +1,23 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNoConflictWhenInheriting.ts === +// @target es6 + +class A { +>A : A + + #foo: number; +>#foo : number +} + +class B extends A { +>B : B +>A : A + + #foo: string; // OK: private names are unique to each class +>#foo : string +} + +const b: A = new B() // OK +>b : A +>new B() : B +>B : typeof B + diff --git a/tests/baselines/reference/privateNamesNoDelete.errors.txt b/tests/baselines/reference/privateNamesNoDelete.errors.txt new file mode 100644 index 0000000000000..f490c83c6bffb --- /dev/null +++ b/tests/baselines/reference/privateNamesNoDelete.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts(6,16): error TS18005: The operand of a delete operator cannot be a private name. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts (1 errors) ==== + // @target es6 + + class A { + #v = 1; + constructor() { + delete this.#v; // Error: The operand of a delete operator cannot be a private name. + ~~~~~~~ +!!! error TS18005: The operand of a delete operator cannot be a private name. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesNoDelete.js b/tests/baselines/reference/privateNamesNoDelete.js new file mode 100644 index 0000000000000..741b7aaa7dca7 --- /dev/null +++ b/tests/baselines/reference/privateNamesNoDelete.js @@ -0,0 +1,21 @@ +//// [privateNamesNoDelete.ts] +// @target es6 + +class A { + #v = 1; + constructor() { + delete this.#v; // Error: The operand of a delete operator cannot be a private name. + } +} + + +//// [privateNamesNoDelete.js] +"use strict"; +// @target es6 +var A = /** @class */ (function () { + function A() { + this.#v = 1; + delete this.#v; // Error: The operand of a delete operator cannot be a private name. + } + return A; +}()); diff --git a/tests/baselines/reference/privateNamesNoDelete.symbols b/tests/baselines/reference/privateNamesNoDelete.symbols new file mode 100644 index 0000000000000..50e2542c07877 --- /dev/null +++ b/tests/baselines/reference/privateNamesNoDelete.symbols @@ -0,0 +1,16 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNamesNoDelete.ts, 0, 0)) + + #v = 1; +>#v : Symbol(A.#v, Decl(privateNamesNoDelete.ts, 2, 9)) + + constructor() { + delete this.#v; // Error: The operand of a delete operator cannot be a private name. +>this.#v : Symbol(A.#v, Decl(privateNamesNoDelete.ts, 2, 9)) +>this : Symbol(A, Decl(privateNamesNoDelete.ts, 0, 0)) + } +} + diff --git a/tests/baselines/reference/privateNamesNoDelete.types b/tests/baselines/reference/privateNamesNoDelete.types new file mode 100644 index 0000000000000..681651a4f770a --- /dev/null +++ b/tests/baselines/reference/privateNamesNoDelete.types @@ -0,0 +1,18 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts === +// @target es6 + +class A { +>A : A + + #v = 1; +>#v : number +>1 : 1 + + constructor() { + delete this.#v; // Error: The operand of a delete operator cannot be a private name. +>delete this.#v : boolean +>this.#v : number +>this : this + } +} + diff --git a/tests/baselines/reference/privateNamesNotAllowedAsParameters.errors.txt b/tests/baselines/reference/privateNamesNotAllowedAsParameters.errors.txt new file mode 100644 index 0000000000000..942bea1e251a8 --- /dev/null +++ b/tests/baselines/reference/privateNamesNotAllowedAsParameters.errors.txt @@ -0,0 +1,21 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts(4,12): error TS1138: Parameter declaration expected. +tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts(4,24): error TS1005: ';' expected. +tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts(4,26): error TS1068: Unexpected token. A constructor, method, accessor, or property was expected. +tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts(5,1): error TS1128: Declaration or statement expected. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts (4 errors) ==== + // @target es6 + + class A { + setFoo(#foo: string) {} + ~~~~ +!!! error TS1138: Parameter declaration expected. + ~ +!!! error TS1005: ';' expected. + ~ +!!! error TS1068: Unexpected token. A constructor, method, accessor, or property was expected. + } + ~ +!!! error TS1128: Declaration or statement expected. + \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesNotAllowedAsParameters.js b/tests/baselines/reference/privateNamesNotAllowedAsParameters.js new file mode 100644 index 0000000000000..8c3a394e1ac03 --- /dev/null +++ b/tests/baselines/reference/privateNamesNotAllowedAsParameters.js @@ -0,0 +1,17 @@ +//// [privateNamesNotAllowedAsParameters.ts] +// @target es6 + +class A { + setFoo(#foo: string) {} +} + + +//// [privateNamesNotAllowedAsParameters.js] +// @target es6 +var A = /** @class */ (function () { + function A() { + } + A.prototype.setFoo = function () { }; + return A; +}()); +{ } diff --git a/tests/baselines/reference/privateNamesNotAllowedAsParameters.symbols b/tests/baselines/reference/privateNamesNotAllowedAsParameters.symbols new file mode 100644 index 0000000000000..b7ea0b4850fb9 --- /dev/null +++ b/tests/baselines/reference/privateNamesNotAllowedAsParameters.symbols @@ -0,0 +1,11 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNamesNotAllowedAsParameters.ts, 0, 0)) + + setFoo(#foo: string) {} +>setFoo : Symbol(A.setFoo, Decl(privateNamesNotAllowedAsParameters.ts, 2, 9)) +>#foo : Symbol(A.#foo, Decl(privateNamesNotAllowedAsParameters.ts, 3, 11)) +} + diff --git a/tests/baselines/reference/privateNamesNotAllowedAsParameters.types b/tests/baselines/reference/privateNamesNotAllowedAsParameters.types new file mode 100644 index 0000000000000..effe8726a9470 --- /dev/null +++ b/tests/baselines/reference/privateNamesNotAllowedAsParameters.types @@ -0,0 +1,11 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts === +// @target es6 + +class A { +>A : A + + setFoo(#foo: string) {} +>setFoo : () => any +>#foo : string +} + diff --git a/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.errors.txt b/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.errors.txt new file mode 100644 index 0000000000000..5d79de2754392 --- /dev/null +++ b/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts(3,7): error TS1134: Variable declaration expected. +tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts(3,12): error TS1134: Variable declaration expected. +tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts(3,14): error TS1134: Variable declaration expected. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts (3 errors) ==== + // @target es6 + + const #foo = 3; + ~~~~ +!!! error TS1134: Variable declaration expected. + ~ +!!! error TS1134: Variable declaration expected. + ~ +!!! error TS1134: Variable declaration expected. \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.js b/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.js new file mode 100644 index 0000000000000..3a5f19724d38e --- /dev/null +++ b/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.js @@ -0,0 +1,10 @@ +//// [privateNamesNotAllowedInVariableDeclarations.ts] +// @target es6 + +const #foo = 3; + +//// [privateNamesNotAllowedInVariableDeclarations.js] +"use strict"; +// @target es6 +var ; +3; diff --git a/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.symbols b/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.symbols new file mode 100644 index 0000000000000..8a90d43a114c9 --- /dev/null +++ b/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.symbols @@ -0,0 +1,5 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts === +// @target es6 +No type information for this code. +No type information for this code.const #foo = 3; +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.types b/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.types new file mode 100644 index 0000000000000..1def5f332d291 --- /dev/null +++ b/tests/baselines/reference/privateNamesNotAllowedInVariableDeclarations.types @@ -0,0 +1,6 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts === +// @target es6 + +const #foo = 3; +>3 : 3 + diff --git a/tests/baselines/reference/privateNamesUnique.errors.txt b/tests/baselines/reference/privateNamesUnique.errors.txt new file mode 100644 index 0000000000000..0c3b1ef188c17 --- /dev/null +++ b/tests/baselines/reference/privateNamesUnique.errors.txt @@ -0,0 +1,20 @@ +tests/cases/conformance/classes/members/privateNames/privateNamesUnique.ts(11,7): error TS2322: Type 'B' is not assignable to type 'A'. + Property '#foo' is missing in type 'B'. While type 'B' has a private member with the same spelling, its declaration and accessibility are distinct. + + +==== tests/cases/conformance/classes/members/privateNames/privateNamesUnique.ts (1 errors) ==== + // @target es6 + + class A { + #foo: number; + } + + class B { + #foo: number; + } + + const b: A = new B(); // Error: Property #foo is missing + ~ +!!! error TS2322: Type 'B' is not assignable to type 'A'. +!!! error TS2322: Property '#foo' is missing in type 'B'. While type 'B' has a private member with the same spelling, its declaration and accessibility are distinct. + \ No newline at end of file diff --git a/tests/baselines/reference/privateNamesUnique.js b/tests/baselines/reference/privateNamesUnique.js new file mode 100644 index 0000000000000..52c8a3bc69799 --- /dev/null +++ b/tests/baselines/reference/privateNamesUnique.js @@ -0,0 +1,28 @@ +//// [privateNamesUnique.ts] +// @target es6 + +class A { + #foo: number; +} + +class B { + #foo: number; +} + +const b: A = new B(); // Error: Property #foo is missing + + +//// [privateNamesUnique.js] +"use strict"; +// @target es6 +var A = /** @class */ (function () { + function A() { + } + return A; +}()); +var B = /** @class */ (function () { + function B() { + } + return B; +}()); +var b = new B(); // Error: Property #foo is missing diff --git a/tests/baselines/reference/privateNamesUnique.symbols b/tests/baselines/reference/privateNamesUnique.symbols new file mode 100644 index 0000000000000..5266e47918187 --- /dev/null +++ b/tests/baselines/reference/privateNamesUnique.symbols @@ -0,0 +1,22 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesUnique.ts === +// @target es6 + +class A { +>A : Symbol(A, Decl(privateNamesUnique.ts, 0, 0)) + + #foo: number; +>#foo : Symbol(A.#foo, Decl(privateNamesUnique.ts, 2, 9)) +} + +class B { +>B : Symbol(B, Decl(privateNamesUnique.ts, 4, 1)) + + #foo: number; +>#foo : Symbol(B.#foo, Decl(privateNamesUnique.ts, 6, 9)) +} + +const b: A = new B(); // Error: Property #foo is missing +>b : Symbol(b, Decl(privateNamesUnique.ts, 10, 5)) +>A : Symbol(A, Decl(privateNamesUnique.ts, 0, 0)) +>B : Symbol(B, Decl(privateNamesUnique.ts, 4, 1)) + diff --git a/tests/baselines/reference/privateNamesUnique.types b/tests/baselines/reference/privateNamesUnique.types new file mode 100644 index 0000000000000..a9d738ee0ca5b --- /dev/null +++ b/tests/baselines/reference/privateNamesUnique.types @@ -0,0 +1,22 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesUnique.ts === +// @target es6 + +class A { +>A : A + + #foo: number; +>#foo : number +} + +class B { +>B : B + + #foo: number; +>#foo : number +} + +const b: A = new B(); // Error: Property #foo is missing +>b : A +>new B() : B +>B : typeof B + diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts b/tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts index d4c0b8ad46efb..1f5da9ab9171e 100644 --- a/tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts +++ b/tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts @@ -1,6 +1,9 @@ -class A { - [k: string]: any; - constructor(message: string) { - this.#f = 3 // Error Property '#f' does not exist on type 'A'. - } -} +// @strict: true +// @target es6 + +class A { + [k: string]: any; + constructor(message: string) { + this.#f = 3 // Error Property '#f' does not exist on type 'A'. + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameConstructorReserved.ts b/tests/cases/conformance/classes/members/privateNames/privateNameConstructorReserved.ts new file mode 100644 index 0000000000000..1421db99944d8 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameConstructorReserved.ts @@ -0,0 +1,5 @@ +// @target es6 + +class A { + #constructor() {} // Error: `#constructor` is a reserved word. +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameDuplicateField.ts b/tests/cases/conformance/classes/members/privateNames/privateNameDuplicateField.ts new file mode 100644 index 0000000000000..ba8160cb122ab --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameDuplicateField.ts @@ -0,0 +1,7 @@ +// @strict: true +// @target es6 + +class A { + #foo = "foo"; + #foo = "foo"; +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameField.ts b/tests/cases/conformance/classes/members/privateNames/privateNameField.ts index 02e449fb3e002..d4b823c49da63 100644 --- a/tests/cases/conformance/classes/members/privateNames/privateNameField.ts +++ b/tests/cases/conformance/classes/members/privateNames/privateNameField.ts @@ -1,6 +1,9 @@ -class A { - #name: string; - constructor(name: string) { - this.#name = name; - } +// @strict: true +// @target es6 + +class A { + #name: string; + constructor(name: string) { + this.#name = name; + } } \ No newline at end of file diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-1.ts b/tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-1.ts new file mode 100644 index 0000000000000..04c75fda5f841 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-1.ts @@ -0,0 +1,3 @@ +const obj = { + #foo: 1 +}; diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-2.ts b/tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-2.ts new file mode 100644 index 0000000000000..3356e7a957b1f --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameInObjectLiteral-2.ts @@ -0,0 +1,5 @@ +const obj = { + #foo() { + + } +}; diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts b/tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts new file mode 100644 index 0000000000000..6f14d0ec8d72e --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts @@ -0,0 +1,8 @@ +// @strict: true +// @target es6 + +class A { + #foo: number = 3; +} + +new A().#foo = 4; // Error diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts b/tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts new file mode 100644 index 0000000000000..26aacc421a19a --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameNotAllowedOutsideClass.ts @@ -0,0 +1,4 @@ +// @strict: true +// @target es6 + +const #foo = 3; \ No newline at end of file diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameSneakyRuntimeException.ts b/tests/cases/conformance/classes/members/privateNames/privateNameSneakyRuntimeException.ts new file mode 100644 index 0000000000000..f4450f031ab75 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameSneakyRuntimeException.ts @@ -0,0 +1,16 @@ +// @strict: true +// @target es6 + +function createClass () { + return class { + #foo = 3; + equals(other: any) { + return this.#foo = other.#foo; + } + }; +} + +const a = new (createClass())(); +const b = new (createClass())(); + +console.log(a.equals(b)); // OK at compile time but will be a runtime error diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesAndDecorators.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesAndDecorators.ts new file mode 100644 index 0000000000000..d82e05ef9735e --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesAndDecorators.ts @@ -0,0 +1,8 @@ +declare function dec(target: T): T; + +class A { + @dec // Error + #foo = 1; + @dec // Error + #bar(): void { } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesAndFields.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesAndFields.ts new file mode 100644 index 0000000000000..ebf44118093aa --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesAndFields.ts @@ -0,0 +1,17 @@ +// @strict: true +// @target es6 + +class A { + #foo: number; + constructor () { + this.#foo = 3; + } +} + +class B extends A { + #foo: string; + constructor () { + super(); + this.#foo = "some string"; + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts new file mode 100644 index 0000000000000..fb515e4bb023a --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesAndGenericClasses-2.ts @@ -0,0 +1,29 @@ +// @strict: true +// @target: es6 + +class C { + #foo: T; + #bar(): T { + return this.#foo; + } + constructor(t: T) { + this.#foo = t; + t = this.#bar(); + } + set baz(t: T) { + this.#foo = t; + + } + get baz(): T { + return this.#foo; + } +} + +let a = new C(3); +let b = new C("hello"); + +a.baz = 5 // OK +const x: number = a.baz // OK +a.#foo; // Error +a = b; // Error +b = a; // Error diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts new file mode 100644 index 0000000000000..0673430ce272c --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts @@ -0,0 +1,14 @@ +// @strict: true +// @target: es6 + +class C { + foo = 3; + #bar = 3; + constructor () { + const ok: C["foo"] = 3; + // not supported yet, could support in future: + const badForNow: C[#bar] = 3; // Error + // will never use this syntax, already taken: + const badAlways: C["#bar"] = 3; // Error + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesAndMethods.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesAndMethods.ts new file mode 100644 index 0000000000000..d564860b56e97 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesAndMethods.ts @@ -0,0 +1,32 @@ +// @target: esnext +// @lib: esnext + +class A { + #foo(a: number) {} + async #bar(a: number) {} + async *#baz(a: number) { + return 3; + } + #_quux: number; + get #quux (): number { + return this.#_quux; + } + set #quux (val: number) { + this.#_quux = val; + } + constructor () { + this.#foo(30); + this.#bar(30); + this.#bar(30); + this.#quux = this.#quux + 1; + this.#quux++; + } +} + +class B extends A { + #foo(a: string) {} + constructor () { + super(); + this.#foo("str"); + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticFields.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticFields.ts new file mode 100644 index 0000000000000..ec9906a8ef00d --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticFields.ts @@ -0,0 +1,17 @@ +// @strict: true +// @target es6 + +class A { + static #foo: number; + constructor () { + A.#foo = 3; + } +} + +class B extends A { + static #foo: string; + constructor () { + super(); + B.#foo = "some string"; + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticMethods.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticMethods.ts new file mode 100644 index 0000000000000..7cbf9f8f9992b --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticMethods.ts @@ -0,0 +1,33 @@ +// @strict: true +// @target: esnext +// @lib: esnext + +class A { + static #foo(a: number) {} + static async #bar(a: number) {} + static async *#baz(a: number) { + return 3; + } + static #_quux: number; + static get #quux (): number { + return this.#_quux; + } + static set #quux (val: number) { + this.#_quux = val; + } + constructor () { + A.#foo(30); + A.#bar(30); + A.#bar(30); + A.#quux = A.#quux + 1; + A.#quux++; + } +} + +class B extends A { + static #foo(a: string) {} + constructor () { + super(); + B.#foo("str"); + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesAndkeyof.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesAndkeyof.ts new file mode 100644 index 0000000000000..1e178092c7e8d --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesAndkeyof.ts @@ -0,0 +1,10 @@ +// @strict: true +// @target es6 + +class A { + #foo = 3; + bar = 3; + baz = 3; +} + +type T = keyof A // should not include '#foo' diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts new file mode 100644 index 0000000000000..fbf667d82f921 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesInGenericClasses.ts @@ -0,0 +1,15 @@ +// @strict: true +// @target: es6 + +class C { + #foo: T; + bar(x: C) { return x.#foo; } // OK + baz(x: C) { return x.#foo; } // OK + quux(x: C) { return x.#foo; } // OK +} + +declare let a: C; +declare let b: C; +a.#foo; // Error +a = b; // Error +b = a; // Error diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesInNestedClasses.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesInNestedClasses.ts new file mode 100644 index 0000000000000..dc6076ffbe096 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesInNestedClasses.ts @@ -0,0 +1,28 @@ +// @strict: true +// @target es6 + +class A { + #foo = "A's #foo"; + #bar = "A's #bar"; + method () { + class B { + #foo = "B's #foo"; + bar (a: any) { + a.#foo; // OK, no compile-time error, don't know what `a` is + } + baz (a: A) { + a.#foo; // compile-time error, shadowed + } + quux (b: B) { + b.#foo; // OK + } + } + const a = new A(); + new B().bar(a); + new B().baz(a); + const b = new B(); + new B().quux(b); + } +} + +new A().method(); \ No newline at end of file diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts new file mode 100644 index 0000000000000..a70c8acd143ac --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesNoAccessibilityModifiers.ts @@ -0,0 +1,9 @@ +// @strict: true +// @target es6 + +class A { + public #foo = 3; // Error + private #bar = 3; // Error + protected #baz = 3; // Error + readonly #qux = 3; // OK +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesNoConflictWhenInheriting.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesNoConflictWhenInheriting.ts new file mode 100644 index 0000000000000..937ed9c4c3cfa --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesNoConflictWhenInheriting.ts @@ -0,0 +1,12 @@ +// @strict: true +// @target es6 + +class A { + #foo: number; +} + +class B extends A { + #foo: string; // OK: private names are unique to each class +} + +const b: A = new B() // OK diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts new file mode 100644 index 0000000000000..70b099a0e5397 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesNoDelete.ts @@ -0,0 +1,9 @@ +// @strict: true +// @target es6 + +class A { + #v = 1; + constructor() { + delete this.#v; // Error: The operand of a delete operator cannot be a private name. + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts new file mode 100644 index 0000000000000..5a71fc00803c2 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedAsParameters.ts @@ -0,0 +1,5 @@ +// @target es6 + +class A { + setFoo(#foo: string) {} +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts new file mode 100644 index 0000000000000..26aacc421a19a --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesNotAllowedInVariableDeclarations.ts @@ -0,0 +1,4 @@ +// @strict: true +// @target es6 + +const #foo = 3; \ No newline at end of file diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesUnique.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesUnique.ts new file mode 100644 index 0000000000000..1e9891095512d --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesUnique.ts @@ -0,0 +1,12 @@ +// @strict: true +// @target es6 + +class A { + #foo: number; +} + +class B { + #foo: number; +} + +const b: A = new B(); // Error: Property #foo is missing From 3f6b68f73d7213bea68460a606b29e934047743b Mon Sep 17 00:00:00 2001 From: Joey Watts Date: Wed, 27 Mar 2019 16:09:29 -0400 Subject: [PATCH 6/6] Add private named instance field transformation (#31) Implements private instance fields on top of the class properties refactor. Signed-off-by: Joseph Watts Signed-off-by: Max Heiber --- src/compiler/transformers/classProperties.ts | 445 +++++++++++++++++- src/compiler/transformers/generators.ts | 22 - src/compiler/transformers/utilities.ts | 22 + src/compiler/types.ts | 10 + src/compiler/utilities.ts | 10 + .../reference/privateNameDeclaration.js | 15 + .../reference/privateNameDeclaration.symbols | 8 + .../reference/privateNameDeclaration.types | 8 + .../reference/privateNameDuplicateField.js | 8 +- tests/baselines/reference/privateNameField.js | 8 +- .../reference/privateNameFieldAccess.js | 20 + .../reference/privateNameFieldAccess.symbols | 17 + .../reference/privateNameFieldAccess.types | 19 + .../reference/privateNameFieldAssignment.js | 78 +++ .../privateNameFieldAssignment.symbols | 146 ++++++ .../privateNameFieldAssignment.types | 213 +++++++++ .../privateNameFieldCallExpression.js | 29 ++ .../privateNameFieldCallExpression.symbols | 30 ++ .../privateNameFieldCallExpression.types | 36 ++ .../privateNameFieldDestructuredBinding.js | 37 ++ ...rivateNameFieldDestructuredBinding.symbols | 42 ++ .../privateNameFieldDestructuredBinding.types | 57 +++ .../reference/privateNameFieldInitializer.js | 17 + .../privateNameFieldInitializer.symbols | 11 + .../privateNameFieldInitializer.types | 12 + .../privateNameFieldUnaryMutation.js | 43 ++ .../privateNameFieldUnaryMutation.symbols | 56 +++ .../privateNameFieldUnaryMutation.types | 70 +++ .../privateNameNestedClassNameConflict.js | 28 ++ ...privateNameNestedClassNameConflict.symbols | 17 + .../privateNameNestedClassNameConflict.types | 17 + ...teNameNotAccessibleOutsideDefiningClass.js | 6 +- .../privateNameSneakyRuntimeException.js | 23 +- .../reference/privateNamesAndDecorators.js | 4 +- .../reference/privateNamesAndFields.js | 12 +- .../privateNamesAndGenericClasses-2.js | 15 +- .../reference/privateNamesAndIndexedAccess.js | 5 +- .../reference/privateNamesAndMethods.js | 27 +- .../reference/privateNamesAndStaticFields.js | 10 +- .../reference/privateNamesAndStaticMethods.js | 28 +- .../reference/privateNamesAndkeyof.js | 6 +- .../reference/privateNamesInGenericClasses.js | 12 +- .../reference/privateNamesInNestedClasses.js | 19 +- .../privateNamesNoAccessibilityModifiers.js | 12 +- .../privateNamesNoConflictWhenInheriting.js | 10 +- .../reference/privateNamesNoDelete.js | 9 +- .../privateNamesNotAllowedAsParameters.js | 3 + .../baselines/reference/privateNamesUnique.js | 7 +- .../privateNames/privateNameDeclaration.ts | 3 + .../privateNames/privateNameFieldAccess.ts | 6 + .../privateNameFieldAssignment.ts | 34 ++ .../privateNameFieldCallExpression.ts | 9 + .../privateNameFieldDestructuredBinding.ts | 14 + .../privateNameFieldInitializer.ts | 4 + .../privateNameFieldUnaryMutation.ts | 16 + .../privateNameNestedClassNameConflict.ts | 8 + 56 files changed, 1740 insertions(+), 113 deletions(-) create mode 100644 tests/baselines/reference/privateNameDeclaration.js create mode 100644 tests/baselines/reference/privateNameDeclaration.symbols create mode 100644 tests/baselines/reference/privateNameDeclaration.types create mode 100644 tests/baselines/reference/privateNameFieldAccess.js create mode 100644 tests/baselines/reference/privateNameFieldAccess.symbols create mode 100644 tests/baselines/reference/privateNameFieldAccess.types create mode 100644 tests/baselines/reference/privateNameFieldAssignment.js create mode 100644 tests/baselines/reference/privateNameFieldAssignment.symbols create mode 100644 tests/baselines/reference/privateNameFieldAssignment.types create mode 100644 tests/baselines/reference/privateNameFieldCallExpression.js create mode 100644 tests/baselines/reference/privateNameFieldCallExpression.symbols create mode 100644 tests/baselines/reference/privateNameFieldCallExpression.types create mode 100644 tests/baselines/reference/privateNameFieldDestructuredBinding.js create mode 100644 tests/baselines/reference/privateNameFieldDestructuredBinding.symbols create mode 100644 tests/baselines/reference/privateNameFieldDestructuredBinding.types create mode 100644 tests/baselines/reference/privateNameFieldInitializer.js create mode 100644 tests/baselines/reference/privateNameFieldInitializer.symbols create mode 100644 tests/baselines/reference/privateNameFieldInitializer.types create mode 100644 tests/baselines/reference/privateNameFieldUnaryMutation.js create mode 100644 tests/baselines/reference/privateNameFieldUnaryMutation.symbols create mode 100644 tests/baselines/reference/privateNameFieldUnaryMutation.types create mode 100644 tests/baselines/reference/privateNameNestedClassNameConflict.js create mode 100644 tests/baselines/reference/privateNameNestedClassNameConflict.symbols create mode 100644 tests/baselines/reference/privateNameNestedClassNameConflict.types create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameDeclaration.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameFieldAccess.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameFieldAssignment.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameFieldCallExpression.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameFieldDestructuredBinding.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameFieldInitializer.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameFieldUnaryMutation.ts create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameNestedClassNameConflict.ts diff --git a/src/compiler/transformers/classProperties.ts b/src/compiler/transformers/classProperties.ts index df05710475ab9..6787c2baa2236 100644 --- a/src/compiler/transformers/classProperties.ts +++ b/src/compiler/transformers/classProperties.ts @@ -7,6 +7,23 @@ namespace ts { */ ClassAliases = 1 << 0, } + + const enum PrivateNamePlacement { + InstanceField + } + + type PrivateNameInfo = PrivateNamedInstanceField; + + interface PrivateNamedInstanceField { + placement: PrivateNamePlacement.InstanceField; + weakMapName: Identifier; + } + + /** + * A mapping of private names to information needed for transformation. + */ + type PrivateNameEnvironment = UnderscoreEscapedMap; + /** * Transforms ECMAScript Class Syntax. * TypeScript parameter property syntax is transformed in the TypeScript transformer. @@ -41,6 +58,8 @@ namespace ts { */ let pendingStatements: Statement[] | undefined; + const privateNameEnvironmentStack: PrivateNameEnvironment[] = []; + return chainBundle(transformSourceFile); function transformSourceFile(node: SourceFile) { @@ -55,15 +74,24 @@ namespace ts { function visitor(node: Node): VisitResult { switch (node.kind) { case SyntaxKind.ClassExpression: - return visitClassExpression(node as ClassExpression); case SyntaxKind.ClassDeclaration: - return visitClassDeclaration(node as ClassDeclaration); + return visitClassLike(node as ClassLikeDeclaration); case SyntaxKind.PropertyDeclaration: return visitPropertyDeclaration(node as PropertyDeclaration); case SyntaxKind.VariableStatement: return visitVariableStatement(node as VariableStatement); case SyntaxKind.ComputedPropertyName: return visitComputedPropertyName(node as ComputedPropertyName); + case SyntaxKind.PropertyAccessExpression: + return visitPropertyAccessExpression(node as PropertyAccessExpression); + case SyntaxKind.PrefixUnaryExpression: + return visitPrefixUnaryExpression(node as PrefixUnaryExpression); + case SyntaxKind.PostfixUnaryExpression: + return visitPostfixUnaryExpression(node as PostfixUnaryExpression); + case SyntaxKind.CallExpression: + return visitCallExpression(node as CallExpression); + case SyntaxKind.BinaryExpression: + return visitBinaryExpression(node as BinaryExpression); } return visitEachChild(node, visitor, context); } @@ -138,10 +166,217 @@ namespace ts { return undefined; } - function visitClassDeclaration(node: ClassDeclaration) { + function visitPropertyAccessExpression(node: PropertyAccessExpression) { + if (isPrivateName(node.name)) { + const privateNameInfo = accessPrivateName(node.name); + if (privateNameInfo) { + switch (privateNameInfo.placement) { + case PrivateNamePlacement.InstanceField: + return setOriginalNode( + setTextRange( + createClassPrivateFieldGetHelper( + context, + visitNode(node.expression, visitor, isExpression), + privateNameInfo.weakMapName + ), + node + ), + node + ); + } + } + } + return visitEachChild(node, visitor, context); + } + + function visitPrefixUnaryExpression(node: PrefixUnaryExpression) { + if (isPrivateNamedPropertyAccessExpression(node.operand)) { + const operator = (node.operator === SyntaxKind.PlusPlusToken) ? + SyntaxKind.PlusEqualsToken : (node.operator === SyntaxKind.MinusMinusToken) ? + SyntaxKind.MinusEqualsToken : undefined; + if (operator) { + const transformedExpr = setOriginalNode( + createBinary( + node.operand, + operator, + createNumericLiteral("1") + ), + node + ); + const visited = visitNode(transformedExpr, visitor); + // If the private name was successfully transformed, + // return the transformed node. Otherwise, leave existing source untouched. + if (visited !== transformedExpr) { + return visited; + } + } + } + return visitEachChild(node, visitor, context); + } + + function visitPostfixUnaryExpression(node: PostfixUnaryExpression) { + if (isPrivateNamedPropertyAccessExpression(node.operand)) { + const operator = (node.operator === SyntaxKind.PlusPlusToken) ? + SyntaxKind.PlusToken : (node.operator === SyntaxKind.MinusMinusToken) ? + SyntaxKind.MinusToken : undefined; + if (operator) { + // Create a temporary variable if the receiver is not inlinable, since we + // will need to access it multiple times. + const receiver = isSimpleInlineableExpression(node.operand.expression) ? + undefined : + getGeneratedNameForNode(node.operand.expression); + // Create a temporary variable to store the value returned by the expression. + const returnValue = createTempVariable(/*recordTempVariable*/ undefined); + + const transformedExpr = createCommaList(compact([ + receiver && createAssignment(receiver, node.operand.expression), + // Store the existing value of the private name in the temporary. + createAssignment(returnValue, receiver ? createPropertyAccess(receiver, node.operand.name) : node.operand), + // Assign to private name. + createAssignment( + receiver ? createPropertyAccess(receiver, node.operand.name) : node.operand, + createBinary( + returnValue, operator, createNumericLiteral("1") + ) + ), + // Return the cached value. + returnValue + ]) as Expression[]); + const visited = visitNode(transformedExpr, visitor); + // If the private name was successfully transformed, + // hoist the temporary variable and return the transformed node. + // Otherwise, leave existing source untouched. + if (visited !== transformedExpr) { + if (receiver) { + hoistVariableDeclaration(receiver); + } + hoistVariableDeclaration(returnValue); + return visited; + } + } + } + return visitEachChild(node, visitor, context); + } + + + function visitCallExpression(node: CallExpression) { + if (isPrivateNamedPropertyAccessExpression(node.expression)) { + // Transform call expressions of private names to properly bind the `this` parameter. + let exprForPropertyAccess: Expression = node.expression.expression; + let receiver = node.expression.expression; + if (!isSimpleInlineableExpression(node.expression.expression)) { + const generatedName = getGeneratedNameForNode(node); + hoistVariableDeclaration(generatedName); + exprForPropertyAccess = setOriginalNode( + createAssignment(generatedName, exprForPropertyAccess), + node.expression.expression + ); + receiver = generatedName; + } + return visitNode( + updateCall( + node, + createPropertyAccess( + updatePropertyAccess( + node.expression, + exprForPropertyAccess, + node.expression.name + ), + "call" + ), + /*typeArguments*/ undefined, + [receiver, ...node.arguments] + ), + visitor + ); + } + return visitEachChild(node, visitor, context); + } + + interface PrivateNameAssignmentExpression extends AssignmentExpression { + left: PrivateNamedPropertyAccessExpression; + } + + function isPrivateNameAssignmentExpression(node: Node): node is PrivateNameAssignmentExpression { + return isAssignmentExpression(node) && isPrivateNamedPropertyAccessExpression(node.left); + } + + function visitBinaryExpression(node: BinaryExpression) { + if (isDestructuringAssignment(node)) { + const left = transformDestructuringAssignmentTarget(node.left); + if (left !== node.left) { + return updateBinary(node, left, node.right, node.operatorToken); + } + } + else if (isPrivateNameAssignmentExpression(node)) { + const privateNameInfo = accessPrivateName(node.left.name); + if (privateNameInfo) { + switch (privateNameInfo.placement) { + case PrivateNamePlacement.InstanceField: { + return transformPrivateNamedInstanceFieldAssignment(privateNameInfo, node); + } + } + } + } + return visitEachChild(node, visitor, context); + } + + function transformPrivateNamedInstanceFieldAssignment(privateNameInfo: PrivateNamedInstanceField, node: PrivateNameAssignmentExpression) { + if (isCompoundAssignment(node.operatorToken.kind)) { + const isReceiverInlineable = isSimpleInlineableExpression(node.left.expression); + const getReceiver = isReceiverInlineable ? node.left.expression : createTempVariable(hoistVariableDeclaration); + const setReceiver = isReceiverInlineable + ? node.left.expression + : createAssignment(getReceiver, node.left.expression); + return setOriginalNode( + createClassPrivateFieldSetHelper( + context, + setReceiver, + privateNameInfo.weakMapName, + createBinary( + createClassPrivateFieldGetHelper( + context, + getReceiver, + privateNameInfo.weakMapName + ), + getOperatorForCompoundAssignment(node.operatorToken.kind), + visitNode(node.right, visitor) + ) + ), + node + ); + } + else { + return setOriginalNode( + createClassPrivateFieldSetHelper( + context, + node.left.expression, + privateNameInfo.weakMapName, + visitNode(node.right, visitor) + ), + node + ); + } + } + + /** + * Set up the environment for a class. + */ + function visitClassLike(node: ClassLikeDeclaration) { const savedPendingExpressions = pendingExpressions; pendingExpressions = undefined; + startPrivateNameEnvironment(); + + const result = isClassDeclaration(node) ? + visitClassDeclaration(node) : + visitClassExpression(node); + endPrivateNameEnvironment(); + pendingExpressions = savedPendingExpressions; + return result; + } + + function visitClassDeclaration(node: ClassDeclaration) { const extendsClauseElement = getEffectiveBaseTypeNode(node); const isDerivedClass = !!(extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword); @@ -161,7 +396,6 @@ namespace ts { 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 @@ -177,9 +411,6 @@ namespace ts { } function visitClassExpression(node: ClassExpression): Expression { - const savedPendingExpressions = pendingExpressions; - pendingExpressions = undefined; - // 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. @@ -210,7 +441,6 @@ namespace ts { if (pendingStatements && pendingExpressions && some(pendingExpressions)) { pendingStatements.push(createExpressionStatement(inlineExpressions(pendingExpressions))); } - pendingExpressions = savedPendingExpressions; if (pendingStatements && some(staticProperties)) { addInitializedPropertyStatements(pendingStatements, staticProperties, getInternalName(node)); @@ -238,16 +468,21 @@ namespace ts { addRange(expressions, generateInitializedPropertyExpressions(staticProperties, temp)); expressions.push(startOnNewLine(temp)); - pendingExpressions = savedPendingExpressions; return inlineExpressions(expressions); } } - pendingExpressions = savedPendingExpressions; return classExpression; } function transformClassMembers(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { + // Declare private names. + node.members.forEach(member => { + if (isPrivateNamedPropertyDeclaration(member)) { + addPrivateNameToEnvironment(member.name); + } + }); + const members: ClassElement[] = []; const constructor = transformConstructor(node, isDerivedClass); if (constructor) { @@ -259,8 +494,11 @@ namespace ts { function transformConstructor(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { const constructor = visitNode(getFirstConstructorWithBody(node), visitor, isConstructorDeclaration); - const containsPropertyInitializer = forEach(node.members, isInitializedProperty); - if (!containsPropertyInitializer) { + const containsPropertyInitializerOrPrivateName = forEach( + node.members, + member => isInitializedProperty(member) || isPrivateNamedPropertyDeclaration(member) + ); + if (!containsPropertyInitializerOrPrivateName) { return constructor; } const parameters = visitParameterList(constructor ? constructor.parameters : undefined, visitor, context); @@ -285,7 +523,9 @@ namespace ts { } function transformConstructorBody(node: ClassDeclaration | ClassExpression, constructor: ConstructorDeclaration | undefined, isDerivedClass: boolean) { - const properties = getInitializedProperties(node, /*isStatic*/ false); + const properties = node.members.filter( + (node): node is PropertyDeclaration => isPropertyDeclaration(node) && !hasStaticModifier(node) + ); // Only generate synthetic constructor when there are property initializers to move. if (!constructor && !some(properties)) { @@ -356,7 +596,11 @@ namespace ts { */ function addInitializedPropertyStatements(statements: Statement[], properties: ReadonlyArray, receiver: LeftHandSideExpression) { for (const property of properties) { - const statement = createExpressionStatement(transformInitializedProperty(property, receiver)); + const expression = transformProperty(property, receiver); + if (!expression) { + continue; + } + const statement = createExpressionStatement(expression); setSourceMapRange(statement, moveRangePastModifiers(property)); setCommentRange(statement, property); setOriginalNode(statement, property); @@ -373,7 +617,10 @@ namespace ts { function generateInitializedPropertyExpressions(properties: ReadonlyArray, receiver: LeftHandSideExpression) { const expressions: Expression[] = []; for (const property of properties) { - const expression = transformInitializedProperty(property, receiver); + const expression = transformProperty(property, receiver); + if (!expression) { + continue; + } startOnNewLine(expression); setSourceMapRange(expression, moveRangePastModifiers(property)); setCommentRange(expression, property); @@ -390,12 +637,31 @@ namespace ts { * @param property The property declaration. * @param receiver The object receiving the property assignment. */ - function transformInitializedProperty(property: PropertyDeclaration, receiver: LeftHandSideExpression) { + 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); + const initializer = visitNode(property.initializer, visitor, isExpression); + + if (isPrivateName(propertyName)) { + const privateNameInfo = accessPrivateName(propertyName); + if (privateNameInfo) { + switch (privateNameInfo.placement) { + case PrivateNamePlacement.InstanceField: { + return createPrivateInstanceFieldInitializer( + receiver, + initializer, + privateNameInfo.weakMapName + ); + } + } + } + } + if (!initializer) { + return undefined; + } + const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName); return createAssignment(memberAccess, initializer); @@ -484,6 +750,151 @@ namespace ts { return (inlinable || isIdentifier(innerExpression)) ? undefined : expression; } } + + function startPrivateNameEnvironment() { + const env: PrivateNameEnvironment = createUnderscoreEscapedMap(); + privateNameEnvironmentStack.push(env); + return env; + } + + function endPrivateNameEnvironment() { + privateNameEnvironmentStack.pop(); + } + + function addPrivateNameToEnvironment(name: PrivateName) { + const env = last(privateNameEnvironmentStack); + const text = getTextOfPropertyName(name) as string; + const weakMapName = createOptimisticUniqueName("_" + text.substring(1)); + weakMapName.autoGenerateFlags |= GeneratedIdentifierFlags.ReservedInNestedScopes; + hoistVariableDeclaration(weakMapName); + env.set(name.escapedText, { placement: PrivateNamePlacement.InstanceField, weakMapName }); + (pendingExpressions || (pendingExpressions = [])).push( + createAssignment( + weakMapName, + createNew( + createIdentifier("WeakMap"), + /*typeArguments*/ undefined, + [] + ) + ) + ); + } + + function accessPrivateName(name: PrivateName) { + for (let i = privateNameEnvironmentStack.length - 1; i >= 0; --i) { + const env = privateNameEnvironmentStack[i]; + if (env.has(name.escapedText)) { + return env.get(name.escapedText); + } + } + return undefined; + } + + + function wrapPrivateNameForDestructuringTarget(node: PrivateNamedPropertyAccessExpression) { + return createPropertyAccess( + createObjectLiteral([ + createSetAccessor( + /*decorators*/ undefined, + /*modifiers*/ undefined, + "value", + [createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, "x", + /*questionToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined + )], + createBlock( + [createExpressionStatement( + visitNode( + createAssignment(node, createIdentifier("x")), + visitor + ) + )] + ) + ) + ]), + "value" + ); + } + + function transformDestructuringAssignmentTarget(node: ArrayLiteralExpression | ObjectLiteralExpression) { + const hasPrivateNames = isArrayLiteralExpression(node) ? + forEach(node.elements, isPrivateNamedPropertyAccessExpression) : + forEach(node.properties, property => isPropertyAssignment(property) && isPrivateNamedPropertyAccessExpression(property.initializer)); + if (!hasPrivateNames) { + return node; + } + if (isArrayLiteralExpression(node)) { + // Transforms private names in destructuring assignment array bindings. + // + // Source: + // ([ this.#myProp ] = [ "hello" ]); + // + // Transformation: + // [ { set value(x) { this.#myProp = x; } }.value ] = [ "hello" ]; + return updateArrayLiteral( + node, + node.elements.map( + expr => isPrivateNamedPropertyAccessExpression(expr) ? + wrapPrivateNameForDestructuringTarget(expr) : + expr + ) + ); + } + else { + // Transforms private names in destructuring assignment object bindings. + // + // Source: + // ({ stringProperty: this.#myProp } = { stringProperty: "hello" }); + // + // Transformation: + // ({ stringProperty: { set value(x) { this.#myProp = x; } }.value }) = { stringProperty: "hello" }; + return updateObjectLiteral( + node, + node.properties.map( + prop => isPropertyAssignment(prop) && isPrivateNamedPropertyAccessExpression(prop.initializer) ? + updatePropertyAssignment( + prop, + prop.name, + wrapPrivateNameForDestructuringTarget(prop.initializer) + ) : + prop + ) + ); + } + } + } + + function createPrivateInstanceFieldInitializer(receiver: LeftHandSideExpression, initializer: Expression | undefined, weakMapName: Identifier) { + return createCall( + createPropertyAccess(weakMapName, "set"), + /*typeArguments*/ undefined, + [receiver, initializer || createVoidZero()] + ); + } + + const classPrivateFieldGetHelper: EmitHelper = { + name: "typescript:classPrivateFieldGet", + scoped: false, + text: `var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); };` + }; + + function createClassPrivateFieldGetHelper(context: TransformationContext, receiver: Expression, privateField: Identifier) { + context.requestEmitHelper(classPrivateFieldGetHelper); + return createCall(getHelperName("_classPrivateFieldGet"), /* typeArguments */ undefined, [receiver, privateField]); } + const classPrivateFieldSetHelper: EmitHelper = { + name: "typescript:classPrivateFieldSet", + scoped: false, + text: `var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; };` + }; + + function createClassPrivateFieldSetHelper(context: TransformationContext, receiver: Expression, privateField: Identifier, value: Expression) { + context.requestEmitHelper(classPrivateFieldSetHelper); + return createCall(getHelperName("_classPrivateFieldSet"), /* typeArguments */ undefined, [receiver, privateField, value]); + } } diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 154b09dc93d55..b2a188cf2ff65 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -667,28 +667,6 @@ namespace ts { } } - function isCompoundAssignment(kind: BinaryOperator): kind is CompoundAssignmentOperator { - return kind >= SyntaxKind.FirstCompoundAssignment - && kind <= SyntaxKind.LastCompoundAssignment; - } - - function getOperatorForCompoundAssignment(kind: CompoundAssignmentOperator): BitwiseOperatorOrHigher { - switch (kind) { - case SyntaxKind.PlusEqualsToken: return SyntaxKind.PlusToken; - case SyntaxKind.MinusEqualsToken: return SyntaxKind.MinusToken; - case SyntaxKind.AsteriskEqualsToken: return SyntaxKind.AsteriskToken; - case SyntaxKind.AsteriskAsteriskEqualsToken: return SyntaxKind.AsteriskAsteriskToken; - case SyntaxKind.SlashEqualsToken: return SyntaxKind.SlashToken; - case SyntaxKind.PercentEqualsToken: return SyntaxKind.PercentToken; - case SyntaxKind.LessThanLessThanEqualsToken: return SyntaxKind.LessThanLessThanToken; - case SyntaxKind.GreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanToken; - case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanGreaterThanToken; - case SyntaxKind.AmpersandEqualsToken: return SyntaxKind.AmpersandToken; - case SyntaxKind.BarEqualsToken: return SyntaxKind.BarToken; - case SyntaxKind.CaretEqualsToken: return SyntaxKind.CaretToken; - } - } - /** * Visits a right-associative binary expression containing `yield`. * diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index f5f8a298a490b..54c54771a0ff3 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -250,6 +250,28 @@ namespace ts { isWellKnownSymbolSyntactically(expression); } + export function isCompoundAssignment(kind: BinaryOperator): kind is CompoundAssignmentOperator { + return kind >= SyntaxKind.FirstCompoundAssignment + && kind <= SyntaxKind.LastCompoundAssignment; + } + + export function getOperatorForCompoundAssignment(kind: CompoundAssignmentOperator): BitwiseOperatorOrHigher { + switch (kind) { + case SyntaxKind.PlusEqualsToken: return SyntaxKind.PlusToken; + case SyntaxKind.MinusEqualsToken: return SyntaxKind.MinusToken; + case SyntaxKind.AsteriskEqualsToken: return SyntaxKind.AsteriskToken; + case SyntaxKind.AsteriskAsteriskEqualsToken: return SyntaxKind.AsteriskAsteriskToken; + case SyntaxKind.SlashEqualsToken: return SyntaxKind.SlashToken; + case SyntaxKind.PercentEqualsToken: return SyntaxKind.PercentToken; + case SyntaxKind.LessThanLessThanEqualsToken: return SyntaxKind.LessThanLessThanToken; + case SyntaxKind.GreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanToken; + case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanGreaterThanToken; + case SyntaxKind.AmpersandEqualsToken: return SyntaxKind.AmpersandToken; + case SyntaxKind.BarEqualsToken: return SyntaxKind.BarToken; + case SyntaxKind.CaretEqualsToken: return SyntaxKind.CaretToken; + } + } + /** * Adds super call and preceding prologue directives into the list of statements. * diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 251f04fb974f2..2dfe5196a1ce6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -951,6 +951,11 @@ namespace ts { initializer?: Expression; // Optional initializer } + /*@internal*/ + export interface PrivateNamedPropertyDeclaration extends PropertyDeclaration { + name: PrivateName; + } + export interface ObjectLiteralElement extends NamedDeclaration { _objectLiteralBrandBrand: any; name?: PropertyName; @@ -1775,6 +1780,11 @@ namespace ts { name: Identifier | PrivateName; } + /*@internal*/ + export interface PrivateNamedPropertyAccessExpression extends PropertyAccessExpression { + name: PrivateName; + } + export interface SuperPropertyAccessExpression extends PropertyAccessExpression { expression: SuperExpression; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 7ad07f0f1f5ca..281f3d4d64c17 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -6337,6 +6337,16 @@ namespace ts { || kind === SyntaxKind.ArrayBindingPattern; } + /*@internal*/ + export function isPrivateNamedPropertyDeclaration(node: Node): node is PrivateNamedPropertyDeclaration { + return isPropertyDeclaration(node) && isPrivateName(node.name); + } + + /*@internal*/ + export function isPrivateNamedPropertyAccessExpression(node: Node): node is PrivateNamedPropertyAccessExpression { + return isPropertyAccessExpression(node) && isPrivateName(node.name); + } + // Functions export function isFunctionLike(node: Node): node is SignatureDeclaration { diff --git a/tests/baselines/reference/privateNameDeclaration.js b/tests/baselines/reference/privateNameDeclaration.js new file mode 100644 index 0000000000000..ee7ec86c7b612 --- /dev/null +++ b/tests/baselines/reference/privateNameDeclaration.js @@ -0,0 +1,15 @@ +//// [privateNameDeclaration.ts] +class A { + #name: string; +} + + +//// [privateNameDeclaration.js] +var _name; +var A = /** @class */ (function () { + function A() { + _name.set(this, void 0); + } + return A; +}()); +_name = new WeakMap(); diff --git a/tests/baselines/reference/privateNameDeclaration.symbols b/tests/baselines/reference/privateNameDeclaration.symbols new file mode 100644 index 0000000000000..e34d275f72e67 --- /dev/null +++ b/tests/baselines/reference/privateNameDeclaration.symbols @@ -0,0 +1,8 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameDeclaration.ts === +class A { +>A : Symbol(A, Decl(privateNameDeclaration.ts, 0, 0)) + + #name: string; +>#name : Symbol(A.#name, Decl(privateNameDeclaration.ts, 0, 9)) +} + diff --git a/tests/baselines/reference/privateNameDeclaration.types b/tests/baselines/reference/privateNameDeclaration.types new file mode 100644 index 0000000000000..6de7c4f331104 --- /dev/null +++ b/tests/baselines/reference/privateNameDeclaration.types @@ -0,0 +1,8 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameDeclaration.ts === +class A { +>A : A + + #name: string; +>#name : string +} + diff --git a/tests/baselines/reference/privateNameDuplicateField.js b/tests/baselines/reference/privateNameDuplicateField.js index 3fda0374540d1..6ece4be8f032a 100644 --- a/tests/baselines/reference/privateNameDuplicateField.js +++ b/tests/baselines/reference/privateNameDuplicateField.js @@ -8,12 +8,14 @@ class A { //// [privateNameDuplicateField.js] -"use strict"; // @target es6 +var _foo, _foo_1; +"use strict"; var A = /** @class */ (function () { function A() { - this.#foo = "foo"; - this.#foo = "foo"; + _foo_1.set(this, "foo"); + _foo_1.set(this, "foo"); } return A; }()); +_foo = new WeakMap(), _foo_1 = new WeakMap(); diff --git a/tests/baselines/reference/privateNameField.js b/tests/baselines/reference/privateNameField.js index 254f6833afa2f..57446748cb668 100644 --- a/tests/baselines/reference/privateNameField.js +++ b/tests/baselines/reference/privateNameField.js @@ -9,11 +9,15 @@ class A { } //// [privateNameField.js] -"use strict"; // @target es6 +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +var _name; +"use strict"; var A = /** @class */ (function () { function A(name) { - this.#name = name; + _name.set(this, void 0); + _classPrivateFieldSet(this, _name, name); } return A; }()); +_name = new WeakMap(); diff --git a/tests/baselines/reference/privateNameFieldAccess.js b/tests/baselines/reference/privateNameFieldAccess.js new file mode 100644 index 0000000000000..2f64fc96515fa --- /dev/null +++ b/tests/baselines/reference/privateNameFieldAccess.js @@ -0,0 +1,20 @@ +//// [privateNameFieldAccess.ts] +class A { + #myField = "hello world"; + constructor() { + console.log(this.#myField); + } +} + + +//// [privateNameFieldAccess.js] +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _myField; +var A = /** @class */ (function () { + function A() { + _myField.set(this, "hello world"); + console.log(_classPrivateFieldGet(this, _myField)); + } + return A; +}()); +_myField = new WeakMap(); diff --git a/tests/baselines/reference/privateNameFieldAccess.symbols b/tests/baselines/reference/privateNameFieldAccess.symbols new file mode 100644 index 0000000000000..d69eacd7131f9 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldAccess.symbols @@ -0,0 +1,17 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldAccess.ts === +class A { +>A : Symbol(A, Decl(privateNameFieldAccess.ts, 0, 0)) + + #myField = "hello world"; +>#myField : Symbol(A.#myField, Decl(privateNameFieldAccess.ts, 0, 9)) + + constructor() { + console.log(this.#myField); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>this.#myField : Symbol(A.#myField, Decl(privateNameFieldAccess.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAccess.ts, 0, 0)) + } +} + diff --git a/tests/baselines/reference/privateNameFieldAccess.types b/tests/baselines/reference/privateNameFieldAccess.types new file mode 100644 index 0000000000000..17568587e311d --- /dev/null +++ b/tests/baselines/reference/privateNameFieldAccess.types @@ -0,0 +1,19 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldAccess.ts === +class A { +>A : A + + #myField = "hello world"; +>#myField : string +>"hello world" : "hello world" + + constructor() { + console.log(this.#myField); +>console.log(this.#myField) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>this.#myField : string +>this : this + } +} + diff --git a/tests/baselines/reference/privateNameFieldAssignment.js b/tests/baselines/reference/privateNameFieldAssignment.js new file mode 100644 index 0000000000000..34040558f1f42 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldAssignment.js @@ -0,0 +1,78 @@ +//// [privateNameFieldAssignment.ts] +class A { + #field = 0; + constructor() { + this.#field = 1; + this.#field += 2; + this.#field -= 3; + this.#field /= 4; + this.#field *= 5; + this.#field **= 6; + this.#field %= 7; + this.#field <<= 8; + this.#field >>= 9; + this.#field >>>= 10; + this.#field &= 11; + this.#field |= 12; + this.#field ^= 13; + A.getInstance().#field = 1; + A.getInstance().#field += 2; + A.getInstance().#field -= 3; + A.getInstance().#field /= 4; + A.getInstance().#field *= 5; + A.getInstance().#field **= 6; + A.getInstance().#field %= 7; + A.getInstance().#field <<= 8; + A.getInstance().#field >>= 9; + A.getInstance().#field >>>= 10; + A.getInstance().#field &= 11; + A.getInstance().#field |= 12; + A.getInstance().#field ^= 13; + } + static getInstance() { + return new A(); + } +} + + +//// [privateNameFieldAssignment.js] +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _field; +var A = /** @class */ (function () { + function A() { + _field.set(this, 0); + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m; + _classPrivateFieldSet(this, _field, 1); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) + 2); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) - 3); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) / 4); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) * 5); + _classPrivateFieldSet(this, _field, Math.pow(_classPrivateFieldGet(this, _field), 6)); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) % 7); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) << 8); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) >> 9); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) >>> 10); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) & 11); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) | 12); + _classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) ^ 13); + _classPrivateFieldSet(A.getInstance(), _field, 1); + _classPrivateFieldSet(_a = A.getInstance(), _field, _classPrivateFieldGet(_a, _field) + 2); + _classPrivateFieldSet(_b = A.getInstance(), _field, _classPrivateFieldGet(_b, _field) - 3); + _classPrivateFieldSet(_c = A.getInstance(), _field, _classPrivateFieldGet(_c, _field) / 4); + _classPrivateFieldSet(_d = A.getInstance(), _field, _classPrivateFieldGet(_d, _field) * 5); + _classPrivateFieldSet(_e = A.getInstance(), _field, Math.pow(_classPrivateFieldGet(_e, _field), 6)); + _classPrivateFieldSet(_f = A.getInstance(), _field, _classPrivateFieldGet(_f, _field) % 7); + _classPrivateFieldSet(_g = A.getInstance(), _field, _classPrivateFieldGet(_g, _field) << 8); + _classPrivateFieldSet(_h = A.getInstance(), _field, _classPrivateFieldGet(_h, _field) >> 9); + _classPrivateFieldSet(_j = A.getInstance(), _field, _classPrivateFieldGet(_j, _field) >>> 10); + _classPrivateFieldSet(_k = A.getInstance(), _field, _classPrivateFieldGet(_k, _field) & 11); + _classPrivateFieldSet(_l = A.getInstance(), _field, _classPrivateFieldGet(_l, _field) | 12); + _classPrivateFieldSet(_m = A.getInstance(), _field, _classPrivateFieldGet(_m, _field) ^ 13); + } + A.getInstance = function () { + return new A(); + }; + return A; +}()); +_field = new WeakMap(); diff --git a/tests/baselines/reference/privateNameFieldAssignment.symbols b/tests/baselines/reference/privateNameFieldAssignment.symbols new file mode 100644 index 0000000000000..3f08ea141f07f --- /dev/null +++ b/tests/baselines/reference/privateNameFieldAssignment.symbols @@ -0,0 +1,146 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldAssignment.ts === +class A { +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + #field = 0; +>#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) + + constructor() { + this.#field = 1; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field += 2; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field -= 3; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field /= 4; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field *= 5; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field **= 6; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field %= 7; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field <<= 8; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field >>= 9; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field >>>= 10; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field &= 11; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field |= 12; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + this.#field ^= 13; +>this.#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + + A.getInstance().#field = 1; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field += 2; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field -= 3; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field /= 4; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field *= 5; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field **= 6; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field %= 7; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field <<= 8; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field >>= 9; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field >>>= 10; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field &= 11; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field |= 12; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + A.getInstance().#field ^= 13; +>A.getInstance().#field : Symbol(A.#field, Decl(privateNameFieldAssignment.ts, 0, 9)) +>A.getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + } + static getInstance() { +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldAssignment.ts, 29, 5)) + + return new A(); +>A : Symbol(A, Decl(privateNameFieldAssignment.ts, 0, 0)) + } +} + diff --git a/tests/baselines/reference/privateNameFieldAssignment.types b/tests/baselines/reference/privateNameFieldAssignment.types new file mode 100644 index 0000000000000..8a3c507c393f0 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldAssignment.types @@ -0,0 +1,213 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldAssignment.ts === +class A { +>A : A + + #field = 0; +>#field : number +>0 : 0 + + constructor() { + this.#field = 1; +>this.#field = 1 : 1 +>this.#field : number +>this : this +>1 : 1 + + this.#field += 2; +>this.#field += 2 : number +>this.#field : number +>this : this +>2 : 2 + + this.#field -= 3; +>this.#field -= 3 : number +>this.#field : number +>this : this +>3 : 3 + + this.#field /= 4; +>this.#field /= 4 : number +>this.#field : number +>this : this +>4 : 4 + + this.#field *= 5; +>this.#field *= 5 : number +>this.#field : number +>this : this +>5 : 5 + + this.#field **= 6; +>this.#field **= 6 : number +>this.#field : number +>this : this +>6 : 6 + + this.#field %= 7; +>this.#field %= 7 : number +>this.#field : number +>this : this +>7 : 7 + + this.#field <<= 8; +>this.#field <<= 8 : number +>this.#field : number +>this : this +>8 : 8 + + this.#field >>= 9; +>this.#field >>= 9 : number +>this.#field : number +>this : this +>9 : 9 + + this.#field >>>= 10; +>this.#field >>>= 10 : number +>this.#field : number +>this : this +>10 : 10 + + this.#field &= 11; +>this.#field &= 11 : number +>this.#field : number +>this : this +>11 : 11 + + this.#field |= 12; +>this.#field |= 12 : number +>this.#field : number +>this : this +>12 : 12 + + this.#field ^= 13; +>this.#field ^= 13 : number +>this.#field : number +>this : this +>13 : 13 + + A.getInstance().#field = 1; +>A.getInstance().#field = 1 : 1 +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>1 : 1 + + A.getInstance().#field += 2; +>A.getInstance().#field += 2 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>2 : 2 + + A.getInstance().#field -= 3; +>A.getInstance().#field -= 3 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>3 : 3 + + A.getInstance().#field /= 4; +>A.getInstance().#field /= 4 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>4 : 4 + + A.getInstance().#field *= 5; +>A.getInstance().#field *= 5 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>5 : 5 + + A.getInstance().#field **= 6; +>A.getInstance().#field **= 6 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>6 : 6 + + A.getInstance().#field %= 7; +>A.getInstance().#field %= 7 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>7 : 7 + + A.getInstance().#field <<= 8; +>A.getInstance().#field <<= 8 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>8 : 8 + + A.getInstance().#field >>= 9; +>A.getInstance().#field >>= 9 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>9 : 9 + + A.getInstance().#field >>>= 10; +>A.getInstance().#field >>>= 10 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>10 : 10 + + A.getInstance().#field &= 11; +>A.getInstance().#field &= 11 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>11 : 11 + + A.getInstance().#field |= 12; +>A.getInstance().#field |= 12 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>12 : 12 + + A.getInstance().#field ^= 13; +>A.getInstance().#field ^= 13 : number +>A.getInstance().#field : number +>A.getInstance() : A +>A.getInstance : () => A +>A : typeof A +>getInstance : () => A +>13 : 13 + } + static getInstance() { +>getInstance : () => A + + return new A(); +>new A() : A +>A : typeof A + } +} + diff --git a/tests/baselines/reference/privateNameFieldCallExpression.js b/tests/baselines/reference/privateNameFieldCallExpression.js new file mode 100644 index 0000000000000..b1b1260faee53 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldCallExpression.js @@ -0,0 +1,29 @@ +//// [privateNameFieldCallExpression.ts] +class A { + #fieldFunc = () => this.x = 10; + x = 1; + test() { + this.#fieldFunc(); + const func = this.#fieldFunc; + func(); + } +} + + +//// [privateNameFieldCallExpression.js] +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _fieldFunc; +var A = /** @class */ (function () { + function A() { + var _this = this; + _fieldFunc.set(this, function () { return _this.x = 10; }); + this.x = 1; + } + A.prototype.test = function () { + _classPrivateFieldGet(this, _fieldFunc).call(this); + var func = _classPrivateFieldGet(this, _fieldFunc); + func(); + }; + return A; +}()); +_fieldFunc = new WeakMap(); diff --git a/tests/baselines/reference/privateNameFieldCallExpression.symbols b/tests/baselines/reference/privateNameFieldCallExpression.symbols new file mode 100644 index 0000000000000..692141acb9878 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldCallExpression.symbols @@ -0,0 +1,30 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldCallExpression.ts === +class A { +>A : Symbol(A, Decl(privateNameFieldCallExpression.ts, 0, 0)) + + #fieldFunc = () => this.x = 10; +>#fieldFunc : Symbol(A.#fieldFunc, Decl(privateNameFieldCallExpression.ts, 0, 9)) +>this.x : Symbol(A.x, Decl(privateNameFieldCallExpression.ts, 1, 35)) +>this : Symbol(A, Decl(privateNameFieldCallExpression.ts, 0, 0)) +>x : Symbol(A.x, Decl(privateNameFieldCallExpression.ts, 1, 35)) + + x = 1; +>x : Symbol(A.x, Decl(privateNameFieldCallExpression.ts, 1, 35)) + + test() { +>test : Symbol(A.test, Decl(privateNameFieldCallExpression.ts, 2, 10)) + + this.#fieldFunc(); +>this.#fieldFunc : Symbol(A.#fieldFunc, Decl(privateNameFieldCallExpression.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldCallExpression.ts, 0, 0)) + + const func = this.#fieldFunc; +>func : Symbol(func, Decl(privateNameFieldCallExpression.ts, 5, 13)) +>this.#fieldFunc : Symbol(A.#fieldFunc, Decl(privateNameFieldCallExpression.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldCallExpression.ts, 0, 0)) + + func(); +>func : Symbol(func, Decl(privateNameFieldCallExpression.ts, 5, 13)) + } +} + diff --git a/tests/baselines/reference/privateNameFieldCallExpression.types b/tests/baselines/reference/privateNameFieldCallExpression.types new file mode 100644 index 0000000000000..e9d12b0d1741c --- /dev/null +++ b/tests/baselines/reference/privateNameFieldCallExpression.types @@ -0,0 +1,36 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldCallExpression.ts === +class A { +>A : A + + #fieldFunc = () => this.x = 10; +>#fieldFunc : () => number +>() => this.x = 10 : () => number +>this.x = 10 : 10 +>this.x : number +>this : this +>x : number +>10 : 10 + + x = 1; +>x : number +>1 : 1 + + test() { +>test : () => void + + this.#fieldFunc(); +>this.#fieldFunc() : number +>this.#fieldFunc : () => number +>this : this + + const func = this.#fieldFunc; +>func : () => number +>this.#fieldFunc : () => number +>this : this + + func(); +>func() : number +>func : () => number + } +} + diff --git a/tests/baselines/reference/privateNameFieldDestructuredBinding.js b/tests/baselines/reference/privateNameFieldDestructuredBinding.js new file mode 100644 index 0000000000000..dadf60bab9d08 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldDestructuredBinding.js @@ -0,0 +1,37 @@ +//// [privateNameFieldDestructuredBinding.ts] +class A { + #field = 1; + testObject() { + return { x: 10, y: 6 }; + } + testArray() { + return [10, 11]; + } + constructor() { + let y: number; + ({ x: this.#field, y } = this.testObject()); + ([this.#field, y] = this.testArray()); + } +} + + +//// [privateNameFieldDestructuredBinding.js] +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +var _field; +var A = /** @class */ (function () { + function A() { + var _a, _b; + _field.set(this, 1); + var y; + (_a = this.testObject(), { set value(x) { _classPrivateFieldSet(this, _field, x); } }.value = _a.x, y = _a.y); + (_b = this.testArray(), { set value(x) { _classPrivateFieldSet(this, _field, x); } }.value = _b[0], y = _b[1]); + } + A.prototype.testObject = function () { + return { x: 10, y: 6 }; + }; + A.prototype.testArray = function () { + return [10, 11]; + }; + return A; +}()); +_field = new WeakMap(); diff --git a/tests/baselines/reference/privateNameFieldDestructuredBinding.symbols b/tests/baselines/reference/privateNameFieldDestructuredBinding.symbols new file mode 100644 index 0000000000000..efa03587dfc98 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldDestructuredBinding.symbols @@ -0,0 +1,42 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldDestructuredBinding.ts === +class A { +>A : Symbol(A, Decl(privateNameFieldDestructuredBinding.ts, 0, 0)) + + #field = 1; +>#field : Symbol(A.#field, Decl(privateNameFieldDestructuredBinding.ts, 0, 9)) + + testObject() { +>testObject : Symbol(A.testObject, Decl(privateNameFieldDestructuredBinding.ts, 1, 15)) + + return { x: 10, y: 6 }; +>x : Symbol(x, Decl(privateNameFieldDestructuredBinding.ts, 3, 16)) +>y : Symbol(y, Decl(privateNameFieldDestructuredBinding.ts, 3, 23)) + } + testArray() { +>testArray : Symbol(A.testArray, Decl(privateNameFieldDestructuredBinding.ts, 4, 5)) + + return [10, 11]; + } + constructor() { + let y: number; +>y : Symbol(y, Decl(privateNameFieldDestructuredBinding.ts, 9, 11)) + + ({ x: this.#field, y } = this.testObject()); +>x : Symbol(x, Decl(privateNameFieldDestructuredBinding.ts, 10, 10)) +>this.#field : Symbol(A.#field, Decl(privateNameFieldDestructuredBinding.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldDestructuredBinding.ts, 0, 0)) +>y : Symbol(y, Decl(privateNameFieldDestructuredBinding.ts, 10, 26)) +>this.testObject : Symbol(A.testObject, Decl(privateNameFieldDestructuredBinding.ts, 1, 15)) +>this : Symbol(A, Decl(privateNameFieldDestructuredBinding.ts, 0, 0)) +>testObject : Symbol(A.testObject, Decl(privateNameFieldDestructuredBinding.ts, 1, 15)) + + ([this.#field, y] = this.testArray()); +>this.#field : Symbol(A.#field, Decl(privateNameFieldDestructuredBinding.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldDestructuredBinding.ts, 0, 0)) +>y : Symbol(y, Decl(privateNameFieldDestructuredBinding.ts, 9, 11)) +>this.testArray : Symbol(A.testArray, Decl(privateNameFieldDestructuredBinding.ts, 4, 5)) +>this : Symbol(A, Decl(privateNameFieldDestructuredBinding.ts, 0, 0)) +>testArray : Symbol(A.testArray, Decl(privateNameFieldDestructuredBinding.ts, 4, 5)) + } +} + diff --git a/tests/baselines/reference/privateNameFieldDestructuredBinding.types b/tests/baselines/reference/privateNameFieldDestructuredBinding.types new file mode 100644 index 0000000000000..b948b04e66cd7 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldDestructuredBinding.types @@ -0,0 +1,57 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldDestructuredBinding.ts === +class A { +>A : A + + #field = 1; +>#field : number +>1 : 1 + + testObject() { +>testObject : () => { x: number; y: number; } + + return { x: 10, y: 6 }; +>{ x: 10, y: 6 } : { x: number; y: number; } +>x : number +>10 : 10 +>y : number +>6 : 6 + } + testArray() { +>testArray : () => number[] + + return [10, 11]; +>[10, 11] : number[] +>10 : 10 +>11 : 11 + } + constructor() { + let y: number; +>y : number + + ({ x: this.#field, y } = this.testObject()); +>({ x: this.#field, y } = this.testObject()) : { x: number; y: number; } +>{ x: this.#field, y } = this.testObject() : { x: number; y: number; } +>{ x: this.#field, y } : { x: number; y: number; } +>x : number +>this.#field : number +>this : this +>y : number +>this.testObject() : { x: number; y: number; } +>this.testObject : () => { x: number; y: number; } +>this : this +>testObject : () => { x: number; y: number; } + + ([this.#field, y] = this.testArray()); +>([this.#field, y] = this.testArray()) : number[] +>[this.#field, y] = this.testArray() : number[] +>[this.#field, y] : [number, number] +>this.#field : number +>this : this +>y : number +>this.testArray() : number[] +>this.testArray : () => number[] +>this : this +>testArray : () => number[] + } +} + diff --git a/tests/baselines/reference/privateNameFieldInitializer.js b/tests/baselines/reference/privateNameFieldInitializer.js new file mode 100644 index 0000000000000..8f40b98bb096e --- /dev/null +++ b/tests/baselines/reference/privateNameFieldInitializer.js @@ -0,0 +1,17 @@ +//// [privateNameFieldInitializer.ts] +class A { + #field = 10; + #uninitialized; +} + + +//// [privateNameFieldInitializer.js] +var _field, _uninitialized; +var A = /** @class */ (function () { + function A() { + _field.set(this, 10); + _uninitialized.set(this, void 0); + } + return A; +}()); +_field = new WeakMap(), _uninitialized = new WeakMap(); diff --git a/tests/baselines/reference/privateNameFieldInitializer.symbols b/tests/baselines/reference/privateNameFieldInitializer.symbols new file mode 100644 index 0000000000000..015a4f9ef4aa1 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldInitializer.symbols @@ -0,0 +1,11 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldInitializer.ts === +class A { +>A : Symbol(A, Decl(privateNameFieldInitializer.ts, 0, 0)) + + #field = 10; +>#field : Symbol(A.#field, Decl(privateNameFieldInitializer.ts, 0, 9)) + + #uninitialized; +>#uninitialized : Symbol(A.#uninitialized, Decl(privateNameFieldInitializer.ts, 1, 16)) +} + diff --git a/tests/baselines/reference/privateNameFieldInitializer.types b/tests/baselines/reference/privateNameFieldInitializer.types new file mode 100644 index 0000000000000..e6e701777c80c --- /dev/null +++ b/tests/baselines/reference/privateNameFieldInitializer.types @@ -0,0 +1,12 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldInitializer.ts === +class A { +>A : A + + #field = 10; +>#field : number +>10 : 10 + + #uninitialized; +>#uninitialized : any +} + diff --git a/tests/baselines/reference/privateNameFieldUnaryMutation.js b/tests/baselines/reference/privateNameFieldUnaryMutation.js new file mode 100644 index 0000000000000..e3fb0956b41dd --- /dev/null +++ b/tests/baselines/reference/privateNameFieldUnaryMutation.js @@ -0,0 +1,43 @@ +//// [privateNameFieldUnaryMutation.ts] +class C { + #test: number = 24; + constructor() { + this.#test++; + this.#test--; + ++this.#test; + --this.#test; + } + test() { + this.getInstance().#test++; + this.getInstance().#test--; + ++this.getInstance().#test; + --this.getInstance().#test; + } + getInstance() { return new C(); } +} + + +//// [privateNameFieldUnaryMutation.js] +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +var _test; +var C = /** @class */ (function () { + function C() { + _test.set(this, 24); + var _a, _b; + _a = _classPrivateFieldGet(this, _test), _classPrivateFieldSet(this, _test, _a + 1), _a; + _b = _classPrivateFieldGet(this, _test), _classPrivateFieldSet(this, _test, _b - 1), _b; + _classPrivateFieldSet(this, _test, _classPrivateFieldGet(this, _test) + 1); + _classPrivateFieldSet(this, _test, _classPrivateFieldGet(this, _test) - 1); + } + C.prototype.test = function () { + var _a, _b, _c, _d, _e, _f; + _a = this.getInstance(), _b = _classPrivateFieldGet(_a, _test), _classPrivateFieldSet(_a, _test, _b + 1), _b; + _c = this.getInstance(), _d = _classPrivateFieldGet(_c, _test), _classPrivateFieldSet(_c, _test, _d - 1), _d; + _classPrivateFieldSet(_e = this.getInstance(), _test, _classPrivateFieldGet(_e, _test) + 1); + _classPrivateFieldSet(_f = this.getInstance(), _test, _classPrivateFieldGet(_f, _test) - 1); + }; + C.prototype.getInstance = function () { return new C(); }; + return C; +}()); +_test = new WeakMap(); diff --git a/tests/baselines/reference/privateNameFieldUnaryMutation.symbols b/tests/baselines/reference/privateNameFieldUnaryMutation.symbols new file mode 100644 index 0000000000000..f224ef769c379 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldUnaryMutation.symbols @@ -0,0 +1,56 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldUnaryMutation.ts === +class C { +>C : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) + + #test: number = 24; +>#test : Symbol(C.#test, Decl(privateNameFieldUnaryMutation.ts, 0, 9)) + + constructor() { + this.#test++; +>this.#test : Symbol(C.#test, Decl(privateNameFieldUnaryMutation.ts, 0, 9)) +>this : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) + + this.#test--; +>this.#test : Symbol(C.#test, Decl(privateNameFieldUnaryMutation.ts, 0, 9)) +>this : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) + + ++this.#test; +>this.#test : Symbol(C.#test, Decl(privateNameFieldUnaryMutation.ts, 0, 9)) +>this : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) + + --this.#test; +>this.#test : Symbol(C.#test, Decl(privateNameFieldUnaryMutation.ts, 0, 9)) +>this : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) + } + test() { +>test : Symbol(C.test, Decl(privateNameFieldUnaryMutation.ts, 7, 5)) + + this.getInstance().#test++; +>this.getInstance().#test : Symbol(C.#test, Decl(privateNameFieldUnaryMutation.ts, 0, 9)) +>this.getInstance : Symbol(C.getInstance, Decl(privateNameFieldUnaryMutation.ts, 13, 5)) +>this : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) +>getInstance : Symbol(C.getInstance, Decl(privateNameFieldUnaryMutation.ts, 13, 5)) + + this.getInstance().#test--; +>this.getInstance().#test : Symbol(C.#test, Decl(privateNameFieldUnaryMutation.ts, 0, 9)) +>this.getInstance : Symbol(C.getInstance, Decl(privateNameFieldUnaryMutation.ts, 13, 5)) +>this : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) +>getInstance : Symbol(C.getInstance, Decl(privateNameFieldUnaryMutation.ts, 13, 5)) + + ++this.getInstance().#test; +>this.getInstance().#test : Symbol(C.#test, Decl(privateNameFieldUnaryMutation.ts, 0, 9)) +>this.getInstance : Symbol(C.getInstance, Decl(privateNameFieldUnaryMutation.ts, 13, 5)) +>this : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) +>getInstance : Symbol(C.getInstance, Decl(privateNameFieldUnaryMutation.ts, 13, 5)) + + --this.getInstance().#test; +>this.getInstance().#test : Symbol(C.#test, Decl(privateNameFieldUnaryMutation.ts, 0, 9)) +>this.getInstance : Symbol(C.getInstance, Decl(privateNameFieldUnaryMutation.ts, 13, 5)) +>this : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) +>getInstance : Symbol(C.getInstance, Decl(privateNameFieldUnaryMutation.ts, 13, 5)) + } + getInstance() { return new C(); } +>getInstance : Symbol(C.getInstance, Decl(privateNameFieldUnaryMutation.ts, 13, 5)) +>C : Symbol(C, Decl(privateNameFieldUnaryMutation.ts, 0, 0)) +} + diff --git a/tests/baselines/reference/privateNameFieldUnaryMutation.types b/tests/baselines/reference/privateNameFieldUnaryMutation.types new file mode 100644 index 0000000000000..130aa9bf39f82 --- /dev/null +++ b/tests/baselines/reference/privateNameFieldUnaryMutation.types @@ -0,0 +1,70 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameFieldUnaryMutation.ts === +class C { +>C : C + + #test: number = 24; +>#test : number +>24 : 24 + + constructor() { + this.#test++; +>this.#test++ : number +>this.#test : number +>this : this + + this.#test--; +>this.#test-- : number +>this.#test : number +>this : this + + ++this.#test; +>++this.#test : number +>this.#test : number +>this : this + + --this.#test; +>--this.#test : number +>this.#test : number +>this : this + } + test() { +>test : () => void + + this.getInstance().#test++; +>this.getInstance().#test++ : number +>this.getInstance().#test : number +>this.getInstance() : C +>this.getInstance : () => C +>this : this +>getInstance : () => C + + this.getInstance().#test--; +>this.getInstance().#test-- : number +>this.getInstance().#test : number +>this.getInstance() : C +>this.getInstance : () => C +>this : this +>getInstance : () => C + + ++this.getInstance().#test; +>++this.getInstance().#test : number +>this.getInstance().#test : number +>this.getInstance() : C +>this.getInstance : () => C +>this : this +>getInstance : () => C + + --this.getInstance().#test; +>--this.getInstance().#test : number +>this.getInstance().#test : number +>this.getInstance() : C +>this.getInstance : () => C +>this : this +>getInstance : () => C + } + getInstance() { return new C(); } +>getInstance : () => C +>new C() : C +>C : typeof C +} + diff --git a/tests/baselines/reference/privateNameNestedClassNameConflict.js b/tests/baselines/reference/privateNameNestedClassNameConflict.js new file mode 100644 index 0000000000000..d8e0e240a7a6b --- /dev/null +++ b/tests/baselines/reference/privateNameNestedClassNameConflict.js @@ -0,0 +1,28 @@ +//// [privateNameNestedClassNameConflict.ts] +class A { + #foo: string; + constructor() { + class A { + #foo: string; + } + } +} + + +//// [privateNameNestedClassNameConflict.js] +var _foo; +var A = /** @class */ (function () { + function A() { + _foo.set(this, void 0); + var _foo_1; + var A = /** @class */ (function () { + function A() { + _foo_1.set(this, void 0); + } + return A; + }()); + _foo_1 = new WeakMap(); + } + return A; +}()); +_foo = new WeakMap(); diff --git a/tests/baselines/reference/privateNameNestedClassNameConflict.symbols b/tests/baselines/reference/privateNameNestedClassNameConflict.symbols new file mode 100644 index 0000000000000..5fec01b052701 --- /dev/null +++ b/tests/baselines/reference/privateNameNestedClassNameConflict.symbols @@ -0,0 +1,17 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameNestedClassNameConflict.ts === +class A { +>A : Symbol(A, Decl(privateNameNestedClassNameConflict.ts, 0, 0)) + + #foo: string; +>#foo : Symbol(A.#foo, Decl(privateNameNestedClassNameConflict.ts, 0, 9)) + + constructor() { + class A { +>A : Symbol(A, Decl(privateNameNestedClassNameConflict.ts, 2, 19)) + + #foo: string; +>#foo : Symbol(A.#foo, Decl(privateNameNestedClassNameConflict.ts, 3, 17)) + } + } +} + diff --git a/tests/baselines/reference/privateNameNestedClassNameConflict.types b/tests/baselines/reference/privateNameNestedClassNameConflict.types new file mode 100644 index 0000000000000..de6589940da50 --- /dev/null +++ b/tests/baselines/reference/privateNameNestedClassNameConflict.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameNestedClassNameConflict.ts === +class A { +>A : A + + #foo: string; +>#foo : string + + constructor() { + class A { +>A : A + + #foo: string; +>#foo : string + } + } +} + diff --git a/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.js b/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.js index 7ea7a6b5f370c..655f3c7c55d37 100644 --- a/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.js +++ b/tests/baselines/reference/privateNameNotAccessibleOutsideDefiningClass.js @@ -9,12 +9,14 @@ new A().#foo = 4; // Error //// [privateNameNotAccessibleOutsideDefiningClass.js] -"use strict"; // @target es6 +var _foo; +"use strict"; var A = /** @class */ (function () { function A() { - this.#foo = 3; + _foo.set(this, 3); } return A; }()); +_foo = new WeakMap(); new A().#foo = 4; // Error diff --git a/tests/baselines/reference/privateNameSneakyRuntimeException.js b/tests/baselines/reference/privateNameSneakyRuntimeException.js index 11914013c8af0..e437f4da29fb5 100644 --- a/tests/baselines/reference/privateNameSneakyRuntimeException.js +++ b/tests/baselines/reference/privateNameSneakyRuntimeException.js @@ -19,16 +19,21 @@ console.log(a.equals(b)); // OK at compile time but will be a runtime error //// [privateNameSneakyRuntimeException.js] "use strict"; // @target es6 +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; function createClass() { - return /** @class */ (function () { - function class_1() { - this.#foo = 3; - } - class_1.prototype.equals = function (other) { - return this.#foo = other.#foo; - }; - return class_1; - }()); + var _foo, _a; + return _a = /** @class */ (function () { + function class_1() { + _foo.set(this, 3); + } + class_1.prototype.equals = function (other) { + return _classPrivateFieldSet(this, _foo, _classPrivateFieldGet(other, _foo)); + }; + return class_1; + }()), + _foo = new WeakMap(), + _a; } var a = new (createClass())(); var b = new (createClass())(); diff --git a/tests/baselines/reference/privateNamesAndDecorators.js b/tests/baselines/reference/privateNamesAndDecorators.js index 57ab082f418bb..3e2e760933e12 100644 --- a/tests/baselines/reference/privateNamesAndDecorators.js +++ b/tests/baselines/reference/privateNamesAndDecorators.js @@ -10,10 +10,12 @@ class A { //// [privateNamesAndDecorators.js] +var _foo; var A = /** @class */ (function () { function A() { - this.#foo = 1; + _foo.set(this, 1); } A.prototype.#bar = function () { }; return A; }()); +_foo = new WeakMap(); diff --git a/tests/baselines/reference/privateNamesAndFields.js b/tests/baselines/reference/privateNamesAndFields.js index dc5a000d32a1b..4af48cfe9b245 100644 --- a/tests/baselines/reference/privateNamesAndFields.js +++ b/tests/baselines/reference/privateNamesAndFields.js @@ -18,7 +18,6 @@ class B extends A { //// [privateNamesAndFields.js] -"use strict"; // @target es6 var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { @@ -33,18 +32,25 @@ var __extends = (this && this.__extends) || (function () { d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +var _foo, _foo_1; +"use strict"; var A = /** @class */ (function () { function A() { - this.#foo = 3; + _foo.set(this, void 0); + _classPrivateFieldSet(this, _foo, 3); } return A; }()); +_foo = new WeakMap(); var B = /** @class */ (function (_super) { __extends(B, _super); function B() { var _this = _super.call(this) || this; - _this.#foo = "some string"; + _foo_1.set(_this, void 0); + _classPrivateFieldSet(_this, _foo_1, "some string"); return _this; } return B; }(A)); +_foo_1 = new WeakMap(); diff --git a/tests/baselines/reference/privateNamesAndGenericClasses-2.js b/tests/baselines/reference/privateNamesAndGenericClasses-2.js index 69ef447e71d1d..972af4a681e20 100644 --- a/tests/baselines/reference/privateNamesAndGenericClasses-2.js +++ b/tests/baselines/reference/privateNamesAndGenericClasses-2.js @@ -28,22 +28,27 @@ b = a; // Error //// [privateNamesAndGenericClasses-2.js] +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _foo; "use strict"; class C { constructor(t) { - this.#foo = t; - t = this.#bar(); + _foo.set(this, void 0); + _classPrivateFieldSet(this, _foo, t); + t = this.#bar.call(this); } #bar() { - return this.#foo; + return _classPrivateFieldGet(this, _foo); } set baz(t) { - this.#foo = t; + _classPrivateFieldSet(this, _foo, t); } get baz() { - return this.#foo; + return _classPrivateFieldGet(this, _foo); } } +_foo = new WeakMap(); let a = new C(3); let b = new C("hello"); a.baz = 5; // OK diff --git a/tests/baselines/reference/privateNamesAndIndexedAccess.js b/tests/baselines/reference/privateNamesAndIndexedAccess.js index b03c0f9ececeb..44dde9629a8c6 100644 --- a/tests/baselines/reference/privateNamesAndIndexedAccess.js +++ b/tests/baselines/reference/privateNamesAndIndexedAccess.js @@ -13,11 +13,13 @@ class C { //// [privateNamesAndIndexedAccess.js] +var _bar, _bar_1; "use strict"; class C { constructor() { this.foo = 3; - this.#bar = 3; + _bar_1.set(this, 3); + _bar_1.set(this, void 0); // will never use this syntax, already taken: this.badAlways = 3; // Error const ok = 3; @@ -25,3 +27,4 @@ class C { const badForNow; } } +_bar = new WeakMap(), _bar_1 = new WeakMap(); diff --git a/tests/baselines/reference/privateNamesAndMethods.js b/tests/baselines/reference/privateNamesAndMethods.js index 8ca4192b12fd0..7cb222a061164 100644 --- a/tests/baselines/reference/privateNamesAndMethods.js +++ b/tests/baselines/reference/privateNamesAndMethods.js @@ -31,30 +31,35 @@ class B extends A { //// [privateNamesAndMethods.js] +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +var __quux; class A { + constructor() { + __quux.set(this, void 0); + this.#foo.call(this, 30); + this.#bar.call(this, 30); + this.#bar.call(this, 30); + this.#quux = this.#quux + 1; + this.#quux++; + } #foo(a) { } async #bar(a) { } async *#baz(a) { return 3; } get #quux() { - return this.#_quux; + return _classPrivateFieldGet(this, __quux); } set #quux(val) { - this.#_quux = val; - } - constructor() { - this.#foo(30); - this.#bar(30); - this.#bar(30); - this.#quux = this.#quux + 1; - this.#quux++; + _classPrivateFieldSet(this, __quux, val); } } +__quux = new WeakMap(); class B extends A { - #foo(a) { } constructor() { super(); - this.#foo("str"); + this.#foo.call(this, "str"); } + #foo(a) { } } diff --git a/tests/baselines/reference/privateNamesAndStaticFields.js b/tests/baselines/reference/privateNamesAndStaticFields.js index 00f1c5fbe5a0a..7beaa98bdb674 100644 --- a/tests/baselines/reference/privateNamesAndStaticFields.js +++ b/tests/baselines/reference/privateNamesAndStaticFields.js @@ -18,7 +18,6 @@ class B extends A { //// [privateNamesAndStaticFields.js] -"use strict"; // @target es6 var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { @@ -33,18 +32,23 @@ var __extends = (this && this.__extends) || (function () { d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +var _foo, _foo_1; +"use strict"; var A = /** @class */ (function () { function A() { - A.#foo = 3; + _classPrivateFieldSet(A, _foo, 3); } return A; }()); +_foo = new WeakMap(); var B = /** @class */ (function (_super) { __extends(B, _super); function B() { var _this = _super.call(this) || this; - B.#foo = "some string"; + _classPrivateFieldSet(B, _foo_1, "some string"); return _this; } return B; }(A)); +_foo_1 = new WeakMap(); diff --git a/tests/baselines/reference/privateNamesAndStaticMethods.js b/tests/baselines/reference/privateNamesAndStaticMethods.js index 7de87a421fe9d..b021f6a606635 100644 --- a/tests/baselines/reference/privateNamesAndStaticMethods.js +++ b/tests/baselines/reference/privateNamesAndStaticMethods.js @@ -31,31 +31,37 @@ class B extends A { //// [privateNamesAndStaticMethods.js] +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; }; +var __quux; "use strict"; class A { + constructor() { + var _a, _b, _c; + (_a = A).#foo.call(_a, 30); + (_b = A).#bar.call(_b, 30); + (_c = A).#bar.call(_c, 30); + A.#quux = A.#quux + 1; + A.#quux++; + } static #foo(a) { } static async #bar(a) { } static async *#baz(a) { return 3; } static get #quux() { - return this.#_quux; + return _classPrivateFieldGet(this, __quux); } static set #quux(val) { - this.#_quux = val; - } - constructor() { - A.#foo(30); - A.#bar(30); - A.#bar(30); - A.#quux = A.#quux + 1; - A.#quux++; + _classPrivateFieldSet(this, __quux, val); } } +__quux = new WeakMap(); class B extends A { - static #foo(a) { } constructor() { + var _a; super(); - B.#foo("str"); + (_a = B).#foo.call(_a, "str"); } + static #foo(a) { } } diff --git a/tests/baselines/reference/privateNamesAndkeyof.js b/tests/baselines/reference/privateNamesAndkeyof.js index d6dbd5d92f796..eeaade8458fc7 100644 --- a/tests/baselines/reference/privateNamesAndkeyof.js +++ b/tests/baselines/reference/privateNamesAndkeyof.js @@ -11,13 +11,15 @@ type T = keyof A // should not include '#foo' //// [privateNamesAndkeyof.js] -"use strict"; // @target es6 +var _foo; +"use strict"; var A = /** @class */ (function () { function A() { - this.#foo = 3; + _foo.set(this, 3); this.bar = 3; this.baz = 3; } return A; }()); +_foo = new WeakMap(); diff --git a/tests/baselines/reference/privateNamesInGenericClasses.js b/tests/baselines/reference/privateNamesInGenericClasses.js index 8f547b1a659a8..e92f777e3b673 100644 --- a/tests/baselines/reference/privateNamesInGenericClasses.js +++ b/tests/baselines/reference/privateNamesInGenericClasses.js @@ -14,12 +14,18 @@ b = a; // Error //// [privateNamesInGenericClasses.js] +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _foo; "use strict"; class C { - bar(x) { return x.#foo; } // OK - baz(x) { return x.#foo; } // OK - quux(x) { return x.#foo; } // OK + constructor() { + _foo.set(this, void 0); + } + bar(x) { return _classPrivateFieldGet(x, _foo); } // OK + baz(x) { return _classPrivateFieldGet(x, _foo); } // OK + quux(x) { return _classPrivateFieldGet(x, _foo); } // OK } +_foo = new WeakMap(); a.#foo; // Error a = b; // Error b = a; // Error diff --git a/tests/baselines/reference/privateNamesInNestedClasses.js b/tests/baselines/reference/privateNamesInNestedClasses.js index acf6099d96c11..021528ae47be5 100644 --- a/tests/baselines/reference/privateNamesInNestedClasses.js +++ b/tests/baselines/reference/privateNamesInNestedClasses.js @@ -28,29 +28,33 @@ class A { new A().method(); //// [privateNamesInNestedClasses.js] -"use strict"; // @target es6 +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _foo, _bar; +"use strict"; var A = /** @class */ (function () { function A() { - this.#foo = "A's #foo"; - this.#bar = "A's #bar"; + _foo.set(this, "A's #foo"); + _bar.set(this, "A's #bar"); } A.prototype.method = function () { + var _foo_1; var B = /** @class */ (function () { function B() { - this.#foo = "B's #foo"; + _foo_1.set(this, "B's #foo"); } B.prototype.bar = function (a) { - a.#foo; // OK, no compile-time error, don't know what `a` is + _classPrivateFieldGet(a, _foo_1); // OK, no compile-time error, don't know what `a` is }; B.prototype.baz = function (a) { - a.#foo; // compile-time error, shadowed + _classPrivateFieldGet(a, _foo_1); // compile-time error, shadowed }; B.prototype.quux = function (b) { - b.#foo; // OK + _classPrivateFieldGet(b, _foo_1); // OK }; return B; }()); + _foo_1 = new WeakMap(); var a = new A(); new B().bar(a); new B().baz(a); @@ -59,4 +63,5 @@ var A = /** @class */ (function () { }; return A; }()); +_foo = new WeakMap(), _bar = new WeakMap(); new A().method(); diff --git a/tests/baselines/reference/privateNamesNoAccessibilityModifiers.js b/tests/baselines/reference/privateNamesNoAccessibilityModifiers.js index 081090dbf645f..23e102b0fa7d7 100644 --- a/tests/baselines/reference/privateNamesNoAccessibilityModifiers.js +++ b/tests/baselines/reference/privateNamesNoAccessibilityModifiers.js @@ -10,14 +10,16 @@ class A { //// [privateNamesNoAccessibilityModifiers.js] -"use strict"; // @target es6 +var _foo, _bar, _baz, _qux; +"use strict"; var A = /** @class */ (function () { function A() { - this.#foo = 3; // Error - this.#bar = 3; // Error - this.#baz = 3; // Error - this.#qux = 3; // OK + _foo.set(this, 3); // Error + _bar.set(this, 3); // Error + _baz.set(this, 3); // Error + _qux.set(this, 3); // OK } return A; }()); +_foo = new WeakMap(), _bar = new WeakMap(), _baz = new WeakMap(), _qux = new WeakMap(); diff --git a/tests/baselines/reference/privateNamesNoConflictWhenInheriting.js b/tests/baselines/reference/privateNamesNoConflictWhenInheriting.js index e25509c4c843a..f54b9d2f8cd6d 100644 --- a/tests/baselines/reference/privateNamesNoConflictWhenInheriting.js +++ b/tests/baselines/reference/privateNamesNoConflictWhenInheriting.js @@ -13,7 +13,6 @@ const b: A = new B() // OK //// [privateNamesNoConflictWhenInheriting.js] -"use strict"; // @target es6 var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { @@ -28,16 +27,23 @@ var __extends = (this && this.__extends) || (function () { d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); +var _foo, _foo_1; +"use strict"; var A = /** @class */ (function () { function A() { + _foo.set(this, void 0); } return A; }()); +_foo = new WeakMap(); var B = /** @class */ (function (_super) { __extends(B, _super); function B() { - return _super !== null && _super.apply(this, arguments) || this; + var _this = _super !== null && _super.apply(this, arguments) || this; + _foo_1.set(_this, void 0); // OK: private names are unique to each class + return _this; } return B; }(A)); +_foo_1 = new WeakMap(); var b = new B(); // OK diff --git a/tests/baselines/reference/privateNamesNoDelete.js b/tests/baselines/reference/privateNamesNoDelete.js index 741b7aaa7dca7..b7826b3aea2f4 100644 --- a/tests/baselines/reference/privateNamesNoDelete.js +++ b/tests/baselines/reference/privateNamesNoDelete.js @@ -10,12 +10,15 @@ class A { //// [privateNamesNoDelete.js] -"use strict"; // @target es6 +var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); }; +var _v; +"use strict"; var A = /** @class */ (function () { function A() { - this.#v = 1; - delete this.#v; // Error: The operand of a delete operator cannot be a private name. + _v.set(this, 1); + delete _classPrivateFieldGet(this, _v); // Error: The operand of a delete operator cannot be a private name. } return A; }()); +_v = new WeakMap(); diff --git a/tests/baselines/reference/privateNamesNotAllowedAsParameters.js b/tests/baselines/reference/privateNamesNotAllowedAsParameters.js index 8c3a394e1ac03..ab41d7579b42d 100644 --- a/tests/baselines/reference/privateNamesNotAllowedAsParameters.js +++ b/tests/baselines/reference/privateNamesNotAllowedAsParameters.js @@ -8,10 +8,13 @@ class A { //// [privateNamesNotAllowedAsParameters.js] // @target es6 +var _foo; var A = /** @class */ (function () { function A() { + _foo.set(this, void 0); } A.prototype.setFoo = function () { }; return A; }()); +_foo = new WeakMap(); { } diff --git a/tests/baselines/reference/privateNamesUnique.js b/tests/baselines/reference/privateNamesUnique.js index 52c8a3bc69799..a55fe8af1faa1 100644 --- a/tests/baselines/reference/privateNamesUnique.js +++ b/tests/baselines/reference/privateNamesUnique.js @@ -13,16 +13,21 @@ const b: A = new B(); // Error: Property #foo is missing //// [privateNamesUnique.js] -"use strict"; // @target es6 +var _foo, _foo_1; +"use strict"; var A = /** @class */ (function () { function A() { + _foo.set(this, void 0); } return A; }()); +_foo = new WeakMap(); var B = /** @class */ (function () { function B() { + _foo_1.set(this, void 0); } return B; }()); +_foo_1 = new WeakMap(); var b = new B(); // Error: Property #foo is missing diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameDeclaration.ts b/tests/cases/conformance/classes/members/privateNames/privateNameDeclaration.ts new file mode 100644 index 0000000000000..e111e4af3d614 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameDeclaration.ts @@ -0,0 +1,3 @@ +class A { + #name: string; +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameFieldAccess.ts b/tests/cases/conformance/classes/members/privateNames/privateNameFieldAccess.ts new file mode 100644 index 0000000000000..42b30a058dc03 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameFieldAccess.ts @@ -0,0 +1,6 @@ +class A { + #myField = "hello world"; + constructor() { + console.log(this.#myField); + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameFieldAssignment.ts b/tests/cases/conformance/classes/members/privateNames/privateNameFieldAssignment.ts new file mode 100644 index 0000000000000..c4551908427b9 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameFieldAssignment.ts @@ -0,0 +1,34 @@ +class A { + #field = 0; + constructor() { + this.#field = 1; + this.#field += 2; + this.#field -= 3; + this.#field /= 4; + this.#field *= 5; + this.#field **= 6; + this.#field %= 7; + this.#field <<= 8; + this.#field >>= 9; + this.#field >>>= 10; + this.#field &= 11; + this.#field |= 12; + this.#field ^= 13; + A.getInstance().#field = 1; + A.getInstance().#field += 2; + A.getInstance().#field -= 3; + A.getInstance().#field /= 4; + A.getInstance().#field *= 5; + A.getInstance().#field **= 6; + A.getInstance().#field %= 7; + A.getInstance().#field <<= 8; + A.getInstance().#field >>= 9; + A.getInstance().#field >>>= 10; + A.getInstance().#field &= 11; + A.getInstance().#field |= 12; + A.getInstance().#field ^= 13; + } + static getInstance() { + return new A(); + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameFieldCallExpression.ts b/tests/cases/conformance/classes/members/privateNames/privateNameFieldCallExpression.ts new file mode 100644 index 0000000000000..8feb41dbeb081 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameFieldCallExpression.ts @@ -0,0 +1,9 @@ +class A { + #fieldFunc = () => this.x = 10; + x = 1; + test() { + this.#fieldFunc(); + const func = this.#fieldFunc; + func(); + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameFieldDestructuredBinding.ts b/tests/cases/conformance/classes/members/privateNames/privateNameFieldDestructuredBinding.ts new file mode 100644 index 0000000000000..e68d32e8bdb56 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameFieldDestructuredBinding.ts @@ -0,0 +1,14 @@ +class A { + #field = 1; + testObject() { + return { x: 10, y: 6 }; + } + testArray() { + return [10, 11]; + } + constructor() { + let y: number; + ({ x: this.#field, y } = this.testObject()); + ([this.#field, y] = this.testArray()); + } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameFieldInitializer.ts b/tests/cases/conformance/classes/members/privateNames/privateNameFieldInitializer.ts new file mode 100644 index 0000000000000..fa58a79d9f993 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameFieldInitializer.ts @@ -0,0 +1,4 @@ +class A { + #field = 10; + #uninitialized; +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameFieldUnaryMutation.ts b/tests/cases/conformance/classes/members/privateNames/privateNameFieldUnaryMutation.ts new file mode 100644 index 0000000000000..84dd6da2ec4d9 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameFieldUnaryMutation.ts @@ -0,0 +1,16 @@ +class C { + #test: number = 24; + constructor() { + this.#test++; + this.#test--; + ++this.#test; + --this.#test; + } + test() { + this.getInstance().#test++; + this.getInstance().#test--; + ++this.getInstance().#test; + --this.getInstance().#test; + } + getInstance() { return new C(); } +} diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameNestedClassNameConflict.ts b/tests/cases/conformance/classes/members/privateNames/privateNameNestedClassNameConflict.ts new file mode 100644 index 0000000000000..ba0bbe1b8c7f9 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameNestedClassNameConflict.ts @@ -0,0 +1,8 @@ +class A { + #foo: string; + constructor() { + class A { + #foo: string; + } + } +}