Ensure instantiation expressions have symbols, preventing crash in signature relations (#56064)

This commit is contained in:
Jake Bailey
2023-11-07 15:59:19 -08:00
committed by GitHub
parent 649e614496
commit 4dd1e2f844
13 changed files with 283 additions and 15 deletions
+18 -15
View File
@@ -6838,6 +6838,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const typeId = type.id;
const symbol = type.symbol;
if (symbol) {
const isInstantiationExpressionType = !!(getObjectFlags(type) & ObjectFlags.InstantiationExpressionType);
if (isInstantiationExpressionType) {
const instantiationExpressionType = type as InstantiationExpressionType;
const existing = instantiationExpressionType.node;
if (isTypeQueryNode(existing) && getTypeFromTypeNode(existing) === type) {
const typeNode = serializeExistingTypeNode(context, existing);
if (typeNode) {
return typeNode;
}
}
if (context.visitedTypes?.has(typeId)) {
return createElidedInformationPlaceholder(context);
}
return visitAndTransformType(type, createTypeNodeFromObjectType);
}
const isInstanceType = isClassInstanceSide(type) ? SymbolFlags.Type : SymbolFlags.Value;
if (isJSConstructor(symbol.valueDeclaration)) {
// Instance and static types share the same symbol; only add 'typeof' for the static side.
@@ -6869,20 +6884,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
else {
const isInstantiationExpressionType = !!(getObjectFlags(type) & ObjectFlags.InstantiationExpressionType);
if (isInstantiationExpressionType) {
const instantiationExpressionType = type as InstantiationExpressionType;
if (isTypeQueryNode(instantiationExpressionType.node)) {
const typeNode = serializeExistingTypeNode(context, instantiationExpressionType.node);
if (typeNode) {
return typeNode;
}
}
if (context.visitedTypes?.has(typeId)) {
return createElidedInformationPlaceholder(context);
}
return visitAndTransformType(type, createTypeNodeFromObjectType);
}
// Anonymous types without a symbol are never circular.
return createTypeNodeFromObjectType(type);
}
@@ -19542,6 +19543,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
function instantiateAnonymousType(type: AnonymousType, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): AnonymousType {
Debug.assert(type.symbol, "anonymous type must have symbol to be instantiated");
const result = createObjectType(type.objectFlags & ~(ObjectFlags.CouldContainTypeVariablesComputed | ObjectFlags.CouldContainTypeVariables) | ObjectFlags.Instantiated, type.symbol) as AnonymousType;
if (type.objectFlags & ObjectFlags.Mapped) {
(result as MappedType).declaration = (type as MappedType).declaration;
@@ -23074,6 +23076,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// method). Simply do a pairwise comparison of the signatures in the two signature lists instead
// of the much more expensive N * M comparison matrix we explore below. We erase type parameters
// as they are known to always be the same.
Debug.assertEqual(sourceSignatures.length, targetSignatures.length);
for (let i = 0; i < targetSignatures.length; i++) {
const related = signatureRelatedTo(sourceSignatures[i], targetSignatures[i], /*erase*/ true, reportErrors, intersectionState, incompatibleReporter(sourceSignatures[i], targetSignatures[i]));
if (!related) {
@@ -35677,7 +35680,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
hasSignatures ||= resolved.callSignatures.length !== 0 || resolved.constructSignatures.length !== 0;
hasApplicableSignature ||= callSignatures.length !== 0 || constructSignatures.length !== 0;
if (callSignatures !== resolved.callSignatures || constructSignatures !== resolved.constructSignatures) {
const result = createAnonymousType(/*symbol*/ undefined, resolved.members, callSignatures, constructSignatures, resolved.indexInfos) as ResolvedType & InstantiationExpressionType;
const result = createAnonymousType(createSymbol(SymbolFlags.None, InternalSymbolName.InstantiationExpression), resolved.members, callSignatures, constructSignatures, resolved.indexInfos) as ResolvedType & InstantiationExpressionType;
result.objectFlags |= ObjectFlags.InstantiationExpressionType;
result.node = node;
return result;
+1
View File
@@ -5955,6 +5955,7 @@ export const enum InternalSymbolName {
ExportEquals = "export=", // Export assignment symbol
Default = "default", // Default export symbol (technically not wholly internal, but included here for usability)
This = "this",
InstantiationExpression = "__instantiationExpression", // Instantiation expressions
}
/**