Skip to content

Commit 7ab47e9

Browse files
committed
Allow other specifications to create readable byte streams
Closes #1121.
1 parent d0bd912 commit 7ab47e9

File tree

1 file changed

+155
-33
lines changed

1 file changed

+155
-33
lines changed

Diff for: index.bs

+155-33
Original file line numberDiff line numberDiff line change
@@ -1791,18 +1791,7 @@ has the following [=struct/items=]:
17911791
The <dfn id="rbs-controller-byob-request" attribute
17921792
for="ReadableByteStreamController">byobRequest</dfn> getter steps are:
17931793

1794-
1. If [=this=].[=ReadableByteStreamController/[[byobRequest]]=] is null and [=this=].[=ReadableByteStreamController/[[pendingPullIntos]]=] is not [=list/is
1795-
empty|empty=],
1796-
1. Let |firstDescriptor| be [=this=].[=ReadableByteStreamController/[[pendingPullIntos]]=][0].
1797-
1. Let |view| be ! [$Construct$]({{%Uint8Array%}}, « |firstDescriptor|'s [=pull-into
1798-
descriptor/buffer=], |firstDescriptor|'s [=pull-into descriptor/byte offset=] +
1799-
|firstDescriptor|'s [=pull-into descriptor/bytes filled=], |firstDescriptor|'s [=pull-into
1800-
descriptor/byte length=] − |firstDescriptor|'s [=pull-into descriptor/bytes filled=] »).
1801-
1. Let |byobRequest| be a [=new=] {{ReadableStreamBYOBRequest}}.
1802-
1. Set |byobRequest|.[=ReadableStreamBYOBRequest/[[controller]]=] to [=this=].
1803-
1. Set |byobRequest|.[=ReadableStreamBYOBRequest/[[view]]=] to |view|.
1804-
1. Set [=this=].[=ReadableByteStreamController/[[byobRequest]]=] to |byobRequest|.
1805-
1. Return [=this=].[=ReadableByteStreamController/[[byobRequest]]=].
1794+
1. Return ! [$ReadableByteStreamControllerGetBYOBRequest$]([=this=]).
18061795
</div>
18071796

18081797
<div algorithm>
@@ -3044,6 +3033,25 @@ The following abstract operations support the implementation of the
30443033
1. Return |ready|.
30453034
</div>
30463035

3036+
<div algorithm>
3037+
<dfn abstract-op
3038+
lt="ReadableByteStreamControllerGetBYOBRequest">ReadableByteStreamControllerGetBYOBRequest(|controller|)</dfn> performs
3039+
the following steps:
3040+
3041+
1. If |controller|.[=ReadableByteStreamController/[[byobRequest]]=] is null and
3042+
|controller|.[=ReadableByteStreamController/[[pendingPullIntos]]=] is not [=list/is empty|empty=],
3043+
1. Let |firstDescriptor| be |controller|.[=ReadableByteStreamController/[[pendingPullIntos]]=][0].
3044+
1. Let |view| be ! [$Construct$]({{%Uint8Array%}}, « |firstDescriptor|'s [=pull-into
3045+
descriptor/buffer=], |firstDescriptor|'s [=pull-into descriptor/byte offset=] +
3046+
|firstDescriptor|'s [=pull-into descriptor/bytes filled=], |firstDescriptor|'s [=pull-into
3047+
descriptor/byte length=] − |firstDescriptor|'s [=pull-into descriptor/bytes filled=] »).
3048+
1. Let |byobRequest| be a [=new=] {{ReadableStreamBYOBRequest}}.
3049+
1. Set |byobRequest|.[=ReadableStreamBYOBRequest/[[controller]]=] to |controller|.
3050+
1. Set |byobRequest|.[=ReadableStreamBYOBRequest/[[view]]=] to |view|.
3051+
1. Set |controller|.[=ReadableByteStreamController/[[byobRequest]]=] to |byobRequest|.
3052+
1. Return |controller|.[=ReadableByteStreamController/[[byobRequest]]=].
3053+
</div>
3054+
30473055
<div algorithm>
30483056
<dfn abstract-op lt="ReadableByteStreamControllerGetDesiredSize"
30493057
id="readable-byte-stream-controller-get-desired-size">ReadableByteStreamControllerGetDesiredSize(|controller|)</dfn>
@@ -6229,7 +6237,7 @@ to grow organically as needed.
62296237
{{ReadableStream}} object |stream|, given an optional algorithm <dfn export for="ReadableStream/set
62306238
up"><var>pullAlgorithm</var></dfn>, an optional algorithm <dfn export for="ReadableStream/set
62316239
up"><var>cancelAlgorithm</var></dfn>, an optional number <dfn export for="ReadableStream/set
6232-
up"><var>highWaterMark</var></dfn> (default 1), an optional algorithm <dfn export
6240+
up"><var>highWaterMark</var></dfn> (default 1), and an optional algorithm <dfn export
62336241
for="ReadableStream/set up"><var>sizeAlgorithm</var></dfn>, perform the following steps. If
62346242
given, |pullAlgorithm| and |cancelAlgorithm| may return a promise. If given, |sizeAlgorithm| must
62356243
be an algorithm accepting [=chunk=] objects and returning a number; and if given, |highWaterMark|
@@ -6247,42 +6255,155 @@ to grow organically as needed.
62476255
1. If |result| is a {{Promise}}, then return |result|.
62486256
1. Return [=a promise resolved with=] undefined.
62496257
1. If |sizeAlgorithm| was not given, then set it to an algorithm that returns 1.
6250-
1. Perform [$InitializeReadableStream$](|stream|).
6258+
1. Perform ! [$InitializeReadableStream$](|stream|).
62516259
1. Let |controller| be a [=new=] {{ReadableStreamDefaultController}}.
62526260
1. Perform ! [$SetUpReadableStreamDefaultController$](|stream|, |controller|, |startAlgorithm|,
62536261
|pullAlgorithmWrapper|, |cancelAlgorithmWrapper|, |highWaterMark|, |sizeAlgorithm|).
6262+
</div>
62546263

