I'm having some trouble registering a simple JS component. The component
is basically a copy of nsSample.js, but with more debug output. The file
nsMyComponent.js below is copied to Mozilla's dist/bin directory, and
test.js below is a simple test file (within my chrome) for verifying its
functionality.
At Mozilla startup the component gets registred. Debug output:
-> NSGetModule()
<- NSGetModule()
-> myComponentModule.registerSelf()
<- myComponentModule.registerSelf()
This means that the component is registred (additional output in
nsComponentManager.cpp tells me that the component registred
successfully). Then, when the chrome is loaded the component gets
tested. The function calls in test.js are very straight forward
(privilegdes are granted because test.js is loaded within the chrome).
Debug output:
-> myComponentTest()
-> NSGetModule()
<- NSGetModule()
-> myComponentModule.getClassObject()
myComponentModule.getClassObject() : cid = nsIMyComponent
myComponentModule.getClassObject() : iid = nsIFactory
<- myComponentModule.getClassObject()
-> myComponentFactory.createInstance()
myComponentFactory.createInstance() : iid = nsISupports
<- myComponentFactory.createInstance()
-> nsMyComponent.QueryInterface()
nsMyComponent.QueryInterface() : iid = nsISupports
<- nsMyComponent.QueryInterface()
-> nsMyComponent.QueryInterface()
nsMyComponent.QueryInterface() : iid = nsISupports
<- nsMyComponent.QueryInterface()
-> nsMyComponent.QueryInterface()
nsMyComponent.QueryInterface() : iid = nsIScriptObjectOwner
<- nsMyComponent.QueryInterface() : Throwing NS_ERROR_NO_INTERFACE
-> nsMyComponent.QueryInterface()
nsMyComponent.QueryInterface() : iid = nsIXPCScriptable
<- nsMyComponent.QueryInterface() : Throwing NS_ERROR_NO_INTERFACE
[Exception... "Could not convert JavaScript argument (NULL value can not
be used for a C++ reference type) arg 0 [nsISupports.QueryInterface]"
nsresult: "0x8057000b (NS_ERROR_XPC_BAD_CONVERT_JS_NULL_REF)" location:
"JS frame :: chrome://mychrome/content/js/test.js :: MyComponentTest ::
line 7" data: no]
<- myComponentTest()
The things that are printed out here are the function calls together
with their arguments. So, in order to execute the instruction
var comp =
Components.classes["@mozilla.org/mycomponent;1"].createInstance();
four different QueryInterface are run. The first two are nsISupports,
and the other ones are nsIScriptObjectOwner and nsIXPCScriptable. The
two last QI both fail and therefore NS_ERROR_NO_INTERFACE is thrown
twice. Afterwards the instruction
comp = comp.QueryInterface(Components.interfaces.nsIMyComponent);
is tried, but because Components.interfaces.nsIMyComponent is undefined
it doesn't work, so it throws the NS_ERROR_XPC_BAD_CONVERT_JS_NULL_REF
exception on me.
Any ideas why this happens?? Is this because the component registration
didn't really work, or is the QueryInterface function incorrect? My
guess would be that the component didn't register correctly, but
printouts from the component manager ensures me that it is...
/martin
test.js
=====
dump("-> myComponentTest()\n");
try {
// create object instance, doesn't work
var comp =
Components.classes["@mozilla.org/mycomponent;1"].createInstance();
// query interface, "Components.interfaces.nsIMyComponent" is
undefined => exception thrown
comp = comp.QueryInterface(Components.interfaces.nsIMyComponent);
// method call, never gets here...
comp.myTest();
}
catch (ex) {
dump(ex + "\n");
}
dump("<- myComponentTest()\n");
nsMyComponent.js
===============
const MYCOMPONENT_CONTRACTID = "@mozilla.org/mycomponent;1";
const MYCOMPONENT_CID =
Components.ID("{0284a776-edee-4d40-9e59-ebc057bfe98c}");
const nsISupports = Components.interfaces.nsISupports;
const nsIFactory = Components.interfaces.nsIFactory;
const nsIMyComponent =
Components.interfaces.nsIMyComponent;
const nsIXPCScriptable =
Components.interfaces.nsIXPCScriptable;
const nsIScriptObjectOwner =
Components.interfaces.nsIScriptObjectOwner;
const nsISecurityCheckedComponent =
Components.interfaces.nsISecurityCheckedComponent;
function nsMyComponent() {}
nsMyComponent.prototype.myTest =
function () {
dump("-> nsMyComponent.myTest()\n");
dump("<- nsMyComponent.myTest()\n");
}
nsMyComponent.prototype.QueryInterface =
function (iid) {
dump("-> nsMyComponent.QueryInterface()\n");
dump(" nsMyComponent.QueryInterface() : iid");
if (iid.equals(nsIMyComponent)) {
dump(" = nsIMyComponent\n");
}
else if (iid.equals(nsIFactory)) {
dump(" = nsIFactory\n");
}
else if (iid.equals(nsISupports)) {
dump(" = nsISupports\n");
}
else if (iid == "{8a9c85f0-ba3a-11d2-982d-006008962422}") {
dump(" = nsIXPCScriptable\n");
}
else if (iid == "{8f6bca7e-ce42-11d1-b724-00600891d8c9}") {
dump(" = nsIScriptObjectOwner\n");
}
else if (iid.equals(nsISecurityCheckedComponent)) {
dump(" = nsISecurityCheckedComponent\n");
}
else {
dump(" = unknown\n");
}
if (!iid.equals(nsIMyComponent) &&
!iid.equals(nsISecurityCheckedComponent) && !iid.equals(nsISupports)) {
dump("<- nsMyComponent.QueryInterface() : Throwing
NS_ERROR_NO_INTERFACE\n");
throw Components.results.NS_ERROR_NO_INTERFACE;
}
dump("<- nsMyComponent.QueryInterface()\n");
return this;
}
var myComponentModule = new Object();
myComponentModule.registerSelf =
function (compMgr, fileSpec, location, type)
{
dump("-> myComponentModule.registerSelf()\n");
compMgr.registerComponentWithType(MYCOMPONENT_CID, "MyComponent JS
Component",
MYCOMPONENT_CONTRACTID, fileSpec,
location,
true, true, type);
dump("<- myComponentModule.registerSelf()\n");
}
myComponentModule.getClassObject =
function (compMgr, cid, iid) {
dump("-> myComponentModule.getClassObject()\n");
dump(" myComponentModule.getClassObject() : cid");
if (cid.equals(MYCOMPONENT_CID)) {
dump(" = nsIMyComponent\n");
}
else {
dump(" = unknown\n");
}
dump(" myComponentModule.getClassObject() : iid");
if (iid.equals(nsIMyComponent)) {
dump(" = nsIMyComponent\n");
}
else if (iid.equals(nsIFactory)) {
dump(" = nsIFactory\n");
}
else if (iid.equals(nsISupports)) {
dump(" = nsISupports\n");
}
else if (iid == "{8a9c85f0-ba3a-11d2-982d-006008962422}") {
dump(" = nsIXPCScriptable\n");
}
else if (iid == "{8f6bca7e-ce42-11d1-b724-00600891d8c9}") {
dump(" = nsIScriptObjectOwner\n");
}
else if (iid.equals(nsISecurityCheckedComponent)) {
dump(" = nsISecurityCheckedComponent\n");
}
else {
dump(" = unknown\n");
}
if (!cid.equals(MYCOMPONENT_CID)) {
dump("<- myComponentModule.getClassObject() : Throwing
NS_ERROR_NO_INTERFACE\n");
throw Components.results.NS_ERROR_NO_INTERFACE;
}
if (!iid.equals(nsIFactory)) {
dump("<- myComponentModule.getClassObject() : Throwing
NS_ERROR_NOT_IMPLEMENTED\n");
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
}
dump("<- myComponentModule.getClassObject()\n");
return myComponentFactory;
}
myComponentModule.canUnload =
function(compMgr) {
return true;
}
myComponentFactory = new Object();
myComponentFactory.createInstance =
function (outer, iid) {
dump("-> myComponentFactory.createInstance()\n");
dump(" myComponentFactory.createInstance() : iid");
if (iid.equals(nsIMyComponent)) {
dump(" = nsIMyComponent\n");
}
else if (iid.equals(nsIFactory)) {
dump(" = nsIFactory\n");
}
else if (iid.equals(nsISupports)) {
dump(" = nsISupports\n");
}
else if (iid == "{8a9c85f0-ba3a-11d2-982d-006008962422}") {
dump(" = nsIXPCScriptable\n");
}
else if (iid == "{8f6bca7e-ce42-11d1-b724-00600891d8c9}") {
dump(" = nsIScriptObjectOwner\n");
}
else if (iid.equals(nsISecurityCheckedComponent)) {
dump(" = nsISecurityCheckedComponent\n");
}
else {
dump(" = unknown\n");
}
if (outer != null) {
dump("<- myComponentFactory.createInstance() : Throwing
NS_ERROR_NO_AGGREGATION\n");
throw Components.results.NS_ERROR_NO_AGGREGATION;
}
dump("<- myComponentFactory.createInstance()\n");
return (new nsMyComponent()).QueryInterface(iid);
}
function NSGetModule(compMgr, fileSpec) {
dump("-> NSGetModule()\n");
dump("<- NSGetModule()\n");
return myComponentModule;
}