From 36de46d092aba474ceb8adb58f212480bab661e1 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Wed, 26 Jun 2019 13:01:00 +0200 Subject: [PATCH 1/3] Editorial: Split out an 'iterator result' algorithm. --- index.bs | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/index.bs b/index.bs index 76894bb9..021b2f38 100644 --- a/index.bs +++ b/index.bs @@ -11783,6 +11783,33 @@ for the interface. The \[[Prototype]] [=internal slot=] of an [=iterator prototype object=] must be {{%IteratorPrototype%}}. +
+ The iterator result for a pair of IDL values |pair| and a kind |kind| is given by the + following steps: + + 1. Let |result| be a value determined by the value of |kind|: +
+ : "key" + :: 1. Let |idlKey| be |pair|’s key. + 1. Let |key| be the result of [=converted to an ECMAScript value|converting=] |idlKey| to an ECMAScript value. + 1. |result| is |key|. + : "value" + :: 1. Let |idlValue| be |pair|’s value. + 1. Let |value| be the result of [=converted to an ECMAScript value|converting=] |idlValue| to an ECMAScript value. + 1. |result| is |value|. + : "key+value" + :: 1. Let |idlKey| be |pair|’s key. + 1. Let |idlValue| be |pair|’s value. + 1. Let |key| be the result of [=converted to an ECMAScript value|converting=] |idlKey| to an ECMAScript value. + 1. Let |value| be the result of [=converted to an ECMAScript value|converting=] |idlValue| to an ECMAScript value. + 1. Let |array| be the result of performing [$ArrayCreate$](2). + 1. Call [$CreateDataProperty$](|array|, "0", |key|). + 1. Call [$CreateDataProperty$](|array|, "1", |value|). + 1. |result| is |array|. +
+ 1. Return [$CreateIterResultObject$](|result|, false). +
+
An [=iterator prototype object=] must have a next data property with attributes @@ -11807,27 +11834,7 @@ must be {{%IteratorPrototype%}}. return CreateIterResultObject(undefined, true). 1. Let |pair| be the entry in |values| at index |index|. 1. Set |object|’s index to |index| + 1. - 1. Let |result| be a value determined by the value of |kind|: -
- : "key" - :: 1. Let |idlKey| be |pair|’s key. - 1. Let |key| be the result of [=converted to an ECMAScript value|converting=] |idlKey| to an ECMAScript value. - 1. |result| is |key|. - : "value" - :: 1. Let |idlValue| be |pair|’s value. - 1. Let |value| be the result of [=converted to an ECMAScript value|converting=] |idlValue| to an ECMAScript value. - 1. |result| is |value|. - : "key+value" - :: 1. Let |idlKey| be |pair|’s key. - 1. Let |idlValue| be |pair|’s value. - 1. Let |key| be the result of [=converted to an ECMAScript value|converting=] |idlKey| to an ECMAScript value. - 1. Let |value| be the result of [=converted to an ECMAScript value|converting=] |idlValue| to an ECMAScript value. - 1. Let |array| be the result of performing ArrayCreate(2). - 1. Call CreateDataProperty(|array|, "0", |key|). - 1. Call CreateDataProperty(|array|, "1", |value|). - 1. |result| is |array|. -
- 1. Return CreateIterResultObject(|result|, false). + 1. Return the [=iterator result=] for |pair| and |kind|.
The [=class string=] of an [=iterator prototype object=] for a given [=interface=] From c026375a5dca7534f265ddc39c24af5249a9e04c Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Wed, 26 Jun 2019 12:59:04 +0200 Subject: [PATCH 2/3] Formalize value pairs. --- index.bs | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/index.bs b/index.bs index 021b2f38..78d57465 100644 --- a/index.bs +++ b/index.bs @@ -3990,8 +3990,15 @@ If a single type parameter is given, then the interface has a values of the specified type. If two type parameters are given, then the interface has a pair iterator and provides -value pairs, where the first value is a key and the second is the -value associated with the key. +[=value pairs=] with the given types. + +A value pair, given a key type and a value type, is a [=/struct=] with two +[=struct/items=]: +1. an [=struct/item=] whose [=struct/name=] is "key", which is referred to as the [=value pair=]'s + key, and whose value is an IDL value of the key type; +1. an [=struct/item=] whose [=struct/name=] is "value", which is referred to as the + [=value pair=]'s value, and whose value is an IDL value of the + value type. A [=value iterator=] must only be declared on an interface @@ -4005,11 +4012,10 @@ defined to iterate over the object’s indexed properties. A [=pair iterator=] must not be declared on an interface that [=support indexed properties|supports indexed properties=]. -Prose accompanying an interface with a -[=pair iterator=] -must define what the list of -value pairs to iterate over -is. + +Prose accompanying an [=interface=] with a [=pair iterator=] must define a [=/list=] of +[=value pairs=] for each instance of the [=interface=], which is the list of +value pairs to iterate over.
@@ -4070,8 +4076,9 @@ that have [=members=] with these names.
- The [=value pairs to iterate over=] are the list of key-value pairs with the key being the username and the - value being the open Session object on the SessionManager + The [=value pairs to iterate over=] are the list of [=value pairs=] with the + [=value pair/key=] being the username and the [=value pair/value=] being the open + Session object on the SessionManager object corresponding to that username, sorted by username.
@@ -11576,8 +11583,8 @@ then the [=function object=] is {{%ArrayProto_forEach%}}. 1. Let |i| be 0. 1. While |i| is less than the length of |pairs|: 1. Let |pair| be the entry in |pairs| at index |i|. - 1. Let |key| be |pair|’s key. - 1. Let |value| be |pair|’s value. + 1. Let |key| be |pair|’s [=value pair/key=]. + 1. Let |value| be |pair|’s [=value pair/value=]. 1. [=Invoke=] |callback| with |thisArg| (or undefined, if the argument was not supplied) as the [=callback this value=] and |value|, |key| and this as its arguments. @@ -11784,22 +11791,22 @@ The \[[Prototype]] [=internal slot=] of an [=iterator prototype object=] must be {{%IteratorPrototype%}}.
- The iterator result for a pair of IDL values |pair| and a kind |kind| is given by the + The iterator result for a [=value pair=] |pair| and a kind |kind| is given by the following steps: 1. Let |result| be a value determined by the value of |kind|:
: "key" - :: 1. Let |idlKey| be |pair|’s key. + :: 1. Let |idlKey| be |pair|’s [=value pair/key=]. 1. Let |key| be the result of [=converted to an ECMAScript value|converting=] |idlKey| to an ECMAScript value. 1. |result| is |key|. : "value" - :: 1. Let |idlValue| be |pair|’s value. + :: 1. Let |idlValue| be |pair|’s [=value pair/value=]. 1. Let |value| be the result of [=converted to an ECMAScript value|converting=] |idlValue| to an ECMAScript value. 1. |result| is |value|. : "key+value" - :: 1. Let |idlKey| be |pair|’s key. - 1. Let |idlValue| be |pair|’s value. + :: 1. Let |idlKey| be |pair|’s [=value pair/key=]. + 1. Let |idlValue| be |pair|’s [=value pair/value=]. 1. Let |key| be the result of [=converted to an ECMAScript value|converting=] |idlKey| to an ECMAScript value. 1. Let |value| be the result of [=converted to an ECMAScript value|converting=] |idlValue| to an ECMAScript value. 1. Let |array| be the result of performing [$ArrayCreate$](2). From 6ac2d3d3eb07b635a7fffe802a1a6a2ca4826f62 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Mon, 29 Apr 2019 12:52:51 +0200 Subject: [PATCH 3/3] Add async_iterable support Fixes #580. --- index.bs | 395 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 385 insertions(+), 10 deletions(-) diff --git a/index.bs b/index.bs index 78d57465..19f55816 100644 --- a/index.bs +++ b/index.bs @@ -83,6 +83,7 @@ urlPrefix: https://tc39.github.io/ecma262/; spec: ECMA-262 text: Promise; url: sec-promise-objects text: Set; url: sec-set-objects text: SharedArrayBuffer; url: sec-sharedarraybuffer-objects + text: %AsyncIteratorPrototype%; url: sec-asynciteratorprototype text: %ErrorPrototype%; url: sec-properties-of-the-error-prototype-object text: %FunctionPrototype%; url: sec-properties-of-the-function-prototype-object text: %IteratorPrototype%; url: sec-%iteratorprototype%-object @@ -106,6 +107,7 @@ urlPrefix: https://tc39.github.io/ecma262/; spec: ECMA-262 text: %PromiseProto_then%; url: sec-promise.prototype.then type: const; for: ECMAScript url: sec-well-known-symbols + text: @@asyncIterator text: @@iterator text: @@toStringTag text: @@unscopables @@ -134,6 +136,7 @@ urlPrefix: https://tc39.github.io/ecma262/; spec: ECMA-262 text: GetFunctionRealm; url: sec-getfunctionrealm text: GetIterator; url: sec-getiterator text: GetMethod; url: sec-getmethod + text: IfAbruptRejectPromise; url: sec-ifabruptrejectpromise text: IsAccessorDescriptor; url: sec-isaccessordescriptor text: IsCallable; url: sec-iscallable text: IsConstructor; url: sec-isconstructor @@ -144,6 +147,7 @@ urlPrefix: https://tc39.github.io/ecma262/; spec: ECMA-262 text: IteratorStep; url: sec-iteratorstep text: IteratorValue; url: sec-iteratorvalue text: NewModuleEnvironment; url: sec-newmoduleenvironment + text: NewPromiseCapability; url: sec-newpromisecapability text: NormalCompletion; url: sec-normalcompletion text: ObjectCreate; url: sec-objectcreate text: OrdinaryDefineOwnProperty; url: sec-ordinarydefineownproperty @@ -1070,6 +1074,7 @@ The qualified name of an [=interface=] |interface| is defined as foll Stringifier StaticMember Iterable + AsyncIterable ReadOnlyMember ReadWriteAttribute ReadWriteMaplike @@ -1196,8 +1201,9 @@ describe the behaviors that can be implemented by an object, as if they were specified on the [=interface=] that [=includes=] them. [=Static attributes=], [=static operations=], [=special operations=] except for [=stringifiers=], and -[=iterable declaration|iterable=], [=maplike declaration|maplike=], and [=setlike declarations=] -cannot appear in [=interface mixin=] declarations. +[=iterable declaration|iterable=], [=asynchronously iterable declaration|asynchronously iterable=], +[=maplike declaration|maplike=], and [=setlike declarations=] cannot appear in [=interface mixin=] +declarations. As with interfaces, the IDL for [=interface mixins=] can be split into multiple parts by using partial interface mixin definitions @@ -1554,6 +1560,13 @@ and summarized in the following informative table: + + [=Asynchronously iterable declarations=] + ● + + + + [=Maplike declarations=] ● @@ -4137,8 +4150,9 @@ must not also have an An interface with an [=iterable declaration=] and its [=inherited interfaces=] must not have a -[=maplike declaration=] or -[=setlike declaration=]. +[=maplike declaration=], +[=setlike declaration=], or +[=asynchronously iterable declaration=]. The following extended attributes are applicable to [=iterable declarations=]: [{{Exposed}}], @@ -4156,6 +4170,144 @@ The following extended attributes are applicable to [=iterable declarations=]: +

