зеркало из https://github.com/mozilla/gecko-dev.git
- the rest of the fix for bug 14738 - detect JSErrors with
JSErrorReports when thrown as exceptions. Extract JSErrorReport and convert to an xpcexception. This restores functionality that was whacked when JS errors-as-exceptions was enabled in the JS engine. - add conversion support for string-with-length as part of array support mentioned in bug 13420. All the array stuff is basically in with minimal testcases. More comprehensive tests need to be written to verify and tune the code. - fix a broken #undef - switch to using PR_Alloc/PR_Free internally in nsjsid where we were using new/delete before. This is prompted by warren's change to nsID::ToString that uses PR_Alloc were before it used new. This fixes an alloc/delete mismatch detected by Purify. r=mccabe
This commit is contained in:
Родитель
295700338f
Коммит
0da203c7c3
|
@ -188,5 +188,10 @@ interface nsIXPCTestArray : nsISupports {
|
|||
[array, size_is(count)] inout string valueArray);
|
||||
void ReverseStringArray(in PRUint32 count,
|
||||
[array, size_is(count)] inout string valueArray);
|
||||
|
||||
void PrintStringWithSize(in PRUint32 count,
|
||||
[size_is(count)] in string str);
|
||||
void DoubleString(inout PRUint32 count,
|
||||
[size_is(count)] inout string str);
|
||||
};
|
||||
|
||||
|
|
|
@ -109,6 +109,7 @@
|
|||
#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)
|
||||
#define NS_ERROR_XPC_NOT_ENOUGH_CHARS_IN_STRING GENERATE_XPC_FAILURE(38)
|
||||
|
||||
// any new errors here should have an associated entry added in xpc.msg
|
||||
|
||||
|
|
|
@ -72,8 +72,9 @@ XPC_MSG_DEF(NS_ERROR_XPC_JAVASCRIPT_ERROR , "JavaScript component
|
|||
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_NOT_ENOUGH_ELEMENTS_IN_ARRAY , "JavaScript Array does not have as many elements as indicated by size argument")
|
||||
XPC_MSG_DEF(NS_ERROR_XPC_CANT_GET_ARRAY_INFO , "Can not find array information")
|
||||
XPC_MSG_DEF(NS_ERROR_XPC_NOT_ENOUGH_CHARS_IN_STRING , "JavaScript String does not have as many characters as indicated by size argument")
|
||||
|
||||
/* common global codes (from nsError.h) */
|
||||
|
||||
|
|
|
@ -83,8 +83,8 @@ static uint8 xpc_reflectable_flags[XPC_FLAG_COUNT] = {
|
|||
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 , 0 , 0 , 0 ), /* T_PSTRING_SIZE_IS */ //XXX disabled
|
||||
XPC_MK_FLAG( 0 , 0 , 0 , 0 ) /* T_PWSTRING_SIZE_IS */ //XXX disabled
|
||||
XPC_MK_FLAG( 0 , 1 , 0 , 1 ), /* T_PSTRING_SIZE_IS */
|
||||
XPC_MK_FLAG( 0 , 1 , 0 , 1 ) /* T_PWSTRING_SIZE_IS */
|
||||
};
|
||||
/***********************************************************/
|
||||
|
||||
|
@ -764,9 +764,20 @@ XPCConvert::JSValToXPCException(JSContext* cx,
|
|||
}
|
||||
else
|
||||
{
|
||||
// It is a JSObject, but not a wrapped native.
|
||||
// It is a JSObject, but not a wrapped native...
|
||||
|
||||
// If it is an engine Error with an error report then let's
|
||||
// extract the report and build an xpcexception from that
|
||||
const JSErrorReport* report;
|
||||
if(nsnull != (report = JS_ErrorFromException(cx, s)))
|
||||
{
|
||||
const char* message = nsnull;
|
||||
JSString* str;
|
||||
if(nsnull != (str = JS_ValueToString(cx, s)))
|
||||
message = JS_GetStringBytes(str);
|
||||
return JSErrorToXPCException(cx, message, report);
|
||||
}
|
||||
|
||||
// XXX should be able to extract info from 'regular' JS Exceptions
|
||||
|
||||
uintN ignored;
|
||||
JSBool found;
|
||||
|
@ -787,6 +798,12 @@ XPCConvert::JSValToXPCException(JSContext* cx,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// XXX we should do a check against 'js_ErrorClass' here and
|
||||
// do the right thing - even though it has no JSErrorReport,
|
||||
// The fact that it is a JSError exceptions means we can extract
|
||||
// particular info and our 'result' should reflect that.
|
||||
|
||||
// otherwise we'll just try to convert it to a string
|
||||
|
||||
JSString* str = JS_ValueToString(cx, s);
|
||||
|
@ -1042,8 +1059,11 @@ XPCConvert::JSArray2Native(JSContext* cx, void** d, jsval s,
|
|||
{
|
||||
NS_PRECONDITION(d, "bad param");
|
||||
|
||||
// No Action, FRee memory, RElease object
|
||||
enum CleanupMode {na, fr, re};
|
||||
CleanupMode cleanupMode;
|
||||
|
||||
JSObject* jsarray = nsnull;
|
||||
void* array = nsnull;
|
||||
JSUint32 initedCount;
|
||||
jsval current;
|
||||
|
@ -1054,6 +1074,18 @@ XPCConvert::JSArray2Native(JSContext* cx, void** d, jsval s,
|
|||
|
||||
if(JSVAL_IS_VOID(s) || JSVAL_IS_NULL(s))
|
||||
{
|
||||
if(0 != count)
|
||||
{
|
||||
if(pErr)
|
||||
*pErr = NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
// If a non-zero capacity was indicated then we build an
|
||||
// empty array rather than return nsnull.
|
||||
if(0 != capacity)
|
||||
goto fill_array;
|
||||
|
||||
*d = nsnull;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -1065,7 +1097,7 @@ XPCConvert::JSArray2Native(JSContext* cx, void** d, jsval s,
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSObject* jsarray = JSVAL_TO_OBJECT(s);
|
||||
jsarray = JSVAL_TO_OBJECT(s);
|
||||
if(!JS_IsArrayObject(cx, jsarray))
|
||||
{
|
||||
if(pErr)
|
||||
|
@ -1107,6 +1139,7 @@ XPCConvert::JSArray2Native(JSContext* cx, void** d, jsval s,
|
|||
|
||||
// XXX make extra space at end of char* and wchar* and null termintate
|
||||
|
||||
fill_array:
|
||||
switch(type.TagPart())
|
||||
{
|
||||
case nsXPTType::T_I8 : POPULATE(na, int8); break;
|
||||
|
@ -1167,3 +1200,220 @@ failure:
|
|||
#undef POPULATE
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool
|
||||
XPCConvert::NativeStringWithSize2JS(JSContext* cx,
|
||||
jsval* d, const void* s,
|
||||
const nsXPTType& type,
|
||||
JSUint32 count,
|
||||
nsresult* pErr)
|
||||
{
|
||||
NS_PRECONDITION(s, "bad param");
|
||||
NS_PRECONDITION(d, "bad param");
|
||||
|
||||
if(pErr)
|
||||
*pErr = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
|
||||
|
||||
if(!type.IsPointer())
|
||||
{
|
||||
XPC_LOG_ERROR(("XPCConvert::NativeStringWithSize2JS : unsupported type"));
|
||||
return JS_FALSE;
|
||||
}
|
||||
switch(type.TagPart())
|
||||
{
|
||||
case nsXPTType::T_PSTRING_SIZE_IS:
|
||||
{
|
||||
char* p = *((char**)s);
|
||||
if(!p)
|
||||
break;
|
||||
JSString* str;
|
||||
if(!(str = JS_NewStringCopyN(cx, p, count)))
|
||||
return JS_FALSE;
|
||||
*d = STRING_TO_JSVAL(str);
|
||||
break;
|
||||
}
|
||||
case nsXPTType::T_PWSTRING_SIZE_IS:
|
||||
{
|
||||
jschar* p = *((jschar**)s);
|
||||
if(!p)
|
||||
break;
|
||||
JSString* str;
|
||||
if(!(str = JS_NewUCStringCopyN(cx, p, count)))
|
||||
return JS_FALSE;
|
||||
*d = STRING_TO_JSVAL(str);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
XPC_LOG_ERROR(("XPCConvert::NativeStringWithSize2JS : unsupported type"));
|
||||
return JS_FALSE;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool
|
||||
XPCConvert::JSStringWithSize2Native(JSContext* cx, void* d, jsval s,
|
||||
JSUint32 count, JSUint32 capacity,
|
||||
const nsXPTType& type,
|
||||
JSBool useAllocator,
|
||||
uintN* pErr)
|
||||
{
|
||||
NS_PRECONDITION(s, "bad param");
|
||||
NS_PRECONDITION(d, "bad param");
|
||||
|
||||
JSUint32 len;
|
||||
|
||||
if(pErr)
|
||||
*pErr = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
|
||||
|
||||
if(capacity < count)
|
||||
{
|
||||
if(pErr)
|
||||
*pErr = NS_ERROR_XPC_NOT_ENOUGH_CHARS_IN_STRING;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if(!type.IsPointer())
|
||||
{
|
||||
XPC_LOG_ERROR(("XPCConvert::JSStringWithSize2Native : unsupported type"));
|
||||
return JS_FALSE;
|
||||
}
|
||||
switch(type.TagPart())
|
||||
{
|
||||
case nsXPTType::T_PSTRING_SIZE_IS:
|
||||
{
|
||||
char* bytes=nsnull;
|
||||
JSString* str;
|
||||
|
||||
if(JSVAL_IS_VOID(s) || JSVAL_IS_NULL(s))
|
||||
{
|
||||
if(0 != count)
|
||||
{
|
||||
if(pErr)
|
||||
*pErr = NS_ERROR_XPC_NOT_ENOUGH_CHARS_IN_STRING;
|
||||
return JS_FALSE;
|
||||
}
|
||||
if(type.IsReference())
|
||||
{
|
||||
if(pErr)
|
||||
*pErr = NS_ERROR_XPC_BAD_CONVERT_JS_NULL_REF;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if(useAllocator && 0 != capacity)
|
||||
{
|
||||
len = (capacity + 1) * sizeof(char);
|
||||
if(!(*((void**)d) = nsAllocator::Alloc(len)))
|
||||
return JS_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
// else ...
|
||||
|
||||
*((char**)d) = nsnull;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if(!(str = JS_ValueToString(cx, s))||
|
||||
!(bytes = JS_GetStringBytes(str)))
|
||||
{
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
len = JS_GetStringLength(str);
|
||||
if(len > count)
|
||||
{
|
||||
if(pErr)
|
||||
*pErr = NS_ERROR_XPC_NOT_ENOUGH_CHARS_IN_STRING;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if(len < capacity)
|
||||
len = capacity;
|
||||
|
||||
if(useAllocator)
|
||||
{
|
||||
JSUint32 alloc_len = (len + 1) * sizeof(char);
|
||||
if(!(*((void**)d) = nsAllocator::Alloc(alloc_len)))
|
||||
{
|
||||
return JS_FALSE;
|
||||
}
|
||||
memcpy(*((char**)d), bytes, count);
|
||||
((char**)d)[count] = 0;
|
||||
}
|
||||
else
|
||||
*((char**)d) = bytes;
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
case nsXPTType::T_PWSTRING_SIZE_IS:
|
||||
{
|
||||
jschar* chars=nsnull;
|
||||
JSString* str;
|
||||
|
||||
if(JSVAL_IS_VOID(s) || JSVAL_IS_NULL(s))
|
||||
{
|
||||
if(0 != count)
|
||||
{
|
||||
if(pErr)
|
||||
*pErr = NS_ERROR_XPC_NOT_ENOUGH_CHARS_IN_STRING;
|
||||
return JS_FALSE;
|
||||
}
|
||||
if(type.IsReference())
|
||||
{
|
||||
if(pErr)
|
||||
*pErr = NS_ERROR_XPC_BAD_CONVERT_JS_NULL_REF;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if(useAllocator && 0 != capacity)
|
||||
{
|
||||
len = (capacity + 1) * sizeof(jschar);
|
||||
if(!(*((void**)d) = nsAllocator::Alloc(len)))
|
||||
return JS_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// else ...
|
||||
*((jschar**)d) = nsnull;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if(!(str = JS_ValueToString(cx, s))||
|
||||
!(chars = JS_GetStringChars(str)))
|
||||
{
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
len = JS_GetStringLength(str);
|
||||
if(len > count)
|
||||
{
|
||||
if(pErr)
|
||||
*pErr = NS_ERROR_XPC_NOT_ENOUGH_CHARS_IN_STRING;
|
||||
return JS_FALSE;
|
||||
}
|
||||
if(len < capacity)
|
||||
len = capacity;
|
||||
|
||||
if(useAllocator)
|
||||
{
|
||||
JSUint32 alloc_len = (len + 1) * sizeof(jschar);
|
||||
if(!(*((void**)d) = nsAllocator::Alloc(alloc_len)))
|
||||
{
|
||||
// XXX should report error
|
||||
return JS_FALSE;
|
||||
}
|
||||
memcpy(*((jschar**)d), chars, alloc_len);
|
||||
((jschar**)d)[count] = 0;
|
||||
}
|
||||
else
|
||||
*((jschar**)d) = chars;
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
default:
|
||||
XPC_LOG_ERROR(("XPCConvert::JSStringWithSize2Native : unsupported type"));
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ struct ResultMap {nsresult rv; const char* name; const char* format;} map[] = {
|
|||
#define XPC_MSG_DEF(val, format) \
|
||||
{(val), #val, format},
|
||||
#include "xpc.msg"
|
||||
#undef MSG_DEF
|
||||
#undef XPC_MSG_DEF
|
||||
{0,0,0} // sentinel to mark end of array
|
||||
};
|
||||
|
||||
|
|
|
@ -66,9 +66,9 @@ nsJSID::nsJSID()
|
|||
nsJSID::~nsJSID()
|
||||
{
|
||||
if(mNumber && mNumber != gNoString)
|
||||
delete [] mNumber;
|
||||
PR_Free(mNumber);
|
||||
if(mName && mName != gNoString)
|
||||
delete [] mName;
|
||||
PR_Free(mName);
|
||||
}
|
||||
|
||||
void nsJSID::Reset()
|
||||
|
@ -76,9 +76,9 @@ void nsJSID::Reset()
|
|||
mID = GetInvalidIID();
|
||||
|
||||
if(mNumber && mNumber != gNoString)
|
||||
delete [] mNumber;
|
||||
PR_Free(mNumber);
|
||||
if(mName && mName != gNoString)
|
||||
delete [] mName;
|
||||
PR_Free(mName);
|
||||
|
||||
mNumber = mName = nsnull;
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ nsJSID::SetName(const char* name)
|
|||
NS_ASSERTION(!mName || mName == gNoString ,"name already set");
|
||||
NS_ASSERTION(name,"null name");
|
||||
int len = strlen(name)+1;
|
||||
mName = new char[len];
|
||||
mName = (char*)PR_Malloc(len);
|
||||
if(!mName)
|
||||
return PR_FALSE;
|
||||
memcpy(mName, name, len);
|
||||
|
@ -1065,7 +1065,7 @@ xpc_NewIDObject(JSContext *cx, const nsID& aID)
|
|||
if(idString)
|
||||
{
|
||||
nsJSID* iid = nsJSID::NewID(idString);
|
||||
delete [] idString;
|
||||
nsCRT::free(idString);
|
||||
if(iid)
|
||||
{
|
||||
nsXPConnect* xpc = nsXPConnect::GetXPConnect();
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
#include "xpcexception.h"
|
||||
#include "xpcjsid.h"
|
||||
#include "prlong.h"
|
||||
#include "prmem.h"
|
||||
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "prthread.h"
|
||||
|
@ -801,6 +802,18 @@ public:
|
|||
JSBool useAllocator, const nsID* iid,
|
||||
uintN* pErr);
|
||||
|
||||
static JSBool NativeStringWithSize2JS(JSContext* cx,
|
||||
jsval* d, const void* s,
|
||||
const nsXPTType& type,
|
||||
JSUint32 count,
|
||||
nsresult* pErr);
|
||||
|
||||
static JSBool JSStringWithSize2Native(JSContext* cx, void* d, jsval s,
|
||||
JSUint32 count, JSUint32 capacity,
|
||||
const nsXPTType& type,
|
||||
JSBool useAllocator,
|
||||
uintN* pErr);
|
||||
|
||||
static nsIXPCException* JSValToXPCException(JSContext* cx,
|
||||
jsval s,
|
||||
const char* ifaceName,
|
||||
|
|
|
@ -519,8 +519,13 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
|
|||
const nsXPTParamInfo& param = info->GetParam(i);
|
||||
const nsXPTType& type = param.GetType();
|
||||
nsXPTType datum_type;
|
||||
JSUint32 array_count;
|
||||
PRBool isArray = type.IsArray();
|
||||
jsval val;
|
||||
PRBool isSizedString = isArray ?
|
||||
JS_FALSE :
|
||||
type.TagPart() == nsXPTType::T_PSTRING_SIZE_IS ||
|
||||
type.TagPart() == nsXPTType::T_PWSTRING_SIZE_IS;
|
||||
|
||||
if(isArray)
|
||||
{
|
||||
|
@ -547,21 +552,30 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
|
|||
&iidIsOwned, &conditional_iid))
|
||||
goto pre_call_clean_up;
|
||||
|
||||
|
||||
if(isArray)
|
||||
if(isArray || isSizedString)
|
||||
{
|
||||
JSUint32 array_count;
|
||||
|
||||
if(!GetArraySizeFromParam(cx, info, param, methodIndex,
|
||||
i, GET_LENGTH, nativeParams,
|
||||
&array_count))
|
||||
goto pre_call_clean_up;
|
||||
}
|
||||
|
||||
if(isArray)
|
||||
{
|
||||
|
||||
if(!XPCConvert::NativeArray2JS(cx, &val, (const void**)&pv->val,
|
||||
datum_type, conditional_iid,
|
||||
array_count, nsnull))
|
||||
goto pre_call_clean_up;
|
||||
}
|
||||
else if(isSizedString)
|
||||
{
|
||||
if(!XPCConvert::NativeStringWithSize2JS(cx, &val,
|
||||
(const void*)&pv->val,
|
||||
datum_type,
|
||||
array_count, nsnull))
|
||||
goto pre_call_clean_up;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!XPCConvert::NativeData2JS(cx, &val, &pv->val, type,
|
||||
|
@ -830,9 +844,14 @@ pre_call_clean_up:
|
|||
jsval val;
|
||||
nsXPTCMiniVariant* pv;
|
||||
nsXPTType datum_type;
|
||||
PRBool isArray = type.IsArray();
|
||||
JSBool useAllocator = JS_FALSE;
|
||||
|
||||
JSUint32 array_count;
|
||||
PRBool isArray = type.IsArray();
|
||||
PRBool isSizedString = isArray ?
|
||||
JS_FALSE :
|
||||
type.TagPart() == nsXPTType::T_PSTRING_SIZE_IS ||
|
||||
type.TagPart() == nsXPTType::T_PWSTRING_SIZE_IS;
|
||||
|
||||
pv = (nsXPTCMiniVariant*) nativeParams[i].val.p;
|
||||
|
||||
if(param.IsRetval())
|
||||
|
@ -863,19 +882,32 @@ pre_call_clean_up:
|
|||
else if(type.IsPointer() && !param.IsShared())
|
||||
useAllocator = JS_TRUE;
|
||||
|
||||
if(isArray)
|
||||
if(isArray || isSizedString)
|
||||
{
|
||||
JSUint32 array_count;
|
||||
if(!GetArraySizeFromParam(cx, info, param, methodIndex,
|
||||
i, GET_LENGTH, nativeParams,
|
||||
&array_count) ||
|
||||
!XPCConvert::JSArray2Native(cx, (void**)&pv->val, val,
|
||||
&array_count))
|
||||
HANDLE_OUT_CONVERSION_FAILURE;
|
||||
}
|
||||
|
||||
if(isArray)
|
||||
{
|
||||
if(!XPCConvert::JSArray2Native(cx, (void**)&pv->val, val,
|
||||
array_count, array_count,
|
||||
datum_type,
|
||||
useAllocator, conditional_iid,
|
||||
nsnull))
|
||||
HANDLE_OUT_CONVERSION_FAILURE;
|
||||
}
|
||||
else if(isSizedString)
|
||||
{
|
||||
if(!XPCConvert::JSStringWithSize2Native(cx,
|
||||
(void*)&pv->val, val,
|
||||
array_count, array_count,
|
||||
datum_type, useAllocator,
|
||||
nsnull))
|
||||
HANDLE_OUT_CONVERSION_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!XPCConvert::JSData2Native(cx, &pv->val, val, type,
|
||||
|
|
|
@ -648,6 +648,11 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
|||
JSBool useAllocator = JS_FALSE;
|
||||
PRBool isArray = type.IsArray();
|
||||
|
||||
PRBool isSizedString = isArray ?
|
||||
JS_FALSE :
|
||||
type.TagPart() == nsXPTType::T_PSTRING_SIZE_IS ||
|
||||
type.TagPart() == nsXPTType::T_PWSTRING_SIZE_IS;
|
||||
|
||||
nsXPTCVariant* dp = &dispatchParams[i];
|
||||
dp->type = type;
|
||||
|
||||
|
@ -711,8 +716,13 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
|||
}
|
||||
}
|
||||
|
||||
if(datum_type.IsInterfacePointer() &&
|
||||
!GetInterfaceTypeFromParam(cx, info, desc, param, vtblIndex,
|
||||
i, datum_type, dispatchParams,
|
||||
&conditional_iid))
|
||||
goto done;
|
||||
|
||||
if(isArray)
|
||||
if(isArray || isSizedString)
|
||||
{
|
||||
if(!GetArraySizeFromParam(cx, info, desc, param, vtblIndex, i,
|
||||
GET_SIZE, dispatchParams,
|
||||
|
@ -722,32 +732,37 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
|||
&array_count))
|
||||
goto done;
|
||||
|
||||
if(datum_type.IsInterfacePointer() &&
|
||||
!GetInterfaceTypeFromParam(cx, info, desc, param, vtblIndex,
|
||||
i, datum_type, dispatchParams,
|
||||
&conditional_iid))
|
||||
goto done;
|
||||
|
||||
if(!XPCConvert::JSArray2Native(cx, (void**)&dp->val, src,
|
||||
array_count, array_capacity,
|
||||
datum_type,
|
||||
useAllocator, conditional_iid, &err))
|
||||
if(isArray)
|
||||
{
|
||||
// XXX need exception scheme for arrays to indicate bad element
|
||||
ThrowBadParamException(err, cx, desc, i);
|
||||
goto done;
|
||||
if(!XPCConvert::JSArray2Native(cx, (void**)&dp->val, src,
|
||||
array_count, array_capacity,
|
||||
datum_type,
|
||||
useAllocator,
|
||||
conditional_iid, &err))
|
||||
{
|
||||
// XXX need exception scheme for arrays to indicate bad element
|
||||
ThrowBadParamException(err, cx, desc, i);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else // if(isSizedString)
|
||||
{
|
||||
if(!XPCConvert::JSStringWithSize2Native(cx, (void*)&dp->val,
|
||||
src,
|
||||
array_count, array_capacity,
|
||||
datum_type, useAllocator,
|
||||
&err))
|
||||
{
|
||||
ThrowBadParamException(err, cx, desc, i);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(datum_type.IsInterfacePointer() &&
|
||||
!GetInterfaceTypeFromParam(cx, info, desc, param, vtblIndex,
|
||||
i, datum_type, dispatchParams,
|
||||
&conditional_iid))
|
||||
goto done;
|
||||
|
||||
if(!XPCConvert::JSData2Native(cx, &dp->val, src, type,
|
||||
useAllocator, conditional_iid, &err))
|
||||
useAllocator, conditional_iid,
|
||||
&err))
|
||||
{
|
||||
ThrowBadParamException(err, cx, desc, i);
|
||||
goto done;
|
||||
|
@ -785,6 +800,10 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
|||
JSUint32 array_count;
|
||||
nsXPTType datum_type;
|
||||
PRBool isArray = type.IsArray();
|
||||
PRBool isSizedString = isArray ?
|
||||
JS_FALSE :
|
||||
type.TagPart() == nsXPTType::T_PSTRING_SIZE_IS ||
|
||||
type.TagPart() == nsXPTType::T_PWSTRING_SIZE_IS;
|
||||
|
||||
if(isArray)
|
||||
{
|
||||
|
@ -798,7 +817,7 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
|||
else
|
||||
datum_type = type;
|
||||
|
||||
if(isArray)
|
||||
if(isArray || isSizedString)
|
||||
{
|
||||
if(!GetArraySizeFromParam(cx, info, desc, param, vtblIndex, i,
|
||||
GET_LENGTH, dispatchParams,
|
||||
|
@ -823,6 +842,17 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
|||
goto done;
|
||||
}
|
||||
}
|
||||
else if (isSizedString)
|
||||
{
|
||||
if(!XPCConvert::NativeStringWithSize2JS(cx, &v,
|
||||
(const void*)&dp->val,
|
||||
datum_type,
|
||||
array_count, &err))
|
||||
{
|
||||
ThrowBadParamException(err, cx, desc, i);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!XPCConvert::NativeData2JS(cx, &v, &dp->val, datum_type,
|
||||
|
|
|
@ -251,6 +251,39 @@ xpcarraytest::ReverseStringArray(PRUint32 count, char ***valueArray)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void PrintStringWithSize (in PRUint32 count, [size_is (count)] in string str); */
|
||||
NS_IMETHODIMP
|
||||
xpcarraytest::PrintStringWithSize(PRUint32 count, const char *str)
|
||||
{
|
||||
if(mReceiver)
|
||||
return mReceiver->PrintStringWithSize(count, str);
|
||||
printf("\"%s\" : %d\n", str, count);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void DoubleString (inout PRUint32 count, [size_is (count)] inout string str); */
|
||||
NS_IMETHODIMP
|
||||
xpcarraytest::DoubleString(PRUint32 *count, char **str)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(str);
|
||||
if(mReceiver)
|
||||
return mReceiver->DoubleString(count, str);
|
||||
if(!count || !*count)
|
||||
return NS_OK;
|
||||
|
||||
char* out = (char*) nsAllocator::Alloc(((*count * 2)+1) * sizeof(char));
|
||||
if(!out)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
for(PRUint32 k = 0; k < *count; k++)
|
||||
out[k*2] = out[(k*2)+1] = (*str)[k];
|
||||
out[k*2] = '\0';
|
||||
nsAllocator::Free(*str);
|
||||
*str = out;
|
||||
*count = *count * 2;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
// static
|
||||
|
|
|
@ -130,6 +130,18 @@ var jsobj = {
|
|||
|
||||
result.value = [this, this];
|
||||
count.value = 2;
|
||||
},
|
||||
PrintStringWithSize : function(len, a) {
|
||||
print("\""+a+"\""+" ; "+len);
|
||||
},
|
||||
DoubleString : function(len, s) {
|
||||
var out = "";
|
||||
for(var k = 0; k < s.value.length; k++) {
|
||||
out += s.value.charAt(k);
|
||||
out += s.value.charAt(k);
|
||||
}
|
||||
len.value *= 2;
|
||||
s.value = out;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -201,3 +213,26 @@ for(i = 0; i < count.value; i++)
|
|||
ifaces.value[i].PrintIntegerArray(a.length, a);
|
||||
|
||||
print("-------------------------------------------");
|
||||
print("-------------------------------------------");
|
||||
print("-------------------------------------------");
|
||||
|
||||
obj.SetReceiver(null);
|
||||
str = "This is a string";
|
||||
obj.PrintStringWithSize(str.length, str);
|
||||
obj.SetReceiver(jsobj);
|
||||
obj.PrintStringWithSize(str.length, str);
|
||||
|
||||
var str2 = {value : "double me baby"};
|
||||
var len2 = {value : str2.value.length};
|
||||
obj.SetReceiver(null);
|
||||
print("\""+str2.value+"\""+" : "+len2.value);
|
||||
obj.DoubleString(len2, str2);
|
||||
print("\""+str2.value+"\""+" : "+len2.value);
|
||||
|
||||
var str2 = {value : "double me baby"};
|
||||
var len2 = {value : str2.value.length};
|
||||
obj.SetReceiver(jsobj);
|
||||
print("\""+str2.value+"\""+" ; "+len2.value);
|
||||
obj.DoubleString(len2, str2);
|
||||
print("\""+str2.value+"\""+" ; "+len2.value);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче