From 6c7927182826dec56c8efa3bfdb46f4935f031f3 Mon Sep 17 00:00:00 2001 From: "jband%netscape.com" Date: Sun, 28 Feb 1999 04:16:20 +0000 Subject: [PATCH] using JS exception thrower (with tests) --- js/src/xpconnect/test/testxpc.js | 31 +++++++++- js/src/xpconnect/xpc.msg | 6 ++ js/src/xpconnect/xpcconvert.cpp | 67 +++++++++++++--------- js/src/xpconnect/xpcprivate.h | 8 +-- js/src/xpconnect/xpcthrower.cpp | 20 ++++--- js/src/xpconnect/xpcwrappedjsclass.cpp | 4 +- js/src/xpconnect/xpcwrappednativeclass.cpp | 63 ++++++++------------ 7 files changed, 117 insertions(+), 82 deletions(-) diff --git a/js/src/xpconnect/test/testxpc.js b/js/src/xpconnect/test/testxpc.js index 0d66e7cb3e9f..059a5ae5133a 100644 --- a/js/src/xpconnect/test/testxpc.js +++ b/js/src/xpconnect/test/testxpc.js @@ -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..."); diff --git a/js/src/xpconnect/xpc.msg b/js/src/xpconnect/xpc.msg index c201ac1d6b1a..30c5aa966f40 100644 --- a/js/src/xpconnect/xpc.msg +++ b/js/src/xpconnect/xpc.msg @@ -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") diff --git a/js/src/xpconnect/xpcconvert.cpp b/js/src/xpconnect/xpcconvert.cpp index 9ec97b521149..74e72ac73bed 100644 --- a/js/src/xpconnect/xpcconvert.cpp +++ b/js/src/xpconnect/xpcconvert.cpp @@ -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; } diff --git a/js/src/xpconnect/xpcprivate.h b/js/src/xpconnect/xpcprivate.h index 75a6675111d3..027e19518814 100644 --- a/js/src/xpconnect/xpcprivate.h +++ b/js/src/xpconnect/xpcprivate.h @@ -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 }; diff --git a/js/src/xpconnect/xpcthrower.cpp b/js/src/xpconnect/xpcthrower.cpp index 896322b20075..47586533429c 100644 --- a/js/src/xpconnect/xpcthrower.cpp +++ b/js/src/xpconnect/xpcthrower.cpp @@ -38,13 +38,19 @@ XPCJSThrower::Verbosify(nsXPCWrappedNativeClass* clazz, const XPCNativeMemberDescriptor* desc, char** psz, PRBool own) { - char* sz = JS_smprintf("%s [%s.%s]", - *psz, - clazz->GetInterfaceName(), - clazz->GetMemberName(desc)); - if(own) - JS_smprintf_free(*psz); - *psz = sz; + 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 diff --git a/js/src/xpconnect/xpcwrappedjsclass.cpp b/js/src/xpconnect/xpcwrappedjsclass.cpp index 41f45435b79e..787faa0901d4 100644 --- a/js/src/xpconnect/xpcwrappedjsclass.cpp +++ b/js/src/xpconnect/xpcwrappedjsclass.cpp @@ -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; } } diff --git a/js/src/xpconnect/xpcwrappednativeclass.cpp b/js/src/xpconnect/xpcwrappednativeclass.cpp index 462ad1d0b022..c024daa19a9e 100644 --- a/js/src/xpconnect/xpcwrappednativeclass.cpp +++ b/js/src/xpconnect/xpcwrappednativeclass.cpp @@ -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; } }