whatwg / streams

Streams Standard
https://streams.spec.whatwg.org/
Other
1.34k stars 155 forks source link

reader.cancel([ reason ]) "behaves the same as stream.cancel(reason)" is confusing #1287

Open jedwards1211 opened 1 year ago

jedwards1211 commented 1 year ago

I know it's a non-normative comment, but what https://streams.spec.whatwg.org/#default-reader-prototype says threw me for a loop:

await reader.cancel([ reason ]) If the reader is active, behaves the same as stream.cancel(reason).

Because stream.cancel() rejects if the stream is locked, I incorrectly assumed I would need to

reader.releaseLock()
await reader.cancel()

However, reader.cancel() does reject if the lock has been released; reading the spec, I see that reader.cancel()actually doesn't throw if the stream is locked, unlike stream.cancel(), so the two don't behave the same at all.

It would be closer to the truth to say reader.cancel([ reason ]) behaves like reader.releaseLock() followed by stream.cancel(reason), since that wouldn't reject; but, even this is inaccurate, since according to the spec reader.cancel doesn't release the lock, it just bypasses the IsReadableStreamLocked check altogether.

MattiasBuelens commented 1 year ago

I suppose it would be more accurate to say that stream.cancel() behaves like const reader = stream.getReader(); reader.cancel(); reader.releaseLock(), where reader is a temporary reader. But that still wouldn't be a good explanation.

In essence, you use stream.cancel() to cancel a stream if you haven't locked it. If you have, you should use reader.cancel() instead, which requires that your reader still has the active lock on the stream.