Skip to content
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

FF102 User define byte stream interface - not experimental #16818

Merged
merged 45 commits into from
Jul 12, 2022
Merged
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
41e5efe
FF102 User defined byte streams not experimental
hamishwillee May 31, 2022
b9f5135
ReadableByteStreamController is also not experimental
hamishwillee May 31, 2022
3bbc431
Add respond
hamishwillee May 31, 2022
8d1ef4c
More basic error fixes
hamishwillee Jun 6, 2022
eb663bf
TransformStream - better description
hamishwillee Jun 6, 2022
19b2f17
Minor fixes to byob request
hamishwillee Jun 7, 2022
9527186
ReadableStreamBYOBRequest proper doc
hamishwillee Jun 10, 2022
251b680
Improve ReadableStreamBYOBRequest
hamishwillee Jun 13, 2022
557c1e4
ReadableByteStreamController - update to current understanding
hamishwillee Jun 13, 2022
5816503
getReader() - specify BYOB fail case
hamishwillee Jun 14, 2022
7d1b4ec
getReader throws if controller not implemented
hamishwillee Jun 14, 2022
a56ae7e
BYOB naming is unhelpful - they are bytes streams that support zero copy
hamishwillee Jun 14, 2022
a4c231f
Simplify getreader
hamishwillee Jun 14, 2022
ddbb9cb
BYOB reader top level docs - all reader docs OK but still missing exa…
hamishwillee Jun 14, 2022
ace1be9
All docs for byob controller minus examples
hamishwillee Jun 14, 2022
05261f1
Clarify that default stream can still use an underlying byte source
hamishwillee Jun 14, 2022
99f85d6
inject spurious space for comment
hamishwillee Jun 14, 2022
a155b22
autoAllocateChunkSize must be set for zero byte transfer with default…
hamishwillee Jun 14, 2022
17ddaa1
Add overview part of Using readables streams
hamishwillee Jun 17, 2022
e2d1f66
Minor fixups
hamishwillee Jun 17, 2022
37b9b87
Fix bugs
hamishwillee Jun 17, 2022
326ac85
Fix a few errors
hamishwillee Jun 17, 2022
dc03bd1
Make the source pretend it can write into the buffer provided liek a …
hamishwillee Jun 17, 2022
a54d04a
Examples added
hamishwillee Jul 2, 2022
7473e1b
Add push source example
hamishwillee Jul 3, 2022
af51226
Cross linking/sidebar for new doc
hamishwillee Jul 4, 2022
04624b5
Add button to cancel streaming if desired
hamishwillee Jul 4, 2022
40d3be4
Add code to demo cancelling a stream
hamishwillee Jul 4, 2022
ccaa7f0
ReadableStreamBYOBReader docs
hamishwillee Jul 4, 2022
6380fd8
ReadableStreamBYOBRequest - example updates
hamishwillee Jul 4, 2022
15a82f1
ReadableByteStreamController - add examples
hamishwillee Jul 4, 2022
9a3c403
Apply suggestions from code review - the easy ones
hamishwillee Jul 8, 2022
34d8fb8
Apply suggestions from code review - respondWithNewView
hamishwillee Jul 8, 2022
70bf3bc
Apply suggestions from code review - accept typo and layout fixes
hamishwillee Jul 8, 2022
1fe162b
Update files/en-us/web/api/streams_api/using_readable_byte_streams/in…
hamishwillee Jul 8, 2022
a481bc1
when use respondWithNewView
hamishwillee Jul 8, 2022
80ff70a
Apply suggestions from code review - accept page type suggestions
hamishwillee Jul 11, 2022
0b1de15
Update files/en-us/web/api/readablebytestreamcontroller/error/index.md
hamishwillee Jul 11, 2022
37f4581
Apply suggestions from code review
hamishwillee Jul 11, 2022
237239d
Update files/en-us/web/api/readablestreambyobreader/cancel/index.md
hamishwillee Jul 11, 2022
0dbcc8e
Apply suggestions from code review
hamishwillee Jul 11, 2022
242ed16
Clarify DefaultREader.releaseLock
hamishwillee Jul 11, 2022
c1a8252
Fix typo
hamishwillee Jul 11, 2022
1740118
Update files/en-us/web/api/streams_api/using_readable_byte_streams/in…
hamishwillee Jul 11, 2022
ae1feb2
Apply suggestions from code review
hamishwillee Jul 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,43 @@ slug: Web/API/ReadableByteStreamController/byobRequest
page-type: web-api-instance-property
tags:
- API
- Experimental
- Property
- ReadableByteStreamController
- Reference
- Streams
- byobRequest
browser-compat: api.ReadableByteStreamController.byobRequest
---
{{SeeCompatTable}}{{APIRef("Streams")}}
{{APIRef("Streams")}}

