Skip to content

Normative: add Iterator.zip and Iterator.zipKeyed#3802

Open
michaelficarra wants to merge 4 commits into
mainfrom
joint-iteration
Open

Normative: add Iterator.zip and Iterator.zipKeyed#3802
michaelficarra wants to merge 4 commits into
mainfrom
joint-iteration

Conversation

@michaelficarra
Copy link
Copy Markdown
Member

@michaelficarra michaelficarra commented Apr 7, 2026

@michaelficarra michaelficarra added normative change Affects behavior required to correctly evaluate some ECMAScript source text pending stage 4 This proposal has not yet achieved stage 4, but may otherwise be ready to merge. proposal This is related to a specific proposal, and will be closed/merged when the proposal reaches stage 4. labels Apr 7, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 7, 2026

The rendered spec preview for this PR is available as a single page at https://tc39.es/ecma262/pr/3802 and as multiple pages at https://tc39.es/ecma262/pr/3802/multipage .

Jack-Works added a commit to engine262/engine262 that referenced this pull request Apr 11, 2026
Comment thread spec.html Outdated
Comment thread spec.html
Comment on lines +48641 to +48642
1. If _mode_ is *"longest"*, then
1. Set _paddingOption_ to ? Get(_options_, *"padding"*).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit odd to read padding only when mode is "longest" (rather than unconditionally), but it was present from the start and is covered in test262. I'm not objecting, but do want to draw attention to this behavior.

Comment thread spec.html
1. Let _iterCount_ be the number of elements in _iters_.
1. If _mode_ is *"longest"*, then
1. If _paddingOption_ is *undefined*, then
1. Repeat _iterCount_ times:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Presumably we're intending to document this form as preferred and expecting ESMeta to add support for it? There's also a more concise approach that wouldn't use it:

            1. If _mode_ is *"longest"*, then
              1. Let _remainingPaddingCount_ be _iterCount_.
              1. If _paddingOption_ is not *undefined*, then
                1. Let _paddingIter_ be Completion(GetIterator(_paddingOption_, ~sync~)).
                1. IfAbruptCloseIterators(_paddingIter_, _iters_).
                1. Let _usingIterator_ be *true*.
                1. Repeat, while _usingIterator_ is *true* and _remainingPaddingCount_ > 0,
                  1. Set _next_ to Completion(IteratorStepValue(_paddingIter_)).
                  1. IfAbruptCloseIterators(_next_, _iters_).
                  1. If _next_ is ~done~, then
                    1. Set _usingIterator_ to *false*.
                  1. Else,
                    1. Append _next_ to _padding_.
                    1. Set _remainingPaddingCount_ to _remainingPaddingCount_ - 1.
                1. If _usingIterator_ is *true*, then
                  1. Let _completion_ be Completion(IteratorClose(_paddingIter_, NormalCompletion(~unused~))).
                  1. IfAbruptCloseIterators(_completion_, _iters_).
              1. Repeat, while _remainingPaddingCount_ > 0,
                1. Append *undefined* to _padding_.
                1. Set _remainingPaddingCount_ to _remainingPaddingCount_ - 1.

Comment thread spec.html
Comment on lines +48687 to +48695
1. If _iterables_ is not an Object, throw a *TypeError* exception.
1. Set _options_ to ? GetOptionsObject(_options_).
1. Let _mode_ be ? Get(_options_, *"mode"*).
1. If _mode_ is *undefined*, set _mode_ to *"shortest"*.
1. If _mode_ is not one of *"shortest"*, *"longest"*, or *"strict"*, throw a *TypeError* exception.
1. Let _paddingOption_ be *undefined*.
1. If _mode_ is *"longest"*, then
1. Set _paddingOption_ to ? Get(_options_, *"padding"*).
1. If _paddingOption_ is not *undefined* and _paddingOption_ is not an Object, throw a *TypeError* exception.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is identical to the start of Iterator.zip and it might be worth highlighting that.

Suggested change
1. If _iterables_ is not an Object, throw a *TypeError* exception.
1. Set _options_ to ? GetOptionsObject(_options_).
1. Let _mode_ be ? Get(_options_, *"mode"*).
1. If _mode_ is *undefined*, set _mode_ to *"shortest"*.
1. If _mode_ is not one of *"shortest"*, *"longest"*, or *"strict"*, throw a *TypeError* exception.
1. Let _paddingOption_ be *undefined*.
1. If _mode_ is *"longest"*, then
1. Set _paddingOption_ to ? Get(_options_, *"padding"*).
1. If _paddingOption_ is not *undefined* and _paddingOption_ is not an Object, throw a *TypeError* exception.
1. If _iterables_ is not an Object, throw a *TypeError* exception.
1. Let _resolvedOptions_ be ? ResolveIteratorZipOptions(_options_).
1. Let _mode_ be _resolvedOptions_.[[Mode]].
1. Let _paddingOption_ be _resolvedOptions_.[[Padding]].

Comment thread spec.html
Comment on lines +48787 to +48788
1. If _completion_ is an abrupt completion, then
1. Return ? IteratorCloseAll(_openIters_, _completion_).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This step can be simplified (because it doesn't mutate openIters):

Suggested change
1. If _completion_ is an abrupt completion, then
1. Return ? IteratorCloseAll(_openIters_, _completion_).
1. IfAbruptCloseIterators(_completion_, _openIters_).

It would be great if the steps that do mutate openIters could also be simplified, and I'm wondering how we might do that... maybe by extending IfAbruptCloseIterators with an optional parameter for an element to remove before invoking IteratorCloseAll?

-                    1. If _result_ is an abrupt completion, then
-                      1. Remove _iter_ from _openIters_.
-                      1. Return ? IteratorCloseAll(_openIters_, _result_).
-                    1. Set _result_ to ! _result_.
+                    1. IfAbruptCloseIterators(_result_, _openIters_, _iter_).
-                          1. If _open_ is an abrupt completion, then
-                            1. Remove _iters_[_k_] from _openIters_.
-                            1. Return ? IteratorCloseAll(_openIters_, _open_).
-                          1. Set _open_ to ! _open_.
+                          1. IfAbruptCloseIterators(_open_, _openIters_, _iters_[_k_]).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

normative change Affects behavior required to correctly evaluate some ECMAScript source text pending stage 4 This proposal has not yet achieved stage 4, but may otherwise be ready to merge. proposal This is related to a specific proposal, and will be closed/merged when the proposal reaches stage 4.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stage 4 tracking

3 participants