using JS exception thrower (with tests)

This commit is contained in:
jband%netscape.com 1999-02-28 04:16:20 +00:00
parent 27844bd641
commit 6c79271828
7 changed files with 117 additions and 82 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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