@@ -106,15 +106,11 @@ namespace ts {
106
106
}
107
107
}
108
108
109
- function visitAwaitExpression ( node : AwaitExpression ) {
109
+ function visitAwaitExpression ( node : AwaitExpression ) : Expression {
110
110
if ( enclosingFunctionFlags & FunctionFlags . Async && enclosingFunctionFlags & FunctionFlags . Generator ) {
111
- const expression = visitNode ( node . expression , visitor , isExpression ) ;
112
111
return setOriginalNode (
113
112
setTextRange (
114
- createYield (
115
- /*asteriskToken*/ undefined ,
116
- createArrayLiteral ( [ createLiteral ( "await" ) , expression ] )
117
- ) ,
113
+ createYield ( createAwaitHelper ( context , visitNode ( node . expression , visitor , isExpression ) ) ) ,
118
114
/*location*/ node
119
115
) ,
120
116
node
@@ -124,18 +120,26 @@ namespace ts {
124
120
}
125
121
126
122
function visitYieldExpression ( node : YieldExpression ) {
127
- if ( enclosingFunctionFlags & FunctionFlags . Async && enclosingFunctionFlags & FunctionFlags . Generator ) {
123
+ if ( enclosingFunctionFlags & FunctionFlags . Async && enclosingFunctionFlags & FunctionFlags . Generator && node . asteriskToken ) {
128
124
const expression = visitNode ( node . expression , visitor , isExpression ) ;
129
- return updateYield (
130
- node ,
131
- node . asteriskToken ,
132
- node . asteriskToken
133
- ? createAsyncDelegatorHelper ( context , expression , expression )
134
- : createArrayLiteral (
135
- expression
136
- ? [ createLiteral ( "yield" ) , expression ]
137
- : [ createLiteral ( "yield" ) ]
138
- )
125
+ return setOriginalNode (
126
+ setTextRange (
127
+ createYield (
128
+ createAwaitHelper ( context ,
129
+ updateYield (
130
+ node ,
131
+ node . asteriskToken ,
132
+ createAsyncDelegatorHelper (
133
+ context ,
134
+ createAsyncValuesHelper ( context , expression , expression ) ,
135
+ expression
136
+ )
137
+ )
138
+ )
139
+ ) ,
140
+ node
141
+ ) ,
142
+ node
139
143
) ;
140
144
}
141
145
return visitEachChild ( node , visitor , context ) ;
@@ -347,23 +351,22 @@ namespace ts {
347
351
) ;
348
352
}
349
353
354
+ function awaitAsYield ( expression : Expression ) {
355
+ return createYield ( /*asteriskToken*/ undefined , enclosingFunctionFlags & FunctionFlags . Generator ? createAwaitHelper ( context , expression ) : expression ) ;
356
+ }
357
+
350
358
function transformForAwaitOfStatement ( node : ForOfStatement , outermostLabeledStatement : LabeledStatement ) {
351
359
const expression = visitNode ( node . expression , visitor , isExpression ) ;
352
360
const iterator = isIdentifier ( expression ) ? getGeneratedNameForNode ( expression ) : createTempVariable ( /*recordTempVariable*/ undefined ) ;
353
361
const result = isIdentifier ( expression ) ? getGeneratedNameForNode ( iterator ) : createTempVariable ( /*recordTempVariable*/ undefined ) ;
354
362
const errorRecord = createUniqueName ( "e" ) ;
355
363
const catchVariable = getGeneratedNameForNode ( errorRecord ) ;
356
364
const returnMethod = createTempVariable ( /*recordTempVariable*/ undefined ) ;
357
- const values = createAsyncValuesHelper ( context , expression , /*location*/ node . expression ) ;
358
- const next = createYield (
359
- /*asteriskToken*/ undefined ,
360
- enclosingFunctionFlags & FunctionFlags . Generator
361
- ? createArrayLiteral ( [
362
- createLiteral ( "await" ) ,
363
- createCall ( createPropertyAccess ( iterator , "next" ) , /*typeArguments*/ undefined , [ ] )
364
- ] )
365
- : createCall ( createPropertyAccess ( iterator , "next" ) , /*typeArguments*/ undefined , [ ] )
366
- ) ;
365
+ const callValues = createAsyncValuesHelper ( context , expression , /*location*/ node . expression ) ;
366
+ const callNext = createCall ( createPropertyAccess ( iterator , "next" ) , /*typeArguments*/ undefined , [ ] ) ;
367
+ const getDone = createPropertyAccess ( result , "done" ) ;
368
+ const getValue = createPropertyAccess ( result , "value" ) ;
369
+ const callReturn = createFunctionCall ( returnMethod , iterator , [ ] ) ;
367
370
368
371
hoistVariableDeclaration ( errorRecord ) ;
369
372
hoistVariableDeclaration ( returnMethod ) ;
@@ -374,16 +377,19 @@ namespace ts {
374
377
/*initializer*/ setEmitFlags (
375
378
setTextRange (
376
379
createVariableDeclarationList ( [
377
- setTextRange ( createVariableDeclaration ( iterator , /*type*/ undefined , values ) , node . expression ) ,
378
- createVariableDeclaration ( result , /*type*/ undefined , next )
380
+ setTextRange ( createVariableDeclaration ( iterator , /*type*/ undefined , callValues ) , node . expression ) ,
381
+ createVariableDeclaration ( result )
379
382
] ) ,
380
383
node . expression
381
384
) ,
382
385
EmitFlags . NoHoisting
383
386
) ,
384
- /*condition*/ createLogicalNot ( createPropertyAccess ( result , "done" ) ) ,
385
- /*incrementor*/ createAssignment ( result , next ) ,
386
- /*statement*/ convertForOfStatementHead ( node , createPropertyAccess ( result , "value" ) )
387
+ /*condition*/ createComma (
388
+ createAssignment ( result , awaitAsYield ( callNext ) ) ,
389
+ createLogicalNot ( getDone )
390
+ ) ,
391
+ /*incrementor*/ undefined ,
392
+ /*statement*/ convertForOfStatementHead ( node , awaitAsYield ( getValue ) )
387
393
) ,
388
394
/*location*/ node
389
395
) ,
@@ -421,26 +427,14 @@ namespace ts {
421
427
createLogicalAnd (
422
428
createLogicalAnd (
423
429
result ,
424
- createLogicalNot (
425
- createPropertyAccess ( result , "done" )
426
- )
430
+ createLogicalNot ( getDone )
427
431
) ,
428
432
createAssignment (
429
433
returnMethod ,
430
434
createPropertyAccess ( iterator , "return" )
431
435
)
432
436
) ,
433
- createStatement (
434
- createYield (
435
- /*asteriskToken*/ undefined ,
436
- enclosingFunctionFlags & FunctionFlags . Generator
437
- ? createArrayLiteral ( [
438
- createLiteral ( "await" ) ,
439
- createFunctionCall ( returnMethod , iterator , [ ] )
440
- ] )
441
- : createFunctionCall ( returnMethod , iterator , [ ] )
442
- )
443
- )
437
+ createStatement ( awaitAsYield ( callReturn ) )
444
438
) ,
445
439
EmitFlags . SingleLine
446
440
)
@@ -880,27 +874,39 @@ namespace ts {
880
874
) ;
881
875
}
882
876
877
+ const awaitHelper : EmitHelper = {
878
+ name : "typescript:await" ,
879
+ scoped : false ,
880
+ text : `
881
+ var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
882
+ `
883
+ } ;
884
+
885
+ function createAwaitHelper ( context : TransformationContext , expression : Expression ) {
886
+ context . requestEmitHelper ( awaitHelper ) ;
887
+ return createCall ( createIdentifier ( "__await" ) , /*typeArguments*/ undefined , [ expression ] ) ;
888
+ }
889
+
883
890
const asyncGeneratorHelper : EmitHelper = {
884
891
name : "typescript:asyncGenerator" ,
885
892
scoped : false ,
886
893
text : `
887
894
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
888
895
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
889
- var g = generator.apply(thisArg, _arguments || []), q = [], c, i;
890
- return i = { next: verb("next"), "throw": verb("throw"), "return": verb("return") }, i[Symbol.asyncIterator] = function () { return this; }, i;
891
- function verb(n) { return function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]), next(); }); }; }
892
- function next() { if (!c && q.length) resume((c = q.shift())[0], c[1]); }
893
- function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(c[3], e); } }
894
- function step(r) { r.done ? settle(c[2], r) : Promise.resolve(r.value[1]).then(r.value[0] === "yield" ? send : fulfill, reject); }
895
- function send(value) { settle(c[2], { value: value, done: false }); }
896
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
897
+ return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
898
+ function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
899
+ function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
900
+ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
896
901
function fulfill(value) { resume("next", value); }
897
902
function reject(value) { resume("throw", value); }
898
- function settle(f, v) { c = void 0, f(v), next( ); }
903
+ function settle(f, v) { if ( f(v), q.shift(), q.length) resume(q[0][0], q[0][1] ); }
899
904
};
900
905
`
901
906
} ;
902
907
903
908
function createAsyncGeneratorHelper ( context : TransformationContext , generatorFunc : FunctionExpression ) {
909
+ context . requestEmitHelper ( awaitHelper ) ;
904
910
context . requestEmitHelper ( asyncGeneratorHelper ) ;
905
911
906
912
// Mark this node as originally an async function
@@ -922,16 +928,16 @@ namespace ts {
922
928
scoped : false ,
923
929
text : `
924
930
var __asyncDelegator = (this && this.__asyncDelegator) || function (o) {
925
- var i = { next: verb("next"), "throw": verb("throw", function (e) { throw e; }), "return": verb("return", function (v) { return { value: v, done: true }; }) } , p;
926
- return o = __asyncValues(o ), i[Symbol.iterator] = function () { return this; }, i;
927
- function verb(n, f ) { return function (v) { return v = p && n === "throw" ? f (v) : p && v.done ? v : { value: p ? ["yield", v.value] : ["await", (o[n] || f).call(o, v)] , done: false }, p = !p, v; }; }
931
+ var i, p;
932
+ return i = {}, verb("next"), verb("throw"), verb("return" ), i[Symbol.iterator] = function () { return this; }, i;
933
+ function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await (o[n](v)) , done: n === "return" } : v; }; }
928
934
};
929
935
`
930
936
} ;
931
937
932
938
function createAsyncDelegatorHelper ( context : TransformationContext , expression : Expression , location ?: TextRange ) {
939
+ context . requestEmitHelper ( awaitHelper ) ;
933
940
context . requestEmitHelper ( asyncDelegator ) ;
934
- context . requestEmitHelper ( asyncValues ) ;
935
941
return setTextRange (
936
942
createCall (
937
943
getHelperName ( "__asyncDelegator" ) ,
0 commit comments