diff --git a/packages/babel-helpers/src/helpers-generated.ts b/packages/babel-helpers/src/helpers-generated.ts index c0e40106c605..1e0f1086920c 100644 --- a/packages/babel-helpers/src/helpers-generated.ts +++ b/packages/babel-helpers/src/helpers-generated.ts @@ -35,30 +35,6 @@ function helper( export { helpers as default }; const helpers: Record = { __proto__: null, - // size: 1095, gzip size: 500 - AsyncGenerator: helper( - "7.0.0-beta.0", - 'function AsyncGeneratorImpl(e){var r,t;function resume(r,t){try{var n=e[r](t),o=n.value,u=o instanceof OverloadYield;Promise.resolve(u?o.v:o).then((function(t){if(u){var i="return"===r?"return":"next";if(!o.k||t.done)return void resume(i,t);t=e[i](t).value}settle(n.done?"return":"normal",t)}),(function(e){resume("throw",e)}))}catch(e){settle("throw",e)}}function settle(e,n){switch(e){case"return":r.resolve({value:n,done:!0});break;case"throw":r.reject(n);break;default:r.resolve({value:n,done:!1})}(r=r.next)?resume(r.key,r.arg):t=null}this._invoke=function(e,n){return new Promise((function(o,u){var i={key:e,arg:n,resolve:o,reject:u,next:null};t?t=t.next=i:(r=t=i,resume(e,n))}))},"function"!=typeof e.return&&(this.return=void 0)}AsyncGeneratorImpl.prototype["function"==typeof Symbol&&Symbol.asyncIterator||"@@asyncIterator"]=function(){return this},AsyncGeneratorImpl.prototype.next=function(e){return this._invoke("next",e)},AsyncGeneratorImpl.prototype.throw=function(e){return this._invoke("throw",e)},AsyncGeneratorImpl.prototype.return=function(e){return this._invoke("return",e)};', - { - globals: ["Promise", "Symbol"], - locals: { - AsyncGeneratorImpl: [ - "body.0.id", - "body.1.expression.expressions.0.left.object.object", - "body.1.expression.expressions.1.left.object.object", - "body.1.expression.expressions.2.left.object.object", - "body.1.expression.expressions.3.left.object.object", - ], - }, - exportBindingAssignments: [], - exportName: "AsyncGeneratorImpl", - dependencies: { - OverloadYield: [ - "body.0.body.body.1.body.body.0.block.body.0.declarations.2.init.right", - ], - }, - }, - ), // size: 47, gzip size: 63 OverloadYield: helper( "7.18.14", @@ -1382,18 +1358,28 @@ const helpers: Record = { dependencies: {}, }, ), - // size: 102, gzip size: 96 + // size: 1177, gzip size: 528 wrapAsyncGenerator: helper( "7.0.0-beta.0", - "function _wrapAsyncGenerator(r){return function(){return new AsyncGenerator(r.apply(this,arguments))}}", + 'function _wrapAsyncGenerator(e){return function(){return new AsyncGenerator(e.apply(this,arguments))}}function AsyncGenerator(e){var r,t;function resume(r,t){try{var n=e[r](t),o=n.value,u=o instanceof OverloadYield;Promise.resolve(u?o.v:o).then((function(t){if(u){var i="return"===r?"return":"next";if(!o.k||t.done)return void resume(i,t);t=e[i](t).value}settle(n.done?"return":"normal",t)}),(function(e){resume("throw",e)}))}catch(e){settle("throw",e)}}function settle(e,n){switch(e){case"return":r.resolve({value:n,done:!0});break;case"throw":r.reject(n);break;default:r.resolve({value:n,done:!1})}(r=r.next)?resume(r.key,r.arg):t=null}this._invoke=function(e,n){return new Promise((function(o,u){var i={key:e,arg:n,resolve:o,reject:u,next:null};t?t=t.next=i:(r=t=i,resume(e,n))}))},"function"!=typeof e.return&&(this.return=void 0)}AsyncGenerator.prototype["function"==typeof Symbol&&Symbol.asyncIterator||"@@asyncIterator"]=function(){return this},AsyncGenerator.prototype.next=function(e){return this._invoke("next",e)},AsyncGenerator.prototype.throw=function(e){return this._invoke("throw",e)},AsyncGenerator.prototype.return=function(e){return this._invoke("return",e)};', { - globals: [], - locals: { _wrapAsyncGenerator: ["body.0.id"] }, + globals: ["Promise", "Symbol"], + locals: { + _wrapAsyncGenerator: ["body.0.id"], + AsyncGenerator: [ + "body.1.id", + "body.0.body.body.0.argument.body.body.0.argument.callee", + "body.2.expression.expressions.0.left.object.object", + "body.2.expression.expressions.1.left.object.object", + "body.2.expression.expressions.2.left.object.object", + "body.2.expression.expressions.3.left.object.object", + ], + }, exportBindingAssignments: [], exportName: "_wrapAsyncGenerator", dependencies: { - AsyncGenerator: [ - "body.0.body.body.0.argument.body.body.0.argument.callee", + OverloadYield: [ + "body.1.body.body.1.body.body.0.block.body.0.declarations.2.init.right", ], }, }, diff --git a/packages/babel-helpers/src/helpers/AsyncGenerator.ts b/packages/babel-helpers/src/helpers/AsyncGenerator.ts deleted file mode 100644 index 80bd32dc1b66..000000000000 --- a/packages/babel-helpers/src/helpers/AsyncGenerator.ts +++ /dev/null @@ -1,155 +0,0 @@ -/* @minVersion 7.0.0-beta.0 */ - -import OverloadYield from "./OverloadYield.ts"; - -type AsyncIteratorMethod = "next" | "throw" | "return"; - -declare class AsyncGeneratorImpl - implements AsyncGenerator -{ - _invoke: ( - key: AsyncIteratorMethod, - arg: IteratorResult, - ) => Promise>; - - constructor(gen: Generator); - - next(...args: [] | [TNext]): Promise>; - return( - value: TReturn | PromiseLike, - ): Promise>; - throw(e: any): Promise>; - [Symbol.asyncIterator](): AsyncGenerator; -} - -interface AsyncGeneratorRequest { - key: AsyncIteratorMethod; - arg: IteratorResult; - resolve: (value: IteratorResult) => void; - reject: (error: any) => void; - next: AsyncGeneratorRequest | null; -} - -function AsyncGeneratorImpl( - this: AsyncGeneratorImpl, - gen: Generator, -) { - var front: AsyncGeneratorRequest | null, - back: AsyncGeneratorRequest | null; - - function send(key: AsyncIteratorMethod, arg: IteratorResult) { - return new Promise>(function (resolve, reject) { - var request: AsyncGeneratorRequest = { - 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: AsyncIteratorMethod, arg: IteratorResult) { - try { - var result = gen[key](arg); - var value = result.value; - var overloaded = value instanceof OverloadYield; - - Promise.resolve( - overloaded ? (value as OverloadYield).v : value, - ).then( - function (arg: any) { - if (overloaded) { - // Overloaded yield requires calling into the generator twice: - // - first we get the iterator result wrapped in a promise - // (the gen[key](arg) call above) - // - then we await it (the Promise.resolve call above) - // - then we give the result back to the iterator, so that it can: - // * if it was an await, use its result - // * if it was a yield*, possibly return the `done: true` signal - // so that yield* knows that the iterator is finished. - // This needs to happen in the second call, because in the - // first one `done: true` was hidden in the promise and thus - // not visible to the (sync) yield*. - // The other part of this implementation is in asyncGeneratorDelegate. - var nextKey: "return" | "next" = - key === "return" ? "return" : "next"; - if ( - !(value as OverloadYield>).k || - arg.done - ) { - // await or end of yield* - resume(nextKey, arg); - return; - } else { - // yield*, not done - arg = gen[nextKey](arg).value; - } - } - - settle(result.done ? "return" : "normal", arg); - }, - function (err) { - resume("throw", err); - }, - ); - } catch (err) { - settle("throw", err); - } - } - - function settle(type: AsyncIteratorMethod | "normal", value: any) { - 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; - - // Hide "return" method if generator return is not supported - if (typeof gen.return !== "function") { - // @ts-expect-error -- intentionally remove "return" when not supported - this.return = undefined; - } -} - -AsyncGeneratorImpl.prototype[ - ((typeof Symbol === "function" && Symbol.asyncIterator) || - "@@asyncIterator") as typeof Symbol.asyncIterator -] = function () { - return this; -}; - -AsyncGeneratorImpl.prototype.next = function (arg: IteratorResult) { - return this._invoke("next", arg); -}; -AsyncGeneratorImpl.prototype.throw = function (arg: IteratorResult) { - return this._invoke("throw", arg); -}; -AsyncGeneratorImpl.prototype.return = function (arg: IteratorResult) { - return this._invoke("return", arg); -}; - -export { AsyncGeneratorImpl as default }; diff --git a/packages/babel-helpers/src/helpers/wrapAsyncGenerator.ts b/packages/babel-helpers/src/helpers/wrapAsyncGenerator.ts index 9ad108053f7d..e99495d95260 100644 --- a/packages/babel-helpers/src/helpers/wrapAsyncGenerator.ts +++ b/packages/babel-helpers/src/helpers/wrapAsyncGenerator.ts @@ -1,6 +1,6 @@ /* @minVersion 7.0.0-beta.0 */ -import AsyncGenerator from "./AsyncGenerator.ts"; +import OverloadYield from "./OverloadYield.ts"; export default function _wrapAsyncGenerator(fn: GeneratorFunction) { return function (this: any) { @@ -8,3 +8,155 @@ export default function _wrapAsyncGenerator(fn: GeneratorFunction) { return new AsyncGenerator(fn.apply(this, arguments as any)); }; } + +/* == The implementation of the AsyncGenerator class == */ + +type AsyncIteratorMethod = "next" | "throw" | "return"; + +declare class AsyncGenerator + implements globalThis.AsyncGenerator +{ + _invoke: ( + key: AsyncIteratorMethod, + arg: IteratorResult, + ) => Promise>; + + constructor(gen: Generator); + + next(...args: [] | [TNext]): Promise>; + return( + value: TReturn | PromiseLike, + ): Promise>; + throw(e: any): Promise>; + [Symbol.asyncIterator](): AsyncGenerator; +} + +interface AsyncGeneratorRequest { + key: AsyncIteratorMethod; + arg: IteratorResult; + resolve: (value: IteratorResult) => void; + reject: (error: any) => void; + next: AsyncGeneratorRequest | null; +} + +function AsyncGenerator( + this: AsyncGenerator, + gen: Generator, +) { + var front: AsyncGeneratorRequest | null, + back: AsyncGeneratorRequest | null; + + function send(key: AsyncIteratorMethod, arg: IteratorResult) { + return new Promise>(function (resolve, reject) { + var request: AsyncGeneratorRequest = { + 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: AsyncIteratorMethod, arg: IteratorResult) { + try { + var result = gen[key](arg); + var value = result.value; + var overloaded = value instanceof OverloadYield; + + Promise.resolve( + overloaded ? (value as OverloadYield).v : value, + ).then( + function (arg: any) { + if (overloaded) { + // Overloaded yield requires calling into the generator twice: + // - first we get the iterator result wrapped in a promise + // (the gen[key](arg) call above) + // - then we await it (the Promise.resolve call above) + // - then we give the result back to the iterator, so that it can: + // * if it was an await, use its result + // * if it was a yield*, possibly return the `done: true` signal + // so that yield* knows that the iterator is finished. + // This needs to happen in the second call, because in the + // first one `done: true` was hidden in the promise and thus + // not visible to the (sync) yield*. + // The other part of this implementation is in asyncGeneratorDelegate. + var nextKey: "return" | "next" = + key === "return" ? "return" : "next"; + if ( + !(value as OverloadYield>).k || + arg.done + ) { + // await or end of yield* + resume(nextKey, arg); + return; + } else { + // yield*, not done + arg = gen[nextKey](arg).value; + } + } + + settle(result.done ? "return" : "normal", arg); + }, + function (err) { + resume("throw", err); + }, + ); + } catch (err) { + settle("throw", err); + } + } + + function settle(type: AsyncIteratorMethod | "normal", value: any) { + 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; + + // Hide "return" method if generator return is not supported + if (typeof gen.return !== "function") { + // @ts-expect-error -- intentionally remove "return" when not supported + this.return = undefined; + } +} + +AsyncGenerator.prototype[ + ((typeof Symbol === "function" && Symbol.asyncIterator) || + "@@asyncIterator") as typeof Symbol.asyncIterator +] = function () { + return this; +}; + +AsyncGenerator.prototype.next = function (arg: IteratorResult) { + return this._invoke("next", arg); +}; +AsyncGenerator.prototype.throw = function (arg: IteratorResult) { + return this._invoke("throw", arg); +}; +AsyncGenerator.prototype.return = function (arg: IteratorResult) { + return this._invoke("return", arg); +};