зеркало из https://github.com/mozilla/gecko-dev.git
bug 66610 - add xpconnect support for DOMStrings. r=jst sr=brendan
This commit is contained in:
Родитель
c608cd4fc1
Коммит
d242dcca69
|
@ -90,7 +90,7 @@ static uint8 xpc_reflectable_flags[XPC_FLAG_COUNT] = {
|
|||
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_DOMSTRING */
|
||||
XPC_MK_FLAG( 0 , 1 , 0 , 0 ), /* T_DOMSTRING */
|
||||
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 */
|
||||
|
@ -347,9 +347,35 @@ XPCConvert::NativeData2JS(JSContext* cx, jsval* d, const void* s,
|
|||
}
|
||||
|
||||
case nsXPTType::T_DOMSTRING:
|
||||
// XXX implement DOMSTRING
|
||||
XPC_LOG_ERROR(("XPCConvert::NativeData2JS : DOMSTRING params not supported"));
|
||||
return JS_FALSE;
|
||||
{
|
||||
const nsAReadableString* p = *((const nsAReadableString**)s);
|
||||
if(!p)
|
||||
break;
|
||||
|
||||
PRUint32 length = p->Length();
|
||||
|
||||
jschar* chars = (jschar *)
|
||||
JS_malloc(cx, (length + 1) * sizeof(jschar));
|
||||
if(!chars)
|
||||
return JS_FALSE;
|
||||
|
||||
if(length && !CopyUnicodeTo(*p, 0, (PRUnichar*)chars, length))
|
||||
{
|
||||
JS_free(cx, chars);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
chars[length] = 0;
|
||||
|
||||
JSString* str;
|
||||
if(!(str = JS_NewUCString(cx, chars, length)))
|
||||
{
|
||||
JS_free(cx, chars);
|
||||
return JS_FALSE;
|
||||
}
|
||||
*d = STRING_TO_JSVAL(str);
|
||||
break;
|
||||
}
|
||||
|
||||
case nsXPTType::T_CHAR_STR:
|
||||
{
|
||||
|
@ -586,9 +612,74 @@ XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
|
|||
}
|
||||
|
||||
case nsXPTType::T_DOMSTRING:
|
||||
// XXX implement DOMSTRING
|
||||
XPC_LOG_ERROR(("XPCConvert::JSData2Native : DOMSTRING params not supported"));
|
||||
return JS_FALSE;
|
||||
{
|
||||
static const NS_NAMED_LITERAL_STRING(sEmptyString, "");
|
||||
static const NS_NAMED_LITERAL_STRING(sNullString, "null");
|
||||
static const NS_NAMED_LITERAL_STRING(sVoidString, "undefined");
|
||||
|
||||
const PRUnichar* chars;
|
||||
PRUint32 length;
|
||||
JSBool isNewString = JS_FALSE;
|
||||
|
||||
if(JSVAL_IS_VOID(s))
|
||||
{
|
||||
chars = sVoidString.get();
|
||||
length = sVoidString.Length();
|
||||
}
|
||||
else if(JSVAL_IS_NULL(s))
|
||||
{
|
||||
// XXX We don't yet have a way to represent a null nsAXXXString
|
||||
// XXX Do we *want* to use "null"?
|
||||
chars = sNullString.get();
|
||||
length = sNullString.Length();
|
||||
}
|
||||
else
|
||||
{
|
||||
JSString* str = JS_ValueToString(cx, s);
|
||||
if(!str)
|
||||
return JS_FALSE;
|
||||
|
||||
length = (PRUint32) JS_GetStringLength(str);
|
||||
if(length)
|
||||
{
|
||||
chars = (const PRUnichar*) JS_GetStringChars(str);
|
||||
if(!chars)
|
||||
return JS_FALSE;
|
||||
if(STRING_TO_JSVAL(str) != s)
|
||||
isNewString = JS_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
chars = sEmptyString.get();
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERTION(chars, "I must be really confused");
|
||||
|
||||
if(useAllocator)
|
||||
{
|
||||
nsAReadableString* rs;
|
||||
|
||||
// If the underlying JSString may have been created in the
|
||||
// JS_ValueToString call, then we need to make a copied string
|
||||
// to avoid the possibility of the string data being gc'd before
|
||||
// we are done.
|
||||
if(isNewString)
|
||||
rs = new nsString(chars, length);
|
||||
else
|
||||
rs = new nsLiteralString(chars, length);
|
||||
|
||||
if(!rs)
|
||||
return JS_FALSE;
|
||||
*((nsAReadableString**)d) = rs;
|
||||
}
|
||||
else
|
||||
{
|
||||
nsAWritableString* ws = *((nsAWritableString**)d);
|
||||
ws->Assign(chars);
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
case nsXPTType::T_CHAR_STR:
|
||||
{
|
||||
|
|
|
@ -1067,7 +1067,7 @@ pre_call_clean_up:
|
|||
for(i = 0; i < paramCount; i++)
|
||||
{
|
||||
const nsXPTParamInfo& param = info->GetParam(i);
|
||||
if(!param.IsOut())
|
||||
if(!param.IsOut() && !param.IsDipper())
|
||||
continue;
|
||||
|
||||
const nsXPTType& type = param.GetType();
|
||||
|
@ -1082,7 +1082,10 @@ pre_call_clean_up:
|
|||
JSBool useAllocator = JS_FALSE;
|
||||
nsXPTCMiniVariant* pv;
|
||||
|
||||
pv = (nsXPTCMiniVariant*) nativeParams[i].val.p;
|
||||
if(param.IsDipper())
|
||||
pv = (nsXPTCMiniVariant*) &nativeParams[i].val.p;
|
||||
else
|
||||
pv = (nsXPTCMiniVariant*) nativeParams[i].val.p;
|
||||
|
||||
if(param.IsRetval())
|
||||
val = result;
|
||||
|
@ -1100,7 +1103,7 @@ pre_call_clean_up:
|
|||
HANDLE_OUT_CONVERSION_FAILURE;
|
||||
iidIsOwned = JS_TRUE;
|
||||
}
|
||||
else if(type.IsPointer() && !param.IsShared())
|
||||
else if(type.IsPointer() && !param.IsShared() && !param.IsDipper())
|
||||
useAllocator = JS_TRUE;
|
||||
|
||||
if(!XPCConvert::JSData2Native(cx, &pv->val, val, type,
|
||||
|
|
|
@ -271,15 +271,6 @@ nsXPCWrappedNativeClass::BuildMemberDescriptors(XPCContext* xpcc)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
void
|
||||
nsXPCWrappedNativeClass::XPCContextBeingDestroyed()
|
||||
{
|
||||
DestroyMemberDescriptors();
|
||||
mXPCContext = nsnull;
|
||||
}
|
||||
*/
|
||||
|
||||
void
|
||||
nsXPCWrappedNativeClass::DestroyMemberDescriptors()
|
||||
{
|
||||
|
@ -666,7 +657,7 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
|||
for(i = 0; i < paramCount; i++)
|
||||
{
|
||||
nsXPTCVariant* dp = &dispatchParams[i];
|
||||
dp->flags = 0;
|
||||
dp->ClearFlags();
|
||||
dp->val.p = nsnull;
|
||||
}
|
||||
|
||||
|
@ -693,7 +684,7 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
|||
|
||||
if(type_tag == nsXPTType::T_INTERFACE)
|
||||
{
|
||||
dp->flags |= nsXPTCVariant::VAL_IS_IFACE;
|
||||
dp->SetValIsInterface();
|
||||
}
|
||||
|
||||
// set 'src' to be the object from which we get the value and
|
||||
|
@ -701,7 +692,7 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
|||
|
||||
if(param.IsOut())
|
||||
{
|
||||
dp->flags |= nsXPTCVariant::PTR_IS_DATA;
|
||||
dp->SetPtrIsData();
|
||||
dp->ptr = &dp->val;
|
||||
|
||||
if(!param.IsRetval() &&
|
||||
|
@ -720,7 +711,7 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
|||
!param.IsShared())
|
||||
{
|
||||
useAllocator = JS_TRUE;
|
||||
dp->flags |= nsXPTCVariant::VAL_IS_OWNED;
|
||||
dp->SetValIsAllocated();
|
||||
}
|
||||
|
||||
if(!param.IsIn())
|
||||
|
@ -728,14 +719,43 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
|||
}
|
||||
else
|
||||
{
|
||||
src = argv[i];
|
||||
|
||||
if(type.IsPointer() &&
|
||||
type_tag == nsXPTType::T_IID)
|
||||
if(type.IsPointer())
|
||||
{
|
||||
useAllocator = JS_TRUE;
|
||||
dp->flags |= nsXPTCVariant::VAL_IS_OWNED;
|
||||
switch(type_tag)
|
||||
{
|
||||
case nsXPTType::T_IID:
|
||||
dp->SetValIsAllocated();
|
||||
useAllocator = JS_TRUE;
|
||||
break;
|
||||
|
||||
case nsXPTType::T_DOMSTRING:
|
||||
dp->SetValIsDOMString();
|
||||
if(param.IsDipper())
|
||||
{
|
||||
// Is an 'out' DOMString. Make a new nsAWritableString
|
||||
// now and then continue in order to skip the call to
|
||||
// JSData2Native
|
||||
if(!(dp->val.p = new nsString()))
|
||||
{
|
||||
JS_ReportOutOfMemory(cx);
|
||||
goto done;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// else...
|
||||
|
||||
// Is an 'in' DOMString. Set 'useAllocator' to indicate
|
||||
// that JSData2Native should allocate a new
|
||||
// nsAReadableString.
|
||||
useAllocator = JS_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Do this *after* the above because in the case where we have a
|
||||
// "T_DOMSTRING && IsDipper()" then argv might be null since this
|
||||
// is really an 'out' param masquerading as an 'in' param.
|
||||
src = argv[i];
|
||||
}
|
||||
|
||||
if(type_tag == nsXPTType::T_INTERFACE &&
|
||||
|
@ -788,7 +808,7 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
|||
|
||||
if(isArray)
|
||||
{
|
||||
dp->flags |= nsXPTCVariant::VAL_IS_ARRAY;
|
||||
dp->SetValIsArray();
|
||||
|
||||
if(NS_FAILED(mInfo->GetTypeForParam(vtblIndex, ¶m, 1,
|
||||
&datum_type)))
|
||||
|
@ -802,7 +822,7 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
|||
|
||||
if(datum_type.IsInterfacePointer())
|
||||
{
|
||||
dp->flags |= nsXPTCVariant::VAL_IS_IFACE;
|
||||
dp->SetValIsInterface();
|
||||
}
|
||||
|
||||
// set 'src' to be the object from which we get the value and
|
||||
|
@ -810,7 +830,7 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
|||
|
||||
if(param.IsOut())
|
||||
{
|
||||
dp->flags |= nsXPTCVariant::PTR_IS_DATA;
|
||||
dp->SetPtrIsData();
|
||||
dp->ptr = &dp->val;
|
||||
|
||||
if(!param.IsRetval() &&
|
||||
|
@ -828,7 +848,7 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
|||
(isArray || !param.IsShared()))
|
||||
{
|
||||
useAllocator = JS_TRUE;
|
||||
dp->flags |= nsXPTCVariant::VAL_IS_OWNED;
|
||||
dp->SetValIsAllocated();
|
||||
}
|
||||
|
||||
if(!param.IsIn())
|
||||
|
@ -842,7 +862,7 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
|||
datum_type.TagPart() == nsXPTType::T_IID)
|
||||
{
|
||||
useAllocator = JS_TRUE;
|
||||
dp->flags |= nsXPTCVariant::VAL_IS_OWNED;
|
||||
dp->SetValIsAllocated();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -940,7 +960,7 @@ nsXPCWrappedNativeClass::CallWrappedMethod(JSContext* cx,
|
|||
for(i = 0; i < paramCount; i++)
|
||||
{
|
||||
const nsXPTParamInfo& param = info->GetParam(i);
|
||||
if(!param.IsOut())
|
||||
if(!param.IsOut() && !param.IsDipper())
|
||||
continue;
|
||||
|
||||
const nsXPTType& type = param.GetType();
|
||||
|
@ -1054,7 +1074,7 @@ done:
|
|||
if(dp->IsValArray())
|
||||
{
|
||||
// going to have to cleanup the array and perhaps its contents
|
||||
if(dp->IsValOwned() || dp->IsValInterface())
|
||||
if(dp->IsValAllocated() || dp->IsValInterface())
|
||||
{
|
||||
// we need to figure out how many elements are present.
|
||||
JSUint32 array_count;
|
||||
|
@ -1067,7 +1087,7 @@ done:
|
|||
NS_ASSERTION(0,"failed to get array length, we'll leak here");
|
||||
continue;
|
||||
}
|
||||
if(dp->IsValOwned())
|
||||
if(dp->IsValAllocated())
|
||||
{
|
||||
void** a = (void**)p;
|
||||
for(JSUint32 k = 0; k < array_count; k++)
|
||||
|
@ -1089,10 +1109,12 @@ done:
|
|||
// always free the array itself
|
||||
nsMemory::Free(p);
|
||||
}
|
||||
else if(dp->IsValOwned())
|
||||
else if(dp->IsValAllocated())
|
||||
nsMemory::Free(p);
|
||||
else if(dp->IsValInterface())
|
||||
((nsISupports*)p)->Release();
|
||||
else if(dp->IsValDOMString())
|
||||
delete (nsAReadableString*)p;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "nsMemory.h"
|
||||
#include "nsIXPCSecurityManager.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsAWritableString.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsgc.h" // for js_ForceGC
|
||||
|
|
|
@ -102,6 +102,22 @@ NS_IMETHODIMP xpctestEcho::In2OutOneInt(int input, int* output)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* DOMString In2OutOneDOMString (in DOMString input); */
|
||||
NS_IMETHODIMP xpctestEcho::In2OutOneDOMString(const nsAReadableString & input,
|
||||
nsAWritableString & _retval)
|
||||
{
|
||||
_retval.Assign(input);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* DOMString EchoIn2OutOneDOMString (in DOMString input); */
|
||||
NS_IMETHODIMP xpctestEcho::EchoIn2OutOneDOMString(const nsAReadableString & input, nsAWritableString & _retval)
|
||||
{
|
||||
if(mReceiver)
|
||||
return mReceiver->EchoIn2OutOneDOMString(input, _retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP xpctestEcho::In2OutAddTwoInts(int input1,
|
||||
int input2,
|
||||
int* output1,
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "nsIGenericFactory.h"
|
||||
#include "nscore.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAWritableString.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "xpctest.h"
|
||||
|
|
|
@ -66,6 +66,10 @@ interface nsIEcho : nsISupports {
|
|||
out long output1, out long output2);
|
||||
|
||||
string In2OutOneString(in string input);
|
||||
|
||||
DOMString In2OutOneDOMString(in DOMString input);
|
||||
DOMString EchoIn2OutOneDOMString(in DOMString input);
|
||||
|
||||
void SimpleCallNoEcho();
|
||||
void SendManyTypes(in octet p1,
|
||||
in short p2,
|
||||
|
|
|
@ -70,6 +70,12 @@ receiver.SendManyTypes = function()
|
|||
receiver_results[i] = arguments[i];
|
||||
};
|
||||
|
||||
receiver.EchoIn2OutOneDOMString = function(input)
|
||||
{
|
||||
// print("EchoIn2OutOneDOMString called with: "+input);
|
||||
return input;
|
||||
};
|
||||
|
||||
echo.SetReceiver(receiver);
|
||||
|
||||
////////////////////
|
||||
|
@ -217,6 +223,31 @@ for(i = 0; i < 16; i++) {
|
|||
if(all_ok)
|
||||
print("SendInOutManyTypes - passed");
|
||||
|
||||
////////////////////
|
||||
|
||||
var test_string3 = "And this is yet again some other string 3";
|
||||
var test_string4 = "And this is yet again some other string 4";
|
||||
|
||||
print("In2OutOneDOMString - "+(
|
||||
echo.In2OutOneDOMString(test_string3) == test_string3
|
||||
? "passed" : "failed"));
|
||||
|
||||
print("EchoIn2OutOneDOMString - "+(
|
||||
echo.EchoIn2OutOneDOMString(test_string4) == test_string4
|
||||
? "passed" : "failed"));
|
||||
|
||||
print("EchoIn2OutOneDOMString of empty string - "+(
|
||||
echo.EchoIn2OutOneDOMString("") == ""
|
||||
? "passed" : "failed"));
|
||||
|
||||
print("EchoIn2OutOneDOMString of null - "+(
|
||||
echo.EchoIn2OutOneDOMString(null) == "null"
|
||||
? "passed" : "failed"));
|
||||
|
||||
print("EchoIn2OutOneDOMString of undefined - "+(
|
||||
echo.EchoIn2OutOneDOMString(this.propertyThatDoesNotExist) == "undefined"
|
||||
? "passed" : "failed"));
|
||||
|
||||
////////////////////
|
||||
// check exceptions on xpcom error code
|
||||
|
||||
|
@ -373,7 +404,7 @@ foo = bar = iface = clazz = null;
|
|||
print(".......................................");
|
||||
print("simple speed tests...");
|
||||
|
||||
var iterations = 1000;
|
||||
var iterations = 5000;
|
||||
|
||||
var receiver2 = new Object();
|
||||
receiver2.SetReceiver = function() {};
|
||||
|
@ -462,6 +493,8 @@ send_params = null;
|
|||
start_time = null;
|
||||
test_string = null;
|
||||
test_string2 = null;
|
||||
test_string3 = null;
|
||||
test_string4 = null;
|
||||
nsNativeEcho = null;
|
||||
gc();
|
||||
gc();
|
||||
|
|
|
@ -99,15 +99,24 @@ struct nsXPTCVariant : public nsXPTCMiniVariant
|
|||
{
|
||||
// these are bitflags!
|
||||
PTR_IS_DATA = 0x1, // ptr points to 'real' data in val
|
||||
VAL_IS_OWNED = 0x2, // val.p holds alloc'd ptr that must be freed
|
||||
VAL_IS_ALLOCD= 0x2, // val.p holds alloc'd ptr that must be freed
|
||||
VAL_IS_IFACE = 0x4, // val.p holds interface ptr that must be released
|
||||
VAL_IS_ARRAY = 0x8 // val.p holds a pointer to an array needing cleanup
|
||||
VAL_IS_ARRAY = 0x8, // val.p holds a pointer to an array needing cleanup
|
||||
VAL_IS_DOMSTR= 0x10 // val.p holds a pointer to domstring needing cleanup
|
||||
};
|
||||
|
||||
void ClearFlags() {flags = 0;}
|
||||
void SetPtrIsData() {flags |= PTR_IS_DATA;}
|
||||
void SetValIsAllocated() {flags |= VAL_IS_ALLOCD;}
|
||||
void SetValIsInterface() {flags |= VAL_IS_IFACE;}
|
||||
void SetValIsArray() {flags |= VAL_IS_ARRAY;}
|
||||
void SetValIsDOMString() {flags |= VAL_IS_DOMSTR;}
|
||||
|
||||
PRBool IsPtrData() const {return (PRBool) (flags & PTR_IS_DATA);}
|
||||
PRBool IsValOwned() const {return (PRBool) (flags & VAL_IS_OWNED);}
|
||||
PRBool IsValAllocated() const {return (PRBool) (flags & VAL_IS_ALLOCD);}
|
||||
PRBool IsValInterface() const {return (PRBool) (flags & VAL_IS_IFACE);}
|
||||
PRBool IsValArray() const {return (PRBool) (flags & VAL_IS_ARRAY);}
|
||||
PRBool IsValDOMString() const {return (PRBool) (flags & VAL_IS_DOMSTR);}
|
||||
|
||||
void Init(const nsXPTCMiniVariant& mv, const nsXPTType& t, PRUint8 f)
|
||||
{
|
||||
|
|
|
@ -507,6 +507,31 @@ verify_method_declaration(IDL_tree method_tree)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* inout is not allowed with "domstring" types
|
||||
*/
|
||||
if (IDL_PARAM_DCL(param).attr == IDL_PARAM_INOUT &&
|
||||
UP_IS_NATIVE(param_type) &&
|
||||
IDL_tree_property_get(param_type, "domstring") != NULL) {
|
||||
IDL_tree_error(method_tree,
|
||||
"[domstring] types cannot be used as inout "
|
||||
"parameters");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* arrays of "domstring" types not allowed
|
||||
*/
|
||||
if (IDL_tree_property_get(simple_decl, "array") != NULL &&
|
||||
UP_IS_NATIVE(param_type) &&
|
||||
IDL_tree_property_get(param_type, "domstring") != NULL) {
|
||||
IDL_tree_error(method_tree,
|
||||
"[domstring] types cannot be used in array "
|
||||
"parameters");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!check_param_attribute(method_tree, param, IID_IS) ||
|
||||
!check_param_attribute(method_tree, param, LENGTH_IS) ||
|
||||
!check_param_attribute(method_tree, param, SIZE_IS))
|
||||
|
|
Загрузка…
Ссылка в новой задаче