Repository navigation
Clarify pipeToSync() byte accounting when SyncWriter.write() returns false #16
Description
Summary
API.md documents Stream.pipeToSync(source, ...transforms?, writer, options?) as piping a synchronous source to a SyncWriter.
It also documents synchronous writer methods returning boolean, but the required pipeToSync() behavior when a sync write returns false is not explicit.
Should Stream.pipeToSync() treat a false return from writer.write() or writer.writev() as a failed write, and avoid counting those bytes as written?
Current ambiguity
API.md documents sync writer behavior in two related places:
Writer.writeSync()/writevSync()can returnfalseas a failure/backpressure indicator.SyncWriter.write()/writev()returnboolean.Stream.pipeToSync()returnsnumber, described as the total bytes written.
However, pipeToSync() does not currently specify whether a false return means:
- the data was not accepted and
pipeToSync()should throw; - the data was accepted but backpressure was signaled, so bytes should still be counted;
- the data was not accepted, but
pipeToSync()should stop and return the bytes accepted so far.
This matters for byte accounting.
Example
const writer = {
desiredSize: 1,
chunks: [],
write(chunk) {
if (this.chunks.length >= 1) {
return false;
}
this.chunks.push(chunk);
return true;
},
writev(chunks) {
return this.write(chunks[0]);
},
end() {
return this.chunks.reduce((n, chunk) => n + chunk.byteLength, 0);
},
fail() {},
};
const total = Stream.pipeToSync(['a', 'b'], writer, { preventClose: true });If the second write returns false and does not accept the data, should total be 1, or should pipeToSync() throw?
It seems incorrect for pipeToSync() to return 2, because only one byte was accepted by the writer.
Possible behavior
Stream.pipeToSync() could specify:
- If
writer.write()orwriter.writev()returns true, the batch was accepted and its bytes are counted. - If it returns
falseand the writer did not accept the data,pipeToSync()must not count those bytes. - Since
pipeToSync()has no async fallback path, a failed sync write should probably causepipeToSync()to throw. - If any policy allows
falsewhile still accepting data, the docs should explicitly say thatpipeToSync()must count those bytes.
Why
Without this clarification, implementations can silently drop data while still reporting it as written. That makes the number returned by pipeToSync() unreliable.
This also makes it unclear how pipeToSync() should interact with strict backpressure, where a synchronous writer may be unable to accept more data.
Questions
- Should
API.mdspecify thatpipeToSync()throws when a sync write returns false for data that was not accepted? - Should
SyncWriter.write()/writev()distinguish “not accepted” from “accepted but backpressured”, or should false have one consistent meaning forpipeToSync()byte accounting?
Activity
jasnell commentedon May 31, 2026
FWIW, API.md might be out of date. The spec text draft is the source of truth. https://github.com/WinterTC55/iter-streams/blob/main/index.bs
jasnell commentedon May 31, 2026
To answer this, yes. A
falsereturn from a sync operation is a "I couldn't do this for whatever reason". It's intended as a "We can't do this synchronously so you'll probably have to do it asynchronously" ... for a sync pipeline that means the sync pipeline has to error. It cannot proceed.trivikr commentedon May 31, 2026
Fix proposed in #19