Bug 560643 - Part 3, add support for jsval XPIDL type. r=jst, sr=jst.

This commit is contained in:
Jason Orendorff 2010-06-18 15:29:21 -05:00
Родитель 379a1a3599
Коммит 32d2f15ab1
10 изменённых файлов: 107 добавлений и 73 удалений

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

@ -482,7 +482,10 @@ argumentUnboxingTemplates = {
'[cstring]':
" xpc_qsACString ${name}(cx, ${argVal}, ${argPtr});\n"
" if (!${name}.IsValid())\n"
" return JS_FALSE;\n"
" return JS_FALSE;\n",
'[jsval]':
" jsval ${name} = ${argVal};\n"
}
# From JSData2Native.
@ -576,7 +579,7 @@ def writeArgumentUnboxing(f, i, name, type, haveCcx, optional, rvdeclared,
def writeResultDecl(f, type, varname):
if isVoidType(type):
return # nothing to declare
t = unaliasType(type)
if t.kind == 'builtin':
if not t.nativename.endswith('*'):
@ -591,6 +594,8 @@ def writeResultDecl(f, type, varname):
if name in ('[domstring]', '[astring]'):
f.write(" nsString %s;\n" % varname)
return
elif name == '[jsval]':
return # nothing to declare; see special case in outParamForm
elif t.kind in ('interface', 'forward'):
f.write(" nsCOMPtr<%s> %s;\n" % (type.name, varname))
return
@ -603,7 +608,9 @@ def outParamForm(name, type):
if type.kind == 'builtin':
return '&' + name
elif type.kind == 'native':
if type.modifier == 'ref':
if getBuiltinOrNativeTypeName(type) == '[jsval]':
return 'vp'
elif type.modifier == 'ref':
return name
else:
return '&' + name
@ -654,7 +661,12 @@ resultConvTemplates = {
" return xpc_qsStringToJsval(cx, result, ${jsvalPtr});\n",
'[domstring]':
" return xpc_qsStringToJsval(cx, result, ${jsvalPtr});\n"
" return xpc_qsStringToJsval(cx, result, ${jsvalPtr});\n",
'[jsval]':
# Here there's nothing to convert, because the result has already been
# written directly to *rv. See the special case in outParamForm.
" return JS_TRUE;\n"
}
def isVariantType(t):
@ -987,76 +999,52 @@ def writeQuickStub(f, customMethodCalls, member, stubName, isSetter=False):
f.write(callTemplate)
# Only these types can be returned (note: no strings);
# if the type isn't one of these, then traceTypeMap['_default'] is used
# if the type isn't one of these, then defaultTraceType is used
traceReturnTypeMap = {
'void':
["jsval ", "JSVAL", "JSVAL_VOID"],
'boolean':
["JSBool ", "BOOL", "JS_FALSE"],
'short':
["int32 ", "INT32", "0"],
'unsigned short':
["uint32 ", "UINT32", "0"],
'long':
["int32 ", "INT32", "0"],
'unsigned long':
["uint32 ", "UINT32", "0"],
'float':
["jsdouble ", "DOUBLE", "0"],
'double':
["jsdouble ", "DOUBLE", "0"],
'octet':
["uint32 ", "UINT32", "0"]
'void': ("jsval ", "JSVAL", "JSVAL_VOID"),
'boolean': ("JSBool ", "BOOL", "JS_FALSE"),
'short': ("int32 ", "INT32", "0"),
'unsigned short': ("uint32 ", "UINT32", "0"),
'long': ("int32 ", "INT32", "0"),
'unsigned long': ("uint32 ", "UINT32", "0"),
'float': ("jsdouble ", "DOUBLE", "0"),
'double': ("jsdouble ", "DOUBLE", "0"),
'octet': ("uint32 ", "UINT32", "0"),
'jsval': ("jsval ", "JSVAL", "JSVAL_VOID")
}
# This list extends the above list, but includes types that
# are valid for arguments only, namely strings. It also
# includes the default jsval type.
traceTypeMap = {
'[astring]':
["JSString *", "STRING", "nsnull"],
'[domstring]':
["JSString *", "STRING", "nsnull"],
'[cstring]':
["JSString *", "STRING", "nsnull"],
'string':
["JSString *", "STRING", "nsnull"],
'wstring':
["JSString *", "STRING", "nsnull"],
# are valid for arguments only, namely strings.
traceTypeMap = traceReturnTypeMap.copy()
traceTypeMap.update({
'[astring]': ("JSString *", "STRING", "nsnull"),
'[domstring]': ("JSString *", "STRING", "nsnull"),
'[cstring]': ("JSString *", "STRING", "nsnull"),
'string': ("JSString *", "STRING", "nsnull"),
'wstring': ("JSString *", "STRING", "nsnull"),
})
'_default':
["jsval ", "JSVAL", "JSVAL_VOID"]
}
defaultTraceType = ("jsval ", "JSVAL", "JSVAL_VOID")
def getTraceType(type):
type = getBuiltinOrNativeTypeName(type)
traceType = traceReturnTypeMap.get(type) or traceTypeMap.get(type) or traceTypeMap.get("_default")
assert traceType
return traceType[0]
return traceTypeMap.get(type, defaultTraceType)[0]
def getTraceReturnType(type):
type = getBuiltinOrNativeTypeName(type)
traceType = traceReturnTypeMap.get(type) or traceTypeMap.get("_default")
assert traceType
return traceType[0]
return traceReturnTypeMap.get(type, defaultTraceType)[0]
def getTraceInfoType(type):
type = getBuiltinOrNativeTypeName(type)
traceType = traceReturnTypeMap.get(type) or traceTypeMap.get(type) or traceTypeMap.get("_default")
assert traceType
return traceType[1]
return traceTypeMap.get(type, defaultTraceType)[1]
def getTraceInfoReturnType(type):
type = getBuiltinOrNativeTypeName(type)
traceType = traceReturnTypeMap.get(type) or traceTypeMap.get("_default")
assert traceType
return traceType[1]
return traceReturnTypeMap.get(type, defaultTraceType)[1]
def getTraceInfoDefaultReturn(type):
type = getBuiltinOrNativeTypeName(type)
traceType = traceTypeMap.get(type) or traceTypeMap.get("_default")
assert traceType
return traceType[2]
return traceTypeMap.get(type, defaultTraceType)[2]
def getFailureString(retval, indent):
assert indent > 0
@ -1142,7 +1130,7 @@ def writeTraceableArgumentConversion(f, member, i, name, type, haveCcx,
f.write(" xpc_qsSelfRef %sref;\n" % name)
f.write(" rv = xpc_qsUnwrapArg<%s>("
"cx, %s, &%s, &%sref.ptr, &vp.array[%d]);\n"
% (type.name, argVal, name, name, 1 + i))
% (type.name, argVal, name, name, 2 + i))
f.write(" if (NS_FAILED(rv)) {\n")
if haveCcx:
f.write(" xpc_qsThrowBadArgWithCcx(ccx, rv, %d);\n" % i)
@ -1188,6 +1176,8 @@ traceableResultConvTemplates = {
" if (!xpc_qsStringToJsval(cx, result, &rval)) {\n"
" JS_ReportOutOfMemory(cx);\n${errorStr}"
" return rval;\n",
'[jsval]':
" return vp.array[0];\n"
}
def writeTraceableResultConv(f, type):
@ -1264,17 +1254,17 @@ def writeTraceableQuickStub(f, customMethodCalls, member, stubName):
else:
f.write(" %s *self;\n" % customMethodCall['thisType'])
f.write(" xpc_qsSelfRef selfref;\n")
f.write(" xpc_qsArgValArray<%d> vp(cx);\n" % (1 + len(member.params)))
f.write(" xpc_qsArgValArray<%d> vp(cx);\n" % (2 + len(member.params)))
if haveCcx:
f.write(" if (!xpc_qsUnwrapThisFromCcx(ccx, &self, &selfref.ptr, "
"&vp.array[0])) {\n")
"&vp.array[1])) {\n")
elif (member.kind == 'method') and isInterfaceType(member.realtype):
f.write(" XPCLazyCallContext lccx(JS_CALLER, cx, obj);\n")
f.write(" if (!xpc_qsUnwrapThis(cx, obj, callee, &self, &selfref.ptr, "
"&vp.array[0], &lccx)) {\n")
"&vp.array[1], &lccx)) {\n")
else:
f.write(" if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, "
"&vp.array[0], nsnull)) {\n")
"&vp.array[1], nsnull)) {\n")
writeFailure(f, getTraceInfoDefaultReturn(member.realtype), 2)
argNames = []
@ -1314,7 +1304,9 @@ def writeTraceableQuickStub(f, customMethodCalls, member, stubName):
# Call the method.
comName = header.methodNativeName(member)
if not isVoidType(member.realtype):
if getBuiltinOrNativeTypeName(member.realtype) == '[jsval]':
argNames.append("&vp.array[0]")
elif not isVoidType(member.realtype):
argNames.append(outParamForm(resultname, member.realtype))
args = ', '.join(argNames)

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

