diff options
Diffstat (limited to 'src/js/builtins/ConsoleObject.ts')
-rw-r--r-- | src/js/builtins/ConsoleObject.ts | 78 |
1 files changed, 59 insertions, 19 deletions
diff --git a/src/js/builtins/ConsoleObject.ts b/src/js/builtins/ConsoleObject.ts index 45746459a..2d657a78b 100644 --- a/src/js/builtins/ConsoleObject.ts +++ b/src/js/builtins/ConsoleObject.ts @@ -1,18 +1,55 @@ $overriddenName = "[Symbol.asyncIterator]"; export function asyncIterator(this: Console) { - const Iterator = async function* ConsoleAsyncIterator() { - const stream = Bun.stdin.stream(); - var reader = stream.getReader(); + var stream = Bun.stdin.stream(); - // TODO: use builtin - var decoder = new (globalThis as any).TextDecoder("utf-8", { fatal: false }) as TextDecoder; - var deferredError; - var indexOf = Bun.indexOfLine; + var decoder = new TextDecoder("utf-8", { fatal: false }); + var indexOf = Bun.indexOfLine; + var actualChunk: Uint8Array; + var i: number = -1; + var idx: number; + var last: number; + var done: boolean; + var value: Uint8Array[]; + var value_len: number; + var pendingChunk: Uint8Array | undefined; + async function* ConsoleAsyncIterator() { + var reader = stream.getReader(); + var deferredError; try { + if (i !== -1) { + last = i + 1; + i = indexOf(actualChunk, last); + + while (i !== -1) { + yield decoder.decode(actualChunk.subarray(last, i)); + last = i + 1; + i = indexOf(actualChunk, last); + } + + for (idx++; idx < value_len; idx++) { + actualChunk = value[idx]; + if (pendingChunk) { + actualChunk = Buffer.concat([pendingChunk, actualChunk]); + pendingChunk = undefined; + } + + last = 0; + // TODO: "\r", 0x4048, 0x4049, 0x404A, 0x404B, 0x404C, 0x404D, 0x404E, 0x404F + i = indexOf(actualChunk, last); + while (i !== -1) { + yield decoder.decode(actualChunk.subarray(last, i)); + last = i + 1; + i = indexOf(actualChunk, last); + } + i = -1; + + pendingChunk = actualChunk.subarray(last); + } + actualChunk = undefined!; + } + while (true) { - var done, value; - var pendingChunk; const firstResult = reader.readMany(); if ($isPromise(firstResult)) { ({ done, value } = await firstResult); @@ -27,26 +64,29 @@ export function asyncIterator(this: Console) { return; } - var actualChunk; // we assume it was given line-by-line - for (const chunk of value) { - actualChunk = chunk; + for (idx = 0, value_len = value.length; idx < value_len; idx++) { + actualChunk = value[idx]; if (pendingChunk) { - actualChunk = Buffer.concat([pendingChunk, chunk]); - pendingChunk = null; + actualChunk = Buffer.concat([pendingChunk, actualChunk]); + pendingChunk = undefined; } - var last = 0; + last = 0; // TODO: "\r", 0x4048, 0x4049, 0x404A, 0x404B, 0x404C, 0x404D, 0x404E, 0x404F - var i = indexOf(actualChunk, last); + i = indexOf(actualChunk, last); while (i !== -1) { + // This yield may end the function, in that case we need to be able to recover state + // if the iterator was fired up again. yield decoder.decode(actualChunk.subarray(last, i)); last = i + 1; i = indexOf(actualChunk, last); } + i = -1; pendingChunk = actualChunk.subarray(last); } + actualChunk = undefined!; } } catch (e) { deferredError = e; @@ -57,11 +97,11 @@ export function asyncIterator(this: Console) { throw deferredError; } } - }; + } const symbol = globalThis.Symbol.asyncIterator; - this[symbol] = Iterator; - return Iterator(); + this[symbol] = ConsoleAsyncIterator; + return ConsoleAsyncIterator(); } export function write(this: Console, input) { |