import { WritableStream, WritableStreamDefaultWriter, WritableStreamDefaultController, CountQueuingStrategy, ByteLengthQueuingStrategy, ReadableStream, TransformStream } from "node:stream/web"; import { out, deferred, result, caught, sameError, launch } from "./helpers.js"; export function reportErrors() { launch(async () => { for (const [name, fn] of [ ["null-sink", () => new WritableStream(null)], ["false-sink", () => new WritableStream(false)], ["type", () => new WritableStream({ type: "bytes" })], ["hwm", () => new WritableStream({}, { highWaterMark: -1 })], ["nan", () => new WritableStream({}, { highWaterMark: NaN })], ["size-fn", () => new WritableStream({}, { size: 1 })], ["write-fn", () => new WritableStream({ write: true })], ["close-fn", () => new WritableStream({ close: {} })], ["abort-fn", () => new WritableStream({ abort: "bad" })], ["writer", () => new WritableStreamDefaultWriter({})], ["controller", () => new WritableStreamDefaultController()], ["count-init", () => new CountQueuingStrategy()], ["bytes-init", () => new ByteLengthQueuingStrategy(null)], ["count-missing", () => new CountQueuingStrategy({})], ["bytes-array", () => new ByteLengthQueuingStrategy([])], ]) out(name, caught(fn)); out("unchecked-hwm", new CountQueuingStrategy({ highWaterMark: -1 }).highWaterMark, new ByteLengthQueuingStrategy({ highWaterMark: NaN }).highWaterMark); out("null-strategy", caught(() => new WritableStream({}, null)), caught(() => new WritableStream(() => {}))); const wproto = WritableStreamDefaultWriter.prototype; for (const name of ["abort", "close", "write"]) out("writer-brand:" + name, await result(wproto[name].call({}))); out("writer-release-brand", caught(() => wproto.releaseLock.call({}))); for (const name of ["ready", "closed"]) out("writer-brand:" + name, await result(Object.getOwnPropertyDescriptor(wproto, name).get.call({}))); out("writer-size-brand", caught(() => Object.getOwnPropertyDescriptor(wproto, "desiredSize").get.call({}))); for (const name of ["abort", "close"]) out("stream-brand:" + name, await result(WritableStream.prototype[name].call({}))); out("stream-writer-brand", caught(() => WritableStream.prototype.getWriter.call({}))); out("controller-brand", caught(() => WritableStreamDefaultController.prototype.error.call({}))); { const entered = deferred(), gate = deferred(), reason = new Error("controller-error"); let controller, abortCalls = 0; const stream = new WritableStream({ start(c) { controller = c; }, write() { entered.resolve(); return gate.promise; }, abort() { abortCalls++; } }); const w = stream.getWriter(), a = result(w.write("a")), b = sameError(w.write("b"), reason); await entered.promise; controller.error(reason); controller.error(new Error("ignored")); out("controller-error", w.desiredSize, controller.signal.aborted, await sameError(w.ready, reason)); gate.resolve(); out("controller-writes", await a, await b, await sameError(w.closed, reason), await sameError(w.write(), reason)); out("errored-abort", await result(w.abort()), abortCalls); } for (const kind of ["start", "write", "close", "abort"]) { const error = new Error("sink-" + kind), seen = [], sink = {}; for (const name of ["start", "write", "close", "abort"]) sink[name] = function () { seen.push(name); if (name === kind) return Promise.reject(error); }; const stream = new WritableStream(sink), w = stream.getWriter(); if (kind === "start" || kind === "write") { const a = sameError(w.write("a"), error), b = sameError(w.write("b"), error), c = sameError(w.close(), error); out("sink-error:" + kind, await a, await b, await c, await sameError(w.closed, error), seen.join(",")); } else if (kind === "close") { await w.write("a"); out("sink-error:close", await sameError(w.close(), error), await sameError(w.closed, error), seen.join(",")); } else { const reason = new Error("original-abort"); out("sink-error:abort", await sameError(w.abort(reason), error), await sameError(w.closed, reason), seen.join(",")); } } for (const size of [-1, NaN, Infinity, undefined]) { const stream = new WritableStream({}, { size() { return size; } }), w = stream.getWriter(); out("bad-size", String(size), await result(w.write("a")), await result(w.closed), w.desiredSize); } { const w = new WritableStream({}, { size() { return 1n; } }).getWriter(); const error = await w.write("bigint").catch((e) => e); out("bigint-size", error instanceof TypeError, error.code === undefined, await sameError(w.closed, error), w.desiredSize); } { const error = new Error("size-callback"); const stream = new WritableStream({}, { size() { throw error; } }), w = stream.getWriter(); out("throwing-size", await sameError(w.write(), error), await sameError(w.closed, error)); } { let writer; const stream = new WritableStream({}, { size() { writer.releaseLock(); return 1; } }); writer = stream.getWriter(); out("size-release", await result(writer.write("a")), stream.locked); await stream.close(); } { let controller; const stream = new ReadableStream({ start(c) { controller = c; } }, { size() { return -1; } }); out("readable-size", caught(() => controller.enqueue("bad")), controller.desiredSize, await result(stream.getReader().read())); } { const reason = new Error("sync-start"); out("sync-start", caught(() => new WritableStream({ start() { throw reason; } }))); const w = new WritableStream({ write() { throw new Error("sync-write"); } }).getWriter(); out("sync-write", await result(w.write()), await result(w.closed)); } { const reason = new Error("transform-start"); const t = new TransformStream({ start() { return Promise.reject(reason); } }); const r = t.readable.getReader(), w = t.writable.getWriter(); out("transform-start-error", await sameError(r.read(), reason), await sameError(w.write("a"), reason), await sameError(r.closed, reason), await sameError(w.closed, reason)); } }); }