XPConnect supplies no special magic for converting
nsISupportsArray into JS arrays. nsISupportsArray is just mapped
into JS like any other interface. So the 'myArray' in your
example is not a JS array object and it happens not to have a
property accessible as myArray[0].
You didn't post the idl declaration here. But I assume you have
something like...
[scritpable, uuid(...)]
interface nsIMTest : nsISupports
{
nsISupportsArray GetWindowList();
};
You can go a couple of ways here...
A) You can do what you are already doing in the idl and on the
C++ side, but change you JS code to access the nsISupportsArray
interface (really the nsICollection interface it inherits from).
[I didn't test this. Wrapping in try/catch is good...]
const nsISupportsString =
Components.interfaces.nsISupportsString;
var myArray = sample.GetWindowList();
dump(myArray + "\n");
var count = myArray.Count();
for(var i = 0; i < count; i++)
{
// Unfortunately the container is decared to have elements
// that are generic nsISupports. So, we must QI...
var element =
myArray.GetElementAt(i).QueryInterface(nsISupportsString);
// nsISupportsString has a 'toString' method that xpconnect
// will automatically invoke when using the object in a
// 'string context'. element.data is more certain to get you
// the string though.
dump("::" + element.data + "\n");
}
B) You can declare your interface to build a *real* array and
pass that from C++ to your JS code (which would work for the JS
code you already have - with one change). When the param is
declared as [array] then xpconnect will build a plain old JS
array to hold the data.
[scritpable, uuid(...)]
interface nsIMTest : nsISupports
{
void GetWindowList(PRUint32 count,
[retval, array, size_is(count)]
out string aList);
};
There is a sample of this sort of thing in the tree. See the
parts in /js/src/xpconnect/tests/ in the results of the query:
http://lxr.mozilla.org/seamonkey/search?string=GetStrings
Notes:
1) The size_is() part is required and must reference a value of
type PRUint32.
2) Be careful in the allocations required to pass this 'out'
array. The array itself and each of the members need to be
allocated with the nsMemory allocator.
3) You need to pass an object from JS to receive the 'count'
param. XPConnect will set a 'value' property on that object to
hold the count and you can ignore it if you want. But you have to
pass the object.
John.
James Moey wrote:
>
> Hi,
> I am currently writting a small xpcom component that are to be
> access from Javascript. In one of the function, it is suppose to
> return an array contain string.
>
> ----Component Source Code----
> .........
> char * data = "Testing";
> nsISupportsArray * array;
> nsresult rv = NS_NewISupportsArray(&array);
> rv = nsComponentManager::CreateInstance(NS_SUPPORTS_STRING_CONTRACTID,
> nsnull, NS_GET_IID(nsISupportsString), (void**) &xpcomString);
> xpcomString->SetData(data);
> array->AppendElement(xpcomString);
> *_retval = array;
> .........
> ---End---
> The javascript that accessing this function was able to get the
> nsISupportsArray that this function return. But it was not able to
> access the value inside the array.
>
> ---JS Source Code---
> var sample = Components.classes["@mozilla.org/mtest;1"].createInstance();
> sample = sample.QueryInterface(Components.interfaces.nsIMTest);
> dump("sample = " + sample + "\n");
> var myArray = sample.GetWindowList();
> dump(myArray + "\n");
> dump("::" + myArray[0] + "\n");
> ---End---
> The dump from myArray display a nsISupportsArray object but the
> myArray[0] display an undefined value.
>
> What am I doing wrong ? Why can't the JS access my nsISupportString ?
>
> from
> James