Phabricator will be unavailable due to database maintenance from 14:00 UTC until 18:00 UTC on Saturday, October 13, 2018.
Bugzilla will remain up during this time. All users have been logged out of Bugzilla
Bugzilla will remain up during this time. All users have been logged out of Bugzilla
Status
()
People
(Reporter: bakkot, Unassigned)
Tracking
Firefox Tracking Flags
(Not tracked)
Details
User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
Steps to reproduce:
// Run the following
if (typeof console === 'undefined') console = { log: print };
let a = {
x: 0,
y: 1,
};
let pa = new Proxy(a, {});
for (let key in pa) {
console.log(key);
delete a.y;
if (key === 'y') {
console.log('reached');
}
}
Actual results:
Prints `x, y, reached`.
Expected results:
Prints only `x`. It should not reach the step with `y`, since `y` has been deleted before it gets to that iteration of the loop. The spec is pretty loose here, but does not allow this behavior: in #sec-enumerate-object-properties, it says "A property that is deleted before it is processed by the iterator's next method is ignored." No other engine except moddable's embedded XS engine has this behavior.
This doesn't happen if using `a` instead of the proxy `pa`, even though `pa` is a transparent wrapper around `a`.
If you add a trap for `getOwnPropertyDescriptor`, you can observe that `getOwnPropertyDescriptor` is being called for each property before enumerating executing the body of the loop at all, presumably to determine presence and enumerability. But because properties may be deleted before their iteration of the loop is reached, you need to check for presence immediately before the loop step covering them, not ahead of time. (It's not clear whether it's legal to check enumerability ahead of time.)
See also (and please comment on) this open spec bug about more precisely specifying the behavior of for-in, which prompted the investigation which lead me to discovering this: https://github.com/tc39/ecma262/issues/1281Summary: For-in over a proxy prints hits keys → For-in over a proxy prints hits deleted keys
Actually, this can happen even with no proxies:
```
if (typeof console === 'undefined') console = { log: print };
let a = { x: 0 };
let b = { y: 1 };
Object.setPrototypeOf(a, b);
for (let key in a) {
console.log(key);
delete b.y;
if (key === 'y') {
console.log('reached');
}
}
```
This prints `x, y, reached`. This is forbidden per the spec text cited above, and no other engine has this behavior.Summary: For-in over a proxy prints hits deleted keys → For-in can hit deleted keys
Ah, this is maybe a duplicate of https://bugzilla.mozilla.org/show_bug.cgi?id=862771.
You need to log in
before you can comment on or make changes to this bug.
Description
•