From 82a8b3b34f2d5c25c8f45135200a7b9a8a1d6369 Mon Sep 17 00:00:00 2001 From: Mark Stuart Date: Sat, 17 Oct 2026 22:24:15 +0000 Subject: [PATCH] fix: close zero-length take streams immediately --- index.js | 5 +++++ readme.md | 2 ++ regression.test.js | 20 ++++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 regression.test.js diff --git a/index.js b/index.js index dc2b9b6..c7ffcfa 100644 --- a/index.js +++ b/index.js @@ -41,6 +41,11 @@ export function takeStream(count) { let taken = 0; return new TransformStream({ + start(controller) { + if (count === 0) { + controller.terminate(); + } + }, transform(chunk, controller) { if (taken < count) { taken += 1; diff --git a/readme.md b/readme.md index 3b90303..b362015 100644 --- a/readme.md +++ b/readme.md @@ -44,6 +44,8 @@ Returns a `TransformStream` that only passes chunks where `function_` returns `t ### takeStream(count) +A count of zero closes the readable side immediately, without waiting for upstream data. + Returns a `TransformStream` that passes only the first `count` chunks then terminates. ### batchStream(size) diff --git a/regression.test.js b/regression.test.js new file mode 100644 index 0000000..3bd1136 --- /dev/null +++ b/regression.test.js @@ -0,0 +1,20 @@ +import test from "ava"; +import { takeStream } from "./index.js"; + +test("takeStream(0) closes without waiting for an upstream chunk", async (t) => { + const transform = takeStream(0); + const reader = transform.readable.getReader(); + let timeout; + try { + const result = await Promise.race([ + reader.read(), + new Promise((resolve) => { + timeout = setTimeout(() => resolve("still pending"), 100); + }), + ]); + t.deepEqual(result, { done: true, value: undefined }); + } finally { + clearTimeout(timeout); + await reader.cancel(); + } +});