Transform async functions and await expressions#101
Conversation
|
And here's an example of the transform in action (borrowed from here): async function chainAnimationsAsync(elem, animations) {
var ret = null;
try {
for (var anim in animations) {
ret = await anim(elem);
}
} catch(e) { /* ignore and keep going */ }
return ret;
}becomes function chainAnimationsAsync(elem, animations) {
var ret, anim;
return wrapGenerator.async(function chainAnimationsAsync$($ctx0) {
while (1) switch ($ctx0.prev = $ctx0.next) {
case 0:
ret = null;
$ctx0.prev = 1;
$ctx0.t0 = $ctx0.keys(animations);
case 3:
if (($ctx0.t1 = $ctx0.t0()).done) {
$ctx0.next = 10;
break;
}
anim = $ctx0.t1.value;
$ctx0.next = 7;
return anim(elem);
case 7:
ret = $ctx0.sent;
$ctx0.next = 3;
break;
case 10:
$ctx0.next = 14;
break;
case 12:
$ctx0.prev = 12;
$ctx0.t2 = $ctx0.catch(1);
case 14:
return $ctx0.abrupt("return", ret);
case 15:
case "end":
return $ctx0.stop();
}
}, this, [[1, 12]]);
} |
|
Regenerator doesn't support arrow generator functions yet, because there's no agreed-upon syntax for them, but I definitely intend to add support for |
runtime/dev.js
Outdated
There was a problem hiding this comment.
nit: calling this looks awkward, why not just bind to the first arg instead?
There was a problem hiding this comment.
Just trying to shave bytes, that's all.
|
nice! I thought it's going to take a lot more code to implement. |
There was a problem hiding this comment.
"async" is more likely to occur in JS codebases, e.g. the popular library. Maybe 'await' is better to check for?
There was a problem hiding this comment.
You can have an async function that has no awaits in it -- but you probably could get away with being more specific a la /\bfunction\s*\*|\basync\s+function\b/
|
Very nice |
|
This looks so awesome. |
|
This is awesome. I tried a more complex example, and ran into a problem with the handling of this: var headers;
async function foo() {
}This compiles to the following: var headers;
(function foo() {
return wrapGenerator.async(function foo$($ctx0) {
while (1) switch ($ctx0.prev = $ctx0.next) {
case 0:
case "end":
return $ctx0.stop();
}
}, this);
})Note the extra parentheses added around the function declaration, turning it into a function expression and not binding a global variable to the name This only happens when a statement like I expect this is an issue in the esprima additions for |
|
A larger sample working with this is here: https://github.com/lukehoban/ecmascript-asyncawait/blob/regenerator/server.asyncawait.js as part of a branch of the async/await proposal to try to switch to using this regenerator branch for the sample instead of sweet.js macros. |
|
Yep, I can confirm that this is related to my Esprima changes, and Recast is just trying to respect the wrong Will investigate. |
|
@lukehoban Fixed this bug by adding benjamn/esprima@b714306 to my https://github.com/ariya/esprima/pull/234 pull request. In short, I was misusing I also switched |
|
@lukehoban where did TC39 come down on |
|
Hey everybody, great work @benjamn . I see no movement since April, how's the progress on this? |
88194f9 to
bcaf484
Compare
8f31787 to
5da67bc
Compare
5da67bc to
ef11dd2
Compare
Transform async functions and await expressions.
|
Nice! |
|
👍 |

This functionality depends on my
async-awaitbranch of the Esprima parser (pull request: https://github.com/ariya/esprima/pull/234).The
wrapGenerator.asyncfunction is heavily inspired by @lukehoban'sspawnfunction: https://github.com/lukehoban/ecmascript-asyncawait#spawningNote that
Promiseis left as a free variable, so you have to bring your ownPromisepolyfill.Adding a bunch of tests for this functionality is my next order of business.
cc @amasad @thomasboyt @subtleGradient @bklimt @lukehoban @arv