@@ -104,14 +104,15 @@ namespace ts {
104104 let seenThisKeyword : boolean ;
105105
106106 // state used by reachability checks
107- let hasExplicitReturn : boolean ;
108107 let currentFlow : FlowNode ;
109108 let currentBreakTarget : FlowLabel ;
110109 let currentContinueTarget : FlowLabel ;
110+ let currentReturnTarget : FlowLabel ;
111111 let currentTrueTarget : FlowLabel ;
112112 let currentFalseTarget : FlowLabel ;
113113 let preSwitchCaseFlow : FlowNode ;
114114 let activeLabels : ActiveLabel [ ] ;
115+ let hasExplicitReturn : boolean ;
115116
116117 // state used for emit helpers
117118 let hasClassExtends : boolean ;
@@ -156,13 +157,14 @@ namespace ts {
156157 blockScopeContainer = undefined ;
157158 lastContainer = undefined ;
158159 seenThisKeyword = false ;
159- hasExplicitReturn = false ;
160160 currentFlow = undefined ;
161161 currentBreakTarget = undefined ;
162162 currentContinueTarget = undefined ;
163+ currentReturnTarget = undefined ;
163164 currentTrueTarget = undefined ;
164165 currentFalseTarget = undefined ;
165166 activeLabels = undefined ;
167+ hasExplicitReturn = false ;
166168 hasClassExtends = false ;
167169 hasAsyncFunctions = false ;
168170 hasDecorators = false ;
@@ -443,44 +445,51 @@ namespace ts {
443445 blockScopeContainer . locals = undefined ;
444446 }
445447
446- let savedHasExplicitReturn : boolean ;
447- let savedCurrentFlow : FlowNode ;
448- let savedBreakTarget : FlowLabel ;
449- let savedContinueTarget : FlowLabel ;
450- let savedActiveLabels : ActiveLabel [ ] ;
448+ let saveCurrentFlow : FlowNode ;
449+ let saveBreakTarget : FlowLabel ;
450+ let saveContinueTarget : FlowLabel ;
451+ let saveReturnTarget : FlowLabel ;
452+ let saveActiveLabels : ActiveLabel [ ] ;
453+ let saveHasExplicitReturn : boolean ;
454+ let isIIFE : boolean ;
451455
452456 const kind = node . kind ;
453457 let flags = node . flags ;
454458
455- // reset all reachability check related flags on node (for incremental scenarios)
456- flags &= ~ NodeFlags . ReachabilityCheckFlags ;
457-
458- // reset all emit helper flags on node (for incremental scenarios)
459- flags &= ~ NodeFlags . EmitHelperFlags ;
459+ // Reset all reachability check related flags on node (for incremental scenarios)
460+ // Reset all emit helper flags on node (for incremental scenarios)
461+ flags &= ~ NodeFlags . ReachabilityAndEmitFlags ;
460462
461463 if ( kind === SyntaxKind . InterfaceDeclaration ) {
462464 seenThisKeyword = false ;
463465 }
464466
465467 const saveState = kind === SyntaxKind . SourceFile || kind === SyntaxKind . ModuleBlock || isFunctionLikeKind ( kind ) ;
466468 if ( saveState ) {
467- savedHasExplicitReturn = hasExplicitReturn ;
468- savedCurrentFlow = currentFlow ;
469- savedBreakTarget = currentBreakTarget ;
470- savedContinueTarget = currentContinueTarget ;
471- savedActiveLabels = activeLabels ;
472-
473- hasExplicitReturn = false ;
474- currentFlow = { flags : FlowFlags . Start } ;
475- if ( kind === SyntaxKind . FunctionExpression || kind === SyntaxKind . ArrowFunction ) {
476- ( < FlowStart > currentFlow ) . container = < FunctionExpression | ArrowFunction > node ;
469+ saveCurrentFlow = currentFlow ;
470+ saveBreakTarget = currentBreakTarget ;
471+ saveContinueTarget = currentContinueTarget ;
472+ saveReturnTarget = currentReturnTarget ;
473+ saveActiveLabels = activeLabels ;
474+ saveHasExplicitReturn = hasExplicitReturn ;
475+ isIIFE = ( kind === SyntaxKind . FunctionExpression || kind === SyntaxKind . ArrowFunction ) && ! ! getImmediatelyInvokedFunctionExpression ( node ) ;
476+ if ( isIIFE ) {
477+ currentReturnTarget = createBranchLabel ( ) ;
478+ }
479+ else {
480+ currentFlow = { flags : FlowFlags . Start } ;
481+ if ( kind === SyntaxKind . FunctionExpression || kind === SyntaxKind . ArrowFunction ) {
482+ ( < FlowStart > currentFlow ) . container = < FunctionExpression | ArrowFunction > node ;
483+ }
484+ currentReturnTarget = undefined ;
477485 }
478486 currentBreakTarget = undefined ;
479487 currentContinueTarget = undefined ;
480488 activeLabels = undefined ;
489+ hasExplicitReturn = false ;
481490 }
482491
483- if ( isInJavaScriptFile ( node ) && node . jsDocComment ) {
492+ if ( node . flags & NodeFlags . JavaScriptFile && node . jsDocComment ) {
484493 bind ( node . jsDocComment ) ;
485494 }
486495
@@ -518,11 +527,18 @@ namespace ts {
518527 node . flags = flags ;
519528
520529 if ( saveState ) {
521- hasExplicitReturn = savedHasExplicitReturn ;
522- currentFlow = savedCurrentFlow ;
523- currentBreakTarget = savedBreakTarget ;
524- currentContinueTarget = savedContinueTarget ;
525- activeLabels = savedActiveLabels ;
530+ if ( isIIFE ) {
531+ addAntecedent ( currentReturnTarget , currentFlow ) ;
532+ currentFlow = finishFlowLabel ( currentReturnTarget ) ;
533+ }
534+ else {
535+ currentFlow = saveCurrentFlow ;
536+ }
537+ currentBreakTarget = saveBreakTarget ;
538+ currentContinueTarget = saveContinueTarget ;
539+ currentReturnTarget = saveReturnTarget ;
540+ activeLabels = saveActiveLabels ;
541+ hasExplicitReturn = saveHasExplicitReturn ;
526542 }
527543
528544 container = saveContainer ;
@@ -854,6 +870,9 @@ namespace ts {
854870 bind ( node . expression ) ;
855871 if ( node . kind === SyntaxKind . ReturnStatement ) {
856872 hasExplicitReturn = true ;
873+ if ( currentReturnTarget ) {
874+ addAntecedent ( currentReturnTarget , currentFlow ) ;
875+ }
857876 }
858877 currentFlow = unreachableFlow ;
859878 }
@@ -1105,7 +1124,6 @@ namespace ts {
11051124 }
11061125
11071126 function bindCallExpressionFlow ( node : CallExpression ) {
1108- forEachChild ( node , bind ) ;
11091127 // If the target of the call expression is a function expression or arrow function we have
11101128 // an immediately invoked function expression (IIFE). Initialize the flowNode property to
11111129 // the current control flow (which includes evaluation of the IIFE arguments).
@@ -1114,7 +1132,12 @@ namespace ts {
11141132 expr = ( < ParenthesizedExpression > expr ) . expression ;
11151133 }
11161134 if ( expr . kind === SyntaxKind . FunctionExpression || expr . kind === SyntaxKind . ArrowFunction ) {
1117- node . flowNode = currentFlow ;
1135+ forEach ( node . typeArguments , bind ) ;
1136+ forEach ( node . arguments , bind ) ;
1137+ bind ( node . expression ) ;
1138+ }
1139+ else {
1140+ forEachChild ( node , bind ) ;
11181141 }
11191142 }
11201143
0 commit comments