@@ -164,7 +164,6 @@ import {
164
164
EmitResolver,
165
165
EmitTextWriter,
166
166
emptyArray,
167
- emptyMap,
168
167
EntityName,
169
168
EntityNameExpression,
170
169
EntityNameOrEntityNameExpression,
@@ -2111,14 +2110,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2111
2110
}
2112
2111
return t;
2113
2112
}, () => "(unmeasurable reporter)");
2114
- reportUnreliableMapper.instantiations = emptyMap;
2115
2113
var reportUnmeasurableMapper = makeFunctionTypeMapper(t => {
2116
2114
if (outofbandVarianceMarkerHandler && (t === markerSuperType || t === markerSubType || t === markerOtherType)) {
2117
2115
outofbandVarianceMarkerHandler(/*onlyUnreliable*/ false);
2118
2116
}
2119
2117
return t;
2120
2118
}, () => "(unreliable reporter)");
2121
- reportUnmeasurableMapper.instantiations = emptyMap;
2122
2119
2123
2120
var emptyObjectType = createAnonymousType(/*symbol*/ undefined, emptySymbols, emptyArray, emptyArray, emptyArray);
2124
2121
var emptyJsxObjectType = createAnonymousType(/*symbol*/ undefined, emptySymbols, emptyArray, emptyArray, emptyArray);
@@ -2319,6 +2316,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2319
2316
var inferenceContexts: (InferenceContext | undefined)[] = [];
2320
2317
var inferenceContextCount = 0;
2321
2318
2319
+ var activeTypeMappers: TypeMapper[] = [];
2320
+ var activeTypeMappersCaches: Map<string, Type>[] = [];
2321
+ var activeTypeMappersCount = 0;
2322
+
2322
2323
var emptyStringType = getStringLiteralType("");
2323
2324
var zeroType = getNumberLiteralType(0);
2324
2325
var zeroBigIntType = getBigIntLiteralType({ negative: false, base10Value: "0" });
@@ -20374,22 +20375,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
20374
20375
error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite);
20375
20376
return errorType;
20376
20377
}
20377
- let key: string;
20378
- if (mapper.instantiations !== emptyMap) {
20379
- key = type.id + getAliasId(aliasSymbol, aliasTypeArguments);
20380
- const cached = (mapper.instantiations ??= new Map()).get(key);
20381
- if (cached) {
20382
- return cached;
20383
- }
20378
+ const index = findActiveMapper(mapper);
20379
+ if (index === -1) {
20380
+ pushActiveMapper(mapper);
20381
+ }
20382
+ const key = type.id + getAliasId(aliasSymbol, aliasTypeArguments);
20383
+ const mapperCache = activeTypeMappersCaches[index !== -1 ? index : activeTypeMappersCount - 1];
20384
+ const cached = mapperCache.get(key);
20385
+ if (cached) {
20386
+ return cached;
20384
20387
}
20385
20388
totalInstantiationCount++;
20386
20389
instantiationCount++;
20387
20390
instantiationDepth++;
20388
20391
const result = instantiateTypeWorker(type, mapper, aliasSymbol, aliasTypeArguments);
20389
- if (mapper.instantiations !== emptyMap) {
20390
- // volatile caches (like on `nonFixingMapper`) could have been cleared by the above `instantiateTypeWorker`
20391
- // if so, we don't want to cache the result as it likely won't be valid anymore anyway
20392
- mapper.instantiations?.set(key!, result);
20392
+ if (index === -1) {
20393
+ popActiveMapper();
20394
+ }
20395
+ else {
20396
+ mapperCache.set(key, result);
20393
20397
}
20394
20398
instantiationDepth--;
20395
20399
return result;
@@ -25594,7 +25598,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
25594
25598
25595
25599
function clearCachedInferences(context: InferenceContext | undefined, inferences: InferenceInfo[]) {
25596
25600
if (context) {
25597
- context.nonFixingMapper.instantiations = undefined ;
25601
+ clearActiveMapperCache( context.nonFixingMapper) ;
25598
25602
}
25599
25603
for (const inference of inferences) {
25600
25604
if (!inference.isFixed) {
@@ -26967,7 +26971,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
26967
26971
// instantiating the constraint could reenter this function if the type parameter's constraint depends on that parameter
26968
26972
// in such a case the reentering call just returns the preemptively set `.inferredType`
26969
26973
// but given the `.inferredType` gets changed changed above, the cached instantiations have to be cleared because they were cached for the wrong type
26970
- context.nonFixingMapper.instantiations = undefined ;
26974
+ clearActiveMapperCache( context.nonFixingMapper) ;
26971
26975
}
26972
26976
}
26973
26977
}
@@ -32186,6 +32190,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
32186
32190
}
32187
32191
}
32188
32192
32193
+ function pushActiveMapper(mapper: TypeMapper) {
32194
+ activeTypeMappers[activeTypeMappersCount] = mapper;
32195
+ activeTypeMappersCaches[activeTypeMappersCount] = new Map();
32196
+ activeTypeMappersCount++;
32197
+ }
32198
+
32199
+ function popActiveMapper() {
32200
+ activeTypeMappersCount--;
32201
+ }
32202
+
32203
+ function findActiveMapper(mapper: TypeMapper) {
32204
+ for (let i = activeTypeMappersCount - 1; i >= 0; i--) {
32205
+ if (mapper === activeTypeMappers[i]) {
32206
+ return i;
32207
+ }
32208
+ }
32209
+ return -1;
32210
+ }
32211
+
32212
+ function clearActiveMapperCache(mapper: TypeMapper) {
32213
+ const index = findActiveMapper(mapper);
32214
+ if (index !== -1) {
32215
+ activeTypeMappersCaches[index] = new Map();
32216
+ }
32217
+ }
32218
+
32189
32219
function getContextualImportAttributeType(node: ImportAttribute) {
32190
32220
return getTypeOfPropertyOfContextualType(getGlobalImportAttributesType(/*reportErrors*/ false), getNameFromImportAttribute(node));
32191
32221
}
0 commit comments