Stage 2 Draft / April 17, 2024

Joint Iteration

1 Iterator.zipToArrays ( iterables [ , options ] )

This method performs the following steps when called:

  1. If iterables is not an Object, throw a TypeError exception.
  2. Set options to ? GetOptionsObject(options).
  3. Let longest be ? GetOption(options, "longest", boolean, empty, false).
  4. Let strict be ? GetOption(options, "strict", boolean, empty, false).
  5. If longest is true and strict is true, throw a TypeError exception.
  6. Let mode be shortest.
  7. Let paddingOption be undefined.
  8. If longest is true, then
    1. Set mode to longest.
    2. Set paddingOption to ? Get(options, "padding").
  9. If strict is true, set mode to strict.
  10. Let iters be a new empty List.
  11. Let padding be a new empty List.
  12. Let inputIter be ? GetIterator(iterables, sync).
  13. Let next be not-started.
  14. Repeat, while next is not done,
    1. Set next to Completion(IteratorStepValue(inputIter)).
    2. IfAbruptCloseIterators(next, iters).
    3. If next is not done, then
      1. Let iter be Completion(GetIteratorFlattenable(next, iterate-strings)).
      2. IfAbruptCloseIterators(iter, the list-concatenation of « inputIter » and iters).
      3. Append iter to iters.
  15. Let iterCount be the number of elements in iters.
  16. If mode is longest, then
    1. If paddingOption is undefined, then
      1. Perform the following steps iterCount times:
        1. Append undefined to padding.
    2. Else,
      1. Let paddingIter be Completion(GetIterator(paddingOption, sync)).
      2. IfAbruptCloseIterators(paddingIter, iters).
      3. Let usingIterator be true.
      4. Perform the following steps iterCount times:
        1. If usingIterator is true, then
          1. Set next to Completion(IteratorStepValue(paddingIter)).
          2. IfAbruptCloseIterators(next, iters).
          3. If next is done, then
            1. Set usingIterator to false.
          4. Else,
            1. Append next to padding.
        2. If usingIterator is false, append undefined to padding.
      5. If usingIterator is true, then
        1. Let completion be Completion(IteratorClose(paddingIter, NormalCompletion(unused))).
        2. IfAbruptCloseIterators(completion, iters).
  17. Let finishResults be a new Abstract Closure with parameters (results) that captures nothing and performs the following steps when called:
    1. Return CreateArrayFromList(results).
  18. Return IteratorZipCore(iters, mode, padding, finishResults).

2 Iterator.zipToObjects ( iterables [ , options ] )

This method performs the following steps when called:

  1. If iterables is not an Object, throw a TypeError exception.
  2. Set options to ? GetOptionsObject(options).
  3. Let longest be ? GetOption(options, "longest", boolean, empty, false).
  4. Let strict be ? GetOption(options, "strict", boolean, empty, false).
  5. If longest is true and strict is true, throw a TypeError exception.
  6. Let mode be shortest.
  7. Let paddingOption be undefined.
  8. If longest is true, then
    1. Set mode to longest.
    2. Set paddingOption to ? Get(options, "padding").
  9. If strict is true, set mode to strict.
  10. Let iters be a new empty List.
  11. Let padding be a new empty List.
  12. Let allKeys be ? iterables.[[OwnPropertyKeys]]().
  13. Let keys be a new empty List.
  14. For each element key of allKeys, do
    1. Let desc be ? iterables.[[GetOwnProperty]](key).
    2. If desc is not undefined and desc.[[Enumerable]] is true, then
      1. Let value be undefined.
      2. If IsDataDescriptor(desc) is true, then
        1. Set value to desc.[[Value]].
      3. Else,
        1. Assert: IsAccessorDescriptor(desc) is true.
        2. Let getter be desc.[[Get]].
        3. If getter is not undefined, then
          1. Let getterResult be Completion(Call(getter, iterables)).
          2. IfAbruptCloseIterators(getterResult, iters).
          3. Set value to getterResult.
      4. If value is not undefined, then
        1. Append key to keys.
        2. Let iter be Completion(GetIteratorFlattenable(value, iterate-strings)).
        3. IfAbruptCloseIterators(iter, iters).
        4. Append iter to iters.
  15. Let iterCount be the number of elements in iters.
  16. If mode is longest, then
    1. If paddingOption is undefined, then
      1. Perform the following steps iterCount times:
        1. Append undefined to padding.
    2. Else,
      1. For each element key of keys, do
        1. Let value be Completion(Get(paddingOption, key)).
        2. IfAbruptCloseIterators(value, iters).
        3. Append value to padding.
  17. Let finishResults be a new Abstract Closure with parameters (results) that captures keys and iterCount and performs the following steps when called:
    1. Let obj be OrdinaryObjectCreate(null).
    2. For each integer i such that 0 ≤ i < iterCount, do
      1. Perform ! CreateDataPropertyOrThrow(obj, keys[i], results[i]).
    3. Return obj.
  18. Return IteratorZipCore(iters, mode, padding, finishResults).

3 IteratorZipCore ( iters, mode, padding, finishResults )