The **`byobRequest`** read-only property of the
{{domxref("ReadableByteStreamController")}} interface returns the current BYOB pull
request, or `undefined` if there are no pending requests.
The **`byobRequest`** read-only property of the {{domxref("ReadableByteStreamController")}} interface returns the current BYOB request, or `null` if there are no pending requests.

An underlying byte source should check this property, and use it to write data to the stream if it exists (rather than using {{domxref("ReadableByteStreamController.enqueue()")}}).
This will result in an efficient zero-byte transfer of the data to the consumer.

## Value

A {{domxref("ReadableStreamBYOBRequest")}} object instance, or `undefined`.
A {{domxref("ReadableStreamBYOBRequest")}} object instance, or `null`.

## Examples

TBD.
The example in [Using readable byte streams > Creating a readable socket push byte stream](/en-US/docs/Web/API/Streams_API/Using_readable_byte_streams#creating_a_readable_socket_push_byte_stream) shows how you use a `byobRequest` to transfer data (if it exists), or otherwise copy the data to the stream's internal queues using {{domxref("ReadableByteStreamController.enqueue()")}}.

The relevant code is reproduced below.
If the `byobRequest` exists, data is read into {{domxref("ReadableStreamBYOBRequest.view","controller.byobRequest.view")}}, and then {{domxref("ReadableStreamBYOBRequest.respond()")}} is called to signal the amount of data that is ready to transfer.

```js
if (controller.byobRequest) {
const v = controller.byobRequest.view;
bytesRead = socket.readInto(v.buffer, v.byteOffset, v.byteLength);
if (bytesRead === 0) {
controller.close();
}
controller.byobRequest.respond(bytesRead);
} else {
// Write to data using enqueue().
}
```

## Specifications

Expand All @@ -33,3 +49,7 @@ TBD.
## Browser compatibility

{{Compat}}

## See also

- [Using readable byte streams](/en-US/docs/Web/API/Streams_API/Using_readable_byte_streams)
34 changes: 25 additions & 9 deletions files/en-us/web/api/readablebytestreamcontroller/close/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ slug: Web/API/ReadableByteStreamController/close
page-type: web-api-instance-method
tags:
- API
- Experimental
- Method
- ReadableByteStreamController
- Reference
- Streams
- close
browser-compat: api.ReadableByteStreamController.close
---
{{SeeCompatTable}}{{APIRef("Streams")}}
{{APIRef("Streams")}}

The **`close()`** method of the
{{domxref("ReadableByteStreamController")}} interface closes the associated stream.
The **`close()`** method of the {{domxref("ReadableByteStreamController")}} interface closes the associated stream.

> **Note:** Readers will still be able to read any previously-enqueued
> chunks from the stream, but once those are read, the stream will become closed.
This might be called by the underlying source when its data source has been exhausted/completed.

> **Note:** Readers will still be able to read any previously-enqueued chunks from the stream, but once those are read, the stream will become closed.
> However if there is an outstanding and partially written {{domxref("ReadableByteStreamController.byobRequest","byobRequest")}} when `close()` is called, the stream will be errored.

## Syntax

Expand All @@ -37,12 +37,24 @@ None ({{jsxref("undefined")}}).
### Exceptions

- {{jsxref("TypeError")}}
- : Thrown if the source object is not a `ReadableByteStreamController`, or the stream
is not readable for some other reason.
- : Thrown if the source object is not a `ReadableByteStreamController`, it is already closed, or the stream is not readable for some other reason.

## Examples

TBD.
The example in [Using readable byte streams > Creating a readable socket push byte stream](/en-US/docs/Web/API/Streams_API/Using_readable_byte_streams#creating_a_readable_socket_push_byte_stream) how we might close the stream when there is no more data.

The relevant code is reproduced below.
This relies on the hypothetical `readInto()` method returning 0 bytes only when there is no more data.

```js
bytesRead = socket.readInto(v.buffer, v.byteOffset, v.byteLength);
if (bytesRead === 0) {
controller.close();
}
```

After calling close, the stream will be closed, and any consumers signalled.
For example if using a {{domxref("ReadableStreamBYOBReader")}} any {{domxref("ReadableStreamBYOBReader.read()","read()")}} requests would resolve with `done: true` and the promise from {{domxref("ReadableStreamBYOBReader.closed")}} would also be resolved.

## Specifications

Expand All @@ -51,3 +63,7 @@ TBD.
## Browser compatibility

{{Compat}}

## See also

- [Using readable byte streams](/en-US/docs/Web/API/Streams_API/Using_readable_byte_streams)
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,33 @@ slug: Web/API/ReadableByteStreamController/desiredSize
page-type: web-api-instance-property
tags:
- API
- Experimental
- Property
- ReadableByteStreamController
- Reference
- Streams
- desiredSize
browser-compat: api.ReadableByteStreamController.desiredSize
---
{{SeeCompatTable}}{{APIRef("Streams")}}
{{APIRef("Streams")}}

The **`desiredSize`** read-only property of the
{{domxref("ReadableByteStreamController")}} interface returns the desired size required
to fill the stream's internal queue.
The **`desiredSize`** read-only property of the {{domxref("ReadableByteStreamController")}} interface returns the number of bytes required to fill the stream's internal queue to its "desired size".

The value is used by the stream to indicate a preferred flow rate to the underlying source.
Sources that support throttling or pausing their inflow of data (not all do!) should control the inflow such that `desiredSize` of the stream buffer is kept positive and as close to zero as possible.

The `desiredSize` is used to apply [backpressure](/en-US/docs/Web/API/Streams_API/Concepts#backpressure) from downstream consumers.

## Value

An integer. Note that this can be negative if the queue is over-full.

The value will be `null` if the stream has errored and `0` if it is closed.

## Examples

TBD.
The [A readable stream with an underlying push source and backpressure support](https://streams.spec.whatwg.org/#example-rs-push-backpressure) example in the spec provides a good example of using `desiredSize` to manually detect when the stream is full and apply backpressure.

While the example uses a default source, the concepts are exactly the same as for readable byte sources.

## Specifications

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,18 @@ slug: Web/API/ReadableByteStreamController/enqueue
page-type: web-api-instance-method
tags:
- API
- Experimental
- Method
- ReadableByteStreamController
- Reference
- Streams
- enqueue
browser-compat: api.ReadableByteStreamController.enqueue
---
{{SeeCompatTable}}{{APIRef("Streams")}}
{{APIRef("Streams")}}

The **`enqueue()`** method of the
{{domxref("ReadableByteStreamController")}} interface enqueues a given chunk in the
associated stream.
The **`enqueue()`** method of the {{domxref("ReadableByteStreamController")}} interface enqueues a given chunk on the associated readable byte stream (the chunk is copied into the stream's internal queues).

This should only be used to transfer data to the queue when {{domxref("ReadableByteStreamController.byobRequest","byobRequest")}} is `null`.

## Syntax

Expand All @@ -36,13 +35,25 @@ None ({{jsxref("undefined")}}).
### Exceptions

- {{jsxref("TypeError")}}
- : Thrown if the source object is not a `ReadableByteStreamController`, or the stream
cannot be read for some other reason, or the chunk is not an object, or the chunk's
internal array buffer is non-existent or detached.
- : Thrown if the source object is not a `ReadableByteStreamController`, or the stream cannot be read for some other reason, or the chunk is not an object, or the chunk's internal array buffer is non-existent, zero-length, or detached.
It is also thrown if the stream has been closed.

## Examples

TBD.
The example in [Using readable byte streams > Creating a readable socket push byte stream](/en-US/docs/Web/API/Streams_API/Using_readable_byte_streams#creating_a_readable_socket_push_byte_stream) shows how you can use `enqueue()` to copy data to the stream if there is no outstanding {{domxref("ReadableByteStreamController.byobRequest","byobRequest")}}.
If there is a `byobRequest` then it should be used!

The code below shows data being read into an `ArrayBuffer` using a "hypothetical" `socket.readInto()` method and then enqueued (but only if data was actually copied):

```js
const buffer = new ArrayBuffer(DEFAULT_CHUNK_SIZE);
bytesRead = socket.readInto(buffer, 0, DEFAULT_CHUNK_SIZE);
if (bytesRead === 0) {
controller.close();
} else {
controller.enqueue(new Uint8Array(buffer, 0, bytesRead));
}
```

## Specifications

Expand All @@ -51,3 +62,7 @@ TBD.
## Browser compatibility

{{Compat}}

## See also

- [Using readable byte streams](/en-US/docs/Web/API/Streams_API/Using_readable_byte_streams)
36 changes: 28 additions & 8 deletions files/en-us/web/api/readablebytestreamcontroller/error/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ page-type: web-api-instance-method
tags:
- API
- Error
- Experimental
- Method
- ReadableByteStreamController
- Reference
- Streams
browser-compat: api.ReadableByteStreamController.error
---
{{SeeCompatTable}}{{APIRef("Streams")}}
{{APIRef("Streams")}}

The **`error()`** method of the
{{domxref("ReadableByteStreamController")}} interface causes any future interactions
with the associated stream to error.
The **`error()`** method of the {{domxref("ReadableByteStreamController")}} interface causes any future interactions with the associated stream to error with the specified reason.

This is commonly called by an underlying source to surface an error from the interface where it gets its data (such as a file-read or socket error).
It can also be called from elsewhere to trigger a stream error, for example if another part of the system that the stream relies on fails.

## Syntax

Expand All @@ -36,12 +36,28 @@ None ({{jsxref("undefined")}}).
### Exceptions

- {{jsxref("TypeError")}}
- : Thrown if the source object is not a `ReadableByteStreamController`, or the stream
is not readable for some other reason.
- : Thrown if the source object is not a `ReadableByteStreamController`, or the stream is not readable for some other reason.

## Examples

TBD.
The example in [Using readable byte streams > Creating a readable socket push byte stream](/en-US/docs/Web/API/Streams_API/Using_readable_byte_streams#creating_a_readable_socket_push_byte_stream) shows how you might use `error()` to manually trigger a stream error if another part of the system it relies on fails.

Specifically, the underlying source `start()` method calls `readRepeatedly()` to perform all setup operations and to make a request for data.
This returns a promise.
If there are any errors thrown when reading the data they will be caught by the chained `catch()` function.
In `catch()` we then call `error()` on the controller, passing the reason from the underlying source.

```js
start(controller) {
readRepeatedly().catch((e) => controller.error(e));
}

function readRepeatedly() {
return socket.select2().then(() => {
// ...
}
}
```

## Specifications

Expand All @@ -50,3 +66,7 @@ TBD.
## Browser compatibility

{{Compat}}

## See also

- [Using readable byte streams](/en-US/docs/Web/API/Streams_API/Using_readable_byte_streams)
36 changes: 30 additions & 6 deletions files/en-us/web/api/readablebytestreamcontroller/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,44 @@ slug: Web/API/ReadableByteStreamController
page-type: web-api-interface
tags:
- API
- Experimental
- Fetch
- Interface
- ReadableByteStreamController
- Reference
- Streams
browser-compat: api.ReadableByteStreamController
---
{{APIRef("Streams")}}{{SeeCompatTable}}
{{APIRef("Streams")}}

The **`ReadableByteStreamController`** interface of the [Streams API](/en-US/docs/Web/API/Streams_API) represents a controller allowing control of a {{domxref("ReadableStream")}}'s state and internal queue. Byte stream controllers are for byte streams.
The **`ReadableByteStreamController`** interface of the [Streams API](/en-US/docs/Web/API/Streams_API) represents a controller for a [readable byte stream](/en-US/docs/Web/API/Streams_API/Using_readable_byte_streams).
It allows control of the state and internal queue of a {{domxref("ReadableStream")}} with an underlying byte source, and enables efficient zero-copy transfer of data from the underlying source to a consumer when the stream's internal queue is empty.

An instance of this controller type is created if an `underlyingSource` object with the property `type="bytes"` is passed as an argument to the [`ReadableStream()` constructor](/en-US/docs/Web/API/ReadableStream/ReadableStream#type).
The `underlyingSource` object may also define [`start()`](/en-US/docs/Web/API/ReadableStream/ReadableStream#start) and [`pull()`](/en-US/docs/Web/API/ReadableStream/ReadableStream#pull) callback functions.
These are called with the controller as a parameter, in order to setup the underlying source, and request data when needed.

The underlying source uses the controller to supply data to the stream via its [`byobRequest`](#readablebytestreamcontroller.byobrequest) property or [`enqueue()`](#readablebytestreamcontroller.enqueue) method.
[`byobRequest`](#readablebytestreamcontroller.byobrequest) is a {{domxref("ReadableStreamBYOBRequest")}} object that represents a pending request from a consumer to make a zero-copy transfer of data direct to a consumer.
`byobRequest` must be used to copy data if it exists (do not use `enqueue()` in this case)!
If the underlying source needs to pass data to the stream and `byobRequest` is `null` then the source can call [`enqueue()`](#readablebytestreamcontroller.enqueue) to add the data to the stream's internal queues.

Note that the [`byobRequest`](#readablebytestreamcontroller.byobrequest) is only created in "BYOB mode" when there is a request from a reader and the stream's internal queue is empty.
"BYOB mode" is enabled when using a {{domxref("ReadableStreamBYOBReader")}} (typically constructed by calling {{domxref("ReadableStream.getReader()")}} with the argument `{ mode: 'byob' }`).
It is also enabled when using a default reader and [`autoAllocateChunkSize`](/en-US/docs/Web/API/ReadableStream/ReadableStream#autoallocatechunksize) is specified in the [`ReadableController()` constructor](/en-US/docs/Web/API/ReadableStream/ReadableStream#autoallocatechunksize).

An underlying byte source can also use the controller to [`close()`](#readablebytestreamcontroller.close) the stream when all the data has been sent and report errors from the underlying source using [`error()`](#readablebytestreamcontroller.error).
The controller's [`desiredSize`](#readablebytestreamcontroller.desiredsize) property is used to apply "backpressure", informing the underlying source of the size of the internal queue (small values indicate that the queue is filling up, hinting to the underlying source that it is be desirable to pause or throttle the inflow).

Note that even though the controller is primarily used by the underlying byte source, there is no reason it cannot be stored used by other parts of the system to signal the stream.

## Constructor

None. `ReadableByteStreamController` instances are created automatically during `ReadableStream` construction.
None. `ReadableByteStreamController` instances are automatically created if an `underlyingSource` with the property `type="bytes"` is passed to the [`ReadableStream()` constructor](/en-US/docs/Web/API/ReadableStream/ReadableStream#type).

## Properties

- {{domxref("ReadableByteStreamController.byobRequest")}} {{readonlyInline}}
- : Returns the current BYOB pull request.
- : Returns the current BYOB pull request, or `null` if there no outstanding request.
- {{domxref("ReadableByteStreamController.desiredSize")}} {{readonlyInline}}
- : Returns the desired size required to fill the stream's internal queue.

Expand All @@ -38,7 +56,9 @@ None. `ReadableByteStreamController` instances are created automatically during

## Examples

TBD.
The controller is used by an underlying source to transfer or enqueue data, to signal that the stream has no more data (has closed) or has errored. It is also used to signal the underlying source from "upstream" of the desired data rate, using {{domxref("ReadableByteStreamController.desiredSize","desiredSize")}}.

The example in [Using readable byte streams](/en-US/docs/Web/API/Streams_API/Using_readable_byte_streams), in particular [Creating a readable socket push byte stream](/en-US/docs/Web/API/Streams_API/Using_readable_byte_streams#creating_a_readable_socket_push_byte_stream), show most of these cases.

## Specifications

Expand All @@ -47,3 +67,7 @@ TBD.
## Browser compatibility

{{Compat}}

## See also

- [Using readable byte streams](/en-US/docs/Web/API/Streams_API/Using_readable_byte_streams)
20 changes: 12 additions & 8 deletions files/en-us/web/api/readablestream/getreader/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,22 @@ While the stream is locked, no other reader can be acquired until this one is re

```js
getReader()
getReader(mode)
getReader(options)
```

### Parameters

- `mode` {{optional_inline}}
- `options` {{optional_inline}}

- : An object containing a property `mode`, specifying the type of reader to create.
Values can be:
- : An object containing the following properties:

- `"byob"`, which results in a {{domxref("ReadableStreamBYOBReader")}} being created that can read readable byte streams (i.e. can handle "bring your own buffer" reading).
- `undefined` (or not specified at all — this is the default), which results in a {{domxref("ReadableStreamDefaultReader")}} being created that can read individual chunks from a stream.
- `mode` {{optional_inline}}

- : An property that specifies the type of reader to create.
Values can be:

- `"byob"`, which results in a {{domxref("ReadableStreamBYOBReader")}} being created that can read readable byte streams (streams that support zero-copy transfer from an underlying byte source to the reader when internal stream buffers are empty).
- `undefined` (or not specified at all — this is the default), which results in a {{domxref("ReadableStreamDefaultReader")}} being created that can read individual chunks from a stream.

### Return value

Expand All @@ -42,8 +46,8 @@ A {{domxref("ReadableStreamDefaultReader")}} or {{domxref("ReadableStreamBYOBRea
- {{jsxref("RangeError")}}
- : Thrown if the provided mode value is not `"byob"` or `undefined`.
- {{jsxref("TypeError")}}
- : Thrown if the stream you are trying to create a reader for is not a
{{domxref("ReadableStream")}}.
- : Thrown if the stream you are trying to create a reader for is already locked, or not a {{domxref("ReadableStream")}}.
This is also thrown if a BYOB reader is requested and the stream controller is not a {{domxref("ReadableByteStreamController")}} (the stream was not [constructed](/en-US/docs/Web/API/ReadableStream/ReadableStream) as an underlying source with [`type="bytes"`](/en-US/docs/Web/API/ReadableStream/ReadableStream#type)).

## Examples

Expand Down
Loading