6255-
<div class="example" id="example-set-up-rs">
6256-
Creating a {{ReadableStream}} from other specifications is thus a two-step process, like so:
6264+
<div algorithm="set up a byte-source ReadableStream">
6265+
To <dfn export for="ReadableStream">set up with byte reading support</dfn> a
6266+
newly-[=new|created-via-Web IDL=] {{ReadableStream}} object |stream|, given an optional algorithm
6267+
<dfn export for="ReadableStream/set up with byte reading support"><var>pullAlgorithm</var></dfn>,
6268+
an optional algorithm <dfn export for="ReadableStream/set up with byte reading
6269+
support"><var>cancelAlgorithm</var></dfn>, and an optional number <dfn export
6270+
for="ReadableStream/set up with byte reading support"><var>highWaterMark</var></dfn> (default 0),
6271+
perform the following steps. If given, |pullALgorithm| and |cancelAlgorithm| may return a promise.
6272+
If given, |highWaterMark| must be a non-negative, non-NaN number.
62576273

6258-
1. Let |readableStream| be a [=new=] {{ReadableStream}}.
6259-
1. [=ReadableStream/Set up=] |readableStream| given….
6260-
</div>
6274+
1. Let |startAlgorithm| be an algorithm that returns undefined.
6275+
1. Let |pullAlgorithmWrapper| be an algorithm that runs these steps:
6276+
1. Let |result| be the result of running |pullAlgorithm|, if |pullAlgorithm| was given, or null
6277+
otherwise. If this throws an exception |e|, return [=a promise rejected with=] |e|.
6278+
1. If |result| is a {{Promise}}, then return |result|.
6279+
1. Return [=a promise resolved with=] undefined.
6280+
1. Let |cancelAlgorithmWrapper| be an algorithm that runs these steps:
6281+
1. Let |result| be the result of running |cancelAlgorithm|, if |cancelAlgorithm| was given, or
6282+
null otherwise. If this throws an exception |e|, return [=a promise rejected with=] |e|.
6283+
1. If |result| is a {{Promise}}, then return |result|.
6284+
1. Return [=a promise resolved with=] undefined.
6285+
1. Perform ! [$InitializeReadableStream$](|stream|).
6286+
1. Let |controller| be a [=new=] {{ReadableByteStreamController}}.
6287+
1. Perform ! [$SetUpReadableByteStreamController$](|stream|, |controller|, |startAlgorithm|,
6288+
|pullAlgorithmWrapper|, |cancelAlgorithmWrapper|, |highWaterMark|, undefined).
6289+
</div>
62616290

6262-
<p class="note">Subclasses of {{ReadableStream}} will use the [=ReadableStream/set up=] operation
6263-
directly on the [=this=] value inside their constructor steps.</p>
6291+
<div class="example" id="example-set-up-rs">
6292+
Creating a {{ReadableStream}} from other specifications is thus a two-step process, like so:
6293+
6294+
1. Let |readableStream| be a [=new=] {{ReadableStream}}.
6295+
1. [=ReadableStream/Set up=] |readableStream| given….
62646296
</div>
62656297

6298+
<p class="note">Subclasses of {{ReadableStream}} will use the [=ReadableStream/set up=] or
6299+
[=ReadableStream/set up with byte reading support=] operations directly on the [=this=] value inside
6300+
their constructor steps.
6301+
62666302
<hr>
62676303

