archives

« Bugzilla Issues Index

#4013 — Specify behaviour of forEach when structure is mutated during iteration


~~~~
var o = [0, 1, 2], seen = [];
o.forEach(function (value, i, obj) {
seen.push(value);
if (value === 1) {
o.pop();
o.push(3);
}
});
~~~~

This results in `o === seen === [0, 1, 3]` in both Firefox 31.4 and Chrome 40.0. Similar results are obtained for Set and Map as well. However, the spec for `Array.prototype.forEach` says:

> Elements which are appended to the array after the call to `forEach` begins will not be visited by *callbackfn*

It would also be nice if the spec for `Set.prototype.forEach` and `Map.prototype.forEach` mentioned this behaviour explicitly. Currently, the Set spec "sort of" implies this behaviour, and the Map spec does not mention it at all:

> [Set] However, a value will be revisited if it is deleted after it has been visited and then re-added before the to `forEach` call completes.


The non-normative NOTE on Array.prototype.forEach is incorrect in this detail, but the algorithm is the real standard, and that's what Firefox and Chrome are following here.

(Incidentally my HTML-generating script doesn't read that NOTE properly; I should go figure that out...)


The spec for Set.prototype.forEach explicitly says:

> New values added, after the call to forEach begins are visited.

I think this is appropriate because that's how SetIterator objects work.

Two typos:

1. The comma quoted above seems ungrammatical to me.

2. There's a stray "to" in that paragraph as well:
"before the to forEach call completes"


Deleted the troublesome informative paragraph from Array forEach because the algorithm is clear enough.

Kept the corresponding paragraph for Set and added a similar one for Map. These paragraphs also shouldn't be necessary but they should resolve any doubt a reader may have about whether a pseudo code for each over a list see mutation to the list.

fixed the typos that Jason identified.


fixed in rev35