for-in enumerates over properties deleted from prototype during enumeration

RESOLVED DUPLICATE of bug 1486656

Status

()

P3
minor
RESOLVED DUPLICATE of bug 1486656
6 years ago
5 months ago

People

(Reporter: gareth, Unassigned)

Tracking

20 Branch
x86_64
Linux
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

6 years ago
If, during a for-in enumeration, we delete a property that has not yet been visited, it should not be subsequently visited. SpiderMonkey correctly skips properties that are deleted from the exact object being enumerated over, but incorrectly visits properties that are deleted from the prototype of the object being enumerated over.

I've tested the following functions on FF20, and on the SpiderMonkey command line from hg:

$ hg sum
parent: 128905:09f78adf4e79 tip
 Merge m-c to inbound.
branch: default
commit: 7413 unknown (clean)
update: (current)

In both cases, test1a() returned that w did not appear - which I think is correct behaviour ; and test1b() returned that w did appear after we deleted it - which I think is incorrect behaviour.

// var console = {log:function(){}}; // uncomment if testing using spidermonkey command line.

function test1a() {
    "use strict";
    var title = "Deleting a property that hasn't appeared will correctly prevent it from appearing.";
    console.log(title);
    var ret = "w did not appear";
    var deleted_w_yet = false;
    var a = {z:4, w:5};
    for (var i in a) {
        console.log(i+":"+a[i]);
        if (i == "z") {console.log("** Deleting w"); deleted_w_yet = delete(a.w);}
        if (i =="w") {
            if (deleted_w_yet) {ret = "w appeared after we deleted it";}
            else {ret = "We didn't delete w fast enough. This test is invalid.";}
        }
    }
    return title+"\n"+ret;
}

function test1b() {
    "use strict";
    var title = "Deleting a property that hasn't yet appeared *from a prototype* does not prevent it from appearing.";
    console.log(title);
    var ret = "w did not appear";
    var deleted_w_yet = false;
    var b = {z:4, w:5};
    var child_factory = function(){};
    child_factory.prototype = b;
    var a = new child_factory();

    for (var i in a) {
        console.log(i+":"+a[i]);
        if (i == "z") {console.log("** Deleting w"); deleted_w_yet = delete(b.w);}
        if (i =="w") {
            if (deleted_w_yet) {ret = "w appeared after we deleted it";}
            else {ret = "We didn't delete w fast enough. This test is invalid.";}
        }
    }
    return title+"\n"+ret;
}
Assignee: general → nobody
Status: UNCONFIRMED → RESOLVED
Last Resolved: 5 months ago
Priority: -- → P3
Resolution: --- → DUPLICATE
Duplicate of bug: 1486656
You need to log in before you can comment on or make changes to this bug.