Adhering to async generator yield behavior change (#6452)
This commit is contained in:
committed by
GitHub
parent
39d05da3ed
commit
4684edaec7
@@ -5,7 +5,7 @@ const awaitTemplate = `
|
||||
function* wrapper() {
|
||||
var ITERATOR_COMPLETION = true;
|
||||
var ITERATOR_HAD_ERROR_KEY = false;
|
||||
var ITERATOR_ERROR_KEY = undefined;
|
||||
var ITERATOR_ERROR_KEY;
|
||||
try {
|
||||
for (
|
||||
var ITERATOR_KEY = GET_ITERATOR(OBJECT), STEP_KEY, STEP_VALUE;
|
||||
@@ -38,7 +38,7 @@ const buildForAwaitWithoutWrapping = template(
|
||||
awaitTemplate.replace(/\bAWAIT\b/g, ""),
|
||||
);
|
||||
|
||||
export default function(path, helpers) {
|
||||
export default function(path, { getAsyncIterator, wrapAwait }) {
|
||||
const { node, scope, parent } = path;
|
||||
|
||||
const stepKey = scope.generateUidIdentifier("step");
|
||||
@@ -58,9 +58,7 @@ export default function(path, helpers) {
|
||||
]);
|
||||
}
|
||||
|
||||
const build = helpers.wrapAwait
|
||||
? buildForAwait
|
||||
: buildForAwaitWithoutWrapping;
|
||||
const build = wrapAwait ? buildForAwait : buildForAwaitWithoutWrapping;
|
||||
let template = build({
|
||||
ITERATOR_HAD_ERROR_KEY: scope.generateUidIdentifier("didIteratorError"),
|
||||
ITERATOR_COMPLETION: scope.generateUidIdentifier(
|
||||
@@ -68,11 +66,11 @@ export default function(path, helpers) {
|
||||
),
|
||||
ITERATOR_ERROR_KEY: scope.generateUidIdentifier("iteratorError"),
|
||||
ITERATOR_KEY: scope.generateUidIdentifier("iterator"),
|
||||
GET_ITERATOR: helpers.getAsyncIterator,
|
||||
GET_ITERATOR: getAsyncIterator,
|
||||
OBJECT: node.right,
|
||||
STEP_VALUE: stepValue,
|
||||
STEP_KEY: stepKey,
|
||||
...(helpers.wrapAwait ? { AWAIT: helpers.wrapAwait } : {}),
|
||||
...(wrapAwait ? { AWAIT: wrapAwait } : {}),
|
||||
});
|
||||
|
||||
// remove generator function wrapper
|
||||
|
||||
@@ -10,11 +10,21 @@ const awaitVisitor = {
|
||||
path.skip();
|
||||
},
|
||||
|
||||
AwaitExpression({ node }, { wrapAwait }) {
|
||||
node.type = "YieldExpression";
|
||||
if (wrapAwait) {
|
||||
node.argument = t.callExpression(wrapAwait, [node.argument]);
|
||||
AwaitExpression(path, { wrapAwait }) {
|
||||
const argument = path.get("argument");
|
||||
|
||||
if (path.parentPath.isYieldExpression()) {
|
||||
path.replaceWith(argument.node);
|
||||
return;
|
||||
}
|
||||
|
||||
path.replaceWith(
|
||||
t.yieldExpression(
|
||||
wrapAwait
|
||||
? t.callExpression(wrapAwait, [argument.node])
|
||||
: argument.node,
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
ForOfStatement(path, { file, wrapAwait }) {
|
||||
|
||||
@@ -89,7 +89,7 @@ helpers.asyncIterator = defineHelper(`
|
||||
|
||||
helpers.AwaitValue = defineHelper(`
|
||||
export default function _AwaitValue(value) {
|
||||
this.value = value;
|
||||
this.wrapped = value;
|
||||
}
|
||||
`);
|
||||
|
||||
@@ -106,7 +106,7 @@ helpers.AsyncGenerator = defineHelper(`
|
||||
arg: arg,
|
||||
resolve: resolve,
|
||||
reject: reject,
|
||||
next: null
|
||||
next: null,
|
||||
};
|
||||
|
||||
if (back) {
|
||||
@@ -122,13 +122,18 @@ helpers.AsyncGenerator = defineHelper(`
|
||||
try {
|
||||
var result = gen[key](arg)
|
||||
var value = result.value;
|
||||
if (value instanceof AwaitValue) {
|
||||
Promise.resolve(value.value).then(
|
||||
function (arg) { resume("next", arg); },
|
||||
function (arg) { resume("throw", arg); });
|
||||
} else {
|
||||
settle(result.done ? "return" : "normal", result.value);
|
||||
}
|
||||
var wrappedAwait = value instanceof AwaitValue;
|
||||
|
||||
Promise.resolve(wrappedAwait ? value.wrapped : value).then(
|
||||
function (arg) {
|
||||
if (wrappedAwait) {
|
||||
resume("next", arg);
|
||||
return
|
||||
}
|
||||
|
||||
settle(result.done ? "return" : "normal", arg);
|
||||
},
|
||||
function (err) { resume("throw", err); });
|
||||
} catch (err) {
|
||||
settle("throw", err);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
"use strict";
|
||||
|
||||
const actual = [];
|
||||
const expected = ["foo", "bar", "baz", "xyz"];
|
||||
|
||||
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
async function* test() {
|
||||
yield await delay(0).then(() => actual.push("foo"));
|
||||
await delay(0).then(() => actual.push("bar"));
|
||||
yield delay(0).then(() => actual.push("baz"));
|
||||
actual.push("xyz");
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const g = test();
|
||||
g.next();
|
||||
g.next();
|
||||
await g.next();
|
||||
}
|
||||
|
||||
return main().then(() => {
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"plugins": [
|
||||
"external-helpers",
|
||||
"transform-async-to-generator",
|
||||
"transform-async-generator-functions"
|
||||
],
|
||||
"presets": ["es2015"],
|
||||
"parserOpts": {
|
||||
"allowReturnOutsideFunction": true
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
babelHelpers.asyncToGenerator(function* () {
|
||||
var _iteratorNormalCompletion = true;
|
||||
var _didIteratorError = false;
|
||||
var _iteratorError = undefined;
|
||||
|
||||
var _iteratorError;
|
||||
|
||||
try {
|
||||
for (var _iterator = babelHelpers.asyncIterator(y), _step, _value; _step = yield _iterator.next(), _iteratorNormalCompletion = _step.done, _value = yield _step.value, !_iteratorNormalCompletion; _iteratorNormalCompletion = true) {
|
||||
|
||||
@@ -2,7 +2,8 @@ let f = (() => {
|
||||
var _ref = babelHelpers.asyncToGenerator(function* () {
|
||||
var _iteratorNormalCompletion = true;
|
||||
var _didIteratorError = false;
|
||||
var _iteratorError = undefined;
|
||||
|
||||
var _iteratorError;
|
||||
|
||||
try {
|
||||
for (var _iterator = babelHelpers.asyncIterator(y), _step, _value; _step = yield _iterator.next(), _iteratorNormalCompletion = _step.done, _value = yield _step.value, !_iteratorNormalCompletion; _iteratorNormalCompletion = true) {
|
||||
|
||||
@@ -2,7 +2,8 @@ let g = (() => {
|
||||
var _ref = babelHelpers.wrapAsyncGenerator(function* () {
|
||||
var _iteratorNormalCompletion = true;
|
||||
var _didIteratorError = false;
|
||||
var _iteratorError = undefined;
|
||||
|
||||
var _iteratorError;
|
||||
|
||||
try {
|
||||
for (var _iterator = babelHelpers.asyncIterator(y), _step, _value; _step = yield babelHelpers.awaitAsyncGenerator(_iterator.next()), _iteratorNormalCompletion = _step.done, _value = yield babelHelpers.awaitAsyncGenerator(_step.value), !_iteratorNormalCompletion; _iteratorNormalCompletion = true) {
|
||||
|
||||
@@ -2,7 +2,8 @@ let f = (() => {
|
||||
var _ref = babelHelpers.asyncToGenerator(function* () {
|
||||
var _iteratorNormalCompletion = true;
|
||||
var _didIteratorError = false;
|
||||
var _iteratorError = undefined;
|
||||
|
||||
var _iteratorError;
|
||||
|
||||
try {
|
||||
for (var _iterator = babelHelpers.asyncIterator(a), _step, _value; _step = yield _iterator.next(), _iteratorNormalCompletion = _step.done, _value = yield _step.value, !_iteratorNormalCompletion; _iteratorNormalCompletion = true) {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
babelHelpers.asyncToGenerator(function* () {
|
||||
var _iteratorNormalCompletion = true;
|
||||
var _didIteratorError = false;
|
||||
var _iteratorError = undefined;
|
||||
|
||||
var _iteratorError;
|
||||
|
||||
try {
|
||||
for (var _iterator = babelHelpers.asyncIterator(iterable), _step, _value; _step = yield _iterator.next(), _iteratorNormalCompletion = _step.done, _value = yield _step.value, !_iteratorNormalCompletion; _iteratorNormalCompletion = true) {
|
||||
|
||||
@@ -16,7 +16,7 @@ function _awaitAsyncGenerator(value) { return new _AwaitValue(value); }
|
||||
|
||||
function _wrapAsyncGenerator(fn) { return function () { return new _AsyncGenerator(fn.apply(this, arguments)); }; }
|
||||
|
||||
function _AsyncGenerator(gen) { var front, back; function send(key, arg) { return new Promise(function (resolve, reject) { var request = { key: key, arg: arg, resolve: resolve, reject: reject, next: null }; if (back) { back = back.next = request; } else { front = back = request; resume(key, arg); } }); } function resume(key, arg) { try { var result = gen[key](arg); var value = result.value; if (value instanceof _AwaitValue) { Promise.resolve(value.value).then(function (arg) { resume("next", arg); }, function (arg) { resume("throw", arg); }); } else { settle(result.done ? "return" : "normal", result.value); } } catch (err) { settle("throw", err); } } function settle(type, value) { switch (type) { case "return": front.resolve({ value: value, done: true }); break; case "throw": front.reject(value); break; default: front.resolve({ value: value, done: false }); break; } front = front.next; if (front) { resume(front.key, front.arg); } else { back = null; } } this._invoke = send; if (typeof gen.return !== "function") { this.return = undefined; } }
|
||||
function _AsyncGenerator(gen) { var front, back; function send(key, arg) { return new Promise(function (resolve, reject) { var request = { key: key, arg: arg, resolve: resolve, reject: reject, next: null }; if (back) { back = back.next = request; } else { front = back = request; resume(key, arg); } }); } function resume(key, arg) { try { var result = gen[key](arg); var value = result.value; var wrappedAwait = value instanceof _AwaitValue; Promise.resolve(wrappedAwait ? value.wrapped : value).then(function (arg) { if (wrappedAwait) { resume("next", arg); return; } settle(result.done ? "return" : "normal", arg); }, function (err) { resume("throw", err); }); } catch (err) { settle("throw", err); } } function settle(type, value) { switch (type) { case "return": front.resolve({ value: value, done: true }); break; case "throw": front.reject(value); break; default: front.resolve({ value: value, done: false }); break; } front = front.next; if (front) { resume(front.key, front.arg); } else { back = null; } } this._invoke = send; if (typeof gen.return !== "function") { this.return = undefined; } }
|
||||
|
||||
if (typeof Symbol === "function" && Symbol.asyncIterator) { _AsyncGenerator.prototype[Symbol.asyncIterator] = function () { return this; }; }
|
||||
|
||||
@@ -26,4 +26,4 @@ _AsyncGenerator.prototype.throw = function (arg) { return this._invoke("throw",
|
||||
|
||||
_AsyncGenerator.prototype.return = function (arg) { return this._invoke("return", arg); };
|
||||
|
||||
function _AwaitValue(value) { this.value = value; }
|
||||
function _AwaitValue(value) { this.wrapped = value; }
|
||||
|
||||
Reference in New Issue
Block a user