-
Notifications
You must be signed in to change notification settings - Fork 161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for ReadableStream "owning" type #1271
base: main
Are you sure you want to change the base?
Add support for ReadableStream "owning" type #1271
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
General approach looks good. I made some early nitpicks.
We can bikeshed whether type: 'transfer'
or a new optional flag transfer: true
is better. type: 'transfer'
makes it easier to extend TransformStream. transfer: true
maintains the 1:1 relationship between types and controllers.
I went with type: 'transfer' as transfer does not make sense for byob streams. |
A few thoughts:
|
That makes sense to me.
I'm hoping we won't have to add any more controller types, since they are costly in terms of specification and implementation size. |
Agreed.
I would lean towards erroring the stream. Silently losing data is something I want to avoid.
It makes me a bit uncomfortable but I think it's acceptable.
If we add two-argument |
Done.
Yes, I plan to do a separate PR for WritableStream.
I did not add this in this PR but it should be fairly easy to extend it as a follow-up.
|
I think the current version of the PR is ready for reference implementation prototyping. |
These are good points. Let's do it your way. |
I like that a lot! 🙂 I understand that it's a bit out-of-scope for this PR, but I'd love to see that in a follow-up PR. When we do add this, I would suggest we use an options object though, to align with
Yes, please. Each spec change on the Streams standard should be accompanied with new WPT tests, and the reference implementation should pass those new tests. |
Yes, please do. |
OK, I'll start doing it.
|
For testing, it seems we use node.js with WPT and the ref implementation. |
This maybe needs a bit more bikeshedding. Another alternative I can think of is
I really like the syntactic sugar personally, and I think being a different |
I would be most comfortable with requiring However, I recognize it is verbose. So we might want to blaze a new path here and have
You might run up against the limits of the reference implementation here, for which I apologize. It appears that for transferrable streams #1053 we did not make any reference implementation changes and just skipped running the relevant tests against the reference implementation. But that was mostly fine because it didn't change the streams API itself. This change is more intrusive to the streams API so it would be a real shame to let the reference implementation get out of sync. Your main tools for trying to tackle this are:
|
340375a
to
86ff876
Compare
I'll change to this, it is less confusing than
Let's start with this and let's do the shortcut as a follow-up.
ReadableStreamTee would error both branches according the current algorithm. |
d465e3f
to
aacc034
Compare
b52ba6b
to
841d2fd
Compare
PR is ready for review.
|
Co-authored-by: Jan-Ivar Bruaroey <[email protected]>
…ebidl Co-authored-by: Kagami Sascha Rosylight <[email protected]>
b700260
to
eed4579
Compare
eed4579
to
9146111
Compare
PR is green and was approved. Is it ready for being merged? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, should we care about Symbol.dispose
ECMA262 Stage 3 proposal? It looks reasonable for this API to support that, and if so it should be better sooner than later to prevent webcompat issue.
@@ -651,8 +651,15 @@ enum ReadableStreamType { "bytes" }; | |||
<p>For an example of how to set up a readable byte stream, including using the different | |||
controller interface, see [[#example-rbs-push]]. | |||
|
|||
<p>Setting any value other than "{{ReadableStreamType/bytes}}" or undefined will cause the | |||
{{ReadableStream()}} constructor to throw an exception. | |||
<p>Can be set to "<dfn enum-value for="ReadableStreamType">owning</dfn>" to signal that the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<p>Can be set to "<dfn enum-value for="ReadableStreamType">owning</dfn>" to signal that the | |
<p>If set to "<dfn enum-value for="ReadableStreamType">owning</dfn>", it signals that the |
Can this and the above be "If set to"? "Can be set to" made sense when there was only one possibility, but repeating that makes less sense to me.
index.bs
Outdated
{{ReadableStream()}} constructor to throw an exception. | ||
<p>Can be set to "<dfn enum-value for="ReadableStreamType">owning</dfn>" to signal that the | ||
constructed {{ReadableStream}} will own chunks (via transfer or serialization) before enqueuing them. | ||
This ensures that enqueued chunks are not mutable by the source. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This ensures that enqueued chunks are not mutable by the source. | |
This ensures that enqueued chunks are not mutated by the source. |
"mutable by" sounds a bit unnatural.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's change it to cannot be mutated by the source
@@ -2950,13 +2969,21 @@ The following abstract operations support the implementation of the | |||
<div algorithm> | |||
<dfn abstract-op lt="ReadableStreamDefaultControllerEnqueue" | |||
id="readable-stream-default-controller-enqueue">ReadableStreamDefaultControllerEnqueue(|controller|, | |||
|chunk|)</dfn> performs the following steps: | |||
|chunk|, |transferList|)</dfn> performs the following steps: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I understand your comment, I mean Streams have no existing example that receives empty list, while it has several optional parameters in section 9. But either way is fine I guess.
index.bs
Outdated
@@ -5188,7 +5217,7 @@ The following abstract operations support the implementation of the | |||
id="writable-stream-default-controller-close">WritableStreamDefaultControllerClose(|controller|)</dfn> | |||
performs the following steps: | |||
|
|||
1. Perform ! [$EnqueueValueWithSize$](|controller|, [=close sentinel=], 0). | |||
1. Perform ! [$EnqueueValueWithSize$](|controller|, [=close sentinel=], 0, undefined). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this undefined
be « »
for consistency, or vise versa?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right let's do that.
<div algorithm> | ||
<dfn abstract-op lt="StructuredTransferOrClone">StructuredTransferOrClone(|value|, |transferList|)</dfn> | ||
performs the following steps: | ||
1. Let |serialized| be ? [$StructuredSerializeWithTransfer$](|value|, |transferList|). | ||
1. Let |deserialized| be ? [$StructuredDeserializeWithTransfer$](|serialized|, [=the current Realm=]). | ||
1. Return |deserialized|.\[[Deserialized]]. | ||
</div> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Please file an issue to not keep the duplication too long, or let me know so that I can file one)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, with a remaining question about Symbol.dispose.
Oh sorry, I missed the question. |
Is it ready to merge? |
Sorry for the radio silence. I'm trying to catch up on the latest changes, but I've been a bit swamped. |
Any updates on this? We're trying to solve w3c/webtransport#507. |
@ricea Friendly ping. If you could find some time to review this, that'd be appreciated. 😉 |
Overall I'm happy with the general idea but this feels rather heavyweight for the use case. Perhaps For instance, |
@jasnell That would imply that a stream can hold both "owned" and "unowned" chunks at the same time. This would mean a bunch more bookkeeping and passing around extra parameters:
All in all, I think it's easier to have a separate type for owning streams. |
Hmm, how does this interact with transferable streams? Sure, we transfer in
To support this, I think we'll have to store the transfer list alongside each chunk in the queue, so we can re-transfer the chunk later on. 🤔 |
@MattiasBuelens ... sorry I wasn't clear in my comment here #1271 (comment) ... what I was suggesting is ONLY cloning/transferring at the point the chunk is enqueued, forgoing the rest of the proposed "owning" semantics. |
Random thought about being heavyweight, what about: let readable = new ReadableStream({
start(controller) {
// Wrap the chunk with a new interface (name chosen randomly)
controller.enqueue(new Ownership(chunk));
}
});
// ResetQueue checks whether the chunk is Ownership, and if yes,
// run dispose steps of the inner data of Ownership.
readable.cancel();
// Same for WritableStream, it would handle chunks that are Ownership.
readable.pipeTo(writable) |
I also think a stream that only handles owned chunks is simpler to reason about and as powerful. |
I think having a separate representation of ownership instead of changing the internal of streams would be easier; when you pipe you pass the ownership without having to worry about whether the destination is owning stream or not. (But doing so would have bigger effect in the web platform...) |
Implement part of streams-for-raw-video-explainer.md.
(See WHATWG Working Mode: Changes for more details.)
Preview | Diff