Asynchronously iterable declarations

+ +An [=interface=] can be declared to be asynchronously iterable by using an +asynchronously iterable declaration +(matching AsyncIterable) in the body of the +[=interface=]. + +
+    interface interface_identifier {
+      async iterable<key_type, value_type>;
+    };
+
+ +Objects that [=implement=] an [=interface=] that is declared to be asynchronously iterable support +being iterated over asynchronously to obtain a sequence of values. + +Note: In the ECMAScript language binding, an interface that is asynchronously iterable will have +entries, keys, values, +and {{@@asyncIterator}} properties on its [=interface prototype object=]. + +Prose accompanying an [=interface=] with an [=asynchronously iterable declaration=] must define a +get the next iteration result algorithm. +This algorithm receives a [=this=] value, which is an instance of the [=interface=] that it +is defined for, and the current state. +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 as the + [=current state=]. + +The prose may also define asynchronous iterator initialization steps for the +[=interface=] with an [=asynchronously iterable declaration=], which would then be called with the +newly created iterator object. + +[=Interfaces=] with an [=asynchronously iterable declaration=] must not have any +[=interface members=] named "entries", "keys", or "values", +or have any [=inherited interfaces=] that have [=interface members=] with these names. + +
+ + Consider the following interface SessionManager, which allows access + to a number of Session objects keyed by username: + +
+        [Exposed=Window]
+        interface SessionManager {
+          Session getSessionForUser(DOMString username);
+
+          async iterable<DOMString, Session>;
+        };
+
+        [Exposed=Window]
+        interface Session {
+          readonly attribute DOMString username;
+          // ...
+        };
+    
+ + The behavior of the iterator could be defined like so: + +
+ + To [=get the next iteration result=] for SessionManager, run the + following steps: + + 1. Let |promise| be a new promise. + 1. Let |key| be the following value, if it exists, or null otherwise: +
+ : If current state is "not yet started" + :: the smallest username in this's open sessions, in lexicographical order + + : Otherwise + :: the smallest username in this's open sessions that is greater than + current state, in lexicographical order +
+ + Note: current state might no longer be present in the open sessions. + 1. If |key| is null, then: + 1. Resolve |promise| with undefined. + 1. Otherwise: + 1. Let |session| be the Session object corresponding to |key|. + 1. Resolve |promise| with (|username|, |session|, |username|). + 1. Return |promise|. + +
+ + In the ECMAScript language binding, the [=interface prototype object=] for the + SessionManager [=interface=] has a values method that is a + function, which, when invoked, returns an asynchronous iterator object that itself has a + next method that returns the next value to be iterated over. + It has keys and entries methods that iterate over the usernames of + session objects and (username, Session) object pairs, respectively. + It also has a {{@@asyncIterator}} method that allows a SessionManager + to be used in a for await..of loop that has the same value as the + entries method: + +
+        // Get an instance of SessionManager.
+        // Assume that it has sessions for two users, "anna" and "brian".
+        var sm = getSessionManager();
+
+        typeof SessionManager.prototype.values;            // Evaluates to "function"
+        var it = sm.values();                              // values() returns an iterator object
+        typeof it.next;                                    // Evaluates to "function"
+
+        // This loop will log "anna" and then "brian".
+        for await (let username of sm.keys()) {
+          console.log(username);
+        }
+
+        // Yet another way of accomplishing the same.
+        for await (let [username, session] of sm) {
+          console.log(username);
+        }
+    
+
+ +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. + +
+    AsyncIterable :
+        "async" "iterable" "<" TypeWithExtendedAttributes "," TypeWithExtendedAttributes ">" ";"
+
+ +

