@@ -209,10 +209,11 @@ namespace ts {
209
209
let symbolCount = 0 ;
210
210
211
211
let Symbol : new ( flags : SymbolFlags , name : __String ) => Symbol ;
212
+ let FlowNode : new ( flags : FlowFlags ) => FlowNodeBase ;
212
213
let classifiableNames : UnderscoreEscapedMap < true > ;
213
214
214
- const unreachableFlow : FlowNode = { flags : FlowFlags . Unreachable } ;
215
- const reportedUnreachableFlow : FlowNode = { flags : FlowFlags . Unreachable } ;
215
+ let unreachableFlow : FlowNode ;
216
+ let reportedUnreachableFlow : FlowNode ;
216
217
217
218
// state used to aggregate transform flags during bind.
218
219
let subtreeTransformFlags : TransformFlags = TransformFlags . None ;
@@ -227,6 +228,17 @@ namespace ts {
227
228
return createDiagnosticForNodeInSourceFile ( getSourceFileOfNode ( node ) || file , node , message , arg0 , arg1 , arg2 ) ;
228
229
}
229
230
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
+
230
242
function bindSourceFile ( f : SourceFile , opts : CompilerOptions ) {
231
243
file = f ;
232
244
options = opts ;
@@ -236,7 +248,7 @@ namespace ts {
236
248
symbolCount = 0 ;
237
249
skipTransformFlagAggregation = file . isDeclarationFile ;
238
250
239
- Symbol = objectAllocator . getSymbolConstructor ( ) ;
251
+ initializeBinder ( ) ;
240
252
241
253
if ( ! file . locals ) {
242
254
bind ( file ) ;
@@ -623,7 +635,7 @@ namespace ts {
623
635
// A non-async, non-generator IIFE is considered part of the containing control flow. Return statements behave
624
636
// similarly to break statements that exit to a label just past the statement body.
625
637
if ( ! isIIFE ) {
626
- currentFlow = { flags : FlowFlags . Start } ;
638
+ currentFlow = createFlowStart ( ) ;
627
639
if ( containerFlags & ( ContainerFlags . IsFunctionExpression | ContainerFlags . IsObjectLiteralOrClassExpressionMethod ) ) {
628
640
currentFlow . node = < FunctionExpression | ArrowFunction | MethodDeclaration > node ;
629
641
}
@@ -917,11 +929,15 @@ namespace ts {
917
929
}
918
930
919
931
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 ;
921
935
}
922
936
923
937
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 ;
925
941
}
926
942
927
943
function setFlowNodeReferenced ( flow : FlowNode ) {
@@ -936,6 +952,10 @@ namespace ts {
936
952
}
937
953
}
938
954
955
+ function createFlowStart ( ) : FlowStart {
956
+ return new FlowNode ( FlowFlags . Start ) as FlowStart ;
957
+ }
958
+
939
959
function createFlowCondition ( flags : FlowFlags , antecedent : FlowNode , expression : Expression | undefined ) : FlowNode {
940
960
if ( antecedent . flags & FlowFlags . Unreachable ) {
941
961
return antecedent ;
@@ -953,30 +973,47 @@ namespace ts {
953
973
return antecedent ;
954
974
}
955
975
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 ) ;
957
980
}
958
981
959
982
function createFlowSwitchClause ( antecedent : FlowNode , switchStatement : SwitchStatement , clauseStart : number , clauseEnd : number ) : FlowNode {
960
983
if ( ! isNarrowingExpression ( switchStatement . expression ) ) {
961
984
return antecedent ;
962
985
}
963
986
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 ) ;
965
993
}
966
994
967
995
function createFlowAssignment ( antecedent : FlowNode , node : Expression | VariableDeclaration | BindingElement ) : FlowNode {
968
996
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 ) ;
970
1001
}
971
1002
972
1003
function createFlowCall ( antecedent : FlowNode , node : CallExpression ) : FlowNode {
973
1004
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 ) ;
975
1009
}
976
1010
977
1011
function createFlowArrayMutation ( antecedent : FlowNode , node : CallExpression | BinaryExpression ) : FlowNode {
978
1012
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 ) ;
980
1017
}
981
1018
982
1019
function finishFlowLabel ( flow : FlowLabel ) : FlowNode {
@@ -1259,7 +1296,9 @@ namespace ts {
1259
1296
//
1260
1297
// extra edges that we inject allows to control this behavior
1261
1298
// 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 = { } ;
1263
1302
addAntecedent ( preFinallyLabel , preFinallyFlow ) ;
1264
1303
1265
1304
currentFlow = finishFlowLabel ( preFinallyLabel ) ;
@@ -1278,7 +1317,9 @@ namespace ts {
1278
1317
}
1279
1318
}
1280
1319
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 ) ;
1282
1323
preFinallyFlow . lock = afterFinallyFlow ;
1283
1324
currentFlow = afterFinallyFlow ;
1284
1325
}
@@ -1986,7 +2027,7 @@ namespace ts {
1986
2027
const host = getJSDocHost ( typeAlias ) ;
1987
2028
container = findAncestor ( host . parent , n => ! ! ( getContainerFlags ( n ) & ContainerFlags . IsContainer ) ) || file ;
1988
2029
blockScopeContainer = getEnclosingBlockScopeContainer ( host ) || file ;
1989
- currentFlow = { flags : FlowFlags . Start } ;
2030
+ currentFlow = createFlowStart ( ) ;
1990
2031
parent = typeAlias ;
1991
2032
bind ( typeAlias . typeExpression ) ;
1992
2033
const declName = getNameOfDeclaration ( typeAlias ) ;
0 commit comments