@@ -820,6 +820,7 @@ namespace ts {
820820 let deferredGlobalESSymbolConstructorSymbol: Symbol | undefined;
821821 let deferredGlobalESSymbolType: ObjectType;
822822 let deferredGlobalTypedPropertyDescriptorType: GenericType;
823+ let deferredGlobalAwaitedSymbol: Symbol | undefined;
823824 let deferredGlobalPromiseType: GenericType;
824825 let deferredGlobalPromiseLikeType: GenericType;
825826 let deferredGlobalPromiseConstructorSymbol: Symbol | undefined;
@@ -874,7 +875,6 @@ namespace ts {
874875 const potentialThisCollisions: Node[] = [];
875876 const potentialNewTargetCollisions: Node[] = [];
876877 const potentialWeakMapCollisions: Node[] = [];
877- const awaitedTypeStack: number[] = [];
878878
879879 const diagnostics = createDiagnosticCollection();
880880 const suggestionDiagnostics = createDiagnosticCollection();
@@ -11309,6 +11309,10 @@ namespace ts {
1130911309 return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType;
1131011310 }
1131111311
11312+ function getGlobalAwaitedSymbol(reportErrors: boolean) {
11313+ return deferredGlobalAwaitedSymbol || (deferredGlobalAwaitedSymbol = getGlobalTypeSymbol("Awaited" as __String, reportErrors));
11314+ }
11315+
1131211316 function getGlobalPromiseType(reportErrors: boolean) {
1131311317 return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
1131411318 }
@@ -26053,8 +26057,6 @@ namespace ts {
2605326057 // creates a `Promise<T>` type where `T` is the promisedType argument
2605426058 const globalPromiseType = getGlobalPromiseType(/*reportErrors*/ true);
2605526059 if (globalPromiseType !== emptyGenericType) {
26056- // if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
26057- promisedType = getAwaitedType(promisedType) || unknownType;
2605826060 return createTypeReference(globalPromiseType, [promisedType]);
2605926061 }
2606026062
@@ -26065,8 +26067,6 @@ namespace ts {
2606526067 // creates a `PromiseLike<T>` type where `T` is the promisedType argument
2606626068 const globalPromiseLikeType = getGlobalPromiseLikeType(/*reportErrors*/ true);
2606726069 if (globalPromiseLikeType !== emptyGenericType) {
26068- // if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
26069- promisedType = getAwaitedType(promisedType) || unknownType;
2607026070 return createTypeReference(globalPromiseLikeType, [promisedType]);
2607126071 }
2607226072
@@ -29528,98 +29528,26 @@ namespace ts {
2952829528 return typeAsAwaitable.awaitedTypeOfType = type;
2952929529 }
2953029530
29531- if (type.flags & TypeFlags.Union) {
29532- let types: Type[] | undefined;
29533- for (const constituentType of (<UnionType>type).types) {
29534- types = append<Type>(types, getAwaitedType(constituentType, errorNode, diagnosticMessage, arg0));
29535- }
29536-
29537- if (!types) {
29538- return undefined;
29539- }
29540-
29541- return typeAsAwaitable.awaitedTypeOfType = getUnionType(types);
29531+ const symbol = getGlobalAwaitedSymbol(/*reportErrors*/ false);
29532+ if (!symbol) {
29533+ return typeAsAwaitable.awaitedTypeOfType = type;
2954229534 }
2954329535
29544- const promisedType = getPromisedTypeOfPromise(type);
29545- if (promisedType) {
29546- if (type.id === promisedType.id || awaitedTypeStack.indexOf(promisedType.id) >= 0) {
29547- // Verify that we don't have a bad actor in the form of a promise whose
29548- // promised type is the same as the promise type, or a mutually recursive
29549- // promise. If so, we return undefined as we cannot guess the shape. If this
29550- // were the actual case in the JavaScript, this Promise would never resolve.
29551- //
29552- // An example of a bad actor with a singly-recursive promise type might
29553- // be:
29554- //
29555- // interface BadPromise {
29556- // then(
29557- // onfulfilled: (value: BadPromise) => any,
29558- // onrejected: (error: any) => any): BadPromise;
29559- // }
29560- // The above interface will pass the PromiseLike check, and return a
29561- // promised type of `BadPromise`. Since this is a self reference, we
29562- // don't want to keep recursing ad infinitum.
29563- //
29564- // An example of a bad actor in the form of a mutually-recursive
29565- // promise type might be:
29566- //
29567- // interface BadPromiseA {
29568- // then(
29569- // onfulfilled: (value: BadPromiseB) => any,
29570- // onrejected: (error: any) => any): BadPromiseB;
29571- // }
29572- //
29573- // interface BadPromiseB {
29574- // then(
29575- // onfulfilled: (value: BadPromiseA) => any,
29576- // onrejected: (error: any) => any): BadPromiseA;
29577- // }
29578- //
29579- if (errorNode) {
29580- error(errorNode, Diagnostics.Type_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method);
29581- }
29582- return undefined;
29583- }
29584-
29585- // Keep track of the type we're about to unwrap to avoid bad recursive promise types.
29586- // See the comments above for more information.
29587- awaitedTypeStack.push(type.id);
29588- const awaitedType = getAwaitedType(promisedType, errorNode, diagnosticMessage, arg0);
29589- awaitedTypeStack.pop();
29590-
29591- if (!awaitedType) {
29592- return undefined;
29593- }
29536+ if (type.aliasSymbol === symbol) {
29537+ return typeAsAwaitable.awaitedTypeOfType = type;
29538+ }
2959429539
29595- return typeAsAwaitable.awaitedTypeOfType = awaitedType;
29540+ const result = getTypeAliasInstantiation(symbol, [type]);
29541+ if (result !== unknownType || type === unknownType || getPromisedTypeOfPromise(type) === unknownType) {
29542+ return typeAsAwaitable.awaitedTypeOfType = result;
2959629543 }
2959729544
29598- // The type was not a promise, so it could not be unwrapped any further.
29599- // As long as the type does not have a callable "then" property, it is
29600- // safe to return the type; otherwise, an error will be reported in
29601- // the call to getNonThenableType and we will return undefined.
29602- //
29603- // An example of a non-promise "thenable" might be:
29604- //
29605- // await { then(): void {} }
29606- //
29607- // The "thenable" does not match the minimal definition for a promise. When
29608- // a Promise/A+-compatible or ES6 promise tries to adopt this value, the promise
29609- // will never settle. We treat this as an error to help flag an early indicator
29610- // of a runtime problem. If the user wants to return this value from an async
29611- // function, they would need to wrap it in some other value. If they want it to
29612- // be treated as a promise, they can cast to <any>.
29613- const thenFunction = getTypeOfPropertyOfType(type, "then" as __String);
29614- if (thenFunction && getSignaturesOfType(thenFunction, SignatureKind.Call).length > 0) {
29615- if (errorNode) {
29616- if (!diagnosticMessage) return Debug.fail();
29617- error(errorNode, diagnosticMessage, arg0);
29618- }
29619- return undefined;
29545+ if (errorNode) {
29546+ if (!diagnosticMessage) return Debug.fail();
29547+ error(errorNode, diagnosticMessage, arg0);
2962029548 }
2962129549
29622- return typeAsAwaitable.awaitedTypeOfType = type ;
29550+ return undefined ;
2962329551 }
2962429552
2962529553 /**
0 commit comments