import { assertEquals, assertRejects } from "@std/assert"; Deno.test("streams can be iterated without native async-iterator support", async (t) => { const native = Object.getOwnPropertyDescriptor(ReadableStream.prototype, Symbol.asyncIterator)!; Reflect.deleteProperty(ReadableStream.prototype, Symbol.asyncIterator); try { await import("./stream-iterator.ts"); await t.step("completion releases the reader without canceling", async () => { let canceled = false; const stream = new ReadableStream({ start(controller) { controller.enqueue("shell output"); controller.close(); }, cancel: () => void (canceled = true), }); const received = []; for await (const chunk of stream) received.push(chunk); assertEquals(received, ["shell output"]); assertEquals(stream.locked, false); assertEquals(canceled, false); }); await t.step("early exit cancels and releases the reader", async () => { let canceled = false; const stream = new ReadableStream({ start: (controller) => controller.enqueue("shell output"), cancel: () => void (canceled = true), }); for await (const _ of stream) break; assertEquals(canceled, true); assertEquals(stream.locked, false); }); await t.step("preventCancel leaves the stream available after early exit", async () => { let canceled = false; const stream = new ReadableStream({ start(controller) { controller.enqueue("first"); controller.enqueue("second"); }, cancel: () => void (canceled = true), }); for await (const _ of stream[Symbol.asyncIterator]({ preventCancel: true })) break; assertEquals(canceled, false); assertEquals(stream.locked, false); const reader = stream.getReader(); assertEquals((await reader.read()).value, "second"); await reader.cancel(); reader.releaseLock(); }); await t.step("read errors propagate and release the reader", async () => { const stream = new ReadableStream({ start: (controller) => controller.error(new Error("connection lost")), }); await assertRejects(() => stream[Symbol.asyncIterator]().next(), Error, "connection lost"); assertEquals(stream.locked, false); }); } finally { Object.defineProperty(ReadableStream.prototype, Symbol.asyncIterator, native); } });