Ahhhh, I see now, you have to wrap it before it goes in as well as
coming out!!!! :) (just call me homer simpson, DOOOOHHHHH!!!).

Now I understand, thanx again for all your help!!!

Sean 

-----Original Message-----
From: John Bandhauer [mailto:[EMAIL PROTECTED]] 
Sent: Sunday, December 15, 2002 2:37 PM
To: [EMAIL PROTECTED]
Subject: Re: PLEASE HELP, PLEASE PRETTY PLEASE

First the code (careful of line wrapping that the email/news 
systems might impose)...

<html>
<body>
<script>

netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect")
;

const nsISupportsArray = Components.interfaces.nsISupportsArray;

var x = 
Components.classes["@mozilla.org/supports-array;1"].createInstance(nsISu
pportsArray);

var y = new Object();
y.foo = "Hello XPConnect!";

// 1) do this...
y.wrappedJSObject = y;

x.AppendElement(y);

//NOW I WANT TO GET MY OBJECT BACK!!!

var z = x.GetElementAt(0);

// 2) and this...
// (which does more xpconnect magic than you might think)
z = z.wrappedJSObject;

alert(z);
alert(z.foo);

</script>
</body>
</html>

I think a few things need to be said...

I don't know what you are trying to build. But, you need to 
understand that direct use of xpcom from JS code is not 
appropriate for regular web content. Anything that needs the 
"UniversalXPConnect" privilege would require the user to trust 
your code completely. This gives the code the power to do 
anything from erasing files to sending arbitrary files off to the 
net. This is just not the sort of power that one wants to grant 
to downloaded web content. If you are extending mozilla or 
building an intranet application or something like that, then 
that's a different story.

That said, the thing I think you are missing is that the JS 
object system and the xpcom object system are completely 
different and know nothing about each other. XPConnect exists to 
be a bridge between those two object systems. The 
nsISupportsArray you are constructing is implemented in C++ and 
works with xpcom objects. The pattern of the code is exactly what 
I was describing before. Whether you are implementing the native 
component or not is immaterial.

This is not about 'casting'. XPCOM is about interfaces based on 
C++ object vtbls. JSObjects are dynamic and happen to be 
implemented using C. They have no fixed interfaces or C++ vtbls. 
XPConnect is all about building *additional objects*: wrappers. 
XPConnect builds one kind of wrapper object around xpcom objects 
that is used to expose the object to JS so that an xpcom object 
*looks* like a JSObject. And, xpconnect builds another kind of 
wrapper object around JSObjects to expose to xpcom to make the 
JSObject look like an xpcom object.

There is quite a bit of this wrapping going on behind the scenes 
in the little example above.

The thing you seem to be expecting is that when you call 
GetElementAt on the xpcom nsISupportArray that the object you get 
back will be automatically unwrapped to be the self-same object 
that you passed in. Very early on in the history of xpconnect 
that is exactly what would have happened. But, as we started to 
build xpcom components in JS (and there are many of these in 
mozilla now), we discovered that this actually was a 
disadvantage. It made the JS use of components work differently 
depending on whether the given component was implemented in JS or 
C++. It exposed the guts of the component to arbitrary JS code - 
thus breaking the interface based encapsulation of xpcom. And, it 
kept various xpconnect utilities (like 'instanceof') from working 
on JS components the same way they work on C++ components (when 
accessed by JS code). We *wanted* JS xpcom components to work 
exactly like C++ xpcom components (or Python xpcom components for 
  that matter). So, I implemented the scheme that we have now...

When you call AppendElement xpconnect builds a wrapper around 
your JSObject to make it look like an xpcom object. When you call 
  GetElementAt xpconnect retrieves an xpcom object (which happens 
to be a wrapper) for you. And then xpconnect builds a wrapper 
around that wrapper to make the object look like a JSObject. In 
the xpconnect internals this is called 'double wrapping'. So, the 
object you get back is wrapped like any other xpcom object to 
only expose the xpcom interface that have been indicated.

In the *rare* case where one wants to retrieve an xpcom object 
and get at the underlying JSObject I supplied the 
'wrappedJSObject' scheme shown in the example above.

Also note that it is wise to use exception handling as shown in 
my previous posting in order to safely catch cases where the 
object you are trying to unwrap might not actually be a wrapped 
JSObject as you expected.

I hope this clears things up for you - or at least shows you how 
to do what you are trying to do.

John.

Snider, Sean wrote:
> Hmmmm. . . maybe I am not being clear enough. . no this example
doesn't
> really help me b/c I am not implementing the XPCom object that I am
> handing a plain old JS Object too. . . 
> 
> Let me try to explain this a little better, the code that I wrote
before
> Is code inside the web browser (not in an XPCom/XPConnect component).

> 
> In the browser I contruct an nsISupportsArray 
> 
> const nsISupportsArray = Components.interfaces.nsISupportsArray;
> var x = Components
>               .classes["@mozilla.org/supports-array;1"]
>               .createInstance(nsISupportsArray);
> 
> and the I construct an regular object.
> 
> var y = new Object();
>     y.sean = "snider";
> 
> Then I put this object in the first slot of the array.
> 
> x.AppendElement(y);
> 
> When I ask for the element back from the Array (x.GetElementAt(0)) in
> browser script code, it just tells me that the object is an instance
of
> nsISupports, but the properties of the object that I inserted are no
> longer defined (i.e. y.sean is now undefined!!!)!!  The wrapping
> methodolgy when in the context of browser script code (NOT XPCom
> component code) doesn't seem to work, or at the very least I am doing
it
> wrong.
> 
> It's as if my object is either:
> 
> A.) Managled
> B.) No longer of JS Object type 
> 
> My guess is that b/c I am using the nsISupportsArray component, when I
> do the insertion into the array, the object is either upcast to
> nsISupports and now needs to be converted back, or its child members
are
> lost during insertion.
> 
> Basically the example you showed me is backwards from what I want. It
> shows how to take in a JSObject from the browser script code (or XPCom
> JS code for that matter) and deal with it.
> 
> Does this explain my problem better???? (Please refer to my previous
> email to see my sample code again).
> 
> 
> Sean Snider
> Software Engineer I
> [EMAIL PROTECTED] 
> 
> -----Original Message-----
> From: John Bandhauer [mailto:[EMAIL PROTECTED]] 
> Sent: Saturday, December 14, 2002 7:50 PM
> To: [EMAIL PROTECTED]
> Subject: Re: PLEASE HELP, PLEASE PRETTY PLEASE
> 
> Snider, Sean wrote:
> 
>>So then I had a look at:
>>
> 
>
http://lxr.mozilla.org/seamonkey/source/modules/plugin/samples/4x-script
> 
>>able/script-test.html#17
> 
> 
> FWIW, there used to be a couple more uses of wrappedJSObject. I 
> know chatzilla used to use it. The example you looked at was 
> something that Patrick Beard was fiddling with for scripting 
> plugins. I don't know if he ever got it to do what he wanted.
> 
> The only remaining example that I think applies is:
> 
>
http://lxr.mozilla.org/seamonkey/source/extensions/irc/js/lib/connection
> -xpcom.js
> 
> John.
> 
> 
> 
> 



Reply via email to