- From: Domenic Denicola <notifications@github.com>
- Date: Wed, 26 May 2021 11:04:04 -0700
- To: whatwg/streams <streams@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/streams/issues/1128/849000992@github.com>
**Here is the start of a proposal for a seek-based API:**
- Underlying sources/sinks can supply a promise-returning `seek` method. If supplied, then the stream's readers/writers support seeking; otherwise they don't.
- We add `seek()` methods and `canSeek` getters to `ReadableStreamDefaultReader` / `ReadableStreamBYOBReader` / `WritableStreamDefaultWriter`. The `seek()` method forwards to the underlying source/sink after doing some basic argument validation (nonnegative, finite).
- Seeks are queued up (i.e. not yet forwarded to the underlying source/sink) if there are any outstanding read requests or write requests. So e.g. even without `await`s, `writer.write(c1); writer.seek(10); writer.write(c2)` writes `c2` at position 10.
- If you seek while a readable stream's queue is non-empty, the queue gets emptied; all the buffered-up chunks are lost since they're no longer relevant.
In this model, the underlying source/sink is responsible for knowing what seek means, and how it interacts with reads/writes. The expectation is that they implement things so that reads/writes advance the current position, e.g. `writer.seek(10); writer.write(size5Chunk); writer.write(chunk)` writes `chunk` at position 15. But this is not enforced by the streams mechanisms.
**Here is the start of a proposal for an offset-based API:**
- Underlying sources/sinks can set `supportsRandomAccess: true`.
- For such streams, `defaultReader.read({ at })`, `byobReader.read(view, { at })`, and `defaultWriter.write(chunk, { at })` work. (For streams without that boolean set, supplying any value for `at` rejects the promise.) They perform basic validation on `at`.
- We add `reader.supportsAt` and `writer.supportsAt` booleans.
- For writable streams, the underlying sink's `write()` method gets forwarded the `at` value from the `writer.write()` call, which it can use as it sees fit. The existing queuing mechanisms for writes ensure that the stream is never asked to write to two different locations concurrently.
- If no `at` is supplied, we can either omit it from the call to the underlying sink, or we can auto-compute it based on the size of the chunks. Not sure which is best.
- For readable streams, the situation is similar, except with the underlying source's `pull()` instead of the underlying sink's `write()`. The automatic calls to `pull()` which occur based on `highWaterMark` would take place at an auto-computed or omitted `at`, and would not be able to fulfill read requests with mismatching `at`s. The simplest thing to do here might be to empty the queue if a read request comes in with an `at` mismatching what was expected; otherwise the "queue" starts becoming a non-queue.
On balance the offset-based API seems a bit cleaner.
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/streams/issues/1128#issuecomment-849000992
Received on Wednesday, 26 May 2021 18:04:17 UTC