mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-28 11:28:38 +00:00
using JS exception thrower (with tests)
This commit is contained in:
parent
27844bd641
commit
6c79271828
@ -207,7 +207,7 @@ if(all_ok)
|
||||
print("SendInOutManyTypes - passed");
|
||||
|
||||
////////////////////
|
||||
// ReturnCode
|
||||
// check exceptions on xpcom error code
|
||||
|
||||
try {
|
||||
echo.ReturnCode(0);
|
||||
@ -222,9 +222,36 @@ try {
|
||||
print("ReturnCode(-1) - failed");
|
||||
}
|
||||
catch(e) {
|
||||
print("ReturnCode(-1) exception text: "+e+" - passed");
|
||||
// print("ReturnCode(-1) exception text: "+e+" - passed");
|
||||
print("ReturnCode(-1) - passed");
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// check exceptions on too few args
|
||||
|
||||
try {
|
||||
echo.ReturnCode(); // supposed to have one arg
|
||||
print("Too few args test - failed");
|
||||
}
|
||||
catch(e) {
|
||||
// print("Too few args test -- exception text: "+e+" - passed");
|
||||
print("Too few args test - passed");
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// check exceptions on can't convert
|
||||
|
||||
try {
|
||||
echo.SetReciever(null);
|
||||
// print("Can't convert arg to Native ("+out+")- failed");
|
||||
print("Can't convert arg to Native - failed");
|
||||
}
|
||||
catch(e) {
|
||||
// print("Can't convert arg to Native ("+e+") - passed");
|
||||
print("Can't convert arg to Native - passed");
|
||||
}
|
||||
|
||||
|
||||
print(".......................................");
|
||||
print("simple speed tests...");
|
||||
|
||||
|
@ -33,3 +33,9 @@ MSG_DEF(NOT_ENOUGH_ARGS, 1, 0, 0, "Not enough arguments")
|
||||
MSG_DEF(NEED_OUT_OBJECT, 2, 0, 0, "'Out' argument must be an object")
|
||||
MSG_DEF(CANT_SET_OUT_VAL, 3, 0, 0, "Can not set 'value' property of 'out' argument")
|
||||
MSG_DEF(NATIVE_RETURNED_FAILURE, 4, 0, 0, "Component returned failure code:")
|
||||
MSG_DEF(CANT_GET_INTERFACE_INFO, 5, 0, 0, "Can not find interface information")
|
||||
MSG_DEF(CANT_GET_PARAM_IFACE_INFO,6, 0, 0, "Can not find interface information for parameter")
|
||||
MSG_DEF(CANT_GET_METHOD_INFO, 7, 0, 0, "Can not find method information")
|
||||
MSG_DEF(UNEXPECTED, 8, 0, 0, "Unexpected error in XPConnect")
|
||||
MSG_DEF(BAD_CONVERT_JS, 9, 0, 0, "Could not convert JavaScript argument")
|
||||
MSG_DEF(BAD_CONVERT_NATIVE, 10, 0, 0, "Could not convert Native argument")
|
||||
|
@ -176,13 +176,17 @@ XPCConvert::IsMethodReflectable(const nsXPTMethodInfo& info)
|
||||
// static
|
||||
JSBool
|
||||
XPCConvert::NativeData2JS(JSContext* cx, jsval* d, const void* s,
|
||||
const nsXPTType& type, const nsID* iid)
|
||||
const nsXPTType& type, const nsID* iid,
|
||||
uintN* pErr)
|
||||
{
|
||||
NS_PRECONDITION(s, "bad param");
|
||||
NS_PRECONDITION(d, "bad param");
|
||||
|
||||
jsdouble* dbl;
|
||||
|
||||
if(pErr)
|
||||
*pErr = XPCJSError::BAD_CONVERT_NATIVE;
|
||||
|
||||
switch(type.TagPart())
|
||||
{
|
||||
case nsXPTType::T_I8 : *d = INT_TO_JSVAL((int32)*((int8*)s)); break;
|
||||
@ -327,7 +331,8 @@ XPCConvert::NativeData2JS(JSContext* cx, jsval* d, const void* s,
|
||||
JSBool
|
||||
XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
|
||||
const nsXPTType& type,
|
||||
nsIAllocator* al, const nsID* iid)
|
||||
nsIAllocator* al, const nsID* iid,
|
||||
uintN* pErr)
|
||||
{
|
||||
NS_PRECONDITION(d, "bad param");
|
||||
|
||||
@ -336,64 +341,80 @@ XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
|
||||
jsdouble td;
|
||||
JSBool r;
|
||||
|
||||
if(pErr)
|
||||
*pErr = XPCJSError::BAD_CONVERT_JS;
|
||||
|
||||
switch(type.TagPart())
|
||||
{
|
||||
case nsXPTType::T_I8 :
|
||||
r = JS_ValueToECMAInt32(cx, s, &ti);
|
||||
if(!JS_ValueToECMAInt32(cx, s, &ti))
|
||||
return JS_FALSE;
|
||||
*((int8*)d) = (int8) ti;
|
||||
break;
|
||||
case nsXPTType::T_I16 :
|
||||
r = JS_ValueToECMAInt32(cx, s, &ti);
|
||||
if(!JS_ValueToECMAInt32(cx, s, &ti))
|
||||
return JS_FALSE;
|
||||
*((int16*)d) = (int16) ti;
|
||||
break;
|
||||
case nsXPTType::T_I32 :
|
||||
r = JS_ValueToECMAInt32(cx, s, (int32*)d);
|
||||
if(!JS_ValueToECMAInt32(cx, s, (int32*)d))
|
||||
return JS_FALSE;
|
||||
break;
|
||||
case nsXPTType::T_I64 :
|
||||
if(JSVAL_IS_INT(s))
|
||||
{
|
||||
r = JS_ValueToECMAInt32(cx, s, &ti);
|
||||
if(!JS_ValueToECMAInt32(cx, s, &ti))
|
||||
return JS_FALSE;
|
||||
*((int64*)d) = (int64) ti;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = JS_ValueToNumber(cx, s, &td);
|
||||
if(r) *((int64*)d) = (int64) td;
|
||||
if(!JS_ValueToNumber(cx, s, &td))
|
||||
return JS_FALSE;
|
||||
*((int64*)d) = (int64) td;
|
||||
}
|
||||
break;
|
||||
case nsXPTType::T_U8 :
|
||||
r = JS_ValueToECMAUint32(cx, s, &tu);
|
||||
if(!JS_ValueToECMAUint32(cx, s, &tu))
|
||||
return JS_FALSE;
|
||||
*((uint8*)d) = (uint8) tu;
|
||||
break;
|
||||
case nsXPTType::T_U16 :
|
||||
r = JS_ValueToECMAUint32(cx, s, &tu);
|
||||
if(!JS_ValueToECMAUint32(cx, s, &tu))
|
||||
return JS_FALSE;
|
||||
*((uint16*)d) = (uint16) tu;
|
||||
break;
|
||||
case nsXPTType::T_U32 :
|
||||
r = JS_ValueToECMAUint32(cx, s, (uint32*)d);
|
||||
if(!JS_ValueToECMAUint32(cx, s, (uint32*)d))
|
||||
return JS_FALSE;
|
||||
break;
|
||||
case nsXPTType::T_U64 :
|
||||
if(JSVAL_IS_INT(s))
|
||||
{
|
||||
r = JS_ValueToECMAUint32(cx, s, &tu);
|
||||
if(!JS_ValueToECMAUint32(cx, s, &tu))
|
||||
return JS_FALSE;
|
||||
*((uint64*)d) = (uint64) tu;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = JS_ValueToNumber(cx, s, &td);
|
||||
if(!JS_ValueToNumber(cx, s, &td))
|
||||
return JS_FALSE;
|
||||
// XXX Win32 can't handle double to uint64 directly
|
||||
if(r) *((uint64*)d) = (uint64)((int64) td);
|
||||
*((uint64*)d) = (uint64)((int64) td);
|
||||
}
|
||||
break;
|
||||
case nsXPTType::T_FLOAT :
|
||||
r = JS_ValueToNumber(cx, s, &td);
|
||||
if(r) *((float*)d) = (float) td;
|
||||
if(!JS_ValueToNumber(cx, s, &td))
|
||||
return JS_FALSE;
|
||||
*((float*)d) = (float) td;
|
||||
break;
|
||||
case nsXPTType::T_DOUBLE :
|
||||
r = JS_ValueToNumber(cx, s, (double*)d);
|
||||
if(!JS_ValueToNumber(cx, s, (double*)d))
|
||||
return JS_FALSE;
|
||||
break;
|
||||
case nsXPTType::T_BOOL :
|
||||
r = JS_ValueToBoolean(cx, s, (PRBool*)d);
|
||||
if(!JS_ValueToBoolean(cx, s, (PRBool*)d))
|
||||
return JS_FALSE;
|
||||
break;
|
||||
case nsXPTType::T_CHAR :
|
||||
{
|
||||
@ -403,7 +424,6 @@ XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
|
||||
if(!(str = JS_ValueToString(cx, s))||
|
||||
!(bytes = JS_GetStringBytes(str)))
|
||||
{
|
||||
// XXX should report error
|
||||
return JS_FALSE;
|
||||
}
|
||||
*((char*)d) = bytes[0];
|
||||
@ -416,7 +436,6 @@ XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
|
||||
if(!(str = JS_ValueToString(cx, s))||
|
||||
!(chars = JS_GetStringChars(str)))
|
||||
{
|
||||
// XXX should report error
|
||||
return JS_FALSE;
|
||||
}
|
||||
*((uint16*)d) = (uint16) chars[0];
|
||||
@ -444,14 +463,12 @@ XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
|
||||
(!(obj = JSVAL_TO_OBJECT(s))) ||
|
||||
(!(pid = xpc_JSObjectToID(cx, obj))))
|
||||
{
|
||||
// XXX should report error
|
||||
return JS_FALSE;
|
||||
}
|
||||
if(al)
|
||||
{
|
||||
if(!(*((void**)d) = al->Alloc(sizeof(nsID))))
|
||||
{
|
||||
// XXX should report error
|
||||
return JS_FALSE;
|
||||
}
|
||||
memcpy(*((void**)d), pid, sizeof(nsID));
|
||||
@ -475,7 +492,6 @@ XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
|
||||
if(!(str = JS_ValueToString(cx, s))||
|
||||
!(bytes = JS_GetStringBytes(str)))
|
||||
{
|
||||
// XXX should report error
|
||||
return JS_FALSE;
|
||||
}
|
||||
if(al)
|
||||
@ -483,7 +499,6 @@ XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
|
||||
int len = strlen(bytes)+1;
|
||||
if(!(*((void**)d) = al->Alloc(len)))
|
||||
{
|
||||
// XXX should report error
|
||||
return JS_FALSE;
|
||||
}
|
||||
memcpy(*((void**)d), bytes, len);
|
||||
@ -502,7 +517,6 @@ XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
|
||||
if(!(str = JS_ValueToString(cx, s))||
|
||||
!(chars = JS_GetStringChars(str)))
|
||||
{
|
||||
// XXX should report error
|
||||
return JS_FALSE;
|
||||
}
|
||||
if(al)
|
||||
@ -528,11 +542,10 @@ XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
|
||||
JSObject* obj;
|
||||
nsISupports* iface = NULL;
|
||||
|
||||
// only wrpa JSObjects
|
||||
// only wrap JSObjects
|
||||
if(!JSVAL_IS_OBJECT(s) ||
|
||||
(!(obj = JSVAL_TO_OBJECT(s))))
|
||||
{
|
||||
// XXX should report error
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
|
@ -455,8 +455,6 @@ private:
|
||||
nsXPCWrappedNativeClass(XPCContext* xpcc, REFNSIID aIID,
|
||||
nsIInterfaceInfo* aInfo);
|
||||
|
||||
void ReportError(const XPCNativeMemberDescriptor* desc, const char* msg);
|
||||
|
||||
void ThrowBadResultException(JSContext* cx,
|
||||
const XPCNativeMemberDescriptor* desc,
|
||||
nsresult result)
|
||||
@ -573,11 +571,13 @@ public:
|
||||
static JSBool IsMethodReflectable(const nsXPTMethodInfo& info);
|
||||
|
||||
static JSBool NativeData2JS(JSContext* cx, jsval* d, const void* s,
|
||||
const nsXPTType& type, const nsID* iid);
|
||||
const nsXPTType& type, const nsID* iid,
|
||||
uintN* pErr);
|
||||
|
||||
static JSBool JSData2Native(JSContext* cx, void* d, jsval s,
|
||||
const nsXPTType& type,
|
||||
nsIAllocator* al, const nsID* iid);
|
||||
nsIAllocator* al, const nsID* iid,
|
||||
uintN* pErr);
|
||||
private:
|
||||
XPCConvert(); // not implemented
|
||||
};
|
||||
|
@ -38,13 +38,19 @@ XPCJSThrower::Verbosify(nsXPCWrappedNativeClass* clazz,
|
||||
const XPCNativeMemberDescriptor* desc,
|
||||
char** psz, PRBool own)
|
||||
{
|
||||
char* sz = JS_smprintf("%s [%s.%s]",
|
||||
char* sz = NULL;
|
||||
|
||||
if(clazz && desc)
|
||||
sz = JS_smprintf("%s [%s.%s]",
|
||||
*psz,
|
||||
clazz->GetInterfaceName(),
|
||||
clazz->GetMemberName(desc));
|
||||
if(sz)
|
||||
{
|
||||
if(own)
|
||||
JS_smprintf_free(*psz);
|
||||
*psz = sz;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -338,7 +338,7 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
|
||||
}
|
||||
|
||||
if(!XPCConvert::NativeData2JS(cx, &val, &pv->val, type,
|
||||
conditional_iid))
|
||||
conditional_iid, NULL))
|
||||
{
|
||||
goto pre_call_clean_up;
|
||||
}
|
||||
@ -452,7 +452,7 @@ pre_call_clean_up:
|
||||
conditional_al = al;
|
||||
|
||||
if(!XPCConvert::JSData2Native(cx, &pv->val, val, type,
|
||||
conditional_al, conditional_iid))
|
||||
conditional_al, conditional_iid, NULL))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -336,27 +336,7 @@ nsXPCWrappedNativeClass::GetConstantAsJSVal(JSContext *cx,
|
||||
memcpy(&v.val, &mv.val, sizeof(mv.val));
|
||||
|
||||
// XXX if iid consts are supported, then coditionally fill it in here
|
||||
return XPCConvert::NativeData2JS(cx, vp, &v.val, v.type, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
nsXPCWrappedNativeClass::ReportError(const XPCNativeMemberDescriptor* desc,
|
||||
const char* msg)
|
||||
{
|
||||
JSContext* cx = GetJSContext();
|
||||
char* sz = JS_smprintf("'%s' accessing '%s' of '%s'",
|
||||
msg, GetMemberName(desc), GetInterfaceName());
|
||||
if(sz)
|
||||
{
|
||||
JSString* str = JS_NewStringCopyZ(cx, sz);
|
||||
if(str)
|
||||
JS_SetPendingException(cx, STRING_TO_JSVAL(str));
|
||||
JS_smprintf_free(sz);
|
||||
}
|
||||
/*
|
||||
JS_ReportError(GetJSContext(), "'%s' accessing '%s' of '%s'",
|
||||
msg, GetMemberName(desc), GetInterfaceName());
|
||||
*/
|
||||
return XPCConvert::NativeData2JS(cx, vp, &v.val, v.type, NULL, NULL);
|
||||
}
|
||||
|
||||
JSBool
|
||||
@ -381,12 +361,13 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
||||
uint8 vtblIndex;
|
||||
nsresult invokeResult;
|
||||
nsIAllocator* al = NULL;
|
||||
uintN err;
|
||||
|
||||
*vp = JSVAL_NULL;
|
||||
|
||||
if(!(al = nsXPConnect::GetAllocator()))
|
||||
{
|
||||
ReportError(desc, "can't get xpcom shared memory allocator");
|
||||
ThrowException(XPCJSError::UNEXPECTED, cx, desc);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -404,7 +385,7 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
||||
|
||||
if(NS_FAILED(mInfo->GetMethodInfo(vtblIndex, &info)))
|
||||
{
|
||||
ReportError(desc, "can't get MethodInfo");
|
||||
ThrowException(XPCJSError::CANT_GET_METHOD_INFO, cx, desc);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -414,7 +395,7 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
||||
(paramCount && info->GetParam(paramCount-1).IsRetval() ? 1 : 0);
|
||||
if(argc < requiredArgs)
|
||||
{
|
||||
ReportError(desc, "not enough arguments");
|
||||
ThrowException(XPCJSError::NOT_ENOUGH_ARGS, cx, desc);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -423,7 +404,7 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
||||
{
|
||||
if(!(dispatchParams = new nsXPCVariant[paramCount]))
|
||||
{
|
||||
ReportError(desc, "out of memory");
|
||||
JS_ReportOutOfMemory(cx);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@ -456,7 +437,8 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
||||
(!JSVAL_IS_OBJECT(argv[i]) ||
|
||||
!JS_GetProperty(cx, JSVAL_TO_OBJECT(argv[i]), XPC_VAL_STR, &src)))
|
||||
{
|
||||
ReportError(desc, "out argument must be object");
|
||||
ThrowBadParamException(XPCJSError::NEED_OUT_OBJECT,
|
||||
cx, desc, i);
|
||||
goto done;
|
||||
}
|
||||
if(!param.IsIn())
|
||||
@ -480,8 +462,8 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
||||
|
||||
if(!(conditional_iid = param.GetInterfaceIID()))
|
||||
{
|
||||
// XXX this (and others!) should throw rather than report error
|
||||
ReportError(desc, "could not get interface type");
|
||||
ThrowBadParamException(XPCJSError::CANT_GET_PARAM_IFACE_INFO,
|
||||
cx, desc, i);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@ -494,18 +476,18 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
||||
const nsXPTType& type = param.GetType();
|
||||
if(!type.IsPointer() || type.TagPart() != nsXPTType::T_IID ||
|
||||
!XPCConvert::JSData2Native(cx, &conditional_iid, argv[arg_num],
|
||||
type, NULL, NULL))
|
||||
type, NULL, NULL, NULL))
|
||||
{
|
||||
// XXX this (and others!) should throw rather than report error
|
||||
ReportError(desc, "could not get interface type");
|
||||
ThrowBadParamException(XPCJSError::CANT_GET_PARAM_IFACE_INFO,
|
||||
cx, desc, i);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if(!XPCConvert::JSData2Native(cx, &dp->val, src, type,
|
||||
conditional_al, conditional_iid))
|
||||
conditional_al, conditional_iid, &err))
|
||||
{
|
||||
NS_ASSERTION(0, "bad type");
|
||||
ThrowBadParamException(err, cx, desc, i);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@ -536,8 +518,8 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
||||
{
|
||||
if(!(conditional_iid = param.GetInterfaceIID()))
|
||||
{
|
||||
// XXX this (and others!) should throw rather than report error
|
||||
ReportError(desc, "could not get interface type");
|
||||
ThrowBadParamException(XPCJSError::CANT_GET_PARAM_IFACE_INFO,
|
||||
cx, desc, i);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@ -549,16 +531,16 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
||||
if(!type.IsPointer() || type.TagPart() != nsXPTType::T_IID ||
|
||||
!(conditional_iid = (nsID*)dispatchParams[arg_num].val.p))
|
||||
{
|
||||
// XXX this (and others!) should throw rather than report error
|
||||
ReportError(desc, "could not get interface type");
|
||||
ThrowBadParamException(XPCJSError::CANT_GET_PARAM_IFACE_INFO,
|
||||
cx, desc, i);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if(!XPCConvert::NativeData2JS(cx, &v, &dp->val, type,
|
||||
conditional_iid))
|
||||
conditional_iid, &err))
|
||||
{
|
||||
retval = NS_ERROR_FAILURE;
|
||||
ThrowBadParamException(err, cx, desc, i);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -570,7 +552,8 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
||||
NS_ASSERTION(JSVAL_IS_OBJECT(argv[i]), "out var is not object");
|
||||
if(!JS_SetProperty(cx, JSVAL_TO_OBJECT(argv[i]), XPC_VAL_STR, &v))
|
||||
{
|
||||
ReportError(desc, "Can't set val on out param object");
|
||||
ThrowBadParamException(XPCJSError::CANT_SET_OUT_VAL,
|
||||
cx, desc, i);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user