archives

« Bugzilla Issues Index

#1444 — 8.3.12 incomplete in the presence of prototype changes and property deletions.


Section 8.3.12 defines the behaviour of [[Enumerate]], and describes what should happen if properties are added or removed during enumeration:

"If a property that has not yet been visited during enumeration is deleted, then it will not be visited. If new properties are added to the object being enumerated during enumeration, the newly added properties are not guaranteed to be visited in the active enumeration."

We are not so clear on what happens if we enter the loop with an
enumerable property shadowing a non-enumerable one, and then delete the
enumerable one before it is visited.

Perhaps the "nicest" reading of the existing would be to treat the revealed
properties the same way we would treat "added" properties. So, in this
case, the "revealed" property would be checked for enumerability and
skipped. This doesn't seem to be the only possible reading of the spec however. while spidermonkey seems to behave as I had expected, V8 disagrees, and visits the non-enumerable property.

Essentially the same trick can be played by mutating __proto__ during enumeration.

Here is a code snippit which demonstrates this behaviour, assuming that x happens to come before z in the enumeration order:

var a = {};
Object.defineProperty(a, 'z', {value: 'secret', enumerable: false});
var b = {x:0, z:"tricky", __proto__:a};
var ret = "We have not visited a.z";
var deleted_z_yet = false;
for (var i in b) {
if(i=='x') {
delete b.z ;
deleted_z_yet = true;
}
if (i=='z' && deleted_z_yet) {
ret = "we have visited a.z" ;
}
}


fixed in rev26

replaced in informative algorithm with an ES generator function

also (hopefully) clarified the language WRT this point.


in rev26