@@ -355,12 +355,11 @@ namespace ts {
355355 }
356356
357357 function visitor ( node : Node ) : VisitResult < Node > {
358- if ( shouldVisitNode ( node ) ) {
359- return visitJavaScript ( node ) ;
360- }
361- else {
362- return node ;
363- }
358+ return shouldVisitNode ( node ) ? visitorWorker ( node , /*expressionResultIsUnused*/ false ) : node ;
359+ }
360+
361+ function visitorWithUnusedExpressionResult ( node : Node ) : VisitResult < Node > {
362+ return shouldVisitNode ( node ) ? visitorWorker ( node , /*expressionResultIsUnused*/ true ) : node ;
364363 }
365364
366365 function callExpressionVisitor ( node : Node ) : VisitResult < Node > {
@@ -370,7 +369,7 @@ namespace ts {
370369 return visitor ( node ) ;
371370 }
372371
373- function visitJavaScript ( node : Node ) : VisitResult < Node > {
372+ function visitorWorker ( node : Node , expressionResultIsUnused : boolean ) : VisitResult < Node > {
374373 switch ( node . kind ) {
375374 case SyntaxKind . StaticKeyword :
376375 return undefined ; // elide static keyword
@@ -456,10 +455,13 @@ namespace ts {
456455 return visitNewExpression ( < NewExpression > node ) ;
457456
458457 case SyntaxKind . ParenthesizedExpression :
459- return visitParenthesizedExpression ( < ParenthesizedExpression > node , /*needsDestructuringValue*/ true ) ;
458+ return visitParenthesizedExpression ( < ParenthesizedExpression > node , expressionResultIsUnused ) ;
460459
461460 case SyntaxKind . BinaryExpression :
462- return visitBinaryExpression ( < BinaryExpression > node , /*needsDestructuringValue*/ true ) ;
461+ return visitBinaryExpression ( < BinaryExpression > node , expressionResultIsUnused ) ;
462+
463+ case SyntaxKind . CommaListExpression :
464+ return visitCommaListExpression ( < CommaListExpression > node , expressionResultIsUnused ) ;
463465
464466 case SyntaxKind . NoSubstitutionTemplateLiteral :
465467 case SyntaxKind . TemplateHead :
@@ -507,6 +509,9 @@ namespace ts {
507509 case SyntaxKind . ReturnStatement :
508510 return visitReturnStatement ( < ReturnStatement > node ) ;
509511
512+ case SyntaxKind . VoidExpression :
513+ return visitVoidExpression ( node as VoidExpression ) ;
514+
510515 default :
511516 return visitEachChild ( node , visitor , context ) ;
512517 }
@@ -596,6 +601,10 @@ namespace ts {
596601 return node ;
597602 }
598603
604+ function visitVoidExpression ( node : VoidExpression ) : Expression {
605+ return visitEachChild ( node , visitorWithUnusedExpressionResult , context ) ;
606+ }
607+
599608 function visitIdentifier ( node : Identifier ) : Identifier {
600609 if ( ! convertedLoopState ) {
601610 return node ;
@@ -1975,59 +1984,69 @@ namespace ts {
19751984 * @param node An ExpressionStatement node.
19761985 */
19771986 function visitExpressionStatement ( node : ExpressionStatement ) : Statement {
1978- // If we are here it is most likely because our expression is a destructuring assignment.
1979- switch ( node . expression . kind ) {
1980- case SyntaxKind . ParenthesizedExpression :
1981- return factory . updateExpressionStatement ( node , visitParenthesizedExpression ( < ParenthesizedExpression > node . expression , /*needsDestructuringValue*/ false ) ) ;
1982- case SyntaxKind . BinaryExpression :
1983- return factory . updateExpressionStatement ( node , visitBinaryExpression ( < BinaryExpression > node . expression , /*needsDestructuringValue*/ false ) ) ;
1984- }
1985- return visitEachChild ( node , visitor , context ) ;
1987+ return visitEachChild ( node , visitorWithUnusedExpressionResult , context ) ;
19861988 }
19871989
19881990 /**
19891991 * Visits a ParenthesizedExpression that may contain a destructuring assignment.
19901992 *
19911993 * @param node A ParenthesizedExpression node.
1992- * @param needsDestructuringValue A value indicating whether we need to hold onto the rhs
1993- * of a destructuring assignment .
1994+ * @param expressionResultIsUnused Indicates the result of an expression is unused by the parent node (i.e., the left side of a comma or the
1995+ * expression of an `ExpressionStatement`) .
19941996 */
1995- function visitParenthesizedExpression ( node : ParenthesizedExpression , needsDestructuringValue : boolean ) : ParenthesizedExpression {
1996- // If we are here it is most likely because our expression is a destructuring assignment.
1997- if ( ! needsDestructuringValue ) {
1998- // By default we always emit the RHS at the end of a flattened destructuring
1999- // expression. If we are in a state where we do not need the destructuring value,
2000- // we pass that information along to the children that care about it.
2001- switch ( node . expression . kind ) {
2002- case SyntaxKind . ParenthesizedExpression :
2003- return factory . updateParenthesizedExpression ( node , visitParenthesizedExpression ( < ParenthesizedExpression > node . expression , /*needsDestructuringValue*/ false ) ) ;
2004- case SyntaxKind . BinaryExpression :
2005- return factory . updateParenthesizedExpression ( node , visitBinaryExpression ( < BinaryExpression > node . expression , /*needsDestructuringValue*/ false ) ) ;
2006- }
2007- }
2008- return visitEachChild ( node , visitor , context ) ;
1997+ function visitParenthesizedExpression ( node : ParenthesizedExpression , expressionResultIsUnused : boolean ) : ParenthesizedExpression {
1998+ return visitEachChild ( node , expressionResultIsUnused ? visitorWithUnusedExpressionResult : visitor , context ) ;
20091999 }
20102000
20112001 /**
20122002 * Visits a BinaryExpression that contains a destructuring assignment.
20132003 *
20142004 * @param node A BinaryExpression node.
2015- * @param needsDestructuringValue A value indicating whether we need to hold onto the rhs
2016- * of a destructuring assignment .
2005+ * @param expressionResultIsUnused Indicates the result of an expression is unused by the parent node (i.e., the left side of a comma or the
2006+ * expression of an `ExpressionStatement`) .
20172007 */
2018- function visitBinaryExpression ( node : BinaryExpression , needsDestructuringValue : boolean ) : Expression {
2008+ function visitBinaryExpression ( node : BinaryExpression , expressionResultIsUnused : boolean ) : Expression {
20192009 // If we are here it is because this is a destructuring assignment.
20202010 if ( isDestructuringAssignment ( node ) ) {
20212011 return flattenDestructuringAssignment (
20222012 node ,
20232013 visitor ,
20242014 context ,
20252015 FlattenLevel . All ,
2026- needsDestructuringValue ) ;
2016+ ! expressionResultIsUnused ) ;
2017+ }
2018+ if ( node . operatorToken . kind === SyntaxKind . CommaToken ) {
2019+ return factory . updateBinaryExpression (
2020+ node ,
2021+ visitNode ( node . left , visitorWithUnusedExpressionResult , isExpression ) ,
2022+ node . operatorToken ,
2023+ visitNode ( node . right , expressionResultIsUnused ? visitorWithUnusedExpressionResult : visitor , isExpression )
2024+ ) ;
20272025 }
20282026 return visitEachChild ( node , visitor , context ) ;
20292027 }
20302028
2029+ /**
2030+ * @param expressionResultIsUnused Indicates the result of an expression is unused by the parent node (i.e., the left side of a comma or the
2031+ * expression of an `ExpressionStatement`).
2032+ */
2033+ function visitCommaListExpression ( node : CommaListExpression , expressionResultIsUnused : boolean ) : Expression {
2034+ if ( expressionResultIsUnused ) {
2035+ return visitEachChild ( node , visitorWithUnusedExpressionResult , context ) ;
2036+ }
2037+ let result : Expression [ ] | undefined ;
2038+ for ( let i = 0 ; i < node . elements . length ; i ++ ) {
2039+ const element = node . elements [ i ] ;
2040+ const visited = visitNode ( element , i < node . elements . length - 1 ? visitorWithUnusedExpressionResult : visitor , isExpression ) ;
2041+ if ( result || visited !== element ) {
2042+ result ||= node . elements . slice ( 0 , i ) ;
2043+ result . push ( visited ) ;
2044+ }
2045+ }
2046+ const elements = result ? setTextRange ( factory . createNodeArray ( result ) , node . elements ) : node . elements ;
2047+ return factory . updateCommaListExpression ( node , elements ) ;
2048+ }
2049+
20312050 function isVariableStatementOfTypeScriptClassWrapper ( node : VariableStatement ) {
20322051 return node . declarationList . declarations . length === 1
20332052 && ! ! node . declarationList . declarations [ 0 ] . initializer
@@ -2288,6 +2307,16 @@ namespace ts {
22882307 outermostLabeledStatement ) ;
22892308 }
22902309
2310+ function visitEachChildOfForStatement ( node : ForStatement ) {
2311+ return factory . updateForStatement (
2312+ node ,
2313+ visitNode ( node . initializer , visitorWithUnusedExpressionResult , isForInitializer ) ,
2314+ visitNode ( node . condition , visitor , isExpression ) ,
2315+ visitNode ( node . incrementor , visitorWithUnusedExpressionResult , isExpression ) ,
2316+ visitNode ( node . statement , visitor , isStatement , factory . liftToBlock )
2317+ ) ;
2318+ }
2319+
22912320 function visitForInStatement ( node : ForInStatement , outermostLabeledStatement : LabeledStatement | undefined ) {
22922321 return visitIterationStatementWithFacts (
22932322 HierarchyFacts . ForInOrForOfStatementExcludes ,
@@ -2371,7 +2400,7 @@ namespace ts {
23712400 // evaluated on every iteration.
23722401 const assignment = factory . createAssignment ( initializer , boundValue ) ;
23732402 if ( isDestructuringAssignment ( assignment ) ) {
2374- statements . push ( factory . createExpressionStatement ( visitBinaryExpression ( assignment , /*needsDestructuringValue */ false ) ) ) ;
2403+ statements . push ( factory . createExpressionStatement ( visitBinaryExpression ( assignment , /*expressionResultIsUnused */ true ) ) ) ;
23752404 }
23762405 else {
23772406 setTextRangeEnd ( assignment , initializer . end ) ;
@@ -2714,7 +2743,10 @@ namespace ts {
27142743
27152744 const result = convert
27162745 ? convert ( node , outermostLabeledStatement , /*convertedLoopBodyStatements*/ undefined , ancestorFacts )
2717- : factory . restoreEnclosingLabel ( visitEachChild ( node , visitor , context ) , outermostLabeledStatement , convertedLoopState && resetLabel ) ;
2746+ : factory . restoreEnclosingLabel (
2747+ isForStatement ( node ) ? visitEachChildOfForStatement ( node ) : visitEachChild ( node , visitor , context ) ,
2748+ outermostLabeledStatement ,
2749+ convertedLoopState && resetLabel ) ;
27182750
27192751 if ( convertedLoopState ) {
27202752 convertedLoopState . allowedNonLabeledJumps = saveAllowedNonLabeledJumps ;
@@ -2777,9 +2809,9 @@ namespace ts {
27772809 const shouldConvertIncrementor = shouldConvertCondition || node . incrementor && shouldConvertPartOfIterationStatement ( node . incrementor ) ;
27782810 return factory . updateForStatement (
27792811 node ,
2780- visitNode ( initializerFunction ? initializerFunction . part : node . initializer , visitor , isForInitializer ) ,
2812+ visitNode ( initializerFunction ? initializerFunction . part : node . initializer , visitorWithUnusedExpressionResult , isForInitializer ) ,
27812813 visitNode ( shouldConvertCondition ? undefined : node . condition , visitor , isExpression ) ,
2782- visitNode ( shouldConvertIncrementor ? undefined : node . incrementor , visitor , isExpression ) ,
2814+ visitNode ( shouldConvertIncrementor ? undefined : node . incrementor , visitorWithUnusedExpressionResult , isExpression ) ,
27832815 convertedLoopBody
27842816 ) ;
27852817 }
0 commit comments