@ -113,7 +113,7 @@ static uint8 xpc_reflectable_flags[XPC_FLAG_COUNT] = {
XPC_MK_FLAG( 0 , 1 , 0 , 0 ), /* T_UTF8STRING */
XPC_MK_FLAG( 0 , 1 , 0 , 0 ), /* T_CSTRING */
XPC_MK_FLAG( 0 , 1 , 0 , 0 ), /* T_ASTRING */
XPC_MK_FLAG( 0 , 0 , 0 , 0 ), /* 26 - reserved */
XPC_MK_FLAG( 1 , 0 , 1 , 0 ), /* T_JSVAL */
XPC_MK_FLAG( 0 , 0 , 0 , 0 ), /* 27 - reserved */
XPC_MK_FLAG( 0 , 0 , 0 , 0 ), /* 28 - reserved */
XPC_MK_FLAG( 0 , 0 , 0 , 0 ), /* 29 - reserved */
@ -292,6 +292,11 @@ XPCConvert::NativeData2JS(XPCLazyCallContext& lccx, jsval* d, const void* s,
*d = STRING_TO_JSVAL(str);
break;
}
case nsXPTType::T_JSVAL :
*d = *((jsval*)s);
break;
default:
if(!type.IsPointer())
{
@ -480,6 +485,7 @@ XPCConvert::NativeData2JS(XPCLazyCallContext& lccx, jsval* d, const void* s,
}
break;
}
default:
NS_ERROR("bad type");
return JS_FALSE;
@ -617,6 +623,9 @@ XPCConvert::JSData2Native(XPCCallContext& ccx, void* d, jsval s,
*((uint16*)d) = (uint16) chars[0];
break;
}
case nsXPTType::T_JSVAL :
*((jsval*)d) = s;
break;
default:
if(!type.IsPointer())
{

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

@ -2380,8 +2380,11 @@ CallMethodHelper::~CallMethodHelper()
delete (nsCString*) p;
else if(dp->IsValCString())
delete (nsCString*) p;
}
else if(dp->IsValJSRoot())
JS_RemoveRoot(mCallContext, (jsval*)dp->ptr);
}
}
}
JSBool
@ -2565,7 +2568,7 @@ CallMethodHelper::GatherAndConvertResults()
if(paramInfo.IsRetval())
{
if(!mCallContext.GetReturnValueWasSet())
if(!mCallContext.GetReturnValueWasSet() && type.TagPart() != nsXPTType::T_JSVAL)
mCallContext.SetRetVal(v);
}
else if(i < mArgc)
@ -2729,6 +2732,22 @@ CallMethodHelper::ConvertIndependentParams(JSBool* foundDependentParam)
dp->SetPtrIsData();
dp->ptr = &dp->val;
if (type_tag == nsXPTType::T_JSVAL)
{
if (paramInfo.IsRetval())
{
dp->ptr = mCallContext.GetRetVal();
}
else
{
jsval *rootp = (jsval *)&dp->val.p;
dp->ptr = rootp;
*rootp = JSVAL_VOID;
if (!JS_AddRoot(mCallContext, rootp))
return JS_FALSE;
}
}
if(type.IsPointer() &&
type_tag != nsXPTType::T_INTERFACE &&
!paramInfo.IsShared())

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

