зеркало из https://github.com/mozilla/pjs.git
Bug 382034, support optional arguments in idl, r+sr=shaver
This commit is contained in:
Родитель
1d9fc51567
Коммит
5daa0a155e
|
@ -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,10 +1905,16 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
|
|||
requiredArgs = paramCount;
|
||||
if(paramCount && methodInfo->GetParam(paramCount-1).IsRetval())
|
||||
requiredArgs--;
|
||||
if(ccx.GetArgc() < requiredArgs)
|
||||
if(argc < requiredArgs)
|
||||
{
|
||||
Throw(NS_ERROR_XPC_NOT_ENOUGH_ARGS, ccx);
|
||||
goto done;
|
||||
// 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
|
||||
|
@ -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))
|
||||
|
|
Загрузка…
Ссылка в новой задаче