62686304
The following algorithms must only be used on {{ReadableStream}} instances initialized via the above
6269-
[=ReadableStream/set up=] algorithm:
6305+
[=ReadableStream/set up=] or [=ReadableStream/set up with byte reading support=] algorithms (not,
6306+
e.g., on web-developer-created instances):
6307+
6308+
<div algorithm>
6309+
A {{ReadableStream}} |stream|'s <dfn export for="ReadableStream">desired size to fill up to the
6310+
high water mark</dfn> is the result of running the following steps:
6311+
6312+
1. If |stream| is not [=ReadableStream/readable=], then return 0.
6313+
1. If |stream|.[=ReadableStream/[[controller]]=] [=implements=] {{ReadableByteStreamController}},
6314+
then return !
6315+
[$ReadableByteStreamControllerGetDesiredSize$](|stream|.[=ReadableStream/[[controller]]=]).
6316+
1. Return !
6317+
[$ReadableStreamDefaultControllerGetDesiredSize$](|stream|.[=ReadableStream/[[controller]]=]).
6318+
</div>
6319+
6320+
<p algorithm>A {{ReadableStream}} <dfn export for="ReadableStream" lt="need more data|needs
6321+
more data">needs more data</dfn> if its [=ReadableStream/desired size to fill up to the high water
6322+
mark=] is greater than zero.
62706323

6271-
<p algorithm>A {{ReadableStream}} |stream| <dfn export for="ReadableStream" lt="need more
6272-
data|needs more data">needs more data</dfn> if |stream| is [=ReadableStream/readable=] and !
6273-
[$ReadableStreamDefaultControllerGetDesiredSize$](|stream|.[=ReadableStream/[[controller]]=])
6274-
returns a positive number.
6324+
<div algorithm>
6325+
To <dfn export for="ReadableStream">close</dfn> a {{ReadableStream}} |stream|:
6326+
6327+
1. If |stream|.[=ReadableStream/[[controller]]=] [=implements=] {{ReadableByteStreamController}},
6328+
then perform !
6329+
[$ReadableByteStreamControllerClose$](|stream|.[=ReadableStream/[[controller]]=]).
6330+
1. Perform ! [$ReadableStreamDefaultControllerClose$](|stream|.[=ReadableStream/[[controller]]=]).
6331+
</div>
6332+
6333+
<div algorithm>
6334+
To <dfn export for="ReadableStream">error</dfn> a {{ReadableStream}} |stream| given a JavaScript
6335+
value |e|:
6336+
6337+
1. If |stream|.[=ReadableStream/[[controller]]=] [=implements=] {{ReadableByteStreamController}},
6338+
then perform ! [$ReadableByteStreamControllerError$](|stream|.[=ReadableStream/[[controller]]=],
6339+
|e|).
6340+
1. Perform ! [$ReadableStreamDefaultControllerError$](|stream|.[=ReadableStream/[[controller]]=],
6341+
|e|).
6342+
</div>
6343+
6344+
<hr>
6345+
6346+
The following algorithm must only be used on {{ReadableStream}} instances initialized via the above
6347+
[=ReadableStream/set up=] algorithm:
62756348

62766349
<p algorithm>To <dfn export for="ReadableStream">enqueue</dfn> the JavaScript value |chunk| into a
62776350
{{ReadableStream}} |stream|, perform !
62786351
[$ReadableStreamDefaultControllerEnqueue$](|stream|.[=ReadableStream/[[controller]]=], |chunk|).
62796352

