Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

XPCNativeWrapper.unwrap?

158 views
Skip to first unread message

johnjbarton

unread,
Apr 8, 2011, 10:52:23 AM4/8/11
to
Keeping my left hand on the wall at all times, I'm trying to sort out
how to show object references in Chromebug again.

The current goal is to show the references as a developer would imagine
them in chrome scope. So, for example, references to content should have
a .wrappedJSObject property.

Th current snag is jsdIValue, the wrapper used by jsd in returning
references. All the references that we get from stack frames etc have
this wrapper. As far as I understand it, this wrapper has nothing to do
with all the other wrappers, this one is primarily to 1) prevent the
holder from locking the object of GC and 2) add type testing so non-JS
code can survive.

jsdIValue has a mechanism for returning the underlying JS object,
getWrappedValue(), from the IDL:
this method returns the JavaScript value wrapped by this
jsdIValue. The calling script is free to use the result as it would any
other JavaScript value.

However this claim seems to fall short in practice ;-). If call this
function for an object that has toString
[object XrayWrapper [object Window]]
then try to enumerate the properties of that object I get things like
"invalid 'in' operand unwrapped" or Component is not available.

Of course Firebug works on such objects, so I conclude that the
following curious code solves the above problem:
if (typeof(unwrapped) == "object")
return XPCNativeWrapper.unwrap(unwrapped);

See:
https://developer.mozilla.org/en/XPCNativeWrapper#Unwrapping_an_object

I don't understand the intermediate state, after we apply
getWrappedValue() but before XPCNativeWrapper.unwrap, but the final
state seems to be a content-view, the thing I would get from
win.wrappedJSObject.

At last the buried treasure ;-) my question is:
How do I get the chrome-view rather than the content-view from a
getWrappedValue() returned object?

jjb

Boris Zbarsky

unread,
Apr 8, 2011, 11:16:23 AM4/8/11
to
On 4/8/11 7:52 AM, johnjbarton wrote:
> I don't understand the intermediate state

Neither do I. Can you please file a bug, with steps to reproduce?

> At last the buried treasure ;-) my question is:
> How do I get the chrome-view rather than the content-view from a
> getWrappedValue() returned object?

Chances are, the answer involves C++ changes to getWrappedValue...

-Boris

Neil

unread,
Apr 8, 2011, 12:05:31 PM4/8/11
to
johnjbarton wrote:

> I don't understand the intermediate state, after we apply
> getWrappedValue() but before XPCNativeWrapper.unwrap, but the final
> state seems to be a content-view, the thing I would get from
> win.wrappedJSObject.

That's because XPCNativeWrapper.unwrap is like win.wrappedJSObject, but
safer.

--
Warning: May contain traces of nuts.

johnjbarton

unread,
Apr 8, 2011, 12:09:50 PM4/8/11
to
On 4/8/2011 9:05 AM, Neil wrote:
> johnjbarton wrote:
>
>> I don't understand the intermediate state, after we apply
>> getWrappedValue() but before XPCNativeWrapper.unwrap, but the final
>> state seems to be a content-view, the thing I would get from
>> win.wrappedJSObject.
>
> That's because XPCNativeWrapper.unwrap is like win.wrappedJSObject, but
> safer.
>

In what way "safer"? In what way is win.wrappedJSObject not safe?

jjb

Boris Zbarsky

unread,
Apr 8, 2011, 12:14:51 PM4/8/11
to
On 4/8/11 9:09 AM, johnjbarton wrote:
> In what way "safer"? In what way is win.wrappedJSObject not safe?

If you know with 100% surety that your |win| is an XPCNativeWrapper (or
XrayWrapper in Fx4), they're equivalent.

But if you don't know that, then win.wrappedJSObject will do the wrong
thing in some cases, while XPCNativeWrapper.unwrap will generally do
what you actually want.

For example, if |win| is a number, win.wrappedJSObject() will throw,
while XPCNativeWrapper.unwrap(win) will just return win.

-Bori

johnjbarton

unread,
Apr 8, 2011, 12:31:18 PM4/8/11
to

Ok then this safer as in "less likely to throw exceptions" not "less
likely to expose security holes".

But I would not recommend using XPCNativeWrapper.unwrap(win) based on
this difference. We used to have a lot of code in Firebug that was
similar, things like
var win = (win.wrappedJSObject ? win.wrappedJSObject : win);
but we took it all out.

When you access win.wrappedJSObject you are getting a reference with a
different API: you intend to examine the state of the object as seen by
content JavaScript. If the reference does not have a wrappedJSObject,
then your code's assumptions are incorrect: you have a bug. Failing back
to 'win' will prevent an exception, but it won't fix the bug. And this
kind of bug is hard to sort out exactly because you don't get an error.

jjb

>
> -Bori

Boris Zbarsky

unread,
Apr 8, 2011, 12:50:29 PM4/8/11
to
On 4/8/11 9:31 AM, johnjbarton wrote:
> But I would not recommend using XPCNativeWrapper.unwrap(win) based on
> this difference. We used to have a lot of code in Firebug that was
> similar, things like
> var win = (win.wrappedJSObject ? win.wrappedJSObject : win);
> but we took it all out.
>
> When you access win.wrappedJSObject you are getting a reference with a
> different API: you intend to examine the state of the object as seen by
> content JavaScript. If the reference does not have a wrappedJSObject,
> then your code's assumptions are incorrect: you have a bug.

