From a64e6919ef94a90ae9514260a9a4890c3193f81c Mon Sep 17 00:00:00 2001 From: Joseph Watts Date: Fri, 8 Mar 2019 16:46:17 -0500 Subject: [PATCH] Add private named instance field transformation Signed-off-by: Joseph Watts --- 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 8ccfb2a010381..07498d85b989a 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 5778b47a4f8b4..66089c15388d3 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -667,28 +667,6 @@ namespace ts { } } - function isCompoundAssignment(kind: BinaryOperator): kind is CompoundAssignmentOperator { - return kind >= SyntaxKind.FirstCompoundAssignment - && kind <= SyntaxKind.LastCompoundAssignment; - } - - function getOperatorForCompoundAssignment(kind: CompoundAssignmentOperator): BitwiseOperatorOrHigher { - switch (kind) { - case SyntaxKind.PlusEqualsToken: return SyntaxKind.PlusToken; - case SyntaxKind.MinusEqualsToken: return SyntaxKind.MinusToken; - case SyntaxKind.AsteriskEqualsToken: return SyntaxKind.AsteriskToken; - case SyntaxKind.AsteriskAsteriskEqualsToken: return SyntaxKind.AsteriskAsteriskToken; - case SyntaxKind.SlashEqualsToken: return SyntaxKind.SlashToken; - case SyntaxKind.PercentEqualsToken: return SyntaxKind.PercentToken; - case SyntaxKind.LessThanLessThanEqualsToken: return SyntaxKind.LessThanLessThanToken; - case SyntaxKind.GreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanToken; - case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanGreaterThanToken; - case SyntaxKind.AmpersandEqualsToken: return SyntaxKind.AmpersandToken; - case SyntaxKind.BarEqualsToken: return SyntaxKind.BarToken; - case SyntaxKind.CaretEqualsToken: return SyntaxKind.CaretToken; - } - } - /** * Visits a right-associative binary expression containing `yield`. * diff --git a/src/compiler/transformers/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 6c71d4d427302..b8c2323e0a000 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -944,6 +944,11 @@ namespace ts { initializer?: Expression; // Optional initializer } + /*@internal*/ + export interface PrivateNamedPropertyDeclaration extends PropertyDeclaration { + name: PrivateName; + } + export interface ObjectLiteralElement extends NamedDeclaration { _objectLiteralBrandBrand: any; name?: PropertyName; @@ -1768,6 +1773,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 e00c14d22a926..4807ddd1563b4 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -6251,6 +6251,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; + } + } +}