-
Notifications
You must be signed in to change notification settings - Fork 167
Description
(Branched from #379 (comment))
Current situation
Based on the result of the discussion at #363, we've introduced pullInto for ReadableByteStream.
The pull and pullInto in the ReadableByteStream were designed to be invoked in response to read() and read(view) call on the stream. It was temporary design.
Now, in the PR #418, I'm converging ReadableStream and ReadableByteStream. Based on the conclusion on #353, ReadableByteStream has a queue in it as well as ReadableStream. I've also ported the strategy based queuing control mechanism to ReadableByteStream for converging. So, now the 1:1 correspondence between read()/read(view) and pull/pullInto is impossible.
I'm trying to give a reasonable semantics to them.
Role of pullInto
Currently, pullInto has a role of notifying the underlying byte source of the outstanding TypedArray (and region on it) to which the underlying byte source should write generated data. So, whenever:
- a new TypedArray comes
- or the outstanding TypedArray is partially filled
- or filled the outstanding TypedArray but there're more TypedArrays waiting to get filled
the controller should invoke a pullInto.
Unlike pullInto, the signal of pull is just that "the amount in the queue has changed". This is probable by looking at desiredSize
.
Plan taken in the PR
My plan was:
- pull is invoked when:
- read() is called when the queue is empty
- read() is called and it consumed all or part of the queue
- read(view) is called and it consumed all or part of the queue
- pullInto is invoked when:
- read(view) is called when the queue is empty
- read(view) is called and it consumed part of the queue but needs to fill more bytes to return to the consumer with at least 1 element (e.g. 2 byte for Uint16Array) filled.
I planned to do nothing on invocation of controller methods. For example, after the source calls controller.enqueue() in pull (or outside pull), the source can probe how much more data is required to fill the queue by accessing controller.desiredSize. But I realized it's more complicated. After calling enqueue() in response to pullInto (either in pullInto or async to pullInto), it's possible there's more read(view)s are waiting.
It seems some more redesign should be made.
Invocation timing and repetition
ReadableByteStream has a new pull/pullInto invocation scheme.
- pull is required when the current call stack contains any pull/pullInto (check by
_pulling
), schedule by setting_pullAgain
- pull/pullInto invocation code is in (or followed by) a while loop (see
ReadableByteStreamControllerCallPullOrPullIntoRepeatedlyIfNeeded()
) to repeat pull/pullInto invocation synchronously while_pullAgain
is set in the last pull/pullInto - when respond() or enqueue() fail to fill enough bytes (only 1 byte filled in Uint16Array), asynchronously invoke pullInto with the remaining region again.
- this depends on how we resolve the issue above (addition of desiredSize like API?)