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