Closed Bug 634150 Opened 13 years ago Closed 13 years ago

Infinite loop with increasing memory involving E4X and object.__proto__

Categories

(Core :: JavaScript Engine, defect)

1.9.2 Branch
defect
Not set
normal

Tracking

()

RESOLVED WONTFIX

People

(Reporter: johnjbarton, Unassigned)

References

Details

I stumbled upon a way to hang Firefox 3.6 with Firebug 1.7a10.

Notes for me:
Open the test console and run the script/EX4 test case. 
It will time out.
Run it again. 
The tab will open and not make progress.
Close both test tabs.
Run the test a third time.

Their are probably other ways.

Here is where Boris comes in, I tracked down the problem to this code:

function instanceOf(object, Klass)
{
    while (object != null)
    {
        FBTrace.sysout("reps instanceOf ("+object+","+Klass+")");
        if (object == Klass.prototype)
           return true;
        object = object.__proto__;
    }
    return false;
}

We call this function only one place:
var found = (win && instanceOf(object,win.Error)) || (object instanceof ErrorCopy);

Where win is a content window.

In our FBTrace console we get lots of stuff then:

----
FTS0: reps instanceOf (<one>
  <two>hi</two>
</one>,function Error() {
    [native code]
}) 
FTS0: reps instanceOf (,function Error() {
    [native code]
}) 
FTS0: reps instanceOf (,function Error() {
    [native code]
}) 
FTS0: reps instanceOf (,function Error() {
    [native code]
}) 
...forever...
--------------

So it seems like the EX4 object has an __proto__ that is self referencing.

Obviously our code is not good here. It seems to me that any object can have a bad value for __proto__ and hose us. 

Boris can you suggest a better solution?  Note that this code is essentially on
https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Details_of_the_Object_Model#Determining_Instance_Relationships
I added two lines

function instanceOf(object, Klass)
{
    while (object != null)
    {
        FBTrace.sysout("reps instanceOf ("+object+","+Klass+")");
        if (object == Klass.prototype)
           return true;
        if ( !(object+"") ) // workaround bug https://bugzilla.mozilla.org/show_bug.cgi?id=634150
            return false;
        object = object.__proto__;
    }
    return false;
}

and the loop is broken. (I don't know if I also broke the function). 

And BTW our E4X test case passes now ;-)
I put this in since instanceof doesn't work with wrappers in Firefox 3.6. I walked Andreas through this when studying and fixing equality issues with wrappers, so it is fixed in 4.0. Thus, Firebug 1.8 can remove it.

In the meantime, if all the Firebug tests pass, then your changes are OK, since there is an FBTest that covers this.
> So it seems like the EX4 object has an __proto__ that is self referencing.

More precisely, _any_ property on that object is self-referencing.  Gotta love E4X.

I believe this can't happen with other objects.... though if script can define getters for __proto__ maybe it can.

For Gecko 2.0 you can use Object.getPrototypeOf, right?  For 1.9.2... I'm not sure.  Moving to the right component for this stuff.
Assignee: nobody → general
Component: DOM: Core & HTML → JavaScript Engine
QA Contact: general → general
Use Object.getPrototypeOf.

You're not hitting a __proto__ cycle, rather, you're extracting an empty XMLList from an empty list, and so on, up to the non-empty XML object

<one>
  <two>hi</two>
</one>

from which you extracted the first empty list, for the non-existent child named __proto__.

/be
> Use Object.getPrototypeOf.

That doesn't help on the 3.6 end, right?  Is there a non-hacky solution for that, or just to not worry about it?
(In reply to comment #5)
> > Use Object.getPrototypeOf.
> 
> That doesn't help on the 3.6 end, right?  Is there a non-hacky solution for
> that, or just to not worry about it?

if (typeof object == "xml") return false

/be
function instanceOf(object, Klass)
{
    while (object != null)
    {
        FBTrace.sysout("reps instanceOf ("+object+","+Klass+")");
        if (object == Klass.prototype)
           return true;
        if (typeof object == 'xml')
           return Klass.prototype == XML.prototype;
        object = object.__proto__;
    }
    return false;
}

This relies on our implementation joining XML.prototype and XMLList.prototype.

/be
Status: NEW → RESOLVED
Closed: 13 years ago
Resolution: --- → WONTFIX
Summary: Infinite loop with increasing memory involving EX4 and object.__proto__ → Infinite loop with increasing memory involving E4X and object.__proto__
You need to log in before you can comment on or make changes to this bug.