bug 66610 - add xpconnect support for DOMStrings. r=jst sr=brendan

This commit is contained in:
jband%netscape.com 2001-02-20 08:09:19 +00:00
Родитель c608cd4fc1
Коммит d242dcca69
10 изменённых файлов: 247 добавлений и 42 удалений

Просмотреть файл

@ -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, &param, 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))