6280-
<p algorithm>To <dfn export for="ReadableStream">close</dfn> a {{ReadableStream}} |stream|, perform
6281-
! [$ReadableStreamDefaultControllerClose$](|stream|.[=ReadableStream/[[controller]]=]).
6353+
<hr>
6354+
6355+
The following algorithms must only be used on {{ReadableStream}} instances initialized via the above
6356+
[=ReadableStream/set up with byte reading support=] algorithm:
6357+
6358+
<div algorithm>
6359+
The <dfn export for="ReadableStream">current requested number of bytes</dfn> for a
6360+
{{ReadableStream}} |stream| is either a positive integer or null, determined by the following
6361+
steps:
6362+
6363+
1. Assert: |stream|.[=ReadableStream/[[controller]]=] [=implements=]
6364+
{{ReadableByteStreamController}}.
6365+
1. Let |byobRequest| be !
6366+
[$ReadableByteStreamControllerGetBYOBRequest$](|stream|.[=ReadableStream/[[controller]]=]).
6367+
1. If |byobRequest| is null, then return null.
6368+
1. Return |byobRequest|.[=ReadableStreamBYOBRequest/[[view]]=].\[[ByteLength]].
6369+
</div>
6370+
6371+
<!-- TODO: use https://github.com/heycam/webidl/pull/987's "create" and "write" when they land. -->
6372+
<div algorithm>
6373+
To <dfn export for="ReadableStream">enqueue bytes</dfn> into a {{ReadableStream}} |stream| given a
6374+
[=byte sequence=] |bytes|:
6375+
6376+
1. Assert: |stream|.[=ReadableStream/[[controller]]=] [=implements=]
6377+
{{ReadableByteStreamController}}.
6378+
1. Assert: |bytes|'s [=byte sequence/length=] is positive.
6379+
1. Let |byobRequest| be !
6380+
[$ReadableByteStreamControllerGetBYOBRequest$](|stream|.[=ReadableStream/[[controller]]=]).
6381+
1. If |byobRequest| is null, or |bytes|'s [=byte sequence/length=] >
6382+
|byobRequest|.[=ReadableStreamBYOBRequest/[[view]]=].\[[ByteLength]], then:
6383+
1. Let |uint8Array| be a new {{Uint8Array}} wrapping an {{ArrayBuffer}} backed by |bytes|.
6384+
1. Perform ! [$ReadableByteStreamControllerEnqueue$](|stream|.[=ReadableStream/[[controller]]=],
6385+
|uint8Array|).
6386+
1. Otherwise,
6387+
1. Assert: |bytes|'s [=byte sequence/length=]
6388+
|byobRequest|.[=ReadableStreamBYOBRequest/[[view]]=].\[[ByteLength]].
6389+
1. Write |bytes| into
6390+
|byobRequest|.[=ReadableStreamBYOBRequest/[[view]]=].\[[ViewedArrayBuffer]].\[[ArrayBufferData]],
6391+
starting at the byte offset given by
6392+
|byobRequest|.[=ReadableStreamBYOBRequest/[[view]]=].\[[ByteOffset]].
6393+
6394+
Implementations are encouraged to, when possible, do this directly from whatever underlying
6395+
I/O system is producing |bytes|. In this sense the existence of an intermediate |bytes|
6396+
variable might end up as spec fiction, if the underlying I/O system can write directly into the
6397+
backing data block.
6398+
1. Perform ! [$ReadableByteStreamControllerRespond$](|stream|.[=ReadableStream/[[controller]]=],
6399+
|bytes|'s [=byte sequence/length=]).
6400+
</div>
6401+
6402+
When the [=ReadableStream/current requested number of bytes=] is non-null, specifications should
6403+
prefer to use [=ReadableStream/enqueue bytes=] with a [=byte sequence=] whose [=byte
6404+
sequence/length=] equal to (or, if not equal to, less than) that value. Doing so will minimize the
6405+
number of copies involved and will better respect the wishes of stream [=consumers=].
62826406

6283-
<p algorithm>To <dfn export for="ReadableStream">error</dfn> a {{ReadableStream}} |stream| given a
6284-
JavaScript value |e|, perform !
6285-
[$ReadableStreamDefaultControllerError$](|stream|.[=ReadableStream/[[controller]]=], |e|).
62866407

62876408
<h4 id="other-specs-rs-reading">Reading</h4>
62886409

@@ -6339,7 +6460,8 @@ a chunk</dfn> from a {{ReadableStreamDefaultReader}} |reader|, given a [=read re
63396460

63406461
<p class="note">Because |reader| grants exclusive access to its corresponding {{ReadableStream}},
63416462
the actual mechanism of how to read cannot be observed. Implementations could use a more direct
6342-
mechanism if convenient.
6463+
mechanism if convenient, such as acquiring and using a {{ReadableStreamBYOBReader}} instead of a
6464+
{{ReadableStreamDefaultReader}}, or accessing the chunks directly.
63436465
</div>
63446466

63456467
<p algorithm>To <dfn export for="ReadableStreamDefaultReader">release</dfn> a
@@ -6425,7 +6547,7 @@ for="ReadableStream">locked</dfn> if ! [$IsReadableStreamLocked$](|stream|) retu
64256547
1. If |result| is a {{Promise}}, then return |result|.
64266548
1. Return [=a promise resolved with=] undefined.
64276549
1. If |sizeAlgorithm| was not given, then set it to an algorithm that returns 1.
6428-
1. Perform [$InitializeWritableStream$](|stream|).
6550+
1. Perform ! [$InitializeWritableStream$](|stream|).
64296551
1. Let |controller| be a [=new=] {{WritableStreamDefaultController}}.
64306552
1. Perform ! [$SetUpWritableStreamDefaultController$](|stream|, |controller|, |startAlgorithm|,
64316553
|writeAlgorithm|, |closeAlgorithmWrapper|, |abortAlgorithmWrapper|, |highWaterMark|,

0 commit comments

Comments
 (0)