@@ -159,9 +159,9 @@ namespace ts {
159
159
let emitAwaiter = false;
160
160
let emitGenerator = false;
161
161
162
- let resolutionTargets: Object [] = [];
162
+ let resolutionTargets: TypeSystemEntity [] = [];
163
163
let resolutionResults: boolean[] = [];
164
- let resolutionKinds: TypeSystemObjectKind [] = [];
164
+ let resolutionPropertyNames: TypeSystemPropertyName [] = [];
165
165
166
166
let mergedSymbols: Symbol[] = [];
167
167
let symbolLinks: SymbolLinks[] = [];
@@ -202,11 +202,11 @@ namespace ts {
202
202
let assignableRelation: Map<RelationComparisonResult> = {};
203
203
let identityRelation: Map<RelationComparisonResult> = {};
204
204
205
- enum TypeSystemObjectKind {
206
- Symbol,
205
+ enum TypeSystemPropertyName {
207
206
Type,
208
- SymbolLinks,
209
- Signature
207
+ ResolvedBaseConstructorType,
208
+ DeclaredType,
209
+ ResolvedReturnType
210
210
}
211
211
212
212
initializeTypeChecker();
@@ -2185,45 +2185,58 @@ namespace ts {
2185
2185
}
2186
2186
}
2187
2187
2188
- // Push an entry on the type resolution stack. If an entry with the given target is not already on the stack,
2189
- // a new entry with that target and an associated result value of true is pushed on the stack, and the value
2190
- // true is returned. Otherwise, a circularity has occurred and the result values of the existing entry and
2191
- // all entries pushed after it are changed to false, and the value false is returned. The target object provides
2192
- // a unique identity for a particular type resolution result: Symbol instances are used to track resolution of
2193
- // SymbolLinks.type, SymbolLinks instances are used to track resolution of SymbolLinks.declaredType, and
2194
- // Signature instances are used to track resolution of Signature.resolvedReturnType.
2195
- function pushTypeResolution(target: Object, flags: TypeSystemObjectKind): boolean {
2196
- let count = resolutionTargets.length;
2197
- let i = count - 1;
2198
- let foundGoodType = false;
2199
- while (i >= 0 && !(foundGoodType = !!hasType(resolutionTargets[i], resolutionKinds[i])) && resolutionTargets[i] !== target) {
2200
- i--;
2201
- }
2202
- if (i >= 0 && !foundGoodType) {
2203
- do {
2204
- resolutionResults[i++] = false;
2188
+ /**
2189
+ * Push an entry on the type resolution stack. If an entry with the given target and the given property name
2190
+ * is already on the stack, and no entries in between already have a type, then a circularity has occurred.
2191
+ * In this case, the result values of the existing entry and all entries pushed after it are changed to false,
2192
+ * and the value false is returned. Otherwise, the new entry is just pushed onto the stack, and true is returned.
2193
+ * In order to see if the same query has already been done before, the target object and the propertyName both
2194
+ * must match the one passed in.
2195
+ *
2196
+ * @param target The symbol, type, or signature whose type is being queried
2197
+ * @param propertyName The property name that should be used to query the target for its type
2198
+ */
2199
+ function pushTypeResolution(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): boolean {
2200
+ let resolutionCycleStartIndex = findResolutionCycleStartIndex(target, propertyName);
2201
+ if (resolutionCycleStartIndex >= 0) {
2202
+ // A cycle was found
2203
+ let { length } = resolutionTargets;
2204
+ for (let i = resolutionCycleStartIndex; i < length; i++) {
2205
+ resolutionResults[i] = false;
2205
2206
}
2206
- while (i < count);
2207
2207
return false;
2208
2208
}
2209
2209
resolutionTargets.push(target);
2210
2210
resolutionResults.push(true);
2211
- resolutionKinds .push(flags );
2211
+ resolutionPropertyNames .push(propertyName );
2212
2212
return true;
2213
2213
}
2214
2214
2215
- function hasType(target: Object, flags: TypeSystemObjectKind): Type {
2216
- if (flags === TypeSystemObjectKind.Symbol) {
2215
+ function findResolutionCycleStartIndex(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): number {
2216
+ for (let i = resolutionTargets.length - 1; i >= 0; i--) {
2217
+ if (hasType(resolutionTargets[i], resolutionPropertyNames[i])) {
2218
+ return -1;
2219
+ }
2220
+ if (resolutionTargets[i] === target && resolutionPropertyNames[i] === propertyName) {
2221
+ return i;
2222
+ }
2223
+ }
2224
+
2225
+ return -1;
2226
+ }
2227
+
2228
+ function hasType(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): Type {
2229
+ if (propertyName === TypeSystemPropertyName.Type) {
2217
2230
return getSymbolLinks(<Symbol>target).type;
2218
2231
}
2219
- else if (flags === TypeSystemObjectKind.Type) {
2232
+ else if (propertyName === TypeSystemPropertyName.DeclaredType) {
2233
+ return getSymbolLinks(<Symbol>target).declaredType;
2234
+ }
2235
+ else if (propertyName === TypeSystemPropertyName.ResolvedBaseConstructorType) {
2220
2236
Debug.assert(!!((<Type>target).flags & TypeFlags.Class));
2221
2237
return (<InterfaceType>target).resolvedBaseConstructorType;
2222
2238
}
2223
- else if (flags === TypeSystemObjectKind.SymbolLinks) {
2224
- return (<SymbolLinks>target).declaredType;
2225
- }
2226
- else if (flags === TypeSystemObjectKind.Signature) {
2239
+ else if (propertyName === TypeSystemPropertyName.ResolvedReturnType) {
2227
2240
return (<Signature>target).resolvedReturnType;
2228
2241
}
2229
2242
@@ -2234,7 +2247,7 @@ namespace ts {
2234
2247
// be true if no circularities were detected, or false if a circularity was found.
2235
2248
function popTypeResolution(): boolean {
2236
2249
resolutionTargets.pop();
2237
- resolutionKinds .pop();
2250
+ resolutionPropertyNames .pop();
2238
2251
return resolutionResults.pop();
2239
2252
}
2240
2253
@@ -2497,7 +2510,7 @@ namespace ts {
2497
2510
return links.type = checkExpression((<ExportAssignment>declaration).expression);
2498
2511
}
2499
2512
// Handle variable, parameter or property
2500
- if (!pushTypeResolution(symbol, TypeSystemObjectKind.Symbol )) {
2513
+ if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type )) {
2501
2514
return unknownType;
2502
2515
}
2503
2516
let type = getWidenedTypeForVariableLikeDeclaration(<VariableLikeDeclaration>declaration, /*reportErrors*/ true);
@@ -2538,7 +2551,7 @@ namespace ts {
2538
2551
function getTypeOfAccessors(symbol: Symbol): Type {
2539
2552
let links = getSymbolLinks(symbol);
2540
2553
if (!links.type) {
2541
- if (!pushTypeResolution(symbol, TypeSystemObjectKind.Symbol )) {
2554
+ if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type )) {
2542
2555
return unknownType;
2543
2556
}
2544
2557
let getter = <AccessorDeclaration>getDeclarationOfKind(symbol, SyntaxKind.GetAccessor);
@@ -2754,7 +2767,7 @@ namespace ts {
2754
2767
if (!baseTypeNode) {
2755
2768
return type.resolvedBaseConstructorType = undefinedType;
2756
2769
}
2757
- if (!pushTypeResolution(type, TypeSystemObjectKind.Type )) {
2770
+ if (!pushTypeResolution(type, TypeSystemPropertyName.ResolvedBaseConstructorType )) {
2758
2771
return unknownType;
2759
2772
}
2760
2773
let baseConstructorType = checkExpression(baseTypeNode.expression);
@@ -2881,7 +2894,7 @@ namespace ts {
2881
2894
if (!links.declaredType) {
2882
2895
// Note that we use the links object as the target here because the symbol object is used as the unique
2883
2896
// identity for resolution of the 'type' property in SymbolLinks.
2884
- if (!pushTypeResolution(links, TypeSystemObjectKind.SymbolLinks )) {
2897
+ if (!pushTypeResolution(symbol, TypeSystemPropertyName.DeclaredType )) {
2885
2898
return unknownType;
2886
2899
}
2887
2900
let declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
@@ -3568,7 +3581,7 @@ namespace ts {
3568
3581
3569
3582
function getReturnTypeOfSignature(signature: Signature): Type {
3570
3583
if (!signature.resolvedReturnType) {
3571
- if (!pushTypeResolution(signature, TypeSystemObjectKind.Signature )) {
3584
+ if (!pushTypeResolution(signature, TypeSystemPropertyName.ResolvedReturnType )) {
3572
3585
return unknownType;
3573
3586
}
3574
3587
let type: Type;
0 commit comments