Skip to content

Commit 57bb716

Browse files
committed
Ensure shared flow nodes are cached
Flow nodes that optionally provide a flow type will delegate to their antecedent to determine a flow type using a loop in `getFlowTypeOfReference`. If these nodes are marked as shared then their result should be cached for future lookups, but the registration inside `getFlowTypeOfReference` did only consider the most-recently processed flow node. Any flow nodes up to that point that did not provide a type but were marked as shared would therefore not be cached at all. This commit keeps track of the first seen shared flow node and ensures that the result type is cached for that node.
1 parent 76cf8fd commit 57bb716

File tree

5 files changed

+959
-3
lines changed

5 files changed

+959
-3
lines changed

src/compiler/checker.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21673,6 +21673,12 @@ namespace ts {
2167321673
}
2167421674
}
2167521675

21676+
function addSharedFlowType(flow: FlowNode, type: FlowType): void {
21677+
sharedFlowNodes[sharedFlowCount] = flow;
21678+
sharedFlowTypes[sharedFlowCount] = type;
21679+
sharedFlowCount++;
21680+
}
21681+
2167621682
function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node, couldBeUninitialized?: boolean) {
2167721683
let key: string | undefined;
2167821684
let isKeySet = false;
@@ -21715,6 +21721,7 @@ namespace ts {
2171521721
return errorType;
2171621722
}
2171721723
flowDepth++;
21724+
let sharedFlow: FlowNode | undefined;
2171821725
while (true) {
2171921726
const flags = flow.flags;
2172021727
if (flags & FlowFlags.Shared) {
@@ -21727,6 +21734,12 @@ namespace ts {
2172721734
return sharedFlowTypes[i];
2172821735
}
2172921736
}
21737+
21738+
// Keep track of the shared flow that is seen first to ensure that the
21739+
// computed type is saved in the shared flow type cache.
21740+
if (!sharedFlow) {
21741+
sharedFlow = flow;
21742+
}
2173021743
}
2173121744
let type: FlowType | undefined;
2173221745
if (flags & FlowFlags.Assignment) {
@@ -21792,9 +21805,12 @@ namespace ts {
2179221805
}
2179321806
if (flags & FlowFlags.Shared) {
2179421807
// Record visited node and the associated type in the cache.
21795-
sharedFlowNodes[sharedFlowCount] = flow;
21796-
sharedFlowTypes[sharedFlowCount] = type;
21797-
sharedFlowCount++;
21808+
addSharedFlowType(flow, type);
21809+
}
21810+
if (sharedFlow && sharedFlow !== flow) {
21811+
// If a shared flow other than the currently active flow was seen, also
21812+
// record the resulting type for that shared flow.
21813+
addSharedFlowType(sharedFlow, type);
2179821814
}
2179921815
flowDepth--;
2180021816
return type;
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
//// [controlFlowManyCallExpressionStatementsPerf.ts]
2+
function test(x: boolean): boolean { return x; }
3+
4+
let state = true;
5+
6+
if (state) {
7+
test(state as any && state);
8+
test(state as any && state);
9+
test(state as any && state);
10+
test(state as any && state);
11+
test(state as any && state);
12+
test(state as any && state);
13+
test(state as any && state);
14+
test(state as any && state);
15+
test(state as any && state);
16+
test(state as any && state);
17+
test(state as any && state);
18+
test(state as any && state);
19+
test(state as any && state);
20+
test(state as any && state);
21+
test(state as any && state);
22+
test(state as any && state);
23+
test(state as any && state);
24+
test(state as any && state);
25+
test(state as any && state);
26+
test(state as any && state);
27+
test(state as any && state);
28+
test(state as any && state);
29+
test(state as any && state);
30+
test(state as any && state);
31+
test(state as any && state);
32+
test(state as any && state);
33+
test(state as any && state);
34+
test(state as any && state);
35+
test(state as any && state);
36+
test(state as any && state);
37+
test(state as any && state);
38+
test(state as any && state);
39+
test(state as any && state);
40+
test(state as any && state);
41+
test(state as any && state);
42+
test(state as any && state);
43+
test(state as any && state);
44+
test(state as any && state);
45+
test(state as any && state);
46+
test(state as any && state);
47+
test(state as any && state);
48+
test(state as any && state);
49+
test(state as any && state);
50+
test(state as any && state);
51+
test(state as any && state);
52+
test(state as any && state);
53+
test(state as any && state);
54+
test(state as any && state);
55+
test(state as any && state);
56+
test(state as any && state);
57+
test(state as any && state);
58+
test(state as any && state);
59+
test(state as any && state);
60+
test(state as any && state);
61+
test(state as any && state);
62+
test(state as any && state);
63+
}
64+
65+
//// [controlFlowManyCallExpressionStatementsPerf.js]
66+
function test(x) { return x; }
67+
var state = true;
68+
if (state) {
69+
test(state && state);
70+
test(state && state);
71+
test(state && state);
72+
test(state && state);
73+
test(state && state);
74+
test(state && state);
75+
test(state && state);
76+
test(state && state);
77+
test(state && state);
78+
test(state && state);
79+
test(state && state);
80+
test(state && state);
81+
test(state && state);
82+
test(state && state);
83+
test(state && state);
84+
test(state && state);
85+
test(state && state);
86+
test(state && state);
87+
test(state && state);
88+
test(state && state);
89+
test(state && state);
90+
test(state && state);
91+
test(state && state);
92+
test(state && state);
93+
test(state && state);
94+
test(state && state);
95+
test(state && state);
96+
test(state && state);
97+
test(state && state);
98+
test(state && state);
99+
test(state && state);
100+
test(state && state);
101+
test(state && state);
102+
test(state && state);
103+
test(state && state);
104+
test(state && state);
105+
test(state && state);
106+
test(state && state);
107+
test(state && state);
108+
test(state && state);
109+
test(state && state);
110+
test(state && state);
111+
test(state && state);
112+
test(state && state);
113+
test(state && state);
114+
test(state && state);
115+
test(state && state);
116+
test(state && state);
117+
test(state && state);
118+
test(state && state);
119+
test(state && state);
120+
test(state && state);
121+
test(state && state);
122+
test(state && state);
123+
test(state && state);
124+
test(state && state);
125+
}

0 commit comments

Comments
 (0)