- From: Domenic Denicola <notifications@github.com>
- Date: Tue, 21 May 2019 18:53:42 +0000 (UTC)
- To: heycam/webidl <webidl@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <heycam/webidl/pull/720/review/240228152@github.com>
domenic commented on this pull request. Overall LGTM! A few clarity suggestions. > +being iterated over asynchronously to obtain a sequence of values. + +Note: In the ECMAScript language binding, an interface that is asynchronously iterable will have +<code class="idl">entries</code>, <code class="idl">keys</code>, <code class="idl">values</code>, +and {{@@asyncIterator}} properties on its [=interface prototype object=]. + +Prose accompanying an [=interface=] with an [=asynchronously iterable declaration=] must define a +<dfn id="dfn-get-the-next-iteration-result">get the next iteration result</dfn> algorithm. +This algorithm receives a <b>[=this=]</b> value, which is an instance of the [=interface=] that it +is defined for, and the <dfn export>current state</dfn>. +It must return a {{Promise}} that either resolves with undefined – to signal the end of the +iteration – or a tuple with three elements: + +1. a value of the first type given in the declaration; +1. a value of the second type given in the declaration; +1. an opaque value that is passed back to the next invocation of the algorithm, Can we omit the opaque value, and have people just store any relevant state on their `this`? > @@ -11577,6 +11725,45 @@ and the String "<code>values</code>" if the interface has a [=setlike declaration=]. +<h5 id="es-async-iterator">@@asyncIterator</h5> + +If the [=interface=] has an [=asynchronously iterable declaration=], then a property must exist +whose name is the {{@@asyncIterator}} symbol, with attributes +{ \[[Writable]]: <emu-val>true</emu-val>, \[[Enumerable]]: <emu-val>false</emu-val>, \[[Configurable]]: <emu-val>true</emu-val> } +and whose value is a [=function object=]. + +The location of the property is determined as follows: + +* If the interface was declared with the [{{Global}}] [=extended attribute=], + then the property exists on the single object that [=implements=] the interface. +* Otherwise, the property exists solely on the interface’s [=interface prototype object=]. Kind of sad to add to the declaratively-added properties list, but oh well, this is probably easier for now. > +An [=interface=] must not have more than one [=asynchronously iterable declaration=]. +The [=inherited interfaces=] of an [=interface=] with an [=asynchronously iterable declaration=] +must not also have an [=asynchronously iterable declaration=]. +An [=interface=] with an [=asynchronously iterable declaration=] and its [=inherited interfaces=] +must not have a [=maplike declaration=], [=setlike declaration=], or [=iterable declaration=]. + +The following extended attributes are applicable to [=asynchronously iterable declarations=]: +[{{Exposed}}], +[{{SecureContext}}]. + +Issue: these [=extended attributes=] are not currently taken into account. +When they are, the effect will be as you would expect. + +<pre class="grammar" id="prod-AsyncIterable"> + AsyncIterable : + "async_iterable" "<" TypeWithExtendedAttributes "," TypeWithExtendedAttributes ">" ";" Streams will also need some side effects on acquiring the iterator (i.e. calling the function) > +It serves as the prototype for [=default asynchronous iterator objects=] for the interface. + +The \[[Prototype]] [=internal slot=] of an [=asynchronous iterator prototype object=] must be +{{%AsyncIteratorPrototype%}}. + +<div algorithm="to invoke the next property of asynchronous iterators"> + + An [=asynchronous iterator prototype object=] must have a <code class="idl">next</code> data + property with attributes + { \[[Writable]]: <emu-val>true</emu-val>, \[[Enumerable]]: <emu-val>true</emu-val>, \[[Configurable]]: <emu-val>true</emu-val> } + and whose value is a [=built-in function object=] that behaves as follows: + + 1. Let |interface| be the [=interface=] for which the + [=asynchronous iterator prototype object=] exists. + + 1. Let |thisValidationPromiseCapability| be [=!=] [$NewPromiseCapability$]({{%Promise%}}). If we had a PromiseReject abstract op, you could just create and return a new promise inline each time. I guess we'd wait for #490 for that. > </div> The [=class string=] of an [=iterator prototype object=] for a given [=interface=] is the result of concatenating the [=identifier=] of the [=interface=] and the string "<code> Iterator</code>". +<h5 id="es-default-asynchronous-iterator-object">Default asynchronous iterator objects</h5> + +A <dfn id="dfn-default-asynchronous-iterator-object" export>default asynchronous iterator object</dfn> +for a given [=interface=], target and iteration kind is an object whose \[[Prototype]] +[=internal slot=] is the [=asynchronous iterator prototype object=] for the [=interface=]. + +A [=default asynchronous iterator object=] has internal values: + +* its <em>target</em>, which is an object whose values are to be iterated, Can we made these dfns, and cross-link to them? > + 1. If |object|'s ongoing promise is not undefined, then: + 1. Let |afterOngoingPromiseCapability| be [=!=] [$NewPromiseCapability$]({{%Promise%}}). + 1. Let |onFulfilled| be [=!=] [$CreateBuiltinFunction$](|nextSteps|, « »). + 1. Perform [=!=] [$PerformPromiseThen$](|object|'s ongoing promise, |onFulfilled|, + <emu-val>undefined</emu-val>, |afterOngoingPromiseCapability|). + 1. Set |object|'s ongoing promise to |afterOngoingPromiseCapability|.\[[Promise]]. + + 1. Otherwise: + 1. Run |nextSteps| and set |object|'s ongoing promise to the result. + + 1. Return |object|'s ongoing promise. +</div> + +Issue: The [=class string=] of an [=asynchronous iterator prototype object=] for a given +[=interface=] is the result of concatenating the [=identifier=] of the [=interface=] and the string +"<code> Iterator</code>". I guess `" AsyncIterator"`? > +being iterated over asynchronously to obtain a sequence of values. + +Note: In the ECMAScript language binding, an interface that is asynchronously iterable will have +<code class="idl">entries</code>, <code class="idl">keys</code>, <code class="idl">values</code>, +and {{@@asyncIterator}} properties on its [=interface prototype object=]. + +Prose accompanying an [=interface=] with an [=asynchronously iterable declaration=] must define a +<dfn id="dfn-get-the-next-iteration-result">get the next iteration result</dfn> algorithm. +This algorithm receives a <b>[=this=]</b> value, which is an instance of the [=interface=] that it +is defined for, and the <dfn export>current state</dfn>. +It must return a {{Promise}} that either resolves with undefined – to signal the end of the +iteration – or a tuple with three elements: + +1. a value of the first type given in the declaration; +1. a value of the second type given in the declaration; +1. an opaque value that is passed back to the next invocation of the algorithm, Oh, I see we cannot, because it needs to be *per iterator instance*, not *per interface instance*. Can you add an explanation to that effect? -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/heycam/webidl/pull/720#pullrequestreview-240228152
Received on Tuesday, 21 May 2019 18:54:16 UTC