-
Notifications
You must be signed in to change notification settings - Fork 160
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
Standard text for TransformStream #811
Conversation
This is very incomplete. I created this PR to permit early commenting. |
cb88cab
to
9b31882
Compare
40f9ef2
to
e8453fc
Compare
This is now complete and ready for review. If possible, I would like both @tyoshino and @domenic to review the formatted text. Almost all the changes are in the transform streams model section and the Transform Streams section. All of the issues I've fixed in my own checks have been visible in the formatted version. I think we need one volunteer to pick through all the new markup for errors, and another volunteer to double-check that the steps in the text match the steps in the reference implementation. I think it's best to coordinate so we don't duplicate this grungy work. |
I can certainly volunteer for markup review for now. |
I did a first pass focused on non-normative text. Of note, I tried to eliminate talking about "output" and "input", given the confusion in #174. Instead I introduced "writable side" and "readable side" and tried to use those as much as possible. I think we should also add some nice examples to the appendix. Ideas:
I'll try to do more review tomorrow. |
writable.close(); | ||
</code></pre> | ||
|
||
Another use of identity transform streams is to add additional buffering to a <a>pipe</a>. In this example we add |
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.
Is it possible to have a separate id for the buffering example without disrupting the readability of this section too much?
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.
Sure, we can just make it another <div>
, not a big deal I think.
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.
+1
index.bs
Outdated
append a suffix to the output data. If this process is asynchronous, it can return a promise | ||
to signal success or failure. On success, the {{readable}} side will be closed. | ||
<li><p><code>start(controller)</code> is called immediately, and is typically used to enqueue prefix <a>chunks</a> | ||
that appear in the <a>readable side</a> but doesn't depend on any writes to the <a>writable side</a>. If this |
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.
"... don't depend on ..."
"appear" is awkward here. Maybe "will be read from"?
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.
Done.
98157cd lgtm. Explicitly defining "readable side" and "writable side" solves a lot of the wording problems I struggled with. |
5ebb666
to
d054b80
Compare
index.bs
Outdated
<h3 id="ts-intro">Using Transform Streams</h3> | ||
|
||
<div class="example" id="example-basic-pipe-through"> | ||
The natural way to use a transform stream is place it in a <a lt="piping">pipe</a> between a <a>readable stream</a> |
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.
place -> placing?
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.
We could use "by placing it" or "to place it". I think I prefer "to place it".
writable.close(); | ||
</code></pre> | ||
|
||
Another use of identity transform streams is to add additional buffering to a <a>pipe</a>. In this example we add |
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.
+1
index.bs
Outdated
1. If _readableType_ is not *undefined*, throw a *RangeError* exception. | ||
1. Let _writableType_ be ? GetV(_transformer_, `"writableType"`). | ||
1. If _writableType_ is not *undefined*, throw a *RangeError* exception. | ||
1. Let _controller_ be ? Construct(`<a idl>TransformStreamDefaultController</a>`, « *this* »). |
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.
extra space between be and ?
1. Perform ! CreateDataProperty(_readableStrategy_, `"highWaterMark"`, _highWaterMark_). | ||
1. Set *this*.[[readable]] to ? Construct(`<a idl>ReadableStream</a>`, « _source_, _readableStrategy_ »). | ||
1. Let _sink_ be ! Construct(`<a idl>TransformStreamDefaultSink</a>`, « *this*, _startPromise_ »). | ||
1. Set *this*.[[writable]] to ? Construct(`<a idl>WritableStream</a>`, « _sink_, _writableStrategy_ »). |
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.
missing writableStrategy creation
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.
It comes directly from the constructor arguments. I can add a note to explain the asymmetry between readableStrategy and writableStrategy.
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.
Oops, sorry. I should've checked the arguments list.
Yeah, it might be helpful, thought it's just because I'm not catching up with the changes. Is fd17cf0 the only background of the asymmetry?
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.
Yes, and issue #777 which discusses it.
I made some fixes in 4d2d14e which is on this branch but inexplicably missing from this PR. If it doesn't show up by tomorrow I will do a rebase to force it. |
OK, going to work on checking that the steps match up now. |
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.
Reviewed everything. Pretty happy.
I left one comment about comments being translated to notes, and I think it applies more generally. I'd be happy to add more notes to the algorithms in the same place you added comments in the .js file. I wish we'd done that with the other streams, but since we have that here, it'd be nice.
index.bs
Outdated
1. Perform ! WritableStreamDefaultControllerErrorIfNeeded(_stream_.[[writable]].[[writableStreamController]], _e_). | ||
1. If _stream_.[[readable]].[[state]] is `"readable"`, perform ! | ||
ReadableStreamDefaultControllerError(_stream_.[[readable]].[[readableStreamController]], _e_). | ||
1. If _stream_.[[backpressure]] is *true*, perform ! TransformStreamSetBackpressure(_stream_, *false*). |
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 has a comment in the source that seems like it might be useful to include in the standard as a note. However it references things I'm not sure about, like write()/pull()/enqueue(). Are those on the transform stream source/sink? Maybe it can be rephrased to capture the important points without the details; not sure.
index.bs
Outdated
<h5 id="ts-default-source-cancel" method for="TransformStreamDefaultSource">cancel(<var>reason</var>)</h5> | ||
|
||
<emu-alg> | ||
1. Perform ! TransformStreamError(*this*.[[ownerTransformStream]], _reason_). |
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.
Just noticing this... is this correct behavior? I'd have thought it'd be more like terminate than error.
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.
It actually does behave like terminate, because the readable side is already closed when cancel() is called. I added a note to make this clearer.
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.
Is there a reason to call TransformStreamError instead of TransformStreamDefaultControllerTerminate? I guess layering, hmm... seems to argue for factoring out a TransformStreamTerminate, if I am understanding correctly.
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.
We'd end up with TypeError('TransformStream terminated') as the storedError in the writable. This seems less desirable to me than retaining whatever was passed to cancel().
However... maybe factoring out the "bottom half" of TransformStreamDefaultControllerTerminate and TransformStreamError is the way to go. I will try it.
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.
I made factored out a new abstract op named "TransformStreamErrorWritableAndUnblockWrite". PTAL.
I reviewed the comments in the reference implementation to see if any would be useful as notes in the standard. I added a couple more notes. To be honest, I feel that inline notes can make the algorithm harder to follow. It would be nice to have a separate non-normative "algorithm overview" section where we explain how it works. But we don't have anything like that for ReadableStream and WritableStream (and it might be prohibitively complicated to have an up-to-date explanation for those). Anyway, I believe that implementers will find out how it works in the process of implementing it. Ordinary web developers don't need to know why it works. The mental model of "transform is called when there is no backpressure" is super-easy to understand and the subtleties involved in delivering that are not their problem. |
Made some tweaks, ready to merge when you are! |
1a26588 lgtm |
Add algorithm steps for TransformStreamDefaultController constructor, desiredSize getter, enqueue() method, TransformStreamDefaultControllerEnqueue abstract operation. For TransformStreamDefaultSink, the constructor, start(), write(), abort() and close() methods.
Also fix a linking error in TransformStreamDefaultControllerEnqueue. Now the only algorithms remaining to be done are those that are expected to change.
TransformStreamDefaultSinkInvokeTransform and TransformStreamDefaultSinkTransform.
- Linkify some things that were not linkified. - Add extension points for readableType / writableType. - Note what the readable / writable accessors are for to make linking to - them more helpful. - Correctly indicate the throwyness of TransformStreamDefaultControllerEnqueue - Add notes for the TSDefaultController abstract ops that intended to be used from other specifications. - Use GetV to access object properties.
Previously the TransformStream constructor used readableStrategy["foo"] syntax. Use Set() instead.
Use CreateDataProperty() instead of Set(). Make the method for constructing the object more concrete.
Also - markup writableStrategy as a <var> in the TransformStream constructor header - add a missing "to" in example-basic-pipe-through - remove an excess space from the TransformStream constructor algorithm steps
All add a comment to the reference implementation to note the same thing.
Explain the reason for calling TransformStreamSetBackpressure there.
Factor out TransformStreamErrorWritableAndUnblockWrite from TransformStreamError and TransformStreamDefaultControllerTerminate. Use the new operation in TransformStreamDefaultSource cancel() to make the semantics clearer.
Explain why the constructor initialises the [[backpressure]] slot to *undefined* and note that implementations can do something else. Also add a note that TransformStreamError can be used even when an error has already occurred. Also change TransformStreamDefaultControllerEnqueue to call TransformStreamErrorWritableAndUnblockWrite rather than TransformStreamError when ReadableStreamDefaultControllerEnqueue throws, since we know that the readable side will already be errored in that case.
It should have been _enqueueValue_.[[Value]]. Also correct `_chunk_` to `_e_` in the arguments to TransformStreamDefaultControllerError and eliminate a pointless local from that operation.
Move the initialisations of [[transformStreamController]] and [[backpressure]] to right before they are needed. This should make the reasons for how they are initialised more obvious.
1a26588
to
cfd14a0
Compare
Rebased. |
I will go ahead and land this since @tyoshino is busy. We can always fix any issues he finds later. |
|
||
enqueue(chunk) | ||
error(reason) | ||
terminate() |
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.
I find it interesting that we have cancel()
, terminate()
, and close()
on different types of streams.
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.
Yes, they all have different semantics. So based on the principle of "different things should look different", we use different names for them. See #774 for the discussion where we added terminate()
. The difference between cancel()
and close()
is mentioned in the FAQ: https://github.com/whatwg/streams/blob/master/FAQ.md#why-dont-errors-that-occur-while-cancelling-put-the-readable-stream-in-an-error-state
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.
That's awesome. Definitely a lesson in there for me. Thanks, @ricea.
I'm building a demo of this as soon as support lands in Canary/any nightly of any browser. |
Add text to the standard for TransformStream.
Preview | Diff