From 3fceae807037d97cd6c93d20d87d1ef5a98fdd75 Mon Sep 17 00:00:00 2001 From: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> Date: Wed, 12 Oct 2022 23:46:15 -0700 Subject: Implement `ReadableStream.prototype[Symbol.asyncIterator]` cc @fabiancook --- src/bun.js/builtins/js/ReadableStream.js | 21 +++++++++ src/bun.js/builtins/js/ReadableStreamInternals.js | 53 +++++++++++++++++++++++ 2 files changed, 74 insertions(+) (limited to 'src/bun.js') diff --git a/src/bun.js/builtins/js/ReadableStream.js b/src/bun.js/builtins/js/ReadableStream.js index 42c0fbdbc..8020b024d 100644 --- a/src/bun.js/builtins/js/ReadableStream.js +++ b/src/bun.js/builtins/js/ReadableStream.js @@ -443,3 +443,24 @@ function locked() return @isReadableStreamLocked(this); } + +function values(options) { + "use strict"; + var prototype = this?.constructor?.prototype; + if (!prototype) { + return @undefined; + } + @readableStreamDefineLazyIterators(prototype); + return prototype.values.@call(this, options); +} + +@linkTimeConstant +function lazyAsyncIterator() { + "use strict"; + var prototype = this?.constructor?.prototype; + if (!prototype) { + return @undefined; + } + @readableStreamDefineLazyIterators(prototype); + return prototype[globalThis.Symbol.asyncIterator].@call(this); +} \ No newline at end of file diff --git a/src/bun.js/builtins/js/ReadableStreamInternals.js b/src/bun.js/builtins/js/ReadableStreamInternals.js index 5321ca922..cbe72c99e 100644 --- a/src/bun.js/builtins/js/ReadableStreamInternals.js +++ b/src/bun.js/builtins/js/ReadableStreamInternals.js @@ -2096,3 +2096,56 @@ async function readableStreamToArrayDirect(stream, underlyingSource) { return capability.@promise; } + + +function readableStreamDefineLazyIterators(prototype) { + "use strict"; + + var asyncIterator = globalThis.Symbol.asyncIterator; + + var ReadableStreamAsyncIterator = async function* ReadableStreamAsyncIterator(stream, preventCancel) { + var reader = stream.getReader(); + var deferredError; + try { + while (true) { + var done, value; + const firstResult = reader.readMany(); + if (@isPromise(firstResult)) { + const result = await firstResult; + done = result.done; + value = result.value; + } else { + done = firstResult.done; + value = firstResult.value; + } + + if (done) { + return; + } + yield* value; + } + } catch(e) { + deferredError = e; + } finally { + reader.releaseLock(); + + if (!preventCancel) { + stream.cancel(deferredError); + } + + if (deferredError) { + throw deferredError; + } + } + }; + + var createAsyncIterator = function asyncIterator() { + return ReadableStreamAsyncIterator(this, false); + }; + var createValues = function values({preventCancel = false} = {preventCancel: false}) { + return ReadableStreamAsyncIterator(this, preventCancel); + }; + @Object.@defineProperty(prototype, asyncIterator, { value: createAsyncIterator }); + @Object.@defineProperty(prototype, "values", { value: createValues }); + return prototype; +} \ No newline at end of file -- cgit v1.2.3