From cc5872f551299e9a74602ce80092168242314656 Mon Sep 17 00:00:00 2001 From: "jband%netscape.com" Date: Tue, 16 Feb 1999 06:29:29 +0000 Subject: [PATCH] NOT YET PART Of SEAMONKEY - fixes for conversions, added 'load' to test program to breakout js code into its own file, added support for global object being a wrapped native, fixed parent interface support, change makefiles for JS_THREADSAFE, add missing dropProperty support to my Ops, added more tests --- js/src/xpconnect/makefile.win | 2 +- js/src/xpconnect/nsIXPConnect.h | 5 + js/src/xpconnect/nsXPConnect.cpp | 60 ++++++++- js/src/xpconnect/test/TestXPC.cpp | 116 +++++++++++++---- js/src/xpconnect/test/makefile.win | 6 +- js/src/xpconnect/test/testxpc.js | 51 ++++++++ js/src/xpconnect/xpccontext.cpp | 16 ++- js/src/xpconnect/xpcprivate.h | 14 +- js/src/xpconnect/xpcwrappedjsclass.cpp | 142 +++++++++++++++++---- js/src/xpconnect/xpcwrappednativeclass.cpp | 15 ++- js/src/xpconnect/xpt_cpp.cpp | 14 +- js/src/xpconnect/xpt_cpp.h | 2 +- 12 files changed, 366 insertions(+), 77 deletions(-) create mode 100644 js/src/xpconnect/test/testxpc.js diff --git a/js/src/xpconnect/makefile.win b/js/src/xpconnect/makefile.win index ca094a153a2d..de1dfcbe5a25 100644 --- a/js/src/xpconnect/makefile.win +++ b/js/src/xpconnect/makefile.win @@ -28,7 +28,7 @@ DLL =.\$(OBJDIR)\$(DLLNAME).dll MODULE=xpconnect REQUIRES=xpcom js -DEFINES=-DWIN32_LEAN_AND_MEAN -DEXPORT_XPC_API +DEFINES=-DWIN32_LEAN_AND_MEAN -DEXPORT_XPC_API -DJS_THREADSAFE -DDEBUG OBJS= \ .\$(OBJDIR)\xpt_cpp.obj \ diff --git a/js/src/xpconnect/nsIXPConnect.h b/js/src/xpconnect/nsIXPConnect.h index 7682074b2fdc..b8e1a45b5fc9 100644 --- a/js/src/xpconnect/nsIXPConnect.h +++ b/js/src/xpconnect/nsIXPConnect.h @@ -114,6 +114,11 @@ public: NS_IMETHOD InitJSContext(JSContext* aJSContext, JSObject* aGlobalJSObj) = 0; + NS_IMETHOD InitJSContextWithNewWrappedGlobal(JSContext* aJSContext, + nsISupports* aCOMObj, + REFNSIID aIID, + nsIXPConnectWrappedNative** aWrapper) = 0; + NS_IMETHOD WrapNative(JSContext* aJSContext, nsISupports* aCOMObj, REFNSIID aIID, diff --git a/js/src/xpconnect/nsXPConnect.cpp b/js/src/xpconnect/nsXPConnect.cpp index e493499ea273..803101b500cd 100644 --- a/js/src/xpconnect/nsXPConnect.cpp +++ b/js/src/xpconnect/nsXPConnect.cpp @@ -110,6 +110,8 @@ nsXPConnect::nsXPConnect() { NS_INIT_REFCNT(); NS_ADDREF_THIS(); + + nsXPCWrappedNativeClass::OneTimeInit(); mContextMap = JSContext2XPCContextMap::newMap(CONTEXT_MAP_SIZE); mArbitraryScriptable = new nsXPCArbitraryScriptable(); @@ -140,21 +142,60 @@ NS_IMETHODIMP nsXPConnect::InitJSContext(JSContext* aJSContext, JSObject* aGlobalJSObj) { - if(!aJSContext || !aGlobalJSObj || - mContextMap->Find(aJSContext) || !NewContext(aJSContext, aGlobalJSObj)) + if(aJSContext) { - NS_ASSERTION(0,"nsXPConnect::InitJSContext failed"); - return NS_ERROR_FAILURE; + if(!aGlobalJSObj) + aGlobalJSObj = JS_GetGlobalObject(aJSContext); + if(aGlobalJSObj && + !mContextMap->Find(aJSContext) && + NewContext(aJSContext, aGlobalJSObj)) + { + return NS_OK; + } + } + NS_ASSERTION(0,"nsXPConnect::InitJSContext failed"); + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsXPConnect::InitJSContextWithNewWrappedGlobal(JSContext* aJSContext, + nsISupports* aCOMObj, + REFNSIID aIID, + nsIXPConnectWrappedNative** aWrapper) +{ + nsXPCWrappedNative* wrapper = NULL; + XPCContext* xpcc = NULL; + if(!mContextMap->Find(aJSContext) && + NULL != (xpcc = NewContext(aJSContext, NULL, JS_FALSE))) + { + wrapper = nsXPCWrappedNative::GetNewOrUsedWrapper(xpcc, aCOMObj, aIID); + if(wrapper) + { + if(JS_InitStandardClasses(aJSContext, wrapper->GetJSObject()) && + xpcc->Init(wrapper->GetJSObject())) + { + *aWrapper = wrapper; + return NS_OK; + } + } } - return NS_OK; + if(wrapper) + NS_RELEASE(wrapper); + if(xpcc) + { + mContextMap->Remove(xpcc); + delete xpcc; + } + *aWrapper = NULL; + return NS_ERROR_FAILURE; } XPCContext* -nsXPConnect::NewContext(JSContext* cx, JSObject* global) +nsXPConnect::NewContext(JSContext* cx, JSObject* global, + JSBool doInit /*= JS_TRUE*/) { XPCContext* xpcc; NS_PRECONDITION(cx,"bad param"); - NS_PRECONDITION(global,"bad param"); NS_PRECONDITION(!mContextMap->Find(cx),"bad param"); xpcc = XPCContext::newXPCContext(cx, global, @@ -162,6 +203,11 @@ nsXPConnect::NewContext(JSContext* cx, JSObject* global) NATIVE_MAP_SIZE, JS_CLASS_MAP_SIZE, NATIVE_CLASS_MAP_SIZE); + if(doInit && xpcc && !xpcc->Init()) + { + delete xpcc; + xpcc = NULL; + } if(xpcc) mContextMap->Add(xpcc); return xpcc; diff --git a/js/src/xpconnect/test/TestXPC.cpp b/js/src/xpconnect/test/TestXPC.cpp index 66ad804b1bcc..1815cd627126 100644 --- a/js/src/xpconnect/test/TestXPC.cpp +++ b/js/src/xpconnect/test/TestXPC.cpp @@ -141,8 +141,15 @@ class MyScriptable : public nsIXPCScriptable { NS_DECL_ISUPPORTS; XPC_DECLARE_IXPCSCRIPTABLE; + MyScriptable(); }; +MyScriptable::MyScriptable() +{ + NS_INIT_REFCNT(); + NS_ADDREF_THIS(); +} + NS_IMPL_ISUPPORTS(MyScriptable,NS_IXPCSCRIPTABLE_IID); // XPC_IMPLEMENT_FORWARD_IXPCSCRIPTABLE(MyScriptable); @@ -244,6 +251,7 @@ static NS_DEFINE_IID(kWrappedJSMethodsIID, NS_IXPCONNECT_WRAPPED_JS_METHODS_IID) /***************************************************************************/ FILE *gOutFile = NULL; +FILE *gErrFile = NULL; static JSBool Print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) @@ -263,8 +271,38 @@ Print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) return JS_TRUE; } +static JSBool +Load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + uintN i; + JSString *str; + const char *filename; + JSScript *script; + JSBool ok; + jsval result; + + for (i = 0; i < argc; i++) { + str = JS_ValueToString(cx, argv[i]); + if (!str) + return JS_FALSE; + argv[i] = STRING_TO_JSVAL(str); + filename = JS_GetStringBytes(str); + script = JS_CompileFile(cx, obj, filename); + if (!script) + ok = JS_FALSE; + else { + ok = JS_ExecuteScript(cx, obj, script, &result); + JS_DestroyScript(cx, script); + } + if (!ok) + return JS_FALSE; + } + return JS_TRUE; +} + static JSFunctionSpec glob_functions[] = { {"print", Print, 0}, + {"load", Load, 1}, {0} }; @@ -286,6 +324,7 @@ int main() JSContext *cx; JSObject *glob; + gErrFile = stderr; gOutFile = stdout; RegAllocator(); @@ -299,6 +338,10 @@ int main() JS_SetErrorReporter(cx, my_ErrorReporter); + nsIXPConnect* xpc = XPC_GetXPConnect(); + +/* + // old code where global object was plain object glob = JS_NewObject(cx, &global_class, NULL, NULL); if (!glob) return 1; @@ -308,8 +351,8 @@ int main() if (!JS_DefineFunctions(cx, glob, glob_functions)) return 1; - nsIXPConnect* xpc = XPC_GetXPConnect(); xpc->InitJSContext(cx, glob); +*/ nsTestXPCFoo* foo = new nsTestXPCFoo(); @@ -322,8 +365,16 @@ int main() nsIXPConnectWrappedNative* wrapper; nsIXPConnectWrappedNative* wrapper2; +/* if(NS_SUCCEEDED(xpc->WrapNative(cx, foo, kIFooIID, &wrapper))) +*/ + // new code where global object is a wrapped xpcom object + if(NS_SUCCEEDED(xpc->InitJSContextWithNewWrappedGlobal(cx, foo, kIFooIID, + &wrapper))) { + wrapper->GetJSObject(&glob); + JS_DefineFunctions(cx, glob, glob_functions); + if(NS_SUCCEEDED(xpc->WrapNative(cx, foo, kIFoo2IID, &wrapper2))) { JSObject* js_obj; @@ -338,27 +389,8 @@ int main() JS_SetProperty(cx, glob, "foo", &v); char* txt[] = { - "print('foo = '+foo);", - "foo.toString = new Function('return \"foo toString called\";')", - "foo.toStr = new Function('return \"foo toStr called\";')", - "print('foo = '+foo);", - "print('foo.toString() = '+foo.toString());", - "print('foo.toStr() = '+foo.toStr());", - "print('foo.five = '+ foo.five);", - "print('foo.six = '+ foo.six);", - "print('foo.bogus = '+ foo.bogus);", - "foo.bogus = 5;", - "print('foo.bogus = '+ foo.bogus);", - "print('foo.Test(10,20) returned: '+foo.Test(10,20));", - "function Test(p1, p2){print('test called in JS with p1 = '+p1+' and p2 = '+p2);return p1+p2;}", - "bar = new Object();", - "bar.Test = Test;", -// "bar.Test(5,7);", - "function QI(iid){print('QueryInterface called in JS with iid = '+iid); return this;}", - "bar.QueryInterface = QI;", - "print('foo properties:');", - "for(i in foo)print(' foo.'+i+' = '+foo[i]);", - 0, + "load('testxpc.js');", + 0, }; for(char** p = txt; *p; p++) @@ -407,3 +439,43 @@ int main() return 0; } + +/***************************************************************************/ + +#include "jsatom.h" +int +DumpAtom(JSHashEntry *he, int i, void *arg) +{ + FILE *fp = (FILE *)arg; + JSAtom *atom = (JSAtom *)he; + + fprintf(fp, "%3d %08x %5lu ", + i, (uintN)he->keyHash, (unsigned long)atom->number); + if (ATOM_IS_STRING(atom)) + fprintf(fp, "\"%s\"\n", ATOM_BYTES(atom)); + else if (ATOM_IS_INT(atom)) + fprintf(fp, "%ld\n", (long)ATOM_TO_INT(atom)); + else + fprintf(fp, "%.16g\n", *ATOM_TO_DOUBLE(atom)); + return HT_ENUMERATE_NEXT; +} + +int +DumpSymbol(JSHashEntry *he, int i, void *arg) +{ + FILE *fp = (FILE *)arg; + JSSymbol *sym = (JSSymbol *)he; + + fprintf(fp, "%3d %08x", i, (uintN)he->keyHash); + if (JSVAL_IS_INT(sym_id(sym))) + fprintf(fp, " [%ld]\n", (long)JSVAL_TO_INT(sym_id(sym))); + else + fprintf(fp, " \"%s\"\n", ATOM_BYTES(sym_atom(sym))); + return HT_ENUMERATE_NEXT; +} + +/* These are callable from gdb. */ +JS_BEGIN_EXTERN_C +void Dsym(JSSymbol *sym) { if (sym) DumpSymbol(&sym->entry, 0, gErrFile); } +void Datom(JSAtom *atom) { if (atom) DumpAtom(&atom->entry, 0, gErrFile); } +JS_END_EXTERN_C diff --git a/js/src/xpconnect/test/makefile.win b/js/src/xpconnect/test/makefile.win index 864b749d4fa4..9ff53134c800 100644 --- a/js/src/xpconnect/test/makefile.win +++ b/js/src/xpconnect/test/makefile.win @@ -22,8 +22,11 @@ IGNORE_MANIFEST=1 MAKE_OBJ_TYPE = EXE PROG1 = .\$(OBJDIR)\TestXPC.exe PROGRAMS = $(PROG1) +TESTCASES = testxpc.js -LCFLAGS=-DUSE_NSREG +LCFLAGS=-DUSE_NSREG -DJSFILE + +DEFINES=-DWIN32_LEAN_AND_MEAN -DJS_THREADSAFE -DDEBUG REQUIRES=xpcom js xpconnect @@ -43,6 +46,7 @@ include <$(DEPTH)\config\rules.mak> install:: $(PROGRAMS) -for %p in ($(PROGRAMS)) do $(MAKE_INSTALL) %p $(DIST)\bin + -for %p in ($(TESTCASES)) do $(MAKE_INSTALL) %p $(DIST)\bin clobber:: -for %p in ($(PROGRAMS)) do $(RM) %p $(DIST)\bin\%p diff --git a/js/src/xpconnect/test/testxpc.js b/js/src/xpconnect/test/testxpc.js new file mode 100644 index 000000000000..fa08ecf4336c --- /dev/null +++ b/js/src/xpconnect/test/testxpc.js @@ -0,0 +1,51 @@ +// test case... + +var NS_ISUPPORTS_IID = new nsID("{00000000-0000-0000-c000-000000000046}"); +var NS_ITESTXPC_FOO_IID = new nsID("{159E36D0-991E-11d2-AC3F-00C09300144B}"); + +var baz = foo.QueryInterface(NS_ITESTXPC_FOO_IID); +print("baz = "+baz); +print("distinct wrapper test "+ (foo != baz ? "passed" : "failed")); +var baz2 = foo.QueryInterface(NS_ITESTXPC_FOO_IID); +print("shared wrapper test "+ (baz == baz2 ? "passed" : "failed")); +print("root wrapper identity test "+ + (foo.QueryInterface(NS_ISUPPORTS_IID) == + baz.QueryInterface(NS_ISUPPORTS_IID) ? + "passed" : "failed")); + +print("foo = "+foo); +foo.toString = new Function("return 'foo toString called';") +foo.toStr = new Function("return 'foo toStr called';") +print("foo = "+foo); +print("foo.toString() = "+foo.toString()); +print("foo.toStr() = "+foo.toStr()); +print("foo.five = "+ foo.five); +print("foo.six = "+ foo.six); +print("foo.bogus = "+ foo.bogus); +print("setting bogus explicitly to '5'..."); +foo.bogus = 5; +print("foo.bogus = "+ foo.bogus); +print("foo.Test(10,20) returned: "+foo.Test(10,20)); + +function _Test(p1, p2) +{ + print("test called in JS with p1 = "+p1+" and p2 = "+p2); + return p1+p2; +} + +function _QI(iid) +{ + print("QueryInterface called in JS with iid = "+iid); + return this; +} + +print("creating bar"); +bar = new Object(); +bar.Test = _Test; +bar.QueryInterface = _QI; +// this 'bar' object is accessed from native code after this script is run + +print("foo properties:"); +for(i in foo) + print(" foo."+i+" = "+foo[i]); + diff --git a/js/src/xpconnect/xpccontext.cpp b/js/src/xpconnect/xpccontext.cpp index f4ebf76091ce..06754fcd3d20 100644 --- a/js/src/xpconnect/xpccontext.cpp +++ b/js/src/xpconnect/xpccontext.cpp @@ -32,7 +32,6 @@ XPCContext::newXPCContext(JSContext* aJSContext, XPCContext* xpcc; NS_PRECONDITION(aJSContext,"bad param"); - NS_PRECONDITION(aGlobalObj,"bad param"); NS_PRECONDITION(WrappedJSMapSize,"bad param"); NS_PRECONDITION(WrappedNativeMapSize,"bad param"); NS_PRECONDITION(WrappedJSClassMapSize,"bad param"); @@ -50,10 +49,7 @@ XPCContext::newXPCContext(JSContext* aJSContext, xpcc->GetWrappedJSMap() && xpcc->GetWrappedNativeMap() && xpcc->GetWrappedJSClassMap() && - xpcc->GetWrappedNativeClassMap() && - xpc_InitIDClass(xpcc) && - nsXPCWrappedJSClass::InitForContext(xpcc) && - nsXPCWrappedNativeClass::InitForContext(xpcc)) + xpcc->GetWrappedNativeClassMap()) { return xpcc; } @@ -90,3 +86,13 @@ XPCContext::~XPCContext() if(mWrappedNativeClassMap) delete mWrappedNativeClassMap; } + +JSBool +XPCContext::Init(JSObject* aGlobalObj /*= NULL*/) +{ + if(aGlobalObj) + mGlobalObj = aGlobalObj; + return xpc_InitIDClass(this) && + nsXPCWrappedJSClass::InitForContext(this) && + nsXPCWrappedNativeClass::InitForContext(this); +} diff --git a/js/src/xpconnect/xpcprivate.h b/js/src/xpconnect/xpcprivate.h index 8b08ab7a8ec8..bc50958d57eb 100644 --- a/js/src/xpconnect/xpcprivate.h +++ b/js/src/xpconnect/xpcprivate.h @@ -49,6 +49,11 @@ class nsXPConnect : public nsIXPConnect NS_IMETHOD InitJSContext(JSContext* aJSContext, JSObject* aGlobalJSObj); + NS_IMETHOD InitJSContextWithNewWrappedGlobal(JSContext* aJSContext, + nsISupports* aCOMObj, + REFNSIID aIID, + nsIXPConnectWrappedNative** aWrapper); + NS_IMETHOD WrapNative(JSContext* aJSContext, nsISupports* aCOMObj, REFNSIID aIID, @@ -76,7 +81,8 @@ public: virtual ~nsXPConnect(); private: nsXPConnect(); - XPCContext* NewContext(JSContext* cx, JSObject* global); + XPCContext* NewContext(JSContext* cx, JSObject* global, + JSBool doInit = JS_TRUE); private: static nsXPConnect* mSelf; @@ -110,6 +116,8 @@ public: IID2WrappedJSClassMap* GetWrappedJSClassMap() {return mWrappedJSClassMap;} IID2WrappedNativeClassMap* GetWrappedNativeClassMap() {return mWrappedNativeClassMap;} + JSBool Init(JSObject* aGlobalObj = NULL); + ~XPCContext(); private: XPCContext(); // no implementation @@ -280,7 +288,7 @@ public: void SetWritableAttribute() {flags=(flags&~NMD_CAT_MASK)|NMD_ATTRIB_RW;} XPCNativeMemberDescriptor() - : invokeFuncObj(NULL), id(0){} + : invokeFuncObj(NULL), id(0), flags(0) {} private: uint16 flags; }; @@ -318,6 +326,8 @@ public: {return GetXPCContext()->GetXPConnect()->GetArbitraryScriptable();} static JSBool InitForContext(XPCContext* xpcc); + static JSBool OneTimeInit(); + JSObject* NewInstanceJSObject(nsXPCWrappedNative* self); static nsXPCWrappedNative* GetWrappedNativeOfJSObject(JSContext* cx, JSObject* jsobj); diff --git a/js/src/xpconnect/xpcwrappedjsclass.cpp b/js/src/xpconnect/xpcwrappedjsclass.cpp index 36672e92e527..d7761517acb7 100644 --- a/js/src/xpconnect/xpcwrappedjsclass.cpp +++ b/js/src/xpconnect/xpcwrappedjsclass.cpp @@ -270,40 +270,42 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex, uint8 argc; jsval result; uint8 paramCount; - nsresult retval = NS_ERROR_UNEXPECTED; + nsresult retval = NS_ERROR_FAILURE; JSErrorReporter older; JSBool success; JSContext* cx = GetJSContext(); + nsIAllocator* al = NULL; + JSBool InConversionsDone = JS_FALSE; + + if(!(al = nsXPConnect::GetAllocator())) + goto pre_call_clean_up; if(!IsReflectable(methodIndex)) - { - // XXX we need to go through and free and NULL out all 'out' params - return NS_ERROR_FAILURE; - } + goto pre_call_clean_up; // XXX ASSUMES that retval is last arg. paramCount = info->GetParamCount(); argc = paramCount - (paramCount && info->GetParam(paramCount-1).IsRetval() ? 1 : 0); - // XXX do we need to go through and NULL out all 'out' params? - // setup argv if(argc > ARGS_BUFFER_COUNT) { if(!(argv = new jsval[argc])) - return NS_ERROR_OUT_OF_MEMORY; + { + retval = NS_ERROR_OUT_OF_MEMORY; + goto pre_call_clean_up; + } } else argv = argsBuffer; - // from here on out we exit via 'goto done' // build the args for(i = 0; i < argc; i++) { + nsID* conditional_iid = NULL; const nsXPTParamInfo& param = info->GetParam(i); const nsXPTType& type = param.GetType(); - jsval val; if(param.IsIn()) @@ -315,13 +317,31 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex, else pv = ¶ms[i]; - if(type.IsPointer()) - pv = (nsXPCMiniVariant*) pv->val.p; - - if(!XPCConvert::NativeData2JS(cx, &val, &pv->val, type, NULL)) + if(type.TagPart() == nsXPTType::T_INTERFACE) { - retval = NS_ERROR_FAILURE; - goto done; + if(!(conditional_iid = param.GetInterfaceIID())) + goto pre_call_clean_up; + } + else if(type.TagPart() == nsXPTType::T_INTERFACE_IS) + { + uint8 arg_num = param.GetInterfaceIsArgNumber(); + const nsXPTParamInfo& param = info->GetParam(arg_num); + const nsXPTType& type = param.GetType(); + if(type.IsPointer() && type.TagPart() == nsXPTType::T_IID) + { + if(param.IsOut()) + conditional_iid = *((nsID**)params[arg_num].val.p); + else + conditional_iid = (nsID*) params[arg_num].val.p; + } + if(!conditional_iid) + goto pre_call_clean_up; + } + + if(!XPCConvert::NativeData2JS(cx, &val, &pv->val, type, + conditional_iid)) + { + goto pre_call_clean_up; } } @@ -332,13 +352,56 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex, if(param.IsIn()) { if(!JS_SetProperty(cx, obj, XPC_VAL_STR, &val)) - goto done; + goto pre_call_clean_up; } argv[i] = OBJECT_TO_JSVAL(obj); } else argv[i] = val; } + InConversionsDone = JS_TRUE; + +pre_call_clean_up: + // clean up any 'out' params handed in + for(i = 0; i < paramCount; i++) + { + const nsXPTParamInfo& param = info->GetParam(i); + if(!param.IsOut()) + continue; + + const nsXPTType& type = param.GetType(); + if(!type.IsPointer()) + continue; + if(!params[i].val.p) + continue; + + if(type.IsInterfacePointer()) + { + if(param.IsIn()) + { + nsISupports** pp; + if((NULL != (pp = (nsISupports**) params[i].val.p)) && + NULL != *pp) + { + (*pp)->Release(); + *pp = NULL; + } + } + } + else + { + void** pp; + if((NULL != (pp = (void**) params[i].val.p)) && NULL != *pp && al) + { + if(param.IsIn()) + al->Free(*pp); + *pp = NULL; + } + } + } + + if(!InConversionsDone) + goto done; // do the function call @@ -347,10 +410,7 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex, argc, argv, &result); JS_SetErrorReporter(cx, older); if(!success) - { - retval = NS_ERROR_FAILURE; goto done; - } // convert out args and result // NOTE: this is the total number of native params, not just the args @@ -361,31 +421,59 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex, if(param.IsOut()) { jsval val; + nsIAllocator* conditional_al = NULL; + nsID* conditional_iid = NULL; const nsXPTType& type = param.GetType(); nsXPCMiniVariant* pv; + pv = (nsXPCMiniVariant*) params[i].val.p; + if(param.IsRetval()) val = result; else if(!JS_GetProperty(cx, JSVAL_TO_OBJECT(argv[i]), XPC_VAL_STR, &val)) - goto done; + break; - pv = (nsXPCMiniVariant*) params[i].val.p; - if(type.IsPointer()) - pv = (nsXPCMiniVariant*) pv->val.p; + // setup allocator and/or iid - if(!XPCConvert::JSData2Native(cx, &pv->val, val, type, NULL, NULL)) + if(type.TagPart() == nsXPTType::T_INTERFACE) { - NS_ASSERTION(0, "bad type"); - goto done; + if(!(conditional_iid = param.GetInterfaceIID())) + break; } + else if(type.TagPart() == nsXPTType::T_INTERFACE_IS) + { + uint8 arg_num = param.GetInterfaceIsArgNumber(); + const nsXPTParamInfo& param = info->GetParam(arg_num); + const nsXPTType& type = param.GetType(); + if(!type.IsPointer() || type.TagPart() != nsXPTType::T_IID || + !(conditional_iid = *((nsID**)params[arg_num].val.p))) + break; + } + else if(type.IsPointer()) + conditional_al = al; + + if(!XPCConvert::JSData2Native(cx, &pv->val, val, type, + conditional_al, conditional_iid)) + break; } } + // if we didn't manage all the result conversions then we have + // to cleanup any junk that *did* get converted. + if(i != paramCount) + { + // XXX major spagetti! + InConversionsDone = JS_FALSE; + goto pre_call_clean_up; + } + retval = NS_OK; done: if(argv && argv != argsBuffer) delete [] argv; + if(al) + NS_RELEASE(al); return retval; } diff --git a/js/src/xpconnect/xpcwrappednativeclass.cpp b/js/src/xpconnect/xpcwrappednativeclass.cpp index 280a10c40fee..795658af0cb9 100644 --- a/js/src/xpconnect/xpcwrappednativeclass.cpp +++ b/js/src/xpconnect/xpcwrappednativeclass.cpp @@ -454,11 +454,6 @@ nsXPCWrappedNativeClass::CallWrappedMethod(nsXPCWrappedNative* wrapper, } else { - if(type.IsPointer()) - { - dp->flags = nsXPCVariant::PTR_IS_DATA; - dp->ptr = &dp->val; - } src = argv[i]; } @@ -1154,13 +1149,19 @@ static JSClass WrappedNative_class = { // static JSBool -nsXPCWrappedNativeClass::InitForContext(XPCContext* xpcc) +nsXPCWrappedNativeClass::OneTimeInit() { WrappedNative_ops.newObjectMap = js_ObjectOps.newObjectMap; WrappedNative_ops.destroyObjectMap = js_ObjectOps.destroyObjectMap; + WrappedNative_ops.dropProperty = js_ObjectOps.dropProperty; + return JS_TRUE; +} +// static +JSBool +nsXPCWrappedNativeClass::InitForContext(XPCContext* xpcc) +{ // XXX do we really want this class init'd this way? access to ctor? - if (!JS_InitClass(xpcc->GetJSContext(), xpcc->GetGlobalObject(), 0, &WrappedNative_class, 0, 0, 0, 0, diff --git a/js/src/xpconnect/xpt_cpp.cpp b/js/src/xpconnect/xpt_cpp.cpp index 89bbaee26a41..e137be037d57 100644 --- a/js/src/xpconnect/xpt_cpp.cpp +++ b/js/src/xpconnect/xpt_cpp.cpp @@ -133,18 +133,24 @@ XPTInterfaceDescriptor nsISupportsInterfaceDescriptor = XPTInterfaceDescriptor nsITestXPCFooInterfaceDescriptor = {NULL, 2, nsITestXPCFooMethods, 3, nsITestXPCFooConstants}; +XPTInterfaceDescriptor nsITestXPCFoo2InterfaceDescriptor = + {NULL, 0, NULL, 0, NULL}; + XPTInterfaceDirectoryEntry InterfaceDirectoryEntryTable[] = { {NS_ISUPPORTS_IID, "nsISupports", "", &nsISupportsInterfaceDescriptor}, {NS_ITESTXPC_FOO_IID, "nsITestXPCFoo", "", &nsITestXPCFooInterfaceDescriptor}, - {NS_ITESTXPC_FOO2_IID, "nsITestXPCFoo2", "", &nsITestXPCFooInterfaceDescriptor} + {NS_ITESTXPC_FOO2_IID, "nsITestXPCFoo2", "", &nsITestXPCFoo2InterfaceDescriptor} }; #define ENTRY_COUNT (sizeof(InterfaceDirectoryEntryTable)/sizeof(InterfaceDirectoryEntryTable[0])) -#define TABLE_INDEX(p) ((p-InterfaceDirectoryEntryTable)/sizeof(InterfaceDirectoryEntryTable[0])) +#define TABLE_INDEX(p) ((p)-InterfaceDirectoryEntryTable) static BogusTableInit() { nsITestXPCFooInterfaceDescriptor.parent_interface = + &InterfaceDirectoryEntryTable[0]; + + nsITestXPCFoo2InterfaceDescriptor.parent_interface = &InterfaceDirectoryEntryTable[1]; } @@ -154,7 +160,7 @@ static BogusTableInit() nsIInterfaceInfo* nsXPTParamInfo::GetInterface() const { - NS_PRECONDITION(GetType() == nsXPTType::T_INTERFACE,"not an interface"); + NS_PRECONDITION(GetType().TagPart() == nsXPTType::T_INTERFACE,"not an interface"); nsIInterfaceInfoManager* mgr; if(!(mgr = InterfaceInfoManagerImpl::GetInterfaceInfoManager())) @@ -171,7 +177,7 @@ nsXPTParamInfo::GetInterface() const nsIID* nsXPTParamInfo::GetInterfaceIID() const { - NS_PRECONDITION(GetType() == nsXPTType::T_INTERFACE,"not an interface"); + NS_PRECONDITION(GetType().TagPart() == nsXPTType::T_INTERFACE,"not an interface"); return &InterfaceDirectoryEntryTable[type.type.interface].iid; } diff --git a/js/src/xpconnect/xpt_cpp.h b/js/src/xpconnect/xpt_cpp.h index 8b43f08d7008..e8f6070ccba9 100644 --- a/js/src/xpconnect/xpt_cpp.h +++ b/js/src/xpconnect/xpt_cpp.h @@ -104,7 +104,7 @@ public: uint8 GetInterfaceIsArgNumber() const { - NS_PRECONDITION(GetType() == nsXPTType::T_INTERFACE_IS,"not an interface_is"); + NS_PRECONDITION(GetType().TagPart() == nsXPTType::T_INTERFACE_IS,"not an interface_is"); return type.type.argnum; }