@@ -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();
@@ -11425,6 +11425,10 @@ namespace ts {
1142511425 return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType;
1142611426 }
1142711427
11428+ function getGlobalAwaitedSymbol(reportErrors: boolean) {
11429+ return deferredGlobalAwaitedSymbol || (deferredGlobalAwaitedSymbol = getGlobalTypeSymbol("Awaited" as __String, reportErrors));
11430+ }
11431+
1142811432 function getGlobalPromiseType(reportErrors: boolean) {
1142911433 return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
1143011434 }
@@ -26163,8 +26167,6 @@ namespace ts {
2616326167 // creates a `Promise<T>` type where `T` is the promisedType argument
2616426168 const globalPromiseType = getGlobalPromiseType(/*reportErrors*/ true);
2616526169 if (globalPromiseType !== emptyGenericType) {
26166- // if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
26167- promisedType = getAwaitedType(promisedType) || unknownType;
2616826170 return createTypeReference(globalPromiseType, [promisedType]);
2616926171 }
2617026172
@@ -26175,8 +26177,6 @@ namespace ts {
2617526177 // creates a `PromiseLike<T>` type where `T` is the promisedType argument
2617626178 const globalPromiseLikeType = getGlobalPromiseLikeType(/*reportErrors*/ true);
2617726179 if (globalPromiseLikeType !== emptyGenericType) {
26178- // if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
26179- promisedType = getAwaitedType(promisedType) || unknownType;
2618026180 return createTypeReference(globalPromiseLikeType, [promisedType]);
2618126181 }
2618226182
@@ -29636,98 +29636,26 @@ namespace ts {
2963629636 return typeAsAwaitable.awaitedTypeOfType = type;
2963729637 }
2963829638
29639- if (type.flags & TypeFlags.Union) {
29640- let types: Type[] | undefined;
29641- for (const constituentType of (<UnionType>type).types) {
29642- types = append<Type>(types, getAwaitedType(constituentType, errorNode, diagnosticMessage, arg0));
29643- }
29644-
29645- if (!types) {
29646- return undefined;
29647- }
29648-
29649- return typeAsAwaitable.awaitedTypeOfType = getUnionType(types);
29639+ const symbol = getGlobalAwaitedSymbol(/*reportErrors*/ false);
29640+ if (!symbol) {
29641+ return typeAsAwaitable.awaitedTypeOfType = type;
2965029642 }
2965129643
29652- const promisedType = getPromisedTypeOfPromise(type);
29653- if (promisedType) {
29654- if (type.id === promisedType.id || awaitedTypeStack.indexOf(promisedType.id) >= 0) {
29655- // Verify that we don't have a bad actor in the form of a promise whose
29656- // promised type is the same as the promise type, or a mutually recursive
29657- // promise. If so, we return undefined as we cannot guess the shape. If this
29658- // were the actual case in the JavaScript, this Promise would never resolve.
29659- //
29660- // An example of a bad actor with a singly-recursive promise type might
29661- // be:
29662- //
29663- // interface BadPromise {
29664- // then(
29665- // onfulfilled: (value: BadPromise) => any,
29666- // onrejected: (error: any) => any): BadPromise;
29667- // }
29668- // The above interface will pass the PromiseLike check, and return a
29669- // promised type of `BadPromise`. Since this is a self reference, we
29670- // don't want to keep recursing ad infinitum.
29671- //
29672- // An example of a bad actor in the form of a mutually-recursive
29673- // promise type might be:
29674- //
29675- // interface BadPromiseA {
29676- // then(
29677- // onfulfilled: (value: BadPromiseB) => any,
29678- // onrejected: (error: any) => any): BadPromiseB;
29679- // }
29680- //
29681- // interface BadPromiseB {
29682- // then(
29683- // onfulfilled: (value: BadPromiseA) => any,
29684- // onrejected: (error: any) => any): BadPromiseA;
29685- // }
29686- //
29687- if (errorNode) {
29688- error(errorNode, Diagnostics.Type_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method);
29689- }
29690- return undefined;
29691- }
29692-
29693- // Keep track of the type we're about to unwrap to avoid bad recursive promise types.
29694- // See the comments above for more information.
29695- awaitedTypeStack.push(type.id);
29696- const awaitedType = getAwaitedType(promisedType, errorNode, diagnosticMessage, arg0);
29697- awaitedTypeStack.pop();
29698-
29699- if (!awaitedType) {
29700- return undefined;
29701- }
29644+ if (type.aliasSymbol === symbol) {
29645+ return typeAsAwaitable.awaitedTypeOfType = type;
29646+ }
2970229647
29703- return typeAsAwaitable.awaitedTypeOfType = awaitedType;
29648+ const result = getTypeAliasInstantiation(symbol, [type]);
29649+ if (result !== unknownType || type === unknownType || getPromisedTypeOfPromise(type) === unknownType) {
29650+ return typeAsAwaitable.awaitedTypeOfType = result;
2970429651 }
2970529652
29706- // The type was not a promise, so it could not be unwrapped any further.
29707- // As long as the type does not have a callable "then" property, it is
29708- // safe to return the type; otherwise, an error will be reported in
29709- // the call to getNonThenableType and we will return undefined.
29710- //
29711- // An example of a non-promise "thenable" might be:
29712- //
29713- // await { then(): void {} }
29714- //
29715- // The "thenable" does not match the minimal definition for a promise. When
29716- // a Promise/A+-compatible or ES6 promise tries to adopt this value, the promise
29717- // will never settle. We treat this as an error to help flag an early indicator
29718- // of a runtime problem. If the user wants to return this value from an async
29719- // function, they would need to wrap it in some other value. If they want it to
29720- // be treated as a promise, they can cast to <any>.
29721- const thenFunction = getTypeOfPropertyOfType(type, "then" as __String);
29722- if (thenFunction && getSignaturesOfType(thenFunction, SignatureKind.Call).length > 0) {
29723- if (errorNode) {
29724- if (!diagnosticMessage) return Debug.fail();
29725- error(errorNode, diagnosticMessage, arg0);
29726- }
29727- return undefined;
29653+ if (errorNode) {
29654+ if (!diagnosticMessage) return Debug.fail();
29655+ error(errorNode, diagnosticMessage, arg0);
2972829656 }
2972929657
29730- return typeAsAwaitable.awaitedTypeOfType = type ;
29658+ return undefined ;
2973129659 }
2973229660
2973329661 /**
0 commit comments