Skip to content

Commit 203dab4

Browse files
committed
Added additional es5 conformance tests, better emit for functions returning global promise, pass this to __generator
1 parent 0c647c3 commit 203dab4

File tree

112 files changed

+2341
-322
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+2341
-322
lines changed

src/compiler/checker.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ namespace ts {
148148
let getGlobalESSymbolConstructorSymbol: () => Symbol;
149149

150150
let getGlobalPromiseConstructorSymbol: () => Symbol;
151+
let tryGetGlobalPromiseConstructorSymbol: () => Symbol;
151152

152153
let globalObjectType: ObjectType;
153154
let globalFunctionType: ObjectType;
@@ -13922,7 +13923,7 @@ namespace ts {
1392213923
* @param returnType The return type of a FunctionLikeDeclaration
1392313924
* @param location The node on which to report the error.
1392413925
*/
13925-
function checkCorrectPromiseType(returnType: Type, location: Node) {
13926+
function checkCorrectPromiseType(returnType: Type, location: Node, diagnostic: DiagnosticMessage, typeName?: string) {
1392613927
if (returnType === unknownType) {
1392713928
// The return type already had some other error, so we ignore and return
1392813929
// the unknown type.
@@ -13941,7 +13942,7 @@ namespace ts {
1394113942

1394213943
// The promise type was not a valid type reference to the global promise type, so we
1394313944
// report an error and return the unknown type.
13944-
error(location, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type);
13945+
error(location, diagnostic, typeName);
1394513946
return unknownType;
1394613947
}
1394713948

@@ -13961,7 +13962,7 @@ namespace ts {
1396113962
function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration): Type {
1396213963
if (languageVersion >= ScriptTarget.ES6) {
1396313964
const returnType = getTypeFromTypeNode(node.type);
13964-
return checkCorrectPromiseType(returnType, node.type);
13965+
return checkCorrectPromiseType(returnType, node.type, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type);
1396513966
}
1396613967

1396713968
const globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType();
@@ -14007,19 +14008,19 @@ namespace ts {
1400714008

1400814009
const promiseConstructor = getNodeLinks(node.type).resolvedSymbol;
1400914010
if (!promiseConstructor || !symbolIsValue(promiseConstructor)) {
14011+
// try to fall back to global promise type.
1401014012
const typeName = promiseConstructor
1401114013
? symbolToString(promiseConstructor)
1401214014
: typeToString(promiseType);
14013-
error(node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeName);
14014-
return unknownType;
14015+
return checkCorrectPromiseType(promiseType, node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeName);
1401514016
}
1401614017

1401714018
// If the Promise constructor, resolved locally, is an alias symbol we should mark it as referenced.
1401814019
checkReturnTypeAnnotationAsExpression(node);
1401914020

1402014021
// Validate the promise constructor type.
1402114022
const promiseConstructorType = getTypeOfSymbol(promiseConstructor);
14022-
if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) {
14023+
if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) {
1402314024
return unknownType;
1402414025
}
1402514026

@@ -17520,6 +17521,11 @@ namespace ts {
1752017521
function getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind {
1752117522
// Resolve the symbol as a value to ensure the type can be reached at runtime during emit.
1752217523
const valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location);
17524+
const globalPromiseSymbol = tryGetGlobalPromiseConstructorSymbol();
17525+
if (globalPromiseSymbol && valueSymbol === globalPromiseSymbol) {
17526+
return TypeReferenceSerializationKind.Promise;
17527+
}
17528+
1752317529
const constructorType = valueSymbol ? getTypeOfSymbol(valueSymbol) : undefined;
1752417530
if (constructorType && isConstructorType(constructorType)) {
1752517531
return TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue;
@@ -17538,8 +17544,8 @@ namespace ts {
1753817544
else if (type.flags & TypeFlags.Any) {
1753917545
return TypeReferenceSerializationKind.ObjectType;
1754017546
}
17541-
else if (isTypeOfKind(type, TypeFlags.Void)) {
17542-
return TypeReferenceSerializationKind.VoidType;
17547+
else if (isTypeOfKind(type, TypeFlags.Void | TypeFlags.Nullable | TypeFlags.Never)) {
17548+
return TypeReferenceSerializationKind.VoidNullableOrNeverType;
1754317549
}
1754417550
else if (isTypeOfKind(type, TypeFlags.Boolean)) {
1754517551
return TypeReferenceSerializationKind.BooleanType;
@@ -17837,6 +17843,7 @@ namespace ts {
1783717843
getGlobalPromiseLikeType = memoize(() => getGlobalType("PromiseLike", /*arity*/ 1));
1783817844
getInstantiatedGlobalPromiseLikeType = memoize(createInstantiatedPromiseLikeType);
1783917845
getGlobalPromiseConstructorSymbol = memoize(() => getGlobalValueSymbol("Promise"));
17846+
tryGetGlobalPromiseConstructorSymbol = memoize(() => getGlobalSymbol("Promise", SymbolFlags.Value, /*diagnostic*/ undefined) && getGlobalPromiseConstructorSymbol());
1784017847
getGlobalPromiseConstructorLikeType = memoize(() => getGlobalType("PromiseConstructorLike"));
1784117848
getGlobalThenableType = memoize(createThenableType);
1784217849

src/compiler/emitter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7272
};`;
7373

7474
const generatorHelper = `
75-
var __generator = (this && this.__generator) || function (body) {
75+
var __generator = (this && this.__generator) || function (thisArg, body) {
7676
var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f;
7777
function step(op) {
7878
if (f) throw new TypeError("Generator is already executing.");
@@ -97,7 +97,7 @@ var __generator = (this && this.__generator) || function (body) {
9797
_.trys.pop();
9898
continue;
9999
}
100-
op = body(_);
100+
op = body.call(thisArg, _);
101101
}
102102
catch (e) { op = [6, e]; }
103103
finally { f = 0, sent = void 0; }

src/compiler/transformers/generators.ts

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2554,21 +2554,24 @@ namespace ts {
25542554
return createCall(
25552555
createHelperName(currentSourceFile.externalHelpersModuleName, "__generator"),
25562556
/*typeArguments*/ undefined,
2557-
[setNodeEmitFlags(
2558-
createFunctionExpression(
2559-
/*asteriskToken*/ undefined,
2560-
/*name*/ undefined,
2561-
/*typeParameters*/ undefined,
2562-
[createParameter(state)],
2563-
/*type*/ undefined,
2564-
createBlock(
2565-
buildResult,
2566-
/*location*/ undefined,
2567-
/*multiLine*/ buildResult.length > 0
2568-
)
2569-
),
2570-
NodeEmitFlags.ReuseTempVariableScope
2571-
)]
2557+
[
2558+
createThis(),
2559+
setNodeEmitFlags(
2560+
createFunctionExpression(
2561+
/*asteriskToken*/ undefined,
2562+
/*name*/ undefined,
2563+
/*typeParameters*/ undefined,
2564+
[createParameter(state)],
2565+
/*type*/ undefined,
2566+
createBlock(
2567+
buildResult,
2568+
/*location*/ undefined,
2569+
/*multiLine*/ buildResult.length > 0
2570+
)
2571+
),
2572+
NodeEmitFlags.ReuseTempVariableScope
2573+
)
2574+
]
25722575
);
25732576
}
25742577

src/compiler/transformers/ts.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1774,7 +1774,7 @@ namespace ts {
17741774
case TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue:
17751775
return serializeEntityNameAsExpression(node.typeName, /*useFallback*/ false);
17761776

1777-
case TypeReferenceSerializationKind.VoidType:
1777+
case TypeReferenceSerializationKind.VoidNullableOrNeverType:
17781778
return createVoidZero();
17791779

17801780
case TypeReferenceSerializationKind.BooleanType:
@@ -1797,6 +1797,9 @@ namespace ts {
17971797
case TypeReferenceSerializationKind.TypeWithCallSignature:
17981798
return createIdentifier("Function");
17991799

1800+
case TypeReferenceSerializationKind.Promise:
1801+
return createIdentifier("Promise");
1802+
18001803
case TypeReferenceSerializationKind.ObjectType:
18011804
default:
18021805
return createIdentifier("Object");
@@ -2221,8 +2224,21 @@ namespace ts {
22212224
}
22222225
}
22232226

2227+
function getPromiseConstructor(type: TypeNode) {
2228+
const typeName = getEntityNameFromTypeNode(type);
2229+
if (typeName && isEntityName(typeName)) {
2230+
const serializationKind = resolver.getTypeReferenceSerializationKind(typeName);
2231+
if (serializationKind === TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue
2232+
|| serializationKind === TypeReferenceSerializationKind.Unknown) {
2233+
return typeName;
2234+
}
2235+
}
2236+
2237+
return undefined;
2238+
}
2239+
22242240
function transformAsyncFunctionBody(node: FunctionLikeDeclaration): ConciseBody | FunctionBody {
2225-
const promiseConstructor = languageVersion < ScriptTarget.ES6 ? getEntityNameFromTypeNode(node.type) : undefined;
2241+
const promiseConstructor = languageVersion < ScriptTarget.ES6 ? getPromiseConstructor(node.type) : undefined;
22262242
const isArrowFunction = node.kind === SyntaxKind.ArrowFunction;
22272243
const hasLexicalArguments = (resolver.getNodeCheckFlags(node) & NodeCheckFlags.CaptureArguments) !== 0;
22282244

src/compiler/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2043,12 +2043,13 @@ namespace ts {
20432043
// function that can be reached at runtime (e.g. a `class`
20442044
// declaration or a `var` declaration for the static side
20452045
// of a type, such as the global `Promise` type in lib.d.ts).
2046-
VoidType, // The TypeReferenceNode resolves to a Void-like type.
2046+
VoidNullableOrNeverType, // The TypeReferenceNode resolves to a Void-like, Nullable, or Never type.
20472047
NumberLikeType, // The TypeReferenceNode resolves to a Number-like type.
20482048
StringLikeType, // The TypeReferenceNode resolves to a String-like type.
20492049
BooleanType, // The TypeReferenceNode resolves to a Boolean-like type.
20502050
ArrayLikeType, // The TypeReferenceNode resolves to an Array-like type.
20512051
ESSymbolType, // The TypeReferenceNode resolves to the ESSymbol type.
2052+
Promise, // The TypeReferenceNode resolved to the global Promise constructor symbol.
20522053
TypeWithCallSignature, // The TypeReferenceNode resolves to a Function type or a type
20532054
// with call signatures.
20542055
ObjectType, // The TypeReferenceNode resolves to any other type.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//// [asyncAliasReturnType_es5.ts]
2+
type PromiseAlias<T> = Promise<T>;
3+
4+
async function f(): PromiseAlias<void> {
5+
}
6+
7+
//// [asyncAliasReturnType_es5.js]
8+
function f() {
9+
return __awaiter(this, void 0, void 0, function () {
10+
return __generator(this, function (_a) {
11+
return [2 /*return*/];
12+
});
13+
});
14+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
=== tests/cases/conformance/async/es5/asyncAliasReturnType_es5.ts ===
2+
type PromiseAlias<T> = Promise<T>;
3+
>PromiseAlias : Symbol(PromiseAlias, Decl(asyncAliasReturnType_es5.ts, 0, 0))
4+
>T : Symbol(T, Decl(asyncAliasReturnType_es5.ts, 0, 18))
5+
>Promise : Symbol(Promise, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
6+
>T : Symbol(T, Decl(asyncAliasReturnType_es5.ts, 0, 18))
7+
8+
async function f(): PromiseAlias<void> {
9+
>f : Symbol(f, Decl(asyncAliasReturnType_es5.ts, 0, 34))
10+
>PromiseAlias : Symbol(PromiseAlias, Decl(asyncAliasReturnType_es5.ts, 0, 0))
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
=== tests/cases/conformance/async/es5/asyncAliasReturnType_es5.ts ===
2+
type PromiseAlias<T> = Promise<T>;
3+
>PromiseAlias : Promise<T>
4+
>T : T
5+
>Promise : Promise<T>
6+
>T : T
7+
8+
async function f(): PromiseAlias<void> {
9+
>f : () => Promise<void>
10+
>PromiseAlias : Promise<T>
11+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
tests/cases/conformance/async/es5/asyncAwaitIsolatedModules_es5.ts(1,27): error TS2307: Cannot find module 'missing'.
2+
3+
4+
==== tests/cases/conformance/async/es5/asyncAwaitIsolatedModules_es5.ts (1 errors) ====
5+
import { MyPromise } from "missing";
6+
~~~~~~~~~
7+
!!! error TS2307: Cannot find module 'missing'.
8+
9+
declare var p: Promise<number>;
10+
declare var mp: MyPromise<number>;
11+
12+
async function f0() { }
13+
async function f1(): Promise<void> { }
14+
async function f3(): MyPromise<void> { }
15+
16+
let f4 = async function() { }
17+
let f5 = async function(): Promise<void> { }
18+
let f6 = async function(): MyPromise<void> { }
19+
20+
let f7 = async () => { };
21+
let f8 = async (): Promise<void> => { };
22+
let f9 = async (): MyPromise<void> => { };
23+
let f10 = async () => p;
24+
let f11 = async () => mp;
25+
let f12 = async (): Promise<number> => mp;
26+
let f13 = async (): MyPromise<number> => p;
27+
28+
let o = {
29+
async m1() { },
30+
async m2(): Promise<void> { },
31+
async m3(): MyPromise<void> { }
32+
};
33+
34+
class C {
35+
async m1() { }
36+
async m2(): Promise<void> { }
37+
async m3(): MyPromise<void> { }
38+
static async m4() { }
39+
static async m5(): Promise<void> { }
40+
static async m6(): MyPromise<void> { }
41+
}
42+
43+
module M {
44+
export async function f1() { }
45+
}

0 commit comments

Comments
 (0)