@@ -334,7 +334,7 @@ namespace ts {
334
334
let flowLoopStart = 0;
335
335
let flowLoopCount = 0;
336
336
let sharedFlowCount = 0;
337
- let flowAnalysisDisabled = false ;
337
+ let flowNodeCount = 0 ;
338
338
339
339
const emptyStringType = getLiteralType("");
340
340
const zeroType = getLiteralType(0);
@@ -11495,8 +11495,8 @@ namespace ts {
11495
11495
11496
11496
function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node, couldBeUninitialized?: boolean) {
11497
11497
let key: string;
11498
- let flowLength = 0;
11499
- if (flowAnalysisDisabled ) {
11498
+ let flowDepth = 0;
11499
+ if (flowNodeCount < 0 ) {
11500
11500
return unknownType;
11501
11501
}
11502
11502
if (!reference.flowNode || !couldBeUninitialized && !(declaredType.flags & TypeFlags.Narrowable)) {
@@ -11516,14 +11516,14 @@ namespace ts {
11516
11516
return resultType;
11517
11517
11518
11518
function getTypeAtFlowNode(flow: FlowNode): FlowType {
11519
- flowLength ++;
11519
+ flowDepth ++;
11520
11520
while (true) {
11521
- flowLength ++;
11522
- if (flowLength >= 5000 ) {
11523
- // We have visited as many as 5000 nodes through as many as 2500 recursive invocations . Rather than
11524
- // spending an excessive amount of time and possibly overflowing the call stack , we report an error
11521
+ flowNodeCount ++;
11522
+ if (flowDepth >= 2500 || flowNodeCount >= 100000000 ) {
11523
+ // We have made over 2500 recursive invocations or visited over 100M flow nodes . Rather than
11524
+ // overflowing the call stack or spending an excessive amount of time, we report an error
11525
11525
// and disable further control flow analysis in the containing function or module body.
11526
- flowAnalysisDisabled = true ;
11526
+ flowNodeCount = -1 ;
11527
11527
reportFlowControlError(reference);
11528
11528
return unknownType;
11529
11529
}
@@ -11534,6 +11534,7 @@ namespace ts {
11534
11534
// antecedent of more than one node.
11535
11535
for (let i = sharedFlowStart; i < sharedFlowCount; i++) {
11536
11536
if (sharedFlowNodes[i] === flow) {
11537
+ flowDepth--;
11537
11538
return sharedFlowTypes[i];
11538
11539
}
11539
11540
}
@@ -11601,6 +11602,7 @@ namespace ts {
11601
11602
sharedFlowTypes[sharedFlowCount] = type;
11602
11603
sharedFlowCount++;
11603
11604
}
11605
+ flowDepth--;
11604
11606
return type;
11605
11607
}
11606
11608
}
@@ -19976,9 +19978,15 @@ namespace ts {
19976
19978
if (node.kind === SyntaxKind.Block) {
19977
19979
checkGrammarStatementInAmbientContext(node);
19978
19980
}
19979
- const saveFlowAnalysisDisabled = flowAnalysisDisabled;
19980
- forEach(node.statements, checkSourceElement);
19981
- flowAnalysisDisabled = saveFlowAnalysisDisabled;
19981
+ if (isFunctionOrModuleBlock(node)) {
19982
+ const saveFlowNodeCount = flowNodeCount;
19983
+ flowNodeCount = 0;
19984
+ forEach(node.statements, checkSourceElement);
19985
+ flowNodeCount = saveFlowNodeCount;
19986
+ }
19987
+ else {
19988
+ forEach(node.statements, checkSourceElement);
19989
+ }
19982
19990
if (node.locals) {
19983
19991
registerForUnusedIdentifiersCheck(node);
19984
19992
}
@@ -22568,7 +22576,7 @@ namespace ts {
22568
22576
22569
22577
deferredNodes = [];
22570
22578
deferredUnusedIdentifierNodes = produceDiagnostics && noUnusedIdentifiers ? [] : undefined;
22571
- flowAnalysisDisabled = false ;
22579
+ flowNodeCount = 0 ;
22572
22580
22573
22581
forEach(node.statements, checkSourceElement);
22574
22582
0 commit comments