From 84bfc894a40419d0c4650d92460b94bd648f060b Mon Sep 17 00:00:00 2001 From: "jband%netscape.com" Date: Wed, 31 Oct 2001 23:35:07 +0000 Subject: [PATCH] add support for nsIVariant and nsIPropertyBag. bug 44675 and bug 98209. sr=vidur r=dbradley --- js/src/xpconnect/src/Makefile.in | 1 + js/src/xpconnect/src/makefile.win | 1 + js/src/xpconnect/src/nsScriptError.cpp | 1 - js/src/xpconnect/src/nsXPConnect.cpp | 8 + js/src/xpconnect/src/xpc.msg | 7 + js/src/xpconnect/src/xpccontext.cpp | 6 +- js/src/xpconnect/src/xpcconvert.cpp | 101 +++++++-- js/src/xpconnect/src/xpcforwards.h | 3 + js/src/xpconnect/src/xpcmaps.cpp | 1 - js/src/xpconnect/src/xpcprivate.h | 97 ++++++++- js/src/xpconnect/src/xpcstring.cpp | 1 - js/src/xpconnect/src/xpcwrappedjs.cpp | 29 +++ js/src/xpconnect/src/xpcwrappedjsclass.cpp | 194 ++++++++++++++++++ js/src/xpconnect/src/xpcwrappednative.cpp | 68 +++++- .../xpconnect/src/xpcwrappednativejsops.cpp | 2 +- js/src/xpconnect/tests/TestXPC.cpp | 145 ++++++++----- js/src/xpconnect/tests/components/Makefile.in | 1 + .../xpconnect/tests/components/makefile.win | 1 + .../tests/components/xpctest_echo.cpp | 3 - .../tests/components/xpctest_module.cpp | 5 +- .../tests/components/xpctest_private.h | 7 + js/src/xpconnect/tests/idl/xpctest.idl | 58 ++++++ xpcom/base/nsError.h | 10 + xpcom/base/nsrootidl.idl | 16 +- xpcom/build/dlldeps.cpp | 2 + xpcom/build/nsXPComInit.cpp | 7 +- xpcom/ds/MANIFEST | 1 + xpcom/ds/MANIFEST_IDL | 1 + xpcom/ds/Makefile.in | 4 + xpcom/ds/makefile.win | 4 + xpcom/io/nsIObjectInputStream.idl | 2 - xpcom/proxy/public/nsIProxyCreateInstance.idl | 4 - xpcom/proxy/tests/nsITestProxy.idl | 3 - 33 files changed, 694 insertions(+), 100 deletions(-) diff --git a/js/src/xpconnect/src/Makefile.in b/js/src/xpconnect/src/Makefile.in index 67cfcefefccb..da7b30211afa 100644 --- a/js/src/xpconnect/src/Makefile.in +++ b/js/src/xpconnect/src/Makefile.in @@ -71,6 +71,7 @@ CPPSRCS = \ xpcthreadcontext.cpp \ xpcthrower.cpp \ xpcwrappedjs.cpp \ + xpcvariant.cpp \ xpcwrappedjsclass.cpp \ xpcwrappednative.cpp \ xpcwrappednativeinfo.cpp \ diff --git a/js/src/xpconnect/src/makefile.win b/js/src/xpconnect/src/makefile.win index 4ae3c2800937..ba94c720e99a 100644 --- a/js/src/xpconnect/src/makefile.win +++ b/js/src/xpconnect/src/makefile.win @@ -74,6 +74,7 @@ OBJS= \ .\$(OBJDIR)\xpcstring.obj \ .\$(OBJDIR)\xpcthreadcontext.obj \ .\$(OBJDIR)\xpcthrower.obj \ + .\$(OBJDIR)\xpcvariant.obj \ .\$(OBJDIR)\xpcwrappedjs.obj \ .\$(OBJDIR)\xpcwrappedjsclass.obj \ .\$(OBJDIR)\xpcwrappednative.obj \ diff --git a/js/src/xpconnect/src/nsScriptError.cpp b/js/src/xpconnect/src/nsScriptError.cpp index f8b91c1f58f6..3ea5579fbc71 100644 --- a/js/src/xpconnect/src/nsScriptError.cpp +++ b/js/src/xpconnect/src/nsScriptError.cpp @@ -43,7 +43,6 @@ */ #include "xpcprivate.h" -#include "nsReadableUtils.h" NS_IMPL_THREADSAFE_ISUPPORTS2(nsScriptError, nsIConsoleMessage, nsIScriptError); diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp index 2a9e775f5727..96534b132f69 100644 --- a/js/src/xpconnect/src/nsXPConnect.cpp +++ b/js/src/xpconnect/src/nsXPConnect.cpp @@ -279,6 +279,14 @@ nsXPConnect::GetRuntime(nsXPConnect* xpc /*= nsnull*/) return xpc->EnsureRuntime() ? xpc->mRuntime : nsnull; } +// static +nsIJSRuntimeService* +nsXPConnect::GetJSRuntimeService(nsXPConnect* xpc /* = nsnull */) +{ + XPCJSRuntime* rt = GetRuntime(xpc); + return rt ? rt->GetJSRuntimeService() : nsnull; +} + // static XPCContext* nsXPConnect::GetContext(JSContext* cx, nsXPConnect* xpc /*= nsnull*/) diff --git a/js/src/xpconnect/src/xpc.msg b/js/src/xpconnect/src/xpc.msg index dde50575e34d..5ab0a5780dc0 100644 --- a/js/src/xpconnect/src/xpc.msg +++ b/js/src/xpconnect/src/xpc.msg @@ -147,3 +147,10 @@ XPC_MSG_DEF(NS_ERROR_FILE_NOT_FOUND , "File error: Not found") XPC_MSG_DEF(NS_ERROR_FILE_READ_ONLY , "File error: Read only") XPC_MSG_DEF(NS_ERROR_FILE_DIR_NOT_EMPTY , "File error: Dir not empty") XPC_MSG_DEF(NS_ERROR_FILE_ACCESS_DENIED , "File error: Access denied") + +/* added from nsError.h on Sept 6 2001... */ + +XPC_MSG_DEF(NS_ERROR_CANNOT_CONVERT_DATA , "Data conversion error") +XPC_MSG_DEF(NS_ERROR_OBJECT_IS_IMMUTABLE , "Can not modify immutable data container") +XPC_MSG_DEF(NS_ERROR_LOSS_OF_SIGNIFICANT_DATA , "Data conversion failed because significant data would be lost") +XPC_MSG_DEF(NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA , "Data conversion succeeded but data was rounded to fit") diff --git a/js/src/xpconnect/src/xpccontext.cpp b/js/src/xpconnect/src/xpccontext.cpp index 2279e0ece984..17be4b7e5db2 100644 --- a/js/src/xpconnect/src/xpccontext.cpp +++ b/js/src/xpconnect/src/xpccontext.cpp @@ -66,9 +66,9 @@ XPCContext::XPCContext(XPCJSRuntime* aRuntime, mCallingLangType(LANG_UNKNOWN) { MOZ_COUNT_CTOR(XPCContext); - JS_AddArgumentFormatter(mJSContext, - XPC_ARG_FORMATTER_FORMAT_STR, - XPC_JSArgumentFormatter); + + for(const char** p = XPC_ARG_FORMATTER_FORMAT_STRINGS; *p; p++) + JS_AddArgumentFormatter(mJSContext, *p, XPC_JSArgumentFormatter); } XPCContext::~XPCContext() diff --git a/js/src/xpconnect/src/xpcconvert.cpp b/js/src/xpconnect/src/xpcconvert.cpp index d79c615a4c9c..dfb9875dbd5d 100644 --- a/js/src/xpconnect/src/xpcconvert.cpp +++ b/js/src/xpconnect/src/xpcconvert.cpp @@ -38,7 +38,6 @@ /* Data conversion between native and JavaScript types. */ #include "xpcprivate.h" -#include "nsReadableUtils.h" //#define STRICT_CHECK_OF_UNICODE #ifdef STRICT_CHECK_OF_UNICODE @@ -345,6 +344,17 @@ XPCConvert::NativeData2JS(XPCCallContext& ccx, jsval* d, const void* s, nsISupports* iface = *((nsISupports**)s); if(iface) { + if(iid->Equals(NS_GET_IID(nsIVariant))) + { + nsCOMPtr variant = do_QueryInterface(iface); + if(!variant) + return JS_FALSE; + + return XPCVariant::VariantDataToJS(ccx, variant, + scope, pErr, d); + } + // else... + nsCOMPtr holder; if(!NativeInterface2JSObject(ccx, getter_AddRefs(holder), iface, iid, scope, pErr)) @@ -719,8 +729,18 @@ XPCConvert::JSData2Native(XPCCallContext& ccx, void* d, jsval s, case nsXPTType::T_INTERFACE: case nsXPTType::T_INTERFACE_IS: { - NS_ASSERTION(iid,"can't do interface conversions without iid"); JSObject* obj; + NS_ASSERTION(iid,"can't do interface conversions without iid"); + + if(iid->Equals(NS_GET_IID(nsIVariant))) + { + XPCVariant* variant = XPCVariant::newVariant(ccx, s); + if(!variant) + return JS_FALSE; + *((nsISupports**)d) = NS_STATIC_CAST(nsIVariant*, variant); + return JS_TRUE; + } + //else ... if(JSVAL_IS_VOID(s) || JSVAL_IS_NULL(s)) { @@ -886,8 +906,16 @@ XPCConvert::JSObject2NativeInterface(XPCCallContext& ccx, *pErr = rv; if(NS_SUCCEEDED(rv) && wrapper) { - *dest = NS_STATIC_CAST(nsXPTCStubBase*, wrapper); - return JS_TRUE; + // We need to go through the QueryInterface logic to make this return + // the right thing for the various 'special' interfaces; e.g. + // nsIPropertyBag. We must use AggregatedQueryInterface in cases where + // there is an outer to avoid nasty recursion. + rv = aOuter ? wrapper->AggregatedQueryInterface(*iid, dest) : + wrapper->QueryInterface(*iid, dest); + if(pErr) + *pErr = rv; + NS_RELEASE(wrapper); + return NS_SUCCEEDED(rv); } // else... @@ -1180,7 +1208,8 @@ XPCConvert::JSErrorToXPCException(XPCCallContext& ccx, #define VARARGS_ASSIGN(foo, bar) (foo) = (bar) #endif -const char XPC_ARG_FORMATTER_FORMAT_STR[] = "%ip"; +// We assert below that these formats all begin with "%i". +const char* XPC_ARG_FORMATTER_FORMAT_STRINGS[] = {"%ip", "%iv", "%is", nsnull}; JSBool JS_DLL_CALLBACK XPC_JSArgumentFormatter(JSContext *cx, const char *format, @@ -1196,24 +1225,67 @@ XPC_JSArgumentFormatter(JSContext *cx, const char *format, vp = *vpp; VARARGS_ASSIGN(ap, *app); - nsXPTType type = nsXPTType((uint8)(TD_INTERFACE_TYPE | XPT_TDP_POINTER)); - nsISupports* iface; + nsXPTType type; + const nsIID* iid; + void* p; + + NS_ASSERTION(format[0] == '%' && format[1] == 'i', "bad format!"); + char which = format[2]; if(fromJS) { - if(!XPCConvert::JSData2Native(ccx, &iface, vp[0], type, JS_FALSE, - &(NS_GET_IID(nsISupports)), nsnull)) + switch(which) + { + case 'p': + type = nsXPTType((uint8)(TD_INTERFACE_TYPE | XPT_TDP_POINTER)); + iid = &NS_GET_IID(nsISupports); + break; + case 'v': + type = nsXPTType((uint8)(TD_INTERFACE_TYPE | XPT_TDP_POINTER)); + iid = &NS_GET_IID(nsIVariant); + break; + case 's': + type = nsXPTType((uint8)(TD_DOMSTRING | XPT_TDP_POINTER)); + iid = nsnull; + p = va_arg(ap, void *); + break; + default: + NS_ERROR("bad format!"); + return JS_FALSE; + } + + if(!XPCConvert::JSData2Native(ccx, &p, vp[0], type, JS_FALSE, + iid, nsnull)) return JS_FALSE; - *va_arg(ap, nsISupports **) = iface; + + if(which != 's') + *va_arg(ap, void **) = p; } else { - const nsIID* iid; + switch(which) + { + case 'p': + type = nsXPTType((uint8)(TD_INTERFACE_TYPE | XPT_TDP_POINTER)); + iid = va_arg(ap, const nsIID*); + break; + case 'v': + type = nsXPTType((uint8)(TD_INTERFACE_TYPE | XPT_TDP_POINTER)); + iid = &NS_GET_IID(nsIVariant); + break; + case 's': + type = nsXPTType((uint8)(TD_DOMSTRING | XPT_TDP_POINTER)); + iid = nsnull; + break; + default: + NS_ERROR("bad format!"); + return JS_FALSE; + } - iid = va_arg(ap, const nsIID*); - iface = va_arg(ap, nsISupports *); + // NOTE: MUST be retrieved *after* the iid in the 'p' case above. + p = va_arg(ap, void *); - if(!XPCConvert::NativeData2JS(ccx, &vp[0], &iface, type, iid, + if(!XPCConvert::NativeData2JS(ccx, &vp[0], &p, type, iid, JS_GetGlobalObject(cx), nsnull)) return JS_FALSE; } @@ -1323,6 +1395,7 @@ XPCConvert::JSArray2Native(XPCCallContext& ccx, void** d, jsval s, // No Action, FRee memory, RElease object enum CleanupMode {na, fr, re}; + CleanupMode cleanupMode; JSObject* jsarray = nsnull; diff --git a/js/src/xpconnect/src/xpcforwards.h b/js/src/xpconnect/src/xpcforwards.h index e6e4e639d7d6..7fe8f6cf8779 100644 --- a/js/src/xpconnect/src/xpcforwards.h +++ b/js/src/xpconnect/src/xpcforwards.h @@ -87,4 +87,7 @@ class nsXPCConstructor; class AutoMarkingPtr; +class xpcProperty; +class xpcPropertyBagEnumerator; + #endif /* xpcforwards_h___ */ diff --git a/js/src/xpconnect/src/xpcmaps.cpp b/js/src/xpconnect/src/xpcmaps.cpp index 382b4c6b8b47..c25f2b2d8dfd 100644 --- a/js/src/xpconnect/src/xpcmaps.cpp +++ b/js/src/xpconnect/src/xpcmaps.cpp @@ -35,7 +35,6 @@ /* Private maps (hashtables). */ -#include "nscore.h" #include "xpcprivate.h" /***************************************************************************/ diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index d54bbdaa3a39..36c7f14f746e 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -93,6 +93,10 @@ #include "nsIScriptError.h" #include "nsIExceptionService.h" +#include "nsVariant.h" +#include "nsIPropertyBag.h" +#include "nsSupportsArray.h" + #include "nsIXPCScriptNotify.h" // used to notify: ScriptEvaluated #ifndef XPCONNECT_STANDALONE #define XPC_USE_SECURITY_CHECKED_COMPONENT @@ -190,7 +194,7 @@ void DEBUG_CheckWrapperThreadSafety(const XPCWrappedNative* wrapper); /***************************************************************************/ // data declarations... -extern const char XPC_ARG_FORMATTER_FORMAT_STR[]; // format string +extern const char* XPC_ARG_FORMATTER_FORMAT_STRINGS[]; // format strings extern const char XPC_CONTEXT_STACK_CONTRACTID[]; extern const char XPC_RUNTIME_CONTRACTID[]; extern const char XPC_EXCEPTION_CONTRACTID[]; @@ -372,6 +376,7 @@ public: static nsXPConnect* GetXPConnect(); static XPCJSRuntime* GetRuntime(nsXPConnect* xpc = nsnull); static XPCContext* GetContext(JSContext* cx, nsXPConnect* xpc = nsnull); + static nsIJSRuntimeService* GetJSRuntimeService(nsXPConnect* xpc = nsnull); // Gets addref'd pointer static nsresult GetInterfaceInfoManager(nsIInterfaceInfoManager** iim, @@ -447,6 +452,8 @@ public: JSRuntime* GetJSRuntime() const {return mJSRuntime;} nsXPConnect* GetXPConnect() const {return mXPConnect;} + nsIJSRuntimeService* GetJSRuntimeService() const {return mJSRuntimeService;} + JSObject2WrappedJSMap* GetWrappedJSMap() const {return mWrappedJSMap;} @@ -1965,6 +1972,18 @@ public: const nsXPTMethodInfo* info, nsXPTCMiniVariant* params); + JSObject* CallQueryInterfaceOnJSObject(XPCCallContext& ccx, + JSObject* jsobj, REFNSIID aIID); + + static nsresult BuildPropertyEnumerator(XPCCallContext& ccx, + JSObject* aJSObj, + nsISimpleEnumerator** aEnumerate); + + static nsresult GetNamedPropertyAsVariant(XPCCallContext& ccx, + JSObject* aJSObj, + jsval aName, + nsIVariant** aResult); + virtual ~nsXPCWrappedJSClass(); private: nsXPCWrappedJSClass(); // not implemented @@ -1973,9 +1992,6 @@ private: JSObject* NewOutObject(JSContext* cx); - JSObject* CallQueryInterfaceOnJSObject(XPCCallContext& ccx, - JSObject* jsobj, REFNSIID aIID); - JSBool IsReflectable(uint16 i) const {return (JSBool)(mDescriptors[i/32] & (1 << (i%32)));} void SetReflectable(uint16 i, JSBool b) @@ -2024,13 +2040,15 @@ private: class nsXPCWrappedJS : public nsXPTCStubBase, public nsIXPConnectWrappedJS, - public nsSupportsWeakReference + public nsSupportsWeakReference, + public nsIPropertyBag { public: NS_DECL_ISUPPORTS NS_DECL_NSIXPCONNECTJSOBJECTHOLDER NS_DECL_NSIXPCONNECTWRAPPEDJS NS_DECL_NSISUPPORTSWEAKREFERENCE + NS_DECL_NSIPROPERTYBAG // Note that both nsXPTCStubBase and nsIXPConnectWrappedJS declare // GetInterfaceInfo methods with the same sig. So, the declaration @@ -2125,6 +2143,36 @@ private: **************************************************************************** ***************************************************************************/ +class xpcProperty : public nsIProperty +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIPROPERTY + + xpcProperty(const PRUnichar* aName, PRUint32 aNameLen, nsIVariant* aValue); + virtual ~xpcProperty() {} + +private: + nsString mName; + nsCOMPtr mValue; +}; + +class xpcPropertyBagEnumerator : public nsISimpleEnumerator +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSISIMPLEENUMERATOR + + xpcPropertyBagEnumerator(PRUint32 count); + virtual ~xpcPropertyBagEnumerator() {} + + JSBool AppendElement(nsISupports* element); + +private: + nsSupportsArray mArray; + PRUint32 mIndex; + PRUint32 mCount; +}; /***************************************************************************/ // data conversion @@ -3055,6 +3103,45 @@ extern char* xpc_CloneAllAccess(); extern char * xpc_CheckAccessList(const PRUnichar* wideName, const char* list[]); #endif +/***************************************************************************/ +// in xpcvariant.cpp... + +// {1809FD50-91E8-11d5-90F9-0010A4E73D9A} +#define XPCVARIANT_IID \ + {0x1809fd50, 0x91e8, 0x11d5, \ + { 0x90, 0xf9, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a } } + +class XPCVariant : public nsIVariant +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIVARIANT + + // We #define and iid so that out module local code can use QI to detect + // if a given nsIVariant is in fact an XPCVariant. + NS_DEFINE_STATIC_IID_ACCESSOR(XPCVARIANT_IID) + + static XPCVariant* newVariant(XPCCallContext& ccx, jsval aJSVal); + + jsval GetJSVal() const {return mJSVal;} + + XPCVariant(); + + static JSBool VariantDataToJS(XPCCallContext& ccx, + nsIVariant* variant, + JSObject* scope, nsresult* pErr, + jsval* pJSVal); + +protected: + virtual ~XPCVariant(); + + JSBool InitializeData(XPCCallContext& ccx); + +protected: + nsDiscriminatedUnion mData; + jsval mJSVal; +}; + /***************************************************************************/ // Inlined utilities. diff --git a/js/src/xpconnect/src/xpcstring.cpp b/js/src/xpconnect/src/xpcstring.cpp index f23e7ed7f5a4..7cc31f106f44 100644 --- a/js/src/xpconnect/src/xpcstring.cpp +++ b/js/src/xpconnect/src/xpcstring.cpp @@ -47,7 +47,6 @@ * well as providing refcounting support. */ -#include "nscore.h" #include "xpcprivate.h" /* diff --git a/js/src/xpconnect/src/xpcwrappedjs.cpp b/js/src/xpconnect/src/xpcwrappedjs.cpp index fd8de90e8169..dcb43b32d738 100644 --- a/js/src/xpconnect/src/xpcwrappedjs.cpp +++ b/js/src/xpconnect/src/xpcwrappedjs.cpp @@ -464,6 +464,35 @@ nsXPCWrappedJS::SystemIsBeingShutDown(JSRuntime* rt) /***************************************************************************/ +/* readonly attribute nsISimpleEnumerator enumerator; */ +NS_IMETHODIMP +nsXPCWrappedJS::GetEnumerator(nsISimpleEnumerator * *aEnumerate) +{ + XPCCallContext ccx(NATIVE_CALLER); + if(!ccx.IsValid()) + return NS_ERROR_UNEXPECTED; + + return nsXPCWrappedJSClass::BuildPropertyEnumerator(ccx, mJSObj, aEnumerate); +} + +/* nsIVariant getProperty (in AString name); */ +NS_IMETHODIMP +nsXPCWrappedJS::GetProperty(const nsAReadableString & name, nsIVariant **_retval) +{ + XPCCallContext ccx(NATIVE_CALLER); + if(!ccx.IsValid()) + return NS_ERROR_UNEXPECTED; + + JSString* jsstr = XPCStringConvert::ReadableToJSString(ccx, name); + if(!jsstr) + return NS_ERROR_OUT_OF_MEMORY; + + return nsXPCWrappedJSClass:: + GetNamedPropertyAsVariant(ccx, mJSObj, STRING_TO_JSVAL(jsstr), _retval); +} + +/***************************************************************************/ + NS_IMETHODIMP nsXPCWrappedJS::DebugDump(PRInt16 depth) { diff --git a/js/src/xpconnect/src/xpcwrappedjsclass.cpp b/js/src/xpconnect/src/xpcwrappedjsclass.cpp index e66e1cb8890b..aabf5632a0d6 100644 --- a/js/src/xpconnect/src/xpcwrappedjsclass.cpp +++ b/js/src/xpconnect/src/xpcwrappedjsclass.cpp @@ -279,6 +279,184 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(XPCCallContext& ccx, return success ? retObj : nsnull; } +/***************************************************************************/ + +static JSBool +GetNamedPropertyAsVariantRaw(XPCCallContext& ccx, + JSObject* aJSObj, + jsid aName, + nsIVariant** aResult, + nsresult* pErr) +{ + nsXPTType type = nsXPTType((uint8)(TD_INTERFACE_TYPE | XPT_TDP_POINTER)); + jsval val; + + return OBJ_GET_PROPERTY(ccx, aJSObj, aName, &val) && + XPCConvert::JSData2Native(ccx, aResult, val, type, JS_FALSE, + &NS_GET_IID(nsIVariant), pErr); +} + +// static +nsresult +nsXPCWrappedJSClass::GetNamedPropertyAsVariant(XPCCallContext& ccx, + JSObject* aJSObj, + jsval aName, + nsIVariant** aResult) +{ + JSContext* cx = ccx.GetJSContext(); + JSBool ok; + jsid id; + nsresult rv; + + JSExceptionState* saved_exception = DoPreScriptEvaluated(cx); + JSErrorReporter older = JS_SetErrorReporter(cx, nsnull); + + ok = JS_ValueToId(cx, aName, &id) && + GetNamedPropertyAsVariantRaw(ccx, aJSObj, id, aResult, &rv); + + JS_SetErrorReporter(cx, older); + DoPostScriptEvaluated(cx, saved_exception); + + return ok ? NS_OK : NS_FAILED(rv) ? rv : NS_ERROR_FAILURE; +} + +/***************************************************************************/ + +// static +nsresult +nsXPCWrappedJSClass::BuildPropertyEnumerator(XPCCallContext& ccx, + JSObject* aJSObj, + nsISimpleEnumerator** aEnumerate) +{ + JSContext* cx = ccx.GetJSContext(); + nsresult retval = NS_ERROR_FAILURE; + JSIdArray* idArray = nsnull; + xpcPropertyBagEnumerator* enumerator = nsnull; + int i; + + // Saved state must be restored, all exits through 'out'... + JSExceptionState* saved_exception = DoPreScriptEvaluated(cx); + JSErrorReporter older = JS_SetErrorReporter(cx, nsnull); + + idArray = JS_Enumerate(cx, aJSObj); + if(!idArray) + goto out; + + enumerator = new xpcPropertyBagEnumerator(idArray->length); + if(!enumerator) + goto out; + NS_ADDREF(enumerator); + + for(i = 0; i < idArray->length; i++) + { + nsCOMPtr value; + jsid idName = idArray->vector[i]; + nsresult rv; + + if(!GetNamedPropertyAsVariantRaw(ccx, aJSObj, idName, + getter_AddRefs(value), &rv)) + { + if(NS_FAILED(rv)) + retval = rv; + goto out; + } + + jsval jsvalName; + if(!JS_IdToValue(cx, idName, &jsvalName)) + goto out; + + JSString* name = JS_ValueToString(cx, jsvalName); + if(!name) + goto out; + + nsCOMPtr property = + new xpcProperty(JS_GetStringChars(name), + JS_GetStringLength(name), + value); + if(!property) + goto out; + + if(!enumerator->AppendElement(property)) + goto out; + } + + NS_ADDREF(*aEnumerate = enumerator); + retval = NS_OK; + +out: + NS_IF_RELEASE(enumerator); + if(idArray) + JS_DestroyIdArray(cx, idArray); + JS_SetErrorReporter(cx, older); + DoPostScriptEvaluated(cx, saved_exception); + + return retval; +} + +/***************************************************************************/ + +NS_IMPL_ISUPPORTS1(xpcProperty, nsIProperty) + +xpcProperty::xpcProperty(const PRUnichar* aName, PRUint32 aNameLen, + nsIVariant* aValue) + : mName(aName, aNameLen), mValue(aValue) +{ + NS_INIT_ISUPPORTS(); +} + +/* readonly attribute AString name; */ +NS_IMETHODIMP xpcProperty::GetName(nsAWritableString & aName) +{ + aName.Assign(mName); + return NS_OK; +} + +/* readonly attribute nsIVariant value; */ +NS_IMETHODIMP xpcProperty::GetValue(nsIVariant * *aValue) +{ + NS_ADDREF(*aValue = mValue); + return NS_OK; +} + +/***************************************************************************/ + +NS_IMPL_ISUPPORTS1(xpcPropertyBagEnumerator, nsISimpleEnumerator) + +xpcPropertyBagEnumerator::xpcPropertyBagEnumerator(PRUint32 count) + : mIndex(0), mCount(0) +{ + NS_INIT_ISUPPORTS(); + mArray.SizeTo(count); +} + +JSBool xpcPropertyBagEnumerator::AppendElement(nsISupports* element) +{ + if(!mArray.AppendElement(element)) + return JS_FALSE; + mCount++; + return JS_TRUE; +} + +/* boolean hasMoreElements (); */ +NS_IMETHODIMP xpcPropertyBagEnumerator::HasMoreElements(PRBool *_retval) +{ + *_retval = mIndex < mCount; + return NS_OK; +} + +/* nsISupports getNext (); */ +NS_IMETHODIMP xpcPropertyBagEnumerator::GetNext(nsISupports **_retval) +{ + if(!(mIndex < mCount)) + { + NS_ERROR("Bad nsISimpleEnumerator caller!"); + return NS_ERROR_FAILURE; + } + + *_retval = mArray.ElementAt(mIndex++); + return *_retval ? NS_OK : NS_ERROR_FAILURE; +} + /***************************************************************************/ // This 'WrappedJSIdentity' class and singleton allow us to figure out if // any given nsISupports* is implemented by a WrappedJS object. This is done @@ -342,6 +520,22 @@ nsXPCWrappedJSClass::DelegatedQueryInterface(nsXPCWrappedJS* self, return NS_OK; } + if(aIID.Equals(NS_GET_IID(nsIPropertyBag))) + { + // We only want to expose one implementation from our aggregate. + nsXPCWrappedJS* root = self->GetRootWrapper(); + + if(!root->IsValid()) + { + *aInstancePtr = nsnull; + return NS_NOINTERFACE; + } + + NS_ADDREF(root); + *aInstancePtr = (void*) NS_STATIC_CAST(nsIPropertyBag*,root); + return NS_OK; + } + XPCCallContext ccx(NATIVE_CALLER); if(!ccx.IsValid()) { diff --git a/js/src/xpconnect/src/xpcwrappednative.cpp b/js/src/xpconnect/src/xpcwrappednative.cpp index 9ff2824c7f1b..371f7bdee197 100644 --- a/js/src/xpconnect/src/xpcwrappednative.cpp +++ b/js/src/xpconnect/src/xpcwrappednative.cpp @@ -35,7 +35,6 @@ /* Wrapper object for reflecting native xpcom objects into JavaScript. */ -#include "nscore.h" #include "xpcprivate.h" /***************************************************************************/ @@ -1326,10 +1325,13 @@ XPCWrappedNative::InitTearOff(XPCCallContext& ccx, // into an infinite loop. // see: http://bugzilla.mozilla.org/show_bug.cgi?id=96725 + // The code in this block also does a check for the double wrapped + // nsIPropertyBag case. + nsCOMPtr wrappedJS(do_QueryInterface(obj)); if(wrappedJS) { - JSObject* jso; + JSObject* jso = nsnull; if(NS_SUCCEEDED(wrappedJS->GetJSObject(&jso)) && jso == GetFlatJSObject()) { @@ -1378,7 +1380,34 @@ XPCWrappedNative::InitTearOff(XPCCallContext& ccx, NS_RELEASE(obj); aTearOff->SetInterface(nsnull); return NS_OK; - } + } + + // Decide whether or not to expose nsIPropertyBag to calling + // JS code in the double wrapped case. + // + // Our rule here is that when JSObjects are double wrapped and + // exposed to other JSObjects then the nsIPropertyBag interface + // is only exposed on an 'opt-in' basis; i.e. if the underlying + // JSObject wants other JSObjects to be able to see this interface + // then it must implement QueryInterface and not throw an exception + // when asked for nsIPropertyBag. It need not actually *implement* + // nsIPropertyBag - xpconnect will do that work. + + nsXPCWrappedJSClass* clazz; + if(iid->Equals(NS_GET_IID(nsIPropertyBag)) && jso && + NS_SUCCEEDED(nsXPCWrappedJSClass::GetNewOrUsed(ccx,*iid,&clazz))&& + clazz) + { + JSObject* answer = + clazz->CallQueryInterfaceOnJSObject(ccx, jso, *iid); + NS_RELEASE(clazz); + if(!answer) + { + NS_RELEASE(obj); + aTearOff->SetInterface(nsnull); + return NS_ERROR_NO_INTERFACE; + } + } } nsIXPCSecurityManager* sm; @@ -1567,6 +1596,22 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx, #define PARAM_BUFFER_COUNT 8 nsXPTCVariant paramBuffer[PARAM_BUFFER_COUNT]; + + // Number of nsAutoStrings to construct on the stack for use with method + // calls that use 'out' AStrings (aka [domstring]). These can save us from + // a new/delete of an nsString. But the cost is that the ctor/dtor code + // is run for each nsAutoString in the array for each call - whether or not + // a specific call actually uses *any* AStrings. Also, we have these + // large-ish nsAutoString objects using up stack space. + // + // Set this to zero to disable use of these auto strings. +#define PARAM_AUTOSTRING_COUNT 1 + +#if PARAM_AUTOSTRING_COUNT + XPCVoidableString autoStrings[PARAM_AUTOSTRING_COUNT]; + int autoStringIndex = 0; +#endif + JSBool retval = JS_FALSE; nsXPTCVariant* dispatchParams = nsnull; @@ -1744,12 +1789,24 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx, break; case nsXPTType::T_DOMSTRING: - dp->SetValIsDOMString(); if(paramInfo.IsDipper()) { // Is an 'out' DOMString. Make a new nsAWritableString // now and then continue in order to skip the call to // JSData2Native + + // If autoStrings array support is enabld, then use + // one of them if they are not already used up. +#if PARAM_AUTOSTRING_COUNT + if(autoStringIndex < PARAM_AUTOSTRING_COUNT) + { + // Don't call SetValIsDOMString because we don't + // want to delete this pointer. + dp->val.p = &autoStrings[autoStringIndex++]; + continue; + } +#endif + dp->SetValIsDOMString(); if(!(dp->val.p = new XPCVoidableString())) { JS_ReportOutOfMemory(ccx); @@ -1762,6 +1819,7 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx, // Is an 'in' DOMString. Set 'useAllocator' to indicate // that JSData2Native should allocate a new // nsAReadableString. + dp->SetValIsDOMString(); useAllocator = JS_TRUE; break; } @@ -2134,7 +2192,7 @@ done: if(dispatchParams && dispatchParams != paramBuffer) delete [] dispatchParams; -#ifdef DEBUG_stats_jband +#ifdef off_DEBUG_stats_jband endTime = PR_IntervalNow(); printf("%s::%s %d ( js->c ) \n", diff --git a/js/src/xpconnect/src/xpcwrappednativejsops.cpp b/js/src/xpconnect/src/xpcwrappednativejsops.cpp index e27ac4111ade..eee2b25fdcbb 100644 --- a/js/src/xpconnect/src/xpcwrappednativejsops.cpp +++ b/js/src/xpconnect/src/xpcwrappednativejsops.cpp @@ -345,7 +345,7 @@ DefinePropertyIfFound(XPCCallContext& ccx, GetDoubleWrappedJSObject(ccx, wrapperToReflectDoubleWrap)) { // We build and add a getter function. - // A security is done on a per-get basis. + // A security check is done on a per-get basis. JSFunction* fun; diff --git a/js/src/xpconnect/tests/TestXPC.cpp b/js/src/xpconnect/tests/TestXPC.cpp index 42ee0b318662..6d77d39c95d8 100644 --- a/js/src/xpconnect/tests/TestXPC.cpp +++ b/js/src/xpconnect/tests/TestXPC.cpp @@ -47,6 +47,7 @@ #include "nsIXPCSecurityManager.h" #include "nsICategoryManager.h" #include "nsAWritableString.h" +#include "nsIVariant.h" #include "jsapi.h" #include "jsgc.h" // for js_ForceGC @@ -440,62 +441,98 @@ TestArgFormatter(JSContext* jscontext, JSObject* glob, nsIXPConnect* xpc) jsval* argv; void* mark; - nsTestXPCFoo* foo = new nsTestXPCFoo(); - const char* a_in = "some string"; - const char* b_in = "another meaningless chunck of text"; - char* a_out; - char* b_out; + const char* a_in = "some string"; + nsCOMPtr b_in = new nsTestXPCFoo(); + nsCOMPtr c_in = do_CreateInstance("@mozilla.org/variant;1"); + static const NS_NAMED_LITERAL_STRING(d_in, "foo bar"); + const char* e_in = "another meaningless chunck of text"; + + + char* a_out; + nsCOMPtr b_out; + nsCOMPtr c_out; + nsAutoString d_out; + char* e_out; + + nsCOMPtr specified; + PRInt32 val; printf("ArgumentFormatter test: "); - argv = JS_PushArguments(jscontext, &mark, "s %ip s", - a_in, &NS_GET_IID(nsITestXPCFoo2), foo, b_in); - - if(argv) + if(!b_in || !c_in || NS_FAILED(c_in->SetAsInt32(5))) { - nsISupports* fooc; - nsTestXPCFoo* foog; - if(JS_ConvertArguments(jscontext, 3, argv, "s %ip s", - &a_out, &fooc, &b_out)) - { - if(fooc) - { - if(NS_SUCCEEDED(fooc->QueryInterface(NS_GET_IID(nsTestXPCFoo), - (void**)&foog))) - { - if(foog == foo) - { - if(!strcmp(a_in, a_out) && !strcmp(b_in, b_out)) - printf("passed\n"); - else - printf(" conversion OK, but surrounding was mangled -- FAILED!\n"); - } - else - printf(" JS to native returned wrong value -- FAILED!\n"); - NS_RELEASE(foog); - } - else - { - printf(" could not QI value JS to native returned -- FAILED!\n"); - } - NS_RELEASE(fooc); - } - else - { - printf(" JS to native returned NULL -- FAILED!\n"); - } - } - else - { - printf(" could not convert from JS to native -- FAILED!\n"); - } - JS_PopArguments(jscontext, mark); + printf(" failed to construct test objects -- FAILED!\n"); + return; } - else + + argv = JS_PushArguments(jscontext, &mark, "s %ip %iv %is s", + a_in, + &NS_GET_IID(nsITestXPCFoo2), b_in, + c_in, + NS_STATIC_CAST(const nsAString*, &d_in), + e_in); + + if(!argv) { printf(" could not convert from native to JS -- FAILED!\n"); + return; } - NS_IF_RELEASE(foo); + + if(!JS_ConvertArguments(jscontext, 5, argv, "s %ip %iv %is s", + &a_out, + getter_AddRefs(b_out), + getter_AddRefs(c_out), + NS_STATIC_CAST(nsAString*, &d_out), + &e_out)) + { + printf(" could not convert from JS to native -- FAILED!\n"); + goto out; + } + + if(!b_out) + { + printf(" JS to native for %ip returned NULL -- FAILED!\n"); + goto out; + } + + specified = do_QueryInterface(b_out); + if(!specified) + { + printf(" could not QI value JS to native returned -- FAILED!\n"); + goto out; + } + + if(specified.get() != b_in.get()) + { + printf(" JS to native returned wrong value -- FAILED!\n"); + goto out; + } + + if(!c_out) + { + printf(" JS to native for %iv returned NULL -- FAILED!\n"); + goto out; + } + + if(NS_FAILED(c_out->GetAsInt32(&val)) || val != 5) + { + printf(" JS to native for %iv holds wrong value -- FAILED!\n"); + goto out; + } + + if(d_in != d_out) + { + printf(" JS to native for %is returned the wrong value -- FAILED!\n"); + goto out; + } + + if(!strcmp(a_in, a_out) && !strcmp(e_in, e_out)) + printf("passed\n"); + else + printf(" conversion OK, but surrounding was mangled -- FAILED!\n"); + +out: + JS_PopArguments(jscontext, mark); } /***************************************************************************/ @@ -700,7 +737,7 @@ int main() DIE("FAILED to get the nsThreadJSContextStack service!\n"); if(NS_FAILED(cxstack->Push(jscontext))) - DIE("FAILED to get push the current jscontext on the nsThreadJSContextStack service!\n"); + DIE("FAILED to push the current jscontext on the nsThreadJSContextStack service!\n"); // XXX I'd like to replace this with code that uses a wrapped xpcom object // as the global object. The old TextXPC did this. The support for this @@ -719,12 +756,16 @@ int main() /**********************************************/ // run the tests... - TestCategoryManmager(); - TestSecurityManager(jscontext, glob, xpc); + //TestCategoryManmager(); + //TestSecurityManager(jscontext, glob, xpc); TestArgFormatter(jscontext, glob, xpc); - TestThreadJSContextStack(jscontext); + //TestThreadJSContextStack(jscontext); /**********************************************/ + + if(NS_FAILED(cxstack->Pop(nsnull))) + DIE("FAILED to pop the current jscontext from the nsThreadJSContextStack service!\n"); + JS_ClearScope(jscontext, glob); js_ForceGC(jscontext); js_ForceGC(jscontext); diff --git a/js/src/xpconnect/tests/components/Makefile.in b/js/src/xpconnect/tests/components/Makefile.in index eeafcfc962c3..17097c34a2d6 100644 --- a/js/src/xpconnect/tests/components/Makefile.in +++ b/js/src/xpconnect/tests/components/Makefile.in @@ -67,6 +67,7 @@ CPPSRCS = \ xpctest_multiple.cpp \ xpctest_out.cpp \ xpctest_domstring.cpp \ + xpctest_variant.cpp \ $(NULL) EXTRA_DSO_LDOPTS += \ diff --git a/js/src/xpconnect/tests/components/makefile.win b/js/src/xpconnect/tests/components/makefile.win index a6b9afde38a5..c4b612252159 100644 --- a/js/src/xpconnect/tests/components/makefile.win +++ b/js/src/xpconnect/tests/components/makefile.win @@ -64,6 +64,7 @@ OBJS= \ .\$(OBJDIR)\xpctest_calljs.obj \ .\$(OBJDIR)\xpctest_multiple.obj\ .\$(OBJDIR)\xpctest_domstring.obj \ + .\$(OBJDIR)\xpctest_variant.obj \ $(NULL) LINCS=-I$(PUBLIC)\xpconnect -I$(PUBLIC)\xpcom -I$(PUBLIC)\js \ diff --git a/js/src/xpconnect/tests/components/xpctest_echo.cpp b/js/src/xpconnect/tests/components/xpctest_echo.cpp index 4b4d544f2805..8c3a5928ab24 100644 --- a/js/src/xpconnect/tests/components/xpctest_echo.cpp +++ b/js/src/xpconnect/tests/components/xpctest_echo.cpp @@ -533,9 +533,6 @@ NS_IMETHODIMP xpctestEcho::SetSomeValue(PRInt32 aSomeValue) return NS_OK; } - -/***************************************************/ - /***************************************************************************/ // static diff --git a/js/src/xpconnect/tests/components/xpctest_module.cpp b/js/src/xpconnect/tests/components/xpctest_module.cpp index 6dbc4d6ab4e8..a698c2d30da4 100644 --- a/js/src/xpconnect/tests/components/xpctest_module.cpp +++ b/js/src/xpconnect/tests/components/xpctest_module.cpp @@ -64,8 +64,9 @@ static nsModuleComponentInfo components[] = { {nsnull, NS_XPCTESTCHILD3_CID, "@mozilla.org/js/xpc/test/Child3;1", xpctest::ConstructXPCTestChild3 }, {nsnull, NS_XPCTESTCHILD4_CID, "@mozilla.org/js/xpc/test/Child4;1", xpctest::ConstructXPCTestChild4 }, {nsnull, NS_XPCTESTCHILD5_CID, "@mozilla.org/js/xpc/test/Child5;1", xpctest::ConstructXPCTestChild5 }, - {nsnull, NS_ARRAY_CID, "@mozilla.org/js/xpc/test/ArrayTest;1", xpctest::ConstructArrayTest }, - {nsnull, NS_XPCTESTDOMSTRING_CID, "@mozilla.org/js/xpc/test/DOMString;1", xpctest::ConstructXPCTestDOMString } + {nsnull, NS_ARRAY_CID, "@mozilla.org/js/xpc/test/ArrayTest;1", xpctest::ConstructArrayTest }, + {nsnull, NS_XPCTESTDOMSTRING_CID, "@mozilla.org/js/xpc/test/DOMString;1", xpctest::ConstructXPCTestDOMString }, + {nsnull, NS_XPCTESTVARIANT_CID, "@mozilla.org/js/xpc/test/TestVariant;1", xpctest::ConstructXPCTestVariant } }; NS_IMPL_NSGETMODULE(xpconnect_test, components) diff --git a/js/src/xpconnect/tests/components/xpctest_private.h b/js/src/xpconnect/tests/components/xpctest_private.h index b7673b505e82..8864a8a258f8 100644 --- a/js/src/xpconnect/tests/components/xpctest_private.h +++ b/js/src/xpconnect/tests/components/xpctest_private.h @@ -48,6 +48,7 @@ #include "nscore.h" #include "nsCOMPtr.h" #include "nsAWritableString.h" +#include "nsVariant.h" #include #include "xpctest.h" @@ -149,6 +150,11 @@ {0xdb569f7e, 0x16fb, 0x1bcb, \ { 0xa8, 0x6c, 0xe0, 0x8a, 0xa7, 0xf9, 0x76, 0x66 }} +// {DC932D30-95B0-11d5-90FC-0010A4E73D9A} +#define NS_XPCTESTVARIANT_CID \ + {0xdc932d30, 0x95b0, 0x11d5, \ + { 0x90, 0xfc, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a }} + // 'namespace' class class xpctest { @@ -173,6 +179,7 @@ public: static NS_METHOD ConstructXPCTestChild5(nsISupports *aOuter, REFNSIID aIID, void **aResult); static NS_METHOD ConstructArrayTest(nsISupports *aOuter, REFNSIID aIID, void **aResult); static NS_METHOD ConstructXPCTestDOMString(nsISupports *aOuter, REFNSIID aIID, void **aResult); + static NS_METHOD ConstructXPCTestVariant(nsISupports *aOuter, REFNSIID aIID, void **aResult); private: xpctest(); // not implemented diff --git a/js/src/xpconnect/tests/idl/xpctest.idl b/js/src/xpconnect/tests/idl/xpctest.idl index b6ce1db204c5..da77fffeff85 100644 --- a/js/src/xpconnect/tests/idl/xpctest.idl +++ b/js/src/xpconnect/tests/idl/xpctest.idl @@ -35,6 +35,8 @@ #include "nsISupports.idl" #include "xpcexception.idl" +#include "nsIVariant.idl" +#include "nsIPropertyBag.idl" // forward declaration (to test that such things work) interface nsITestXPCSomeUselessThing; @@ -239,3 +241,59 @@ interface nsIWrappedJSObjectTest : nsISupports { void interfaceMember(); }; + +[scriptable, uuid(41d923d0-5bc1-11d5-90db-0010a4e73d9a)] +interface nsIBogus1 : nsISupports {}; + +[scriptable, uuid(8d8f4210-5bc1-11d5-90db-0010a4e73d9a)] +interface nsIBogus2 : nsISupports +{ + attribute nsIBogus1 bogus; +}; + +[scriptable, uuid(34bc9990-95af-11d5-90fc-0010a4e73d9a)] +interface nsITestVariant : nsISupports +{ + /** + * Just return the variant that was passed in. + */ + nsIVariant passThruVariant(in nsIVariant value); + + /** + * Just return the type of the passed in variant. + */ + PRUint16 returnVariantType(in nsIVariant value); + + /** + * Construct and return a default xpcom variant instance using the + * value of the passed in variant. Use the type of the passed in variant. + */ + nsIVariant copyVariant(in nsIVariant value); + + /** + * Construct and return a default xpcom variant instance using the + * value of the passed in variant. Use the type as specified to get data + * from the passed in variant. + */ + nsIVariant copyVariantAsType(in nsIVariant value, in PRUint16 type); + + /** + * Construct a default xpcom variant instance using the + * value of the passed in variant. Use the type as specified in type1 to + * get data from the passed in variant. Then construct and return a default + * xpcom variant based on that object using the type2. This allows for + * testing all the 'ConvertTo*' methods on the default xpcom variant class. + */ + nsIVariant copyVariantAsTypeTwice(in nsIVariant value, + in PRUint16 type1, in PRUint16 type2); + + /** + * Get a named property from object that will be QI'd to nsIPropertyBag. + */ + nsIVariant getNamedProperty(in nsISupports aBag, in AString aName); + + /** + * Get a enumerator from object that will be QI'd to nsIPropertyBag. + */ + nsISimpleEnumerator getEnumerator(in nsISupports aBag); +}; diff --git a/xpcom/base/nsError.h b/xpcom/base/nsError.h index 1db227bf378b..71f4626b9f9a 100644 --- a/xpcom/base/nsError.h +++ b/xpcom/base/nsError.h @@ -272,6 +272,16 @@ #define NS_ERROR_FILE_DIR_NOT_EMPTY NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 20) #define NS_ERROR_FILE_ACCESS_DENIED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 21) +//////////////////////////////////////////////////////////////////////////////// +// Result codes used by nsIVariant + +#define NS_ERROR_CANNOT_CONVERT_DATA NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 1) +#define NS_ERROR_OBJECT_IS_IMMUTABLE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 2) +#define NS_ERROR_LOSS_OF_SIGNIFICANT_DATA NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 3) + +#define NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 1) + + //////////////////////////////////////////////////////////////////////////////// // This will return the nsresult corresponding to the most recent NSPR failure // returned by PR_GetError. diff --git a/xpcom/base/nsrootidl.idl b/xpcom/base/nsrootidl.idl index 4abd4cf602ca..aac25a804a3c 100644 --- a/xpcom/base/nsrootidl.idl +++ b/xpcom/base/nsrootidl.idl @@ -74,8 +74,6 @@ typedef unsigned long size_t; [ptr] native charPtr(char); [ptr] native unicharPtr(PRUnichar); -[nsid] native nsCID(nsCID); - [ref, nsid] native nsIDRef(nsID); [ref, nsid] native nsIIDRef(nsIID); [ref, nsid] native nsCIDRef(nsCID); @@ -84,6 +82,20 @@ typedef unsigned long size_t; [ptr, nsid] native nsIIDPtr(nsIID); [ptr, nsid] native nsCIDPtr(nsCID); +// NOTE: Be careful in using the following 3 types. The *Ref and *Ptr variants +// are more commonly used (and better supported). Those variants require +// nsMemory alloc'd copies when used as 'out' params while these types do not. +// However, currently these types can not be used for 'in' params. And, methods +// that use them as 'out' params *must* be declared [notxpcom] (with an explicit +// return type of nsresult). This makes such methods implicitly not scriptable. +// Use of these types in methods without a [notxpcom] declaration will cause +// the xpidl compiler to raise an error. +// See: http://bugzilla.mozilla.org/show_bug.cgi?id=93792 + +[nsid] native nsIID(nsIID); +[nsid] native nsID(nsID); +[nsid] native nsCID(nsCID); + [ptr] native nsQIResult(void); [ref, domstring] native DOMString(ignored); diff --git a/xpcom/build/dlldeps.cpp b/xpcom/build/dlldeps.cpp index c0872123cbcb..1b3aa4f76233 100644 --- a/xpcom/build/dlldeps.cpp +++ b/xpcom/build/dlldeps.cpp @@ -91,6 +91,7 @@ #ifdef NS_TRACE_MALLOC #include "nsTraceMalloc.h" #endif +#include "nsVariant.h" class dummyComparitor: public nsAVLNodeComparitor { public: @@ -192,4 +193,5 @@ void XXXNeverCalled() NS_TraceMallocDumpAllocations(NULL); NS_TraceMallocFlushLogfiles(); #endif + nsVariant(); } diff --git a/xpcom/build/nsXPComInit.cpp b/xpcom/build/nsXPComInit.cpp index 3b186d44eec6..220ba658289f 100644 --- a/xpcom/build/nsXPComInit.cpp +++ b/xpcom/build/nsXPComInit.cpp @@ -93,6 +93,8 @@ #include "nsTraceRefcnt.h" #include "nsTimelineService.h" +#include "nsVariant.h" + #ifdef GC_LEAK_DETECTOR #include "nsLeakDetector.h" #endif @@ -132,6 +134,8 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsConsoleService); NS_GENERIC_FACTORY_CONSTRUCTOR(nsAtomService); NS_GENERIC_FACTORY_CONSTRUCTOR(nsExceptionService); +NS_GENERIC_FACTORY_CONSTRUCTOR(nsVariant); + #ifdef MOZ_TIMELINE NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimelineService); #endif @@ -256,7 +260,8 @@ static nsModuleComponentInfo components[] = { COMPONENT(FILESPEC, nsFileSpecImpl::Create), COMPONENT(DIRECTORYITERATOR, nsDirectoryIteratorImpl::Create), - COMPONENT(FASTLOADSERVICE, nsFastLoadService::Create) + COMPONENT(FASTLOADSERVICE, nsFastLoadService::Create), + COMPONENT(VARIANT, nsVariantConstructor) }; #undef COMPONENT diff --git a/xpcom/ds/MANIFEST b/xpcom/ds/MANIFEST index c2ef04852a9d..36a7e8220a03 100644 --- a/xpcom/ds/MANIFEST +++ b/xpcom/ds/MANIFEST @@ -20,6 +20,7 @@ nsSupportsArray.h nsSupportsPrimitives.h nsTime.h nsUnitConversion.h +nsVariant.h nsVector.h nsVoidArray.h nsVoidBTree.h diff --git a/xpcom/ds/MANIFEST_IDL b/xpcom/ds/MANIFEST_IDL index 50bdda2b7d8b..94113c9f5535 100644 --- a/xpcom/ds/MANIFEST_IDL +++ b/xpcom/ds/MANIFEST_IDL @@ -13,3 +13,4 @@ nsISupportsArray.idl nsITimelineService.idl nsISupportsIterators.idl nsISupportsPrimitives.idl +nsIVariant.idl diff --git a/xpcom/ds/Makefile.in b/xpcom/ds/Makefile.in index 4cc9d5fb0c5d..3f7f22d15a19 100644 --- a/xpcom/ds/Makefile.in +++ b/xpcom/ds/Makefile.in @@ -65,6 +65,7 @@ CPPSRCS = \ nsSupportsArrayEnumerator.cpp \ nsSupportsPrimitives.cpp \ nsUnicharBuffer.cpp \ + nsVariant.cpp \ nsVoidArray.cpp \ nsVoidBTree.cpp \ nsTextFormatter.cpp \ @@ -94,6 +95,7 @@ EXPORTS = \ nsSupportsPrimitives.h \ nsTime.h \ nsUnitConversion.h \ + nsVariant.h \ nsVector.h \ nsVoidArray.h \ nsVoidBTree.h \ @@ -111,6 +113,8 @@ XPIDLSRCS = \ nsIObserverService.idl \ nsIPersistentProperties2.idl \ nsIProperties.idl \ + nsIPropertyBag.idl \ + nsIVariant.idl \ nsISerializable.idl \ nsISimpleEnumerator.idl \ nsIStopwatch.idl \ diff --git a/xpcom/ds/makefile.win b/xpcom/ds/makefile.win index 979ee5577dc7..c408cae40cb7 100644 --- a/xpcom/ds/makefile.win +++ b/xpcom/ds/makefile.win @@ -53,6 +53,7 @@ EXPORTS = \ nsTime.h \ nsTimelineService.h \ nsUnitConversion.h \ + nsVariant.h \ nsVector.h \ nsVoidArray.h \ nsVoidBTree.h \ @@ -72,12 +73,14 @@ XPIDLSRCS = \ .\nsIPersistentProperties2.idl \ .\nsITimelineService.idl \ .\nsIProperties.idl \ + .\nsIPropertyBag.idl \ .\nsISerializable.idl \ .\nsISimpleEnumerator.idl \ .\nsIStopwatch.idl \ .\nsISupportsArray.idl \ .\nsISupportsIterators.idl \ .\nsISupportsPrimitives.idl \ + .\nsIVariant.idl \ $(NULL) ################################################################################ @@ -116,6 +119,7 @@ CPP_OBJS = \ .\$(OBJDIR)\nsTextFormatter.obj \ .\$(OBJDIR)\nsTimelineService.obj \ .\$(OBJDIR)\nsUnicharBuffer.obj \ + .\$(OBJDIR)\nsVariant.obj \ .\$(OBJDIR)\nsVoidArray.obj \ .\$(OBJDIR)\nsVoidBTree.obj \ .\$(OBJDIR)\pldhash.obj \ diff --git a/xpcom/io/nsIObjectInputStream.idl b/xpcom/io/nsIObjectInputStream.idl index 526f04f7027a..0ab6e98da8a1 100644 --- a/xpcom/io/nsIObjectInputStream.idl +++ b/xpcom/io/nsIObjectInputStream.idl @@ -44,8 +44,6 @@ * @See nsIBinaryInputStream */ -[nsid] native nsID(nsID); - [scriptable, uuid(6c248606-4eae-46fa-9df0-ba58502368eb)] interface nsIObjectInputStream : nsIBinaryInputStream { diff --git a/xpcom/proxy/public/nsIProxyCreateInstance.idl b/xpcom/proxy/public/nsIProxyCreateInstance.idl index 31b2008ec7c3..6657b253279d 100644 --- a/xpcom/proxy/public/nsIProxyCreateInstance.idl +++ b/xpcom/proxy/public/nsIProxyCreateInstance.idl @@ -37,11 +37,7 @@ #include "nsISupports.idl" -/* XXX should be built in */ -native nsID(nsID *); - [scriptable, uuid(948c2080-0398-11d3-915e-0000863011c4)] - interface nsIProxyCreateInstance : nsISupports { [noscript] void CreateInstanceByIID(in nsIIDRef cid, diff --git a/xpcom/proxy/tests/nsITestProxy.idl b/xpcom/proxy/tests/nsITestProxy.idl index 8342639f6d26..98cb3f94ceae 100644 --- a/xpcom/proxy/tests/nsITestProxy.idl +++ b/xpcom/proxy/tests/nsITestProxy.idl @@ -1,8 +1,5 @@ #include "nsISupports.idl" -/* XXX should be built in */ -native nsID(nsID *); - [uuid(1979e980-1cfd-11d3-915e-0000863011c4)] interface nsITestProxy : nsISupports {