StreamAPI requires properties to determine wether stream is alive, closed or disturbed

Proposal

  1. Add methods or properties to determine wether Stream instance is readable or writable.
  2. Add method or property to determine what amount of data has already written to/read from the stream.
  3. Add method or property to determine if Stream is canceled.

Explanation

Today ReadableStream and WritableStream classes have no properties or methods to determine are they alive, closed or disturbed on JS side. I found some opinions of core members that this behavior is unnecessary. In the same time it is using by browser itself for example in Response constructor. And I don’t see any reasonable explanation for this .

Such behavior makes impossible to implement some APIs which works with streams. Because a lack of this flags makes code unreliable and unpredictable.

I’m working on a web server compatible with WebAPI and it’s near to impossible to create Response object which could receive ReadableStream as constructor argument and to throw an exception if it was disturbed.

There is one hack which can be used to check if stream was disturbed by using Response’s constructor:

var stream = new ReadableStream()
stream.cancel()

try {
  new Response(stream);
} catch (err) {
 // Is disturbed
}

But I think it should be fixed in specification.

I think it might be best to take this one directly to the WHATWG’s repository. @domenic, agree? Or do you want to discuss here?

When a ReadableStream is read there are value and done. There is also ReadableStreamDefaultReader.closed property which is a Promise. What methods are you proposing?

There should be boolean flags ‘disturbed’, ‘opened’ (due to ‘closed’ is taken), not a promises. Because you couldn’t use promises in constructors. Requirement of such flags is proven by Response implementation, which relies on them.

Also, If you rely on value and done, then you should to disturb the stream and thus couldn’t use it in Response. Property closed is blocking execution flow and could create infinite Promise if the stream never closes.

@marcosc I saw Domenic asked to resign him from TC39 proposals. Seems like it’s stuck. How could we move this forward?

Please file these as separate issues at https://github.com/whatwg/streams/issues. Streams standard contributors are not necessarily going to be looking here.

Proposal 2. already exists as https://github.com/whatwg/streams/issues/367. It’s closed, but you could request a re-examination.

It’s unfortunate that that there’s no way to implement the Response constructor from JavaScript because the [[disturbed]] slot is not exposed. I have mixed feelings about exposing it because it’s unfortunate that it exists and I don’t want to encourage increased usage. I recommend filing this as a separate issue anyway.

My personal opinions on each proposal:

  1. Add methods or properties to determine wether Stream instance is readable or writable.

Problematic because there’s no guarantee that the streams will still be readable when all microtasks have run.

  1. Add method or property to determine what amount of data has already written to/read from the stream.

Problematic because it would add extra overhead.

  1. Add method or property to determine if Stream is canceled.

Has similar problems to 1., but is a bit better because “canceled” is a terminal state and so there’s no way it’s going to become uncanceled again.

Thanks for your reply. But I have strong concerns about this. Lack of control leads to uncertain solutions and tricky logic to avoid race conditions. While stream isn’t cancelled or closed, even single byte read could lead us to invalid result on the processing steps. If we want to summarize values from a stream we would get invalid sum if any value already has been taken from it. If we parse HTTP request we would generate Parsing error, even if there is none. And the isDisturbed flag in C++ code is a consequence of this lack of control.

Stream related race conditions should be solved with exclusive borrowing, that getReader() do and flags. Here it is a logic of such behavior:

  1. Check stream reading has been initiated or stream is cancelled.
  2. Check stream has not been borrowed with Stream#locked.
  3. Borrow stream with Stream#getReader().
  4. Initiate reading.

After this steps possible states are: a) start chunk received b) stream cancelled. In the current form we have three states: a1) start chunk received, a2) intermediate chunk received and b) stream cancelled, and to decide wether it is a1 or a2 is just impossible, thus we stuck in a superposition.

The situation when streams become free flowing in the memory without being borrowed by anyone is not a proper case of stream usage. It’s a fault state which should throw an error and shouldn’t be decided as a correct work.

Thanks, again for response and suggestions.

Apologies for the delay. Rereading, it still appears that these issues need to be taken up in the Streams repository itself (as @ricea suggested).

Thanks. I had already opened an issue (#1025).

What should I do to promote it better, maybe notify someone?

I don’t think you need to do much. The right people are all notified - just be mindful that it can take a while.