Closed Bug 862771 Opened 11 years ago Closed 6 years ago

for-in enumerates over properties deleted from prototype during enumeration

Categories

(Core :: JavaScript Engine, defect, P3)

20 Branch
x86_64
Linux
defect

Tracking

()

RESOLVED DUPLICATE of bug 1486656

People

(Reporter: gareth, Unassigned)

Details

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
Closed: 6 years ago
Priority: -- → P3
Resolution: --- → DUPLICATE
You need to log in before you can comment on or make changes to this bug.