@@ -841,6 +841,7 @@ namespace ts {
841841 let deferredGlobalESSymbolConstructorSymbol: Symbol | undefined;
842842 let deferredGlobalESSymbolType: ObjectType;
843843 let deferredGlobalTypedPropertyDescriptorType: GenericType;
844+ let deferredGlobalAwaitedSymbol: Symbol | undefined;
844845 let deferredGlobalPromiseType: GenericType;
845846 let deferredGlobalPromiseLikeType: GenericType;
846847 let deferredGlobalPromiseConstructorSymbol: Symbol | undefined;
@@ -895,7 +896,6 @@ namespace ts {
895896 const potentialThisCollisions: Node[] = [];
896897 const potentialNewTargetCollisions: Node[] = [];
897898 const potentialWeakMapCollisions: Node[] = [];
898- const awaitedTypeStack: number[] = [];
899899
900900 const diagnostics = createDiagnosticCollection();
901901 const suggestionDiagnostics = createDiagnosticCollection();
@@ -11449,6 +11449,10 @@ namespace ts {
1144911449 return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType;
1145011450 }
1145111451
11452+ function getGlobalAwaitedSymbol(reportErrors: boolean) {
11453+ return deferredGlobalAwaitedSymbol || (deferredGlobalAwaitedSymbol = getGlobalTypeSymbol("Awaited" as __String, reportErrors));
11454+ }
11455+
1145211456 function getGlobalPromiseType(reportErrors: boolean) {
1145311457 return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
1145411458 }
@@ -26192,8 +26196,6 @@ namespace ts {
2619226196 // creates a `Promise<T>` type where `T` is the promisedType argument
2619326197 const globalPromiseType = getGlobalPromiseType(/*reportErrors*/ true);
2619426198 if (globalPromiseType !== emptyGenericType) {
26195- // if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
26196- promisedType = getAwaitedType(promisedType) || unknownType;
2619726199 return createTypeReference(globalPromiseType, [promisedType]);
2619826200 }
2619926201
@@ -26204,8 +26206,6 @@ namespace ts {
2620426206 // creates a `PromiseLike<T>` type where `T` is the promisedType argument
2620526207 const globalPromiseLikeType = getGlobalPromiseLikeType(/*reportErrors*/ true);
2620626208 if (globalPromiseLikeType !== emptyGenericType) {
26207- // if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
26208- promisedType = getAwaitedType(promisedType) || unknownType;
2620926209 return createTypeReference(globalPromiseLikeType, [promisedType]);
2621026210 }
2621126211
@@ -29665,98 +29665,26 @@ namespace ts {
2966529665 return typeAsAwaitable.awaitedTypeOfType = type;
2966629666 }
2966729667
29668- if (type.flags & TypeFlags.Union) {
29669- let types: Type[] | undefined;
29670- for (const constituentType of (<UnionType>type).types) {
29671- types = append<Type>(types, getAwaitedType(constituentType, errorNode, diagnosticMessage, arg0));
29672- }
29673-
29674- if (!types) {
29675- return undefined;
29676- }
29677-
29678- return typeAsAwaitable.awaitedTypeOfType = getUnionType(types);
29668+ const symbol = getGlobalAwaitedSymbol(/*reportErrors*/ false);
29669+ if (!symbol) {
29670+ return typeAsAwaitable.awaitedTypeOfType = type;
2967929671 }
2968029672
29681- const promisedType = getPromisedTypeOfPromise(type);
29682- if (promisedType) {
29683- if (type.id === promisedType.id || awaitedTypeStack.indexOf(promisedType.id) >= 0) {
29684- // Verify that we don't have a bad actor in the form of a promise whose
29685- // promised type is the same as the promise type, or a mutually recursive
29686- // promise. If so, we return undefined as we cannot guess the shape. If this
29687- // were the actual case in the JavaScript, this Promise would never resolve.
29688- //
29689- // An example of a bad actor with a singly-recursive promise type might
29690- // be:
29691- //
29692- // interface BadPromise {
29693- // then(
29694- // onfulfilled: (value: BadPromise) => any,
29695- // onrejected: (error: any) => any): BadPromise;
29696- // }
29697- // The above interface will pass the PromiseLike check, and return a
29698- // promised type of `BadPromise`. Since this is a self reference, we
29699- // don't want to keep recursing ad infinitum.
29700- //
29701- // An example of a bad actor in the form of a mutually-recursive
29702- // promise type might be:
29703- //
29704- // interface BadPromiseA {
29705- // then(
29706- // onfulfilled: (value: BadPromiseB) => any,
29707- // onrejected: (error: any) => any): BadPromiseB;
29708- // }
29709- //
29710- // interface BadPromiseB {
29711- // then(
29712- // onfulfilled: (value: BadPromiseA) => any,
29713- // onrejected: (error: any) => any): BadPromiseA;
29714- // }
29715- //
29716- if (errorNode) {
29717- error(errorNode, Diagnostics.Type_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method);
29718- }
29719- return undefined;
29720- }
29721-
29722- // Keep track of the type we're about to unwrap to avoid bad recursive promise types.
29723- // See the comments above for more information.
29724- awaitedTypeStack.push(type.id);
29725- const awaitedType = getAwaitedType(promisedType, errorNode, diagnosticMessage, arg0);
29726- awaitedTypeStack.pop();
29727-
29728- if (!awaitedType) {
29729- return undefined;
29730- }
29673+ if (type.aliasSymbol === symbol) {
29674+ return typeAsAwaitable.awaitedTypeOfType = type;
29675+ }
2973129676
29732- return typeAsAwaitable.awaitedTypeOfType = awaitedType;
29677+ const result = getTypeAliasInstantiation(symbol, [type]);
29678+ if (result !== unknownType || type === unknownType || getPromisedTypeOfPromise(type) === unknownType) {
29679+ return typeAsAwaitable.awaitedTypeOfType = result;
2973329680 }
2973429681
29735- // The type was not a promise, so it could not be unwrapped any further.
29736- // As long as the type does not have a callable "then" property, it is
29737- // safe to return the type; otherwise, an error will be reported in
29738- // the call to getNonThenableType and we will return undefined.
29739- //
29740- // An example of a non-promise "thenable" might be:
29741- //
29742- // await { then(): void {} }
29743- //
29744- // The "thenable" does not match the minimal definition for a promise. When
29745- // a Promise/A+-compatible or ES6 promise tries to adopt this value, the promise
29746- // will never settle. We treat this as an error to help flag an early indicator
29747- // of a runtime problem. If the user wants to return this value from an async
29748- // function, they would need to wrap it in some other value. If they want it to
29749- // be treated as a promise, they can cast to <any>.
29750- const thenFunction = getTypeOfPropertyOfType(type, "then" as __String);
29751- if (thenFunction && getSignaturesOfType(thenFunction, SignatureKind.Call).length > 0) {
29752- if (errorNode) {
29753- if (!diagnosticMessage) return Debug.fail();
29754- error(errorNode, diagnosticMessage, arg0);
29755- }
29756- return undefined;
29682+ if (errorNode) {
29683+ if (!diagnosticMessage) return Debug.fail();
29684+ error(errorNode, diagnosticMessage, arg0);
2975729685 }
2975829686
29759- return typeAsAwaitable.awaitedTypeOfType = type ;
29687+ return undefined ;
2976029688 }
2976129689
2976229690 /**
0 commit comments