Skip to content

Commit 825d2c9

Browse files
committed
stream: handle sync writev completion in pipeTo
Treat writer.writev() returning undefined as synchronous success to match the existing write() fallback behavior for duck-typed writers. This avoids calling Promise.prototype.then on undefined after a batch write has already been accepted. Fixes: #63560 Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: openai:gpt-5.5
1 parent 15d0c61 commit 825d2c9

2 files changed

Lines changed: 30 additions & 1 deletion

File tree

lib/internal/streams/iter/pull.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const {
1313
ArrayPrototypePush,
1414
ArrayPrototypeSlice,
1515
PromisePrototypeThen,
16+
PromiseResolve,
1617
SymbolAsyncIterator,
1718
SymbolIterator,
1819
TypedArrayPrototypeGetByteLength,
@@ -922,7 +923,14 @@ async function pipeTo(source, ...args) {
922923
return waitForSyncBackpressure();
923924
}
924925
const opts = signal ? { __proto__: null, signal } : undefined;
925-
return PromisePrototypeThen(writer.writev(batch, opts), () => {
926+
const result = writer.writev(batch, opts);
927+
if (result === undefined) {
928+
for (let i = 0; i < batch.length; i++) {
929+
totalBytes += TypedArrayPrototypeGetByteLength(batch[i]);
930+
}
931+
return;
932+
}
933+
return PromisePrototypeThen(PromiseResolve(result), () => {
926934
for (let i = 0; i < batch.length; i++) {
927935
totalBytes += TypedArrayPrototypeGetByteLength(batch[i]);
928936
}

test/parallel/test-stream-iter-pipeto-writev.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,26 @@ async function testWritevAsyncFallback() {
4646
assert.ok(batches.some((b) => b.length > 1));
4747
}
4848

49+
// Multi-chunk batch with synchronous writev success (returns undefined)
50+
async function testWritevSyncUndefinedSuccess() {
51+
const chunks = [];
52+
const writer = {
53+
write(chunk) {
54+
chunks.push(chunk);
55+
},
56+
writev(batch) {
57+
chunks.push(...batch);
58+
},
59+
end() {},
60+
};
61+
async function* source() {
62+
yield [new Uint8Array([65]), new Uint8Array([66])];
63+
}
64+
const total = await pipeTo(source(), writer);
65+
assert.strictEqual(total, 2);
66+
assert.strictEqual(Buffer.concat(chunks).toString(), 'AB');
67+
}
68+
4969
// writevSync returns false — falls through to async writev
5070
async function testWritevSyncFails() {
5171
const asyncCalls = [];
@@ -190,6 +210,7 @@ async function testPipeToSyncWriteFallback() {
190210
Promise.all([
191211
testWritevSyncSuccess(),
192212
testWritevAsyncFallback(),
213+
testWritevSyncUndefinedSuccess(),
193214
testWritevSyncFails(),
194215
testWriteSyncFailsMidBatch(),
195216
testWriteSyncAlwaysFails(),

0 commit comments

Comments
 (0)