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

Tracking issue for Web IDL async iterator support #1017

Closed
domenic opened this issue Sep 24, 2019 · 2 comments · Fixed by #1035
Closed

Tracking issue for Web IDL async iterator support #1017

domenic opened this issue Sep 24, 2019 · 2 comments · Fixed by #1035

Comments

@domenic
Copy link
Member

domenic commented Sep 24, 2019

A blocker for #963 is expanding Web IDL's async iterator support to be powerful enough for readable streams. The tracking issue over there is whatwg/webidl#800.

On this side I want to record a draft of the algorithms. After the following get done:

then it will look something like this:

Async iterator initialization steps, given a ReadableStream stream, async iterator iterator, and argument options:

  1. Let reader be ? AcquireReadableStreamDefaultReader(stream).
  2. Set iterator.[[reader]] to reader.
  3. Set iterator.[[preventCancel]] to options["preventCancel"].

To get the next iteration result for ReadableStream given the async iterator iterator:

  1. Let promise be a new promise.
  2. Let reader be iterator.[[reader]].
  3. If reader.[[ownerReadableStream]] is undefined, return a promise rejected with a TypeError exception.
  4. Return the result of reacting to ! ReadableStreamDefaultReaderRead(reader) with a fulfillment handler that takes an argument result and performs the following steps:
    1. Assert: Type(result) is Object.
    2. Let done be ! Get(result, "done").
    3. Assert: Type(done) is Boolean.
    4. If done is true,
      1. Perform ! ReadableStreamReaderGenericRelease(reader).
      2. Return undefined.
    5. Let value be ! Get(result, "value").
    6. Return _value.

(The above will become a bit cleaner if we are able to move away from using actual ES objects for read results, which will likely happen as part of the general Web IDL conversion.)

To close the async iterator for ReadableStream given the async iterator iterator and argument value:

  1. Let reader be iterator.[[asyncIteratorReader]].
  2. If reader.[[ownerReadableStream]] is undefined, return a promise rejected with a TypeError exception.
  3. If reader.[[readRequests]] is not empty, return a promise rejected with a TypeError exception.
  4. If iterator.[[preventCancel]] is false, then:
    1. Let result be ! ReadableStreamReaderGenericCancel(reader, value).
    2. Perform ! ReadableStreamReaderGenericRelease(reader).
    3. Return result.
  5. Perform ! ReadableStreamReaderGenericRelease(reader).
  6. Return a promise resolved with undefined.

I think this all works, so that's good.

domenic added a commit that referenced this issue Jun 11, 2020
Closes #963.

Normative changes to widely-implemented features, roughly in order of most disruptive to least-disruptive:

* For the queuing strategy classes, their size and highWaterMark properties are now getters on the prototype, instead of data properties on the prototype and instance (respectively). Closes #1005. In particular this means that attempts to set either of them post-creation will throw a TypeError. Chromium already ships these semantics.

* Functions which take a dictionary no longer accept non-objects.

* For the queuing strategy classes, their highWaterMark property will no longer return a non-number from their highWaterMark properties, if one was passed to the constructor. Instead, NaN will be returned.

* All methods and accessors are now enumerable, per Web IDL defaults, instead of non-enumerable, per ECMAScript defaults.

* All classes are now exposed globally. Formerly, ReadableStreamDefaultReader, ReadableStreamBYOBReader, ReadableStreamDefaultController, ReadableByteStreamController, WritableStreamDefaultWriter, WritableStreamDefaultController, and TransformStreamDefaultController were not exposed. Closes #586.

* All classes now have [Symbol.toStringTag] properties. Closes #952.

* Some functions have changed their length property value.

* Some exceptions are thrown earlier, at argument-conversion time.

* Property lookup in options arguments now happens earlier, at argument-conversion time, and in alphabetical order, per dictionary rules.

Normative changes to unimplemented features:

* ReadableStream's getIterator() method has been renamed to values() as part of adopting Web IDL's infrastructure for async iterators.

* The byobRequest property on ReadableByteStreamController now returns null when there is no BYOB request, instead of returning undefined.

* The view property on ReadableStreamBYOBRequest now returns null when the view cannot be written into, instead of returning undefined.

* Various byte-stream-related APIs that used to specifically prohibit detached buffers now check for zero-length views or buffers, which is a more general category.

* The async iterator's next() and return() methods now behave more like async generators, e.g. returning promises fulfilled with { value: undefined, done: true } after return()ing the iterator, instead of returning a rejected promise.

Editorial changes:

* All APIs are specified to using Web IDL now, instead of using a modified version of the ECMAScript specification conventions. We continue using abstract operations and completion records for now, and we have to drop down to the ECMAScript level in a couple places (notably for dealing with %ObjectPrototype% vs. null-prototype iteration result objects, and transferring array buffers). But overall this removes a lot of type-checking and conversion boilerplate from the specification. Closes #963. Closes #1017. See #1036 for further followup on the iteration result objects.

* Individual abstract operations, constructors, methods, and properties no longer have their own heading. They are instead lumped together in sections. Closes #885.

