unfinished array support. fixes for exceptions

git-svn-id: svn://10.0.0.236/trunk@46935 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
jband%netscape.com
1999-09-11 05:21:30 +00:00
parent b9d4c03546
commit d3f6bf2cee
19 changed files with 1121 additions and 142 deletions

View File

@@ -18,6 +18,7 @@
#include "nsISupports.idl"
#include "xpcexception.idl"
#include "nsIComponentManager.idl"
[scriptable, uuid(4b62a640-d26c-11d2-9842-006008962422)]
interface nsIXPCInterfaces : nsISupports
@@ -47,6 +48,7 @@ interface nsIXPCComponents : nsISupports
readonly attribute nsIXPCClassesByID classesByID;
readonly attribute nsIJSStackFrameLocation stack;
readonly attribute nsIXPCResults results;
readonly attribute nsIComponentManager manager;
/* 'lastResult' is accessable via JavaScript only */
/* 'returnCode' is accessable via JavaScript only */

View File

@@ -38,7 +38,6 @@ interface nsITestXPCFoo : nsISupports {
interface nsITestXPCFoo2 : nsITestXPCFoo {
};
[scriptable, uuid(CD2F2F40-C5D9-11d2-9838-006008962422)]
interface nsIEcho : nsISupports {
@@ -101,6 +100,9 @@ interface nsIEcho : nsISupports {
void SetReceiverReturnOldReceiver(inout nsIEcho aReceiver);
void MethodWithForwardDeclaredParam(in nsITestXPCSomeUselessThing sut);
void PseudoQueryInterface(in nsIIDRef uuid,
[iid_is(uuid),retval] out nsQIResult result);
};
/***************************************************************************/
@@ -141,3 +143,20 @@ interface nsIXPCTestOverloaded : nsISupports {
void Foo1(in PRInt32 p1);
void Foo2(in PRInt32 p1, in PRInt32 p2);
};
[scriptable, uuid(3d2e64b0-6552-11d3-989e-006008962422)]
interface nsIXPCTestArray : nsISupports {
void PrintIntegerArray(in PRUint32 count,
[array, size_is(count)] in PRInt32 valueArray);
void PrintStringArray(in PRUint32 count,
[array, size_is(count)] in string valueArray);
void MultiplyEachItemInIntegerArray(
in PRInt32 val,
in PRUint32 count,
[array, size_is(count)] inout PRInt32 valueArray);
void MultiplyEachItemInIntegerArrayAndAppend(
in PRInt32 val,
inout PRUint32 count,
[array, size_is(count)] inout PRInt32 valueArray);
};

View File

@@ -56,38 +56,43 @@
#define GENERATE_XPC_FAILURE(x) \
(NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCONNECT,x))
#define NS_ERROR_XPC_NOT_ENOUGH_ARGS GENERATE_XPC_FAILURE( 1)
#define NS_ERROR_XPC_NEED_OUT_OBJECT GENERATE_XPC_FAILURE( 2)
#define NS_ERROR_XPC_CANT_SET_OUT_VAL GENERATE_XPC_FAILURE( 3)
#define NS_ERROR_XPC_NATIVE_RETURNED_FAILURE GENERATE_XPC_FAILURE( 4)
#define NS_ERROR_XPC_CANT_GET_INTERFACE_INFO GENERATE_XPC_FAILURE( 5)
#define NS_ERROR_XPC_CANT_GET_PARAM_IFACE_INFO GENERATE_XPC_FAILURE( 6)
#define NS_ERROR_XPC_CANT_GET_METHOD_INFO GENERATE_XPC_FAILURE( 7)
#define NS_ERROR_XPC_UNEXPECTED GENERATE_XPC_FAILURE( 8)
#define NS_ERROR_XPC_BAD_CONVERT_JS GENERATE_XPC_FAILURE( 9)
#define NS_ERROR_XPC_BAD_CONVERT_NATIVE GENERATE_XPC_FAILURE(10)
#define NS_ERROR_XPC_BAD_CONVERT_JS_NULL_REF GENERATE_XPC_FAILURE(11)
#define NS_ERROR_XPC_BAD_OP_ON_WN_PROTO GENERATE_XPC_FAILURE(12)
#define NS_ERROR_XPC_CANT_CONVERT_WN_TO_FUN GENERATE_XPC_FAILURE(13)
#define NS_ERROR_XPC_CANT_DEFINE_PROP_ON_WN GENERATE_XPC_FAILURE(14)
#define NS_ERROR_XPC_CANT_WATCH_WN_STATIC GENERATE_XPC_FAILURE(15)
#define NS_ERROR_XPC_CANT_EXPORT_WN_STATIC GENERATE_XPC_FAILURE(16)
#define NS_ERROR_XPC_SCRIPTABLE_CALL_FAILED GENERATE_XPC_FAILURE(17)
#define NS_ERROR_XPC_SCRIPTABLE_CTOR_FAILED GENERATE_XPC_FAILURE(18)
#define NS_ERROR_XPC_CANT_CALL_WO_SCRIPTABLE GENERATE_XPC_FAILURE(19)
#define NS_ERROR_XPC_CANT_CTOR_WO_SCRIPTABLE GENERATE_XPC_FAILURE(20)
#define NS_ERROR_XPC_CI_RETURNED_FAILURE GENERATE_XPC_FAILURE(21)
#define NS_ERROR_XPC_GS_RETURNED_FAILURE GENERATE_XPC_FAILURE(22)
#define NS_ERROR_XPC_BAD_CID GENERATE_XPC_FAILURE(23)
#define NS_ERROR_XPC_BAD_IID GENERATE_XPC_FAILURE(24)
#define NS_ERROR_XPC_CANT_CREATE_WN GENERATE_XPC_FAILURE(25)
#define NS_ERROR_XPC_JS_THREW_EXCEPTION GENERATE_XPC_FAILURE(26)
#define NS_ERROR_XPC_JS_THREW_NATIVE_OBJECT GENERATE_XPC_FAILURE(27)
#define NS_ERROR_XPC_JS_THREW_JS_OBJECT GENERATE_XPC_FAILURE(28)
#define NS_ERROR_XPC_JS_THREW_NULL GENERATE_XPC_FAILURE(29)
#define NS_ERROR_XPC_JS_THREW_STRING GENERATE_XPC_FAILURE(30)
#define NS_ERROR_XPC_JAVASCRIPT_ERROR GENERATE_XPC_FAILURE(31)
#define NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS GENERATE_XPC_FAILURE(32)
#define NS_ERROR_XPC_NOT_ENOUGH_ARGS GENERATE_XPC_FAILURE( 1)
#define NS_ERROR_XPC_NEED_OUT_OBJECT GENERATE_XPC_FAILURE( 2)
#define NS_ERROR_XPC_CANT_SET_OUT_VAL GENERATE_XPC_FAILURE( 3)
#define NS_ERROR_XPC_NATIVE_RETURNED_FAILURE GENERATE_XPC_FAILURE( 4)
#define NS_ERROR_XPC_CANT_GET_INTERFACE_INFO GENERATE_XPC_FAILURE( 5)
#define NS_ERROR_XPC_CANT_GET_PARAM_IFACE_INFO GENERATE_XPC_FAILURE( 6)
#define NS_ERROR_XPC_CANT_GET_METHOD_INFO GENERATE_XPC_FAILURE( 7)
#define NS_ERROR_XPC_UNEXPECTED GENERATE_XPC_FAILURE( 8)
#define NS_ERROR_XPC_BAD_CONVERT_JS GENERATE_XPC_FAILURE( 9)
#define NS_ERROR_XPC_BAD_CONVERT_NATIVE GENERATE_XPC_FAILURE(10)
#define NS_ERROR_XPC_BAD_CONVERT_JS_NULL_REF GENERATE_XPC_FAILURE(11)
#define NS_ERROR_XPC_BAD_OP_ON_WN_PROTO GENERATE_XPC_FAILURE(12)
#define NS_ERROR_XPC_CANT_CONVERT_WN_TO_FUN GENERATE_XPC_FAILURE(13)
#define NS_ERROR_XPC_CANT_DEFINE_PROP_ON_WN GENERATE_XPC_FAILURE(14)
#define NS_ERROR_XPC_CANT_WATCH_WN_STATIC GENERATE_XPC_FAILURE(15)
#define NS_ERROR_XPC_CANT_EXPORT_WN_STATIC GENERATE_XPC_FAILURE(16)
#define NS_ERROR_XPC_SCRIPTABLE_CALL_FAILED GENERATE_XPC_FAILURE(17)
#define NS_ERROR_XPC_SCRIPTABLE_CTOR_FAILED GENERATE_XPC_FAILURE(18)
#define NS_ERROR_XPC_CANT_CALL_WO_SCRIPTABLE GENERATE_XPC_FAILURE(19)
#define NS_ERROR_XPC_CANT_CTOR_WO_SCRIPTABLE GENERATE_XPC_FAILURE(20)
#define NS_ERROR_XPC_CI_RETURNED_FAILURE GENERATE_XPC_FAILURE(21)
#define NS_ERROR_XPC_GS_RETURNED_FAILURE GENERATE_XPC_FAILURE(22)
#define NS_ERROR_XPC_BAD_CID GENERATE_XPC_FAILURE(23)
#define NS_ERROR_XPC_BAD_IID GENERATE_XPC_FAILURE(24)
#define NS_ERROR_XPC_CANT_CREATE_WN GENERATE_XPC_FAILURE(25)
#define NS_ERROR_XPC_JS_THREW_EXCEPTION GENERATE_XPC_FAILURE(26)
#define NS_ERROR_XPC_JS_THREW_NATIVE_OBJECT GENERATE_XPC_FAILURE(27)
#define NS_ERROR_XPC_JS_THREW_JS_OBJECT GENERATE_XPC_FAILURE(28)
#define NS_ERROR_XPC_JS_THREW_NULL GENERATE_XPC_FAILURE(29)
#define NS_ERROR_XPC_JS_THREW_STRING GENERATE_XPC_FAILURE(30)
#define NS_ERROR_XPC_JS_THREW_NUMBER GENERATE_XPC_FAILURE(31)
#define NS_ERROR_XPC_JAVASCRIPT_ERROR GENERATE_XPC_FAILURE(32)
#define NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS GENERATE_XPC_FAILURE(33)
#define NS_ERROR_XPC_CANT_CONVERT_PRIMITIVE_TO_ARRAY GENERATE_XPC_FAILURE(34)
#define NS_ERROR_XPC_CANT_CONVERT_OBJECT_TO_ARRAY GENERATE_XPC_FAILURE(35)
#define NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY GENERATE_XPC_FAILURE(36)
#define NS_ERROR_XPC_CANT_GET_ARRAY_INFO GENERATE_XPC_FAILURE(37)
// any new errors here should have an associated entry added in xpc.msg

View File

@@ -21,38 +21,43 @@
/* xpconnect specific codes (from nsIXPConnect.h) */
XPC_MSG_DEF(NS_ERROR_XPC_NOT_ENOUGH_ARGS , "Not enough arguments")
XPC_MSG_DEF(NS_ERROR_XPC_NEED_OUT_OBJECT , "'Out' argument must be an object")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_SET_OUT_VAL , "Can not set 'value' property of 'out' argument")
XPC_MSG_DEF(NS_ERROR_XPC_NATIVE_RETURNED_FAILURE , "Component returned failure code:")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_GET_INTERFACE_INFO , "Can not find interface information")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_GET_PARAM_IFACE_INFO , "Can not find interface information for parameter")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_GET_METHOD_INFO , "Can not find method information")
XPC_MSG_DEF(NS_ERROR_XPC_UNEXPECTED , "Unexpected error in XPConnect")
XPC_MSG_DEF(NS_ERROR_XPC_BAD_CONVERT_JS , "Could not convert JavaScript argument")
XPC_MSG_DEF(NS_ERROR_XPC_BAD_CONVERT_NATIVE , "Could not convert Native argument")
XPC_MSG_DEF(NS_ERROR_XPC_BAD_CONVERT_JS_NULL_REF , "Could not convert JavaScript argument (NULL value can not be used for a C++ reference type)")
XPC_MSG_DEF(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO , "Illegal operation on WrappedNative prototype object")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_CONVERT_WN_TO_FUN , "Cannot convert WrappedNative to function")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_DEFINE_PROP_ON_WN , "Cannot define new property in a WrappedNative")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_WATCH_WN_STATIC , "Cannot place watchpoints on WrappedNative object static properties")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_EXPORT_WN_STATIC , "Cannot export a WrappedNative object's static properties")
XPC_MSG_DEF(NS_ERROR_XPC_SCRIPTABLE_CALL_FAILED , "nsIXPCScriptable::Call failed")
XPC_MSG_DEF(NS_ERROR_XPC_SCRIPTABLE_CTOR_FAILED , "nsIXPCScriptable::Construct failed")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_CALL_WO_SCRIPTABLE , "Can not use wrapper as function unless it implements nsIXPCScriptable")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_CTOR_WO_SCRIPTABLE , "Can not use wrapper as constuctor unless it implements nsIXPCScriptable")
XPC_MSG_DEF(NS_ERROR_XPC_CI_RETURNED_FAILURE , "ComponentManager::CreateInstance returned failure code:")
XPC_MSG_DEF(NS_ERROR_XPC_GS_RETURNED_FAILURE , "ServiceManager::GetService returned failure code:")
XPC_MSG_DEF(NS_ERROR_XPC_BAD_CID , "Invalid ClassID or ProgID")
XPC_MSG_DEF(NS_ERROR_XPC_BAD_IID , "Invalid InterfaceID")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_CREATE_WN , "Can not create wrapper around native interface")
XPC_MSG_DEF(NS_ERROR_XPC_JS_THREW_EXCEPTION , "JavaScript component threw exception")
XPC_MSG_DEF(NS_ERROR_XPC_JS_THREW_NATIVE_OBJECT , "JavaScript component threw a native object that is not an exception")
XPC_MSG_DEF(NS_ERROR_XPC_JS_THREW_JS_OBJECT , "JavaScript component threw a JavaScript object")
XPC_MSG_DEF(NS_ERROR_XPC_JS_THREW_NULL , "JavaScript component threw a null value as an exception")
XPC_MSG_DEF(NS_ERROR_XPC_JS_THREW_STRING , "JavaScript component threw a string as an exception")
XPC_MSG_DEF(NS_ERROR_XPC_JAVASCRIPT_ERROR , "JavaScript component caused a JavaScript error")
XPC_MSG_DEF(NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS, "JavaScript component caused a JavaScript error (detailed report attached)")
XPC_MSG_DEF(NS_ERROR_XPC_NOT_ENOUGH_ARGS , "Not enough arguments")
XPC_MSG_DEF(NS_ERROR_XPC_NEED_OUT_OBJECT , "'Out' argument must be an object")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_SET_OUT_VAL , "Can not set 'value' property of 'out' argument")
XPC_MSG_DEF(NS_ERROR_XPC_NATIVE_RETURNED_FAILURE , "Component returned failure code:")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_GET_INTERFACE_INFO , "Can not find interface information")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_GET_PARAM_IFACE_INFO , "Can not find interface information for parameter")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_GET_METHOD_INFO , "Can not find method information")
XPC_MSG_DEF(NS_ERROR_XPC_UNEXPECTED , "Unexpected error in XPConnect")
XPC_MSG_DEF(NS_ERROR_XPC_BAD_CONVERT_JS , "Could not convert JavaScript argument")
XPC_MSG_DEF(NS_ERROR_XPC_BAD_CONVERT_NATIVE , "Could not convert Native argument")
XPC_MSG_DEF(NS_ERROR_XPC_BAD_CONVERT_JS_NULL_REF , "Could not convert JavaScript argument (NULL value can not be used for a C++ reference type)")
XPC_MSG_DEF(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO , "Illegal operation on WrappedNative prototype object")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_CONVERT_WN_TO_FUN , "Cannot convert WrappedNative to function")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_DEFINE_PROP_ON_WN , "Cannot define new property in a WrappedNative")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_WATCH_WN_STATIC , "Cannot place watchpoints on WrappedNative object static properties")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_EXPORT_WN_STATIC , "Cannot export a WrappedNative object's static properties")
XPC_MSG_DEF(NS_ERROR_XPC_SCRIPTABLE_CALL_FAILED , "nsIXPCScriptable::Call failed")
XPC_MSG_DEF(NS_ERROR_XPC_SCRIPTABLE_CTOR_FAILED , "nsIXPCScriptable::Construct failed")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_CALL_WO_SCRIPTABLE , "Can not use wrapper as function unless it implements nsIXPCScriptable")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_CTOR_WO_SCRIPTABLE , "Can not use wrapper as constuctor unless it implements nsIXPCScriptable")
XPC_MSG_DEF(NS_ERROR_XPC_CI_RETURNED_FAILURE , "ComponentManager::CreateInstance returned failure code:")
XPC_MSG_DEF(NS_ERROR_XPC_GS_RETURNED_FAILURE , "ServiceManager::GetService returned failure code:")
XPC_MSG_DEF(NS_ERROR_XPC_BAD_CID , "Invalid ClassID or ProgID")
XPC_MSG_DEF(NS_ERROR_XPC_BAD_IID , "Invalid InterfaceID")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_CREATE_WN , "Can not create wrapper around native interface")
XPC_MSG_DEF(NS_ERROR_XPC_JS_THREW_EXCEPTION , "JavaScript component threw exception")
XPC_MSG_DEF(NS_ERROR_XPC_JS_THREW_NATIVE_OBJECT , "JavaScript component threw a native object that is not an exception")
XPC_MSG_DEF(NS_ERROR_XPC_JS_THREW_JS_OBJECT , "JavaScript component threw a JavaScript object")
XPC_MSG_DEF(NS_ERROR_XPC_JS_THREW_NULL , "JavaScript component threw a null value as an exception")
XPC_MSG_DEF(NS_ERROR_XPC_JS_THREW_STRING , "JavaScript component threw a string as an exception")
XPC_MSG_DEF(NS_ERROR_XPC_JS_THREW_NUMBER , "JavaScript component threw a number as an exception")
XPC_MSG_DEF(NS_ERROR_XPC_JAVASCRIPT_ERROR , "JavaScript component caused a JavaScript error")
XPC_MSG_DEF(NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS , "JavaScript component caused a JavaScript error (detailed report attached)")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_CONVERT_PRIMITIVE_TO_ARRAY, "Can not convert primitive JavaScript value into an array")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_CONVERT_OBJECT_TO_ARRAY , "Can not convert JavaScript object into an array")
XPC_MSG_DEF(NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY , "JavaScript Array does not have enough elements")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_GET_ARRAY_INFO , "Can not find array information")
/* common global codes (from nsError.h) */
@@ -70,7 +75,7 @@ XPC_MSG_DEF(NS_ERROR_UNEXPECTED , "Unexpected error")
XPC_MSG_DEF(NS_ERROR_OUT_OF_MEMORY , "Out of Memory")
XPC_MSG_DEF(NS_ERROR_ILLEGAL_VALUE , "Illegal value")
XPC_MSG_DEF(NS_ERROR_INVALID_ARG , "Invalid argument")
XPC_MSG_DEF(NS_ERROR_NO_AGGREGATION , "Component doe not support aggregation")
XPC_MSG_DEF(NS_ERROR_NO_AGGREGATION , "Component does not support aggregation")
XPC_MSG_DEF(NS_ERROR_NOT_AVAILABLE , "Component is not available")
XPC_MSG_DEF(NS_ERROR_FACTORY_NOT_REGISTERED , "Factory not registered")
XPC_MSG_DEF(NS_ERROR_FACTORY_NOT_LOADED , "Factory not loaded")

