@@ -164,7 +164,6 @@ import {
164164 EmitResolver,
165165 EmitTextWriter,
166166 emptyArray,
167- emptyMap,
168167 EntityName,
169168 EntityNameExpression,
170169 EntityNameOrEntityNameExpression,
@@ -2111,14 +2110,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
21112110 }
21122111 return t;
21132112 }, () => "(unmeasurable reporter)");
2114- reportUnreliableMapper.instantiations = emptyMap;
21152113 var reportUnmeasurableMapper = makeFunctionTypeMapper(t => {
21162114 if (outofbandVarianceMarkerHandler && (t === markerSuperType || t === markerSubType || t === markerOtherType)) {
21172115 outofbandVarianceMarkerHandler(/*onlyUnreliable*/ false);
21182116 }
21192117 return t;
21202118 }, () => "(unreliable reporter)");
2121- reportUnmeasurableMapper.instantiations = emptyMap;
21222119
21232120 var emptyObjectType = createAnonymousType(/*symbol*/ undefined, emptySymbols, emptyArray, emptyArray, emptyArray);
21242121 var emptyJsxObjectType = createAnonymousType(/*symbol*/ undefined, emptySymbols, emptyArray, emptyArray, emptyArray);
@@ -2319,6 +2316,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
23192316 var inferenceContexts: (InferenceContext | undefined)[] = [];
23202317 var inferenceContextCount = 0;
23212318
2319+ var activeTypeMappers: TypeMapper[] = [];
2320+ var activeTypeMappersCaches: Map<string, Type>[] = [];
2321+ var activeTypeMappersCount = 0;
2322+
23222323 var emptyStringType = getStringLiteralType("");
23232324 var zeroType = getNumberLiteralType(0);
23242325 var zeroBigIntType = getBigIntLiteralType({ negative: false, base10Value: "0" });
@@ -20374,22 +20375,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2037420375 error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite);
2037520376 return errorType;
2037620377 }
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;
2038420387 }
2038520388 totalInstantiationCount++;
2038620389 instantiationCount++;
2038720390 instantiationDepth++;
2038820391 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);
2039320397 }
2039420398 instantiationDepth--;
2039520399 return result;
@@ -25594,7 +25598,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2559425598
2559525599 function clearCachedInferences(context: InferenceContext | undefined, inferences: InferenceInfo[]) {
2559625600 if (context) {
25597- context.nonFixingMapper.instantiations = undefined ;
25601+ clearActiveMapperCache( context.nonFixingMapper) ;
2559825602 }
2559925603 for (const inference of inferences) {
2560025604 if (!inference.isFixed) {
@@ -26967,7 +26971,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2696726971 // instantiating the constraint could reenter this function if the type parameter's constraint depends on that parameter
2696826972 // in such a case the reentering call just returns the preemptively set `.inferredType`
2696926973 // 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) ;
2697126975 }
2697226976 }
2697326977 }
@@ -32186,6 +32190,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3218632190 }
3218732191 }
3218832192
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+
3218932219 function getContextualImportAttributeType(node: ImportAttribute) {
3219032220 return getTypeOfPropertyOfContextualType(getGlobalImportAttributesType(/*reportErrors*/ false), getNameFromImportAttribute(node));
3219132221 }
0 commit comments