@@ -2110,6 +2110,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2110
2110
2111
2111
const contextualTypeNodes: Node[] = [];
2112
2112
const contextualTypes: (Type | undefined)[] = [];
2113
+ const contextualIsCache: boolean[] = [];
2113
2114
let contextualTypeCount = 0;
2114
2115
2115
2116
const inferenceContextNodes: Node[] = [];
@@ -19199,7 +19200,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
19199
19200
}
19200
19201
19201
19202
function checkExpressionForMutableLocationWithContextualType(next: Expression, sourcePropType: Type) {
19202
- pushContextualType(next, sourcePropType);
19203
+ pushContextualType(next, sourcePropType, /*isCache*/ false );
19203
19204
const result = checkExpressionForMutableLocation(next, CheckMode.Contextual);
19204
19205
popContextualType();
19205
19206
return result;
@@ -19516,7 +19517,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
19516
19517
}
19517
19518
// recreate a tuple from the elements, if possible
19518
19519
// Since we're re-doing the expression type, we need to reapply the contextual type
19519
- pushContextualType(node, target);
19520
+ pushContextualType(node, target, /*isCache*/ false );
19520
19521
const tupleizedType = checkArrayLiteral(node, CheckMode.Contextual, /*forceTuple*/ true);
19521
19522
popContextualType();
19522
19523
if (isTupleLikeType(tupleizedType)) {
@@ -29035,10 +29036,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
29035
29036
// We cannot answer semantic questions within a with block, do not proceed any further
29036
29037
return undefined;
29037
29038
}
29038
- const index = findContextualNode(node);
29039
+ // Cached contextual types are obtained with no ContextFlags, so we can only consult them for
29040
+ // requests with no ContextFlags.
29041
+ const index = findContextualNode(node, /*includeCaches*/ !contextFlags);
29039
29042
if (index >= 0) {
29040
- const cached = contextualTypes[index];
29041
- if (cached || !contextFlags) return cached;
29043
+ return contextualTypes[index];
29042
29044
}
29043
29045
const { parent } = node;
29044
29046
switch (parent.kind) {
@@ -29111,19 +29113,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
29111
29113
return undefined;
29112
29114
}
29113
29115
29114
- function pushContextualType(node: Node, type: Type | undefined) {
29116
+ function pushCachedContextualType(node: Expression) {
29117
+ pushContextualType(node, getContextualType(node, /*contextFlags*/ undefined), /*isCache*/ true);
29118
+ }
29119
+
29120
+ function pushContextualType(node: Expression, type: Type | undefined, isCache: boolean) {
29115
29121
contextualTypeNodes[contextualTypeCount] = node;
29116
29122
contextualTypes[contextualTypeCount] = type;
29123
+ contextualIsCache[contextualTypeCount] = isCache;
29117
29124
contextualTypeCount++;
29118
29125
}
29119
29126
29120
29127
function popContextualType() {
29121
29128
contextualTypeCount--;
29122
29129
}
29123
29130
29124
- function findContextualNode(node: Node) {
29131
+ function findContextualNode(node: Node, includeCaches: boolean ) {
29125
29132
for (let i = contextualTypeCount - 1; i >= 0; i--) {
29126
- if (node === contextualTypeNodes[i]) {
29133
+ if (node === contextualTypeNodes[i] && (includeCaches || !contextualIsCache[i]) ) {
29127
29134
return i;
29128
29135
}
29129
29136
}
@@ -29150,7 +29157,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
29150
29157
29151
29158
function getContextualJsxElementAttributesType(node: JsxOpeningLikeElement, contextFlags: ContextFlags | undefined) {
29152
29159
if (isJsxOpeningElement(node) && contextFlags !== ContextFlags.Completions) {
29153
- const index = findContextualNode(node.parent);
29160
+ const index = findContextualNode(node.parent, /*includeCaches*/ !contextFlags );
29154
29161
if (index >= 0) {
29155
29162
// Contextually applied type is moved from attributes up to the outer jsx attributes so when walking up from the children they get hit
29156
29163
// _However_ to hit them from the _attributes_ we must look for them here; otherwise we'll used the declared type
@@ -29486,7 +29493,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
29486
29493
const elementCount = elements.length;
29487
29494
const elementTypes: Type[] = [];
29488
29495
const elementFlags: ElementFlags[] = [];
29489
- pushContextualType (node, getContextualType(node, /*contextFlags*/ undefined) );
29496
+ pushCachedContextualType (node);
29490
29497
const inDestructuringPattern = isAssignmentTarget(node);
29491
29498
const inConstContext = isConstContext(node);
29492
29499
const contextualType = getApparentTypeOfContextualType(node, /*contextFlags*/ undefined);
@@ -29669,7 +29676,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
29669
29676
let propertiesArray: Symbol[] = [];
29670
29677
let spread: Type = emptyObjectType;
29671
29678
29672
- pushContextualType (node, getContextualType(node, /*contextFlags*/ undefined) );
29679
+ pushCachedContextualType (node);
29673
29680
const contextualType = getApparentTypeOfContextualType(node, /*contextFlags*/ undefined);
29674
29681
const contextualTypeHasPattern = contextualType && contextualType.pattern &&
29675
29682
(contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern || contextualType.pattern.kind === SyntaxKind.ObjectLiteralExpression);
@@ -36828,16 +36835,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
36828
36835
type.flags & TypeFlags.InstantiableNonPrimitive && maybeTypeOfKind(getBaseConstraintOfType(type) || unknownType, TypeFlags.StringLike));
36829
36836
}
36830
36837
36831
- function getContextNode(node: Expression): Node {
36832
- if (node.kind === SyntaxKind.JsxAttributes && !isJsxSelfClosingElement(node.parent)) {
36838
+ function getContextNode(node: Expression): Expression {
36839
+ if (isJsxAttributes( node) && !isJsxSelfClosingElement(node.parent)) {
36833
36840
return node.parent.parent; // Needs to be the root JsxElement, so it encompasses the attributes _and_ the children (which are essentially part of the attributes)
36834
36841
}
36835
36842
return node;
36836
36843
}
36837
36844
36838
36845
function checkExpressionWithContextualType(node: Expression, contextualType: Type, inferenceContext: InferenceContext | undefined, checkMode: CheckMode): Type {
36839
36846
const contextNode = getContextNode(node);
36840
- pushContextualType(contextNode, contextualType);
36847
+ pushContextualType(contextNode, contextualType, /*isCache*/ false );
36841
36848
pushInferenceContext(contextNode, inferenceContext);
36842
36849
const type = checkExpression(node, checkMode | CheckMode.Contextual | (inferenceContext ? CheckMode.Inferential : 0));
36843
36850
// In CheckMode.Inferential we collect intra-expression inference sites to process before fixing any type
@@ -37228,7 +37235,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
37228
37235
if (links.contextFreeType) {
37229
37236
return links.contextFreeType;
37230
37237
}
37231
- pushContextualType(node, anyType);
37238
+ pushContextualType(node, anyType, /*isCache*/ false );
37232
37239
const type = links.contextFreeType = checkExpression(node, CheckMode.SkipContextSensitive);
37233
37240
popContextualType();
37234
37241
return type;
0 commit comments