Alec Flett wrote:
>
> John,
> I was just talking with shaver on IRC about this, was wondering if you
> had any ideas about what to do. Basically, I'm trying to move a C++
> implementation of an nsIURIContentListener into JS. The way these are
> used are via the URILoader service:
>
> uriLoader.registerContentListener(foo);
>
> and uriLoader stores a weak reference to "foo" in an nsVoidArray.
> but the problem is that when I go to unregister the javascript version:
>
> uriLoader.unRegisterContentListener(foo)
>
> a different pointer seems to get passed into unRegisterContentListener()
> - so the unregistration never happens, and we're left with a weak
> reference to a disposed-of wrapper object in a void array, which
> subsequently causes a crash.... and just to make sure I wasn't going
> crazy, I did this:
>
> uriLoader.unRegisterContentListener(foo)
> uriLoader.unRegisterContentListener(foo)
>
> and amazingly got two different pointers from c++, neither of which
> matched the original.
>
> any thoughts? I'm holding a strong reference to the object else from
> C++, but I haven't looked to see what the value of THAT pointer is yet...
A few...
When you say 'stores a weak reference to "foo"' do you mean the
pointer from asking for nsIWeakReference?
In that case, you'd want unRegisterContentListener to also ask
for the nsIWeakReference of the passed pointer and try to remove
*that*. Or better, look at the result of QueryReferent on the
nsIWeakReference.
In general wrappedJS wrappers are going to give you a different
pointer for every interface you QI it for - even if those
interfaces share an inheritance relationship. The exception is
nsISupports which *sometimes* shares a wrapper with another
interface. Any xpcom object might also do this - so your code
should be ready for this - but wrapped JS objects do it more.
You should *never* be expecting equality of pointers that have
not been QI'd to the same interface.
> uriLoader.unRegisterContentListener(foo)
> uriLoader.unRegisterContentListener(foo)
I'm assuming that you are not holding a reference to the the
wrapper around foo between calls. XPConnect is going to give you
a new pointer each time unless you are holding a reference on the
native side OR you get the nsIWeakReferece on the native side AND
the JSObject does not get collected in the interim. No native
code should ever try to compare native pointers unless it is
holding a reference to both of them at the time it compares them.
Does any of this overlap with what you are seeing? There is a
*possibility* of a problem with the hashtable scheme for reusing
live wrappers around wrapped JSObjects. But, I'm thinking that is
unlikely.
John.
>
> Alec