Skip to content

Commit 5fac436

Browse files
committed
stream: skip null output from stateful transforms
Treat null yielded by sync and async stateful transforms as no output, consistent with transform normalization semantics. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
1 parent 1ee6017 commit 5fac436

2 files changed

Lines changed: 26 additions & 0 deletions

File tree

lib/internal/streams/iter/pull.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,7 @@ function* withFlushSync(source) {
503503
function* applyStatefulSyncTransform(source, transform) {
504504
const output = transform(withFlushSync(source));
505505
for (const item of output) {
506+
if (item === null) continue;
506507
const batch = [];
507508
for (const chunk of flattenTransformYieldSync(item)) {
508509
ArrayPrototypePush(batch, chunk);
@@ -642,6 +643,7 @@ async function* withFlushAsync(source) {
642643
async function* applyStatefulAsyncTransform(source, transform, options) {
643644
const output = transform(withFlushAsync(source), options);
644645
for await (const item of output) {
646+
if (item === null) continue;
645647
// Fast path: item is already a Uint8Array[] batch (e.g. compression transforms)
646648
if (isUint8ArrayBatch(item)) {
647649
if (item.length > 0) {

test/parallel/test-stream-iter-transform-output.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,28 @@ async function testStatefulSyncTransformYieldsString() {
142142
assert.deepStrictEqual(data, new TextEncoder().encode('world'));
143143
}
144144

145+
// Stateful async transform yields null (no output)
146+
async function testStatefulTransformYieldsNull() {
147+
const tx = {
148+
async *transform() {
149+
yield null;
150+
},
151+
};
152+
const data = await bytes(pull(from('x'), tx));
153+
assert.deepStrictEqual(data, new Uint8Array());
154+
}
155+
156+
// Stateful sync transform yields null (no output)
157+
async function testStatefulSyncTransformYieldsNull() {
158+
const tx = {
159+
*transform() {
160+
yield null;
161+
},
162+
};
163+
const data = bytesSync(pullSync(fromSync('x'), tx));
164+
assert.deepStrictEqual(data, new Uint8Array());
165+
}
166+
145167
// Flush returns single Uint8Array (not batch)
146168
async function testFlushReturnsSingleUint8Array() {
147169
const tx = (chunks) => {
@@ -217,6 +239,8 @@ Promise.all([
217239
testStatefulTransformYieldsString(),
218240
testStatefulTransformYieldsArrayBuffer(),
219241
testStatefulSyncTransformYieldsString(),
242+
testStatefulTransformYieldsNull(),
243+
testStatefulSyncTransformYieldsNull(),
220244
testFlushReturnsSingleUint8Array(),
221245
testFlushReturnsString(),
222246
testSyncFlushReturnsSingleUint8Array(),

0 commit comments

Comments
 (0)