Bug 382034, support optional arguments in idl, r+sr=shaver

This commit is contained in:
enndeakin%sympatico.ca 2007-06-22 14:22:23 +00:00
Родитель 1d9fc51567
Коммит 5daa0a155e
6 изменённых файлов: 55 добавлений и 12 удалений

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

@ -1842,6 +1842,7 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
nsIInterfaceInfo* ifaceInfo = ccx.GetInterface()->GetInterfaceInfo();
jsval name = ccx.GetMember()->GetName();
jsval* argv = ccx.GetArgv();
PRUint32 argc = ccx.GetArgc();
#ifdef DEBUG_stats_jband
PRIntervalTime startTime = PR_IntervalNow();
@ -1904,11 +1905,17 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
requiredArgs = paramCount;
if(paramCount && methodInfo->GetParam(paramCount-1).IsRetval())
requiredArgs--;
if(ccx.GetArgc() < requiredArgs)
if(argc < requiredArgs)
{
// skip over any optional arguments
while (requiredArgs && methodInfo->GetParam(requiredArgs-1).IsOptional())
requiredArgs--;
if(argc < requiredArgs) {
Throw(NS_ERROR_XPC_NOT_ENOUGH_ARGS, ccx);
goto done;
}
}
// setup variant array pointer
if(paramCount > PARAM_BUFFER_COUNT)
@ -1941,6 +1948,7 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
const nsXPTType& type = paramInfo.GetType();
uint8 type_tag = type.TagPart();
jsval arg = paramInfo.IsOptional() && argc < i ? JSVAL_NULL : argv[i];
if(type.IsDependent())
{
@ -1961,8 +1969,8 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
if((paramInfo.IsOut() || paramInfo.IsDipper()) &&
!paramInfo.IsRetval() &&
(JSVAL_IS_PRIMITIVE(argv[i]) ||
!OBJ_GET_PROPERTY(ccx, JSVAL_TO_OBJECT(argv[i]),
(JSVAL_IS_PRIMITIVE(arg) ||
!OBJ_GET_PROPERTY(ccx, JSVAL_TO_OBJECT(arg),
rt->GetStringID(XPCJSRuntime::IDX_VALUE),
&src)))
{
@ -2057,9 +2065,9 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
}
// Do this *after* the above because in the case where we have a
// "T_DOMSTRING && IsDipper()" then argv might be null since this
// "T_DOMSTRING && IsDipper()" then arg might be null since this
// is really an 'out' param masquerading as an 'in' param.
src = argv[i];
src = arg;
}
if(type_tag == nsXPTType::T_INTERFACE &&
@ -2085,6 +2093,7 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
{
const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
const nsXPTType& type = paramInfo.GetType();
jsval arg = paramInfo.IsOptional() && argc < i ? JSVAL_NULL : argv[i];
if(!type.IsDependent())
continue;
@ -2131,8 +2140,8 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
dp->ptr = &dp->val;
if(!paramInfo.IsRetval() &&
(JSVAL_IS_PRIMITIVE(argv[i]) ||
!OBJ_GET_PROPERTY(ccx, JSVAL_TO_OBJECT(argv[i]),
(JSVAL_IS_PRIMITIVE(arg) ||
!OBJ_GET_PROPERTY(ccx, JSVAL_TO_OBJECT(arg),
rt->GetStringID(XPCJSRuntime::IDX_VALUE), &src)))
{
ThrowBadParam(NS_ERROR_XPC_NEED_OUT_OBJECT, i, ccx);
@ -2152,7 +2161,7 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
}
else
{
src = argv[i];
src = arg;
if(datum_type.IsPointer() &&
datum_type.TagPart() == nsXPTType::T_IID)
@ -2328,7 +2337,7 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
if(!ccx.GetReturnValueWasSet())
ccx.SetRetVal(v);
}
else
else if (!paramInfo.IsOptional() || argc > i)
{
// we actually assured this before doing the invoke
NS_ASSERTION(JSVAL_IS_OBJECT(argv[i]), "out var is not object");

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

@ -159,6 +159,7 @@ public:
PRBool IsRetval() const {return 0 != (XPT_PD_IS_RETVAL(flags));}
PRBool IsShared() const {return 0 != (XPT_PD_IS_SHARED(flags));}
PRBool IsDipper() const {return 0 != (XPT_PD_IS_DIPPER(flags));}
PRBool IsOptional() const {return 0 != (XPT_PD_IS_OPTIONAL(flags));}
const nsXPTType GetType() const {return type.prefix;}
// NOTE: other activities on types are done via methods on nsIInterfaceInfo

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

@ -988,6 +988,11 @@ fill_pd_from_param(TreeState *state, XPTParamDescriptor *pd, IDL_tree tree)
flags |= XPT_PD_SHARED;
}
if (IDL_tree_property_get(IDL_PARAM_DCL(tree).simple_declarator,
"optional")) {
flags |= XPT_PD_OPTIONAL;
}
/* stick param where we can see it later */
state->tree = tree;
return fill_pd_from_type(state, pd, flags,

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

@ -559,6 +559,7 @@ verify_method_declaration(IDL_tree method_tree)
gboolean scriptable_interface;
gboolean scriptable_method;
gboolean seen_retval = FALSE;
gboolean hasoptional = PR_FALSE;
const char *method_name = IDL_IDENT(IDL_OP_DCL(method_tree).ident).str;
/* We don't support attributes named IID, conflicts with static GetIID
@ -716,6 +717,19 @@ verify_method_declaration(IDL_tree method_tree)
}
}
/*
* confirm that once an optional argument is used, all remaining
* arguments are marked as optional
*/
if (IDL_tree_property_get(simple_decl, "optional") != NULL) {
hasoptional = PR_TRUE;
}
else if (hasoptional) {
IDL_tree_error(method_tree,
"non-optional parameter used after one marked [optional]");
return FALSE;
}
/*
* inout is not allowed with "domstring", "UTF8String", "CString"
* and "AString" types

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

@ -452,13 +452,15 @@ struct XPTParamDescriptor {
#define XPT_PD_RETVAL 0x20
#define XPT_PD_SHARED 0x10
#define XPT_PD_DIPPER 0x08
#define XPT_PD_FLAGMASK 0xf8
#define XPT_PD_OPTIONAL 0x04
#define XPT_PD_FLAGMASK 0xfc
#define XPT_PD_IS_IN(flags) (flags & XPT_PD_IN)
#define XPT_PD_IS_OUT(flags) (flags & XPT_PD_OUT)
#define XPT_PD_IS_RETVAL(flags) (flags & XPT_PD_RETVAL)
#define XPT_PD_IS_SHARED(flags) (flags & XPT_PD_SHARED)
#define XPT_PD_IS_DIPPER(flags) (flags & XPT_PD_DIPPER)
#define XPT_PD_IS_OPTIONAL(flags) (flags & XPT_PD_OPTIONAL)
extern XPT_PUBLIC_API(PRBool)
XPT_FillParamDescriptor(XPTArena *arena,

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

@ -605,6 +605,9 @@ XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
fprintf(stdout, "retval ");
}
}
if (XPT_PD_IS_OPTIONAL(pd->flags)) {
fprintf(stdout, "optional ");
}
} else {
if (XPT_PD_IS_OUT(pd->flags)) {
fprintf(stdout, "out ");
@ -614,6 +617,9 @@ XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
if (XPT_PD_IS_SHARED(pd->flags)) {
fprintf(stdout, "shared ");
}
if (XPT_PD_IS_OPTIONAL(pd->flags)) {
fprintf(stdout, "optional ");
}
} else {
param_problems = PR_TRUE;
fprintf(stdout, "XXX ");
@ -737,6 +743,12 @@ XPT_DumpParamDescriptor(XPTHeader *header, XPTParamDescriptor *pd,
else
fprintf(stdout, "FALSE\n");
fprintf(stdout, "%*sOptional? ", indent, " ");
if (XPT_PD_IS_OPTIONAL(pd->flags))
fprintf(stdout, "TRUE\n");
else
fprintf(stdout, "FALSE\n");
fprintf(stdout, "%*sType Descriptor:\n", indent, " ");
if (!XPT_DumpTypeDescriptor(&pd->type, id, new_indent, verbose_mode))