Maplike declarations

An [=interface=] can be declared to be @@ -4226,6 +4378,7 @@ also have a [=maplike declaration=]. A maplike interface and its [=inherited interfaces=] must not have an [=iterable declaration=], +an [=asynchronously iterable declaration=], a [=setlike declaration=], or an [=indexed property getter=]. @@ -4319,6 +4472,7 @@ also have a [=setlike declaration=]. A setlike interface and its [=inherited interfaces=] must not have an [=iterable declaration=], +an [=asynchronously iterable declaration=], a [=maplike declaration=], or an [=indexed property getter=]. @@ -8797,6 +8951,7 @@ with the same [=identifier=]. There also must not be more than one [=stringifier=] or more than one [=iterable declaration=], +[=asynchronously iterable declaration=], [=maplike declaration=] or [=setlike declaration=] across those interfaces. @@ -11541,6 +11696,48 @@ and the String "values" if the interface has a [=setlike declaration=]. +
@@asyncIterator
+ +If the [=interface=] has an [=asynchronously iterable declaration=], then a property must exist +whose name is the {{@@asyncIterator}} symbol, with attributes +{ \[[Writable]]: true, \[[Enumerable]]: false, \[[Configurable]]: true } +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=]. + +
+ + The [=function object=] is a [=built-in function object=] that, when invoked, must behave as + follows: + + 1. Let |object| be the result of calling [$ToObject$] on the this value. + 1. If |object| [=is a platform object=], then [=perform a security check=], passing: + * the platform object |object|, + * the identifier "@@asyncIterator", and + * the type "method". + 1. Let |interface| be the [=interface=] on which the [=asynchronously iterable declaration=] + is declared. + 1. If |object| does not [=implement=] |interface|, then [=ECMAScript/throw=] a + {{ECMAScript/TypeError}}. + 1. Let |iterator| be a newly created [=default asynchronous iterator object=] for |interface| + with |object| as its [=default asynchronous iterator object/target=] and + "key+value" as its [=default asynchronous iterator object/kind=]. + 1. Run the [=asynchronous iterator initialization steps=] for |interface| with |iterator|, if + any. + 1. Return |iterator|. +
+ +The value of the {{@@asyncIterator}} [=function object=]’s length property +is the Number value 0. + +The value of the {{@@asyncIterator}} [=function object=]’s name property +is the String value "entries". + +
forEach
If the [=interface=] has any of the following: @@ -11645,7 +11842,7 @@ property is the String value "forEach".
entries
-If the [=interface=] has an [=iterable declaration=], +If the [=interface=] has an [=iterable declaration=] or an [=asynchronously iterable declaration=], then an entries data property must exist with attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true } and whose value is a [=function object=]. @@ -11663,10 +11860,12 @@ If the interface has a [=pair iterator=], then the [=function object=] is the value of the {{@@iterator}} property. +If the interface has an [=asynchronously iterable declaration=], then the [=function object=] is +the value of the {{@@asyncIterator}} property.
keys
-If the [=interface=] has an [=iterable declaration=], +If the [=interface=] has an [=iterable declaration=] or an [=asynchronously iterable declaration=], then a keys data property must exist with attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true } and whose value is a [=function object=]. @@ -11692,7 +11891,7 @@ then the [=function object=] is {{%ArrayProto_keys%}}. * the identifier "keys", and * the type "method". 1. Let |interface| be the [=interface=] - on which the [=iterable declaration=] is declared on. + on which the [=iterable declaration=] is declared. 1. If |object| does not [=implement=] |interface|, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. 1. Let |iterator| be a newly created [=default iterator object=] @@ -11700,6 +11899,28 @@ then the [=function object=] is {{%ArrayProto_keys%}}. 1. Return |iterator|.
+
+ + If the interface has an [=asynchronously iterable declaration=], then the method, when invoked, + must behave as follows: + + 1. Let |object| be the result of calling [$ToObject$] on the this value. + 1. If |object| [=is a platform object=], then [=perform a security check=], passing: + * the platform object |object|, + * the identifier "keys", and + * the type "method". + 1. Let |interface| be the [=interface=] on which the [=asynchronously iterable declaration=] + is declared. + 1. If |object| does not [=implement=] |interface|, then [=ECMAScript/throw=] a + {{ECMAScript/TypeError}}. + 1. Let |iterator| be a newly created [=default asynchronous iterator object=] for |interface| + with |object| as its [=default asynchronous iterator object/target=] and + "key" as its [=default asynchronous iterator object/kind=]. + 1. Run the [=asynchronous iterator initialization steps=] for |interface| with |iterator|, if + any. + 1. Return |iterator|. +
+ The value of the [=function object=]’s length property is the Number value 0. The value of the [=function object=]’s name property is the String value "keys". @@ -11707,8 +11928,7 @@ The value of the [=function object=]’s name property
values
-If the [=interface=] has an -[=iterable declaration=], +If the [=interface=] has an [=iterable declaration=] or an [=asynchronously iterable declaration=], then a values data property must exist with attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true } and whose value is a [=function object=]. @@ -11735,7 +11955,7 @@ the value of the {{@@iterator}} property. * the identifier "entries", and * the type "method". 1. Let |interface| be the [=interface=] - on which the [=iterable declaration=] is declared on. + on which the [=iterable declaration=] is declared. 1. If |object| does not [=implement=] |interface|, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. 1. Let |iterator| be a newly created [=default iterator object=] @@ -11743,6 +11963,28 @@ the value of the {{@@iterator}} property. 1. Return |iterator|.
+
+ + If the interface has an [=asynchronously iterable declaration=], then the method, when invoked, + must behave as follows: + + 1. Let |object| be the result of calling [$ToObject$] on the this value. + 1. If |object| [=is a platform object=], then [=perform a security check=], passing: + * the platform object |object|, + * the identifier "entries", and + * the type "method". + 1. Let |interface| be the [=interface=] on which the [=asynchronously iterable declaration=] + is declared. + 1. If |object| does not [=implement=] |interface|, then [=ECMAScript/throw=] a + {{ECMAScript/TypeError}}. + 1. Let |iterator| be a newly created [=default asynchronous iterator object=] for |interface| + with |object| as its [=default asynchronous iterator object/target=] and + "value" as its [=default asynchronous iterator object/kind=]. + 1. Run the [=asynchronous iterator initialization steps=] for |interface| with |iterator|, if + any. + 1. Return |iterator|. +
+ The value of the [=function object=]’s length property is the Number value 0. The value of the [=function object=]’s name property is the String value "values". @@ -11849,6 +12091,139 @@ is the result of concatenating the [=identifier=] of the [=interface=] and the string " Iterator". +
Default asynchronous iterator objects
+ +A default asynchronous iterator +object 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 target, which is an object whose + values are to be iterated, +* its kind, which is the iteration kind, +* its ongoing promise, which is a + {{Promise}} or undefined, +* its state, which is one of + "not yet started" and "finished", or an opaque value used to store the position of the iterator + by the algorithm to [=get the next iteration result=]. + + Note: This value is associated with the iterator instance, rather than the [=interface=] + instance. It is explicitly handled here because the iterator instance is not exposed to the + prose that [=get the next iteration result|gets the next iteration result=]. + +When a [=default asynchronous iterator object=] is first created, its +[=default asynchronous iterator object/state=] is "not yet started". + +Note: [=Default asynchronous iterator objects=] do not have [=class strings=]; when +Object.prototype.toString() is called on a +[=default asynchronous iterator object=] of a given [=interface=], the [=class string=] of the +[=asynchronous iterator prototype object=] of that [=interface=] is used. + + +
Asynchronous iterator prototype object
+ +The +asynchronous iterator prototype object +for a given [=interface=] is an object that exists for every interface that has an +[=asynchronously iterable declaration=]. +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%}}. + +
+ + An [=asynchronous iterator prototype object=] must have a next data + property with attributes { \[[Writable]]: true, + \[[Enumerable]]: true, \[[Configurable]]: true } + 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%}}). + + 1. Let |object| be the result of calling [$ToObject$] on the + this value. + + 1. [$IfAbruptRejectPromise$](|object|, |thisValidationPromiseCapability|). + + 1. If |object| [=is a platform object=], then [=perform a security check=], passing: + * the platform object |object|, + * the identifier "next", and + * the type "method". + + If this threw an exception |e|, then: + 1. Perform [=!=] [$Call$](|thisValidationPromiseCapability|.\[[Reject]], + undefined, « |e| »). + 1. Return |thisValidationPromiseCapability|.\[[Promise]]. + + 1. If |object| is not a [=default asynchronous iterator object=] for |interface|, then: + 1. Issue: [=Realm=] check? + 1. Let |error| be a new {{ECMAScript/TypeError}}. + 1. Perform [=!=] [$Call$](|thisValidationPromiseCapability|.\[[Reject]], + undefined, « |error| »). + 1. Return |thisValidationPromiseCapability|.\[[Promise]]. + + 1. Let |nextSteps| be the following steps: + 1. Let |nextPromiseCapability| be [=!=] [$NewPromiseCapability$]({{%Promise%}}). + 1. Let |oldState| be |object|'s [=default asynchronous iterator object/state=]. + 1. If |oldState| is "finished", then: + 1. Let |result| be [$CreateIterResultObject$](undefined, + true). + 1. Perform [=!=] [$Call$](|nextPromiseCapability|.\[[Resolve]], + undefined, « |result| »). + 1. Return |nextPromiseCapability|.\[[Promise]]. + 1. Let |kind| be |object|'s [=default asynchronous iterator object/kind=]. + 1. Let |nextPromise| be the result of + [=get the next iteration result|getting the next iteration result=] with |object|'s + [=default asynchronous iterator object/target=] as [=this=] and |oldState| as + the [=current state=]. + 1. Let |resolveSteps| be the following steps, given |next|: + 1. Set |object|'s [=default asynchronous iterator object/ongoing promise=] to + undefined. + 1. If |next| is undefined, then: + 1. Set |object|'s [=default asynchronous iterator object/state=] to null. + 1. Let |result| be [$CreateIterResultObject$](undefined, + true). + 1. Perform [=!=] [$Call$](|nextPromiseCapability|.\[[Resolve]], + undefined, « |result| »). + 1. Otherwise: + 1. Let (|key|, |value|, |newState|) be |next|. + 1. Set |object|'s [=default asynchronous iterator object/state=] to |newState|. + 1. Let |result| be the [=iterator result=] for (|key|, |value|) and |kind|. + 1. Perform [=!=] [$Call$](|nextPromiseCapability|.\[[Resolve]], + undefined, « |result| »). + 1. Let |onFulfilled| be [=!=] [$CreateBuiltinFunction$](|resolveSteps|, « »). + 1. Perform [=!=] [$PerformPromiseThen$](|nextPromise|, |onFulfilled|, + undefined, |nextPromiseCapability|). + 1. Return |nextPromiseCapability|.\[[Promise]]. + + 1. Let |promise| be |object|'s [=default asynchronous iterator object/ongoing promise=]. + + 1. If |promise| is not undefined, then: + 1. Let |afterOngoingPromiseCapability| be [=!=] [$NewPromiseCapability$]({{%Promise%}}). + 1. Let |onFulfilled| be [=!=] [$CreateBuiltinFunction$](|nextSteps|, « »). + 1. Perform [=!=] [$PerformPromiseThen$](|promise|, |onFulfilled|, + undefined, |afterOngoingPromiseCapability|). + 1. Set |object|'s [=default asynchronous iterator object/ongoing promise=] to + |afterOngoingPromiseCapability|.\[[Promise]]. + + 1. Otherwise: + 1. Run |nextSteps| and set |object|'s + [=default asynchronous iterator object/ongoing promise=] to the result. + + 1. Return |object|'s [=default asynchronous iterator object/ongoing promise=]. +
+ +Issue: return; throw methods? + +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 +" AsyncIterator". + +

Maplike declarations

Any object that [=implements=] an [=interface=]