The abstract operation IteratorZipCore takes arguments iters (a List of Iterator Records), mode (either shortest, longest, or strict), padding (a List of ECMAScript language values), and finishResults (an Abstract Closure that takes a List of ECMAScript values and returns an ECMAScript value) and returns a Generator. TODO It performs the following steps when called:

  1. Let iterCount be the number of elements in iters.
  2. Let openIters be a copy of iters.
  3. Let closure be a new Abstract Closure with no parameters that captures iters, iterCount, openIters, mode, padding, and finishResults, and performs the following steps when called:
    1. If iterCount = 0, return undefined.
    2. Repeat,
      1. Let results be a new empty List.
      2. Assert: openIters is not empty.
      3. For each integer i such that 0 ≤ i < iterCount, in ascending order, do
        1. If iters[i] is null, then
          1. Let result be padding[i].
        2. Else,
          1. Let result be Completion(IteratorStepValue(iters[i])).
          2. If result is an abrupt completion, then
            1. Remove iters[i] from openIters.
            2. Return ? IteratorCloseAll(openIters, result).
          3. Set result to ! result.
          4. If result is done, then
            1. Remove iters[i] from openIters.
            2. If mode is shortest, then
              1. Return ? IteratorCloseAll(openIters, NormalCompletion(undefined)).
            3. Else if mode is strict, then
              1. If i ≠ 0, then
                1. Return ? IteratorCloseAll(openIters, ThrowCompletion(a newly created TypeError object)).
              2. For each integer k such that 1 ≤ k < iterCount, in ascending order, do
                1. Assert: iters[k] is not null.
                2. Let open be Completion(IteratorStep(iters[k])).
                3. If open is an abrupt completion, then
                  1. Remove iters[k] from openIters.
                  2. Return ? IteratorCloseAll(openIters, open).
                4. Set open to ! open.
                5. If open is false, then
                  1. Remove iters[k] from openIters.
                6. Else,
                  1. Return ? IteratorCloseAll(openIters, ThrowCompletion(a newly created TypeError object)).
              3. Return undefined.
            4. Else,
              1. Assert: mode is longest.
              2. If openIters is empty, return undefined.
              3. Set iters[i] to null.
              4. Set result to padding[i].
        3. Append result to results.
      4. Set results to finishResults(results).
      5. Let completion be Completion(Yield(results)).
      6. If completion is an abrupt completion, then
        1. Return ? IteratorCloseAll(openIters, completion).
  4. Let gen be CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »).
  5. Set gen.[[UnderlyingIterators]] to openIters.
  6. Return gen.

4 IteratorCloseAll ( iters, completion )

The abstract operation IteratorCloseAll takes arguments iters (a List of Iterator Records) and completion (a Completion Record) and returns a Completion Record. TODO It performs the following steps when called:

  1. For each element iter of iters, in reverse List order, do
    1. Set completion to Completion(IteratorClose(iter, completion)).
  2. Return ? completion.

5 IfAbruptCloseIterators ( value, iteratorRecords )

IfAbruptCloseIterators is a shorthand for a sequence of algorithm steps that use a list of Iterator Records. An algorithm step of the form:

  1. IfAbruptCloseIterators(value, iteratorRecords).

means the same thing as:

  1. Assert: value is a Completion Record.
  2. If value is an abrupt completion, return ? IteratorCloseAll(iteratorRecords, value).
  3. Else, set value to value.[[Value]].

6 %IteratorHelperPrototype%.return ( )

  1. Let O be this value.
  2. Perform ? RequireInternalSlot(O, [[UnderlyingIterator]]).
  3. Perform ? RequireInternalSlot(O, [[UnderlyingIterators]]).
  4. Assert: O has a [[GeneratorState]] slot.
  5. If O.[[GeneratorState]] is suspended-start, then
    1. Set O.[[GeneratorState]] to completed.
    2. NOTE: Once a generator enters the completed state it never leaves it and its associated execution context is never resumed. Any execution state associated with O can be discarded at this point.
    3. Perform ? IteratorClose(O.[[UnderlyingIterator]], NormalCompletion(unused)).
    4. Perform ? IteratorCloseAll(O.[[UnderlyingIterators]], NormalCompletion(unused)).
    5. Return CreateIterResultObject(undefined, true).
  6. Let C be Completion { [[Type]]: return, [[Value]]: undefined, [[Target]]: empty }.
  7. Return ? GeneratorResumeAbrupt(O, C, "Iterator Helper").

7 Infra

Note

These AOs are taken from ecma402 and are listed here because they will need to move to ecma262. This is the first API in ecma262 that will take an options bag.

7.1 GetOptionsObject ( options )

The abstract operation GetOptionsObject takes argument options (an ECMAScript language value) and returns either a normal completion containing an Object or a throw completion. It returns an Object suitable for use with GetOption, either options itself or a default empty Object. It throws a TypeError if options is not undefined and not an Object. It performs the following steps when called:

  1. If options is undefined, then
    1. Return OrdinaryObjectCreate(null).
  2. If Type(options) is Object, then
    1. Return options.
  3. Throw a TypeError exception.

7.2 GetOption ( options, property, type, values, default )

The abstract operation GetOption takes arguments options (an Object), property (a property key), type (boolean or string), values (empty or a List of ECMAScript language values), and default (required or an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or a throw completion. It extracts the value of the specified property of options, converts it to the required type, checks whether it is allowed by values if values is not empty, and substitutes default if the value is undefined. It performs the following steps when called:

  1. Let value be ? Get(options, property).
  2. If value is undefined, then
    1. If default is required, throw a RangeError exception.
    2. Return default.
  3. If type is boolean, then
    1. Set value to ToBoolean(value).
  4. Else,
    1. Assert: type is string.
    2. Set value to ? ToString(value).
  5. If values is not empty and values does not contain value, throw a RangeError exception.
  6. Return value.