- 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