- From: Boris Zbarsky <bzbarsky@mit.edu>
- Date: Wed, 21 Oct 2015 09:50:12 -0400
- To: "public-script-coord@w3.org" <public-script-coord@w3.org>
The current spec is at http://heycam.github.io/webidl/#es-forEach but
clearly has some problems.
Specifically, we need to answer the following questions:
1) For two-type iterables, what should be passed as arguments to the
callback function? The obvious answer seems to be "value, key, this",
with the index not passed at all.
2) For one-type iterables, what should be passed as arguments to the
callback function? The two possible answers are "value, value, this"
and "value, index, this"; the former matches Set and the latter matches
Array. The only one-type iterable I'm aware of shipping so far in
browsers is DOMTokenList in Chrome, and this has the arraylike behavior,
but it's also got an indexed getter so might be a special case anyway...
3) How should deletion and addition during iteration, especially
deletion be handled? The two possible answers are:
a) forEach starts an index at 0, increments it as it goes, uses that
to index into the list, stops when the index is greater than the
list length. This means values can get skipped when an entry
that's already had forEach called on it is deleted.
b) forEach takes a list and ensures that all entries that were in it
before start and aren't deleted during the forEach callbacks, as
well as all entries added during forEach callbacks, get a callback.
Behavior (a) is what Array does. Behavior (b) is what Set and Map do
(though they handwave exactly how it's supposed to work). Note that in
both the Array and Map cases the behavior of forEach matches the
behavior of iterating the object and calling the callback on each value
the iterator returns. In the case of IDL iterables, the iterator
behavior is the Array-like behavior, with values possibly getting skipped.
Chrome's Headers (the only two-type iterator I'm aware of anyone
shipping so far), seems to implement behavior (a) here, based on this
testcase:
var h = new Headers;
h.append("a", "b")
h.append("c", "d")
h.append("e", "f")
h.forEach(function(...args) {
console.log(args);
h.delete("a");
});
Chrome's DOMTokenList also seems to implement behavior (a) (though I
personally think that it should be using Array.prototype.forEach in any
case, since it has indexed getters, so it may not be a good testcase).
-Boris
Received on Wednesday, 21 October 2015 13:50:42 UTC