@ -120,7 +120,7 @@ typedef unsigned long size_t;
[ref, astring] native AStringRef(ignored);
[ptr, astring] native AStringPtr(ignored);
native jsval(jsval);
[jsval] native jsval(jsval);
%{C++
/*

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

@ -405,7 +405,8 @@ class Native(object):
'domstring': 'nsAString',
'utf8string': 'nsACString',
'cstring': 'nsACString',
'astring': 'nsAString'
'astring': 'nsAString',
'jsval': 'jsval'
}
def __init__(self, name, nativename, attlist, location):

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

@ -95,7 +95,8 @@ struct nsXPTCVariant : public nsXPTCMiniVariant
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
VAL_IS_UTF8STR = 0x20, // val.p holds a pointer to utf8string needing cleanup
VAL_IS_CSTR = 0x40 // val.p holds a pointer to cstring needing cleanup
VAL_IS_CSTR = 0x40, // val.p holds a pointer to cstring needing cleanup
VAL_IS_JSROOT = 0x80 // val.p holds a pointer to a jsval that must be unrooted
};
void ClearFlags() {flags = 0;}
@ -105,7 +106,8 @@ struct nsXPTCVariant : public nsXPTCMiniVariant
void SetValIsArray() {flags |= VAL_IS_ARRAY;}
void SetValIsDOMString() {flags |= VAL_IS_DOMSTR;}
void SetValIsUTF8String() {flags |= VAL_IS_UTF8STR;}
void SetValIsCString() {flags |= VAL_IS_CSTR;}
void SetValIsCString() {flags |= VAL_IS_CSTR;}
void SetValIsJSRoot() {flags |= VAL_IS_JSROOT;}
PRBool IsPtrData() const {return 0 != (flags & PTR_IS_DATA);}
PRBool IsValAllocated() const {return 0 != (flags & VAL_IS_ALLOCD);}
@ -114,6 +116,7 @@ struct nsXPTCVariant : public nsXPTCMiniVariant
PRBool IsValDOMString() const {return 0 != (flags & VAL_IS_DOMSTR);}
PRBool IsValUTF8String() const {return 0 != (flags & VAL_IS_UTF8STR);}
PRBool IsValCString() const {return 0 != (flags & VAL_IS_CSTR);}
PRBool IsValJSRoot() const {return 0 != (flags & VAL_IS_JSROOT);}
void Init(const nsXPTCMiniVariant& mv, const nsXPTType& t, PRUint8 f)
{

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

@ -141,7 +141,8 @@ public:
T_PWSTRING_SIZE_IS = TD_PWSTRING_SIZE_IS ,
T_UTF8STRING = TD_UTF8STRING ,
T_CSTRING = TD_CSTRING ,
T_ASTRING = TD_ASTRING
T_ASTRING = TD_ASTRING ,
T_JSVAL = TD_JSVAL
};
// NO DATA - this a flyweight wrapper
};

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

@ -874,6 +874,10 @@ handle_iid_is:
td->prefix.flags = TD_CSTRING | XPT_TDP_POINTER;
if (IDL_tree_property_get(type, "ref"))
td->prefix.flags |= XPT_TDP_REFERENCE;
} else if (IDL_tree_property_get(type, "jsval")) {
td->prefix.flags = TD_JSVAL;
if (IDL_tree_property_get(type, "ptr"))
td->prefix.flags |= XPT_TDP_POINTER;
} else {
td->prefix.flags = TD_VOID | XPT_TDP_POINTER;
}

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

@ -373,7 +373,8 @@ verify_attribute_declaration(IDL_tree attr_tree)
IDL_tree_property_get(attr_type, "domstring") == NULL &&
IDL_tree_property_get(attr_type, "utf8string") == NULL &&
IDL_tree_property_get(attr_type, "cstring") == NULL &&
IDL_tree_property_get(attr_type, "astring") == NULL)
IDL_tree_property_get(attr_type, "astring") == NULL &&
IDL_tree_property_get(attr_type, "jsval") == NULL)
{
IDL_tree_error(attr_tree,
"attributes in [scriptable] interfaces that are "
@ -623,7 +624,8 @@ verify_method_declaration(IDL_tree method_tree)
IDL_tree_property_get(param_type, "domstring") == NULL &&
IDL_tree_property_get(param_type, "utf8string") == NULL &&
IDL_tree_property_get(param_type, "cstring") == NULL &&
IDL_tree_property_get(param_type, "astring") == NULL)
IDL_tree_property_get(param_type, "astring") == NULL &&
IDL_tree_property_get(param_type, "jsval") == NULL)
{
IDL_tree_error(method_tree,
"methods in [scriptable] interfaces that are "
@ -700,7 +702,8 @@ verify_method_declaration(IDL_tree method_tree)
!IDL_tree_property_get(real_type, "domstring") &&
!IDL_tree_property_get(real_type, "utf8string") &&
!IDL_tree_property_get(real_type, "cstring") &&
!IDL_tree_property_get(real_type, "astring"))))
!IDL_tree_property_get(real_type, "astring") &&
!IDL_tree_property_get(real_type, "jsval"))))
{
IDL_tree_error(method_tree,
"[shared] parameter \"%s\" must be of type "
@ -785,7 +788,8 @@ verify_method_declaration(IDL_tree method_tree)
IDL_tree_property_get(op->op_type_spec, "domstring") == NULL &&
IDL_tree_property_get(op->op_type_spec, "utf8string") == NULL &&
IDL_tree_property_get(op->op_type_spec, "cstring") == NULL &&
IDL_tree_property_get(op->op_type_spec, "astring") == NULL)
IDL_tree_property_get(op->op_type_spec, "astring") == NULL &&
IDL_tree_property_get(op->op_type_spec, "jsval") == NULL)
{
IDL_tree_error(method_tree,
"methods in [scriptable] interfaces that are "

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

@ -375,7 +375,8 @@ enum XPTTypeDescriptorTags {
TD_PWSTRING_SIZE_IS = 22,
TD_UTF8STRING = 23,
TD_CSTRING = 24,
TD_ASTRING = 25
TD_ASTRING = 25,
TD_JSVAL = 26
};
struct XPTTypeDescriptor {