diff --git a/_packages/api/src/node/protocol.generated.ts b/_packages/api/src/node/protocol.generated.ts index 1abfddf12a..e428075a2e 100644 --- a/_packages/api/src/node/protocol.generated.ts +++ b/_packages/api/src/node/protocol.generated.ts @@ -124,6 +124,7 @@ export const childProperties: Readonly; +} export interface JsxElement extends PrimaryExpressionBase { readonly kind: SyntaxKind.JsxElement; readonly openingElement: JsxOpeningElement; diff --git a/_packages/ast/src/enums/syntaxKind.enum.ts b/_packages/ast/src/enums/syntaxKind.enum.ts index d5bf4fc78f..08a43ccd0c 100644 --- a/_packages/ast/src/enums/syntaxKind.enum.ts +++ b/_packages/ast/src/enums/syntaxKind.enum.ts @@ -352,9 +352,10 @@ export enum SyntaxKind { JSImportDeclaration = 348, NotEmittedStatement = 349, PartiallyEmittedExpression = 350, - SyntheticReferenceExpression = 351, - NotEmittedTypeElement = 352, - Count = 353, + CommaListExpression = 351, + SyntheticReferenceExpression = 352, + NotEmittedTypeElement = 353, + Count = 354, FirstAssignment = EqualsToken, LastAssignment = CaretEqualsToken, FirstCompoundAssignment = PlusEqualsToken, diff --git a/_packages/ast/src/enums/syntaxKind.ts b/_packages/ast/src/enums/syntaxKind.ts index c4f8e3931f..2cdd7822be 100644 --- a/_packages/ast/src/enums/syntaxKind.ts +++ b/_packages/ast/src/enums/syntaxKind.ts @@ -352,9 +352,10 @@ export var SyntaxKind: any; SyntaxKind[SyntaxKind["JSImportDeclaration"] = 348] = "JSImportDeclaration"; SyntaxKind[SyntaxKind["NotEmittedStatement"] = 349] = "NotEmittedStatement"; SyntaxKind[SyntaxKind["PartiallyEmittedExpression"] = 350] = "PartiallyEmittedExpression"; - SyntaxKind[SyntaxKind["SyntheticReferenceExpression"] = 351] = "SyntheticReferenceExpression"; - SyntaxKind[SyntaxKind["NotEmittedTypeElement"] = 352] = "NotEmittedTypeElement"; - SyntaxKind[SyntaxKind["Count"] = 353] = "Count"; + SyntaxKind[SyntaxKind["CommaListExpression"] = 351] = "CommaListExpression"; + SyntaxKind[SyntaxKind["SyntheticReferenceExpression"] = 352] = "SyntheticReferenceExpression"; + SyntaxKind[SyntaxKind["NotEmittedTypeElement"] = 353] = "NotEmittedTypeElement"; + SyntaxKind[SyntaxKind["Count"] = 354] = "Count"; SyntaxKind[SyntaxKind["FirstAssignment"] = 63] = "FirstAssignment"; SyntaxKind[SyntaxKind["LastAssignment"] = 78] = "LastAssignment"; SyntaxKind[SyntaxKind["FirstCompoundAssignment"] = 64] = "FirstCompoundAssignment"; diff --git a/_packages/ast/src/factory.generated.ts b/_packages/ast/src/factory.generated.ts index 0cd991bbd2..d88fa50178 100644 --- a/_packages/ast/src/factory.generated.ts +++ b/_packages/ast/src/factory.generated.ts @@ -31,6 +31,7 @@ import type { ClassExpression, ClassStaticBlockDeclaration, ColonToken, + CommaListExpression, CommonJSExport, ComputedPropertyName, ConciseBody, @@ -943,6 +944,8 @@ function cloneNodeData(node: Node): any { return { type: n.type, isSpread: n.isSpread, tupleNameSource: n.tupleNameSource }; case SyntaxKind.PartiallyEmittedExpression: return { expression: n.expression }; + case SyntaxKind.CommaListExpression: + return { elements: n.elements }; case SyntaxKind.JsxElement: return { openingElement: n.openingElement, children: n.children, closingElement: n.closingElement }; case SyntaxKind.JsxAttributes: @@ -1440,6 +1443,7 @@ const forEachChildTable: Record = { visitNode(cbNode, data.literal), [SyntaxKind.SyntheticExpression]: (data, cbNode, cbNodes) => visitNode(cbNode, data.tupleNameSource), [SyntaxKind.PartiallyEmittedExpression]: (data, cbNode, cbNodes) => visitNode(cbNode, data.expression), + [SyntaxKind.CommaListExpression]: (data, cbNode, cbNodes) => visitNodes(cbNode, cbNodes, data.elements), [SyntaxKind.JsxElement]: (data, cbNode, cbNodes) => visitNode(cbNode, data.openingElement) || visitNodes(cbNode, cbNodes, data.children) || @@ -2617,6 +2621,12 @@ export function createPartiallyEmittedExpression(expression: Expression): Partia }) as unknown as PartiallyEmittedExpression; } +export function createCommaListExpression(elements: readonly Expression[]): CommaListExpression { + return new NodeObject(SyntaxKind.CommaListExpression, { + elements: createNodeArray(elements), + }) as unknown as CommaListExpression; +} + export function createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement { return new NodeObject(SyntaxKind.JsxElement, { openingElement, @@ -3541,6 +3551,10 @@ export function updatePartiallyEmittedExpression(node: PartiallyEmittedExpressio return node.expression !== expression ? createPartiallyEmittedExpression(expression) : node; } +export function updateCommaListExpression(node: CommaListExpression, elements: readonly Expression[]): CommaListExpression { + return node.elements !== elements ? createCommaListExpression(elements) : node; +} + export function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement { return node.openingElement !== openingElement || node.children !== children || node.closingElement !== closingElement ? createJsxElement(openingElement, children, closingElement) : node; } diff --git a/_packages/ast/src/is.generated.ts b/_packages/ast/src/is.generated.ts index b68a2e8cf9..1e9919b12a 100644 --- a/_packages/ast/src/is.generated.ts +++ b/_packages/ast/src/is.generated.ts @@ -51,6 +51,7 @@ import type { ClassLikeDeclaration, ClassStaticBlockDeclaration, ColonToken, + CommaListExpression, CommonJSExport, CompoundAssignmentOperator, ComputedPropertyName, @@ -872,6 +873,10 @@ export function isPartiallyEmittedExpression(node: Node): node is PartiallyEmitt return node.kind === SyntaxKind.PartiallyEmittedExpression; } +export function isCommaListExpression(node: Node): node is CommaListExpression { + return node.kind === SyntaxKind.CommaListExpression; +} + export function isJsxElement(node: Node): node is JsxElement { return node.kind === SyntaxKind.JsxElement; } diff --git a/_packages/ast/src/visitor.generated.ts b/_packages/ast/src/visitor.generated.ts index a3da2d52c3..256ee1dead 100644 --- a/_packages/ast/src/visitor.generated.ts +++ b/_packages/ast/src/visitor.generated.ts @@ -20,6 +20,7 @@ import type { ClassDeclaration, ClassExpression, ClassStaticBlockDeclaration, + CommaListExpression, CommonJSExport, ComputedPropertyName, ConditionalExpression, @@ -197,6 +198,7 @@ import { updateClassDeclaration, updateClassExpression, updateClassStaticBlockDeclaration, + updateCommaListExpression, updateCommonJSExport, updateComputedPropertyName, updateConditionalExpression, @@ -1134,6 +1136,10 @@ const visitEachChildTable: Record = { const _expression = visitNode(node.expression, visitor, isExpression); return updatePartiallyEmittedExpression(node, _expression); }, + [SyntaxKind.CommaListExpression]: (node: CommaListExpression, visitor: Visitor): CommaListExpression => { + const _elements = visitNodes(node.elements, visitor); + return updateCommaListExpression(node, _elements); + }, [SyntaxKind.JsxElement]: (node: JsxElement, visitor: Visitor): JsxElement => { const _openingElement = visitNode(node.openingElement, visitor, isJsxOpeningElement); const _children = visitNodes(node.children, visitor); diff --git a/_scripts/ast.json b/_scripts/ast.json index e5c56b0135..00e7799a39 100644 --- a/_scripts/ast.json +++ b/_scripts/ast.json @@ -446,6 +446,7 @@ }, "NotEmittedStatement", "PartiallyEmittedExpression", + "CommaListExpression", "SyntheticReferenceExpression", "NotEmittedTypeElement" ], @@ -4076,6 +4077,19 @@ } ] }, + "CommaListExpression": { + "generateSubtreeFacts": true, + "extends": [ + "ExpressionBase" + ], + "members": [ + { + "name": "Elements", + "type": "Expression", + "list": "NodeList" + } + ] + }, "JsxElement": { "extends": [ "PrimaryExpressionBase", diff --git a/internal/api/encoder/decoder_generated.go b/internal/api/encoder/decoder_generated.go index 464b52adb8..bc5ee11f1f 100644 --- a/internal/api/encoder/decoder_generated.go +++ b/internal/api/encoder/decoder_generated.go @@ -866,6 +866,8 @@ func (d *astDecoder) createChildrenNode(kind ast.Kind, data uint32, childIndices return d.factory.NewSyntheticExpression(typeNode, isSpread, d.singleChild(childIndices)), nil case ast.KindPartiallyEmittedExpression: return d.factory.NewPartiallyEmittedExpression(d.singleChild(childIndices)), nil + case ast.KindCommaListExpression: + return d.factory.NewCommaListExpression(d.singleNodeListChild(childIndices)), nil case ast.KindJsxElement: it := newChildIter(childIndices) openingElement := d.nodeAt(it.nextIf(mask, 0)) diff --git a/internal/api/encoder/encoder_generated.go b/internal/api/encoder/encoder_generated.go index f58b8f15e0..5937adb543 100644 --- a/internal/api/encoder/encoder_generated.go +++ b/internal/api/encoder/encoder_generated.go @@ -380,6 +380,9 @@ func getChildrenPropertyMask(node *ast.Node) uint8 { case ast.KindPartiallyEmittedExpression: n := node.AsPartiallyEmittedExpression() return (boolToByte(n.Expression != nil) << 0) + case ast.KindCommaListExpression: + n := node.AsCommaListExpression() + return (boolToByte(n.Elements != nil) << 0) case ast.KindJsxElement: n := node.AsJsxElement() return (boolToByte(n.OpeningElement != nil) << 0) | (boolToByte(n.Children != nil) << 1) | (boolToByte(n.ClosingElement != nil) << 2) diff --git a/internal/ast/ast.go b/internal/ast/ast.go index 60c983f35f..ac19d5fc2a 100644 --- a/internal/ast/ast.go +++ b/internal/ast/ast.go @@ -1049,6 +1049,8 @@ func (n *Node) ElementList() *NodeList { return n.AsArrayLiteralExpression().Elements case KindTupleType: return n.AsTupleTypeNode().Elements + case KindCommaListExpression: + return n.AsCommaListExpression().Elements } panic("Unhandled case in Node.ElementList: " + n.Kind.String()) } diff --git a/internal/ast/ast_generated.go b/internal/ast/ast_generated.go index 027541b65d..9705dcea40 100644 --- a/internal/ast/ast_generated.go +++ b/internal/ast/ast_generated.go @@ -385,6 +385,7 @@ type ( TemplateLiteralTypeSpanNode = Node SyntheticExpressionNode = Node PartiallyEmittedExpressionNode = Node + CommaListExpressionNode = Node JsxElementNode = Node JsxAttributesNode = Node JsxNamespacedNameNode = Node @@ -6597,6 +6598,48 @@ func IsPartiallyEmittedExpression(node *Node) bool { return node.Kind == KindPartiallyEmittedExpression } +// ────────────────────────────────────────────────────────────────────── +// CommaListExpression +// ────────────────────────────────────────────────────────────────────── + +type CommaListExpression struct { + ExpressionBase + Elements *ElementList +} + +func (f *NodeFactory) NewCommaListExpression(elements *ElementList) *Node { + data := &CommaListExpression{} + data.Elements = elements + return f.newNode(KindCommaListExpression, data) +} + +func (f *NodeFactory) UpdateCommaListExpression(node *CommaListExpression, elements *ElementList) *Node { + if elements != node.Elements { + return updateNode(f.NewCommaListExpression(elements), node.AsNode(), f.hooks) + } + return node.AsNode() +} + +func (node *CommaListExpression) ForEachChild(v Visitor) bool { + return visitNodeList(v, node.Elements) +} + +func (node *CommaListExpression) VisitEachChild(v *NodeVisitor) *Node { + return v.Factory.UpdateCommaListExpression(node, v.visitNodes(node.Elements)) +} + +func (node *CommaListExpression) Clone(f NodeFactoryCoercible) *Node { + return cloneNode(f.AsNodeFactory().NewCommaListExpression(node.Elements), node.AsNode(), f.AsNodeFactory().hooks) +} + +func (node *CommaListExpression) computeSubtreeFacts() SubtreeFacts { + return propagateNodeListSubtreeFacts(node.Elements, propagateSubtreeFacts) +} + +func IsCommaListExpression(node *Node) bool { + return node.Kind == KindCommaListExpression +} + // ────────────────────────────────────────────────────────────────────── // JsxElement // ────────────────────────────────────────────────────────────────────── @@ -9475,6 +9518,10 @@ func (n *Node) AsPartiallyEmittedExpression() *PartiallyEmittedExpression { return n.data.(*PartiallyEmittedExpression) } +func (n *Node) AsCommaListExpression() *CommaListExpression { + return n.data.(*CommaListExpression) +} + func (n *Node) AsJsxElement() *JsxElement { return n.data.(*JsxElement) } diff --git a/internal/ast/kind_generated.go b/internal/ast/kind_generated.go index 3b2c14dff2..43dfc0a0ac 100644 --- a/internal/ast/kind_generated.go +++ b/internal/ast/kind_generated.go @@ -388,6 +388,7 @@ const ( // Transformation nodes KindNotEmittedStatement KindPartiallyEmittedExpression + KindCommaListExpression KindSyntheticReferenceExpression KindNotEmittedTypeElement KindCount diff --git a/internal/ast/kind_stringer_generated.go b/internal/ast/kind_stringer_generated.go index 90cf01216c..12ed22baa4 100644 --- a/internal/ast/kind_stringer_generated.go +++ b/internal/ast/kind_stringer_generated.go @@ -359,14 +359,15 @@ func _() { _ = x[KindJSImportDeclaration-348] _ = x[KindNotEmittedStatement-349] _ = x[KindPartiallyEmittedExpression-350] - _ = x[KindSyntheticReferenceExpression-351] - _ = x[KindNotEmittedTypeElement-352] - _ = x[KindCount-353] + _ = x[KindCommaListExpression-351] + _ = x[KindSyntheticReferenceExpression-352] + _ = x[KindNotEmittedTypeElement-353] + _ = x[KindCount-354] } -const _Kind_name = "KindUnknownKindEndOfFileKindSingleLineCommentTriviaKindMultiLineCommentTriviaKindNewLineTriviaKindWhitespaceTriviaKindConflictMarkerTriviaKindNonTextFileMarkerTriviaKindNumericLiteralKindBigIntLiteralKindStringLiteralKindJsxTextKindJsxTextAllWhiteSpacesKindRegularExpressionLiteralKindNoSubstitutionTemplateLiteralKindTemplateHeadKindTemplateMiddleKindTemplateTailKindOpenBraceTokenKindCloseBraceTokenKindOpenParenTokenKindCloseParenTokenKindOpenBracketTokenKindCloseBracketTokenKindDotTokenKindDotDotDotTokenKindSemicolonTokenKindCommaTokenKindQuestionDotTokenKindLessThanTokenKindLessThanSlashTokenKindGreaterThanTokenKindLessThanEqualsTokenKindGreaterThanEqualsTokenKindEqualsEqualsTokenKindExclamationEqualsTokenKindEqualsEqualsEqualsTokenKindExclamationEqualsEqualsTokenKindEqualsGreaterThanTokenKindPlusTokenKindMinusTokenKindAsteriskTokenKindAsteriskAsteriskTokenKindSlashTokenKindPercentTokenKindPlusPlusTokenKindMinusMinusTokenKindLessThanLessThanTokenKindGreaterThanGreaterThanTokenKindGreaterThanGreaterThanGreaterThanTokenKindAmpersandTokenKindBarTokenKindCaretTokenKindExclamationTokenKindTildeTokenKindAmpersandAmpersandTokenKindBarBarTokenKindQuestionTokenKindColonTokenKindAtTokenKindQuestionQuestionTokenKindBacktickTokenKindHashTokenKindEqualsTokenKindPlusEqualsTokenKindMinusEqualsTokenKindAsteriskEqualsTokenKindAsteriskAsteriskEqualsTokenKindSlashEqualsTokenKindPercentEqualsTokenKindLessThanLessThanEqualsTokenKindGreaterThanGreaterThanEqualsTokenKindGreaterThanGreaterThanGreaterThanEqualsTokenKindAmpersandEqualsTokenKindBarEqualsTokenKindBarBarEqualsTokenKindAmpersandAmpersandEqualsTokenKindQuestionQuestionEqualsTokenKindCaretEqualsTokenKindIdentifierKindPrivateIdentifierKindJSDocCommentTextTokenKindBreakKeywordKindCaseKeywordKindCatchKeywordKindClassKeywordKindConstKeywordKindContinueKeywordKindDebuggerKeywordKindDefaultKeywordKindDeleteKeywordKindDoKeywordKindElseKeywordKindEnumKeywordKindExportKeywordKindExtendsKeywordKindFalseKeywordKindFinallyKeywordKindForKeywordKindFunctionKeywordKindIfKeywordKindImportKeywordKindInKeywordKindInstanceOfKeywordKindNewKeywordKindNullKeywordKindReturnKeywordKindSuperKeywordKindSwitchKeywordKindThisKeywordKindThrowKeywordKindTrueKeywordKindTryKeywordKindTypeOfKeywordKindVarKeywordKindVoidKeywordKindWhileKeywordKindWithKeywordKindImplementsKeywordKindInterfaceKeywordKindLetKeywordKindPackageKeywordKindPrivateKeywordKindProtectedKeywordKindPublicKeywordKindStaticKeywordKindYieldKeywordKindAbstractKeywordKindAccessorKeywordKindAsKeywordKindAssertsKeywordKindAssertKeywordKindAnyKeywordKindAsyncKeywordKindAwaitKeywordKindBooleanKeywordKindConstructorKeywordKindDeclareKeywordKindGetKeywordKindImmediateKeywordKindInferKeywordKindIntrinsicKeywordKindIsKeywordKindKeyOfKeywordKindModuleKeywordKindNamespaceKeywordKindNeverKeywordKindOutKeywordKindReadonlyKeywordKindRequireKeywordKindNumberKeywordKindObjectKeywordKindSatisfiesKeywordKindSetKeywordKindStringKeywordKindSymbolKeywordKindTypeKeywordKindUndefinedKeywordKindUniqueKeywordKindUnknownKeywordKindUsingKeywordKindFromKeywordKindGlobalKeywordKindBigIntKeywordKindOverrideKeywordKindOfKeywordKindDeferKeywordKindQualifiedNameKindComputedPropertyNameKindTypeParameterKindParameterKindDecoratorKindPropertySignatureKindPropertyDeclarationKindMethodSignatureKindMethodDeclarationKindClassStaticBlockDeclarationKindConstructorKindGetAccessorKindSetAccessorKindCallSignatureKindConstructSignatureKindIndexSignatureKindTypePredicateKindTypeReferenceKindFunctionTypeKindConstructorTypeKindTypeQueryKindTypeLiteralKindArrayTypeKindTupleTypeKindOptionalTypeKindRestTypeKindUnionTypeKindIntersectionTypeKindConditionalTypeKindInferTypeKindParenthesizedTypeKindThisTypeKindTypeOperatorKindIndexedAccessTypeKindMappedTypeKindLiteralTypeKindNamedTupleMemberKindTemplateLiteralTypeKindTemplateLiteralTypeSpanKindImportTypeKindObjectBindingPatternKindArrayBindingPatternKindBindingElementKindArrayLiteralExpressionKindObjectLiteralExpressionKindPropertyAccessExpressionKindElementAccessExpressionKindCallExpressionKindNewExpressionKindTaggedTemplateExpressionKindTypeAssertionExpressionKindParenthesizedExpressionKindFunctionExpressionKindArrowFunctionKindDeleteExpressionKindTypeOfExpressionKindVoidExpressionKindAwaitExpressionKindPrefixUnaryExpressionKindPostfixUnaryExpressionKindBinaryExpressionKindConditionalExpressionKindTemplateExpressionKindYieldExpressionKindSpreadElementKindClassExpressionKindOmittedExpressionKindExpressionWithTypeArgumentsKindAsExpressionKindNonNullExpressionKindMetaPropertyKindSyntheticExpressionKindSatisfiesExpressionKindTemplateSpanKindSemicolonClassElementKindBlockKindEmptyStatementKindVariableStatementKindExpressionStatementKindIfStatementKindDoStatementKindWhileStatementKindForStatementKindForInStatementKindForOfStatementKindContinueStatementKindBreakStatementKindReturnStatementKindWithStatementKindSwitchStatementKindLabeledStatementKindThrowStatementKindTryStatementKindDebuggerStatementKindVariableDeclarationKindVariableDeclarationListKindFunctionDeclarationKindClassDeclarationKindInterfaceDeclarationKindTypeAliasDeclarationKindEnumDeclarationKindModuleDeclarationKindModuleBlockKindCaseBlockKindNamespaceExportDeclarationKindImportEqualsDeclarationKindImportDeclarationKindImportClauseKindNamespaceImportKindNamedImportsKindImportSpecifierKindExportAssignmentKindExportDeclarationKindNamedExportsKindNamespaceExportKindExportSpecifierKindMissingDeclarationKindExternalModuleReferenceKindJsxElementKindJsxSelfClosingElementKindJsxOpeningElementKindJsxClosingElementKindJsxFragmentKindJsxOpeningFragmentKindJsxClosingFragmentKindJsxAttributeKindJsxAttributesKindJsxSpreadAttributeKindJsxExpressionKindJsxNamespacedNameKindCaseClauseKindDefaultClauseKindHeritageClauseKindCatchClauseKindImportAttributesKindImportAttributeKindPropertyAssignmentKindShorthandPropertyAssignmentKindSpreadAssignmentKindEnumMemberKindSourceFileKindJSDocTypeExpressionKindJSDocNameReferenceKindJSDocAllTypeKindJSDocNullableTypeKindJSDocNonNullableTypeKindJSDocOptionalTypeKindJSDocVariadicTypeKindJSDocKindJSDocTextKindJSDocTypeLiteralKindJSDocSignatureKindJSDocLinkKindJSDocLinkCodeKindJSDocLinkPlainKindJSDocUnknownTagKindJSDocAugmentsTagKindJSDocImplementsTagKindJSDocDeprecatedTagKindJSDocPublicTagKindJSDocPrivateTagKindJSDocProtectedTagKindJSDocReadonlyTagKindJSDocOverrideTagKindJSDocCallbackTagKindJSDocOverloadTagKindJSDocParameterTagKindJSDocReturnTagKindJSDocThisTagKindJSDocTypeTagKindJSDocTemplateTagKindJSDocTypedefTagKindJSDocSeeTagKindJSDocPropertyTagKindJSDocThrowsTagKindJSDocSatisfiesTagKindJSDocImportTagKindSyntaxListKindJSTypeAliasDeclarationKindJSExportAssignmentKindCommonJSExportKindJSImportDeclarationKindNotEmittedStatementKindPartiallyEmittedExpressionKindSyntheticReferenceExpressionKindNotEmittedTypeElementKindCount" +const _Kind_name = "KindUnknownKindEndOfFileKindSingleLineCommentTriviaKindMultiLineCommentTriviaKindNewLineTriviaKindWhitespaceTriviaKindConflictMarkerTriviaKindNonTextFileMarkerTriviaKindNumericLiteralKindBigIntLiteralKindStringLiteralKindJsxTextKindJsxTextAllWhiteSpacesKindRegularExpressionLiteralKindNoSubstitutionTemplateLiteralKindTemplateHeadKindTemplateMiddleKindTemplateTailKindOpenBraceTokenKindCloseBraceTokenKindOpenParenTokenKindCloseParenTokenKindOpenBracketTokenKindCloseBracketTokenKindDotTokenKindDotDotDotTokenKindSemicolonTokenKindCommaTokenKindQuestionDotTokenKindLessThanTokenKindLessThanSlashTokenKindGreaterThanTokenKindLessThanEqualsTokenKindGreaterThanEqualsTokenKindEqualsEqualsTokenKindExclamationEqualsTokenKindEqualsEqualsEqualsTokenKindExclamationEqualsEqualsTokenKindEqualsGreaterThanTokenKindPlusTokenKindMinusTokenKindAsteriskTokenKindAsteriskAsteriskTokenKindSlashTokenKindPercentTokenKindPlusPlusTokenKindMinusMinusTokenKindLessThanLessThanTokenKindGreaterThanGreaterThanTokenKindGreaterThanGreaterThanGreaterThanTokenKindAmpersandTokenKindBarTokenKindCaretTokenKindExclamationTokenKindTildeTokenKindAmpersandAmpersandTokenKindBarBarTokenKindQuestionTokenKindColonTokenKindAtTokenKindQuestionQuestionTokenKindBacktickTokenKindHashTokenKindEqualsTokenKindPlusEqualsTokenKindMinusEqualsTokenKindAsteriskEqualsTokenKindAsteriskAsteriskEqualsTokenKindSlashEqualsTokenKindPercentEqualsTokenKindLessThanLessThanEqualsTokenKindGreaterThanGreaterThanEqualsTokenKindGreaterThanGreaterThanGreaterThanEqualsTokenKindAmpersandEqualsTokenKindBarEqualsTokenKindBarBarEqualsTokenKindAmpersandAmpersandEqualsTokenKindQuestionQuestionEqualsTokenKindCaretEqualsTokenKindIdentifierKindPrivateIdentifierKindJSDocCommentTextTokenKindBreakKeywordKindCaseKeywordKindCatchKeywordKindClassKeywordKindConstKeywordKindContinueKeywordKindDebuggerKeywordKindDefaultKeywordKindDeleteKeywordKindDoKeywordKindElseKeywordKindEnumKeywordKindExportKeywordKindExtendsKeywordKindFalseKeywordKindFinallyKeywordKindForKeywordKindFunctionKeywordKindIfKeywordKindImportKeywordKindInKeywordKindInstanceOfKeywordKindNewKeywordKindNullKeywordKindReturnKeywordKindSuperKeywordKindSwitchKeywordKindThisKeywordKindThrowKeywordKindTrueKeywordKindTryKeywordKindTypeOfKeywordKindVarKeywordKindVoidKeywordKindWhileKeywordKindWithKeywordKindImplementsKeywordKindInterfaceKeywordKindLetKeywordKindPackageKeywordKindPrivateKeywordKindProtectedKeywordKindPublicKeywordKindStaticKeywordKindYieldKeywordKindAbstractKeywordKindAccessorKeywordKindAsKeywordKindAssertsKeywordKindAssertKeywordKindAnyKeywordKindAsyncKeywordKindAwaitKeywordKindBooleanKeywordKindConstructorKeywordKindDeclareKeywordKindGetKeywordKindImmediateKeywordKindInferKeywordKindIntrinsicKeywordKindIsKeywordKindKeyOfKeywordKindModuleKeywordKindNamespaceKeywordKindNeverKeywordKindOutKeywordKindReadonlyKeywordKindRequireKeywordKindNumberKeywordKindObjectKeywordKindSatisfiesKeywordKindSetKeywordKindStringKeywordKindSymbolKeywordKindTypeKeywordKindUndefinedKeywordKindUniqueKeywordKindUnknownKeywordKindUsingKeywordKindFromKeywordKindGlobalKeywordKindBigIntKeywordKindOverrideKeywordKindOfKeywordKindDeferKeywordKindQualifiedNameKindComputedPropertyNameKindTypeParameterKindParameterKindDecoratorKindPropertySignatureKindPropertyDeclarationKindMethodSignatureKindMethodDeclarationKindClassStaticBlockDeclarationKindConstructorKindGetAccessorKindSetAccessorKindCallSignatureKindConstructSignatureKindIndexSignatureKindTypePredicateKindTypeReferenceKindFunctionTypeKindConstructorTypeKindTypeQueryKindTypeLiteralKindArrayTypeKindTupleTypeKindOptionalTypeKindRestTypeKindUnionTypeKindIntersectionTypeKindConditionalTypeKindInferTypeKindParenthesizedTypeKindThisTypeKindTypeOperatorKindIndexedAccessTypeKindMappedTypeKindLiteralTypeKindNamedTupleMemberKindTemplateLiteralTypeKindTemplateLiteralTypeSpanKindImportTypeKindObjectBindingPatternKindArrayBindingPatternKindBindingElementKindArrayLiteralExpressionKindObjectLiteralExpressionKindPropertyAccessExpressionKindElementAccessExpressionKindCallExpressionKindNewExpressionKindTaggedTemplateExpressionKindTypeAssertionExpressionKindParenthesizedExpressionKindFunctionExpressionKindArrowFunctionKindDeleteExpressionKindTypeOfExpressionKindVoidExpressionKindAwaitExpressionKindPrefixUnaryExpressionKindPostfixUnaryExpressionKindBinaryExpressionKindConditionalExpressionKindTemplateExpressionKindYieldExpressionKindSpreadElementKindClassExpressionKindOmittedExpressionKindExpressionWithTypeArgumentsKindAsExpressionKindNonNullExpressionKindMetaPropertyKindSyntheticExpressionKindSatisfiesExpressionKindTemplateSpanKindSemicolonClassElementKindBlockKindEmptyStatementKindVariableStatementKindExpressionStatementKindIfStatementKindDoStatementKindWhileStatementKindForStatementKindForInStatementKindForOfStatementKindContinueStatementKindBreakStatementKindReturnStatementKindWithStatementKindSwitchStatementKindLabeledStatementKindThrowStatementKindTryStatementKindDebuggerStatementKindVariableDeclarationKindVariableDeclarationListKindFunctionDeclarationKindClassDeclarationKindInterfaceDeclarationKindTypeAliasDeclarationKindEnumDeclarationKindModuleDeclarationKindModuleBlockKindCaseBlockKindNamespaceExportDeclarationKindImportEqualsDeclarationKindImportDeclarationKindImportClauseKindNamespaceImportKindNamedImportsKindImportSpecifierKindExportAssignmentKindExportDeclarationKindNamedExportsKindNamespaceExportKindExportSpecifierKindMissingDeclarationKindExternalModuleReferenceKindJsxElementKindJsxSelfClosingElementKindJsxOpeningElementKindJsxClosingElementKindJsxFragmentKindJsxOpeningFragmentKindJsxClosingFragmentKindJsxAttributeKindJsxAttributesKindJsxSpreadAttributeKindJsxExpressionKindJsxNamespacedNameKindCaseClauseKindDefaultClauseKindHeritageClauseKindCatchClauseKindImportAttributesKindImportAttributeKindPropertyAssignmentKindShorthandPropertyAssignmentKindSpreadAssignmentKindEnumMemberKindSourceFileKindJSDocTypeExpressionKindJSDocNameReferenceKindJSDocAllTypeKindJSDocNullableTypeKindJSDocNonNullableTypeKindJSDocOptionalTypeKindJSDocVariadicTypeKindJSDocKindJSDocTextKindJSDocTypeLiteralKindJSDocSignatureKindJSDocLinkKindJSDocLinkCodeKindJSDocLinkPlainKindJSDocUnknownTagKindJSDocAugmentsTagKindJSDocImplementsTagKindJSDocDeprecatedTagKindJSDocPublicTagKindJSDocPrivateTagKindJSDocProtectedTagKindJSDocReadonlyTagKindJSDocOverrideTagKindJSDocCallbackTagKindJSDocOverloadTagKindJSDocParameterTagKindJSDocReturnTagKindJSDocThisTagKindJSDocTypeTagKindJSDocTemplateTagKindJSDocTypedefTagKindJSDocSeeTagKindJSDocPropertyTagKindJSDocThrowsTagKindJSDocSatisfiesTagKindJSDocImportTagKindSyntaxListKindJSTypeAliasDeclarationKindJSExportAssignmentKindCommonJSExportKindJSImportDeclarationKindNotEmittedStatementKindPartiallyEmittedExpressionKindCommaListExpressionKindSyntheticReferenceExpressionKindNotEmittedTypeElementKindCount" -var _Kind_index = [...]uint16{0, 11, 24, 51, 77, 94, 114, 138, 165, 183, 200, 217, 228, 253, 281, 314, 330, 348, 364, 382, 401, 419, 438, 458, 479, 491, 509, 527, 541, 561, 578, 600, 620, 643, 669, 690, 716, 743, 775, 801, 814, 828, 845, 870, 884, 900, 917, 936, 961, 992, 1034, 1052, 1064, 1078, 1098, 1112, 1139, 1154, 1171, 1185, 1196, 1221, 1238, 1251, 1266, 1285, 1305, 1328, 1359, 1379, 1401, 1432, 1469, 1517, 1541, 1559, 1580, 1613, 1644, 1664, 1678, 1699, 1724, 1740, 1755, 1771, 1787, 1803, 1822, 1841, 1859, 1876, 1889, 1904, 1919, 1936, 1954, 1970, 1988, 2002, 2021, 2034, 2051, 2064, 2085, 2099, 2114, 2131, 2147, 2164, 2179, 2195, 2210, 2224, 2241, 2255, 2270, 2286, 2301, 2322, 2342, 2356, 2374, 2392, 2412, 2429, 2446, 2462, 2481, 2500, 2513, 2531, 2548, 2562, 2578, 2594, 2612, 2634, 2652, 2666, 2686, 2702, 2722, 2735, 2751, 2768, 2788, 2804, 2818, 2837, 2855, 2872, 2889, 2909, 2923, 2940, 2957, 2972, 2992, 3009, 3027, 3043, 3058, 3075, 3092, 3111, 3124, 3140, 3157, 3181, 3198, 3211, 3224, 3245, 3268, 3287, 3308, 3339, 3354, 3369, 3384, 3401, 3423, 3441, 3458, 3475, 3491, 3510, 3523, 3538, 3551, 3564, 3580, 3592, 3605, 3625, 3644, 3657, 3678, 3690, 3706, 3727, 3741, 3756, 3776, 3799, 3826, 3840, 3864, 3887, 3905, 3931, 3958, 3986, 4013, 4031, 4048, 4076, 4103, 4130, 4152, 4169, 4189, 4209, 4227, 4246, 4271, 4297, 4317, 4342, 4364, 4383, 4400, 4419, 4440, 4471, 4487, 4508, 4524, 4547, 4570, 4586, 4611, 4620, 4638, 4659, 4682, 4697, 4712, 4730, 4746, 4764, 4782, 4803, 4821, 4840, 4857, 4876, 4896, 4914, 4930, 4951, 4974, 5001, 5024, 5044, 5068, 5092, 5111, 5132, 5147, 5160, 5190, 5217, 5238, 5254, 5273, 5289, 5308, 5328, 5349, 5365, 5384, 5403, 5425, 5452, 5466, 5491, 5512, 5533, 5548, 5570, 5592, 5608, 5625, 5647, 5664, 5685, 5699, 5716, 5734, 5749, 5769, 5788, 5810, 5841, 5861, 5875, 5889, 5912, 5934, 5950, 5971, 5995, 6016, 6037, 6046, 6059, 6079, 6097, 6110, 6127, 6145, 6164, 6184, 6206, 6228, 6246, 6265, 6286, 6306, 6326, 6346, 6366, 6387, 6405, 6421, 6437, 6457, 6476, 6491, 6511, 6529, 6550, 6568, 6582, 6608, 6630, 6648, 6671, 6694, 6724, 6756, 6781, 6790} +var _Kind_index = [...]uint16{0, 11, 24, 51, 77, 94, 114, 138, 165, 183, 200, 217, 228, 253, 281, 314, 330, 348, 364, 382, 401, 419, 438, 458, 479, 491, 509, 527, 541, 561, 578, 600, 620, 643, 669, 690, 716, 743, 775, 801, 814, 828, 845, 870, 884, 900, 917, 936, 961, 992, 1034, 1052, 1064, 1078, 1098, 1112, 1139, 1154, 1171, 1185, 1196, 1221, 1238, 1251, 1266, 1285, 1305, 1328, 1359, 1379, 1401, 1432, 1469, 1517, 1541, 1559, 1580, 1613, 1644, 1664, 1678, 1699, 1724, 1740, 1755, 1771, 1787, 1803, 1822, 1841, 1859, 1876, 1889, 1904, 1919, 1936, 1954, 1970, 1988, 2002, 2021, 2034, 2051, 2064, 2085, 2099, 2114, 2131, 2147, 2164, 2179, 2195, 2210, 2224, 2241, 2255, 2270, 2286, 2301, 2322, 2342, 2356, 2374, 2392, 2412, 2429, 2446, 2462, 2481, 2500, 2513, 2531, 2548, 2562, 2578, 2594, 2612, 2634, 2652, 2666, 2686, 2702, 2722, 2735, 2751, 2768, 2788, 2804, 2818, 2837, 2855, 2872, 2889, 2909, 2923, 2940, 2957, 2972, 2992, 3009, 3027, 3043, 3058, 3075, 3092, 3111, 3124, 3140, 3157, 3181, 3198, 3211, 3224, 3245, 3268, 3287, 3308, 3339, 3354, 3369, 3384, 3401, 3423, 3441, 3458, 3475, 3491, 3510, 3523, 3538, 3551, 3564, 3580, 3592, 3605, 3625, 3644, 3657, 3678, 3690, 3706, 3727, 3741, 3756, 3776, 3799, 3826, 3840, 3864, 3887, 3905, 3931, 3958, 3986, 4013, 4031, 4048, 4076, 4103, 4130, 4152, 4169, 4189, 4209, 4227, 4246, 4271, 4297, 4317, 4342, 4364, 4383, 4400, 4419, 4440, 4471, 4487, 4508, 4524, 4547, 4570, 4586, 4611, 4620, 4638, 4659, 4682, 4697, 4712, 4730, 4746, 4764, 4782, 4803, 4821, 4840, 4857, 4876, 4896, 4914, 4930, 4951, 4974, 5001, 5024, 5044, 5068, 5092, 5111, 5132, 5147, 5160, 5190, 5217, 5238, 5254, 5273, 5289, 5308, 5328, 5349, 5365, 5384, 5403, 5425, 5452, 5466, 5491, 5512, 5533, 5548, 5570, 5592, 5608, 5625, 5647, 5664, 5685, 5699, 5716, 5734, 5749, 5769, 5788, 5810, 5841, 5861, 5875, 5889, 5912, 5934, 5950, 5971, 5995, 6016, 6037, 6046, 6059, 6079, 6097, 6110, 6127, 6145, 6164, 6184, 6206, 6228, 6246, 6265, 6286, 6306, 6326, 6346, 6366, 6387, 6405, 6421, 6437, 6457, 6476, 6491, 6511, 6529, 6550, 6568, 6582, 6608, 6630, 6648, 6671, 6694, 6724, 6747, 6779, 6804, 6813} func (i Kind) String() string { idx := int(i) - 0 diff --git a/internal/ast/precedence.go b/internal/ast/precedence.go index 1288c86d1b..b79f998ad0 100644 --- a/internal/ast/precedence.go +++ b/internal/ast/precedence.go @@ -222,6 +222,8 @@ const ( // Gets the precedence of an operator func GetOperatorPrecedence(nodeKind Kind, operatorKind Kind, flags OperatorPrecedenceFlags) OperatorPrecedence { switch nodeKind { + case KindCommaListExpression: + return OperatorPrecedenceComma case KindSpreadElement: return OperatorPrecedenceSpread case KindYieldExpression: diff --git a/internal/ast/utilities.go b/internal/ast/utilities.go index 85d5dfab8f..7f250ee3cc 100644 --- a/internal/ast/utilities.go +++ b/internal/ast/utilities.go @@ -440,6 +440,7 @@ func isExpressionKind(kind Kind) bool { KindSpreadElement, KindAsExpression, KindOmittedExpression, + KindCommaListExpression, KindPartiallyEmittedExpression, KindSatisfiesExpression: return true @@ -457,7 +458,7 @@ func IsCommaExpression(node *Node) bool { } func IsCommaSequence(node *Node) bool { - return IsCommaExpression(node) + return IsCommaExpression(node) || IsCommaListExpression(node) } func IsIterationStatement(node *Node, lookInLabeledStatements bool) bool { diff --git a/internal/ast/visitor.go b/internal/ast/visitor.go index b0b7db54d9..1895fd0c3b 100644 --- a/internal/ast/visitor.go +++ b/internal/ast/visitor.go @@ -257,6 +257,33 @@ func (v *NodeVisitor) visitTopLevelStatements(nodes *StatementList) *StatementLi return v.visitNodes(nodes) } +// VisitCommaListElements visits the elements of a CommaListExpression. +// The visitor is used to visit the last element (the "value" element). +// The discardVisitor is used to visit all other elements whose result will be discarded at runtime. +// If discardVisitor is nil, it defaults to visitor. +func VisitCommaListElements(elements *NodeList, visitor *NodeVisitor, discardVisitor *NodeVisitor) *NodeList { + if discardVisitor == nil { + discardVisitor = visitor + } + if discardVisitor == visitor || elements == nil || len(elements.Nodes) <= 1 { + return visitor.VisitNodes(elements) + } + length := len(elements.Nodes) + i := 0 + combined := &NodeVisitor{ + Visit: func(node *Node) *Node { + discarded := i < length-1 + i++ + if discarded { + return discardVisitor.Visit(node) + } + return visitor.Visit(node) + }, + Factory: visitor.Factory, + } + return combined.VisitNodes(elements) +} + func (v *NodeVisitor) liftToBlock(node *Statement) *Statement { var nodes []*Node if node != nil { diff --git a/internal/checker/utilities.go b/internal/checker/utilities.go index d7d592cb44..d5a0739fe8 100644 --- a/internal/checker/utilities.go +++ b/internal/checker/utilities.go @@ -1130,6 +1130,15 @@ func expressionResultIsUnused(node *ast.Node) bool { if ast.IsExpressionStatement(parent) || ast.IsVoidExpression(parent) || ast.IsForStatement(parent) && (parent.Initializer() == node || parent.AsForStatement().Incrementor == node) { return true } + if ast.IsCommaListExpression(parent) { + // left side of comma is always unused + if node != parent.AsCommaListExpression().Elements.Nodes[len(parent.AsCommaListExpression().Elements.Nodes)-1] { + return true + } + // right side of comma is unused if parent is unused + node = parent + continue + } if ast.IsBinaryExpression(parent) && parent.AsBinaryExpression().OperatorToken.Kind == ast.KindCommaToken { // left side of comma is always unused if node == parent.AsBinaryExpression().Left { diff --git a/internal/printer/factory.go b/internal/printer/factory.go index e7e0e5e3e3..a1e954ef1d 100644 --- a/internal/printer/factory.go +++ b/internal/printer/factory.go @@ -243,12 +243,20 @@ func (f *NodeFactory) NewVoidZeroExpression() *ast.Expression { } func flattenCommaElement(node *ast.Expression, expressions []*ast.Expression) []*ast.Expression { - if ast.IsBinaryExpression(node) && ast.NodeIsSynthesized(node) && node.AsBinaryExpression().OperatorToken.Kind == ast.KindCommaToken { - expressions = flattenCommaElement(node.AsBinaryExpression().Left, expressions) - expressions = flattenCommaElement(node.AsBinaryExpression().Right, expressions) - } else { - expressions = append(expressions, node) + if ast.NodeIsSynthesized(node) { + if ast.IsCommaListExpression(node) { + for _, elem := range node.AsCommaListExpression().Elements.Nodes { + expressions = flattenCommaElement(elem, expressions) + } + return expressions + } + if ast.IsBinaryExpression(node) && node.AsBinaryExpression().OperatorToken.Kind == ast.KindCommaToken { + expressions = flattenCommaElement(node.AsBinaryExpression().Left, expressions) + expressions = flattenCommaElement(node.AsBinaryExpression().Right, expressions) + return expressions + } } + expressions = append(expressions, node) return expressions } @@ -261,6 +269,7 @@ func flattenCommaElements(expressions []*ast.Expression) []*ast.Expression { } // Converts a slice of expressions into a single comma-delimited expression. Returns nil if expressions is nil or empty. +// Uses CommaListExpression for >10 elements to avoid deeply nested binary comma trees. func (f *NodeFactory) InlineExpressions(expressions []*ast.Expression) *ast.Expression { if len(expressions) == 0 { return nil @@ -269,6 +278,9 @@ func (f *NodeFactory) InlineExpressions(expressions []*ast.Expression) *ast.Expr return expressions[0] } expressions = flattenCommaElements(expressions) + if len(expressions) > 10 { + return f.NewCommaListExpression(f.NewNodeList(expressions)) + } expression := expressions[0] for _, next := range expressions[1:] { expression = f.NewCommaExpression(expression, next) diff --git a/internal/printer/printer.go b/internal/printer/printer.go index 700e15f6d1..0bbc11a21a 100644 --- a/internal/printer/printer.go +++ b/internal/printer/printer.go @@ -3009,6 +3009,14 @@ func (p *Printer) emitPartiallyEmittedExpression(node *ast.PartiallyEmittedExpre } } +func (p *Printer) emitCommaListElement(node *ast.Expression) { + p.emitExpression(node, ast.OperatorPrecedenceSpread) +} + +func (p *Printer) emitCommaList(node *ast.CommaListExpression) { + p.emitList((*Printer).emitCommaListElement, node.AsNode(), node.Elements, LFCommaListElements) +} + func (p *Printer) commentWillEmitNewLine(comment ast.CommentRange) bool { return comment.Kind == ast.KindSingleLineCommentTrivia || comment.HasTrailingNewLine } @@ -3286,6 +3294,8 @@ func (p *Printer) emitExpression(node *ast.Expression, precedence ast.OperatorPr return case ast.KindPartiallyEmittedExpression: p.emitPartiallyEmittedExpression(node.AsPartiallyEmittedExpression()) + case ast.KindCommaListExpression: + p.emitCommaList(node.AsCommaListExpression()) case ast.KindSyntheticReferenceExpression: panic("SyntheticReferenceExpression should not be printed") diff --git a/internal/printer/utilities.go b/internal/printer/utilities.go index 27d7a3ce63..4a55875f52 100644 --- a/internal/printer/utilities.go +++ b/internal/printer/utilities.go @@ -485,7 +485,7 @@ func getContainingNodeArray(node *ast.Node) *ast.NodeList { return parent.AsUnionTypeNode().Types case ast.KindIntersectionType: return parent.AsIntersectionTypeNode().Types - case ast.KindArrayLiteralExpression, ast.KindTupleType, ast.KindNamedImports, ast.KindNamedExports: + case ast.KindArrayLiteralExpression, ast.KindTupleType, ast.KindNamedImports, ast.KindNamedExports, ast.KindCommaListExpression: return parent.ElementList() case ast.KindObjectLiteralExpression, ast.KindJsxAttributes: return parent.PropertyList() diff --git a/internal/transformers/estransforms/classfields.go b/internal/transformers/estransforms/classfields.go index 8f330a364e..d12c2262e9 100644 --- a/internal/transformers/estransforms/classfields.go +++ b/internal/transformers/estransforms/classfields.go @@ -346,6 +346,8 @@ func (tx *classFieldsTransformer) visitDiscardedValue(node *ast.Node) *ast.Node return tx.visitPreOrPostfixUnaryExpression(node, true /*discarded*/) case ast.KindBinaryExpression: return tx.visitBinaryExpression(node.AsBinaryExpression(), true /*discarded*/) + case ast.KindCommaListExpression: + return tx.visitCommaListExpression(node.AsCommaListExpression(), true /*discarded*/) case ast.KindParenthesizedExpression: return tx.visitParenthesizedExpression(node.AsParenthesizedExpression(), true /*discarded*/) default: @@ -1610,6 +1612,16 @@ func (tx *classFieldsTransformer) visitBinaryExpression(node *ast.BinaryExpressi return tx.Visitor().VisitEachChild(node.AsNode()) } +func (tx *classFieldsTransformer) visitCommaListExpression(node *ast.CommaListExpression, discarded bool) *ast.Node { + var elements *ast.NodeList + if discarded { + elements = ast.VisitCommaListElements(node.Elements, tx.discardedValueVisitor, nil) + } else { + elements = ast.VisitCommaListElements(node.Elements, tx.Visitor(), tx.discardedValueVisitor) + } + return tx.Factory().UpdateCommaListExpression(node, elements) +} + func (tx *classFieldsTransformer) visitParenthesizedExpression(node *ast.ParenthesizedExpression, discarded bool) *ast.Node { // 8.4.5 RS: NamedEvaluation // ParenthesizedExpression : `(` Expression `)` @@ -3547,6 +3559,11 @@ func flattenCommaList(node *ast.Expression) iter.Seq[*ast.Expression] { func flattenCommaListWorker(node *ast.Expression, yield func(*ast.Expression) bool) bool { if ast.IsParenthesizedExpression(node) && ast.NodeIsSynthesized(node) { return flattenCommaListWorker(node.Expression(), yield) + } else if ast.IsCommaListExpression(node) { + for _, child := range node.AsCommaListExpression().Elements.Nodes { + flattenCommaListWorker(child, yield) + } + return true } else if ast.IsCommaExpression(node.AsNode()) { return flattenCommaListWorker(node.AsBinaryExpression().Left, yield) && flattenCommaListWorker(node.AsBinaryExpression().Right, yield) @@ -3559,6 +3576,11 @@ func findComputedPropertyNameCacheAssignment(emitContext *printer.EmitContext, n node := name.Expression() for { node = ast.SkipOuterExpressions(node, 0) + if ast.IsCommaListExpression(node) { + elems := node.AsCommaListExpression().Elements.Nodes + node = elems[len(elems)-1] + continue + } if ast.IsBinaryExpression(node) && node.AsBinaryExpression().OperatorToken.Kind == ast.KindCommaToken { node = node.AsBinaryExpression().Right continue diff --git a/internal/transformers/estransforms/esdecorator.go b/internal/transformers/estransforms/esdecorator.go index 40a16488b2..a293a7bc9d 100644 --- a/internal/transformers/estransforms/esdecorator.go +++ b/internal/transformers/estransforms/esdecorator.go @@ -336,6 +336,8 @@ func (tx *esDecoratorTransformer) visit(node *ast.Node) *ast.Node { return tx.visitForStatement(node) case ast.KindExpressionStatement: return tx.visitExpressionStatement(node) + case ast.KindCommaListExpression: + return tx.visitCommaListExpression(node.AsCommaListExpression(), false /*discarded*/) case ast.KindParenthesizedExpression: return tx.visitParenthesizedExpression(node, false /*discarded*/) case ast.KindPartiallyEmittedExpression: @@ -398,6 +400,8 @@ func (tx *esDecoratorTransformer) discardedValueVisit(node *ast.Node) *ast.Node return tx.visitPreOrPostfixUnaryExpression(node, true /*discarded*/) case ast.KindBinaryExpression: return tx.visitBinaryExpression(node, true /*discarded*/) + case ast.KindCommaListExpression: + return tx.visitCommaListExpression(node.AsCommaListExpression(), true /*discarded*/) case ast.KindParenthesizedExpression: return tx.visitParenthesizedExpression(node, true /*discarded*/) case ast.KindPartiallyEmittedExpression: @@ -407,6 +411,16 @@ func (tx *esDecoratorTransformer) discardedValueVisit(node *ast.Node) *ast.Node } } +func (tx *esDecoratorTransformer) visitCommaListExpression(node *ast.CommaListExpression, discarded bool) *ast.Node { + var elements *ast.NodeList + if discarded { + elements = ast.VisitCommaListElements(node.Elements, tx.discardedVisitor, nil) + } else { + elements = ast.VisitCommaListElements(node.Elements, tx.Visitor(), tx.discardedVisitor) + } + return tx.Factory().UpdateCommaListExpression(node, elements) +} + func (tx *esDecoratorTransformer) nonConstructorClassElementVisit(node *ast.Node) *ast.Node { if ast.IsConstructorDeclaration(node) { return node // skip constructors in pass 1 diff --git a/internal/transformers/estransforms/objectrestspread.go b/internal/transformers/estransforms/objectrestspread.go index ea73e8c2d7..b562c1d27f 100644 --- a/internal/transformers/estransforms/objectrestspread.go +++ b/internal/transformers/estransforms/objectrestspread.go @@ -13,6 +13,7 @@ type objectRestSpreadTransformer struct { inExportedVariableStatement bool expressionResultIsUnused bool + unusedExpressionVisitor *ast.NodeVisitor parametersWithPrecedingObjectRestOrSpread map[*ast.Node]struct{} } @@ -33,6 +34,8 @@ func (ch *objectRestSpreadTransformer) visit(node *ast.Node) *ast.Node { return ch.visitObjectLiteralExpression(node.AsObjectLiteralExpression()) case ast.KindBinaryExpression: return ch.visitBinaryExpression(node.AsBinaryExpression(), expressionResultIsUnused) + case ast.KindCommaListExpression: + return ch.visitCommaListExpression(node.AsCommaListExpression(), expressionResultIsUnused) case ast.KindExpressionStatement: ch.expressionResultIsUnused = true return ch.Visitor().VisitEachChild(node) @@ -513,6 +516,20 @@ func (ch *objectRestSpreadTransformer) visitBinaryExpression(node *ast.BinaryExp return ch.Visitor().VisitEachChild(node.AsNode()) } +func (ch *objectRestSpreadTransformer) visitWithUnusedExpressionResult(node *ast.Node) *ast.Node { + ch.expressionResultIsUnused = true + return ch.visit(node) +} + +func (ch *objectRestSpreadTransformer) visitCommaListExpression(node *ast.CommaListExpression, expressionResultIsUnused bool) *ast.Node { + if expressionResultIsUnused { + ch.expressionResultIsUnused = true + return ch.Visitor().VisitEachChild(node.AsNode()) + } + elements := ast.VisitCommaListElements(node.Elements, ch.Visitor(), ch.unusedExpressionVisitor) + return ch.Factory().UpdateCommaListExpression(node, elements) +} + func (ch *objectRestSpreadTransformer) visitObjectLiteralExpression(node *ast.ObjectLiteralExpression) *ast.Node { if (node.SubtreeFacts() & ast.SubtreeContainsObjectRestOrSpread) == 0 { return ch.Visitor().VisitEachChild(node.AsNode()) @@ -589,5 +606,7 @@ func (ch *objectRestSpreadTransformer) chunkObjectLiteralElements(list *ast.Node func newObjectRestSpreadTransformer(opts *transformers.TransformOptions) *transformers.Transformer { tx := &objectRestSpreadTransformer{compilerOptions: opts.CompilerOptions} - return tx.NewTransformer(tx.visit, opts.Context) + result := tx.NewTransformer(tx.visit, opts.Context) + tx.unusedExpressionVisitor = tx.EmitContext().NewNodeVisitor(tx.visitWithUnusedExpressionResult) + return result }