зеркало из https://github.com/mozilla/gecko-dev.git
1) fix the xpconnect factories to not use static objects.
2) add a test that acts as a sample for doing oberloaded methods on xpconnect wraped natives. 3) add a NOT_IMPLEMENTED method to wrapped native for getting the prototype JS object. 4) Set the global object of the JSContext as the wrapped native JSObject's parent when creating this JSObject. This makes JS code compiled against the wrapper actuall work! 5) fix the refcounting on factories in the tests/components module
This commit is contained in:
Родитель
70e2e6884c
Коммит
eab48df1ca
|
@ -133,3 +133,9 @@ interface nsIXPCTestString : nsISupports {
|
|||
void GetStringB(out string s);
|
||||
void GetStringC([shared,retval] out string s);
|
||||
};
|
||||
|
||||
[scriptable, uuid(0ff4faf0-439a-11d3-988c-006008962422)]
|
||||
interface nsIXPCTestOverloaded : nsISupports {
|
||||
void Foo1(in PRInt32 p1);
|
||||
void Foo2(in PRInt32 p1, in PRInt32 p2);
|
||||
};
|
||||
|
|
|
@ -90,6 +90,9 @@ public:
|
|||
NS_IMETHOD DebugDump(int depth) = 0;
|
||||
NS_IMETHOD SetFinalizeListener(nsIXPConnectFinalizeListener* aListener) = 0;
|
||||
|
||||
// NOT YET IMPLEMTED!!!
|
||||
NS_IMETHOD GetJSObjectPrototype(JSObject** aJSObj) = 0;
|
||||
|
||||
// XXX other methods?
|
||||
};
|
||||
|
||||
|
|
|
@ -23,176 +23,130 @@
|
|||
/***************************************************************************/
|
||||
|
||||
static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
|
||||
static NS_DEFINE_CID(kGenericFactoryCID, NS_GENERICFACTORY_CID);
|
||||
static NS_DEFINE_CID(kJSIID_CID, NS_JS_IID_CID);
|
||||
static NS_DEFINE_CID(kJSCID_CID, NS_JS_CID_CID);
|
||||
static NS_DEFINE_CID(kXPConnect_CID, NS_XPCONNECT_CID);
|
||||
static NS_DEFINE_CID(kXPCThreadJSContextStack_CID, NS_XPC_THREAD_JSCONTEXT_STACK_CID);
|
||||
|
||||
class nsXPCFactory : public nsIFactory
|
||||
/********************************************/
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsJSIID)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsJSCID)
|
||||
|
||||
static NS_IMETHODIMP
|
||||
Construct_nsXPConnect(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
nsresult rv;
|
||||
nsISupports *obj;
|
||||
|
||||
NS_IMETHOD CreateInstance(nsISupports *aOuter,
|
||||
REFNSIID aIID,
|
||||
void **aResult);
|
||||
|
||||
NS_IMETHOD LockFactory(PRBool aLock);
|
||||
|
||||
nsXPCFactory(const nsCID &aCID);
|
||||
virtual ~nsXPCFactory();
|
||||
private:
|
||||
nsCID mCID;
|
||||
};
|
||||
|
||||
nsXPCFactory::nsXPCFactory(const nsCID &aCID)
|
||||
: mCID(aCID)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF_THIS();
|
||||
}
|
||||
|
||||
nsXPCFactory::~nsXPCFactory()
|
||||
{
|
||||
// NS_ASSERTION(mRefCnt == 0, "non-zero refcnt at destruction");
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPCFactory::QueryInterface(const nsIID &aIID, void **aResult)
|
||||
{
|
||||
if(aResult == NULL)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if(aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID()) ||
|
||||
aIID.Equals(nsIFactory::GetIID()) ||
|
||||
aIID.Equals(nsXPCFactory::GetIID()))
|
||||
if(!aResult)
|
||||
{
|
||||
*aResult = (void*)this;
|
||||
rv = NS_ERROR_NULL_POINTER;
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
{
|
||||
*aResult = NULL;
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(nsXPCFactory)
|
||||
NS_IMPL_RELEASE(nsXPCFactory)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPCFactory::CreateInstance(nsISupports *aOuter,
|
||||
const nsIID &aIID,
|
||||
void **aResult)
|
||||
{
|
||||
nsresult res = NS_OK;
|
||||
|
||||
if(aResult == NULL)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aResult = NULL;
|
||||
|
||||
if(aOuter)
|
||||
return NS_NOINTERFACE;
|
||||
|
||||
nsISupports *inst = nsnull;
|
||||
|
||||
// ClassID check happens here
|
||||
// Whenever you add a new class that supports an interface, plug it in here
|
||||
|
||||
// ADD NEW CLASSES HERE
|
||||
if (mCID.Equals(kJSIID_CID))
|
||||
{
|
||||
inst = new nsJSIID;
|
||||
rv = NS_ERROR_NO_AGGREGATION;
|
||||
goto done;
|
||||
}
|
||||
else if (mCID.Equals(kJSCID_CID))
|
||||
{
|
||||
inst = new nsJSCID;
|
||||
}
|
||||
else if (mCID.Equals(kXPConnect_CID))
|
||||
{
|
||||
inst = nsXPConnect::GetXPConnect();
|
||||
}
|
||||
else if (mCID.Equals(kXPCThreadJSContextStack_CID))
|
||||
{
|
||||
inst = nsXPCThreadJSContextStackImpl::GetSingleton();
|
||||
}
|
||||
else
|
||||
return NS_NOINTERFACE;
|
||||
|
||||
if(inst)
|
||||
{
|
||||
res = inst->QueryInterface(aIID, aResult);
|
||||
NS_RELEASE(inst);
|
||||
}
|
||||
else
|
||||
res = NS_ERROR_OUT_OF_MEMORY;
|
||||
obj = nsXPConnect::GetXPConnect();
|
||||
|
||||
return res;
|
||||
if(!obj)
|
||||
{
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rv = obj->QueryInterface(aIID, aResult);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to find correct interface");
|
||||
NS_RELEASE(obj);
|
||||
done:
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPCFactory::LockFactory(PRBool aLock)
|
||||
static NS_IMETHODIMP
|
||||
Construct_nsXPCThreadJSContextStack(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
{
|
||||
return NS_OK;
|
||||
nsresult rv;
|
||||
nsISupports *obj;
|
||||
|
||||
if(!aResult)
|
||||
{
|
||||
rv = NS_ERROR_NULL_POINTER;
|
||||
goto done;
|
||||
}
|
||||
*aResult = NULL;
|
||||
if(aOuter)
|
||||
{
|
||||
rv = NS_ERROR_NO_AGGREGATION;
|
||||
goto done;
|
||||
}
|
||||
|
||||
obj = nsXPCThreadJSContextStackImpl::GetSingleton();
|
||||
|
||||
if(!obj)
|
||||
{
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rv = obj->QueryInterface(aIID, aResult);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to find correct interface");
|
||||
NS_RELEASE(obj);
|
||||
done:
|
||||
return rv;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/********************************************/
|
||||
|
||||
#if defined(XP_MAC) && defined(MAC_STATIC)
|
||||
extern "C" XPC_PUBLIC_API(nsresult)
|
||||
NSGetFactory_XPCONNECT_DLL(nsISupports* servMgr,
|
||||
const nsCID &aClass,
|
||||
const char *aClassName,
|
||||
const char *aProgID,
|
||||
nsIFactory **aFactory)
|
||||
#else
|
||||
extern "C" XPC_PUBLIC_API(nsresult)
|
||||
NSGetFactory(nsISupports* servMgr,
|
||||
extern "C" PR_IMPLEMENT(nsresult)
|
||||
NSGetFactory(nsISupports* aServMgr,
|
||||
const nsCID &aClass,
|
||||
const char *aClassName,
|
||||
const char *aProgID,
|
||||
nsIFactory **aFactory)
|
||||
#endif
|
||||
{
|
||||
static nsXPCFactory iid_factory(kJSIID_CID);
|
||||
static nsXPCFactory cid_factory(kJSCID_CID);
|
||||
static nsXPCFactory xpc_factory(kXPConnect_CID);
|
||||
static nsXPCFactory threadstack_factory(kXPCThreadJSContextStack_CID);
|
||||
nsresult rv;
|
||||
NS_ASSERTION(aFactory != nsnull, "bad factory pointer");
|
||||
|
||||
if(!aFactory)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
NS_WITH_SERVICE1(nsIComponentManager, compMgr,
|
||||
aServMgr, kComponentManagerCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsIGenericFactory* factory;
|
||||
rv = compMgr->CreateInstance(kGenericFactoryCID, nsnull,
|
||||
nsIGenericFactory::GetIID(),
|
||||
(void**)&factory);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// add more factories as 'if else's below...
|
||||
|
||||
if(aClass.Equals(kJSIID_CID))
|
||||
rv = factory->SetConstructor(nsJSIIDConstructor);
|
||||
else if(aClass.Equals(kJSCID_CID))
|
||||
rv = factory->SetConstructor(nsJSCIDConstructor);
|
||||
else if(aClass.Equals(kXPConnect_CID))
|
||||
rv = factory->SetConstructor(Construct_nsXPConnect);
|
||||
else if(aClass.Equals(kXPCThreadJSContextStack_CID))
|
||||
rv = factory->SetConstructor(Construct_nsXPCThreadJSContextStack);
|
||||
else
|
||||
{
|
||||
iid_factory.AddRef();
|
||||
*aFactory = &iid_factory;
|
||||
return NS_OK;
|
||||
}
|
||||
if(aClass.Equals(kJSCID_CID))
|
||||
{
|
||||
cid_factory.AddRef();
|
||||
*aFactory = &cid_factory;
|
||||
return NS_OK;
|
||||
}
|
||||
if(aClass.Equals(kXPConnect_CID))
|
||||
{
|
||||
xpc_factory.AddRef();
|
||||
*aFactory = &xpc_factory;
|
||||
return NS_OK;
|
||||
}
|
||||
if(aClass.Equals(kXPCThreadJSContextStack_CID))
|
||||
{
|
||||
threadstack_factory.AddRef();
|
||||
*aFactory = &threadstack_factory;
|
||||
return NS_OK;
|
||||
NS_ASSERTION(0, "incorrectly registered");
|
||||
rv = NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(factory);
|
||||
return rv;
|
||||
}
|
||||
*aFactory = factory;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
extern "C" XPC_PUBLIC_API(PRBool)
|
||||
NSCanUnload(nsISupports* aServMgr)
|
||||
|
@ -247,4 +201,4 @@ NSUnregisterSelf(nsISupports* aServMgr, const char *aPath)
|
|||
rv = compMgr->UnregisterComponent(kXPCThreadJSContextStack_CID, aPath);
|
||||
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "nsISupports.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIGenericFactory.h"
|
||||
#include "nsIAllocator.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsIInterfaceInfo.h"
|
||||
|
@ -613,6 +614,7 @@ class nsXPCWrappedNative : public nsIXPConnectWrappedNative
|
|||
NS_IMETHOD GetIID(nsIID** iid); // returns IAllocatator alloc'd copy
|
||||
NS_IMETHOD DebugDump(int depth);
|
||||
NS_IMETHOD SetFinalizeListener(nsIXPConnectFinalizeListener* aListener);
|
||||
NS_IMETHOD GetJSObjectPrototype(JSObject** aJSObj);
|
||||
|
||||
public:
|
||||
static nsXPCWrappedNative* GetNewOrUsedWrapper(XPCContext* xpcc,
|
||||
|
|
|
@ -429,6 +429,14 @@ nsXPCWrappedNative::SetFinalizeListener(nsIXPConnectFinalizeListener* aListener)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPCWrappedNative::GetJSObjectPrototype(JSObject** aJSObj)
|
||||
{
|
||||
NS_PRECONDITION(aJSObj, "bad param");
|
||||
NS_PRECONDITION(mJSObj, "bad wrapper");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPCWrappedNative::DebugDump(int depth)
|
||||
{
|
||||
|
|
|
@ -798,7 +798,7 @@ nsXPCWrappedNativeClass::NewInstanceJSObject(nsXPCWrappedNative* self)
|
|||
JSClass* jsclazz = self->GetDynamicScriptable() ?
|
||||
&WrappedNativeWithCall_class :
|
||||
&WrappedNative_class;
|
||||
JSObject* jsobj = JS_NewObject(cx, jsclazz, NULL, NULL);
|
||||
JSObject* jsobj = JS_NewObject(cx, jsclazz, NULL, JS_GetGlobalObject(cx));
|
||||
if(!jsobj || !JS_SetPrivate(cx, jsobj, self))
|
||||
return NULL;
|
||||
// wrapper is responsible for calling DynamicScriptable->Create
|
||||
|
|
|
@ -34,6 +34,7 @@ CPPSRCS= \
|
|||
xpctest_echo.cpp \
|
||||
xpctest_child.cpp \
|
||||
xpctest_noisy.cpp \
|
||||
xpctest_overloaded.cpp \
|
||||
xpctest_string.cpp \
|
||||
xpctest_module.cpp \
|
||||
$(NULL)
|
||||
|
|
|
@ -30,6 +30,7 @@ OBJS= \
|
|||
.\$(OBJDIR)\xpctest_echo.obj \
|
||||
.\$(OBJDIR)\xpctest_child.obj \
|
||||
.\$(OBJDIR)\xpctest_noisy.obj \
|
||||
.\$(OBJDIR)\xpctest_overloaded.obj \
|
||||
.\$(OBJDIR)\xpctest_string.obj \
|
||||
.\$(OBJDIR)\xpctest_module.obj \
|
||||
$(NULL)
|
||||
|
|
|
@ -53,6 +53,8 @@ NSGetFactory(nsISupports* aServMgr,
|
|||
rv = factory->SetConstructor(xpctest::ConstructNoisy);
|
||||
else if(aClass.Equals(xpctest::GetStringTestCID()))
|
||||
rv = factory->SetConstructor(xpctest::ConstructStringTest);
|
||||
else if(aClass.Equals(xpctest::GetOverloadedCID()))
|
||||
rv = factory->SetConstructor(xpctest::ConstructOverloaded);
|
||||
else
|
||||
{
|
||||
NS_ASSERTION(0, "incorrectly registered");
|
||||
|
@ -60,10 +62,9 @@ NSGetFactory(nsISupports* aServMgr,
|
|||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
delete factory;
|
||||
NS_RELEASE(factory);
|
||||
return rv;
|
||||
}
|
||||
NS_ADDREF(factory);
|
||||
*aFactory = factory;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -95,6 +96,11 @@ NSRegisterSelf(nsISupports* aServMgr , const char* aPath)
|
|||
"nsStringTest", "nsStringTest", aPath,
|
||||
PR_TRUE, PR_TRUE);
|
||||
|
||||
rv = compMgr->RegisterComponent(xpctest::GetOverloadedCID(),
|
||||
"nsOverloaded", "nsOverloaded", aPath,
|
||||
PR_TRUE, PR_TRUE);
|
||||
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -110,6 +116,7 @@ NSUnregisterSelf(nsISupports* aServMgr, const char* aPath)
|
|||
rv = compMgr->UnregisterComponent(xpctest::GetChildCID(), aPath);
|
||||
rv = compMgr->UnregisterComponent(xpctest::GetNoisyCID(), aPath);
|
||||
rv = compMgr->UnregisterComponent(xpctest::GetStringTestCID(), aPath);
|
||||
rv = compMgr->UnregisterComponent(xpctest::GetOverloadedCID(), aPath);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,271 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/* implement nsIXPCTestOverloaded as an example. */
|
||||
|
||||
#include "xpctest_private.h"
|
||||
#include "nsIXPCScriptable.h"
|
||||
|
||||
/*
|
||||
* This is an example of one way to reflect an interface into JavaScript such
|
||||
* that one method name is overloaded to reflect multiple methods. This practice
|
||||
* is strongly discouraged. But, some legacy JavaScript interfaces require this
|
||||
* in order to support existing JavaScript code.
|
||||
*/
|
||||
|
||||
/***************************************************************************/
|
||||
/* This is a JS example of calling the object implemented below. */
|
||||
|
||||
/*
|
||||
* // to run this in the shell...
|
||||
* // put this in "foo.js" and the run "xpcshell foo.js"
|
||||
*
|
||||
* var clazz = Components.classes.nsOverloaded;
|
||||
* var iface = Components.interfaces.nsIXPCTestOverloaded;
|
||||
*
|
||||
* foo = clazz.createInstance(iface);
|
||||
*
|
||||
* try {
|
||||
* print("foo.Foo1(1)... "); foo.Foo1(1)
|
||||
* print("foo.Foo2(1,2)..."); foo.Foo2(1,2)
|
||||
* print("foo.Foo(3)... "); foo.Foo(3)
|
||||
* print("foo.Foo(3,4)... "); foo.Foo(3,4)
|
||||
* print("foo.Foo()... "); foo.Foo();
|
||||
* } catch(e) {
|
||||
* print("caught exception: "+e);
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*
|
||||
* This is the implementation of nsIXPCScriptable. This interface is used
|
||||
* by xpconnect in order to allow wrapped native objects to gain greater
|
||||
* control over how they are reflected into JavaScript. Most wrapped native
|
||||
* objects do not need to implement this interface. It is useful for dynamic
|
||||
* properties (those properties not explicitly mentioned in the .idl file).
|
||||
* Here we are using the nsIXPCScriptable as a way to bootstrap some JS code
|
||||
* to be run each time a wrapper is built around an instance of our object.
|
||||
*
|
||||
* xpconnect allows implementors of nsIXPCScriptable to bend the rules a bit...
|
||||
* implementations of nsIXPCScriptable are not required to follow QueryInterface
|
||||
* identity rules; i.e. doing a QI(nsISupports::GetIID()) on this interface is
|
||||
* not required to return the same pointer as doing so on the object that
|
||||
* presented this interface. Thus, it is allowable to implement only one
|
||||
* nsIXPCScriptable instance per class if desired.
|
||||
*/
|
||||
|
||||
class xpcoverloadedScriptable : public nsIXPCScriptable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
XPC_DECLARE_IXPCSCRIPTABLE
|
||||
xpcoverloadedScriptable();
|
||||
virtual ~xpcoverloadedScriptable();
|
||||
};
|
||||
|
||||
xpcoverloadedScriptable::xpcoverloadedScriptable()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF_THIS();
|
||||
}
|
||||
xpcoverloadedScriptable::~xpcoverloadedScriptable()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
static NS_DEFINE_IID(kxpcoverloadedScriptableIID, NS_IXPCSCRIPTABLE_IID);
|
||||
NS_IMPL_ISUPPORTS(xpcoverloadedScriptable, kxpcoverloadedScriptableIID);
|
||||
|
||||
// These macros give default implementations for these methods.
|
||||
|
||||
//XPC_IMPLEMENT_FORWARD_CREATE(xpcoverloadedScriptable)
|
||||
XPC_IMPLEMENT_FORWARD_LOOKUPPROPERTY(xpcoverloadedScriptable)
|
||||
XPC_IMPLEMENT_FORWARD_DEFINEPROPERTY(xpcoverloadedScriptable)
|
||||
XPC_IMPLEMENT_FORWARD_GETPROPERTY(xpcoverloadedScriptable)
|
||||
XPC_IMPLEMENT_FORWARD_SETPROPERTY(xpcoverloadedScriptable)
|
||||
XPC_IMPLEMENT_FORWARD_GETATTRIBUTES(xpcoverloadedScriptable)
|
||||
XPC_IMPLEMENT_FORWARD_SETATTRIBUTES(xpcoverloadedScriptable)
|
||||
XPC_IMPLEMENT_FORWARD_DELETEPROPERTY(xpcoverloadedScriptable)
|
||||
XPC_IMPLEMENT_FORWARD_DEFAULTVALUE(xpcoverloadedScriptable)
|
||||
XPC_IMPLEMENT_FORWARD_ENUMERATE(xpcoverloadedScriptable)
|
||||
XPC_IMPLEMENT_FORWARD_CHECKACCESS(xpcoverloadedScriptable)
|
||||
XPC_IMPLEMENT_FORWARD_CALL(xpcoverloadedScriptable)
|
||||
XPC_IMPLEMENT_FORWARD_CONSTRUCT(xpcoverloadedScriptable)
|
||||
XPC_IMPLEMENT_FORWARD_FINALIZE(xpcoverloadedScriptable)
|
||||
|
||||
// we implement this method ourselves
|
||||
|
||||
NS_IMETHODIMP
|
||||
xpcoverloadedScriptable::Create(JSContext *cx, JSObject *obj,
|
||||
nsIXPConnectWrappedNative* wrapper,
|
||||
nsIXPCScriptable* arbitrary)
|
||||
{
|
||||
/*
|
||||
* Here are two implementations...
|
||||
*
|
||||
* The first uses a shared prototype object to implement the forwarding
|
||||
* function.
|
||||
*
|
||||
* The second adds the forwarding function to each and every object
|
||||
*/
|
||||
#if 1
|
||||
/*
|
||||
* NOTE: in the future xpconnect is likely to build and maintain a
|
||||
* 'per CLSID' prototype object. When we have flattened interfaces code will
|
||||
* be able to ask the wrapper for the prototype object. The prototype object
|
||||
* will be shared by all wrapped objects with the given CLSID.
|
||||
*
|
||||
* *** If anyone uses the code below to make their own prototype objects they
|
||||
* should be prepared to convert the code when the new scheme arrives. ***
|
||||
*/
|
||||
|
||||
static const char name[] = "__xpcoverloadedScriptableProto__";
|
||||
static const char source[] =
|
||||
"__xpcoverloadedScriptableProto__ = {"
|
||||
" Foo : function() {"
|
||||
" switch(arguments.length) {"
|
||||
" case 1: return this.Foo1(arguments[0]);"
|
||||
" case 2: return this.Foo2(arguments[0], arguments[1]);"
|
||||
" default: throw '1 or 2 arguments required';"
|
||||
" }"
|
||||
" }"
|
||||
"};";
|
||||
|
||||
jsval proto;
|
||||
|
||||
if(!JS_GetProperty(cx, JS_GetGlobalObject(cx), name, &proto) ||
|
||||
JSVAL_IS_PRIMITIVE(proto))
|
||||
{
|
||||
if(!JS_EvaluateScript(cx, JS_GetGlobalObject(cx), source, strlen(source),
|
||||
"builtin", 1, &proto) ||
|
||||
!JS_GetProperty(cx, JS_GetGlobalObject(cx), name, &proto)||
|
||||
JSVAL_IS_PRIMITIVE(proto))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
if(!JS_SetPrototype(cx, obj, JSVAL_TO_OBJECT(proto)))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
return NS_OK;
|
||||
|
||||
#else
|
||||
// NOTE: this script is evaluated where the wrapped object is the current
|
||||
// 'this'.
|
||||
|
||||
// here is a 'Foo' implementation that will forward to the appropriate
|
||||
// non-overloaded method.
|
||||
static const char source[] =
|
||||
"this.Foo = function() {"
|
||||
" switch(arguments.length) {"
|
||||
" case 1: return this.Foo1(arguments[0]);"
|
||||
" case 2: return this.Foo2(arguments[0], arguments[1]);"
|
||||
" default: throw '1 or 2 arguments required';"
|
||||
" }"
|
||||
"};";
|
||||
|
||||
jsval ignored;
|
||||
JS_EvaluateScript(cx, obj, source, strlen(source), "builtin", 1, &ignored);
|
||||
return NS_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
class xpcoverloaded : public nsIXPCTestOverloaded
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
/* void Foo1 (in PRInt32 p1); */
|
||||
NS_IMETHOD Foo1(PRInt32 p1);
|
||||
|
||||
/* void Foo2 (in PRInt32 p1, in PRInt32 p2); */
|
||||
NS_IMETHOD Foo2(PRInt32 p1, PRInt32 p2);
|
||||
|
||||
xpcoverloaded();
|
||||
virtual ~xpcoverloaded();
|
||||
private:
|
||||
xpcoverloadedScriptable* mScriptable;
|
||||
};
|
||||
|
||||
xpcoverloaded::xpcoverloaded()
|
||||
: mScriptable(new xpcoverloadedScriptable())
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF_THIS();
|
||||
}
|
||||
|
||||
xpcoverloaded::~xpcoverloaded()
|
||||
{
|
||||
if(mScriptable)
|
||||
NS_RELEASE(mScriptable);
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(xpcoverloaded)
|
||||
NS_IMPL_RELEASE(xpcoverloaded)
|
||||
// this macro is a simple way to expose nsIXPCScriptable implementation
|
||||
NS_IMPL_QUERY_INTERFACE_SCRIPTABLE(xpcoverloaded, mScriptable)
|
||||
|
||||
|
||||
/* void Foo1 (in PRInt32 p1); */
|
||||
NS_IMETHODIMP
|
||||
xpcoverloaded::Foo1(PRInt32 p1)
|
||||
{
|
||||
printf("xpcoverloaded::Foo1 called with p1 = %d\n", p1);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void Foo2 (in PRInt32 p1, in PRInt32 p2); */
|
||||
NS_IMETHODIMP
|
||||
xpcoverloaded::Foo2(PRInt32 p1, PRInt32 p2)
|
||||
{
|
||||
printf("xpcoverloaded::Foo2 called with p1 = %d and p2 = %d\n", p1, p2);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
// our standard generic factory helper.
|
||||
|
||||
// static
|
||||
NS_IMETHODIMP
|
||||
xpctest::ConstructOverloaded(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_ASSERTION(aOuter == nsnull, "no aggregation");
|
||||
xpcoverloaded* obj = new xpcoverloaded();
|
||||
|
||||
if(obj)
|
||||
{
|
||||
rv = obj->QueryInterface(aIID, aResult);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to find correct interface");
|
||||
NS_RELEASE(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
*aResult = nsnull;
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
|
@ -55,6 +55,12 @@
|
|||
{ 0x4dd7ec80, 0x30d9, 0x11d3,\
|
||||
{ 0x98, 0x85, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
|
||||
|
||||
// {DC5FDE90-439D-11d3-988C-006008962422}
|
||||
#define NS_OVERLOADED_CID \
|
||||
{ 0xdc5fde90, 0x439d, 0x11d3, \
|
||||
{ 0x98, 0x8c, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
|
||||
|
||||
|
||||
// 'namespace' class
|
||||
class xpctest
|
||||
{
|
||||
|
@ -71,6 +77,9 @@ public:
|
|||
static const nsID& GetStringTestCID() {static nsID cid = NS_STRING_TEST_CID; return cid;}
|
||||
static NS_METHOD ConstructStringTest(nsISupports *aOuter, REFNSIID aIID, void **aResult);
|
||||
|
||||
static const nsID& GetOverloadedCID() {static nsID cid = NS_OVERLOADED_CID; return cid;}
|
||||
static NS_METHOD ConstructOverloaded(nsISupports *aOuter, REFNSIID aIID, void **aResult);
|
||||
|
||||
private:
|
||||
xpctest(); // not implemented
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче