Await promises from sync iterators with for-await (#13824)
Co-authored-by: Mickey Rose <lightmare@users.noreply.github.com>
This commit is contained in:
parent
6029252bec
commit
b9ea196259
@ -5,6 +5,14 @@
|
|||||||
|
|
||||||
import template from "@babel/template";
|
import template from "@babel/template";
|
||||||
|
|
||||||
|
export const asyncIterator = {
|
||||||
|
minVersion: "7.15.9",
|
||||||
|
ast: () =>
|
||||||
|
template.program.ast(
|
||||||
|
'\nexport default function _asyncIterator(iterable) {\n var method, async, sync;\n if (typeof Symbol !== "undefined") {\n async = Symbol.asyncIterator;\n sync = Symbol.iterator;\n }\n do {\n if (!sync) {\n async = "@@asyncIterator";\n sync = "@@iterator";\n }\n if (async && (method = iterable[async]) != null) {\n return method.call(iterable);\n }\n if ((method = iterable[sync]) != null) {\n return new AsyncFromSyncIterator(method.call(iterable));\n }\n } while (!(sync === "@@iterator" || (sync = null)));\n throw new TypeError("Object is not async iterable");\n}\nfunction AsyncFromSyncIterator(s) {\n AsyncFromSyncIterator = function (s) {\n this.s = s;\n this.n = s.next;\n };\n AsyncFromSyncIterator.prototype = {\n s: null,\n n: null,\n next: function () {\n return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments));\n },\n return: function (value) {\n var ret = this.s.return;\n if (ret === undefined) {\n return Promise.resolve({ value: value, done: true });\n }\n return AsyncFromSyncIteratorContinuation(ret.apply(this.s, arguments));\n },\n throw: function (value) {\n var thr = this.s.return;\n if (thr === undefined) return Promise.reject(value);\n return AsyncFromSyncIteratorContinuation(thr.apply(this.s, arguments));\n },\n };\n function AsyncFromSyncIteratorContinuation(r) {\n \n if (Object(r) !== r) {\n return Promise.reject(new TypeError(r + " is not an object."));\n }\n var done = r.done;\n return Promise.resolve(r.value).then(function (value) {\n return { value: value, done: done };\n });\n }\n return new AsyncFromSyncIterator(s);\n}\n',
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
export const jsx = {
|
export const jsx = {
|
||||||
minVersion: "7.0.0-beta.0",
|
minVersion: "7.0.0-beta.0",
|
||||||
ast: () =>
|
ast: () =>
|
||||||
|
|||||||
@ -16,20 +16,6 @@ const helper = (minVersion: string) => (tpl: TemplateStringsArray) => ({
|
|||||||
ast: () => template.program.ast(tpl),
|
ast: () => template.program.ast(tpl),
|
||||||
});
|
});
|
||||||
|
|
||||||
helpers.asyncIterator = helper("7.0.0-beta.0")`
|
|
||||||
export default function _asyncIterator(iterable) {
|
|
||||||
var method;
|
|
||||||
if (typeof Symbol !== "undefined") {
|
|
||||||
if (Symbol.asyncIterator) method = iterable[Symbol.asyncIterator];
|
|
||||||
if (method == null && Symbol.iterator) method = iterable[Symbol.iterator];
|
|
||||||
}
|
|
||||||
if (method == null) method = iterable["@@asyncIterator"];
|
|
||||||
if (method == null) method = iterable["@@iterator"]
|
|
||||||
if (method == null) throw new TypeError("Object is not async iterable");
|
|
||||||
return method.call(iterable);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
helpers.AwaitValue = helper("7.0.0-beta.0")`
|
helpers.AwaitValue = helper("7.0.0-beta.0")`
|
||||||
export default function _AwaitValue(value) {
|
export default function _AwaitValue(value) {
|
||||||
this.wrapped = value;
|
this.wrapped = value;
|
||||||
|
|||||||
67
packages/babel-helpers/src/helpers/asyncIterator.js
Normal file
67
packages/babel-helpers/src/helpers/asyncIterator.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/* @minVersion 7.15.9 */
|
||||||
|
|
||||||
|
export default function _asyncIterator(iterable) {
|
||||||
|
var method,
|
||||||
|
async,
|
||||||
|
sync,
|
||||||
|
retry = 2;
|
||||||
|
|
||||||
|
if (typeof Symbol !== "undefined") {
|
||||||
|
async = Symbol.asyncIterator;
|
||||||
|
sync = Symbol.iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (retry--) {
|
||||||
|
if (async && (method = iterable[async]) != null) {
|
||||||
|
return method.call(iterable);
|
||||||
|
}
|
||||||
|
if (sync && (method = iterable[sync]) != null) {
|
||||||
|
return new AsyncFromSyncIterator(method.call(iterable));
|
||||||
|
}
|
||||||
|
|
||||||
|
async = "@@asyncIterator";
|
||||||
|
sync = "@@iterator";
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new TypeError("Object is not async iterable");
|
||||||
|
}
|
||||||
|
|
||||||
|
function AsyncFromSyncIterator(s) {
|
||||||
|
AsyncFromSyncIterator = function (s) {
|
||||||
|
this.s = s;
|
||||||
|
this.n = s.next;
|
||||||
|
};
|
||||||
|
AsyncFromSyncIterator.prototype = {
|
||||||
|
/* SyncIterator */ s: null,
|
||||||
|
/* SyncIterator.[[Next]] */ n: null,
|
||||||
|
next: function () {
|
||||||
|
return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments));
|
||||||
|
},
|
||||||
|
return: function (value) {
|
||||||
|
var ret = this.s.return;
|
||||||
|
if (ret === undefined) {
|
||||||
|
return Promise.resolve({ value: value, done: true });
|
||||||
|
}
|
||||||
|
return AsyncFromSyncIteratorContinuation(ret.apply(this.s, arguments));
|
||||||
|
},
|
||||||
|
throw: function (value) {
|
||||||
|
var thr = this.s.return;
|
||||||
|
if (thr === undefined) return Promise.reject(value);
|
||||||
|
return AsyncFromSyncIteratorContinuation(thr.apply(this.s, arguments));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function AsyncFromSyncIteratorContinuation(r) {
|
||||||
|
// This step is _before_ calling AsyncFromSyncIteratorContinuation in the spec.
|
||||||
|
if (Object(r) !== r) {
|
||||||
|
return Promise.reject(new TypeError(r + " is not an object."));
|
||||||
|
}
|
||||||
|
|
||||||
|
var done = r.done;
|
||||||
|
return Promise.resolve(r.value).then(function (value) {
|
||||||
|
return { value: value, done: done };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AsyncFromSyncIterator(s);
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
async function* fn() {
|
||||||
|
for await (const result of [Promise.resolve("ok")]) {
|
||||||
|
return { result };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fn().next().then(result => {
|
||||||
|
expect(result).toEqual({
|
||||||
|
done: true,
|
||||||
|
value: { result: "ok" }
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
async function* fn() {
|
||||||
|
for await (const result of [Promise.resolve("ok")]) {
|
||||||
|
return { result };
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["proposal-async-generator-functions"],
|
||||||
|
"parserOpts": {
|
||||||
|
"allowReturnOutsideFunction": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
function fn() {
|
||||||
|
return _fn.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _fn() {
|
||||||
|
_fn = babelHelpers.wrapAsyncGenerator(function* () {
|
||||||
|
var _iteratorAbruptCompletion = false;
|
||||||
|
var _didIteratorError = false;
|
||||||
|
|
||||||
|
var _iteratorError;
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (var _iterator = babelHelpers.asyncIterator([Promise.resolve("ok")]), _step; _iteratorAbruptCompletion = !(_step = yield babelHelpers.awaitAsyncGenerator(_iterator.next())).done; _iteratorAbruptCompletion = false) {
|
||||||
|
const result = _step.value;
|
||||||
|
return {
|
||||||
|
result
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
_didIteratorError = true;
|
||||||
|
_iteratorError = err;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (_iteratorAbruptCompletion && _iterator.return != null) {
|
||||||
|
yield babelHelpers.awaitAsyncGenerator(_iterator.return());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (_didIteratorError) {
|
||||||
|
throw _iteratorError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return _fn.apply(this, arguments);
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
async function* fn() {
|
||||||
|
yield* [Promise.resolve("ok")] // CreateAsyncFromSyncIterator
|
||||||
|
}
|
||||||
|
|
||||||
|
return fn().next().then(result => {
|
||||||
|
expect(result).toEqual({ value: "ok", done: false });
|
||||||
|
});
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
async function* fn() {
|
||||||
|
yield* [Promise.resolve("ok")] // CreateAsyncFromSyncIterator
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["proposal-async-generator-functions"],
|
||||||
|
"parserOpts": {
|
||||||
|
"allowReturnOutsideFunction": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
function fn() {
|
||||||
|
return _fn.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _fn() {
|
||||||
|
_fn = babelHelpers.wrapAsyncGenerator(function* () {
|
||||||
|
yield* babelHelpers.asyncGeneratorDelegate(babelHelpers.asyncIterator([Promise.resolve("ok")]), babelHelpers.awaitAsyncGenerator); // CreateAsyncFromSyncIterator
|
||||||
|
});
|
||||||
|
return _fn.apply(this, arguments);
|
||||||
|
}
|
||||||
@ -18,6 +18,15 @@
|
|||||||
"regenerator-runtime": "^0.13.4"
|
"regenerator-runtime": "^0.13.4"
|
||||||
},
|
},
|
||||||
"exports": {
|
"exports": {
|
||||||
|
"./helpers/asyncIterator": [
|
||||||
|
{
|
||||||
|
"node": "./helpers/asyncIterator.js",
|
||||||
|
"import": "./helpers/esm/asyncIterator.js",
|
||||||
|
"default": "./helpers/asyncIterator.js"
|
||||||
|
},
|
||||||
|
"./helpers/asyncIterator.js"
|
||||||
|
],
|
||||||
|
"./helpers/esm/asyncIterator": "./helpers/esm/asyncIterator.js",
|
||||||
"./helpers/jsx": [
|
"./helpers/jsx": [
|
||||||
{
|
{
|
||||||
"node": "./helpers/jsx.js",
|
"node": "./helpers/jsx.js",
|
||||||
@ -54,15 +63,6 @@
|
|||||||
"./helpers/wrapRegExp.js"
|
"./helpers/wrapRegExp.js"
|
||||||
],
|
],
|
||||||
"./helpers/esm/wrapRegExp": "./helpers/esm/wrapRegExp.js",
|
"./helpers/esm/wrapRegExp": "./helpers/esm/wrapRegExp.js",
|
||||||
"./helpers/asyncIterator": [
|
|
||||||
{
|
|
||||||
"node": "./helpers/asyncIterator.js",
|
|
||||||
"import": "./helpers/esm/asyncIterator.js",
|
|
||||||
"default": "./helpers/asyncIterator.js"
|
|
||||||
},
|
|
||||||
"./helpers/asyncIterator.js"
|
|
||||||
],
|
|
||||||
"./helpers/esm/asyncIterator": "./helpers/esm/asyncIterator.js",
|
|
||||||
"./helpers/AwaitValue": [
|
"./helpers/AwaitValue": [
|
||||||
{
|
{
|
||||||
"node": "./helpers/AwaitValue.js",
|
"node": "./helpers/AwaitValue.js",
|
||||||
|
|||||||
@ -17,6 +17,15 @@
|
|||||||
"regenerator-runtime": "^0.13.4"
|
"regenerator-runtime": "^0.13.4"
|
||||||
},
|
},
|
||||||
"exports": {
|
"exports": {
|
||||||
|
"./helpers/asyncIterator": [
|
||||||
|
{
|
||||||
|
"node": "./helpers/asyncIterator.js",
|
||||||
|
"import": "./helpers/esm/asyncIterator.js",
|
||||||
|
"default": "./helpers/asyncIterator.js"
|
||||||
|
},
|
||||||
|
"./helpers/asyncIterator.js"
|
||||||
|
],
|
||||||
|
"./helpers/esm/asyncIterator": "./helpers/esm/asyncIterator.js",
|
||||||
"./helpers/jsx": [
|
"./helpers/jsx": [
|
||||||
{
|
{
|
||||||
"node": "./helpers/jsx.js",
|
"node": "./helpers/jsx.js",
|
||||||
@ -53,15 +62,6 @@
|
|||||||
"./helpers/wrapRegExp.js"
|
"./helpers/wrapRegExp.js"
|
||||||
],
|
],
|
||||||
"./helpers/esm/wrapRegExp": "./helpers/esm/wrapRegExp.js",
|
"./helpers/esm/wrapRegExp": "./helpers/esm/wrapRegExp.js",
|
||||||
"./helpers/asyncIterator": [
|
|
||||||
{
|
|
||||||
"node": "./helpers/asyncIterator.js",
|
|
||||||
"import": "./helpers/esm/asyncIterator.js",
|
|
||||||
"default": "./helpers/asyncIterator.js"
|
|
||||||
},
|
|
||||||
"./helpers/asyncIterator.js"
|
|
||||||
],
|
|
||||||
"./helpers/esm/asyncIterator": "./helpers/esm/asyncIterator.js",
|
|
||||||
"./helpers/AwaitValue": [
|
"./helpers/AwaitValue": [
|
||||||
{
|
{
|
||||||
"node": "./helpers/AwaitValue.js",
|
"node": "./helpers/AwaitValue.js",
|
||||||
|
|||||||
@ -17,6 +17,15 @@
|
|||||||
"regenerator-runtime": "^0.13.4"
|
"regenerator-runtime": "^0.13.4"
|
||||||
},
|
},
|
||||||
"exports": {
|
"exports": {
|
||||||
|
"./helpers/asyncIterator": [
|
||||||
|
{
|
||||||
|
"node": "./helpers/asyncIterator.js",
|
||||||
|
"import": "./helpers/esm/asyncIterator.js",
|
||||||
|
"default": "./helpers/asyncIterator.js"
|
||||||
|
},
|
||||||
|
"./helpers/asyncIterator.js"
|
||||||
|
],
|
||||||
|
"./helpers/esm/asyncIterator": "./helpers/esm/asyncIterator.js",
|
||||||
"./helpers/jsx": [
|
"./helpers/jsx": [
|
||||||
{
|
{
|
||||||
"node": "./helpers/jsx.js",
|
"node": "./helpers/jsx.js",
|
||||||
@ -53,15 +62,6 @@
|
|||||||
"./helpers/wrapRegExp.js"
|
"./helpers/wrapRegExp.js"
|
||||||
],
|
],
|
||||||
"./helpers/esm/wrapRegExp": "./helpers/esm/wrapRegExp.js",
|
"./helpers/esm/wrapRegExp": "./helpers/esm/wrapRegExp.js",
|
||||||
"./helpers/asyncIterator": [
|
|
||||||
{
|
|
||||||
"node": "./helpers/asyncIterator.js",
|
|
||||||
"import": "./helpers/esm/asyncIterator.js",
|
|
||||||
"default": "./helpers/asyncIterator.js"
|
|
||||||
},
|
|
||||||
"./helpers/asyncIterator.js"
|
|
||||||
],
|
|
||||||
"./helpers/esm/asyncIterator": "./helpers/esm/asyncIterator.js",
|
|
||||||
"./helpers/AwaitValue": [
|
"./helpers/AwaitValue": [
|
||||||
{
|
{
|
||||||
"node": "./helpers/AwaitValue.js",
|
"node": "./helpers/AwaitValue.js",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user