From 3942b46ed7ae1a4b295503df0977b4967f036552 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Thu, 7 Oct 2021 00:08:00 +0200 Subject: [PATCH 1/4] Await promises from sync iterators with `for-await` --- packages/babel-helpers/src/helpers.ts | 48 +++++++++++++++++-- .../create-async-from-sync-iterator/exec.js | 12 +++++ .../create-async-from-sync-iterator/input.js | 5 ++ .../options.json | 6 +++ .../create-async-from-sync-iterator/output.js | 35 ++++++++++++++ .../create-async-from-sync-iterator/exec.js | 7 +++ .../create-async-from-sync-iterator/input.js | 3 ++ .../options.json | 6 +++ .../create-async-from-sync-iterator/output.js | 10 ++++ 9 files changed, 129 insertions(+), 3 deletions(-) create mode 100644 packages/babel-plugin-proposal-async-generator-functions/test/fixtures/for-await/create-async-from-sync-iterator/exec.js create mode 100644 packages/babel-plugin-proposal-async-generator-functions/test/fixtures/for-await/create-async-from-sync-iterator/input.js create mode 100644 packages/babel-plugin-proposal-async-generator-functions/test/fixtures/for-await/create-async-from-sync-iterator/options.json create mode 100644 packages/babel-plugin-proposal-async-generator-functions/test/fixtures/for-await/create-async-from-sync-iterator/output.js create mode 100644 packages/babel-plugin-proposal-async-generator-functions/test/fixtures/yield-star/create-async-from-sync-iterator/exec.js create mode 100644 packages/babel-plugin-proposal-async-generator-functions/test/fixtures/yield-star/create-async-from-sync-iterator/input.js create mode 100644 packages/babel-plugin-proposal-async-generator-functions/test/fixtures/yield-star/create-async-from-sync-iterator/options.json create mode 100644 packages/babel-plugin-proposal-async-generator-functions/test/fixtures/yield-star/create-async-from-sync-iterator/output.js diff --git a/packages/babel-helpers/src/helpers.ts b/packages/babel-helpers/src/helpers.ts index 0911aee76651..4c5b181baa7b 100644 --- a/packages/babel-helpers/src/helpers.ts +++ b/packages/babel-helpers/src/helpers.ts @@ -16,18 +16,60 @@ const helper = (minVersion: string) => (tpl: TemplateStringsArray) => ({ ast: () => template.program.ast(tpl), }); -helpers.asyncIterator = helper("7.0.0-beta.0")` +helpers.asyncIterator = helper("7.15.9")` 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 && Symbol.iterator) { + method = iterable[Symbol.iterator]; + if (method != null) return new AsyncFromSyncIterator(method.call(iterable)); + } } if (method == null) method = iterable["@@asyncIterator"]; - if (method == null) method = iterable["@@iterator"] + if (method == null) { + method = iterable["@@iterator"]; + if (method != null) return new AsyncFromSyncIterator(method.call(iterable)); + } if (method == null) throw new TypeError("Object is not async iterable"); return method.call(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); + } `; helpers.AwaitValue = helper("7.0.0-beta.0")` 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); +} From eb16405a1935086d6ea14b803cd42f5c2f57ed7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Thu, 7 Oct 2021 00:10:49 +0200 Subject: [PATCH 2/4] Extract helper to its own file --- .../babel-helpers/src/helpers-generated.ts | 8 +++ packages/babel-helpers/src/helpers.ts | 56 ----------------- .../src/helpers/asyncIterator.js | 61 +++++++++++++++++++ packages/babel-runtime-corejs2/package.json | 18 +++--- packages/babel-runtime-corejs3/package.json | 18 +++--- packages/babel-runtime/package.json | 18 +++--- 6 files changed, 96 insertions(+), 83 deletions(-) create mode 100644 packages/babel-helpers/src/helpers/asyncIterator.js diff --git a/packages/babel-helpers/src/helpers-generated.ts b/packages/babel-helpers/src/helpers-generated.ts index c3e523a7c132..d50c76c61996 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;\n if (typeof Symbol !== "undefined") {\n if (Symbol.asyncIterator) method = iterable[Symbol.asyncIterator];\n if (method == null && Symbol.iterator) {\n method = iterable[Symbol.iterator];\n if (method != null) {\n return new AsyncFromSyncIterator(method.call(iterable));\n }\n }\n }\n if (method == null) method = iterable["@@asyncIterator"];\n if (method == null) {\n method = iterable["@@iterator"];\n if (method != null) return new AsyncFromSyncIterator(method.call(iterable));\n }\n if (method == null) throw new TypeError("Object is not async iterable");\n return method.call(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 4c5b181baa7b..1e95f57b0b1d 100644 --- a/packages/babel-helpers/src/helpers.ts +++ b/packages/babel-helpers/src/helpers.ts @@ -16,62 +16,6 @@ const helper = (minVersion: string) => (tpl: TemplateStringsArray) => ({ ast: () => template.program.ast(tpl), }); -helpers.asyncIterator = helper("7.15.9")` - 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) return new AsyncFromSyncIterator(method.call(iterable)); - } - } - if (method == null) method = iterable["@@asyncIterator"]; - if (method == null) { - method = iterable["@@iterator"]; - if (method != null) return new AsyncFromSyncIterator(method.call(iterable)); - } - if (method == null) throw new TypeError("Object is not async iterable"); - return method.call(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); - } -`; - 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..8830c33dbe28 --- /dev/null +++ b/packages/babel-helpers/src/helpers/asyncIterator.js @@ -0,0 +1,61 @@ +/* @minVersion 7.15.9 */ + +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) { + return new AsyncFromSyncIterator(method.call(iterable)); + } + } + } + if (method == null) method = iterable["@@asyncIterator"]; + if (method == null) { + method = iterable["@@iterator"]; + if (method != null) return new AsyncFromSyncIterator(method.call(iterable)); + } + if (method == null) throw new TypeError("Object is not async iterable"); + return method.call(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-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", From ceb9feca6e93949a4452903bd7c02d52371dd187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Thu, 7 Oct 2021 00:12:39 +0200 Subject: [PATCH 3/4] Optimize helper size (934 vs 881 bytes minified) --- .../babel-helpers/src/helpers-generated.ts | 2 +- .../src/helpers/asyncIterator.js | 31 ++++++++++--------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/packages/babel-helpers/src/helpers-generated.ts b/packages/babel-helpers/src/helpers-generated.ts index d50c76c61996..a825ef7e5a07 100755 --- a/packages/babel-helpers/src/helpers-generated.ts +++ b/packages/babel-helpers/src/helpers-generated.ts @@ -9,7 +9,7 @@ export const asyncIterator = { minVersion: "7.15.9", ast: () => template.program.ast( - '\nexport default function _asyncIterator(iterable) {\n var method;\n if (typeof Symbol !== "undefined") {\n if (Symbol.asyncIterator) method = iterable[Symbol.asyncIterator];\n if (method == null && Symbol.iterator) {\n method = iterable[Symbol.iterator];\n if (method != null) {\n return new AsyncFromSyncIterator(method.call(iterable));\n }\n }\n }\n if (method == null) method = iterable["@@asyncIterator"];\n if (method == null) {\n method = iterable["@@iterator"];\n if (method != null) return new AsyncFromSyncIterator(method.call(iterable));\n }\n if (method == null) throw new TypeError("Object is not async iterable");\n return method.call(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', + '\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', ), }; diff --git a/packages/babel-helpers/src/helpers/asyncIterator.js b/packages/babel-helpers/src/helpers/asyncIterator.js index 8830c33dbe28..9ed5f22bb89d 100644 --- a/packages/babel-helpers/src/helpers/asyncIterator.js +++ b/packages/babel-helpers/src/helpers/asyncIterator.js @@ -1,23 +1,24 @@ /* @minVersion 7.15.9 */ export default function _asyncIterator(iterable) { - var method; + var method, async, sync; if (typeof Symbol !== "undefined") { - if (Symbol.asyncIterator) method = iterable[Symbol.asyncIterator]; - if (method == null && Symbol.iterator) { - method = iterable[Symbol.iterator]; - if (method != null) { - return new AsyncFromSyncIterator(method.call(iterable)); - } - } - } - if (method == null) method = iterable["@@asyncIterator"]; - if (method == null) { - method = iterable["@@iterator"]; - if (method != null) return new AsyncFromSyncIterator(method.call(iterable)); + async = Symbol.asyncIterator; + sync = Symbol.iterator; } - if (method == null) throw new TypeError("Object is not async iterable"); - return method.call(iterable); + do { + if (!sync) { + async = "@@asyncIterator"; + sync = "@@iterator"; + } + if (async && (method = iterable[async]) != null) { + return method.call(iterable); + } + if ((method = iterable[sync]) != null) { + return new AsyncFromSyncIterator(method.call(iterable)); + } + } while (!(sync === "@@iterator" || (sync = null))); + throw new TypeError("Object is not async iterable"); } function AsyncFromSyncIterator(s) { From 34b58f06f9412023c5d2e29cf4779ecd4f029e98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Thu, 7 Oct 2021 23:40:44 +0200 Subject: [PATCH 4/4] Optimize helper size (881 vs 855 bytes minified) Co-authored-by: Mickey Rose --- .../src/helpers/asyncIterator.js | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/babel-helpers/src/helpers/asyncIterator.js b/packages/babel-helpers/src/helpers/asyncIterator.js index 9ed5f22bb89d..f560b120b859 100644 --- a/packages/babel-helpers/src/helpers/asyncIterator.js +++ b/packages/babel-helpers/src/helpers/asyncIterator.js @@ -1,23 +1,28 @@ /* @minVersion 7.15.9 */ export default function _asyncIterator(iterable) { - var method, async, sync; + var method, + async, + sync, + retry = 2; + if (typeof Symbol !== "undefined") { async = Symbol.asyncIterator; sync = Symbol.iterator; } - do { - if (!sync) { - async = "@@asyncIterator"; - sync = "@@iterator"; - } + + while (retry--) { if (async && (method = iterable[async]) != null) { return method.call(iterable); } - if ((method = iterable[sync]) != null) { + if (sync && (method = iterable[sync]) != null) { return new AsyncFromSyncIterator(method.call(iterable)); } - } while (!(sync === "@@iterator" || (sync = null))); + + async = "@@asyncIterator"; + sync = "@@iterator"; + } + throw new TypeError("Object is not async iterable"); }