Bug 173146 - add support to XPConnect for IDispatch interfaces. Final implementation, this is the result of the code walk through with jband, jst, adam, and rpots. sr=jst, r=adam, a=asa

This commit is contained in:
dbradley%netscape.com 2002-12-09 19:41:54 +00:00
Родитель 8408d2611f
Коммит 09c839447b
22 изменённых файлов: 943 добавлений и 685 удалений

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

@ -79,7 +79,7 @@ interface nsIDispatchSupport : nsISupports
* @param className contract ID or class ID of the desired component to instantiate
* @return The IDispatch interface pointer if instantiated
*/
IDispatch CreateInstance(in string className, in PRBool testScriptability);
IDispatch CreateInstance(in astring className, in PRBool testScriptability);
};
%{ C++

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

@ -125,6 +125,7 @@
#define NS_ERROR_XPC_COM_ERROR GENERATE_XPC_FAILURE(55)
#define NS_ERROR_XPC_COM_INVALID_CLASS_ID GENERATE_XPC_FAILURE(56)
#define NS_ERROR_XPC_COM_CREATE_FAILED GENERATE_XPC_FAILURE(57)
#define NS_ERROR_XPC_IDISPATCH_NOT_ENABLED GENERATE_XPC_FAILURE(58)
#endif
// any new errors here should have an associated entry added in xpc.msg
/***************************************************************************/

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

@ -44,42 +44,45 @@
VARTYPE XPCDispConvert::JSTypeToCOMType(XPCCallContext& ccx, jsval val)
{
if(JSVAL_IS_STRING(val))
if(JSVAL_IS_PRIMITIVE(val))
{
return VT_BSTR;
if(JSVAL_IS_STRING(val))
{
return VT_BSTR;
}
if(JSVAL_IS_INT(val))
{
return VT_I4;
}
if(JSVAL_IS_DOUBLE(val))
{
return VT_R8;
}
if(JSVAL_IS_BOOLEAN(val))
{
return VT_BOOL;
}
if(JSVAL_IS_VOID(val))
{
return VT_EMPTY;
}
if(JSVAL_IS_NULL(val))
{
return VT_NULL;
}
}
if(JSVAL_IS_INT(val))
{
return VT_I4;
}
if(JSVAL_IS_DOUBLE(val))
{
return VT_R8;
}
if(JSVAL_IS_OBJECT(val))
else
{
if(JS_IsArrayObject(ccx, JSVAL_TO_OBJECT(val)))
return VT_ARRAY | VT_VARIANT;
return VT_DISPATCH;
}
if(JSVAL_IS_BOOLEAN(val))
{
return VT_BOOL;
}
if(JSVAL_IS_VOID(val))
{
return VT_EMPTY;
}
if(JSVAL_IS_NULL(val))
{
return VT_NULL;
}
NS_ERROR("XPCDispConvert::JSTypeToCOMType was unable to identify the type of the jsval");
return VT_EMPTY;
}
JSBool XPCDispConvert::JSArrayToCOMArray(XPCCallContext& ccx, JSObject *obj,
VARIANT & var, nsresult& err)
VARIANT & var, nsresult& err)
{
err = NS_OK;
jsuint len;
@ -89,115 +92,264 @@ JSBool XPCDispConvert::JSArrayToCOMArray(XPCCallContext& ccx, JSObject *obj,
err = NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY;
return PR_FALSE;
}
// Create the safe array and populate it
SAFEARRAY * array = SafeArrayCreateVector(VT_VARIANT, 0, len);
for(long index = 0; index < len; ++index)
// Create the safe array of variants and populate it
SAFEARRAY * array = nsnull;
VARIANT* varArray = 0;
for(jsuint index = 0; index < len; ++index)
{
_variant_t arrayVar;
jsval val;
if(JS_GetElement(ccx, obj, index, &val) &&
JSToCOM(ccx, val, arrayVar, err))
if(JS_GetElement(ccx, obj, index, &val))
{
SafeArrayPutElement(array, &index, &arrayVar);
}
else
{
if(err == NS_OK)
err = NS_ERROR_FAILURE;
// This cleans up the elements as well
SafeArrayDestroyData(array);
return JS_FALSE;
if (!JSVAL_IS_VOID(val))
{
if (!array)
{
// Create an array that starts at index, and has len
// elements
array = SafeArrayCreateVector(VT_VARIANT, index, len - index);
if (!array)
{
err = NS_ERROR_OUT_OF_MEMORY;
return JS_FALSE;
}
if (FAILED(SafeArrayAccessData(array, NS_REINTERPRET_CAST(void**,&varArray))))
{
err = NS_ERROR_FAILURE;
return JS_FALSE;
}
}
if (!JSToCOM(ccx, val, *varArray, err))
{
SafeArrayUnaccessData(array);
err = NS_ERROR_FAILURE;
// This cleans up the elements as well
SafeArrayDestroyData(array);
return JS_FALSE;
}
}
if (varArray)
++varArray;
}
}
SafeArrayUnaccessData(array);
var.vt = VT_ARRAY | VT_VARIANT;
var.parray = array;
return JS_TRUE;
}
#define XPC_ASSIGN(src, dest, data) *dest.p##data = src.data
/**
* Copies a variant to a by ref variant
* NOTE: This does not perform any reference counting. It simply does
* a copy of the values, it's up to the caller to manage any ownership issues
* @param src the variant to be copied
* @param dest the destination for the copy
* @return JS_TRUE if the copy was performed JS_FALSE if it failed
*/
inline
JSBool xpc_CopyVariantByRef(VARIANT & src, VARIANT & dest)
{
VARIANT temp;
VARTYPE vt = dest.vt & ~(VT_BYREF);
if(vt != src.vt)
{
// TODO: This fails more than I had hoped, we may want to
// add some logic to handle more conversions
if(FAILED(VariantChangeType(&temp, &src, VARIANT_ALPHABOOL, vt)))
{
return JS_FALSE;
}
}
else
temp = src;
switch (vt)
{
case VT_I2:
{
XPC_ASSIGN(temp, dest, iVal);
}
break;
case VT_I4:
{
XPC_ASSIGN(temp, dest, lVal);
}
break;
case VT_R4:
{
XPC_ASSIGN(temp, dest, fltVal);
}
break;
case VT_R8:
{
XPC_ASSIGN(temp, dest, dblVal);
}
break;
case VT_CY:
{
XPC_ASSIGN(temp, dest, cyVal);
}
break;
case VT_DATE:
{
XPC_ASSIGN(temp, dest, date);
}
break;
case VT_BSTR:
{
XPC_ASSIGN(temp, dest, bstrVal);
}
break;
case VT_DISPATCH:
{
XPC_ASSIGN(temp, dest, pdispVal);
}
break;
case VT_ERROR:
{
XPC_ASSIGN(temp, dest, scode);
}
break;
case VT_BOOL:
{
XPC_ASSIGN(temp, dest, boolVal);
}
break;
case VT_VARIANT:
{
// Not Supported right now
return JS_FALSE;
}
break;
case VT_I1:
{
XPC_ASSIGN(temp, dest, cVal);
}
break;
case VT_UI1:
{
XPC_ASSIGN(temp, dest, bVal);
}
break;
case VT_UI2:
{
XPC_ASSIGN(temp, dest, iVal);
}
break;
case VT_UI4:
{
XPC_ASSIGN(temp, dest, uiVal);
}
break;
case VT_INT:
{
XPC_ASSIGN(temp, dest, intVal);
}
break;
case VT_UINT:
{
XPC_ASSIGN(temp, dest, uintVal);
}
break;
default:
{
return JS_FALSE;
}
}
return JS_TRUE;
}
JSBool XPCDispConvert::JSToCOM(XPCCallContext& ccx,
jsval src,
VARIANT & dest,
nsresult& err)
jsval src,
VARIANT & dest,
nsresult& err,
JSBool isByRef)
{
err = NS_OK;
if(JSVAL_IS_STRING(src))
VARIANT byRefVariant;
VARIANT * varDest = isByRef ? &byRefVariant : &dest;
varDest->vt = JSTypeToCOMType(ccx, src);
switch (varDest->vt)
{
JSString* str = JSVAL_TO_STRING(src);
if(!str)
case VT_BSTR:
{
JSString* str = JSVAL_TO_STRING(src);
jschar * chars = JS_GetStringChars(str);
if(!chars)
{
err = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
// Avoid cleaning up garabage
varDest->vt = VT_EMPTY;
return JS_FALSE;
}
CComBSTR val(JS_GetStringLength(str), chars);
varDest->bstrVal = val.Detach();
}
break;
case VT_I4:
{
varDest->vt = VT_I4;
varDest->lVal = JSVAL_TO_INT(src);
}
break;
case VT_R8:
{
varDest->vt = VT_R8;
varDest->dblVal = *JSVAL_TO_DOUBLE(src);
}
break;
case VT_EMPTY:
case VT_NULL:
break;
case VT_ARRAY | VT_VARIANT:
{
JSObject * obj = JSVAL_TO_OBJECT(src);
return JSArrayToCOMArray(ccx, obj, *varDest, err);
}
break;
case VT_DISPATCH:
{
JSObject * obj = JSVAL_TO_OBJECT(src);
// We only handle JS Objects that are IDispatch objects
if(!XPCConvert::GetNativeInterfaceFromJSObject(
ccx, (void**)&varDest->pdispVal, obj, &NSID_IDISPATCH,&err))
{
// Avoid cleaning up garabage
varDest->vt = VT_EMPTY;
return JS_FALSE;
}
}
break;
case VT_BOOL:
{
varDest->boolVal = JSVAL_TO_BOOLEAN(src) ? VARIANT_TRUE : VARIANT_FALSE;
}
break;
default:
{
NS_ERROR("This is out of synce with XPCDispConvert::JSTypeToCOMType");
err = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
// Avoid cleaning up garabage
varDest->vt = VT_EMPTY;
return JS_FALSE;
}
jschar * chars = JS_GetStringChars(str);
if(!chars)
break;
}
if(isByRef)
{
if (!xpc_CopyVariantByRef(byRefVariant, dest))
{
err = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
return JS_FALSE;
// Avoid cleaning up garabage
dest.vt = VT_EMPTY;
}
CComBSTR val(chars);
dest.vt = VT_BSTR;
dest.bstrVal = val.Detach();
}
else if(JSVAL_IS_INT(src))
{
dest.vt = VT_I4;
dest.lVal = JSVAL_TO_INT(src);
}
else if(JSVAL_IS_DOUBLE(src))
{
dest.vt = VT_R8;
dest.dblVal = *JSVAL_TO_DOUBLE(src);
}
else if(JSVAL_IS_VOID(src))
{
dest.vt = VT_EMPTY;
}
else if(JSVAL_IS_NULL(src))
{
dest.vt = VT_EMPTY;
}
else if(JSVAL_IS_OBJECT(src))
{
JSObject * obj = JSVAL_TO_OBJECT(src);
if(JS_IsArrayObject(ccx, obj))
{
return JSArrayToCOMArray(ccx, obj, dest, err);
}
else
{
// only wrap JSObjects
IUnknown * pUnknown;
XPCConvert::JSObject2NativeInterface(
ccx,
(void**)&pUnknown,
obj,
&NSID_IDISPATCH,
nsnull,
&err);
dest.vt = VT_DISPATCH;
pUnknown->QueryInterface(IID_IDispatch,
NS_REINTERPRET_CAST(void**,
&dest.pdispVal));
}
}
else if(JSVAL_IS_BOOLEAN(src))
{
dest.vt = VT_BOOL;
dest.boolVal = JSVAL_TO_BOOLEAN(src);
}
else // Unknown type
{
err = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
return JS_FALSE;
}
return JS_TRUE;
}
JSBool XPCDispConvert::COMArrayToJSArray(XPCCallContext& ccx,
const _variant_t & src,
jsval & dest, nsresult& err)
const VARIANT & src,
jsval & dest, nsresult& err)
{
err = NS_OK;
// We only support one dimensional arrays for now
@ -206,33 +358,45 @@ JSBool XPCDispConvert::COMArrayToJSArray(XPCCallContext& ccx,
err = NS_ERROR_FAILURE;
return JS_FALSE;
}
long size;
HRESULT hr = SafeArrayGetUBound(src.parray, 1, &size);
if(FAILED(hr))
// Get the upper bound;
long ubound;
if(FAILED(SafeArrayGetUBound(src.parray, 1, &ubound)))
{
err = NS_ERROR_FAILURE;
return JS_FALSE;
}
JSObject * array = JS_NewArrayObject(ccx, size, nsnull);
// Get the lower bound
long lbound;
if(FAILED(SafeArrayGetLBound(src.parray, 1, &lbound)))
{
err = NS_ERROR_FAILURE;
return JS_FALSE;
}
// Create the JS Array
JSObject * array = JS_NewArrayObject(ccx, ubound - lbound + 1, nsnull);
if(!array)
{
err = NS_ERROR_OUT_OF_MEMORY;
return JS_FALSE;
}
// Devine the type of our array
_variant_t var;
VARTYPE vartype;
if((src.vt & VT_ARRAY) != 0)
{
var.vt = src.vt & ~VT_ARRAY;
vartype = src.vt & ~VT_ARRAY;
}
else // This was maybe a VT_SAFEARRAY
{
SafeArrayGetVartype(src.parray, &var.vt);
if(FAILED(SafeArrayGetVartype(src.parray, &vartype)))
return JS_FALSE;
}
jsval val;
for(long index = 0; index <= size; ++index)
for(long index = lbound; index <= ubound; ++index)
{
hr = SafeArrayGetElement(src.parray, &index, &var.byref);
if(FAILED(hr))
// Devine the type of our array
_variant_t var;
var.vt = vartype;
if(FAILED(SafeArrayGetElement(src.parray, &index, &var.byref)))
{
err = NS_ERROR_FAILURE;
return JS_FALSE;
@ -246,110 +410,101 @@ JSBool XPCDispConvert::COMArrayToJSArray(XPCCallContext& ccx,
}
/**
* Converts an integer number to a jsval
* @param cx a JS context
* @param value the integer to be converted
* @return the converted jsval
* Converts a string to a jsval
* @param cx the JSContext
* @param str the unicode string to be converted
* @param len the length of the string being converted
* @return the jsval representing the string
*/
inline
jsval NumberToJSVal(JSContext* cx, int value)
jsval StringToJSVal(JSContext* cx, const PRUnichar * str, PRUint32 len)
{
jsval val;
if(INT_FITS_IN_JSVAL(value))
val = INT_TO_JSVAL(value);
else
{
if(!JS_NewDoubleValue(cx, NS_STATIC_CAST(jsdouble,value), &val))
val = JSVAL_ZERO;
}
return val;
}
/**
* Converts an floating point number to a jsval
* @param cx a JS context
* @param value the floating point number to be converted
* @return the converted jsval
*/
inline
jsval NumberToJSVal(JSContext* cx, double value)
{
jsval val;
if(JS_NewDoubleValue(cx, NS_STATIC_CAST(jsdouble, value), &val))
return val;
else
return JSVAL_ZERO;
}
inline
jsval StringToJSVal(JSContext* cx, const PRUnichar * str)
{
JSString * s = JS_NewUCStringCopyZ(cx, str);
if (s)
JSString * s = JS_NewUCStringCopyN(cx, str, len);
if(s)
return STRING_TO_JSVAL(s);
else
return JSVAL_NULL;
}
JSBool XPCDispConvert::COMToJS(XPCCallContext& ccx, const _variant_t & src,
jsval& dest, nsresult& err)
#define VALUE(val) (isPtr ? *src.p##val : src.val)
JSBool XPCDispConvert::COMToJS(XPCCallContext& ccx, const VARIANT& src,
jsval& dest, nsresult& err)
{
err = NS_OK;
if(src.vt & VT_ARRAY || src.vt == VT_SAFEARRAY)
{
return COMArrayToJSArray(ccx, src, dest, err);
}
PRBool isPtr = src.vt & VT_BYREF;
switch (src.vt & ~(VT_BYREF))
{
case VT_BSTR:
case VT_UINT:
{
if(src.vt & VT_BYREF)
dest = StringToJSVal(ccx, *src.pbstrVal);
else
dest = StringToJSVal(ccx, src.bstrVal);
return JS_NewNumberValue(ccx, VALUE(uintVal), &dest);
}
break;
case VT_UI4:
{
return JS_NewNumberValue(ccx, VALUE(ulVal), &dest);
}
break;
case VT_INT:
{
return JS_NewNumberValue(ccx, VALUE(intVal), &dest);
}
break;
case VT_I4:
{
dest = NumberToJSVal(ccx, src.lVal);
return JS_NewNumberValue(ccx, VALUE(lVal), &dest);
}
break;
case VT_UI1:
{
dest = INT_TO_JSVAL(src.bVal);
dest = INT_TO_JSVAL(VALUE(bVal));
}
break;
case VT_I1:
{
dest = INT_TO_JSVAL(VALUE(cVal));
}
break;
case VT_UI2:
{
dest = INT_TO_JSVAL(VALUE(uiVal));
}
break;
case VT_I2:
{
dest = INT_TO_JSVAL(src.iVal);
dest = INT_TO_JSVAL(VALUE(iVal));
}
break;
case VT_R4:
{
dest = NumberToJSVal(ccx, src.fltVal);
return JS_NewNumberValue(ccx, VALUE(fltVal), &dest);
}
break;
case VT_R8:
{
dest = NumberToJSVal(ccx, src.dblVal);
return JS_NewNumberValue(ccx, VALUE(dblVal), &dest);
}
break;
case VT_BOOL:
{
dest = BOOLEAN_TO_JSVAL(src.boolVal);
dest = BOOLEAN_TO_JSVAL(VALUE(boolVal) != VARIANT_FALSE ? JS_TRUE : JS_FALSE);
}
break;
case VT_DISPATCH:
{
XPCDispObject::WrapIDispatch(src.pdispVal, ccx,
XPCDispObject::WrapIDispatch(VALUE(pdispVal), ccx,
JS_GetGlobalObject(ccx), &dest);
}
break;
case VT_DATE:
{
_variant_t var(src);
_bstr_t bstr(var);
dest = StringToJSVal(ccx, NS_STATIC_CAST(const PRUnichar*, bstr));
// Convert date to string and frees it when we're done
_bstr_t str(src);
dest = StringToJSVal(ccx, str, str.length());
}
break;
case VT_EMPTY:
@ -357,22 +512,41 @@ JSBool XPCDispConvert::COMToJS(XPCCallContext& ccx, const _variant_t & src,
dest = JSVAL_NULL;
}
break;
case VT_ERROR:
{
return JS_NewNumberValue(ccx, VALUE(scode), &dest);
}
break;
case VT_CY:
{
return JS_NewNumberValue(
ccx,
NS_STATIC_CAST(double,
isPtr ? src.pcyVal->int64 :
src.cyVal.int64) / 100.0,
&dest);
}
break;
/**
* Currently unsupported conversion types
*/
case VT_ERROR:
case VT_CY:
case VT_UNKNOWN:
case VT_I1:
case VT_UI2:
case VT_UI4:
case VT_INT:
case VT_UINT:
default:
{
err = NS_ERROR_XPC_BAD_CONVERT_JS;
return JS_FALSE;
// Last ditch effort to convert to string
if(FAILED(VariantChangeType(NS_CONST_CAST(VARIANT*,&src),
NS_CONST_CAST(VARIANT*,&src),
VARIANT_ALPHABOOL, VT_BSTR)))
{
err = NS_ERROR_XPC_BAD_CONVERT_JS;
return JS_FALSE;
}
} // Fall through on success
case VT_BSTR:
{
dest = StringToJSVal(ccx, VALUE(bstrVal), SysStringLen(VALUE(bstrVal)));
}
break;
}
return JS_TRUE;
}

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

@ -334,7 +334,7 @@ void XPCDispNameArray::SetSize(PRUint32 size)
{
NS_ASSERTION(mCount == 0, "SetSize called more than once");
mCount = size;
mNames = (size ? new nsCString[size] : 0);
mNames = (size ? new nsString[size] : 0);
}
inline
@ -344,27 +344,27 @@ PRUint32 XPCDispNameArray::GetSize() const
}
inline
void XPCDispNameArray::SetName(DISPID dispid, nsACString const & name)
void XPCDispNameArray::SetName(DISPID dispid, nsAString const & name)
{
NS_ASSERTION(dispid <= mCount, "Array bounds error in XPCDispNameArray::SetName");
mNames[dispid - 1] = name;
}
inline
nsCString XPCDispNameArray::GetName(DISPID dispid) const
const nsAString & XPCDispNameArray::GetName(DISPID dispid) const
{
NS_ASSERTION(dispid <= mCount, "Array bounds error in XPCDispNameArray::Get");
if(dispid > 0)
return mNames[dispid - 1];
return nsCString();
return sEmpty;
}
inline
DISPID XPCDispNameArray::Find(const nsACString &target) const
DISPID XPCDispNameArray::Find(const nsAString &target) const
{
for(PRUint32 index = 0; index < mCount; ++index)
{
if(mNames[index] == target)
if(mNames[index].Equals(target))
return NS_STATIC_CAST(DISPID, index + 1);
}
return 0;
@ -429,7 +429,7 @@ PRUint32 XPCDispTypeInfo::FuncDescArray::Length() const
}
inline
nsCString XPCDispTypeInfo::GetNameForDispID(DISPID dispID)
const nsAString & XPCDispTypeInfo::GetNameForDispID(DISPID dispID)
{
return mNameArray.GetName(dispID);
}
@ -486,7 +486,7 @@ void XPCDispJSPropertyInfo::SetSetter()
}
inline
nsACString const & XPCDispJSPropertyInfo::GetName() const
const nsAString & XPCDispJSPropertyInfo::GetName() const
{
return mName;
}
@ -501,31 +501,31 @@ XPCDispJSPropertyInfo::property_type XPCDispJSPropertyInfo::PropertyType() const
// GUID/nsIID/nsCID conversion functions
inline
const nsIID & XPCDispGUID2nsIID(const struct _GUID & guid)
const nsIID & XPCDispIID2nsIID(const IID & iid)
{
NS_ASSERTION(sizeof(struct _GUID) == sizeof(nsIID), "GUID is not the same as nsIID");
return NS_REINTERPRET_CAST(const nsIID &,guid);
NS_ASSERTION(sizeof(IID) == sizeof(nsIID), "IID is not the same size as nsIID");
return NS_REINTERPRET_CAST(const nsIID &,iid);
}
inline
const GUID & XPCDispIID2GUID(const nsIID & iid)
const IID & XPCDispIID2IID(const nsIID & iid)
{
NS_ASSERTION(sizeof(struct _GUID) == sizeof(nsIID), "GUID is not the same as IID");
return NS_REINTERPRET_CAST(const struct _GUID &, iid);
NS_ASSERTION(sizeof(IID) == sizeof(nsIID), "IID is not the same size as nsIID");
return NS_REINTERPRET_CAST(const IID &, iid);
}
inline
const nsCID & XPCDispGUID2nsCID(const struct _GUID & guid)
const nsCID & XPCDispCLSID2nsCID(const CLSID & clsid)
{
NS_ASSERTION(sizeof(struct _GUID) == sizeof(nsCID), "GUID is not the same as nsCID");
return NS_REINTERPRET_CAST(const nsCID &,guid);
NS_ASSERTION(sizeof(CLSID) == sizeof(nsCID), "CLSID is not the same size as nsCID");
return NS_REINTERPRET_CAST(const nsCID &,clsid);
}
inline
const GUID & XPCDispCID2GUID(const nsCID & iid)
const CLSID & XPCDispnsCID2CLSID(const nsCID & clsid)
{
NS_ASSERTION(sizeof(struct _GUID) == sizeof(nsCID), "GUID is not the same as IID");
return NS_REINTERPRET_CAST(const struct _GUID &, iid);
NS_ASSERTION(sizeof(CLSID) == sizeof(nsCID), "CLSID is not the same size as nsCID");
return NS_REINTERPRET_CAST(const CLSID &, clsid);
}
//=============================================================================
@ -537,6 +537,14 @@ void XPCDispParams::SetNamedPropID()
mDispParams.rgdispidNamedArgs = &mPropID;
mDispParams.cNamedArgs = 1;
}
/*
inline
const VARIANT & XPCDispParams::GetParamRef(PRUint32 index) const
{
NS_ASSERTION(index < mDispParams.cArgs, "XPCDispParams::GetParam bounds error");
return mDispParams.rgvarg[mDispParams.cArgs - index - 1];
}
*/
inline
VARIANT & XPCDispParams::GetParamRef(PRUint32 index)
@ -555,7 +563,7 @@ inline
void * XPCDispParams::GetOutputBuffer(PRUint32 index)
{
NS_ASSERTION(index < mDispParams.cArgs, "XPCDispParams::GetParam bounds error");
return mVarBuffer + VARIANT_UNION_SIZE * index;
return mRefBuffer + sizeof(VARIANT) * index;
}
//=============================================================================
@ -579,14 +587,19 @@ JSBool XPCDispParamPropJSClass::Invoke(XPCCallContext& ccx,
* @return a C string (Does not need to be freed)
*/
inline
const char * xpc_JSString2Char(JSContext * cx, jsval val)
jschar * xpc_JSString2String(JSContext * cx, jsval val, PRUint32 * len = 0)
{
JSString* str = JS_ValueToString(cx, val);
if(!str)
return nsnull;
return JS_GetStringBytes(str);
JSString* str = JSVAL_IS_STRING(val) ? JSVAL_TO_STRING(val) :
JS_ValueToString(cx, val);
if(str)
{
if(len)
*len = JS_GetStringLength(str);
return JS_GetStringChars(str);
}
if(len)
*len = 0;
return nsnull;
}
/**

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

@ -41,7 +41,6 @@
*/
#include "xpcprivate.h"
#include <MBSTRING.H>
/**
* Is this function reflectable
@ -82,19 +81,16 @@ PRUint32 GetReflectableCount(ITypeInfo * pTypeInfo, PRUint32 members)
XPCDispInterface* XPCDispInterface::NewInstance(JSContext* cx, nsISupports * pIface)
{
IDispatch * pDispatch;
HRESULT hr = NS_REINTERPRET_CAST(IUnknown*,pIface)->QueryInterface(IID_IDispatch, (PVOID*)&pDispatch);
CComQIPtr<IDispatch> pDispatch(NS_REINTERPRET_CAST(IUnknown*,pIface));
if(SUCCEEDED(hr) && pDispatch)
if(pDispatch)
{
unsigned int count;
hr = pDispatch->GetTypeInfoCount(&count);
HRESULT hr = pDispatch->GetTypeInfoCount(&count);
if(SUCCEEDED(hr) && count > 0)
{
ITypeInfo* pPtr;
hr = pDispatch->GetTypeInfo(0,LOCALE_SYSTEM_DEFAULT, &pPtr);
CComPtr<ITypeInfo> pTypeInfo;
pTypeInfo.Attach(pPtr);
hr = pDispatch->GetTypeInfo(0,LOCALE_SYSTEM_DEFAULT, &pTypeInfo);
if(SUCCEEDED(hr))
{
TYPEATTR * attr;
@ -144,7 +140,7 @@ void ConvertInvokeKind(INVOKEKIND invokeKind, XPCDispInterface::Member & member)
}
}
void XPCDispInterface::InspectIDispatch(JSContext * cx, ITypeInfo * pTypeInfo, PRUint32 members)
PRBool XPCDispInterface::InspectIDispatch(JSContext * cx, ITypeInfo * pTypeInfo, PRUint32 members)
{
HRESULT hResult;
DISPID lastDispID = 0;
@ -154,8 +150,8 @@ void XPCDispInterface::InspectIDispatch(JSContext * cx, ITypeInfo * pTypeInfo, P
for(PRUint32 index = 0; index < members; index++ )
{
FUNCDESC* pFuncDesc;
hResult = pTypeInfo->GetFuncDesc( index, &pFuncDesc );
if(SUCCEEDED( hResult ))
hResult = pTypeInfo->GetFuncDesc(index, &pFuncDesc );
if(SUCCEEDED(hResult))
{
PRBool release = PR_TRUE;
if(IsReflectable(pFuncDesc))
@ -171,10 +167,14 @@ void XPCDispInterface::InspectIDispatch(JSContext * cx, ITypeInfo * pTypeInfo, P
1,
&nameCount)))
{
JSString* str = JS_InternUCString(cx, name);
JSString* str = JS_InternUCStringN(cx, name, ::SysStringLen(name));
::SysFreeString(name);
if(!str)
return PR_FALSE;
// Initialize
pInfo = new (pInfo) Member;
if(!pInfo)
return PR_FALSE;
pInfo->SetName(STRING_TO_JSVAL(str));
lastDispID = pFuncDesc->memid;
pInfo->ResetType();
@ -198,6 +198,7 @@ void XPCDispInterface::InspectIDispatch(JSContext * cx, ITypeInfo * pTypeInfo, P
}
}
}
return PR_TRUE;
}
/**
@ -211,11 +212,13 @@ void XPCDispInterface::InspectIDispatch(JSContext * cx, ITypeInfo * pTypeInfo, P
inline
PRBool CaseInsensitiveCompare(XPCCallContext& ccx, const PRUnichar* lhs, size_t lhsLength, jsval rhs)
{
if(lhsLength == 0)
return PR_FALSE;
size_t rhsLength;
PRUnichar* rhsString = xpc_JSString2PRUnichar(ccx, rhs, &rhsLength);
return rhsString &&
lhsLength == rhsLength &&
_wcsnicmp(lhs, rhsString, lhsLength * sizeof(PRUnichar)) == 0;
_wcsnicmp(lhs, rhsString, lhsLength) == 0;
}
const XPCDispInterface::Member* XPCDispInterface::FindMemberCI(XPCCallContext& ccx, jsval name) const

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

@ -45,17 +45,11 @@
/**
* This is COM's IDispatch IID, but in XPCOM's nsID type
*/
nsID NSID_IDISPATCH = { 0x00020400, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
/**
* Need this for ATL stuff
* We should look into the possiblity of removing this. It would be nice to
* break the ties to ATL all together at some point
*/
CComModule _Module;
const nsID NSID_IDISPATCH = { 0x00020400, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
PRBool
XPCDispObject::WrapIDispatch(IDispatch *pDispatch, JSContext *cx, JSObject *obj, jsval *rval)
XPCDispObject::WrapIDispatch(IDispatch *pDispatch, XPCCallContext &ccx,
JSObject *obj, jsval *rval)
{
if(!pDispatch)
{
@ -64,10 +58,10 @@ XPCDispObject::WrapIDispatch(IDispatch *pDispatch, JSContext *cx, JSObject *obj,
// Wrap the desired COM object
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = nsXPConnect::GetXPConnect()->WrapNative(cx, obj,
NS_REINTERPRET_CAST(nsISupports*, pDispatch),
NSID_IDISPATCH, getter_AddRefs(holder));
if(FAILED(rv) || !holder)
nsresult rv = ccx.GetXPConnect()->WrapNative(
ccx, obj, NS_REINTERPRET_CAST(nsISupports*, pDispatch), NSID_IDISPATCH,
getter_AddRefs(holder));
if(NS_FAILED(rv) || !holder)
{
return PR_FALSE;
}
@ -84,14 +78,14 @@ XPCDispObject::WrapIDispatch(IDispatch *pDispatch, JSContext *cx, JSObject *obj,
* @param the class ID of the COM object to be created
* @return true if it has the category
*/
static PRBool HasSafeScriptingCategory(const GUID & classID)
static PRBool HasSafeScriptingCategory(const CLSID & classID)
{
// TODO: probably should look into caching this if this becomes
// a performance issue
CComPtr<ICatInformation> catInfo;
HRESULT hr = catInfo.CoCreateInstance(CLSID_StdComponentCategoriesMgr);
// Must fail if we can't open the category manager
if(catInfo == NULL)
if(!catInfo)
return PR_FALSE;
// See what categories the class implements
@ -101,6 +95,7 @@ static PRBool HasSafeScriptingCategory(const GUID & classID)
// Search for matching categories
CATID catidNext = GUID_NULL;
// Get the next category, and no, I don't know what the 1 is
while(enumCATID->Next(1, &catidNext, NULL) == S_OK)
{
if(::IsEqualCATID(CATID_SafeForScripting, catidNext))
@ -122,22 +117,17 @@ PRBool ScriptOK(DWORD value)
INTERFACESAFE_FOR_UNTRUSTED_DATA);
}
HRESULT XPCDispObject::COMCreateInstance(const char * className, PRBool testScriptability, IDispatch ** result)
HRESULT XPCDispObject::COMCreateInstance(BSTR className, PRBool testScriptability, IDispatch ** result)
{
_bstr_t bstrName(className);
CLSID classID;
HRESULT hr;
// If this looks like a class ID
if(className[0] == '{' && className[strlen(className) -1] == '}')
if(FAILED(CLSIDFromString(className, &classID)))
{
hr = CLSIDFromString(bstrName, &classID);
hr = CLSIDFromProgID(className, &classID);
if(FAILED(hr))
return hr;
}
else // it's probably a prog ID
{
hr = CLSIDFromProgID(bstrName, &classID);
}
if(FAILED(hr))
return hr;
PRBool scriptableOK = PR_TRUE;
if(testScriptability)
scriptableOK = HasSafeScriptingCategory(classID);
@ -154,7 +144,7 @@ HRESULT XPCDispObject::COMCreateInstance(const char * className, PRBool testScri
{
CComQIPtr<IObjectSafety> objSafety(disp);
// Didn't have IObjectSafety so we'll bail
if(objSafety == 0)
if(!objSafety)
return E_FAIL;
DWORD supported;
DWORD state;
@ -172,18 +162,15 @@ HRESULT XPCDispObject::COMCreateInstance(const char * className, PRBool testScri
// static
JSBool XPCDispObject::Dispatch(XPCCallContext& ccx, IDispatch * disp,
DISPID dispID, CallMode mode,
XPCDispParams & params,
XPCDispParams * params,
jsval* retval,
XPCDispInterface::Member * member,
XPCJSRuntime* rt)
{
// avoid deadlock in case the native method blocks somehow
AutoJSSuspendRequest req(ccx); // scoped suspend of request
_variant_t dispResult;
jsval val;
uintN err;
uintN argc = params.GetParamCount();
uintN argc = params->GetParamCount();
// Figure out what we're doing (getter/setter/method)
WORD dispFlags;
if(mode == CALL_SETTER)
@ -198,16 +185,23 @@ JSBool XPCDispObject::Dispatch(XPCCallContext& ccx, IDispatch * disp,
{
dispFlags = DISPATCH_METHOD;
}
// call IDispatch's invoke
HRESULT invokeResult= disp->Invoke(
dispID, // IDispatch ID
IID_NULL, // Reserved must be IID_NULL
LOCALE_SYSTEM_DEFAULT, // The locale context, use the system's
dispFlags, // Type of Invoke call
params.GetDispParams(), // Parameters
&dispResult, // Where the result is stored
nsnull, // Exception information
0); // Index of an argument error
HRESULT invokeResult;
EXCEPINFO exception;
// Scope the lock
{
// avoid deadlock in case the native method blocks somehow
AutoJSSuspendRequest req(ccx); // scoped suspend of request
// call IDispatch's invoke
invokeResult= disp->Invoke(
dispID, // IDispatch ID
IID_NULL, // Reserved must be IID_NULL
LOCALE_SYSTEM_DEFAULT, // The locale context, use the system's
dispFlags, // Type of Invoke call
params->GetDispParams(), // Parameters
&dispResult, // Where the result is stored
&exception, // Exception information
0); // Index of an argument error
}
if(SUCCEEDED(invokeResult))
{
if(mode == CALL_METHOD)
@ -218,7 +212,7 @@ JSBool XPCDispObject::Dispatch(XPCCallContext& ccx, IDispatch * disp,
const XPCDispInterface::Member::ParamInfo & paramInfo = member->GetParamInfo(index);
if(paramInfo.IsOut())
{
if(!XPCDispConvert::COMToJS(ccx, params.GetParamRef(index), val, err))
if(!XPCDispConvert::COMToJS(ccx, params->GetParamRef(index), val, err))
return ThrowBadParam(err, index, ccx);
if(paramInfo.IsRetVal())
@ -227,10 +221,11 @@ JSBool XPCDispObject::Dispatch(XPCCallContext& ccx, IDispatch * disp,
}
else
{
// we actually assured this before doing the invoke
NS_ASSERTION(JSVAL_IS_OBJECT(val), "out var is not an object");
if(!OBJ_SET_PROPERTY(ccx, JSVAL_TO_OBJECT(val),
rt->GetStringID(XPCJSRuntime::IDX_VALUE), &val))
jsval * argv = ccx.GetArgv();
// Out, in/out parameters must be objects
if(!JSVAL_IS_OBJECT(argv[index]) ||
!OBJ_SET_PROPERTY(ccx, JSVAL_TO_OBJECT(argv[index]),
rt->GetStringID(XPCJSRuntime::IDX_VALUE), &val))
return ThrowBadParam(NS_ERROR_XPC_CANT_SET_OUT_VAL, index, ccx);
}
}
@ -250,7 +245,9 @@ JSBool XPCDispObject::Dispatch(XPCCallContext& ccx, IDispatch * disp,
if(NS_FAILED(invokeResult))
{
XPCThrower::ThrowCOMError(ccx, invokeResult);
XPCThrower::ThrowCOMError(ccx, invokeResult, NS_ERROR_XPC_COM_ERROR,
invokeResult == DISP_E_EXCEPTION ?
&exception : nsnull);
return JS_FALSE;
}
return JS_TRUE;
@ -308,18 +305,19 @@ JSBool XPCDispObject::Invoke(XPCCallContext & ccx, CallMode mode)
jsval name = member->GetName();
nsIXPCSecurityManager* sm = xpcc->GetAppropriateSecurityManager(secFlag);
XPCWrappedNative* wrapper = ccx.GetWrapper();
if(sm && NS_FAILED(sm->CanAccess(secAction, &ccx, ccx,
ccx.GetFlattenedJSObject(),
ccx.GetWrapper()->GetIdentityObject(),
ccx.GetWrapper()->GetClassInfo(), name,
ccx.GetWrapper()->GetSecurityInfoAddr())))
wrapper->GetIdentityObject(),
wrapper->GetClassInfo(), name,
wrapper->GetSecurityInfoAddr())))
{
// the security manager vetoed. It should have set an exception.
return JS_FALSE;
}
XPCWrappedNative* wrapper = ccx.GetWrapper();
nsISupports * pObj = ccx.GetTearOff()->GetNative();
IDispatch * pObj = NS_REINTERPRET_CAST(IDispatch*,
ccx.GetTearOff()->GetNative());
PRUint32 args = member->GetParamCount();
uintN err;
// Make sure setter has one argument
@ -329,14 +327,17 @@ JSBool XPCDispObject::Invoke(XPCCallContext & ccx, CallMode mode)
// are not enough parameters
if(argc < args)
args = argc;
XPCDispParams params(args);
XPCDispParams * params = new XPCDispParams(args);
jsval val;
// If this is a setter, we just need to convert the first parameter
if(mode == CALL_SETTER)
{
params.SetNamedPropID();
if(!XPCDispConvert::JSToCOM(ccx, argv[0],params.GetParamRef(0), err))
params->SetNamedPropID();
if(!XPCDispConvert::JSToCOM(ccx, argv[0], params->GetParamRef(0), err))
{
delete params;
return ThrowBadParam(err, 0, ccx);
}
}
else if(mode != CALL_GETTER) // This is a function
{
@ -354,17 +355,20 @@ JSBool XPCDispObject::Invoke(XPCCallContext & ccx, CallMode mode)
rt->GetStringID(XPCJSRuntime::IDX_VALUE),
&val))
{
ThrowBadParam(NS_ERROR_XPC_NEED_OUT_OBJECT, index, ccx);
delete params;
return ThrowBadParam(NS_ERROR_XPC_NEED_OUT_OBJECT, index, ccx);
}
paramInfo.InitializeOutputParam(params->GetOutputBuffer(index), params->GetParamRef(index));
}
if(!XPCDispConvert::JSToCOM(ccx, val,params.GetParamRef(index), err))
if(!XPCDispConvert::JSToCOM(ccx, val, params->GetParamRef(index), err, paramInfo.IsOut()))
{
ThrowBadParam(err, index, ccx);
delete params;
return ThrowBadParam(err, index, ccx);
}
}
else
{
paramInfo.InitializeOutputParam(params.GetOutputBuffer(index), params.GetParamRef(index));
paramInfo.InitializeOutputParam(params->GetOutputBuffer(index), params->GetParamRef(index));
}
}
}
@ -372,35 +376,37 @@ JSBool XPCDispObject::Invoke(XPCCallContext & ccx, CallMode mode)
if(member->IsParameterizedProperty())
{
// We need to get a parameterized property object to return to JS
if(XPCDispParamPropJSClass::GetNewOrUsed(ccx, wrapper,
member->GetDispID(),
params, &val))
// NewInstance takes ownership of params
if(XPCDispParamPropJSClass::NewInstance(ccx, wrapper,
member->GetDispID(),
params, &val))
{
ccx.SetRetVal(val);
if(!JS_IdToValue(ccx, 1, &val))
{
// This shouldn't fail
NS_ERROR("JS_IdToValue failed in XPCDispParamPropJSClass::NewInstance");
return JS_FALSE;
}
JS_SetCallReturnValue2(ccx, val);
return JS_TRUE;
}
// NewInstance would only fail if there was an out of memory problem
JS_ReportOutOfMemory(ccx);
delete params;
return JS_FALSE;
}
IDispatch * pDisp;
// TODO: I'm not sure this QI is really needed
nsresult result = pObj->QueryInterface(NSID_IDISPATCH, (void**)&pDisp);
if(NS_SUCCEEDED(result))
JSBool retval = Dispatch(ccx, pObj, member->GetDispID(), mode, params, &val, member, rt);
if(retval && mode == CALL_SETTER)
{
JSBool retval = Dispatch(ccx, pDisp, member->GetDispID(), mode, params, &val, member, rt);
if(retval && mode == CALL_SETTER)
{
ccx.SetRetVal(argv[0]);
}
else
{
ccx.SetRetVal(val);
}
return retval;
ccx.SetRetVal(argv[0]);
}
return JS_FALSE;
else
{
ccx.SetRetVal(val);
}
delete params;
return retval;
}
static
@ -466,13 +472,14 @@ XPC_IDispatch_CallMethod(JSContext* cx, JSObject* obj, uintN argc,
XPCDispInterface::Member* member;
XPCNativeInterface* iface;
if(GetMember(ccx, funobj, iface, member))
{
ccx.SetIDispatchInfo(iface, member);
#ifdef DEBUG
PRBool ok =
#endif
GetMember(ccx, funobj, iface, member);
NS_ASSERTION(ok, "GetMember faild in XPC_IDispatch_CallMethod");
ccx.SetIDispatchInfo(iface, member);
return XPCDispObject::Invoke(ccx, XPCDispObject::CALL_METHOD);
}
return JS_FALSE;
return XPCDispObject::Invoke(ccx, XPCDispObject::CALL_METHOD);
}
/**
@ -500,10 +507,12 @@ XPC_IDispatch_GetterSetter(JSContext *cx, JSObject *obj, uintN argc,
ccx.SetArgsAndResultPtr(argc, argv, vp);
XPCDispInterface::Member* member;
XPCNativeInterface* iface;
if(GetMember(ccx, funobj, iface, member))
{
ccx.SetIDispatchInfo(iface, member);
return XPCDispObject::Invoke(ccx, argc != 0 ? XPCDispObject::CALL_SETTER : XPCDispObject::CALL_GETTER);
}
return JS_FALSE;
#ifdef DEBUG
PRBool ok =
#endif
GetMember(ccx, funobj, iface, member);
NS_ASSERTION(ok, "GetMember faild in XPC_IDispatch_CallMethod");
ccx.SetIDispatchInfo(iface, member);
return XPCDispObject::Invoke(ccx, argc != 0 ? XPCDispObject::CALL_SETTER : XPCDispObject::CALL_GETTER);
}

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

@ -73,7 +73,7 @@ XPC_PP_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
XPCDispParamPropJSClass* paramProp = GetParamProp(cx, obj);
JSObject* originalObj = paramProp->GetWrapper()->GetFlatJSObject();
XPCCallContext ccx(JS_CALLER, cx, originalObj, nsnull, id,
paramProp->GetParams().GetParamCount(), nsnull, vp);
paramProp->GetParams()->GetParamCount(), nsnull, vp);
return paramProp->Invoke(ccx, XPCDispObject::CALL_GETTER, vp);
}
@ -94,15 +94,15 @@ XPC_PP_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
XPCDispParamPropJSClass* paramProp = GetParamProp(cx, obj);
JSObject* originalObj = paramProp->GetWrapper()->GetFlatJSObject();
XPCCallContext ccx(JS_CALLER, cx, originalObj, nsnull, id,
paramProp->GetParams().GetParamCount(), nsnull, vp);
paramProp->GetParams()->GetParamCount(), nsnull, vp);
_variant_t var;
uintN err;
if(!XPCDispConvert::JSToCOM(ccx, *vp, var, err))
return JS_FALSE;
XPCDispParams& params = paramProp->GetParams();
params.SetNamedPropID();
XPCDispParams* params = paramProp->GetParams();
params->SetNamedPropID();
// params will own var
params.InsertParam(var);
params->InsertParam(var);
return paramProp->Invoke(ccx, XPCDispObject::CALL_SETTER, vp);
}
@ -173,10 +173,10 @@ static JSClass ParamPropClass = {
};
// static
JSBool XPCDispParamPropJSClass::GetNewOrUsed(XPCCallContext& ccx,
JSBool XPCDispParamPropJSClass::NewInstance(XPCCallContext& ccx,
XPCWrappedNative* wrapper,
PRUint32 dispID,
XPCDispParams& dispParams,
XPCDispParams* dispParams,
jsval* paramPropObj)
{
XPCDispParamPropJSClass* pDispParam =
@ -196,22 +196,22 @@ JSBool XPCDispParamPropJSClass::GetNewOrUsed(XPCCallContext& ccx,
XPCDispParamPropJSClass::XPCDispParamPropJSClass(XPCWrappedNative* wrapper,
nsISupports * dispObj,
PRUint32 dispID,
XPCDispParams& dispParams) :
XPCDispParams* dispParams) :
mWrapper(wrapper),
mDispID(dispID),
mDispParams(dispParams)
mDispParams(dispParams),
mDispObj(nsnull)
{
NS_ADDREF(mWrapper);
nsresult result = dispObj->QueryInterface(NSID_IDISPATCH,
dispObj->QueryInterface(NSID_IDISPATCH,
NS_REINTERPRET_CAST(void**,
&mDispObj));
if(NS_FAILED(result))
mDispObj = nsnull;
}
XPCDispParamPropJSClass::~XPCDispParamPropJSClass()
{
delete mDispParams;
// release our members
NS_RELEASE(mWrapper);
NS_RELEASE(mDispObj);
NS_IF_RELEASE(mWrapper);
NS_IF_RELEASE(mDispObj);
}

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

@ -43,52 +43,32 @@
#include "xpcprivate.h"
XPCDispParams::XPCDispParams(PRUint32 args) :
mVarBuffer(args <= DEFAULT_ARG_ARRAY_SIZE ?
mVarStackBuffer : new char[XPC_VARIANT_BUFFER_SIZE(args)]),
mRefBuffer(mStackRefBuffer + sizeof(VARIANT)),
mDispParamsAllocated(nsnull),
mRefBufferAllocated(nsnull),
mPropID(DISPID_PROPERTYPUT)
#ifdef DEBUG
,mInserted(PR_FALSE)
#endif
{
memset(mVarBuffer, 0, XPC_VARIANT_BUFFER_SIZE(args));
if(args >= DEFAULT_ARG_ARRAY_SIZE)
{
mRefBufferAllocated = new char[RefBufferSize(args)];
mRefBuffer = mRefBufferAllocated + sizeof(VARIANT);
}
// Initialize the full buffer that was allocated
memset(mRefBuffer - sizeof(VARIANT), 0, RefBufferSize(args));
// Initialize the IDispatch parameters
mDispParams.cArgs = args;
mDispParams.rgvarg = args <= DEFAULT_ARG_ARRAY_SIZE ? mStackArgs : new VARIANT[args];
mDispParams.rgdispidNamedArgs = nsnull;
mDispParams.cNamedArgs = 0;
}
XPCDispParams::XPCDispParams(XPCDispParams & other) :
mPropID(DISPID_PROPERTYPUT)
{
// copy the simple values
mDispParams.rgdispidNamedArgs = nsnull;
mDispParams.cNamedArgs = 0;
mDispParams.cArgs = other.mDispParams.cArgs;
// move the variant buffer, used for reference types
if(other.mVarBuffer == other.mVarStackBuffer)
{
mVarBuffer = mVarStackBuffer;
memcpy(mVarBuffer, other.mVarBuffer,
XPC_VARIANT_BUFFER_SIZE(other.mDispParams.cArgs));
}
if(args <= DEFAULT_ARG_ARRAY_SIZE)
mDispParams.rgvarg = mStackArgs + 1;
else
{
mVarBuffer = other.mVarBuffer;
other.mVarBuffer = nsnull;
mDispParamsAllocated = new VARIANT[args + 1];
mDispParams.rgvarg = mDispParamsAllocated + 1;
}
// move the variants
if(other.mDispParams.rgvarg == other.mStackArgs)
{
mDispParams.rgvarg = mStackArgs;
memcpy(mDispParams.rgvarg, other.mStackArgs,
sizeof(VARIANT) * other.mDispParams.cArgs);
other.mDispParams.cArgs;
}
else
{
mDispParams.rgvarg = other.mDispParams.rgvarg;
other.mDispParams.rgvarg = 0;
}
// The source no longer has arguments
other.mDispParams.cArgs = 0;
mDispParams.rgdispidNamedArgs = nsnull;
mDispParams.cNamedArgs = 0;
}
@ -97,31 +77,25 @@ XPCDispParams::~XPCDispParams()
// Cleanup the variants
for(PRUint32 index = 0; index < mDispParams.cArgs; ++index)
VariantClear(mDispParams.rgvarg + index);
// Cleanup if we allocated the variant array
if(mDispParams.rgvarg != mStackArgs)
delete [] mDispParams.rgvarg;
if(mVarBuffer != mVarStackBuffer)
delete [] mVarBuffer;
// Cleanup if we allocated the variant array. Remember that
// our buffer may point one element into the allocate buffer
delete [] mRefBufferAllocated;
delete [] mDispParamsAllocated;
}
void XPCDispParams::InsertParam(_variant_t & var)
{
// Save off the existing pointers
VARIANT* oldArgs = mDispParams.rgvarg;
char * oldVarBuffer = mVarBuffer;
// If this will exceed our internal static buffers we need to create
// dynamic ones
if(mDispParams.cNamedArgs >= DEFAULT_ARG_ARRAY_SIZE)
{
if(mDispParams.rgvarg == mStackArgs)
mDispParams.rgvarg = new VARIANT[mDispParams.cArgs + 1];
if(mVarBuffer == mVarStackBuffer)
mVarBuffer = new char [XPC_VARIANT_BUFFER_SIZE(mDispParams.cArgs + 1)];
}
// Move the data up, using position safe copy
memmove(mDispParams.rgvarg + 1, oldArgs, sizeof(VARIANT) * mDispParams.cArgs);
memmove(mVarBuffer + VARIANT_UNION_SIZE,oldVarBuffer, XPC_VARIANT_BUFFER_SIZE(mDispParams.cArgs));
mDispParams.rgvarg[0] = var.Detach();
memset(mVarBuffer, 0, VARIANT_UNION_SIZE);
#ifdef DEBUG
NS_ASSERTION(!mInserted,
"XPCDispParams::InsertParam cannot be called more than once");
mInserted = PR_TRUE;
#endif
// Bump the pointer back and increment the arg count
--mDispParams.rgvarg;
mRefBuffer -= sizeof(VARIANT);
++mDispParams.cArgs;
// Assign the value
mDispParams.rgvarg[0] = var.Detach();
// initialize the ref buffer
memset(mRefBuffer, 0, sizeof(VARIANT));
}

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

@ -47,27 +47,46 @@
#error "DispPrivate.h should not be included directly, please use XPCPrivate.h"
#endif
/**
* Needed for CComPtr and friends
*/
#include <atlbase.h>
/**
* Needed for _variant_t and _bstr_t
*/
#include <comdef.h>
/**
* IObjectSafety interface and friends
*/
#include "objsafe.h"
// MS clutters the global namespace with so many macro names :-(
// I tried to keep these includes in the CPP's but it became too
// convoluted
#undef GetClassInfo
#undef GetClassName
#undef GetMessage
// We need IDispatch
#include "nsIDispatchSupport.h"
// The following are macro helpers pulled from XPCOM but tailored to COM
#define NS_DECL_IUNKNOWN \
public: \
STDMETHOD(QueryInterface)(const struct _GUID& aIID, \
STDMETHOD(QueryInterface)(REFIID aIID, \
void** aInstancePtr); \
STDMETHODIMP_(nsrefcnt) AddRef(void); \
STDMETHODIMP_(nsrefcnt) Release(void); \
STDMETHODIMP_(ULONG) AddRef(void); \
STDMETHODIMP_(ULONG) Release(void); \
protected: \
nsAutoRefCnt mRefCnt; \
NS_DECL_OWNINGTHREAD \
ULONG mRefCnt;
#define NS_IMPL_COM_QUERY_HEAD(_class) \
STDMETHODIMP _class::QueryInterface(const GUID& aIID, void** aInstancePtr) \
STDMETHODIMP _class::QueryInterface(REFIID aIID, void** aInstancePtr) \
{ \
NS_ASSERTION(aInstancePtr, \
"QueryInterface requires a non-NULL destination!"); \
if( !aInstancePtr ) \
return NS_ERROR_NULL_POINTER; \
return E_POINTER; \
IUnknown* foundInterface;
#define NS_IMPL_COM_QUERY_BODY(_interface) \
@ -77,13 +96,13 @@ STDMETHODIMP _class::QueryInterface(const GUID& aIID, void** aInstancePtr) \
#define NS_IMPL_COM_QUERY_TAIL_GUTS \
foundInterface = 0; \
nsresult status; \
HRESULT status; \
if( !foundInterface ) \
status = NS_NOINTERFACE; \
status = E_NOINTERFACE; \
else \
{ \
NS_ADDREF(foundInterface); \
status = NS_OK; \
status = S_OK; \
} \
*aInstancePtr = foundInterface; \
return status; \
@ -93,11 +112,36 @@ STDMETHODIMP _class::QueryInterface(const GUID& aIID, void** aInstancePtr) \
#define NS_COM_MAP_ENTRY(_interface) NS_IMPL_COM_QUERY_BODY(_interface)
#define NS_COM_MAP_END NS_IMPL_COM_QUERY_TAIL_GUTS
#define NS_COM_IMPL_ADDREF(_class) \
STDMETHODIMP_(ULONG) _class::AddRef(void) \
{ \
NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \
NS_ASSERT_OWNINGTHREAD(_class); \
++mRefCnt; \
NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \
return mRefCnt; \
}
#define NS_COM_IMPL_RELEASE(_class) \
STDMETHODIMP_(ULONG) _class::Release(void) \
{ \
NS_PRECONDITION(0 != mRefCnt, "dup release"); \
NS_ASSERT_OWNINGTHREAD(_class); \
--mRefCnt; \
NS_LOG_RELEASE(this, mRefCnt, #_class); \
if(mRefCnt == 0) { \
mRefCnt = 1; /* stabilize */ \
delete this; \
return 0; \
} \
return mRefCnt; \
}
#ifndef NS_MT_SUPPORTED
#error "We need MT support
#endif
extern nsID NSID_IDISPATCH;
extern const nsID NSID_IDISPATCH;
/**
* JS<>COM Conversion functions. XPCDispConvert serves more as a namespace than
@ -125,7 +169,8 @@ public:
* @return True if the conversion succeeded
*/
static
JSBool JSToCOM(XPCCallContext& ccx, jsval src, VARIANT & dest, nsresult& err);
JSBool JSToCOM(XPCCallContext& ccx, jsval src, VARIANT & dest,
nsresult& err, JSBool isByRef = JS_FALSE);
/**
* Converts a COM variant to a jsval
@ -136,7 +181,7 @@ public:
* @return Returns true if the conversion succeeded
*/
static
JSBool COMToJS(XPCCallContext& ccx, const _variant_t & src, jsval & dest,
JSBool COMToJS(XPCCallContext& ccx, const VARIANT & src, jsval & dest,
nsresult& err);
private:
/**
@ -159,7 +204,7 @@ private:
* @return True if the conversion succeeded
*/
static
JSBool COMArrayToJSArray(XPCCallContext& ccx, const _variant_t & src,
JSBool COMArrayToJSArray(XPCCallContext& ccx, const VARIANT & src,
jsval & dest, nsresult& err);
};
@ -220,22 +265,27 @@ public:
* @param dispid IDispatch id for the name
* @param name the name to assign
*/
void SetName(DISPID dispid, nsACString const & name);
void SetName(DISPID dispid, nsAString const & name);
/**
* Retrieves a name/string for a dispid. This function
* performs bounds checking in debug builds
* @param dispid dispatch ID of the name to retrieve
*/
nsCString GetName(DISPID dispid) const;
const nsAString& GetName(DISPID dispid) const;
/**
* Performs a search of the array for the target returning the
* the id for the name
* @param target the name to find
*/
DISPID Find(const nsACString &target) const;
DISPID Find(const nsAString &target) const;
private:
/**
* This is used by Find when it doesn't find something
* @see XPCDispNameArray::Find
*/
static const nsString sEmpty;
PRUint32 mCount;
nsCString* mNames;
nsString* mNames;
};
/**
@ -436,7 +486,7 @@ public:
* @param dispID the DISPID to look up
* @return the name of the function
*/
nsCString GetNameForDispID(DISPID dispID);
const nsAString& GetNameForDispID(DISPID dispID);
private:
/**
* Initializes the object
@ -524,7 +574,7 @@ public:
* returns the name of the property/method
* @return the name of the property/method
*/
nsACString const & GetName() const;
nsAString const & GetName() const;
private:
enum property_type
{
@ -539,7 +589,7 @@ private:
PRUint32 mParamCount;
PRUint32 mMemID;
jsval mProperty;
nsCAutoString mName;
nsString mName;
/**
* Accessor for the property type mProperty
@ -584,7 +634,7 @@ public:
* interface pointer
* @return HRESULT
*/
STDMETHOD(QueryInterface)(const struct _GUID & IID,void ** pPtr);
STDMETHOD(QueryInterface)(REFIID IID,void ** pPtr);
/**
* Returns the number of type info's for this IDispatch instance.
* See MSDN for form information
@ -622,12 +672,14 @@ private:
// The Type information for our instance
XPCDispTypeInfo * mCOMTypeInfo;
// Reference count
nsrefcnt mRefCnt;
ULONG mRefCnt;
// Returns the type information
XPCDispTypeInfo * GetCOMTypeInfo();
// Returns the JS Object being used to wrap
inline
JSObject* GetJSObject();
NS_DECL_OWNINGTHREAD;
};
/**
@ -909,8 +961,10 @@ private:
* @param cx a JS context
* @param pTypeInfo pointer to the type information for the object
* @param members number of members in the interface
* @return PR_TRUE if it worked, PR_FALSE if it didn't (usually out of
* memory)
*/
void InspectIDispatch(JSContext * cx, ITypeInfo * pTypeInfo,
PRBool InspectIDispatch(JSContext * cx, ITypeInfo * pTypeInfo,
PRUint32 members);
};
@ -937,7 +991,7 @@ public:
*/
static
JSBool Dispatch(XPCCallContext& ccx, IDispatch * pDisp,
DISPID dispID, CallMode mode, XPCDispParams & params,
DISPID dispID, CallMode mode, XPCDispParams * params,
jsval* retval, XPCDispInterface::Member* member = nsnull,
XPCJSRuntime* rt = nsnull);
/**
@ -956,7 +1010,7 @@ public:
* @param result pointer to the pointer to receive the interface pointer
*/
static
HRESULT COMCreateInstance(const char * className,
HRESULT COMCreateInstance(BSTR className,
PRBool testScriptability, IDispatch ** result);
/**
* Wraps an IDispatch interface, returning the object as a jsval
@ -966,7 +1020,7 @@ public:
* @param rval is a pointer to a jsval to receive the JS object wrapper
*/
static
PRBool WrapIDispatch(IDispatch *pDispatch, JSContext *cx,
PRBool WrapIDispatch(IDispatch *pDispatch, XPCCallContext & ccx,
JSObject *obj, jsval *rval);
};
@ -1044,10 +1098,6 @@ public:
* @param args the number of parameters this object will hold
*/
XPCDispParams(PRUint32 args);
/**
* Makes a copy and transfers ownership of buffers
*/
XPCDispParams(XPCDispParams & other);
/**
* Cleans up the parameters' data
*/
@ -1062,6 +1112,12 @@ public:
* @param index index of the parameter
* @return a reference to the parameter at index
*/
// const VARIANT & GetParamRef(PRUint32 index) const;
/**
* Returns a reference to a parameter
* @param index index of the parameter
* @return a reference to the parameter at index
*/
VARIANT & GetParamRef(PRUint32 index);
/**
* Returns the parameter by value
@ -1079,7 +1135,7 @@ public:
* Returns a DISPPARAMS structure pointer for the parameters
* @return a DISPPARAMS structure pointer for the parameters
*/
DISPPARAMS* GetDispParams() { return &mDispParams; }
DISPPARAMS* GetDispParams() const { return &NS_CONST_CAST(XPCDispParams*,this)->mDispParams; }
/**
* Returns the number of parameters
* @return the number of parameters
@ -1092,6 +1148,11 @@ public:
*/
void InsertParam(_variant_t & var);
private:
/**
* Don't allow copying
*/
XPCDispParams(const XPCDispParams & other) {
NS_ERROR("XPCDispParams can't be copied"); }
/**
* We don't allow assignments
*/
@ -1101,16 +1162,24 @@ private:
enum
{
DEFAULT_ARG_ARRAY_SIZE = 8,
// This is the size of the largest member in the union in VARIANT
VARIANT_UNION_SIZE = sizeof(VARIANT) - sizeof(VARTYPE) - sizeof(unsigned short) * 3
DEFAULT_REF_BUFFER_SIZE = 8 * sizeof(VARIANT)
};
#define XPC_VARIANT_BUFFER_SIZE(count) (VARIANT_UNION_SIZE * count)
static
PRUint32 RefBufferSize(PRUint32 args) { return (args + 1) * sizeof(VARIANT); }
DISPPARAMS mDispParams;
char* mVarBuffer;
char mVarStackBuffer[XPC_VARIANT_BUFFER_SIZE(DEFAULT_ARG_ARRAY_SIZE)];
char* mRefBuffer;
VARIANT* mDispParamsAllocated;
char* mRefBufferAllocated;
/**
* Used by output/ref variant types
*/
char mStackRefBuffer[DEFAULT_REF_BUFFER_SIZE];
VARIANT mStackArgs[DEFAULT_ARG_ARRAY_SIZE];
DISPID mPropID;
#ifdef DEBUG
PRBool mInserted;
#endif
};
/**
@ -1132,9 +1201,9 @@ public:
* JS function object
* @return true if the JS function object was created
*/
static JSBool GetNewOrUsed(XPCCallContext& ccx, XPCWrappedNative* wrapper,
static JSBool NewInstance(XPCCallContext& ccx, XPCWrappedNative* wrapper,
PRUint32 dispID,
XPCDispParams& dispParams,
XPCDispParams* dispParams,
jsval* paramPropObj);
/**
* Cleans up the member, derefs the mDispObj, mWrapper and such
@ -1158,7 +1227,7 @@ public:
* Returns the parameters for the parameterized property
* @return a reference to the parameters for the parameterized property
*/
XPCDispParams& GetParams() { return mDispParams; }
XPCDispParams* GetParams() const { return mDispParams; }
private:
/**
* Private constructor to initialize data members
@ -1168,11 +1237,11 @@ private:
* @param dispParams the parameters for the parameterized property
*/
XPCDispParamPropJSClass(XPCWrappedNative* wrapper, nsISupports* dispObj,
PRUint32 dispID, XPCDispParams& dispParams);
PRUint32 dispID, XPCDispParams* dispParams);
XPCWrappedNative* mWrapper;
PRUint32 mDispID;
XPCDispParams mDispParams;
XPCDispParams* mDispParams;
IDispatch* mDispObj;
};

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

@ -50,46 +50,31 @@
*/
static HRESULT Error(HRESULT hResult, const CComBSTR & message)
{
ICreateErrorInfo * pCreateError;
IErrorInfo * pError;
CComPtr<ICreateErrorInfo> pCreateError;
CComPtr<IErrorInfo> pError;
HRESULT result = CreateErrorInfo(&pCreateError);
if (FAILED(result))
if(FAILED(result))
return E_NOTIMPL;
result = pCreateError->QueryInterface(&pError);
if (FAILED(result))
if(FAILED(result))
return E_NOTIMPL;
result = pCreateError->SetDescription(message);
if (FAILED(result))
if(FAILED(result))
return E_NOTIMPL;
result = pCreateError->SetGUID(IID_IDispatch);
if (FAILED(result))
if(FAILED(result))
return E_NOTIMPL;
CComBSTR source(L"@mozilla.XPCDispatchTearOff");
result = pCreateError->SetSource(source);
if (FAILED(result))
if(FAILED(result))
return E_NOTIMPL;
result = SetErrorInfo(0, pError);
if (FAILED(result))
if(FAILED(result))
return E_NOTIMPL;
pError->Release();
pCreateError->Release();
return hResult;
}
/**
* Sets the COM error from a result code and text message
* @param hResult the COM error code to be used
* @param message the message to put in the error
* @return the error code passed in via hResult
*/
inline
HRESULT Error(HRESULT hResult, const nsCString & message)
{
CComBSTR someText(PromiseFlatCString(message).get());
return Error(hResult, someText);
}
/**
* Sets the COM error from a result code and text message
* @param hResult the COM error code to be used
@ -108,28 +93,22 @@ HRESULT Error(HRESULT hResult, const char * message)
* @param exception
* @return the description of the exception
*/
static nsCString BuildMessage(nsIException * exception)
static void BuildMessage(nsIException * exception, nsCString & result)
{
nsCString result;
char * msg;
if(NS_FAILED(exception->GetMessage(&msg)))
msg = "";
char * filename;
if(NS_FAILED(exception->GetFilename(&filename)))
filename = "";
nsXPIDLCString msg;
exception->GetMessage(getter_Copies(msg));
nsXPIDLCString filename;
exception->GetFilename(getter_Copies(filename));
PRUint32 lineNumber;
if(NS_FAILED(exception->GetLineNumber(&lineNumber)))
lineNumber = 0;
char lineNumberStr[32];
sprintf(lineNumberStr, "%d", lineNumber);
result = "Error in file ";
result += filename;
result += ",#";
result += lineNumberStr;
result.AppendInt(lineNumber);
result += " : ";
result += msg;
return result;
}
/**
@ -139,8 +118,9 @@ static nsCString BuildMessage(nsIException * exception)
inline
static void SetCOMError(nsIException * exception)
{
nsCString message = BuildMessage(exception);
Error(E_FAIL, message);
nsCString message;
BuildMessage(exception, message);
Error(E_FAIL, message.get());
}
XPCDispatchTearOff::XPCDispatchTearOff(nsIXPConnectWrappedJS * wrappedJS) :
@ -155,31 +135,8 @@ XPCDispatchTearOff::~XPCDispatchTearOff()
NS_IF_RELEASE(mCOMTypeInfo);
}
ULONG XPCDispatchTearOff::AddRef()
{
NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
nsrefcnt count;
count = PR_AtomicIncrement((PRInt32*)&mRefCnt);
NS_LOG_ADDREF(this, count, "XPCDispatchTearOff", sizeof(*this));
return count;
}
ULONG XPCDispatchTearOff::Release()
{
nsrefcnt count;
NS_PRECONDITION(0 != mRefCnt, "dup release");
count = PR_AtomicDecrement((PRInt32 *)&mRefCnt);
NS_LOG_RELEASE(this, count, "XPCDispatchTearOff");
if(0 == count)
{
mRefCnt = 1; /* stabilize */
/* enable this to find non-threadsafe destructors: */
/* NS_ASSERT_OWNINGTHREAD(XPCDispatchTearOff); */
NS_DELETEXPCOM(this);
return 0;
}
return count;
}
NS_COM_IMPL_ADDREF(XPCDispatchTearOff)
NS_COM_IMPL_RELEASE(XPCDispatchTearOff)
STDMETHODIMP XPCDispatchTearOff::InterfaceSupportsErrorInfo(REFIID riid)
{
@ -201,19 +158,19 @@ STDMETHODIMP XPCDispatchTearOff::QueryInterface(const struct _GUID & guid,
{
if(IsEqualIID(guid, IID_IDispatch))
{
*pPtr = NS_STATIC_CAST(IDispatch*, this);
NS_ADDREF(NS_REINTERPRET_CAST(IUnknown*, *pPtr));
*pPtr = NS_STATIC_CAST(IDispatch*,this);
NS_ADDREF_THIS();
return NS_OK;
}
if(IsEqualIID(guid, IID_ISupportErrorInfo))
{
*pPtr = NS_STATIC_CAST(ISupportErrorInfo*, this);
NS_ADDREF(NS_REINTERPRET_CAST(IUnknown*, *pPtr));
*pPtr = NS_STATIC_CAST(IDispatch*,this);
NS_ADDREF_THIS();
return NS_OK;
}
return mWrappedJS->QueryInterface(XPCDispGUID2nsIID(guid), pPtr);
return mWrappedJS->QueryInterface(XPCDispIID2nsIID(guid), pPtr);
}
STDMETHODIMP XPCDispatchTearOff::GetTypeInfoCount(unsigned int FAR * pctinfo)
@ -265,11 +222,11 @@ xpcWrappedJSErrorReporter(JSContext *cx, const char *message,
JSErrorReport *report);
STDMETHODIMP XPCDispatchTearOff::Invoke(DISPID dispIdMember, REFIID riid,
LCID lcid, WORD wFlags,
DISPPARAMS FAR* pDispParams,
VARIANT FAR* pVarResult,
EXCEPINFO FAR* pExcepInfo,
unsigned int FAR* puArgErr)
LCID lcid, WORD wFlags,
DISPPARAMS FAR* pDispParams,
VARIANT FAR* pVarResult,
EXCEPINFO FAR* pExcepInfo,
unsigned int FAR* puArgErr)
{
XPCDispTypeInfo* pTypeInfo = GetCOMTypeInfo();
if(!pTypeInfo)
@ -290,8 +247,9 @@ STDMETHODIMP XPCDispatchTearOff::Invoke(DISPID dispIdMember, REFIID riid,
cx = nsnull;
}
// Get the name as a flat string
const nsACString & xname = pTypeInfo->GetNameForDispID(dispIdMember);
const nsPromiseFlatCString & name = PromiseFlatCString(xname);
// This isn't that efficient, but we have to make the conversion somewhere
const nsAString & xname = pTypeInfo->GetNameForDispID(dispIdMember);
const nsPromiseFlatCString & name = PromiseFlatCString(NS_LossyConvertUCS2toASCII(xname));
if(name.IsEmpty())
return E_FAIL;
// Decide if this is a getter or setter
@ -309,17 +267,17 @@ STDMETHODIMP XPCDispatchTearOff::Invoke(DISPID dispIdMember, REFIID riid,
obj = GetJSObject();
if(!obj)
return E_FAIL;
if (!JS_GetProperty(cx, obj, name.get(), &val))
if(!JS_GetProperty(cx, obj, name.get(), &val))
{
nsCString msg("Unable to retrieve property ");
msg += xname;
return Error(E_FAIL, msg);
msg += name;
return Error(E_FAIL, msg.get());
}
if(!XPCDispConvert::JSToCOM(ccx, val, *pVarResult, err))
{
nsCString msg("Failed to convert value from JS property ");
msg += xname;
return Error(E_FAIL, msg);
msg += name;
return Error(E_FAIL, msg.get());
}
}
else if(pDispParams->cArgs > 0)
@ -328,17 +286,17 @@ STDMETHODIMP XPCDispatchTearOff::Invoke(DISPID dispIdMember, REFIID riid,
if(!XPCDispConvert::COMToJS(ccx, pDispParams->rgvarg[0], val, err))
{
nsCString msg("Failed to convert value for JS property ");
msg += xname;
return Error(E_FAIL, msg);
msg += name;
return Error(E_FAIL, msg.get());
}
obj = GetJSObject();
if(!obj)
return Error(E_FAIL, "The JS wrapper did not return a JS object");
if (!JS_SetProperty(cx, obj, name.get(), &val))
if(!JS_SetProperty(cx, obj, name.get(), &val))
{
nsCString msg("Unable to set property ");
msg += xname;
return Error(E_FAIL, msg);
msg += name;
return Error(E_FAIL, msg.get());
}
}
}
@ -347,7 +305,7 @@ STDMETHODIMP XPCDispatchTearOff::Invoke(DISPID dispIdMember, REFIID riid,
jsval* stackbase;
jsval* sp = nsnull;
uint8 i;
uint8 argc=pDispParams->cArgs;
uint8 argc = pDispParams->cArgs;
uint8 stack_size;
jsval result;
uint8 paramCount=0;
@ -485,7 +443,7 @@ pre_call_clean_up:
fp = oldfp = cx->fp;
if(!fp)
{
memset(&frame, 0, sizeof frame);
memset(&frame, 0, sizeof(frame));
cx->fp = fp = &frame;
}
oldsp = fp->sp;
@ -545,7 +503,7 @@ pre_call_clean_up:
}
JS_ClearPendingException(cx);
}
// TODO: This exception logic needs to be refactored and shared with wrapped JS
if(xpc_exception)
{
nsresult e_result;

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

@ -49,6 +49,9 @@
#include "xpcprivate.h"
// There's no CPP for XPCDispNameArray so it's just plopped here
const nsString XPCDispNameArray::sEmpty;
/**
* Helper function that initializes the element description
* @param vt The type of variant
@ -96,7 +99,7 @@ ELEMDESC* XPCDispJSPropertyInfo::GetParamInfo()
if(paramCount != 0)
{
elemDesc = new ELEMDESC[paramCount];
if (elemDesc)
if(elemDesc)
{
for(PRUint32 index = 0; index < paramCount; ++index)
{
@ -114,20 +117,21 @@ XPCDispJSPropertyInfo::XPCDispJSPropertyInfo(JSContext* cx, PRUint32 memid,
JSObject* obj, jsval val) :
mPropertyType(INVALID), mMemID(memid)
{
const char* chars = xpc_JSString2Char(cx, val);
PRUint32 len;
jschar * chars = xpc_JSString2String(cx, val, &len);
if(!chars)
return;
mName = chars;
mName = nsString(chars, len);
JSBool found;
uintN attr;
// Get the property's attributes, and make sure it's found and enumerable
if(!JS_GetPropertyAttributes(cx, obj, chars, &attr, &found) ||
if(!JS_GetUCPropertyAttributes(cx, obj, chars, len, &attr, &found) ||
!found || (attr & JSPROP_ENUMERATE) == 0)
return;
// Retrieve the property
if(!chars || !JS_GetProperty(cx, obj, chars, &mProperty) ||
if(!chars || !JS_GetUCProperty(cx, obj, chars, len, &mProperty) ||
JSVAL_IS_NULL(mProperty))
return;
@ -160,6 +164,7 @@ XPCDispJSPropertyInfo::XPCDispJSPropertyInfo(JSContext* cx, PRUint32 memid,
PRBool XPCDispTypeInfo::FuncDescArray::BuildFuncDesc(XPCCallContext& ccx, JSObject* obj,
XPCDispJSPropertyInfo & propInfo)
{
// While this memory is passed out, we're ultimately responsible to free it
FUNCDESC* funcDesc = new FUNCDESC;
if(!funcDesc)
return PR_FALSE;
@ -226,10 +231,6 @@ XPCDispTypeInfo::XPCDispTypeInfo(XPCCallContext& ccx, JSObject* obj,
XPCDispTypeInfo * XPCDispTypeInfo::New(XPCCallContext& ccx, JSObject* obj)
{
nsresult retval = NS_ERROR_FAILURE;
// Saved state must be restored
JSExceptionState* saved_exception = xpc_DoPreScriptEvaluated(ccx);
JSErrorReporter older = JS_SetErrorReporter(ccx, nsnull);
XPCDispTypeInfo * pTypeInfo = 0;
JSIdArray * jsArray = JS_Enumerate(ccx, obj);
if(!jsArray)
@ -243,15 +244,13 @@ XPCDispTypeInfo * XPCDispTypeInfo::New(XPCCallContext& ccx, JSObject* obj)
delete array;
return nsnull;
}
JS_SetErrorReporter(ccx, older);
xpc_DoPostScriptEvaluated(ccx, saved_exception);
NS_ADDREF(pTypeInfo);
return pTypeInfo;
}
NS_COM_MAP_BEGIN(XPCDispTypeInfo)
NS_COM_MAP_ENTRY(ITypeInfo)
NS_COM_MAP_ENTRY(IUnknown)
NS_COM_MAP_ENTRY(ITypeInfo)
NS_COM_MAP_ENTRY(IUnknown)
NS_COM_MAP_END
NS_IMPL_THREADSAFE_ADDREF(XPCDispTypeInfo)
@ -312,14 +311,12 @@ STDMETHODIMP XPCDispTypeInfo::GetIDsOfNames(
/* [in] */ UINT cNames,
/* [size_is][out] */ MEMBERID __RPC_FAR *pMemId)
{
_bstr_t name;
// lookup each name
for(UINT index = 0; index < cNames; ++index)
{
// This can probably be streamlined, I wasn't sure if
// we could go safely from LPOLESTR to nsDependentString
name = rgszNames[index];
nsDependentCString buffer(NS_STATIC_CAST(const char *,name));
nsDependentString buffer(NS_STATIC_CAST(const PRUnichar *,
rgszNames[index]),
SysStringLen(rgszNames[index]));
pMemId[index] = mNameArray.Find(buffer);
}
@ -335,16 +332,13 @@ STDMETHODIMP XPCDispTypeInfo::Invoke(
/* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
/* [out] */ UINT __RPC_FAR *puArgErr)
{
IUnknown* ptr = NS_REINTERPRET_CAST(IUnknown*,pvInstance);
IDispatch* pDisp;
HRESULT result = ptr->QueryInterface(IID_IDispatch,
NS_REINTERPRET_CAST(void**,&pDisp));
if(SUCCEEDED(result))
CComQIPtr<IDispatch> pDisp(NS_REINTERPRET_CAST(IUnknown*,pvInstance));
if(pDisp)
{
result = pDisp->Invoke(memid, IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags,
return pDisp->Invoke(memid, IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags,
pDispParams, pVarResult, pExcepInfo, puArgErr);
}
return result;
return E_NOINTERFACE;
}
STDMETHODIMP XPCDispTypeInfo::GetDocumentation(

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

@ -41,39 +41,45 @@ static const char* const IDISPATCH_NAME = "IDispatch";
PRBool XPCIDispatchExtension::mIsEnabled = PR_TRUE;
static JSBool
CommonConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval, PRBool testScriptability)
CommonConstructor(XPCCallContext &ccx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval, PRBool testScriptability)
{
// Check if IDispatch is enabled, fail if not
if (!nsXPConnect::IsIDispatchEnabled())
{
XPCThrower::Throw(NS_ERROR_XPC_IDISPATCH_NOT_ENABLED, ccx);
return JS_FALSE;
}
// Make sure we were called with one string parameter
if(argc != 1 || (argc == 1 && !JSVAL_IS_STRING(argv[0])))
{
XPCThrower::Throw(NS_ERROR_XPC_COM_INVALID_CLASS_ID, cx);
XPCThrower::Throw(NS_ERROR_XPC_COM_INVALID_CLASS_ID, ccx);
return JS_FALSE;
}
const char * bytes = xpc_JSString2Char(cx, argv[0]);
if(!bytes)
PRUint32 len;
jschar * className = xpc_JSString2String(ccx, argv[0], &len);
CComBSTR bstrClassName(len, className);
if(!className)
{
XPCThrower::Throw(NS_ERROR_XPC_COM_INVALID_CLASS_ID, cx);
XPCThrower::Throw(NS_ERROR_XPC_COM_INVALID_CLASS_ID, ccx);
return JS_FALSE;
}
// Instantiate the desired COM object
IDispatch* pDispatch = nsnull;;
HRESULT rv = XPCDispObject::COMCreateInstance(bytes, testScriptability, &pDispatch);
CComPtr<IDispatch> pDispatch;
HRESULT rv = XPCDispObject::COMCreateInstance(bstrClassName, testScriptability, &pDispatch);
if(FAILED(rv))
{
XPCThrower::ThrowCOMError(cx, rv, NS_ERROR_XPC_COM_CREATE_FAILED);
XPCThrower::ThrowCOMError(ccx, rv, NS_ERROR_XPC_COM_CREATE_FAILED);
return JS_FALSE;
}
// Get a wrapper for our object
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult nsrv = nsXPConnect::GetXPConnect()->WrapNative(cx, obj,
NS_REINTERPRET_CAST(nsISupports*, pDispatch),
NSID_IDISPATCH, getter_AddRefs(holder));
nsresult nsrv = ccx.GetXPConnect()->WrapNative(
ccx, obj, NS_REINTERPRET_CAST(nsISupports*, pDispatch.p), NSID_IDISPATCH,
getter_AddRefs(holder));
if(NS_FAILED(nsrv))
{
XPCThrower::Throw(nsrv, cx);
XPCThrower::Throw(nsrv, ccx);
return JS_FALSE;
}
// get and return the JS object wrapper
@ -81,7 +87,7 @@ CommonConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
nsrv = holder->GetJSObject(&jsobj);
if(NS_FAILED(nsrv))
{
XPCThrower::Throw(nsrv, cx);
XPCThrower::Throw(nsrv, ccx);
return JS_FALSE;
}
*rval = OBJECT_TO_JSVAL(jsobj);
@ -92,20 +98,21 @@ JS_STATIC_DLL_CALLBACK(JSBool)
COMObjectConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
return CommonConstructor(cx, obj, argc, argv, rval, PR_FALSE);
XPCCallContext ccx(JS_CALLER, cx, obj);
return CommonConstructor(ccx, obj, argc, argv, rval, PR_FALSE);
}
JS_STATIC_DLL_CALLBACK(JSBool)
ActiveXConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
jsval *rval)
{
return CommonConstructor(cx, obj, argc, argv, rval, PR_TRUE);
XPCCallContext ccx(JS_CALLER, cx, obj);
return CommonConstructor(ccx, obj, argc, argv, rval, PR_TRUE);
}
JSBool XPCIDispatchExtension::Initialize(JSContext * aJSContext,
JSObject * aGlobalJSObj)
JSObject * aGlobalJSObj)
{
// TODO: Cleanup error code
JSBool result = JS_DefineFunction(aJSContext, aGlobalJSObj, "ActiveXObject",
ActiveXConstructor, 1, 0) != nsnull;
#ifdef XPC_COMOBJECT
@ -121,6 +128,8 @@ JSBool XPCIDispatchExtension::DefineProperty(XPCCallContext & ccx,
XPCWrappedNative* wrapperToReflectInterfaceNames,
uintN propFlags, JSBool* resolved)
{
if(!JSVAL_IS_STRING(idval))
return JS_FALSE;
// Look up the native interface for IDispatch and then find a tearoff
XPCNativeInterface* iface = XPCNativeInterface::GetNewOrUsed(ccx,
"IDispatch");
@ -135,8 +144,6 @@ JSBool XPCIDispatchExtension::DefineProperty(XPCCallContext & ccx,
if(jso == nsnull)
return JS_FALSE;
// Look up the member in the interface
if(!JSVAL_IS_STRING(idval))
return JS_FALSE;
const XPCDispInterface::Member * member = to->GetIDispatchInfo()->FindMember(idval);
if(!member)
{
@ -152,6 +159,9 @@ JSBool XPCIDispatchExtension::DefineProperty(XPCCallContext & ccx,
jsval funval;
if(!member->GetValue(ccx, iface, &funval))
return JS_FALSE;
// Protect the jsval
AUTO_MARK_JSVAL(ccx, funval);
// clone a function we can use for this object
JSObject* funobj = JS_CloneFunctionObject(ccx, JSVAL_TO_OBJECT(funval), obj);
if(!funobj)
return JS_FALSE;
@ -222,6 +232,11 @@ nsresult XPCIDispatchExtension::IDispatchQIWrappedJS(nsXPCWrappedJS * self,
*aInstancePtr = nsnull;
return NS_NOINTERFACE;
}
*aInstancePtr = NS_STATIC_CAST(XPCDispatchTearOff*, new XPCDispatchTearOff(root));
XPCDispatchTearOff* tearOff = new XPCDispatchTearOff(root);
if(!tearOff)
return NS_ERROR_OUT_OF_MEMORY;
tearOff->AddRef();
*aInstancePtr = tearOff;
return NS_OK;
}

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

@ -96,11 +96,15 @@ NS_IMETHODIMP nsDispatchSupport::JSVal2COMVariant(jsval val, VARIANT * comvar)
* @param result pointer to an IDispatch to receive the pointer to the instance
* @return nsresult
*/
NS_IMETHODIMP nsDispatchSupport::CreateInstance(const char * className,
NS_IMETHODIMP nsDispatchSupport::CreateInstance(const nsAString & className,
PRBool testScriptability,
IDispatch ** result)
{
return XPCDispObject::COMCreateInstance(className, testScriptability, result);
if (!nsXPConnect::IsIDispatchEnabled())
return NS_ERROR_XPC_IDISPATCH_NOT_ENABLED;
const nsPromiseFlatString & flat = PromiseFlatString(className);
CComBSTR name(flat.Length(), flat.get());
return XPCDispObject::COMCreateInstance(name, testScriptability, result);
}
nsDispatchSupport* nsDispatchSupport::GetSingleton()

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

@ -162,4 +162,5 @@ XPC_MSG_DEF(NS_ERROR_XPC_COM_UNKNOWN , "Unknown COM error occured
XPC_MSG_DEF(NS_ERROR_XPC_COM_ERROR , "COM Error")
XPC_MSG_DEF(NS_ERROR_XPC_COM_INVALID_CLASS_ID , "Invalid class ID")
XPC_MSG_DEF(NS_ERROR_XPC_COM_CREATE_FAILED , "Unable to create an instance of the desired COM class")
XPC_MSG_DEF(NS_ERROR_XPC_IDISPATCH_NOT_ENABLED , "IDispatch support is not enabled")
#endif

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

@ -1069,6 +1069,47 @@ XPCConvert::NativeInterface2JSObject(XPCCallContext& ccx,
return JS_FALSE;
}
/***************************************************************************/
// static
JSBool XPCConvert::GetNativeInterfaceFromJSObject(XPCCallContext& ccx,
void** dest, JSObject* src,
const nsID* iid,
nsresult* pErr)
{
nsISupports* identity;
// Note that if we have a non-null aOuter then it means that we are
// forcing the creation of a wrapper even if the object *is* a
// wrappedNative or other wise has 'nsISupportness'.
// This allows wrapJSAggregatedToNative to work.
// Is this really a native xpcom object with a wrapper?
XPCWrappedNative* wrappedNative =
XPCWrappedNative::GetWrappedNativeOfJSObject(ccx, src);
if(wrappedNative)
{
identity = wrappedNative->GetIdentityObject();
// is the underlying object the right interface?
if(wrappedNative->GetIID().Equals(*iid))
{
NS_ADDREF(identity);
*dest = identity;
return JS_TRUE;
}
else
return NS_SUCCEEDED(identity->QueryInterface(*iid, dest));
}
// else...
// Does the JSObject have 'nsISupportness'?
// XXX hmm, I wonder if this matters anymore with no
// oldstyle DOM objects around.
if(GetISupportsFromJSObject(ccx, src, &identity) && identity)
{
return NS_SUCCEEDED(identity->QueryInterface(*iid, dest));
}
return JS_FALSE;
}
/***************************************************************************/
// static
@ -1089,46 +1130,14 @@ XPCConvert::JSObject2NativeInterface(XPCCallContext& ccx,
if(pErr)
*pErr = NS_ERROR_XPC_BAD_CONVERT_JS;
nsISupports* iface;
if(!aOuter)
{
// Note that if we have a non-null aOuter then it means that we are
// forcing the creation of a wrapper even if the object *is* a
// wrappedNative or other wise has 'nsISupportness'.
// This allows wrapJSAggregatedToNative to work.
// Is this really a native xpcom object with a wrapper?
XPCWrappedNative* wrappedNative =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, src);
if(wrappedNative)
{
iface = wrappedNative->GetIdentityObject();
// is the underlying object the right interface?
if(wrappedNative->GetIID().Equals(*iid))
{
NS_ADDREF(iface);
*dest = iface;
return JS_TRUE;
}
else
return NS_SUCCEEDED(iface->QueryInterface(*iid, dest));
}
// else...
// Does the JSObject have 'nsISupportness'?
// XXX hmm, I wonder if this matters anymore with no
// oldstyle DOM objects around.
if(GetISupportsFromJSObject(cx, src, &iface))
{
if(iface)
return NS_SUCCEEDED(iface->QueryInterface(*iid, dest));
return JS_FALSE;
}
// See if this is really an wrapped XPCOM object
if(GetNativeInterfaceFromJSObject(ccx, dest, src, iid, pErr))
return JS_TRUE;
}
// else...
// else create a new wrapper
nsXPCWrappedJS* wrapper;
nsresult rv = nsXPCWrappedJS::GetNewOrUsed(ccx, src, *iid, aOuter, &wrapper);

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

@ -96,6 +96,7 @@ struct IDispatch;
class XPCDispParams;
class XPCDispJSPropertyInfo;
class nsIXPConnectWrappedJS;
class XPCIDispatchExtension;
#endif

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

@ -566,10 +566,13 @@ inline
JSObject* XPCWrappedNativeTearOff::GetJSObject() const
{
#ifdef XPC_IDISPATCH_SUPPORT
return IsIDispatch() ? GetIDispatchInfo()->GetJSObject() : mJSObject;
#else
return mJSObject;
if(IsIDispatch())
{
XPCDispInterface * iface = GetIDispatchInfo();
return iface ? iface->GetJSObject() : nsnull;
}
#endif
return mJSObject;
}
inline
@ -577,7 +580,11 @@ void XPCWrappedNativeTearOff::SetJSObject(JSObject* JSObj)
{
#ifdef XPC_IDISPATCH_SUPPORT
if(IsIDispatch())
GetIDispatchInfo()->SetJSObject(JSObj);
{
XPCDispInterface* iface = GetIDispatchInfo();
if (iface)
iface->SetJSObject(JSObj);
}
else
#endif
mJSObject = JSObj;
@ -595,6 +602,8 @@ XPCWrappedNativeTearOff::SetIDispatch(JSContext* cx)
inline XPCDispInterface*
XPCWrappedNativeTearOff::GetIDispatchInfo() const
{
NS_ASSERTION((jsword)mJSObject & 2, "XPCWrappedNativeTearOff::GetIDispatchInfo "
"called on a non IDispatch interface");
return NS_REINTERPRET_CAST(XPCDispInterface*,
(((jsword)mJSObject) & ~JSOBJECT_MASK));
}

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

@ -86,13 +86,13 @@ static const nsModuleComponentInfo components[] = {
// jsloader stuff
{ "JS component loader", MOZJSCOMPONENTLOADER_CID,
mozJSComponentLoaderContractID, mozJSComponentLoaderConstructor,
RegisterJSLoader, UnregisterJSLoader },
RegisterJSLoader, UnregisterJSLoader }
#ifndef NO_SUBSCRIPT_LOADER
{ "JS subscript loader", MOZ_JSSUBSCRIPTLOADER_CID,
mozJSSubScriptLoadContractID, mozJSSubScriptLoaderConstructor },
,{ "JS subscript loader", MOZ_JSSUBSCRIPTLOADER_CID,
mozJSSubScriptLoadContractID, mozJSSubScriptLoaderConstructor }
#endif
#ifdef XPC_IDISPATCH_SUPPORT
{ nsnull, NS_IDISPATCH_SUPPORT_CID, NS_IDISPATCH_SUPPORT_CONTRACTID,
,{ nsnull, NS_IDISPATCH_SUPPORT_CID, NS_IDISPATCH_SUPPORT_CONTRACTID,
nsIDispatchSupportConstructor }
#endif
};

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

@ -114,19 +114,13 @@
#endif
#ifdef XPC_IDISPATCH_SUPPORT
// This goop was added because of EXCEPINFO in ThrowCOMError
// This include is here, because it needs to occur before the undefines below
#include <atlbase.h>
#include <comdef.h>
extern CComModule _Module;
#include <atlcom.h>
#include <atlctl.h>
// MS clutters the global namespace with so many macro names :-(
// I tried to keep these includes in the CPP's but it became too
// convoluted
#include "oaidl.h"
// Nasty MS defines
#undef GetClassInfo
#undef GetClassName
#undef interface
#undef GetMessage
#endif
@ -381,10 +375,6 @@ private:
static void operator delete(void* /*memory*/) {}
};
#ifdef XPC_IDISPATCH_SUPPORT
class XPCIDispatchExtension;
#endif
/***************************************************************************
****************************************************************************
*
@ -1704,7 +1694,6 @@ public:
JSOBJECT_MASK = 3
};
void SetIDispatch(JSContext* cx);
JSObject* Get() const;
JSBool IsIDispatch() const;
XPCDispInterface* GetIDispatchInfo() const;
#endif
@ -2265,13 +2254,10 @@ public:
const nsID* iid,
JSObject* scope, nsresult* pErr);
#ifdef XPC_IDISPATCH_SUPPORT
static JSBool NativeInterface2JSObject(XPCCallContext& ccx,
nsIXPConnectJSObjectHolder** dest,
IDispatch* src,
JSObject* scope, nsresult* pErr);
#endif
static JSBool GetNativeInterfaceFromJSObject(XPCCallContext& ccx,
void** dest, JSObject* src,
const nsID* iid,
nsresult* pErr);
static JSBool JSObject2NativeInterface(XPCCallContext& ccx,
void** dest, JSObject* src,
const nsID* iid,
@ -2462,7 +2448,9 @@ public:
static void ThrowBadResult(nsresult rv, nsresult result, XPCCallContext& ccx);
static void ThrowBadParam(nsresult rv, uintN paramNum, XPCCallContext& ccx);
#ifdef XPC_IDISPATCH_SUPPORT
static void ThrowCOMError(JSContext* cx, HRESULT COMErrorCode, nsresult rv = NS_ERROR_XPC_COM_ERROR);
static void ThrowCOMError(JSContext* cx, unsigned long COMErrorCode,
nsresult rv = NS_ERROR_XPC_COM_ERROR,
const EXCEPINFO * exception = nsnull);
#endif
static JSBool SetVerbosity(JSBool state)
{JSBool old = sVerbose; sVerbose = state; return old;}
@ -3115,12 +3103,14 @@ class XPCMarkableJSVal
public:
XPCMarkableJSVal(jsval val) : mVal(val), mValPtr(&mVal) {}
XPCMarkableJSVal(jsval *pval) : mVal(0), mValPtr(pval) {}
~XPCMarkableJSVal() {}
void Mark() {}
void MarkBeforeJSFinalize(JSContext* cx)
{if(JSVAL_IS_GCTHING(*mValPtr))
JS_MarkGCThing(cx, JSVAL_TO_GCTHING(*mValPtr),
"XPCMarkableJSVal", nsnull);}
private:
XPCMarkableJSVal(); // not implemented
jsval mVal;
jsval* mValPtr;
};

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

@ -155,11 +155,37 @@ XPCThrower::Verbosify(XPCCallContext& ccx,
if(ccx.HasInterfaceAndMember())
{
XPCNativeInterface* interface = ccx.GetInterface();
XPCNativeInterface* iface = ccx.GetInterface();
#ifdef XPC_IDISPATCH_SUPPORT
NS_ASSERTION(ccx.GetIDispatchMember() == nsnull ||
ccx.GetMember() == nsnull,
"Both IDispatch member and regular XPCOM member "
"were set in XPCCallContext");
char const * name;
if(ccx.GetIDispatchMember())
{
XPCDispInterface::Member * member =
NS_REINTERPRET_CAST(XPCDispInterface::Member*,
ccx.GetIDispatchMember());
if(member && JSVAL_IS_STRING(member->GetName()))
{
name = JS_GetStringBytes(JSVAL_TO_STRING(member->GetName()));
}
else
name = "Unknown";
}
else
name = iface->GetMemberName(ccx, ccx.GetMember());
sz = JS_smprintf("%s [%s.%s]",
*psz,
interface->GetNameString(),
interface->GetMemberName(ccx, ccx.GetMember()));
iface->GetNameString(),
name);
#else
sz = JS_smprintf("%s [%s.%s]",
*psz,
iface->GetNameString(),
iface->GetMemberName(ccx, ccx.GetMember()));
#endif
}
if(sz)
@ -246,47 +272,57 @@ XPCThrower::ThrowExceptionObject(JSContext* cx, nsIException* e)
#ifdef XPC_IDISPATCH_SUPPORT
// static
void
XPCThrower::ThrowCOMError(JSContext* cx, HRESULT COMErrorCode, nsresult rv)
XPCThrower::ThrowCOMError(JSContext* cx, unsigned long COMErrorCode,
nsresult rv, const EXCEPINFO * exception)
{
nsCAutoString msg;
IErrorInfo * pError;
// Get the current COM error object
HRESULT result = GetErrorInfo(0, &pError);
if(SUCCEEDED(result) && pError)
{
// Build an error message from the COM error object
BSTR bstrDesc = nsnull;
BSTR bstrSource = nsnull;
if(SUCCEEDED(pError->GetSource(&bstrSource)) && bstrSource)
{
msg = NS_STATIC_CAST(const char *,_bstr_t(bstrSource, FALSE));
msg += " : ";
}
char buffer[9];
sprintf(buffer, "%0X", COMErrorCode);
msg += buffer;
if(SUCCEEDED(pError->GetDescription(&bstrDesc)) && bstrDesc)
{
msg += " - ";
msg += NS_STATIC_CAST(const char *,_bstr_t(bstrDesc, FALSE));
}
}
else
{
// No error object, so just report the result
const char* format;
if(!nsXPCException::NameAndFormatForNSResult(rv, nsnull, &format))
format = "";
char buffer[48];
sprintf(buffer, "COM Error Result = %0X", COMErrorCode);
msg = buffer;
}
const char * format;
if(!nsXPCException::NameAndFormatForNSResult(rv, nsnull, &format))
format = "";
char * finalMsg = JS_smprintf("%s - %s", format, PromiseFlatCString(msg).get());
XPCThrower::BuildAndThrowException(cx, rv, finalMsg);
JS_smprintf_free(finalMsg);
msg = format;
if(exception)
{
msg += NS_STATIC_CAST(const char *,
_bstr_t(exception->bstrSource, false));
msg += " : ";
msg.AppendInt(COMErrorCode);
msg += " - ";
msg += NS_STATIC_CAST(const char *,
_bstr_t(exception->bstrDescription, false));
}
else
{
// Get the current COM error object
unsigned long result = GetErrorInfo(0, &pError);
if(SUCCEEDED(result) && pError)
{
// Build an error message from the COM error object
BSTR bstrSource = NULL;
if(SUCCEEDED(pError->GetSource(&bstrSource)) && bstrSource)
{
_bstr_t src(bstrSource, false);
msg += NS_STATIC_CAST(const char *,src);
msg += " : ";
}
msg.AppendInt(COMErrorCode, 16);
BSTR bstrDesc = NULL;
if(SUCCEEDED(pError->GetDescription(&bstrDesc)) && bstrDesc)
{
msg += " - ";
_bstr_t desc(bstrDesc, false);
msg += NS_STATIC_CAST(const char *,desc);
}
}
else
{
// No error object, so just report the result
msg += "COM Error Result = ";
msg.AppendInt(COMErrorCode, 16);
}
}
XPCThrower::BuildAndThrowException(cx, rv, msg.get());
}
#endif

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

@ -216,7 +216,7 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
// in a pointer that hasn't been QI'd to IDispatch properly this could
// create multiple wrappers for the same object, creating a fair bit of
// confusion.
if(nsXPConnect::IsIDispatchEnabled() && Interface->GetIID()->Equals(NSID_IDISPATCH))
if(Interface->GetIID()->Equals(NSID_IDISPATCH))
identity = Object;
else
#endif
@ -435,7 +435,7 @@ XPCWrappedNative::GetUsedOnly(XPCCallContext& ccx,
nsCOMPtr<nsISupports> identity;
#ifdef XPC_IDISPATCH_SUPPORT
// XXX See GetNewOrUsed for more info on this
if(!nsXPConnect::IsIDispatchEnabled() && Interface->GetIID()->Equals(NSID_IDISPATCH))
if(Interface->GetIID()->Equals(NSID_IDISPATCH))
identity = Object;
else
#endif
@ -1443,7 +1443,7 @@ XPCWrappedNative::InitTearOff(XPCCallContext& ccx,
aTearOff->SetNative(obj);
#ifdef XPC_IDISPATCH_SUPPORT
// Are we building a tearoff for IDispatch?
if(ccx.GetXPConnect()->IsIDispatchEnabled() && iid->Equals(NSID_IDISPATCH))
if(iid->Equals(NSID_IDISPATCH))
{
aTearOff->SetIDispatch(ccx);
}
@ -2477,7 +2477,7 @@ XPCWrappedNative::HandlePossibleNameCaseError(XPCCallContext& ccx,
PRUnichar* oldStr;
PRUnichar* newStr;
XPCNativeMember* member;
XPCNativeInterface* interface;
XPCNativeInterface* localIface;
/* PRUnichar->char->PRUnichar hack is to avoid pulling in i18n code. */
if(JSVAL_IS_STRING(name) &&
@ -2492,11 +2492,11 @@ XPCWrappedNative::HandlePossibleNameCaseError(XPCCallContext& ccx,
newJSStr = JS_NewUCStringCopyZ(ccx, (const jschar*)newStr);
nsCRT::free(newStr);
if(newJSStr && (set ?
set->FindMember(STRING_TO_JSVAL(newJSStr), &member, &interface) :
set->FindMember(STRING_TO_JSVAL(newJSStr), &member, &localIface) :
(JSBool)NS_PTR_TO_INT32(iface->FindMember(STRING_TO_JSVAL(newJSStr)))))
{
// found it!
const char* ifaceName = interface->GetNameString();
const char* ifaceName = localIface->GetNameString();
const char* goodName = JS_GetStringBytes(newJSStr);
const char* badName = JS_GetStringBytes(oldJSStr);
char* locationStr = nsnull;

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

@ -376,7 +376,6 @@ DefinePropertyIfFound(XPCCallContext& ccx,
#ifdef XPC_IDISPATCH_SUPPORT
// Check to see if there's an IDispatch tearoff
if(wrapperToReflectInterfaceNames &&
nsXPConnect::IsIDispatchEnabled() &&
XPCIDispatchExtension::DefineProperty(ccx, obj,
idval, wrapperToReflectInterfaceNames, propFlags, resolved))
return JS_TRUE;
@ -604,19 +603,18 @@ XPC_WN_Shared_Enumerate(JSContext *cx, JSObject *obj)
XPCNativeInterface** interfaceArray = set->GetInterfaceArray();
for(PRUint16 i = 0; i < interface_count; i++)
{
XPCNativeInterface* interface = interfaceArray[i];
XPCNativeInterface* iface = interfaceArray[i];
#ifdef XPC_IDISPATCH_SUPPORT
if (nsXPConnect::GetXPConnect()->IsIDispatchEnabled() &&
interface->GetIID()->Equals(NSID_IDISPATCH))
if(iface->GetIID()->Equals(NSID_IDISPATCH))
{
XPCIDispatchExtension::Enumerate(ccx, obj, wrapper);
continue;
}
#endif
PRUint16 member_count = interface->GetMemberCount();
PRUint16 member_count = iface->GetMemberCount();
for(PRUint16 k = 0; k < member_count; k++)
{
XPCNativeMember* member = interface->GetMemberAt(k);
XPCNativeMember* member = iface->GetMemberAt(k);
jsval name = member->GetName();
// Skip if this member is going to come from the proto.