@@ -209,10 +209,11 @@ namespace ts {
209209 let symbolCount = 0 ;
210210
211211 let Symbol : new ( flags : SymbolFlags , name : __String ) => Symbol ;
212+ let FlowNode : new ( flags : FlowFlags ) => FlowNodeBase ;
212213 let classifiableNames : UnderscoreEscapedMap < true > ;
213214
214- const unreachableFlow : FlowNode = { flags : FlowFlags . Unreachable } ;
215- const reportedUnreachableFlow : FlowNode = { flags : FlowFlags . Unreachable } ;
215+ let unreachableFlow : FlowNode ;
216+ let reportedUnreachableFlow : FlowNode ;
216217
217218 // state used to aggregate transform flags during bind.
218219 let subtreeTransformFlags : TransformFlags = TransformFlags . None ;
@@ -227,6 +228,17 @@ namespace ts {
227228 return createDiagnosticForNodeInSourceFile ( getSourceFileOfNode ( node ) || file , node , message , arg0 , arg1 , arg2 ) ;
228229 }
229230
231+ function initializeBinder ( ) {
232+ const symbolConstructor = objectAllocator . getSymbolConstructor ( ) ;
233+ const flowNodeConstructor = objectAllocator . getFlowNodeConstructor ( ) ;
234+ if ( Symbol !== symbolConstructor || FlowNode !== flowNodeConstructor ) {
235+ Symbol = symbolConstructor ;
236+ FlowNode = flowNodeConstructor ;
237+ unreachableFlow = new FlowNode ( FlowFlags . Unreachable ) ;
238+ reportedUnreachableFlow = new FlowNode ( FlowFlags . Unreachable ) ;
239+ }
240+ }
241+
230242 function bindSourceFile ( f : SourceFile , opts : CompilerOptions ) {
231243 file = f ;
232244 options = opts ;
@@ -236,7 +248,7 @@ namespace ts {
236248 symbolCount = 0 ;
237249 skipTransformFlagAggregation = file . isDeclarationFile ;
238250
239- Symbol = objectAllocator . getSymbolConstructor ( ) ;
251+ initializeBinder ( ) ;
240252
241253 if ( ! file . locals ) {
242254 bind ( file ) ;
@@ -623,7 +635,7 @@ namespace ts {
623635 // A non-async, non-generator IIFE is considered part of the containing control flow. Return statements behave
624636 // similarly to break statements that exit to a label just past the statement body.
625637 if ( ! isIIFE ) {
626- currentFlow = { flags : FlowFlags . Start } ;
638+ currentFlow = createFlowStart ( ) ;
627639 if ( containerFlags & ( ContainerFlags . IsFunctionExpression | ContainerFlags . IsObjectLiteralOrClassExpressionMethod ) ) {
628640 currentFlow . node = < FunctionExpression | ArrowFunction | MethodDeclaration > node ;
629641 }
@@ -917,11 +929,15 @@ namespace ts {
917929 }
918930
919931 function createBranchLabel ( ) : FlowLabel {
920- return { flags : FlowFlags . BranchLabel , antecedents : undefined } ;
932+ const flow = new FlowNode ( FlowFlags . BranchLabel ) as FlowLabel ;
933+ flow . antecedents = undefined ;
934+ return flow ;
921935 }
922936
923937 function createLoopLabel ( ) : FlowLabel {
924- return { flags : FlowFlags . LoopLabel , antecedents : undefined } ;
938+ const flow = new FlowNode ( FlowFlags . LoopLabel ) as FlowLabel ;
939+ flow . antecedents = undefined ;
940+ return flow ;
925941 }
926942
927943 function setFlowNodeReferenced ( flow : FlowNode ) {
@@ -936,6 +952,10 @@ namespace ts {
936952 }
937953 }
938954
955+ function createFlowStart ( ) : FlowStart {
956+ return new FlowNode ( FlowFlags . Start ) as FlowStart ;
957+ }
958+
939959 function createFlowCondition ( flags : FlowFlags , antecedent : FlowNode , expression : Expression | undefined ) : FlowNode {
940960 if ( antecedent . flags & FlowFlags . Unreachable ) {
941961 return antecedent ;
@@ -953,30 +973,47 @@ namespace ts {
953973 return antecedent ;
954974 }
955975 setFlowNodeReferenced ( antecedent ) ;
956- return flowNodeCreated ( { flags, antecedent, node : expression } ) ;
976+ const flow = new FlowNode ( flags ) as FlowCondition ;
977+ flow . antecedent = antecedent ;
978+ flow . node = expression ;
979+ return flowNodeCreated ( flow ) ;
957980 }
958981
959982 function createFlowSwitchClause ( antecedent : FlowNode , switchStatement : SwitchStatement , clauseStart : number , clauseEnd : number ) : FlowNode {
960983 if ( ! isNarrowingExpression ( switchStatement . expression ) ) {
961984 return antecedent ;
962985 }
963986 setFlowNodeReferenced ( antecedent ) ;
964- return flowNodeCreated ( { flags : FlowFlags . SwitchClause , antecedent, switchStatement, clauseStart, clauseEnd } ) ;
987+ const flow = new FlowNode ( FlowFlags . SwitchClause ) as FlowSwitchClause ;
988+ flow . antecedent = antecedent ;
989+ flow . switchStatement = switchStatement ;
990+ flow . clauseStart = clauseStart ;
991+ flow . clauseEnd = clauseEnd ;
992+ return flowNodeCreated ( flow ) ;
965993 }
966994
967995 function createFlowAssignment ( antecedent : FlowNode , node : Expression | VariableDeclaration | BindingElement ) : FlowNode {
968996 setFlowNodeReferenced ( antecedent ) ;
969- return flowNodeCreated ( { flags : FlowFlags . Assignment , antecedent, node } ) ;
997+ const flow = new FlowNode ( FlowFlags . Assignment ) as FlowAssignment ;
998+ flow . antecedent = antecedent ;
999+ flow . node = node ;
1000+ return flowNodeCreated ( flow ) ;
9701001 }
9711002
9721003 function createFlowCall ( antecedent : FlowNode , node : CallExpression ) : FlowNode {
9731004 setFlowNodeReferenced ( antecedent ) ;
974- return flowNodeCreated ( { flags : FlowFlags . Call , antecedent, node } ) ;
1005+ const flow = new FlowNode ( FlowFlags . Call ) as FlowCall ;
1006+ flow . antecedent = antecedent ;
1007+ flow . node = node ;
1008+ return flowNodeCreated ( flow ) ;
9751009 }
9761010
9771011 function createFlowArrayMutation ( antecedent : FlowNode , node : CallExpression | BinaryExpression ) : FlowNode {
9781012 setFlowNodeReferenced ( antecedent ) ;
979- return flowNodeCreated ( { flags : FlowFlags . ArrayMutation , antecedent, node } ) ;
1013+ const flow = new FlowNode ( FlowFlags . ArrayMutation ) as FlowArrayMutation ;
1014+ flow . antecedent = antecedent ;
1015+ flow . node = node ;
1016+ return flowNodeCreated ( flow ) ;
9801017 }
9811018
9821019 function finishFlowLabel ( flow : FlowLabel ) : FlowNode {
@@ -1259,7 +1296,9 @@ namespace ts {
12591296 //
12601297 // extra edges that we inject allows to control this behavior
12611298 // if when walking the flow we step on post-finally edge - we can mark matching pre-finally edge as locked so it will be skipped.
1262- const preFinallyFlow : PreFinallyFlow = { flags : FlowFlags . PreFinally , antecedent : preFinallyPrior , lock : { } } ;
1299+ const preFinallyFlow = new FlowNode ( FlowFlags . PreFinally ) as PreFinallyFlow ;
1300+ preFinallyFlow . antecedent = preFinallyPrior ;
1301+ preFinallyFlow . lock = { } ;
12631302 addAntecedent ( preFinallyLabel , preFinallyFlow ) ;
12641303
12651304 currentFlow = finishFlowLabel ( preFinallyLabel ) ;
@@ -1278,7 +1317,9 @@ namespace ts {
12781317 }
12791318 }
12801319 if ( ! ( currentFlow . flags & FlowFlags . Unreachable ) ) {
1281- const afterFinallyFlow : AfterFinallyFlow = flowNodeCreated ( { flags : FlowFlags . AfterFinally , antecedent : currentFlow } ) ;
1320+ const afterFinallyFlow = new FlowNode ( FlowFlags . AfterFinally ) as AfterFinallyFlow ;
1321+ afterFinallyFlow . antecedent = currentFlow ;
1322+ flowNodeCreated ( afterFinallyFlow ) ;
12821323 preFinallyFlow . lock = afterFinallyFlow ;
12831324 currentFlow = afterFinallyFlow ;
12841325 }
@@ -1986,7 +2027,7 @@ namespace ts {
19862027 const host = getJSDocHost ( typeAlias ) ;
19872028 container = findAncestor ( host . parent , n => ! ! ( getContainerFlags ( n ) & ContainerFlags . IsContainer ) ) || file ;
19882029 blockScopeContainer = getEnclosingBlockScopeContainer ( host ) || file ;
1989- currentFlow = { flags : FlowFlags . Start } ;
2030+ currentFlow = createFlowStart ( ) ;
19902031 parent = typeAlias ;
19912032 bind ( typeAlias . typeExpression ) ;
19922033 const declName = getNameOfDeclaration ( typeAlias ) ;
0 commit comments