@@ -62,10 +62,17 @@ import {
6262 Expression ,
6363 ExpressionStatement ,
6464 findAncestor ,
65+ FlowArrayMutation ,
66+ FlowAssignment ,
67+ FlowCall ,
68+ FlowCondition ,
6569 FlowFlags ,
6670 FlowLabel ,
6771 FlowNode ,
72+ FlowNodeBase ,
6873 FlowReduceLabel ,
74+ FlowStart ,
75+ FlowSwitchClause ,
6976 forEach ,
7077 forEachChild ,
7178 ForInOrOfStatement ,
@@ -464,11 +471,88 @@ const enum ContainerFlags {
464471 IsObjectLiteralOrClassExpressionMethodOrAccessor = 1 << 7 ,
465472}
466473
467- function initFlowNode < T extends FlowNode > ( node : T ) {
468- Debug . attachFlowNodeDebugInfo ( node ) ;
469- return node ;
474+ function createFlowNode < T extends FlowNode > (
475+ flags : FlowFlags ,
476+ node ?: Node ,
477+ antecedent ?: FlowNode ,
478+ antecedents ?: FlowNode [ ] ,
479+ target ?: FlowLabel ,
480+ switchStatement ?: SwitchStatement ,
481+ clauseStart ?: number ,
482+ clauseEnd ?: number ,
483+ ) : T {
484+ // Create all flow nodes in a predictable order. If FlowNode changes, add more
485+ // properties here.
486+ const flowNode : FlowNodeBase = {
487+ flags,
488+ id : undefined ,
489+ node,
490+ antecedent,
491+ antecedents,
492+ target,
493+ switchStatement,
494+ clauseStart,
495+ clauseEnd,
496+ } ;
497+ Debug . attachFlowNodeDebugInfo ( flowNode ) ;
498+ return flowNode as T ;
470499}
471500
501+ function createFlowStartNode ( flags : FlowFlags ) : FlowStart {
502+ return createFlowNode ( flags ) ;
503+ }
504+
505+ function createFlowLabelNode (
506+ flags : FlowFlags ,
507+ antecedents : FlowNode [ ] | undefined ,
508+ ) : FlowLabel {
509+ return createFlowNode ( flags , /*node*/ undefined , /*antecedent*/ undefined , antecedents ) ;
510+ }
511+
512+ function createFlowMutationNode (
513+ flags : FlowFlags ,
514+ node : FlowAssignment [ "node" ] | FlowArrayMutation [ "node" ] ,
515+ antecedent : FlowNode ,
516+ ) : FlowAssignment | FlowArrayMutation {
517+ return createFlowNode ( flags , node , antecedent ) ;
518+ }
519+
520+ function createFlowConditionNode (
521+ flags : FlowFlags ,
522+ node : FlowCondition [ "node" ] ,
523+ antecedent : FlowNode ,
524+ ) : FlowCondition {
525+ return createFlowNode ( flags , node , antecedent ) ;
526+ }
527+
528+ function createFlowSwitchClauseNode (
529+ flags : FlowFlags ,
530+ switchStatement : SwitchStatement ,
531+ clauseStart : number ,
532+ clauseEnd : number ,
533+ antecedent : FlowNode ,
534+ ) : FlowSwitchClause {
535+ return createFlowNode ( flags , /*node*/ undefined , antecedent , /*antecedents*/ undefined , /*target*/ undefined , switchStatement , clauseStart , clauseEnd ) ;
536+ }
537+
538+ function createFlowCallNode (
539+ flags : FlowFlags ,
540+ node : FlowCall [ "node" ] ,
541+ antecedent : FlowNode ,
542+ ) : FlowCall {
543+ return createFlowNode ( flags , node , antecedent ) ;
544+ }
545+
546+ function createFlowReduceLabelNode (
547+ flags : FlowFlags ,
548+ antecedent : FlowNode ,
549+ antecedents : FlowNode [ ] ,
550+ target : FlowLabel ,
551+ ) : FlowReduceLabel {
552+ return createFlowNode ( flags , /*node*/ undefined , antecedent , antecedents , target ) ;
553+ }
554+
555+
472556const binder = createBinder ( ) ;
473557
474558/** @internal */
@@ -965,7 +1049,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
9651049 // A non-async, non-generator IIFE is considered part of the containing control flow. Return statements behave
9661050 // similarly to break statements that exit to a label just past the statement body.
9671051 if ( ! isImmediatelyInvoked ) {
968- currentFlow = initFlowNode ( { flags : FlowFlags . Start } ) ;
1052+ currentFlow = createFlowStartNode ( FlowFlags . Start ) ;
9691053 if ( containerFlags & ( ContainerFlags . IsFunctionExpression | ContainerFlags . IsObjectLiteralOrClassExpressionMethodOrAccessor ) ) {
9701054 currentFlow . node = node as FunctionExpression | ArrowFunction | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration ;
9711055 }
@@ -1261,15 +1345,15 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
12611345 }
12621346
12631347 function createBranchLabel ( ) : FlowLabel {
1264- return initFlowNode ( { flags : FlowFlags . BranchLabel , antecedents : undefined } ) ;
1348+ return createFlowLabelNode ( FlowFlags . BranchLabel , /* antecedents*/ undefined ) ;
12651349 }
12661350
12671351 function createLoopLabel ( ) : FlowLabel {
1268- return initFlowNode ( { flags : FlowFlags . LoopLabel , antecedents : undefined } ) ;
1352+ return createFlowLabelNode ( FlowFlags . LoopLabel , /* antecedents*/ undefined ) ;
12691353 }
12701354
12711355 function createReduceLabel ( target : FlowLabel , antecedents : FlowNode [ ] , antecedent : FlowNode ) : FlowReduceLabel {
1272- return initFlowNode ( { flags : FlowFlags . ReduceLabel , target , antecedents, antecedent } ) ;
1356+ return createFlowReduceLabelNode ( FlowFlags . ReduceLabel , antecedent , antecedents , target ) ;
12731357 }
12741358
12751359 function setFlowNodeReferenced ( flow : FlowNode ) {
@@ -1300,17 +1384,17 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
13001384 return antecedent ;
13011385 }
13021386 setFlowNodeReferenced ( antecedent ) ;
1303- return initFlowNode ( { flags, antecedent , node : expression } ) ;
1387+ return createFlowConditionNode ( flags , expression , antecedent ) ;
13041388 }
13051389
13061390 function createFlowSwitchClause ( antecedent : FlowNode , switchStatement : SwitchStatement , clauseStart : number , clauseEnd : number ) : FlowNode {
13071391 setFlowNodeReferenced ( antecedent ) ;
1308- return initFlowNode ( { flags : FlowFlags . SwitchClause , antecedent , switchStatement, clauseStart, clauseEnd } ) ;
1392+ return createFlowSwitchClauseNode ( FlowFlags . SwitchClause , switchStatement , clauseStart , clauseEnd , antecedent ) ;
13091393 }
13101394
13111395 function createFlowMutation ( flags : FlowFlags , antecedent : FlowNode , node : Expression | VariableDeclaration | ArrayBindingElement ) : FlowNode {
13121396 setFlowNodeReferenced ( antecedent ) ;
1313- const result = initFlowNode ( { flags, antecedent , node } ) ;
1397+ const result = createFlowMutationNode ( flags , node , antecedent ) ;
13141398 if ( currentExceptionTarget ) {
13151399 addAntecedent ( currentExceptionTarget , result ) ;
13161400 }
@@ -1319,7 +1403,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
13191403
13201404 function createFlowCall ( antecedent : FlowNode , node : CallExpression ) : FlowNode {
13211405 setFlowNodeReferenced ( antecedent ) ;
1322- return initFlowNode ( { flags : FlowFlags . Call , antecedent , node } ) ;
1406+ return createFlowCallNode ( FlowFlags . Call , node , antecedent ) ;
13231407 }
13241408
13251409 function finishFlowLabel ( flow : FlowLabel ) : FlowNode {
@@ -2415,7 +2499,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
24152499 const host = typeAlias . parent . parent ;
24162500 container = findAncestor ( host . parent , n => ! ! ( getContainerFlags ( n ) & ContainerFlags . IsContainer ) ) || file ;
24172501 blockScopeContainer = getEnclosingBlockScopeContainer ( host ) || file ;
2418- currentFlow = initFlowNode ( { flags : FlowFlags . Start } ) ;
2502+ currentFlow = createFlowStartNode ( FlowFlags . Start ) ;
24192503 parent = typeAlias ;
24202504 bind ( typeAlias . typeExpression ) ;
24212505 const declName = getNameOfDeclaration ( typeAlias ) ;
0 commit comments