Skip to content

Commit 500dd16

Browse files
authored
Merge pull request microsoft#15590 from Microsoft/fix15471
Add check for tslib __await helper
2 parents d2bdfbb + 6f357e5 commit 500dd16

11 files changed

+210
-127
lines changed

src/compiler/checker.ts

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15999,7 +15999,7 @@ namespace ts {
1599915999
// From within an async function you can return either a non-promise value or a promise. Any
1600016000
// Promise/A+ compatible implementation will always assimilate any foreign promise, so the
1600116001
// return type of the body is awaited type of the body, wrapped in a native Promise<T> type.
16002-
return (functionFlags & FunctionFlags.AsyncOrAsyncGenerator) === FunctionFlags.Async
16002+
return (functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async
1600316003
? createPromiseReturnType(func, widenedType) // Async function
1600416004
: widenedType; // Generator function, AsyncGenerator function, or normal function
1600516005
}
@@ -16215,7 +16215,7 @@ namespace ts {
1621516215

1621616216
const functionFlags = getFunctionFlags(node);
1621716217
const returnOrPromisedType = node.type &&
16218-
((functionFlags & FunctionFlags.AsyncOrAsyncGenerator) === FunctionFlags.Async ?
16218+
((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async ?
1621916219
checkAsyncFunctionReturnType(node) : // Async function
1622016220
getTypeFromTypeNode(node.type)); // AsyncGenerator function, Generator function, or normal function
1622116221

@@ -16245,7 +16245,7 @@ namespace ts {
1624516245
// its return type annotation.
1624616246
const exprType = checkExpression(<Expression>node.body);
1624716247
if (returnOrPromisedType) {
16248-
if ((functionFlags & FunctionFlags.AsyncOrAsyncGenerator) === FunctionFlags.Async) { // Async function
16248+
if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async) { // Async function
1624916249
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);
1625016250
checkTypeAssignableTo(awaitedType, returnOrPromisedType, node.body);
1625116251
}
@@ -16985,12 +16985,16 @@ namespace ts {
1698516985
// we are in a yield context.
1698616986
const functionFlags = func && getFunctionFlags(func);
1698716987
if (node.asteriskToken) {
16988-
if (functionFlags & FunctionFlags.Async) {
16989-
if (languageVersion < ScriptTarget.ES2017) {
16990-
checkExternalEmitHelpers(node, ExternalEmitHelpers.AsyncDelegator);
16991-
}
16988+
// Async generator functions prior to ESNext require the __await, __asyncDelegator,
16989+
// and __asyncValues helpers
16990+
if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.AsyncGenerator &&
16991+
languageVersion < ScriptTarget.ESNext) {
16992+
checkExternalEmitHelpers(node, ExternalEmitHelpers.AsyncDelegatorIncludes);
1699216993
}
16993-
else if (languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) {
16994+
16995+
// Generator functions prior to ES2015 require the __values helper
16996+
if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Generator &&
16997+
languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) {
1699416998
checkExternalEmitHelpers(node, ExternalEmitHelpers.Values);
1699516999
}
1699617000
}
@@ -17509,18 +17513,20 @@ namespace ts {
1750917513
}
1751017514

1751117515
const functionFlags = getFunctionFlags(<FunctionLikeDeclaration>node);
17512-
if ((functionFlags & FunctionFlags.InvalidAsyncOrAsyncGenerator) === FunctionFlags.Async && languageVersion < ScriptTarget.ES2017) {
17513-
checkExternalEmitHelpers(node, ExternalEmitHelpers.Awaiter);
17514-
if (languageVersion < ScriptTarget.ES2015) {
17515-
checkExternalEmitHelpers(node, ExternalEmitHelpers.Generator);
17516+
if (!(functionFlags & FunctionFlags.Invalid)) {
17517+
// Async generators prior to ESNext require the __await and __asyncGenerator helpers
17518+
if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.AsyncGenerator && languageVersion < ScriptTarget.ESNext) {
17519+
checkExternalEmitHelpers(node, ExternalEmitHelpers.AsyncGeneratorIncludes);
1751617520
}
17517-
}
1751817521

17519-
if ((functionFlags & FunctionFlags.InvalidGenerator) === FunctionFlags.Generator) {
17520-
if (functionFlags & FunctionFlags.Async && languageVersion < ScriptTarget.ES2017) {
17521-
checkExternalEmitHelpers(node, ExternalEmitHelpers.AsyncGenerator);
17522+
// Async functions prior to ES2017 require the __awaiter helper
17523+
if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async && languageVersion < ScriptTarget.ES2017) {
17524+
checkExternalEmitHelpers(node, ExternalEmitHelpers.Awaiter);
1752217525
}
17523-
else if (languageVersion < ScriptTarget.ES2015) {
17526+
17527+
// Generator functions, Async functions, and Async Generator functions prior to
17528+
// ES2015 require the __generator helper
17529+
if ((functionFlags & FunctionFlags.AsyncGenerator) !== FunctionFlags.Normal && languageVersion < ScriptTarget.ES2015) {
1752417530
checkExternalEmitHelpers(node, ExternalEmitHelpers.Generator);
1752517531
}
1752617532
}
@@ -17548,7 +17554,7 @@ namespace ts {
1754817554

1754917555
if (node.type) {
1755017556
const functionFlags = getFunctionFlags(<FunctionDeclaration>node);
17551-
if ((functionFlags & FunctionFlags.InvalidGenerator) === FunctionFlags.Generator) {
17557+
if ((functionFlags & (FunctionFlags.Invalid | FunctionFlags.Generator)) === FunctionFlags.Generator) {
1755217558
const returnType = getTypeFromTypeNode(node.type);
1755317559
if (returnType === voidType) {
1755417560
error(node.type, Diagnostics.A_generator_cannot_have_a_void_type_annotation);
@@ -17568,7 +17574,7 @@ namespace ts {
1756817574
checkTypeAssignableTo(iterableIteratorInstantiation, returnType, node.type);
1756917575
}
1757017576
}
17571-
else if ((functionFlags & FunctionFlags.AsyncOrAsyncGenerator) === FunctionFlags.Async) {
17577+
else if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async) {
1757217578
checkAsyncFunctionReturnType(<FunctionLikeDeclaration>node);
1757317579
}
1757417580
}
@@ -19535,11 +19541,14 @@ namespace ts {
1953519541

1953619542
if (node.kind === SyntaxKind.ForOfStatement) {
1953719543
if ((<ForOfStatement>node).awaitModifier) {
19538-
if (languageVersion < ScriptTarget.ES2017) {
19544+
const functionFlags = getFunctionFlags(getContainingFunction(node));
19545+
if ((functionFlags & (FunctionFlags.Invalid | FunctionFlags.Async)) === FunctionFlags.Async && languageVersion < ScriptTarget.ESNext) {
19546+
// for..await..of in an async function or async generator function prior to ESNext requires the __asyncValues helper
1953919547
checkExternalEmitHelpers(node, ExternalEmitHelpers.ForAwaitOfIncludes);
1954019548
}
1954119549
}
19542-
else if (languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) {
19550+
else if (compilerOptions.downlevelIteration && languageVersion < ScriptTarget.ES2015) {
19551+
// for..of prior to ES2015 requires the __values helper when downlevelIteration is enabled
1954319552
checkExternalEmitHelpers(node, ExternalEmitHelpers.ForOfIncludes);
1954419553
}
1954519554
}
@@ -19969,7 +19978,7 @@ namespace ts {
1996919978
}
1997019979

1997119980
function isUnwrappedReturnTypeVoidOrAny(func: FunctionLikeDeclaration, returnType: Type): boolean {
19972-
const unwrappedReturnType = (getFunctionFlags(func) & FunctionFlags.AsyncOrAsyncGenerator) === FunctionFlags.Async
19981+
const unwrappedReturnType = (getFunctionFlags(func) & FunctionFlags.AsyncGenerator) === FunctionFlags.Async
1997319982
? getPromisedTypeOfPromise(returnType) // Async function
1997419983
: returnType; // AsyncGenerator function, Generator function, or normal function
1997519984
return unwrappedReturnType && maybeTypeOfKind(unwrappedReturnType, TypeFlags.Void | TypeFlags.Any);
@@ -22979,6 +22988,7 @@ namespace ts {
2297922988
case ExternalEmitHelpers.Values: return "__values";
2298022989
case ExternalEmitHelpers.Read: return "__read";
2298122990
case ExternalEmitHelpers.Spread: return "__spread";
22991+
case ExternalEmitHelpers.Await: return "__await";
2298222992
case ExternalEmitHelpers.AsyncGenerator: return "__asyncGenerator";
2298322993
case ExternalEmitHelpers.AsyncDelegator: return "__asyncDelegator";
2298422994
case ExternalEmitHelpers.AsyncValues: return "__asyncValues";

src/compiler/transformers/esnext.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,7 @@ namespace ts {
884884

885885
function createAwaitHelper(context: TransformationContext, expression: Expression) {
886886
context.requestEmitHelper(awaitHelper);
887-
return createCall(createIdentifier("__await"), /*typeArguments*/ undefined, [expression]);
887+
return createCall(getHelperName("__await"), /*typeArguments*/ undefined, [expression]);
888888
}
889889

890890
const asyncGeneratorHelper: EmitHelper = {

src/compiler/types.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3980,18 +3980,25 @@ namespace ts {
39803980
Awaiter = 1 << 6, // __awaiter (used by ES2017 async functions transformation)
39813981
Generator = 1 << 7, // __generator (used by ES2015 generator transformation)
39823982
Values = 1 << 8, // __values (used by ES2015 for..of and yield* transformations)
3983-
Read = 1 << 9, // __read (used by ES2015 iterator destructuring transformation)
3983+
Read = 1 << 9, // __read (used by ES2015 iterator destructuring transformation)
39843984
Spread = 1 << 10, // __spread (used by ES2015 array spread and argument list spread transformations)
3985-
AsyncGenerator = 1 << 11, // __asyncGenerator (used by ES2017 async generator transformation)
3986-
AsyncDelegator = 1 << 12, // __asyncDelegator (used by ES2017 async generator yield* transformation)
3987-
AsyncValues = 1 << 13, // __asyncValues (used by ES2017 for..await..of transformation)
3985+
Await = 1 << 11, // __await (used by ES2017 async generator transformation)
3986+
AsyncGenerator = 1 << 12, // __asyncGenerator (used by ES2017 async generator transformation)
3987+
AsyncDelegator = 1 << 13, // __asyncDelegator (used by ES2017 async generator yield* transformation)
3988+
AsyncValues = 1 << 14, // __asyncValues (used by ES2017 for..await..of transformation)
39883989

39893990
// Helpers included by ES2015 for..of
39903991
ForOfIncludes = Values,
39913992

39923993
// Helpers included by ES2017 for..await..of
39933994
ForAwaitOfIncludes = AsyncValues,
39943995

3996+
// Helpers included by ES2017 async generators
3997+
AsyncGeneratorIncludes = Await | AsyncGenerator,
3998+
3999+
// Helpers included by yield* in ES2017 async generators
4000+
AsyncDelegatorIncludes = Await | AsyncDelegator | AsyncValues,
4001+
39954002
// Helpers included by ES2015 spread
39964003
SpreadIncludes = Read | Spread,
39974004

src/compiler/utilities.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1924,16 +1924,18 @@ namespace ts {
19241924
}
19251925

19261926
export const enum FunctionFlags {
1927-
Normal = 0,
1928-
Generator = 1 << 0,
1929-
Async = 1 << 1,
1930-
AsyncOrAsyncGenerator = Async | Generator,
1931-
Invalid = 1 << 2,
1932-
InvalidAsyncOrAsyncGenerator = AsyncOrAsyncGenerator | Invalid,
1933-
InvalidGenerator = Generator | Invalid,
1927+
Normal = 0, // Function is a normal function
1928+
Generator = 1 << 0, // Function is a generator function or async generator function
1929+
Async = 1 << 1, // Function is an async function or an async generator function
1930+
Invalid = 1 << 2, // Function is a signature or overload and does not have a body.
1931+
AsyncGenerator = Async | Generator, // Function is an async generator function
19341932
}
19351933

1936-
export function getFunctionFlags(node: FunctionLikeDeclaration) {
1934+
export function getFunctionFlags(node: FunctionLikeDeclaration | undefined) {
1935+
if (!node) {
1936+
return FunctionFlags.Invalid;
1937+
}
1938+
19371939
let flags = FunctionFlags.Normal;
19381940
switch (node.kind) {
19391941
case SyntaxKind.FunctionDeclaration:

tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -293,15 +293,13 @@ var C4 = (function () {
293293
}
294294
C4.prototype.f = function () {
295295
return __asyncGenerator(this, arguments, function f_1() {
296-
var x, _a;
297-
return __generator(this, function (_b) {
298-
switch (_b.label) {
299-
case 0:
300-
_a = __await;
301-
return [5 /*yield**/, __values(__asyncDelegator(__asyncValues([1])))];
302-
case 1: return [4 /*yield*/, _a.apply(void 0, [_b.sent()])];
296+
var x;
297+
return __generator(this, function (_a) {
298+
switch (_a.label) {
299+
case 0: return [5 /*yield**/, __values(__asyncDelegator(__asyncValues([1])))];
300+
case 1: return [4 /*yield*/, __await.apply(void 0, [_a.sent()])];
303301
case 2:
304-
x = _b.sent();
302+
x = _a.sent();
305303
return [2 /*return*/];
306304
}
307305
});
@@ -374,22 +372,20 @@ var C5 = (function () {
374372
}
375373
C5.prototype.f = function () {
376374
return __asyncGenerator(this, arguments, function f_1() {
377-
var x, _a;
378-
return __generator(this, function (_b) {
379-
switch (_b.label) {
380-
case 0:
381-
_a = __await;
382-
return [5 /*yield**/, __values(__asyncDelegator(__asyncValues((function () { return __asyncGenerator(this, arguments, function () { return __generator(this, function (_a) {
383-
switch (_a.label) {
384-
case 0: return [4 /*yield*/, 1];
385-
case 1:
386-
_a.sent();
387-
return [2 /*return*/];
388-
}
389-
}); }); })())))];
390-
case 1: return [4 /*yield*/, _a.apply(void 0, [_b.sent()])];
375+
var x;
376+
return __generator(this, function (_a) {
377+
switch (_a.label) {
378+
case 0: return [5 /*yield**/, __values(__asyncDelegator(__asyncValues((function () { return __asyncGenerator(this, arguments, function () { return __generator(this, function (_a) {
379+
switch (_a.label) {
380+
case 0: return [4 /*yield*/, 1];
381+
case 1:
382+
_a.sent();
383+
return [2 /*return*/];
384+
}
385+
}); }); })())))];
386+
case 1: return [4 /*yield*/, __await.apply(void 0, [_a.sent()])];
391387
case 2:
392-
x = _b.sent();
388+
x = _a.sent();
393389
return [2 /*return*/];
394390
}
395391
});

tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -244,15 +244,13 @@ var __values = (this && this.__values) || function (o) {
244244
};
245245
function f4() {
246246
return __asyncGenerator(this, arguments, function f4_1() {
247-
var x, _a;
248-
return __generator(this, function (_b) {
249-
switch (_b.label) {
250-
case 0:
251-
_a = __await;
252-
return [5 /*yield**/, __values(__asyncDelegator(__asyncValues([1])))];
253-
case 1: return [4 /*yield*/, _a.apply(void 0, [_b.sent()])];
247+
var x;
248+
return __generator(this, function (_a) {
249+
switch (_a.label) {
250+
case 0: return [5 /*yield**/, __values(__asyncDelegator(__asyncValues([1])))];
251+
case 1: return [4 /*yield*/, __await.apply(void 0, [_a.sent()])];
254252
case 2:
255-
x = _b.sent();
253+
x = _a.sent();
256254
return [2 /*return*/];
257255
}
258256
});
@@ -320,22 +318,20 @@ var __values = (this && this.__values) || function (o) {
320318
};
321319
function f5() {
322320
return __asyncGenerator(this, arguments, function f5_1() {
323-
var x, _a;
324-
return __generator(this, function (_b) {
325-
switch (_b.label) {
326-
case 0:
327-
_a = __await;
328-
return [5 /*yield**/, __values(__asyncDelegator(__asyncValues((function () { return __asyncGenerator(this, arguments, function () { return __generator(this, function (_a) {
329-
switch (_a.label) {
330-
case 0: return [4 /*yield*/, 1];
331-
case 1:
332-
_a.sent();
333-
return [2 /*return*/];
334-
}
335-
}); }); })())))];
336-
case 1: return [4 /*yield*/, _a.apply(void 0, [_b.sent()])];
321+
var x;
322+
return __generator(this, function (_a) {
323+
switch (_a.label) {
324+
case 0: return [5 /*yield**/, __values(__asyncDelegator(__asyncValues((function () { return __asyncGenerator(this, arguments, function () { return __generator(this, function (_a) {
325+
switch (_a.label) {
326+
case 0: return [4 /*yield*/, 1];
327+
case 1:
328+
_a.sent();
329+
return [2 /*return*/];
330+
}
331+
}); }); })())))];
332+
case 1: return [4 /*yield*/, __await.apply(void 0, [_a.sent()])];
337333
case 2:
338-
x = _b.sent();
334+
x = _a.sent();
339335
return [2 /*return*/];
340336
}
341337
});

0 commit comments

Comments
 (0)