@@ -800,6 +800,7 @@ namespace ts {
800
800
let deferredGlobalESSymbolConstructorSymbol: Symbol | undefined;
801
801
let deferredGlobalESSymbolType: ObjectType;
802
802
let deferredGlobalTypedPropertyDescriptorType: GenericType;
803
+ let deferredGlobalAwaitedSymbol: Symbol | undefined;
803
804
let deferredGlobalPromiseType: GenericType;
804
805
let deferredGlobalPromiseLikeType: GenericType;
805
806
let deferredGlobalPromiseConstructorSymbol: Symbol | undefined;
@@ -853,7 +854,6 @@ namespace ts {
853
854
const flowNodeReachable: (boolean | undefined)[] = [];
854
855
const potentialThisCollisions: Node[] = [];
855
856
const potentialNewTargetCollisions: Node[] = [];
856
- const awaitedTypeStack: number[] = [];
857
857
858
858
const diagnostics = createDiagnosticCollection();
859
859
const suggestionDiagnostics = createDiagnosticCollection();
@@ -11059,6 +11059,10 @@ namespace ts {
11059
11059
return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType;
11060
11060
}
11061
11061
11062
+ function getGlobalAwaitedSymbol(reportErrors: boolean) {
11063
+ return deferredGlobalAwaitedSymbol || (deferredGlobalAwaitedSymbol = getGlobalTypeSymbol("Awaited" as __String, reportErrors));
11064
+ }
11065
+
11062
11066
function getGlobalPromiseType(reportErrors: boolean) {
11063
11067
return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
11064
11068
}
@@ -25719,7 +25723,7 @@ namespace ts {
25719
25723
// Promise/A+ compatible implementation will always assimilate any foreign promise, so the
25720
25724
// return type of the body should be unwrapped to its awaited type, which we will wrap in
25721
25725
// the native Promise<T> type later in this function.
25722
- returnType = checkAwaitedType(returnType, /*errorNode*/ func, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member );
25726
+ returnType = checkAwaitedType(returnType);
25723
25727
}
25724
25728
}
25725
25729
else if (isGenerator) { // Generator or AsyncGenerator function
@@ -25858,9 +25862,7 @@ namespace ts {
25858
25862
const errorNode = node.expression || node;
25859
25863
// A `yield*` expression effectively yields everything that its operand yields
25860
25864
const yieldedType = node.asteriskToken ? checkIteratedTypeOrElementType(isAsync ? IterationUse.AsyncYieldStar : IterationUse.YieldStar, expressionType, sentType, errorNode) : expressionType;
25861
- return !isAsync ? yieldedType : getAwaitedType(yieldedType, errorNode, node.asteriskToken
25862
- ? Diagnostics.Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member
25863
- : Diagnostics.Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
25865
+ return !isAsync ? yieldedType : getAwaitedType(yieldedType);
25864
25866
}
25865
25867
25866
25868
/**
@@ -25951,7 +25953,7 @@ namespace ts {
25951
25953
// Promise/A+ compatible implementation will always assimilate any foreign promise, so the
25952
25954
// return type of the body should be unwrapped to its awaited type, which should be wrapped in
25953
25955
// the native Promise<T> type by the caller.
25954
- type = checkAwaitedType(type, func, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member );
25956
+ type = checkAwaitedType(type);
25955
25957
}
25956
25958
if (type.flags & TypeFlags.Never) {
25957
25959
hasReturnOfTypeNever = true;
@@ -26155,7 +26157,7 @@ namespace ts {
26155
26157
const returnOrPromisedType = getReturnOrPromisedType(returnType, functionFlags);
26156
26158
if (returnOrPromisedType) {
26157
26159
if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async) { // Async function
26158
- const awaitedType = checkAwaitedType(exprType, node.body, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member );
26160
+ const awaitedType = checkAwaitedType(exprType);
26159
26161
checkTypeAssignableToAndOptionallyElaborate(awaitedType, returnOrPromisedType, node.body, node.body);
26160
26162
}
26161
26163
else { // Normal function
@@ -26324,7 +26326,7 @@ namespace ts {
26324
26326
}
26325
26327
26326
26328
const operandType = checkExpression(node.expression);
26327
- const awaitedType = checkAwaitedType(operandType, node, Diagnostics.Type_of_await_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member );
26329
+ const awaitedType = checkAwaitedType(operandType);
26328
26330
if (awaitedType === operandType && awaitedType !== errorType && !(operandType.flags & TypeFlags.AnyOrUnknown)) {
26329
26331
addErrorOrSuggestion(/*isError*/ false, createDiagnosticForNode(node, Diagnostics.await_has_no_effect_on_the_type_of_this_expression));
26330
26332
}
@@ -28830,9 +28832,9 @@ namespace ts {
28830
28832
}
28831
28833
}
28832
28834
28833
- function getAwaitedTypeOfPromise(type: Type, errorNode?: Node, diagnosticMessage?: DiagnosticMessage, arg0?: string | number ): Type | undefined {
28835
+ function getAwaitedTypeOfPromise(type: Type, errorNode?: Node): Type | undefined {
28834
28836
const promisedType = getPromisedTypeOfPromise(type, errorNode);
28835
- return promisedType && getAwaitedType(promisedType, errorNode, diagnosticMessage, arg0 );
28837
+ return promisedType && getAwaitedType(promisedType);
28836
28838
}
28837
28839
28838
28840
/**
@@ -28900,12 +28902,12 @@ namespace ts {
28900
28902
* Promise-like type; otherwise, it is the type of the expression. This is used to reflect
28901
28903
* The runtime behavior of the `await` keyword.
28902
28904
*/
28903
- function checkAwaitedType(type: Type, errorNode: Node, diagnosticMessage: DiagnosticMessage, arg0?: string | number ): Type {
28904
- const awaitedType = getAwaitedType(type, errorNode, diagnosticMessage, arg0 );
28905
+ function checkAwaitedType(type: Type): Type {
28906
+ const awaitedType = getAwaitedType(type);
28905
28907
return awaitedType || errorType;
28906
28908
}
28907
28909
28908
- function getAwaitedType(type: Type, errorNode?: Node, diagnosticMessage?: DiagnosticMessage, arg0?: string | number ): Type | undefined {
28910
+ function getAwaitedType(type: Type): Type | undefined {
28909
28911
const typeAsAwaitable = <PromiseOrAwaitableType>type;
28910
28912
if (typeAsAwaitable.awaitedTypeOfType) {
28911
28913
return typeAsAwaitable.awaitedTypeOfType;
@@ -28915,95 +28917,10 @@ namespace ts {
28915
28917
return typeAsAwaitable.awaitedTypeOfType = type;
28916
28918
}
28917
28919
28918
- if (type.flags & TypeFlags.Union) {
28919
- let types: Type[] | undefined;
28920
- for (const constituentType of (<UnionType>type).types) {
28921
- types = append<Type>(types, getAwaitedType(constituentType, errorNode, diagnosticMessage, arg0));
28922
- }
28923
-
28924
- if (!types) {
28925
- return undefined;
28926
- }
28927
-
28928
- return typeAsAwaitable.awaitedTypeOfType = getUnionType(types);
28929
- }
28930
-
28931
- const promisedType = getPromisedTypeOfPromise(type);
28932
- if (promisedType) {
28933
- if (type.id === promisedType.id || awaitedTypeStack.indexOf(promisedType.id) >= 0) {
28934
- // Verify that we don't have a bad actor in the form of a promise whose
28935
- // promised type is the same as the promise type, or a mutually recursive
28936
- // promise. If so, we return undefined as we cannot guess the shape. If this
28937
- // were the actual case in the JavaScript, this Promise would never resolve.
28938
- //
28939
- // An example of a bad actor with a singly-recursive promise type might
28940
- // be:
28941
- //
28942
- // interface BadPromise {
28943
- // then(
28944
- // onfulfilled: (value: BadPromise) => any,
28945
- // onrejected: (error: any) => any): BadPromise;
28946
- // }
28947
- // The above interface will pass the PromiseLike check, and return a
28948
- // promised type of `BadPromise`. Since this is a self reference, we
28949
- // don't want to keep recursing ad infinitum.
28950
- //
28951
- // An example of a bad actor in the form of a mutually-recursive
28952
- // promise type might be:
28953
- //
28954
- // interface BadPromiseA {
28955
- // then(
28956
- // onfulfilled: (value: BadPromiseB) => any,
28957
- // onrejected: (error: any) => any): BadPromiseB;
28958
- // }
28959
- //
28960
- // interface BadPromiseB {
28961
- // then(
28962
- // onfulfilled: (value: BadPromiseA) => any,
28963
- // onrejected: (error: any) => any): BadPromiseA;
28964
- // }
28965
- //
28966
- if (errorNode) {
28967
- error(errorNode, Diagnostics.Type_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method);
28968
- }
28969
- return undefined;
28970
- }
28971
-
28972
- // Keep track of the type we're about to unwrap to avoid bad recursive promise types.
28973
- // See the comments above for more information.
28974
- awaitedTypeStack.push(type.id);
28975
- const awaitedType = getAwaitedType(promisedType, errorNode, diagnosticMessage, arg0);
28976
- awaitedTypeStack.pop();
28977
-
28978
- if (!awaitedType) {
28979
- return undefined;
28980
- }
28981
-
28982
- return typeAsAwaitable.awaitedTypeOfType = awaitedType;
28983
- }
28984
-
28985
- // The type was not a promise, so it could not be unwrapped any further.
28986
- // As long as the type does not have a callable "then" property, it is
28987
- // safe to return the type; otherwise, an error will be reported in
28988
- // the call to getNonThenableType and we will return undefined.
28989
- //
28990
- // An example of a non-promise "thenable" might be:
28991
- //
28992
- // await { then(): void {} }
28993
- //
28994
- // The "thenable" does not match the minimal definition for a promise. When
28995
- // a Promise/A+-compatible or ES6 promise tries to adopt this value, the promise
28996
- // will never settle. We treat this as an error to help flag an early indicator
28997
- // of a runtime problem. If the user wants to return this value from an async
28998
- // function, they would need to wrap it in some other value. If they want it to
28999
- // be treated as a promise, they can cast to <any>.
29000
- const thenFunction = getTypeOfPropertyOfType(type, "then" as __String);
29001
- if (thenFunction && getSignaturesOfType(thenFunction, SignatureKind.Call).length > 0) {
29002
- if (errorNode) {
29003
- if (!diagnosticMessage) return Debug.fail();
29004
- error(errorNode, diagnosticMessage, arg0);
29005
- }
29006
- return undefined;
28920
+ const symbol = getGlobalAwaitedSymbol(/*reportErrors*/ false);
28921
+ if (symbol) {
28922
+ const result = getTypeAliasInstantiation(symbol, [type]) as PromiseOrAwaitableType;
28923
+ return typeAsAwaitable.awaitedTypeOfType = result.awaitedTypeOfType = result;
29007
28924
}
29008
28925
29009
28926
return typeAsAwaitable.awaitedTypeOfType = type;
@@ -29109,7 +29026,7 @@ namespace ts {
29109
29026
return;
29110
29027
}
29111
29028
}
29112
- checkAwaitedType(returnType, node, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member );
29029
+ checkAwaitedType(returnType);
29113
29030
}
29114
29031
29115
29032
/** Check a decorator */
@@ -30699,13 +30616,13 @@ namespace ts {
30699
30616
return iterationTypes === noIterationTypes ? undefined : iterationTypes;
30700
30617
}
30701
30618
30702
- function getAsyncFromSyncIterationTypes(iterationTypes: IterationTypes, errorNode: Node | undefined ) {
30619
+ function getAsyncFromSyncIterationTypes(iterationTypes: IterationTypes) {
30703
30620
if (iterationTypes === noIterationTypes) return noIterationTypes;
30704
30621
if (iterationTypes === anyIterationTypes) return anyIterationTypes;
30705
30622
const { yieldType, returnType, nextType } = iterationTypes;
30706
30623
return createIterationTypes(
30707
- getAwaitedType(yieldType, errorNode ) || anyType,
30708
- getAwaitedType(returnType, errorNode ) || anyType,
30624
+ getAwaitedType(yieldType) || anyType,
30625
+ getAwaitedType(returnType) || anyType,
30709
30626
nextType);
30710
30627
}
30711
30628
@@ -30741,7 +30658,7 @@ namespace ts {
30741
30658
if (use & IterationUse.AllowsAsyncIterablesFlag) {
30742
30659
// for a sync iterable in an async context, only use the cached types if they are valid.
30743
30660
if (iterationTypes !== noIterationTypes) {
30744
- return (type as IterableOrIteratorType).iterationTypesOfAsyncIterable = getAsyncFromSyncIterationTypes(iterationTypes, errorNode );
30661
+ return (type as IterableOrIteratorType).iterationTypesOfAsyncIterable = getAsyncFromSyncIterationTypes(iterationTypes);
30745
30662
}
30746
30663
}
30747
30664
else {
@@ -30762,7 +30679,7 @@ namespace ts {
30762
30679
if (iterationTypes !== noIterationTypes) {
30763
30680
if (use & IterationUse.AllowsAsyncIterablesFlag) {
30764
30681
return (type as IterableOrIteratorType).iterationTypesOfAsyncIterable = iterationTypes
30765
- ? getAsyncFromSyncIterationTypes(iterationTypes, errorNode )
30682
+ ? getAsyncFromSyncIterationTypes(iterationTypes)
30766
30683
: noIterationTypes;
30767
30684
}
30768
30685
else {
@@ -31170,7 +31087,7 @@ namespace ts {
31170
31087
else if (getReturnTypeFromAnnotation(func)) {
31171
31088
const unwrappedReturnType = unwrapReturnType(returnType, functionFlags);
31172
31089
const unwrappedExprType = functionFlags & FunctionFlags.Async
31173
- ? checkAwaitedType(exprType, node, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member )
31090
+ ? checkAwaitedType(exprType)
31174
31091
: exprType;
31175
31092
if (unwrappedReturnType) {
31176
31093
// If the function has a return type, but promisedType is
0 commit comments