-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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 |
|
||
function step(arg) { | ||
try { | ||
var info = this(arg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: calling this
looks awkward, why not just bind to the first arg instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just trying to shave bytes, that's all.
nice! I thought it's going to take a lot more code to implement. |
@@ -15,7 +15,7 @@ var transform = require("./lib/visit").transform; | |||
var utils = require("./lib/util"); | |||
var recast = require("recast"); | |||
var types = recast.types; | |||
var genFunExp = /\bfunction\s*\*/; | |||
var genOrAsyncFunExp = /\bfunction\s*\*|\basync\b/; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can have an async function that has no await
s 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-await
branch of the Esprima parser (pull request: https://github.com/ariya/esprima/pull/234).The
wrapGenerator.async
function is heavily inspired by @lukehoban'sspawn
function: https://github.com/lukehoban/ecmascript-asyncawait#spawningNote that
Promise
is left as a free variable, so you have to bring your ownPromise
polyfill.Adding a bunch of tests for this functionality is my next order of business.
cc @amasad @thomasboyt @subtleGradient @bklimt @lukehoban @arv