diff --git a/mozilla/js/src/xpconnect/idl/xpccomponents.idl b/mozilla/js/src/xpconnect/idl/xpccomponents.idl index 38fe860de56..d9c4b7ef029 100644 --- a/mozilla/js/src/xpconnect/idl/xpccomponents.idl +++ b/mozilla/js/src/xpconnect/idl/xpccomponents.idl @@ -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 */ diff --git a/mozilla/js/src/xpconnect/idl/xpctest.idl b/mozilla/js/src/xpconnect/idl/xpctest.idl index eb9d8e1b71c..a4ea79075ac 100644 --- a/mozilla/js/src/xpconnect/idl/xpctest.idl +++ b/mozilla/js/src/xpconnect/idl/xpctest.idl @@ -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); +}; + diff --git a/mozilla/js/src/xpconnect/public/nsIXPConnect.h b/mozilla/js/src/xpconnect/public/nsIXPConnect.h index e67ae825d96..7106f460522 100644 --- a/mozilla/js/src/xpconnect/public/nsIXPConnect.h +++ b/mozilla/js/src/xpconnect/public/nsIXPConnect.h @@ -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 diff --git a/mozilla/js/src/xpconnect/src/xpc.msg b/mozilla/js/src/xpconnect/src/xpc.msg index 0a89de923f3..3485ac97471 100644 --- a/mozilla/js/src/xpconnect/src/xpc.msg +++ b/mozilla/js/src/xpconnect/src/xpc.msg @@ -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") diff --git a/mozilla/js/src/xpconnect/src/xpccomponents.cpp b/mozilla/js/src/xpconnect/src/xpccomponents.cpp index 5795e62849e..3df9a7a9683 100644 --- a/mozilla/js/src/xpconnect/src/xpccomponents.cpp +++ b/mozilla/js/src/xpconnect/src/xpccomponents.cpp @@ -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) diff --git a/mozilla/js/src/xpconnect/src/xpcconvert.cpp b/mozilla/js/src/xpconnect/src/xpcconvert.cpp index bde3b448d66..9a41768297d 100644 --- a/mozilla/js/src/xpconnect/src/xpcconvert.cpp +++ b/mozilla/js/src/xpconnect/src/xpcconvert.cpp @@ -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, ¤t, ((_t*)*s)+i, type, iid, pErr) || \ + !JS_SetElement(cx, array, i, ¤t)) \ + 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, ¤t) || \ + !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 +} + diff --git a/mozilla/js/src/xpconnect/src/xpcprivate.h b/mozilla/js/src/xpconnect/src/xpcprivate.h index 96fff3cf17c..db48f2573dc 100644 --- a/mozilla/js/src/xpconnect/src/xpcprivate.h +++ b/mozilla/js/src/xpconnect/src/xpcprivate.h @@ -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 { diff --git a/mozilla/js/src/xpconnect/src/xpcwrappedjs.cpp b/mozilla/js/src/xpconnect/src/xpcwrappedjs.cpp index f8c66d8c060..e0c11038847 100644 --- a/mozilla/js/src/xpconnect/src/xpcwrappedjs.cpp +++ b/mozilla/js/src/xpconnect/src/xpcwrappedjs.cpp @@ -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); diff --git a/mozilla/js/src/xpconnect/src/xpcwrappedjsclass.cpp b/mozilla/js/src/xpconnect/src/xpcwrappedjsclass.cpp index 67d91795802..37455450f8e 100644 --- a/mozilla/js/src/xpconnect/src/xpcwrappedjsclass.cpp +++ b/mozilla/js/src/xpconnect/src/xpcwrappedjsclass.cpp @@ -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 { diff --git a/mozilla/js/src/xpconnect/src/xpcwrappednative.cpp b/mozilla/js/src/xpconnect/src/xpcwrappednative.cpp index f23d282d867..197dc9e191d 100644 --- a/mozilla/js/src/xpconnect/src/xpcwrappednative.cpp +++ b/mozilla/js/src/xpconnect/src/xpcwrappednative.cpp @@ -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; diff --git a/mozilla/js/src/xpconnect/src/xpcwrappednativeclass.cpp b/mozilla/js/src/xpconnect/src/xpcwrappednativeclass.cpp index f28de0706df..138847ed5e9 100644 --- a/mozilla/js/src/xpconnect/src/xpcwrappednativeclass.cpp +++ b/mozilla/js/src/xpconnect/src/xpcwrappednativeclass.cpp @@ -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, ¶m, 1, &argnum); + else + rv = mInfo->GetLengthIsArgNumberForParam(vtblIndex, ¶m, 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, ¶m, 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, ¶m, &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, ¶m, 1, + &type_in_array))) + { + ThrowException(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, cx, desc); + goto done; + } + + if(NS_FAILED( + mInfo->GetSizeIsArgNumberForParam(vtblIndex, ¶m, 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++) diff --git a/mozilla/js/src/xpconnect/tests/TestXPC.cpp b/mozilla/js/src/xpconnect/tests/TestXPC.cpp index bd7fc111f89..14a44dce1bc 100644 --- a/mozilla/js/src/xpconnect/tests/TestXPC.cpp +++ b/mozilla/js/src/xpconnect/tests/TestXPC.cpp @@ -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 diff --git a/mozilla/js/src/xpconnect/tests/components/Makefile.in b/mozilla/js/src/xpconnect/tests/components/Makefile.in index 8f3063b7f24..b89f33da7f2 100644 --- a/mozilla/js/src/xpconnect/tests/components/Makefile.in +++ b/mozilla/js/src/xpconnect/tests/components/Makefile.in @@ -27,6 +27,7 @@ LIBRARY_NAME = xpctest IS_COMPONENT = 1 CPPSRCS = \ + xpctest_array.cpp \ xpctest_echo.cpp \ xpctest_child.cpp \ xpctest_noisy.cpp \ diff --git a/mozilla/js/src/xpconnect/tests/components/makefile.win b/mozilla/js/src/xpconnect/tests/components/makefile.win index 87305cf8aa9..bed15ea4db3 100644 --- a/mozilla/js/src/xpconnect/tests/components/makefile.win +++ b/mozilla/js/src/xpconnect/tests/components/makefile.win @@ -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 \ diff --git a/mozilla/js/src/xpconnect/tests/components/xpctest_array.cpp b/mozilla/js/src/xpconnect/tests/components/xpctest_array.cpp new file mode 100644 index 00000000000..c1983486e6e --- /dev/null +++ b/mozilla/js/src/xpconnect/tests/components/xpctest_array.cpp @@ -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; +} +/***************************************************************************/ + + + + diff --git a/mozilla/js/src/xpconnect/tests/components/xpctest_echo.cpp b/mozilla/js/src/xpconnect/tests/components/xpctest_echo.cpp index c522fa5e76c..2fa9b24de02 100644 --- a/mozilla/js/src/xpconnect/tests/components/xpctest_echo.cpp +++ b/mozilla/js/src/xpconnect/tests/components/xpctest_echo.cpp @@ -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 diff --git a/mozilla/js/src/xpconnect/tests/components/xpctest_module.cpp b/mozilla/js/src/xpconnect/tests/components/xpctest_module.cpp index 2122bf1091b..e9a27f311c0 100644 --- a/mozilla/js/src/xpconnect/tests/components/xpctest_module.cpp +++ b/mozilla/js/src/xpconnect/tests/components/xpctest_module.cpp @@ -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; } diff --git a/mozilla/js/src/xpconnect/tests/components/xpctest_private.h b/mozilla/js/src/xpconnect/tests/components/xpctest_private.h index 790581ed0b0..364ca9e1c50 100644 --- a/mozilla/js/src/xpconnect/tests/components/xpctest_private.h +++ b/mozilla/js/src/xpconnect/tests/components/xpctest_private.h @@ -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 }; diff --git a/mozilla/js/src/xpconnect/tests/xpctest_exceptions.js b/mozilla/js/src/xpconnect/tests/xpctest_exceptions.js new file mode 100644 index 00000000000..3e25b834f58 --- /dev/null +++ b/mozilla/js/src/xpconnect/tests/xpctest_exceptions.js @@ -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); +} + +