Correctly delegate .return() in async generator (#10422)
* Correctly delegate .return() in async generator * Add catch param * minNodeVersion * Add another test
This commit is contained in:
parent
861844761f
commit
d25262ec4b
@ -136,7 +136,7 @@ helpers.AsyncGenerator = helper("7.0.0-beta.0")`
|
||||
Promise.resolve(wrappedAwait ? value.wrapped : value).then(
|
||||
function (arg) {
|
||||
if (wrappedAwait) {
|
||||
resume("next", arg);
|
||||
resume(key === "return" ? "return" : "next", arg);
|
||||
return
|
||||
}
|
||||
|
||||
@ -238,6 +238,10 @@ helpers.asyncGeneratorDelegate = helper("7.0.0-beta.0")`
|
||||
|
||||
if (typeof inner.return === "function") {
|
||||
iter.return = function (value) {
|
||||
if (waiting) {
|
||||
waiting = false;
|
||||
return value;
|
||||
}
|
||||
return pump("return", value);
|
||||
};
|
||||
}
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
const log = [];
|
||||
|
||||
async function* func1() {
|
||||
log.push(1);
|
||||
yield "a";
|
||||
log.push(2);
|
||||
}
|
||||
|
||||
async function* func2() {
|
||||
yield* func1();
|
||||
log.push(3);
|
||||
}
|
||||
|
||||
return (async () => {
|
||||
const iterator = func2();
|
||||
await iterator.next();
|
||||
await iterator.return();
|
||||
|
||||
expect(log).toEqual([1]);
|
||||
})();
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"minNodeVersion": "8.0.0"
|
||||
}
|
||||
10
packages/babel-plugin-proposal-async-generator-functions/test/fixtures/yield-star/options.json
vendored
Normal file
10
packages/babel-plugin-proposal-async-generator-functions/test/fixtures/yield-star/options.json
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"parserOpts": {
|
||||
"allowReturnOutsideFunction": true
|
||||
},
|
||||
"plugins": [
|
||||
"external-helpers",
|
||||
"transform-async-to-generator",
|
||||
"proposal-async-generator-functions"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
const log = [];
|
||||
|
||||
async function* inner() {
|
||||
try {
|
||||
log.push(1);
|
||||
yield "a";
|
||||
log.push(2);
|
||||
yield "b";
|
||||
log.push(3);
|
||||
} finally {
|
||||
log.push(4);
|
||||
yield "c";
|
||||
log.push(5);
|
||||
}
|
||||
}
|
||||
|
||||
async function* outer() {
|
||||
log.push(6);
|
||||
yield* inner();
|
||||
log.push(7);
|
||||
}
|
||||
|
||||
return (async () => {
|
||||
const iterator = outer();
|
||||
|
||||
let res = await iterator.next();
|
||||
expect(res).toEqual({ value: "a", done: false });
|
||||
expect(log).toEqual([6, 1]);
|
||||
|
||||
const [res1, res2] = await Promise.all([ iterator.return("x"), iterator.return("y") ]);
|
||||
expect(res1).toEqual({ value: "c", done: false });
|
||||
expect(res2).toEqual({ value: "y", done: true });
|
||||
expect(log).toEqual([6, 1, 4]);
|
||||
})();
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"minNodeVersion": "8.0.0"
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
const log = [];
|
||||
|
||||
async function* inner() {
|
||||
try {
|
||||
log.push(1);
|
||||
yield "a";
|
||||
log.push(2);
|
||||
yield "b";
|
||||
log.push(3);
|
||||
} finally {
|
||||
log.push(4);
|
||||
yield "c";
|
||||
log.push(5);
|
||||
}
|
||||
}
|
||||
|
||||
async function* outer() {
|
||||
log.push(6);
|
||||
yield* inner();
|
||||
log.push(7);
|
||||
}
|
||||
|
||||
return (async () => {
|
||||
const iterator = outer();
|
||||
|
||||
let res = await iterator.next();
|
||||
expect(res).toEqual({ value: "a", done: false });
|
||||
expect(log).toEqual([6, 1]);
|
||||
|
||||
res = await iterator.return("x");
|
||||
expect(res).toEqual({ value: "c", done: false });
|
||||
expect(log).toEqual([6, 1, 4]);
|
||||
|
||||
res = await iterator.return("y");
|
||||
expect(res).toEqual({ value: "y", done: true });
|
||||
expect(log).toEqual([6, 1, 4]);
|
||||
})();
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"minNodeVersion": "8.0.0"
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
const log = [];
|
||||
|
||||
async function* inner() {
|
||||
try {
|
||||
log.push(1);
|
||||
yield "a";
|
||||
log.push(2);
|
||||
yield "b";
|
||||
log.push(3);
|
||||
} finally {
|
||||
log.push(4);
|
||||
yield "c";
|
||||
log.push(5);
|
||||
}
|
||||
}
|
||||
|
||||
async function* outer() {
|
||||
log.push(6);
|
||||
yield* inner();
|
||||
log.push(7);
|
||||
}
|
||||
|
||||
return (async () => {
|
||||
const iterator = outer();
|
||||
|
||||
let res = await iterator.next();
|
||||
expect(res).toEqual({ value: "a", done: false });
|
||||
expect(log).toEqual([6, 1]);
|
||||
|
||||
res = await iterator.return();
|
||||
expect(res).toEqual({ value: "c", done: false });
|
||||
expect(log).toEqual([6, 1, 4]);
|
||||
|
||||
res = await iterator.next();
|
||||
expect(res).toEqual({ value: undefined, done: true });
|
||||
expect(log).toEqual([6, 1, 4, 5, 7]);
|
||||
})();
|
||||
@ -0,0 +1,31 @@
|
||||
const log = [];
|
||||
|
||||
async function* inner() {
|
||||
log.push(1);
|
||||
yield "a";
|
||||
log.push(2);
|
||||
yield "b";
|
||||
log.push(3);
|
||||
}
|
||||
|
||||
async function* outer() {
|
||||
log.push(4);
|
||||
yield* inner();
|
||||
log.push(5);
|
||||
}
|
||||
|
||||
return (async () => {
|
||||
const iterator = outer();
|
||||
|
||||
let res = await iterator.next();
|
||||
expect(res).toEqual({ value: "a", done: false });
|
||||
expect(log).toEqual([4, 1]);
|
||||
|
||||
res = await iterator.return();
|
||||
expect(res).toEqual({ value: undefined, done: true });
|
||||
expect(log).toEqual([4, 1]);
|
||||
|
||||
res = await iterator.next();
|
||||
expect(res).toEqual({ value: undefined, done: true });
|
||||
expect(log).toEqual([4, 1]);
|
||||
})();
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"minNodeVersion": "8.0.0"
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
const log = [];
|
||||
|
||||
async function* inner() {
|
||||
try {
|
||||
log.push(1);
|
||||
yield "a";
|
||||
log.push(2);
|
||||
yield "b";
|
||||
log.push(3);
|
||||
} catch (e) {
|
||||
log.push(4);
|
||||
yield "c";
|
||||
log.push(5);
|
||||
}
|
||||
}
|
||||
|
||||
async function* outer() {
|
||||
log.push(6);
|
||||
yield* inner();
|
||||
log.push(7);
|
||||
}
|
||||
|
||||
return (async () => {
|
||||
const iterator = outer();
|
||||
|
||||
let res = await iterator.next();
|
||||
expect(res).toEqual({ value: "a", done: false });
|
||||
expect(log).toEqual([6, 1]);
|
||||
|
||||
res = await iterator.throw(new Error("TEST"));
|
||||
expect(res).toEqual({ value: "c", done: false });
|
||||
expect(log).toEqual([6, 1, 4]);
|
||||
|
||||
res = await iterator.next();
|
||||
expect(res).toEqual({ value: undefined, done: true });
|
||||
expect(log).toEqual([6, 1, 4, 5, 7]);
|
||||
})();
|
||||
@ -0,0 +1,37 @@
|
||||
const log = [];
|
||||
|
||||
async function* inner() {
|
||||
try {
|
||||
log.push(1);
|
||||
yield "a";
|
||||
log.push(2);
|
||||
yield "b";
|
||||
log.push(3);
|
||||
} finally {
|
||||
log.push(4);
|
||||
yield "c";
|
||||
log.push(5);
|
||||
}
|
||||
}
|
||||
|
||||
async function* outer() {
|
||||
log.push(6);
|
||||
yield* inner();
|
||||
log.push(7);
|
||||
}
|
||||
|
||||
return (async () => {
|
||||
const iterator = outer();
|
||||
|
||||
let res = await iterator.next();
|
||||
expect(res).toEqual({ value: "a", done: false });
|
||||
expect(log).toEqual([6, 1]);
|
||||
|
||||
res = await iterator.throw(new Error("TEST"));
|
||||
expect(res).toEqual({ value: "c", done: false });
|
||||
expect(log).toEqual([6, 1, 4]);
|
||||
|
||||
// "yield" in finally suspended the exception for one turn
|
||||
await expect(iterator.next()).rejects.toThrow(/TEST/);
|
||||
expect(log).toEqual([6, 1, 4, 5]);
|
||||
})();
|
||||
@ -4,7 +4,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; 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; } }
|
||||
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(key === "return" ? "return" : "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; }; }
|
||||
|
||||
|
||||
@ -310,7 +310,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; 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; } }
|
||||
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(key === "return" ? "return" : "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; }; }
|
||||
|
||||
|
||||
@ -42,7 +42,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; 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; } }
|
||||
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(key === "return" ? "return" : "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; }; }
|
||||
|
||||
|
||||
@ -12,7 +12,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; 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; } }
|
||||
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(key === "return" ? "return" : "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; }; }
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user