View File

@@ -979,6 +979,23 @@ nsXPCComponents::GetStack(nsIJSStackFrameLocation * *aStack)
return nsXPConnect::GetXPConnect()->GetCurrentJSStack(aStack);
}
NS_IMETHODIMP
nsXPCComponents::GetManager(nsIComponentManager * *aManager)
{
NS_ENSURE_ARG_POINTER(aManager);
nsIComponentManager* cm;
if(NS_FAILED(NS_GetGlobalComponentManager(&cm)))
{
*aManager = nsnull;
return NS_ERROR_FAILURE;
}
NS_IF_ADDREF(cm);
*aManager = cm;
return NS_OK;
}
/**********************************************/
// XPC_IMPLEMENT_FORWARD_CREATE(nsXPCComponents)

View File

@@ -40,32 +40,34 @@
((uint8)((np_no) | ((p_no) << 1) | ((np_o) << 2) | ((p_o) << 3)))
/***********************************************************/
#define XPC_FLAG_COUNT nsXPTType::T_INTERFACE_IS+1
#define XPC_FLAG_COUNT nsXPTType::T_ARRAY_WITH_LENGTH+1
/* '1' means 'reflectable'. '0' means 'not reflectable'. */
/* '1' means 'reflectable'. '0' means 'not reflectable'. */
static uint8 xpc_reflectable_flags[XPC_FLAG_COUNT] = {
/* 'p' stands for 'pointer' and 'o' stands for 'out' */
/* !p&!o, p&!o, !p&o, p&o */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_I8 */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_I16 */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_I32 */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_I64 */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_U8 */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_U16 */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_U32 */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_U64 */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_FLOAT */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_DOUBLE */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_BOOL */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_CHAR */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_WCHAR */
XPC_MK_FLAG( 0 , 0 , 0 , 0 ), /* T_VOID */
XPC_MK_FLAG( 0 , 1 , 0 , 1 ), /* T_IID */
XPC_MK_FLAG( 0 , 0 , 0 , 0 ), /* T_BSTR */
XPC_MK_FLAG( 0 , 1 , 0 , 1 ), /* T_CHAR_STR */
XPC_MK_FLAG( 0 , 1 , 0 , 1 ), /* T_WCHAR_STR */
XPC_MK_FLAG( 0 , 1 , 0 , 1 ), /* T_INTERFACE */
XPC_MK_FLAG( 0 , 1 , 0 , 1 ) /* T_INTERFACE_IS */
/* 'p' stands for 'pointer' and 'o' stands for 'out' */
/* !p&!o, p&!o, !p&o, p&o */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_I8 */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_I16 */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_I32 */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_I64 */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_U8 */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_U16 */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_U32 */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_U64 */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_FLOAT */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_DOUBLE */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_BOOL */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_CHAR */
XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_WCHAR */
XPC_MK_FLAG( 0 , 0 , 0 , 0 ), /* T_VOID */
XPC_MK_FLAG( 0 , 1 , 0 , 1 ), /* T_IID */
XPC_MK_FLAG( 0 , 0 , 0 , 0 ), /* T_BSTR */
XPC_MK_FLAG( 0 , 1 , 0 , 1 ), /* T_CHAR_STR */
XPC_MK_FLAG( 0 , 1 , 0 , 1 ), /* T_WCHAR_STR */
XPC_MK_FLAG( 0 , 1 , 0 , 1 ), /* T_INTERFACE */
XPC_MK_FLAG( 0 , 1 , 0 , 1 ), /* T_INTERFACE_IS */
XPC_MK_FLAG( 0 , 1 , 0 , 1 ), /* T_ARRAY */
XPC_MK_FLAG( 0 , 1 , 0 , 1 ) /* T_ARRAY_WITH_LENGTH */
};
/***********************************************************/
@@ -168,7 +170,7 @@ JAM_DOUBLE(JSContext *cx, double v, jsdouble *dbl)
JSBool
XPCConvert::NativeData2JS(JSContext* cx, jsval* d, const void* s,
const nsXPTType& type, const nsID* iid,
uintN* pErr)
nsresult* pErr)
{
NS_PRECONDITION(s, "bad param");
NS_PRECONDITION(d, "bad param");
@@ -365,7 +367,7 @@ JSBool
XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
const nsXPTType& type,
JSBool useAllocator, const nsID* iid,
uintN* pErr)
nsresult* pErr)
{
NS_PRECONDITION(d, "bad param");
@@ -755,7 +757,7 @@ XPCConvert::JSValToXPCException(JSContext* cx,
// heuristic to see if it might be usable as an xpcexception
if(JS_GetPropertyAttributes(cx, obj, "message", &ignored, &found) &&
found &&
JS_GetPropertyAttributes(cx, obj, "code", &ignored, &found) &&
JS_GetPropertyAttributes(cx, obj, "result", &ignored, &found) &&
found)
{
// lets try to build a wrapper around the JSObject
@@ -786,12 +788,59 @@ XPCConvert::JSValToXPCException(JSContext* cx,
nsnull, ifaceName, methodName, nsnull);
}
// lets see if it looks like and nsresult
if(JSVAL_IS_NUMBER(s))
{
// lets see if it looks like an nsresult
nsresult rv;
double number;
JSBool isResult = JS_FALSE;
nsresult rv;
if(JSVAL_IS_NUMBER(s) && JS_ValueToECMAUint32(cx, s, (uint32*)&rv))
return ConstructException(rv, nsnull, ifaceName, methodName, nsnull);
if(JSVAL_IS_INT(s))
{
rv = (nsresult) JSVAL_TO_INT(s);
if(NS_FAILED(rv))
isResult = JS_TRUE;
else
number = (double) JSVAL_TO_INT(s);
}
else
{
if(JSVAL_TO_DOUBLE(s))
{
number = *(JSVAL_TO_DOUBLE(s));
if(number > 0.0 &&
number < (double)0xffffffff &&
0.0 == fmod(number,1))
{
rv = (nsresult) number;
if(NS_FAILED(rv))
isResult = JS_TRUE;
}
}
}
if(isResult)
return ConstructException(rv, nsnull, ifaceName, methodName, nsnull);
else
{
nsISupportsDouble* data;
nsIComponentManager* cm;
if(NS_FAILED(NS_GetGlobalComponentManager(&cm)) || !cm ||
NS_FAILED(cm->CreateInstanceByProgID(
NS_SUPPORTS_DOUBLE_PROGID,
nsnull,
NS_GET_IID(nsISupportsDouble),
(void**)&data)))
return nsnull;
data->SetData(number);
nsIXPCException* e =
ConstructException(NS_ERROR_XPC_JS_THREW_NUMBER,
nsnull,
ifaceName, methodName, data);
NS_RELEASE(data);
return e;
}
}
// otherwise we'll just try to convert it to a string
@@ -882,3 +931,244 @@ XPC_JSArgumentFormatter(JSContext *cx, const char *format,
return JS_TRUE;
}
/***************************************************************************/
XPCArrayDataScavenger::XPCArrayDataScavenger(XPCArrayDataScavenger* aNext)
: mCleanupMode(NO_ACTION),
mInitedCount(0),
mData(nsnull),
mNext(aNext)
{
// nada
}
XPCArrayDataScavenger::~XPCArrayDataScavenger()
{
if(mData)
{
if(mCleanupMode == DO_FREE)
{
for(PRUint32 i = 0; i < mInitedCount; i++)
{
void* p = mData[i];
if(p) nsAllocator::Free(p);
}
}
else if(mCleanupMode == DO_RELEASE)
{
for(PRUint32 i = 0; i < mInitedCount; i++)
{
nsISupports* p = NS_REINTERPRET_CAST(nsISupports*, mData[i]);
NS_IF_RELEASE(p);
}
}
}
if(mNext)
delete mNext;
}
/***************************************************************************/
// array fun...
#ifdef POPULATE
#undef POPULATE
#endif
// static
JSBool
XPCConvert::NativeArray2JS(JSContext* cx,
jsval* d, const void** s,
const nsXPTType& type, const nsID* iid,
JSUint32 count,
nsresult* pErr)
{
NS_PRECONDITION(s, "bad param");
NS_PRECONDITION(d, "bad param");
// XXX add support for putting chars in a string rather than an array
// XXX add support to indicate *which* array element was not convertable
JSObject *array = JS_NewArrayObject(cx, count, nsnull);
if(!array)
return JS_FALSE;
// root this early
*d = OBJECT_TO_JSVAL(array);
if(pErr)
*pErr = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
JSUint32 i;
jsval current;
#define POPULATE(_t) \
PR_BEGIN_MACRO \
for(i = 0; i < count; i++) \
{ \
if(!NativeData2JS(cx, &current, ((_t*)*s)+i, type, iid, pErr) || \
!JS_SetElement(cx, array, i, &current)) \
goto failure; \
} \
PR_END_MACRO
// XXX check IsPtr - esp. to handle array of nsID (as opposed to nsID*)
switch(type.TagPart())
{
case nsXPTType::T_I8 : POPULATE(int8); break;
case nsXPTType::T_I16 : POPULATE(int16); break;
case nsXPTType::T_I32 : POPULATE(int32); break;
case nsXPTType::T_I64 : POPULATE(int64); break;
case nsXPTType::T_U8 : POPULATE(uint8); break;
case nsXPTType::T_U16 : POPULATE(uint16); break;
case nsXPTType::T_U32 : POPULATE(uint32); break;
case nsXPTType::T_U64 : POPULATE(uint64); break;
case nsXPTType::T_FLOAT : POPULATE(float); break;
case nsXPTType::T_DOUBLE : POPULATE(double); break;
case nsXPTType::T_BOOL : POPULATE(PRBool); break;
case nsXPTType::T_CHAR : POPULATE(char); break;
case nsXPTType::T_WCHAR : POPULATE(jschar); break;
case nsXPTType::T_VOID : NS_ASSERTION(0,"bad type"); goto failure;
case nsXPTType::T_IID : POPULATE(nsID*); break;
case nsXPTType::T_BSTR : NS_ASSERTION(0,"bad type"); goto failure;
case nsXPTType::T_CHAR_STR : POPULATE(char*); break;
case nsXPTType::T_WCHAR_STR : POPULATE(jschar*); break;
case nsXPTType::T_INTERFACE : POPULATE(nsISupports*); break;
case nsXPTType::T_INTERFACE_IS : POPULATE(nsISupports*); break;
default : NS_ASSERTION(0,"bad type"); goto failure;
}
if(pErr)
*pErr = NS_OK;
return JS_TRUE;
failure:
return JS_FALSE;
#undef POPULATE
}
// static
JSBool
XPCConvert::JSArray2Native(JSContext* cx, void** d, jsval s,
JSUint32 count, JSUint32 capacity,
XPCArrayDataScavenger* scavenger,
const nsXPTType& type,
JSBool useAllocator, const nsID* iid,
uintN* pErr)
{
NS_PRECONDITION(d, "bad param");
NS_PRECONDITION(scavenger, "bad param");
// XXX add support for getting chars from strings
// XXX add support to indicate *which* array element was not convertable
if(JSVAL_IS_VOID(s) || JSVAL_IS_NULL(s))
{
*d = nsnull;
return JS_TRUE;
}
if(!JSVAL_IS_OBJECT(s))
{
if(pErr)
*pErr = NS_ERROR_XPC_CANT_CONVERT_PRIMITIVE_TO_ARRAY;
return JS_FALSE;
}
JSObject* jsarray = JSVAL_TO_OBJECT(s);
if(!JS_IsArrayObject(cx, jsarray))
{
if(pErr)
*pErr = NS_ERROR_XPC_CANT_CONVERT_OBJECT_TO_ARRAY;
return JS_FALSE;
}
jsuint len;
if(!JS_GetArrayLength(cx, jsarray, &len) || len < count)
{
if(pErr)
*pErr = NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY;
return JS_FALSE;
}
if(pErr)
*pErr = NS_ERROR_XPC_BAD_CONVERT_JS;
void* array = nsnull;
JSUint32 i;
jsval current;
#define POPULATE(_mode, _t) \
PR_BEGIN_MACRO \
if(nsnull == (array = nsAllocator::Alloc(capacity * sizeof(_t)))) \
{ \
if(pErr) \
*pErr = NS_ERROR_OUT_OF_MEMORY; \
goto failure; \
} \
scavenger->SetDataPtr((void**)array); \
scavenger->SetCleanupMode(_mode); \
for(i = 0; i < count; i++) \
{ \
if(!JS_GetElement(cx, jsarray, i, &current) || \
!JSData2Native(cx, ((_t*)array)+i, current, type, \
useAllocator, iid, pErr)) \
goto failure; \
scavenger->IncrementInitedCount(); \
} \
PR_END_MACRO
static const XPCArrayDataScavenger::CleanupMode
na = XPCArrayDataScavenger::NO_ACTION,
fr = useAllocator ?
XPCArrayDataScavenger::DO_FREE :
XPCArrayDataScavenger::NO_ACTION,
re = XPCArrayDataScavenger::DO_RELEASE;
// XXX check IsPtr - esp. to handle array of nsID (as opposed to nsID*)
// XXX make extra space at end of char* and wchar* and null termintate
switch(type.TagPart())
{
case nsXPTType::T_I8 : POPULATE(na, int8); break;
case nsXPTType::T_I16 : POPULATE(na, int16); break;
case nsXPTType::T_I32 : POPULATE(na, int32); break;
case nsXPTType::T_I64 : POPULATE(na, int64); break;
case nsXPTType::T_U8 : POPULATE(na, uint8); break;
case nsXPTType::T_U16 : POPULATE(na, uint16); break;
case nsXPTType::T_U32 : POPULATE(na, uint32); break;
case nsXPTType::T_U64 : POPULATE(na, uint64); break;
case nsXPTType::T_FLOAT : POPULATE(na, float); break;
case nsXPTType::T_DOUBLE : POPULATE(na, double); break;
case nsXPTType::T_BOOL : POPULATE(na, PRBool); break;
case nsXPTType::T_CHAR : POPULATE(na, char); break;
case nsXPTType::T_WCHAR : POPULATE(na, jschar); break;
case nsXPTType::T_VOID : NS_ASSERTION(0,"bad type"); goto failure;
case nsXPTType::T_IID : POPULATE(fr, nsID*); break;
case nsXPTType::T_BSTR : NS_ASSERTION(0,"bad type"); goto failure;
case nsXPTType::T_CHAR_STR : POPULATE(fr, char*); break;
case nsXPTType::T_WCHAR_STR : POPULATE(fr, jschar*); break;
case nsXPTType::T_INTERFACE : POPULATE(re, nsISupports*); break;
case nsXPTType::T_INTERFACE_IS : POPULATE(re, nsISupports*); break;
default : NS_ASSERTION(0,"bad type"); goto failure;
}
*d = array;
if(pErr)
*pErr = NS_OK;
return JS_TRUE;
failure:
return JS_FALSE;
#undef POPULATE
}

View File

@@ -619,6 +619,19 @@ private:
JSBool BuildMemberDescriptors();
void DestroyMemberDescriptors();
enum SizeMode {GET_SIZE, GET_LENGTH};
JSBool GetArraySizeFromParam(JSContext* cx,
const nsXPTMethodInfo* method,
const XPCNativeMemberDescriptor* desc,
const nsXPTParamInfo& param,
uint8 vtblIndex,
uint8 paramIndex,
SizeMode mode,
jsval *argv,
JSUint32* result);
private:
XPCContext* mXPCContext;
nsIID mIID;
@@ -703,6 +716,32 @@ public:
/***************************************************************************/
// data convertion
class XPCArrayDataScavenger
{
public:
enum CleanupMode {NO_ACTION, DO_FREE, DO_RELEASE};
void SetDataPtr(void** aData)
{NS_ASSERTION(!mData,"must set data only once"); mData = aData;}
void SetCleanupMode(CleanupMode aCleanupMode)
{mCleanupMode = aCleanupMode;}
void IncrementInitedCount()
{NS_ASSERTION(mData,"must set data first"); mInitedCount++;}
XPCArrayDataScavenger(XPCArrayDataScavenger* aNext);
~XPCArrayDataScavenger();
private:
XPCArrayDataScavenger(); // no implementation
private:
CleanupMode mCleanupMode;
PRUint32 mInitedCount;
void** mData;
XPCArrayDataScavenger* mNext;
};
// class here just for static methods
class XPCConvert
{
@@ -711,12 +750,25 @@ public:
static JSBool NativeData2JS(JSContext* cx, jsval* d, const void* s,
const nsXPTType& type, const nsID* iid,
uintN* pErr);
nsresult* pErr);
static JSBool JSData2Native(JSContext* cx, void* d, jsval s,
const nsXPTType& type,
JSBool useAllocator, const nsID* iid,
uintN* pErr);
nsresult* pErr);
static JSBool NativeArray2JS(JSContext* cx,
jsval* d, const void** s,
const nsXPTType& type, const nsID* iid,
JSUint32 count,
nsresult* pErr);
static JSBool JSArray2Native(JSContext* cx, void** d, jsval s,
JSUint32 count, JSUint32 capacity,
XPCArrayDataScavenger* scavenger,
const nsXPTType& type,
JSBool useAllocator, const nsID* iid,
uintN* pErr);
static nsIXPCException* JSValToXPCException(JSContext* cx,
jsval s,
@@ -889,9 +941,10 @@ public:
/***************************************************************************/
// a class to put on the stack when we are entering xpconnect from an entry
// point where the JSContext is known. This pushes and pops the given context
// point where the JSContext is known. This pushs and pops the given context
// with the nsThreadJSContextStack service as this object goes into and out
// of scope.
// of scope. It is optimized to not push/pop the cx if it is already on top
// of the stack.
class AutoPushJSContext
{

View File

@@ -188,6 +188,13 @@ nsXPCWrappedJS::nsXPCWrappedJS(JSObject* aJSObj,
mRoot(root ? root : this),
mNext(nsnull)
{
#ifdef DEBUG_stats_jband
static int count = 0;
static const int interval = 10;
if(0 == (++count % interval))
printf("//////// %d instances of nsXPCWrappedJS created\n", count);
#endif
NS_INIT_REFCNT();
NS_ADDREF_THIS();
NS_ADDREF(aClass);

View File

@@ -320,6 +320,13 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
void* mark;
nsXPConnect* xpc = nsXPConnect::GetXPConnect();
#ifdef DEBUG_stats_jband
static int count = 0;
static const int interval = 10;
if(0 == (++count % interval))
printf("<<<<<<<< %d calls on nsXPCWrappedJSs made\n", count);
#endif
// XXX ASSUMES that retval is last arg.
paramCount = info->GetParamCount();
argc = paramCount -
@@ -519,6 +526,8 @@ pre_call_clean_up:
/* this one would be set by our error reporter */
xpc_exception = mXPCContext->GetException();
if(xpc_exception)
mXPCContext->SetException(nsnull);
// get this right away in case we do something below to cause JS code
// to run on this JSContext
@@ -542,22 +551,17 @@ pre_call_clean_up:
if(xpc_exception)
{
// Only throw the exception and fail if the JS code threw something
// that does indicate a failure; i.e. 'throw 0' is not really a failure
nsresult e_result;
if(NS_SUCCEEDED(xpc_exception->GetResult(&e_result)) && NS_FAILED(e_result))
if(NS_SUCCEEDED(xpc_exception->GetResult(&e_result)))
{
xpc->SetPendingException(xpc_exception);
NS_RELEASE(xpc_exception);
mXPCContext->SetException(nsnull);
retval = e_result;
success = JS_FALSE;
}
else
{
pending_result = e_result;
NS_RELEASE(xpc_exception);
if(NS_FAILED(e_result))
{
xpc->SetPendingException(xpc_exception);
retval = e_result;
}
}
NS_RELEASE(xpc_exception);
success = JS_FALSE;
}
else
{

View File

@@ -238,6 +238,13 @@ nsXPCWrappedNative::nsXPCWrappedNative(nsISupports* aObj,
NS_ADDREF(aClass);
NS_ADDREF(aObj);
#ifdef DEBUG_stats_jband
static int count = 0;
static const int interval = 10;
if(0 == (++count % interval))
printf("++++++++ %d instances of nsXPCWrappedNative created\n", count);
#endif
if(mRoot == this)
{
nsIXPCScriptable* ds;

View File

@@ -288,6 +288,68 @@ nsXPCWrappedNativeClass::GetConstantAsJSVal(JSContext *cx,
return XPCConvert::NativeData2JS(cx, vp, &v.val, v.type, nsnull, nsnull);
}
JSBool
nsXPCWrappedNativeClass::GetArraySizeFromParam(
JSContext* cx,
const nsXPTMethodInfo* method,
const XPCNativeMemberDescriptor* desc,
const nsXPTParamInfo& param,
uint8 vtblIndex,
uint8 paramIndex,
SizeMode mode,
jsval *argv,
JSUint32* result)
{
uint8 argnum;
nsresult rv;
jsval val;
// XXX fixup the various exceptions that are thrown
if(mode == GET_SIZE)
rv = mInfo->GetSizeIsArgNumberForParam(vtblIndex, &param, 1, &argnum);
else
rv = mInfo->GetLengthIsArgNumberForParam(vtblIndex, &param, 1, &argnum);
if(NS_FAILED(rv))
{
ThrowException(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, cx, desc);
return JS_FALSE;
}
const nsXPTParamInfo& arg_param = method->GetParam(argnum);
const nsXPTType& arg_type = arg_param.GetType();
// XXX require PRUint32 here - need to require in compiler too!
if(arg_type.IsPointer() || arg_type.TagPart() != nsXPTType::T_U32)
{
ThrowException(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, cx, desc);
return JS_FALSE;
}
if(arg_param.IsOut())
{
if(JSVAL_IS_PRIMITIVE(argv[argnum]) ||
!JS_GetProperty(cx, JSVAL_TO_OBJECT(argv[argnum]),
XPC_VAL_STR, &val))
{
ThrowException(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, cx, desc);
return JS_FALSE;
}
}
else
{
val = argv[argnum];
}
if(!XPCConvert::JSData2Native(cx, result, val,
arg_type, JS_FALSE, nsnull, nsnull))
{
ThrowBadParamException(NS_ERROR_XPC_CANT_GET_ARRAY_INFO,
cx, desc, paramIndex);
return JS_FALSE;
}
return JS_TRUE;
}
JSBool
nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
nsXPCWrappedNative* wrapper,
@@ -313,6 +375,14 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
uintN err;
XPCContext* xpcc = nsXPConnect::GetContext(cx);
nsIXPCSecurityManager* securityManager;
XPCArrayDataScavenger* scavenger = nsnull;
#ifdef DEBUG_stats_jband
static int count = 0;
static const int interval = 10;
if(0 == (++count % interval))
printf(">>>>>>>> %d calls on nsXPCWrappedNatives made\n", count);
#endif
if(vp)
*vp = JSVAL_NULL;
@@ -415,6 +485,18 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
JSBool useAllocator = JS_FALSE;
const nsXPTParamInfo& param = info->GetParam(i);
const nsXPTType& type = param.GetType();
nsXPTType type_in_array = type;
uint8 type_tag = type.TagPart();
PRBool isArray = type.IsArray();
JSUint32 array_count;
JSUint32 array_capacity;
if(isArray && NS_FAILED(mInfo->GetTypeForParam(vtblIndex, &param, 1,
&type_in_array)))
{
ThrowException(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, cx, desc);
goto done;
}
nsXPTCVariant* dp = &dispatchParams[i];
dp->type = type;
@@ -422,8 +504,8 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
dp->val.p = nsnull;
dispatchParamsInitedCount++;
if(type.TagPart() == nsXPTType::T_INTERFACE ||
type.TagPart() == nsXPTType::T_INTERFACE_IS)
if(type_tag == nsXPTType::T_INTERFACE ||
type_tag == nsXPTType::T_INTERFACE_IS)
{
dp->flags |= nsXPTCVariant::VAL_IS_IFACE;
}
@@ -444,12 +526,26 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
cx, desc, i);
goto done;
}
if(type.IsPointer() &&
!type.IsInterfacePointer() &&
!param.IsShared())
if(isArray)
{
useAllocator = JS_TRUE;
dp->flags |= nsXPTCVariant::VAL_IS_OWNED;
if(type_in_array.IsPointer() &&
!type_in_array.IsInterfacePointer() &&
!param.IsShared())
{
useAllocator = JS_TRUE;
dp->flags |= nsXPTCVariant::VAL_IS_OWNED;
}
}
else
{
if(type.IsPointer() &&
!type.IsInterfacePointer() &&
!param.IsShared())
{
useAllocator = JS_TRUE;
dp->flags |= nsXPTCVariant::VAL_IS_OWNED;
}
}
if(!param.IsIn())
continue;
@@ -457,14 +553,45 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
else
{
src = argv[i];
if(type.IsPointer() && type.TagPart() == nsXPTType::T_IID)
if(isArray)
{
useAllocator = JS_TRUE;
dp->flags |= nsXPTCVariant::VAL_IS_OWNED;
if(type_in_array.IsPointer() &&
type_in_array.TagPart() == nsXPTType::T_IID)
{
useAllocator = JS_TRUE;
}
}
else
{
if(type.IsPointer() && type_tag == nsXPTType::T_IID)
{
useAllocator = JS_TRUE;
dp->flags |= nsXPTCVariant::VAL_IS_OWNED;
}
}
}
if(type.TagPart() == nsXPTType::T_INTERFACE)
if(isArray)
{
if(!GetArraySizeFromParam(cx, info, desc, param, vtblIndex,
i, GET_SIZE, argv, &array_capacity))
goto done;
// XXX add code to handle length here!
array_count = array_capacity;
}
else
{
// XXX fix for arrays of interfaces!
// Need to fix GetInterfaceIsArgNumber() to be a method on the
// interface info instead of the param - so it can look at the right
// type info.
if(type_tag == nsXPTType::T_INTERFACE)
{
if(NS_FAILED(GetInterfaceInfo()->
GetIIDForParam(vtblIndex, &param, &conditional_iid)))
@@ -474,14 +601,15 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
goto done;
}
}
else if(type.TagPart() == nsXPTType::T_INTERFACE_IS)
else if(type_tag == nsXPTType::T_INTERFACE_IS)
{
uint8 arg_num = param.GetInterfaceIsArgNumber();
const nsXPTParamInfo& param = info->GetParam(arg_num);
const nsXPTType& type = param.GetType();
if(!type.IsPointer() || type.TagPart() != nsXPTType::T_IID ||
const nsXPTParamInfo& arg_param = info->GetParam(arg_num);
const nsXPTType& arg_type = arg_param.GetType();
if(!arg_type.IsPointer() ||
arg_type.TagPart() != nsXPTType::T_IID ||
!XPCConvert::JSData2Native(cx, &conditional_iid, argv[arg_num],
type, JS_TRUE, nsnull, nsnull))
arg_type, JS_TRUE, nsnull, nsnull))
{
ThrowBadParamException(NS_ERROR_XPC_CANT_GET_PARAM_IFACE_INFO,
cx, desc, i);
@@ -489,12 +617,38 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
}
}
if(!XPCConvert::JSData2Native(cx, &dp->val, src, type,
useAllocator, conditional_iid, &err))
{
ThrowBadParamException(err, cx, desc, i);
goto done;
}
if(isArray)
{
XPCArrayDataScavenger* new_scavenger;
if(!(new_scavenger = new XPCArrayDataScavenger(scavenger)))
{
JS_ReportOutOfMemory(cx);
goto done;
}
scavenger = new_scavenger;
if(!XPCConvert::JSArray2Native(cx, (void**)&dp->val, src,
array_count, array_capacity,
scavenger, type_in_array,
useAllocator, conditional_iid, &err))
{
// XXX need exception scheme for arrays to indicate bad element
ThrowBadParamException(err, cx, desc, i);
goto done;
}
}
else
{
if(!XPCConvert::JSData2Native(cx, &dp->val, src, type,
useAllocator, conditional_iid, &err))
{
ThrowBadParamException(err, cx, desc, i);
goto done;
}
}
if(conditional_iid)
{
nsAllocator::Free((void*)conditional_iid);
@@ -522,6 +676,53 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
if(param.IsOut())
{
jsval v;
JSUint32 array_count;
JSUint32 array_capacity;
nsXPTType type_in_array;
PRBool isArray = type.IsArray();
if(isArray)
{
uint8 size_is_argnum;
if(NS_FAILED(mInfo->GetTypeForParam(vtblIndex, &param, 1,
&type_in_array)))
{
ThrowException(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, cx, desc);
goto done;
}
if(NS_FAILED(
mInfo->GetSizeIsArgNumberForParam(vtblIndex, &param, 1,
&size_is_argnum)))
{
ThrowException(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, cx, desc);
goto done;
}
const nsXPTParamInfo& arg_param = info->GetParam(size_is_argnum);
const nsXPTType& arg_type = arg_param.GetType();
// XXX require PRUint32 here - need to require in compiler too!
if(arg_type.IsPointer() ||
arg_type.TagPart() != nsXPTType::T_U32)
{
ThrowBadParamException(NS_ERROR_XPC_CANT_GET_ARRAY_INFO,
cx, desc, i);
goto done;
}
array_capacity = dispatchParams[size_is_argnum].val.u32;
// XXX add code to handle length here!
array_count = array_capacity;
}
else
{
// XXX fix for arrays of interfaces!
// Need to fix GetInterfaceIsArgNumber() to be a method on the
// interface info instead of the param - so it can look at the right
// type info.
if(type.TagPart() == nsXPTType::T_INTERFACE)
{
@@ -536,9 +737,10 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
else if(type.TagPart() == nsXPTType::T_INTERFACE_IS)
{
uint8 arg_num = param.GetInterfaceIsArgNumber();
const nsXPTParamInfo& param = info->GetParam(arg_num);
const nsXPTType& type = param.GetType();
if(!type.IsPointer() || type.TagPart() != nsXPTType::T_IID ||
const nsXPTParamInfo& arg_param = info->GetParam(arg_num);
const nsXPTType& arg_type = arg_param.GetType();
if(!arg_type.IsPointer() ||
arg_type.TagPart() != nsXPTType::T_IID ||
!(conditional_iid = (nsID*)
nsAllocator::Clone(dispatchParams[arg_num].val.p,
sizeof(nsID))))
@@ -548,12 +750,27 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
goto done;
}
}
}
if(!XPCConvert::NativeData2JS(cx, &v, &dp->val, type,
conditional_iid, &err))
if(isArray)
{
ThrowBadParamException(err, cx, desc, i);
goto done;
if(!XPCConvert::NativeArray2JS(cx, &v, (const void**)&dp->val,
type_in_array, conditional_iid,
array_count, &err))
{
// XXX need exception scheme for arrays to indicate bad element
ThrowBadParamException(err, cx, desc, i);
goto done;
}
}
else
{
if(!XPCConvert::NativeData2JS(cx, &v, &dp->val, type,
conditional_iid, &err))
{
ThrowBadParamException(err, cx, desc, i);
goto done;
}
}
if(param.IsRetval())
@@ -582,6 +799,10 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
retval = JS_TRUE;
done:
// delete any array contents that have been allocated
if(scavenger)
delete scavenger;
// iterate through the params that were init'd (again!) and clean up
// any alloc'd stuff and release wrappers of params
for(i = 0; i < dispatchParamsInitedCount; i++)

View File

@@ -442,6 +442,17 @@ MyEcho::MethodWithForwardDeclaredParam(nsITestXPCSomeUselessThing *sut)
return NS_OK;
}
/* void PseudoQueryInterface (in nsIIDRef uuid, [iid_is (uuid), retval] out nsQIResult result); */
NS_IMETHODIMP
MyEcho::PseudoQueryInterface(const nsIID & uuid, void * *result)
{
if(!result)
return NS_ERROR_NULL_POINTER;
if(mReceiver)
return mReceiver->PseudoQueryInterface(uuid, result);
return NS_OK;
}
/***************************************************************************/
// security manager test class

View File

@@ -27,6 +27,7 @@ LIBRARY_NAME = xpctest
IS_COMPONENT = 1
CPPSRCS = \
xpctest_array.cpp \
xpctest_echo.cpp \
xpctest_child.cpp \
xpctest_noisy.cpp \

View File

@@ -26,6 +26,7 @@ MODULE=xpconnect
DEFINES=-DWIN32_LEAN_AND_MEAN
OBJS= \
.\$(OBJDIR)\xpctest_array.obj \
.\$(OBJDIR)\xpctest_echo.obj \
.\$(OBJDIR)\xpctest_child.obj \
.\$(OBJDIR)\xpctest_noisy.obj \

View File

@@ -0,0 +1,144 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* implement nsIXPCTestString for testing. */
#include "xpctest_private.h"
class xpcarraytest : public nsIXPCTestArray
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIXPCTESTARRAY
xpcarraytest();
virtual ~xpcarraytest();
};
xpcarraytest::xpcarraytest()
{
NS_INIT_REFCNT();
NS_ADDREF_THIS();
}
xpcarraytest::~xpcarraytest()
{
}
NS_IMPL_ISUPPORTS1(xpcarraytest, nsIXPCTestArray);
/* void PrintIntegerArray (in PRUint32 count, [array, size_is (count)] in PRInt32 valueArray); */
NS_IMETHODIMP
xpcarraytest::PrintIntegerArray(PRUint32 count, PRInt32 *valueArray)
{
if(valueArray && count)
{
for(PRUint32 i = 0; i < count; i++)
printf("%d%s", valueArray[i], i == count -1 ? "\n" : ",");
}
else
printf("empty array\n");
return NS_OK;
}
/* void PrintStringArray (in PRUint32 count, [array, size_is (count)] in string valueArray); */
NS_IMETHODIMP
xpcarraytest::PrintStringArray(PRUint32 count, const char **valueArray)
{
if(valueArray && count)
{
for(PRUint32 i = 0; i < count; i++)
printf("\"%s\"%s", valueArray[i], i == count -1 ? "\n" : ",");
}
else
printf("empty array\n");
return NS_OK;
}
/* void MultiplyEachItemInIntegerArray (in PRInt32 val, in PRUint32 count, [array, size_is (count)] inout PRInt32 valueArray); */
NS_IMETHODIMP
xpcarraytest::MultiplyEachItemInIntegerArray(PRInt32 val, PRUint32 count, PRInt32 **valueArray)
{
PRInt32* a;
if(valueArray && count && nsnull != (a = *valueArray))
{
for(PRUint32 i = 0; i < count; i++)
a[i] *= val;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
/* void MultiplyEachItemInIntegerArrayAndAppend (in PRInt32 val, inout PRUint32 count, [array, size_is (count)] inout PRInt32 valueArray); */
NS_IMETHODIMP
xpcarraytest::MultiplyEachItemInIntegerArrayAndAppend(PRInt32 val, PRUint32 *count, PRInt32 **valueArray)
{
PRInt32* in;
PRUint32 in_count;
if(valueArray && count && 0 != (in_count = *count) && nsnull != (in = *valueArray))
{
PRInt32* out =
(PRInt32*) nsAllocator::Alloc(in_count * 2 * sizeof(PRUint32));
if(!out)
return NS_ERROR_OUT_OF_MEMORY;
for(PRUint32 i = 0; i < in_count; i++)
{
out[i*2] = in[i];
out[i*2+1] = in[i] * val;
}
nsAllocator::Free(in);
*valueArray = out;
*count = in_count * 2;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
/***************************************************************************/
// static
NS_IMETHODIMP
xpctest::ConstructArrayTest(nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
nsresult rv;
NS_ASSERTION(aOuter == nsnull, "no aggregation");
xpcarraytest* obj = new xpcarraytest();
if(obj)
{
rv = obj->QueryInterface(aIID, aResult);
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to find correct interface");
NS_RELEASE(obj);
}
else
{
*aResult = nsnull;
rv = NS_ERROR_OUT_OF_MEMORY;
}
return rv;
}
/***************************************************************************/

View File

@@ -265,6 +265,17 @@ xpctestEcho::MethodWithForwardDeclaredParam(nsITestXPCSomeUselessThing *sut)
return NS_OK;
}
/* void PseudoQueryInterface (in nsIIDRef uuid, [iid_is (uuid), retval] out nsQIResult result); */
NS_IMETHODIMP
xpctestEcho::PseudoQueryInterface(const nsIID & uuid, void * *result)
{
if(!result)
return NS_ERROR_NULL_POINTER;
if(mReceiver)
return mReceiver->PseudoQueryInterface(uuid, result);
return NS_OK;
}
/***************************************************************************/
// static

View File

@@ -55,6 +55,8 @@ NSGetFactory(nsISupports* aServMgr,
rv = factory->SetConstructor(xpctest::ConstructStringTest);
else if(aClass.Equals(xpctest::GetOverloadedCID()))
rv = factory->SetConstructor(xpctest::ConstructOverloaded);
else if(aClass.Equals(xpctest::GetArrayTestCID()))
rv = factory->SetConstructor(xpctest::ConstructArrayTest);
else
{
NS_ASSERTION(0, "incorrectly registered");
@@ -100,6 +102,9 @@ NSRegisterSelf(nsISupports* aServMgr , const char* aPath)
"nsOverloaded", "nsOverloaded", aPath,
PR_TRUE, PR_TRUE);
rv = compMgr->RegisterComponent(xpctest::GetArrayTestCID(),
"nsArrayTest", "nsArrayTest", aPath,
PR_TRUE, PR_TRUE);
return rv;
}
@@ -117,6 +122,7 @@ NSUnregisterSelf(nsISupports* aServMgr, const char* aPath)
rv = compMgr->UnregisterComponent(xpctest::GetNoisyCID(), aPath);
rv = compMgr->UnregisterComponent(xpctest::GetStringTestCID(), aPath);
rv = compMgr->UnregisterComponent(xpctest::GetOverloadedCID(), aPath);
rv = compMgr->UnregisterComponent(xpctest::GetArrayTestCID(), aPath);
return rv;
}

View File

@@ -60,6 +60,11 @@
{ 0xdc5fde90, 0x439d, 0x11d3, \
{ 0x98, 0x8c, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
// {5B9AF380-6569-11d3-989E-006008962422}
#define NS_ARRAY_CID \
{ 0x5b9af380, 0x6569, 0x11d3, \
{ 0x98, 0x9e, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } };
// 'namespace' class
class xpctest
@@ -80,6 +85,9 @@ public:
static const nsID& GetOverloadedCID() {static nsID cid = NS_OVERLOADED_CID; return cid;}
static NS_METHOD ConstructOverloaded(nsISupports *aOuter, REFNSIID aIID, void **aResult);
static const nsID& GetArrayTestCID() {static nsID cid = NS_ARRAY_CID; return cid;}
static NS_METHOD ConstructArrayTest(nsISupports *aOuter, REFNSIID aIID, void **aResult);
private:
xpctest(); // not implemented
};

View File

@@ -0,0 +1,167 @@
function printExceptionDoubleData(e) {
if(!e || !e.data)
return;
if(e instanceof Components.interfaces.nsIXPCException) {
try {
var d = e.data.QueryInterface(Components.interfaces.nsISupportsDouble)
try {
print("e.data = "+d.data);
} catch(i) {
print("could not get double from e.data");
}
} catch(i) {
print("e.data was not an nsISupportsDouble");
}
}
else {
print("object was not an nsIXPCException");
}
}
var clazz = Components.classes.nsEcho;
var iface = Components.interfaces.nsIEcho;
var nativeEcho = clazz.createInstance(iface);
var localEcho = {
SendOneString : function() {throw this.result;},
result : 0
};
nativeEcho.SetReceiver(localEcho);
localEcho.result = 0;
print("\n");
try {
nativeEcho.SendOneString("foo");
print("no error");
} catch(e) {
print("caught "+e);
printExceptionDoubleData(e);
}
localEcho.result = 1;
print("\n");
try {
nativeEcho.SendOneString("foo");
print("no error");
} catch(e) {
print("caught "+e);
printExceptionDoubleData(e);
}
localEcho.result = -1;
print("\n");
try {
nativeEcho.SendOneString("foo");
print("no error");
} catch(e) {
print("caught "+e);
printExceptionDoubleData(e);
}
localEcho.result = Components.results.NS_ERROR_NO_AGGREGATION;
print("\n");
try {
nativeEcho.SendOneString("foo");
print("no error");
} catch(e) {
print("caught "+e);
printExceptionDoubleData(e);
}
localEcho.result = 0x80040154;
print("\n");
try {
nativeEcho.SendOneString("foo");
print("no error");
} catch(e) {
print("caught "+e);
printExceptionDoubleData(e);
}
print("\n");
localEcho.result = new Components.Exception("hi", Components.results.NS_ERROR_ABORT);
try {
nativeEcho.SendOneString("foo");
} catch(e) {
print("caught "+e);
}
print("\n");
localEcho.result = {message : "pretending to be NS_OK does not work", result : 0};
try {
nativeEcho.SendOneString("foo");
print("pretending 0 == NS_OK");
} catch(e) {
print("caught "+e);
}
print("\n");
localEcho.result = {message : "pretending to be NS_ERROR_NO_INTERFACE",
result : Components.results.NS_ERROR_NO_INTERFACE};
try {
nativeEcho.SendOneString("foo");
} catch(e) {
print("caught "+e.message);
}
print("\n");
localEcho.result = "just a string";
try {
nativeEcho.SendOneString("foo");
} catch(e) {
print("caught "+e);
}
print("\n");
localEcho.result = Components.results.NS_ERROR_NO_INTERFACE;
try {
nativeEcho.SendOneString("foo");
} catch(e) {
print("caught "+e);
}
print("\n");
localEcho.result = "NS_OK";
try {
nativeEcho.SendOneString("foo");
} catch(e) {
print("caught "+e);
}
print("\n");
localEcho.result = Components;
try {
nativeEcho.SendOneString("foo");
} catch(e) {
print("caught "+e);
}
print("\n");
/* make this function have a JS runtime error */
localEcho.SendOneString = function(){return Components.foo.bar;};
try {
nativeEcho.SendOneString("foo");
} catch(e) {
print("caught "+e);
}
print("\n");
/* make this function have a JS compiletime error */
localEcho.SendOneString = function(){new Function("","foo ===== 1")};
try {
nativeEcho.SendOneString("foo");
} catch(e) {
print("caught "+e);
}