add support for nsIVariant and nsIPropertyBag. bug 44675 and bug 98209. sr=vidur r=dbradley

This commit is contained in:
jband%netscape.com 2001-10-31 23:35:07 +00:00
Родитель d483c8a09c
Коммит 84bfc894a4
33 изменённых файлов: 694 добавлений и 100 удалений

Просмотреть файл

@ -71,6 +71,7 @@ CPPSRCS = \
xpcthreadcontext.cpp \
xpcthrower.cpp \
xpcwrappedjs.cpp \
xpcvariant.cpp \
xpcwrappedjsclass.cpp \
xpcwrappednative.cpp \
xpcwrappednativeinfo.cpp \

Просмотреть файл

@ -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 \

Просмотреть файл

@ -43,7 +43,6 @@
*/
#include "xpcprivate.h"
#include "nsReadableUtils.h"
NS_IMPL_THREADSAFE_ISUPPORTS2(nsScriptError, nsIConsoleMessage, nsIScriptError);

Просмотреть файл

@ -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*/)

Просмотреть файл

@ -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")

Просмотреть файл

@ -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()

Просмотреть файл

@ -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<nsIVariant> variant = do_QueryInterface(iface);
if(!variant)
return JS_FALSE;
return XPCVariant::VariantDataToJS(ccx, variant,
scope, pErr, d);
}
// else...
nsCOMPtr<nsIXPConnectJSObjectHolder> 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;
*va_arg(ap, nsISupports **) = iface;
}
if(!XPCConvert::JSData2Native(ccx, &p, vp[0], type, JS_FALSE,
iid, nsnull))
return JS_FALSE;
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*);
iface = va_arg(ap, 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;
break;
default:
NS_ERROR("bad format!");
return JS_FALSE;
}
if(!XPCConvert::NativeData2JS(ccx, &vp[0], &iface, type, iid,
// NOTE: MUST be retrieved *after* the iid in the 'p' case above.
p = va_arg(ap, void *);
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;

Просмотреть файл

@ -87,4 +87,7 @@ class nsXPCConstructor;
class AutoMarkingPtr;
class xpcProperty;
class xpcPropertyBagEnumerator;
#endif /* xpcforwards_h___ */

Просмотреть файл

@ -35,7 +35,6 @@
/* Private maps (hashtables). */
#include "nscore.h"
#include "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<nsIVariant> 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.

Просмотреть файл

@ -47,7 +47,6 @@
* well as providing refcounting support.
*/
#include "nscore.h"
#include "xpcprivate.h"
/*

Просмотреть файл

@ -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)
{

Просмотреть файл

@ -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<nsIVariant> 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<nsIProperty> 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())
{

Просмотреть файл

@ -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<nsIXPConnectWrappedJS> wrappedJS(do_QueryInterface(obj));
if(wrappedJS)
{
JSObject* jso;
JSObject* jso = nsnull;
if(NS_SUCCEEDED(wrappedJS->GetJSObject(&jso)) &&
jso == GetFlatJSObject())
{
@ -1379,6 +1381,33 @@ XPCWrappedNative::InitTearOff(XPCCallContext& ccx,
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",

Просмотреть файл

@ -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;

Просмотреть файл

@ -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,63 +441,99 @@ 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";
nsCOMPtr<nsITestXPCFoo> b_in = new nsTestXPCFoo();
nsCOMPtr<nsIWritableVariant> 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;
char* b_out;
nsCOMPtr<nsISupports> b_out;
nsCOMPtr<nsIVariant> c_out;
nsAutoString d_out;
char* e_out;
nsCOMPtr<nsITestXPCFoo> specified;
PRInt32 val;
printf("ArgumentFormatter test: ");
argv = JS_PushArguments(jscontext, &mark, "s %ip s",
a_in, &NS_GET_IID(nsITestXPCFoo2), foo, b_in);
if(!b_in || !c_in || NS_FAILED(c_in->SetAsInt32(5)))
{
printf(" failed to construct test objects -- FAILED!\n");
return;
}
if(argv)
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)
{
nsISupports* fooc;
nsTestXPCFoo* foog;
if(JS_ConvertArguments(jscontext, 3, argv, "s %ip s",
&a_out, &fooc, &b_out))
printf(" could not convert from native to JS -- FAILED!\n");
return;
}
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))
{
if(fooc)
printf(" could not convert from JS to native -- FAILED!\n");
goto out;
}
if(!b_out)
{
if(NS_SUCCEEDED(fooc->QueryInterface(NS_GET_IID(nsTestXPCFoo),
(void**)&foog)))
printf(" JS to native for %ip returned NULL -- FAILED!\n");
goto out;
}
specified = do_QueryInterface(b_out);
if(!specified)
{
if(foog == foo)
printf(" could not QI value JS to native returned -- FAILED!\n");
goto out;
}
if(specified.get() != b_in.get())
{
if(!strcmp(a_in, a_out) && !strcmp(b_in, b_out))
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");
}
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");
}
out:
JS_PopArguments(jscontext, mark);
}
else
{
printf(" could not convert from native to JS -- FAILED!\n");
}
NS_IF_RELEASE(foo);
}
/***************************************************************************/
// ThreadJSContextStack test
@ -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);

Просмотреть файл

@ -67,6 +67,7 @@ CPPSRCS = \
xpctest_multiple.cpp \
xpctest_out.cpp \
xpctest_domstring.cpp \
xpctest_variant.cpp \
$(NULL)
EXTRA_DSO_LDOPTS += \

Просмотреть файл

@ -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 \

Просмотреть файл

@ -533,9 +533,6 @@ NS_IMETHODIMP xpctestEcho::SetSomeValue(PRInt32 aSomeValue)
return NS_OK;
}
/***************************************************/
/***************************************************************************/
// static

Просмотреть файл

@ -65,7 +65,8 @@ static nsModuleComponentInfo components[] = {
{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_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)

Просмотреть файл

@ -48,6 +48,7 @@
#include "nscore.h"
#include "nsCOMPtr.h"
#include "nsAWritableString.h"
#include "nsVariant.h"
#include <stdio.h>
#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

Просмотреть файл

@ -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);
};

Просмотреть файл

@ -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.

Просмотреть файл

@ -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);

Просмотреть файл

@ -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();
}

Просмотреть файл

@ -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

Просмотреть файл

@ -20,6 +20,7 @@ nsSupportsArray.h
nsSupportsPrimitives.h
nsTime.h
nsUnitConversion.h
nsVariant.h
nsVector.h
nsVoidArray.h
nsVoidBTree.h

Просмотреть файл

@ -13,3 +13,4 @@ nsISupportsArray.idl
nsITimelineService.idl
nsISupportsIterators.idl
nsISupportsPrimitives.idl
nsIVariant.idl

Просмотреть файл

@ -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 \

Просмотреть файл

@ -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 \

Просмотреть файл

@ -44,8 +44,6 @@
* @See nsIBinaryInputStream
*/
[nsid] native nsID(nsID);
[scriptable, uuid(6c248606-4eae-46fa-9df0-ba58502368eb)]
interface nsIObjectInputStream : nsIBinaryInputStream
{

Просмотреть файл

@ -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,

Просмотреть файл

@ -1,8 +1,5 @@
#include "nsISupports.idl"
/* XXX should be built in */
native nsID(nsID *);
[uuid(1979e980-1cfd-11d3-915e-0000863011c4)]
interface nsITestProxy : nsISupports
{