* The constructors, methods, and properties are now documented in a per-class block, using the usual WHATWG "domintro" style. Closes #907.

* Abstract operations are now consistently alphabetized within their section. Closes #684.

* By using Bikeshed's <div algorithm> feature, we now get automatic identifier highlighting. Closes #687.

* Switched to 100-character line limits, 1-space indents, and omitting end tags, per WHATWG conventions.

* Removed usage of emu-algify in favor of using some more of Bikeshed's built-in features, plus manually annotating a few things.

* Switched to concise Bikeshed linking syntax, e.g. [=term=] and [$AbstractOp$].

* Eliminated a number of utility abstract operations, especially around calling functions, by better using Web IDL.

Other bug fixes:

* Web IDL makes constructor behavior clear, so this closes #965.
@Jack-Works
Copy link

Does it specify as async iterable in the specification? I found there is no @@asyncIterator on the ReadableStreamDefaultReader.prototype

@MattiasBuelens
Copy link
Collaborator

@Jack-Works The async iterator is defined on ReadableStream itself (instead of ReadableStreamDefaultReader), so you should expect to see ReadableStream.prototype[Symbol.asyncIterator]. (Note that the specification does not define the Symbol.asyncIterator method itself, instead it uses an async iterable declaration in its Web IDL. The actual Symbol.asyncIterator method is defined by Web IDL, which internally uses the steps from the "async iteration" section to create and advance the iterator.)

That said, the async iterator feature is fairly new and is not yet implemented in any browser. If you want to use it today, you're probably going to need a polyfill (shameless plug! 😁).

yutakahirano pushed a commit to yutakahirano/streams that referenced this issue Jun 3, 2021
Closes whatwg#963.

Normative changes to widely-implemented features, roughly in order of most disruptive to least-disruptive:

* For the queuing strategy classes, their size and highWaterMark properties are now getters on the prototype, instead of data properties on the prototype and instance (respectively). Closes whatwg#1005. In particular this means that attempts to set either of them post-creation will throw a TypeError. Chromium already ships these semantics.

* Functions which take a dictionary no longer accept non-objects.

* For the queuing strategy classes, their highWaterMark property will no longer return a non-number from their highWaterMark properties, if one was passed to the constructor. Instead, NaN will be returned.

* All methods and accessors are now enumerable, per Web IDL defaults, instead of non-enumerable, per ECMAScript defaults.

* All classes are now exposed globally. Formerly, ReadableStreamDefaultReader, ReadableStreamBYOBReader, ReadableStreamDefaultController, ReadableByteStreamController, WritableStreamDefaultWriter, WritableStreamDefaultController, and TransformStreamDefaultController were not exposed. Closes whatwg#586.

* All classes now have [Symbol.toStringTag] properties. Closes whatwg#952.

* Some functions have changed their length property value.

* Some exceptions are thrown earlier, at argument-conversion time.

* Property lookup in options arguments now happens earlier, at argument-conversion time, and in alphabetical order, per dictionary rules.

Normative changes to unimplemented features:

* ReadableStream's getIterator() method has been renamed to values() as part of adopting Web IDL's infrastructure for async iterators.

* The byobRequest property on ReadableByteStreamController now returns null when there is no BYOB request, instead of returning undefined.

* The view property on ReadableStreamBYOBRequest now returns null when the view cannot be written into, instead of returning undefined.

* Various byte-stream-related APIs that used to specifically prohibit detached buffers now check for zero-length views or buffers, which is a more general category.

* The async iterator's next() and return() methods now behave more like async generators, e.g. returning promises fulfilled with { value: undefined, done: true } after return()ing the iterator, instead of returning a rejected promise.

Editorial changes:

* All APIs are specified to using Web IDL now, instead of using a modified version of the ECMAScript specification conventions. We continue using abstract operations and completion records for now, and we have to drop down to the ECMAScript level in a couple places (notably for dealing with %ObjectPrototype% vs. null-prototype iteration result objects, and transferring array buffers). But overall this removes a lot of type-checking and conversion boilerplate from the specification. Closes whatwg#963. Closes whatwg#1017. See whatwg#1036 for further followup on the iteration result objects.

* Individual abstract operations, constructors, methods, and properties no longer have their own heading. They are instead lumped together in sections. Closes whatwg#885.

* The constructors, methods, and properties are now documented in a per-class block, using the usual WHATWG "domintro" style. Closes whatwg#907.

* Abstract operations are now consistently alphabetized within their section. Closes whatwg#684.

* By using Bikeshed's <div algorithm> feature, we now get automatic identifier highlighting. Closes whatwg#687.

* Switched to 100-character line limits, 1-space indents, and omitting end tags, per WHATWG conventions.

* Removed usage of emu-algify in favor of using some more of Bikeshed's built-in features, plus manually annotating a few things.

* Switched to concise Bikeshed linking syntax, e.g. [=term=] and [$AbstractOp$].

* Eliminated a number of utility abstract operations, especially around calling functions, by better using Web IDL.

Other bug fixes:

* Web IDL makes constructor behavior clear, so this closes whatwg#965.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

3 participants