diff --git a/packages/babel-helpers/src/helpers-generated.ts b/packages/babel-helpers/src/helpers-generated.ts index c3e523a7c132..a825ef7e5a07 100755 --- a/packages/babel-helpers/src/helpers-generated.ts +++ b/packages/babel-helpers/src/helpers-generated.ts @@ -5,6 +5,14 @@ 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 = { minVersion: "7.0.0-beta.0", ast: () => diff --git a/packages/babel-helpers/src/helpers.ts b/packages/babel-helpers/src/helpers.ts index 0911aee76651..1e95f57b0b1d 100644 --- a/packages/babel-helpers/src/helpers.ts +++ b/packages/babel-helpers/src/helpers.ts @@ -16,20 +16,6 @@ const helper = (minVersion: string) => (tpl: TemplateStringsArray) => ({ 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")` export default function _AwaitValue(value) { this.wrapped = value; diff --git a/packages/babel-helpers/src/helpers/asyncIterator.js b/packages/babel-helpers/src/helpers/asyncIterator.js new file mode 100644 index 000000000000..f560b120b859 --- /dev/null +++ b/packages/babel-helpers/src/helpers/asyncIterator.js @@ -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); +} diff --git a/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/for-await/create-async-from-sync-iterator/exec.js b/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/for-await/create-async-from-sync-iterator/exec.js new file mode 100644 index 000000000000..e4833cda45d8 --- /dev/null +++ b/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/for-await/create-async-from-sync-iterator/exec.js @@ -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" } + }); +}); diff --git a/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/for-await/create-async-from-sync-iterator/input.js b/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/for-await/create-async-from-sync-iterator/input.js new file mode 100644 index 000000000000..9412e388ae80 --- /dev/null +++ b/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/for-await/create-async-from-sync-iterator/input.js @@ -0,0 +1,5 @@ +async function* fn() { + for await (const result of [Promise.resolve("ok")]) { + return { result }; + } +} diff --git a/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/for-await/create-async-from-sync-iterator/options.json b/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/for-await/create-async-from-sync-iterator/options.json new file mode 100644 index 000000000000..37c83a1dda0a --- /dev/null +++ b/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/for-await/create-async-from-sync-iterator/options.json @@ -0,0 +1,6 @@ +{ + "plugins": ["proposal-async-generator-functions"], + "parserOpts": { + "allowReturnOutsideFunction": true + } +} diff --git a/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/for-await/create-async-from-sync-iterator/output.js b/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/for-await/create-async-from-sync-iterator/output.js new file mode 100644 index 000000000000..8afcb0903de1 --- /dev/null +++ b/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/for-await/create-async-from-sync-iterator/output.js @@ -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); +} diff --git a/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/yield-star/create-async-from-sync-iterator/exec.js b/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/yield-star/create-async-from-sync-iterator/exec.js new file mode 100644 index 000000000000..16b02fb93ab5 --- /dev/null +++ b/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/yield-star/create-async-from-sync-iterator/exec.js @@ -0,0 +1,7 @@ +async function* fn() { + yield* [Promise.resolve("ok")] // CreateAsyncFromSyncIterator +} + +return fn().next().then(result => { + expect(result).toEqual({ value: "ok", done: false }); +}); diff --git a/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/yield-star/create-async-from-sync-iterator/input.js b/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/yield-star/create-async-from-sync-iterator/input.js new file mode 100644 index 000000000000..70b1fbe54868 --- /dev/null +++ b/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/yield-star/create-async-from-sync-iterator/input.js @@ -0,0 +1,3 @@ +async function* fn() { + yield* [Promise.resolve("ok")] // CreateAsyncFromSyncIterator +} diff --git a/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/yield-star/create-async-from-sync-iterator/options.json b/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/yield-star/create-async-from-sync-iterator/options.json new file mode 100644 index 000000000000..37c83a1dda0a --- /dev/null +++ b/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/yield-star/create-async-from-sync-iterator/options.json @@ -0,0 +1,6 @@ +{ + "plugins": ["proposal-async-generator-functions"], + "parserOpts": { + "allowReturnOutsideFunction": true + } +} diff --git a/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/yield-star/create-async-from-sync-iterator/output.js b/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/yield-star/create-async-from-sync-iterator/output.js new file mode 100644 index 000000000000..549ec238e862 --- /dev/null +++ b/packages/babel-plugin-proposal-async-generator-functions/test/fixtures/yield-star/create-async-from-sync-iterator/output.js @@ -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); +} diff --git a/packages/babel-runtime-corejs2/package.json b/packages/babel-runtime-corejs2/package.json index 2e8e9035ffa4..72529bd1a1f0 100644 --- a/packages/babel-runtime-corejs2/package.json +++ b/packages/babel-runtime-corejs2/package.json @@ -18,6 +18,15 @@ "regenerator-runtime": "^0.13.4" }, "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": [ { "node": "./helpers/jsx.js", @@ -54,15 +63,6 @@ "./helpers/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": [ { "node": "./helpers/AwaitValue.js", diff --git a/packages/babel-runtime-corejs3/package.json b/packages/babel-runtime-corejs3/package.json index acbd0ae6ac3a..e4eb3cefd6f7 100644 --- a/packages/babel-runtime-corejs3/package.json +++ b/packages/babel-runtime-corejs3/package.json @@ -17,6 +17,15 @@ "regenerator-runtime": "^0.13.4" }, "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": [ { "node": "./helpers/jsx.js", @@ -53,15 +62,6 @@ "./helpers/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": [ { "node": "./helpers/AwaitValue.js", diff --git a/packages/babel-runtime/package.json b/packages/babel-runtime/package.json index 7d7142bbcab4..5b3952e34a23 100644 --- a/packages/babel-runtime/package.json +++ b/packages/babel-runtime/package.json @@ -17,6 +17,15 @@ "regenerator-runtime": "^0.13.4" }, "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": [ { "node": "./helpers/jsx.js", @@ -53,15 +62,6 @@ "./helpers/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": [ { "node": "./helpers/AwaitValue.js",