@@ -146,7 +146,6 @@ import {
146146 isDeclarationStatement ,
147147 isDestructuringAssignment ,
148148 isDottedName ,
149- isElementAccessExpression ,
150149 isEmptyObjectLiteral ,
151150 isEntityNameExpression ,
152151 isEnumConst ,
@@ -188,7 +187,6 @@ import {
188187 isModuleExportsAccessExpression ,
189188 isNamedDeclaration ,
190189 isNamespaceExport ,
191- isNonNullExpression ,
192190 isNullishCoalesce ,
193191 isObjectLiteralExpression ,
194192 isObjectLiteralMethod ,
@@ -540,6 +538,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
540538 var preSwitchCaseFlow : FlowNode | undefined ;
541539 var activeLabelList : ActiveLabel | undefined ;
542540 var hasExplicitReturn : boolean ;
541+ var hasFlowEffects : boolean ;
543542
544543 // state used for emit helpers
545544 var emitFlags : NodeFlags ;
@@ -618,6 +617,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
618617 currentExceptionTarget = undefined ;
619618 activeLabelList = undefined ;
620619 hasExplicitReturn = false ;
620+ hasFlowEffects = false ;
621621 inAssignmentPattern = false ;
622622 emitFlags = NodeFlags . None ;
623623 }
@@ -1223,8 +1223,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
12231223 function isNarrowingExpression ( expr : Expression ) : boolean {
12241224 switch ( expr . kind ) {
12251225 case SyntaxKind . Identifier :
1226- case SyntaxKind . PrivateIdentifier :
12271226 case SyntaxKind . ThisKeyword :
1227+ return true ;
12281228 case SyntaxKind . PropertyAccessExpression :
12291229 case SyntaxKind . ElementAccessExpression :
12301230 return containsNarrowableReference ( expr ) ;
@@ -1248,11 +1248,24 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
12481248 }
12491249
12501250 function isNarrowableReference ( expr : Expression ) : boolean {
1251- return isDottedName ( expr )
1252- || ( isPropertyAccessExpression ( expr ) || isNonNullExpression ( expr ) || isParenthesizedExpression ( expr ) ) && isNarrowableReference ( expr . expression )
1253- || isBinaryExpression ( expr ) && expr . operatorToken . kind === SyntaxKind . CommaToken && isNarrowableReference ( expr . right )
1254- || isElementAccessExpression ( expr ) && ( isStringOrNumericLiteralLike ( expr . argumentExpression ) || isEntityNameExpression ( expr . argumentExpression ) ) && isNarrowableReference ( expr . expression )
1255- || isAssignmentExpression ( expr ) && isNarrowableReference ( expr . left ) ;
1251+ switch ( expr . kind ) {
1252+ case SyntaxKind . Identifier :
1253+ case SyntaxKind . ThisKeyword :
1254+ case SyntaxKind . SuperKeyword :
1255+ case SyntaxKind . MetaProperty :
1256+ return true ;
1257+ case SyntaxKind . PropertyAccessExpression :
1258+ case SyntaxKind . ParenthesizedExpression :
1259+ case SyntaxKind . NonNullExpression :
1260+ return isNarrowableReference ( ( expr as PropertyAccessExpression | ParenthesizedExpression | NonNullExpression ) . expression ) ;
1261+ case SyntaxKind . ElementAccessExpression :
1262+ return ( isStringOrNumericLiteralLike ( ( expr as ElementAccessExpression ) . argumentExpression ) || isEntityNameExpression ( ( expr as ElementAccessExpression ) . argumentExpression ) ) &&
1263+ isNarrowableReference ( ( expr as ElementAccessExpression ) . expression ) ;
1264+ case SyntaxKind . BinaryExpression :
1265+ return ( expr as BinaryExpression ) . operatorToken . kind === SyntaxKind . CommaToken && isNarrowableReference ( ( expr as BinaryExpression ) . right ) ||
1266+ isAssignmentOperator ( ( expr as BinaryExpression ) . operatorToken . kind ) && isLeftHandSideExpression ( ( expr as BinaryExpression ) . left ) ;
1267+ }
1268+ return false ;
12561269 }
12571270
12581271 function containsNarrowableReference ( expr : Expression ) : boolean {
@@ -1371,6 +1384,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
13711384
13721385 function createFlowMutation ( flags : FlowFlags , antecedent : FlowNode , node : Expression | VariableDeclaration | ArrayBindingElement ) : FlowNode {
13731386 setFlowNodeReferenced ( antecedent ) ;
1387+ hasFlowEffects = true ;
13741388 const result = initFlowNode ( { flags, antecedent, node } ) ;
13751389 if ( currentExceptionTarget ) {
13761390 addAntecedent ( currentExceptionTarget , result ) ;
@@ -1380,6 +1394,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
13801394
13811395 function createFlowCall ( antecedent : FlowNode , node : CallExpression ) : FlowNode {
13821396 setFlowNodeReferenced ( antecedent ) ;
1397+ hasFlowEffects = true ;
13831398 return initFlowNode ( { flags : FlowFlags . Call , antecedent, node } ) ;
13841399 }
13851400
@@ -1559,6 +1574,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
15591574 }
15601575 }
15611576 currentFlow = unreachableFlow ;
1577+ hasFlowEffects = true ;
15621578 }
15631579
15641580 function findActiveLabel ( name : __String ) {
@@ -1575,6 +1591,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
15751591 if ( flowLabel ) {
15761592 addAntecedent ( flowLabel , currentFlow ) ;
15771593 currentFlow = unreachableFlow ;
1594+ hasFlowEffects = true ;
15781595 }
15791596 }
15801597
@@ -1904,8 +1921,12 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
19041921 if ( isLogicalOrCoalescingBinaryOperator ( operator ) || isLogicalOrCoalescingAssignmentOperator ( operator ) ) {
19051922 if ( isTopLevelLogicalExpression ( node ) ) {
19061923 const postExpressionLabel = createBranchLabel ( ) ;
1924+ const saveCurrentFlow = currentFlow ;
1925+ const saveHasFlowEffects = hasFlowEffects ;
1926+ hasFlowEffects = false ;
19071927 bindLogicalLikeExpression ( node , postExpressionLabel , postExpressionLabel ) ;
1908- currentFlow = finishFlowLabel ( postExpressionLabel ) ;
1928+ currentFlow = hasFlowEffects ? finishFlowLabel ( postExpressionLabel ) : saveCurrentFlow ;
1929+ hasFlowEffects ||= saveHasFlowEffects ;
19091930 }
19101931 else {
19111932 bindLogicalLikeExpression ( node , currentTrueTarget ! , currentFalseTarget ! ) ;
@@ -1985,6 +2006,9 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
19852006 const trueLabel = createBranchLabel ( ) ;
19862007 const falseLabel = createBranchLabel ( ) ;
19872008 const postExpressionLabel = createBranchLabel ( ) ;
2009+ const saveCurrentFlow = currentFlow ;
2010+ const saveHasFlowEffects = hasFlowEffects ;
2011+ hasFlowEffects = false ;
19882012 bindCondition ( node . condition , trueLabel , falseLabel ) ;
19892013 currentFlow = finishFlowLabel ( trueLabel ) ;
19902014 bind ( node . questionToken ) ;
@@ -1994,7 +2018,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
19942018 bind ( node . colonToken ) ;
19952019 bind ( node . whenFalse ) ;
19962020 addAntecedent ( postExpressionLabel , currentFlow ) ;
1997- currentFlow = finishFlowLabel ( postExpressionLabel ) ;
2021+ currentFlow = hasFlowEffects ? finishFlowLabel ( postExpressionLabel ) : saveCurrentFlow ;
2022+ hasFlowEffects ||= saveHasFlowEffects ;
19982023 }
19992024
20002025 function bindInitializedVariableFlow ( node : VariableDeclaration | ArrayBindingElement ) {
@@ -2134,8 +2159,11 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
21342159 function bindOptionalChainFlow ( node : OptionalChain ) {
21352160 if ( isTopLevelLogicalExpression ( node ) ) {
21362161 const postExpressionLabel = createBranchLabel ( ) ;
2162+ const saveCurrentFlow = currentFlow ;
2163+ const saveHasFlowEffects = hasFlowEffects ;
21372164 bindOptionalChain ( node , postExpressionLabel , postExpressionLabel ) ;
2138- currentFlow = finishFlowLabel ( postExpressionLabel ) ;
2165+ currentFlow = hasFlowEffects ? finishFlowLabel ( postExpressionLabel ) : saveCurrentFlow ;
2166+ hasFlowEffects ||= saveHasFlowEffects ;
21392167 }
21402168 else {
21412169 bindOptionalChain ( node , currentTrueTarget ! , currentFalseTarget ! ) ;
0 commit comments