Now that I've been able to do some more thorough testing and clean-up, I
will post the solution I have used to register components for JS, so others
may benefit. This should be easier than looking at the XMLHttpRequest
example, because it is the least amount of things you need to do, and it
will compile with MOZILLA_STRICT_API. I still have not figured out how to
prevent JS attributes from being GC on the XPCOM component yet.
Use the following macro for defining entries in your nsComponentModuleInfo,
in the following way.
#define XPCOM_REGISTER_WITH_JAVASCRIPT( componentName, contractId ) \
static NS_METHOD \
Register##componentName(nsIComponentManager *aCompMgr, \
nsIFile *aPath, \
const char *registryLocation, \
const char *componentType, \
const nsModuleComponentInfo *info) \
{ \
nsCOMPtr< nsIServiceManager > serviceManager; \
nsresult result = NS_GetServiceManager( getter_AddRefs(
serviceManager ) ); \
NS_ENSURE_SUCCESS( result, result ); \
\
nsCOMPtr< nsICategoryManager > catman; \
result = serviceManager->GetServiceByContractID(
"@mozilla.org/categorymanager;1", \
NS_GET_IID(
nsICategoryManager ), \
getter_AddRefs(
catman ) ); \
NS_ENSURE_SUCCESS( result, result ); \
\
nsEmbedCString previous; \
return catman->AddCategoryEntry(JAVASCRIPT_DOM_CLASS, \
#componentName, \
contractId, \
PR_TRUE, PR_TRUE,
getter_Copies(previous)); \
}
XPCOM_REGISTER_WITH_JAVASCRIPT( Foo, FOO_CONTRACTID );
static const nsModuleComponentInfo components[] =
{
{ "Foo",
FOO_CID,
FOO_CONTRACTID,
FooConstructor,
RegisterFoo,
nsnull,
nsnull,
NS_CI_INTERFACE_GETTER_NAME(Foo),
nsnull,
&NS_CLASSINFO_NAME(Foo),
nsIClassInfo::DOM_OBJECT // Pretend to be part of the DOM, so component
has same-origin access.
}
}
In the component, make sure to use the NS_IMPL_ISUPPORTS3_CI family of
macros to declare a class interface.
For each foo, you should initialize before running any JS, with a call to
the following. (One gotcha is that keepAliveFooName must be kept alive as
long as the DOM needs it, so I suggest putting it in a static variable.)
domSOFactory->RegisterDOMClassInfo( keepAliveFooName.get(),
&GetClassInfoFor,
NULL,
interfaces,
DOM_DEFAULT_SCRIPTABLE_FLAGS,
PR_TRUE,
&fooCID );
Where GetClassInfoFor returns the nsIClassInfo object. If you have many
objects to register, then you can use one GetClassInfoFor function that
looks up the proper CID in a map. In any event, a call to the following is
the key part of the module I called GetClassInfoFor. (Another gotcha is
that although GetClassInfoFor may seem like a getter, it is not
XPCOM-compliant, so you should not AddRef, unless you want a memory leak.
This means calling Release on classInfo, after calling GetClassObject and
before returning.)
componentManager->GetClassObject( fooCID,
NS_GET_IID( nsIClassInfo ),
reinterpret_cast< void** >(
&classInfo ) );
_______________________________________________
dev-tech-xpcom mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-xpcom