Of course if it _does_ have a wrappedJSObject, that doesn't mean that
it's an XPCNativeWrapper. Other kinds of XPConnect wrappers also have a
.wrappedJSObject that returns underlying JS objects. That's the other
situation in which XPCNativeWrapper.unwrap is better: it will only
unwrap XPCNativeWrapper, not other wrappers.

But as you point out, the correct usage really depends on what you're doing.

-Boris

Neil

unread,
Apr 8, 2011, 1:06:59 PM4/8/11
to
johnjbarton wrote:

> When you access win.wrappedJSObject you are getting a reference with a
> different API: you intend to examine the state of the object as seen
> by content JavaScript.

Any object can have a .wrappedJSObject property whereas
XPCNativeWrapper.unwrap guarantees you the content view of an object,
returning the original object if it already is a content view or if it
does not have one.

johnjbarton

unread,
Apr 8, 2011, 1:16:08 PM4/8/11
to
On 4/8/2011 10:06 AM, Neil wrote:
> johnjbarton wrote:
>
>> When you access win.wrappedJSObject you are getting a reference with a
>> different API: you intend to examine the state of the object as seen
>> by content JavaScript.
>
> Any object can have a .wrappedJSObject property whereas

True, but in my experience these objects are almost always XPCOM
components which are unlikely to be confused with the objects related to
a window.

> XPCNativeWrapper.unwrap guarantees you the content view of an object,
> returning the original object if it already is a content view or if it
> does not have one.
>

Yes, but a better API would call the function "getContentView()" and it
would return false unless the object has a content view.

jjb

johnjbarton

unread,
Apr 8, 2011, 1:18:07 PM4/8/11
to
On 4/8/2011 8:16 AM, Boris Zbarsky wrote:
> On 4/8/11 7:52 AM, johnjbarton wrote:
>> I don't understand the intermediate state
>
> Neither do I. Can you please file a bug, with steps to reproduce?

https://bugzilla.mozilla.org/show_bug.cgi?id=648560
this isn't about getWrappedValue, but rather its related to the my
attempt to work around the issue.

jjb

reesd

unread,
Apr 14, 2011, 6:35:43 PM4/14/11
to
On Friday, April 8, 2011 12:50:29 PM UTC-4, Boris Zbarsky wrote:

> Of course if it _does_ have a wrappedJSObject, that doesn't mean that
> it's an XPCNativeWrapper. Other kinds of XPConnect wrappers also have a
> .wrappedJSObject that returns underlying JS objects. That's the other
> situation in which XPCNativeWrapper.unwrap is better: it will only
> unwrap XPCNativeWrapper, not other wrappers.
>

Is there a correct way to test an object to see if its a wrapper or even specifically a XPCNativeWrapper? Based on this discussion wrappedJSObject is wrong since any object could have that, and unwrap always returns a value so it's not a good test either.

d

Boris Zbarsky

unread,
Apr 14, 2011, 11:05:23 PM4/14/11
to
On 4/14/11 6:35 PM, reesd wrote:
> Is there a correct way to test an object to see if its a wrapper

Why do you care?

> or even specifically a XPCNativeWrapper?

Again, why do you care?

> Based on this discussion wrappedJSObject is wrong since any object could have that, and unwrap always returns a value so it's not a good test either.

XPCNativeWrapper.unwrap(foo) !== foo

is a pretty good test for foo being an XPCNativeWrapper.

-Boris

johnjbarton

unread,
Apr 15, 2011, 2:26:13 PM4/15/11
to
On 4/14/2011 8:05 PM, Boris Zbarsky wrote:
> On 4/14/11 6:35 PM, reesd wrote:
>> Is there a correct way to test an object to see if its a wrapper
>
> Why do you care?

Because of https://bugzilla.mozilla.org/show_bug.cgi?id=648560 we have a
reference which has a wrappedJSObject property but nothing else as far
as I can tell. We can't enumerate its properties, for...in throws. We
can't use it in Firebug code for object display because our display code
relies on Object methods, which fail.

I think what David needs is just try/catch around for...in and a test
for .wrappedJSObject. Then you know you hit the buggy wrapper case. I
implemented this kind of workaround in Chromebug.

jjb

David Rees

unread,
Apr 15, 2011, 5:59:50 PM4/15/11
to

And beyond just making it work in Chromebug, there are cases in
extension code where it would be good to verify what one is dealing
with. Since these are often created automatically by Firefox and pretend
to be normal objects in most cases, they can surprise you. There can
also be cases where a developer doesn't know if something handed to them
is wrapped or not and they want to check (sandbox for example).

This is especially true when Firefox changes things like the
loadSubScript issue I posted about in the other thread
(https://groups.google.com/forum/#!topic/mozilla.dev.platform/asEn-JQy-5c).

I can't seem to find a rock solid way to verify that I have a wrapper.
Either wrappedJSObject or toString (with different matches for 3.6 and
4) seem to be a developer's best bet right now, but I am leery of both
since they can be changed.

Would rather have something like XPCWrapper.wrapperType() which returns
null if the object isn't wrapped.

d

0 new messages