зеркало из 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();
|
nsIInterfaceInfo* ifaceInfo = ccx.GetInterface()->GetInterfaceInfo();
|
||||||
jsval name = ccx.GetMember()->GetName();
|
jsval name = ccx.GetMember()->GetName();
|
||||||
jsval* argv = ccx.GetArgv();
|
jsval* argv = ccx.GetArgv();
|
||||||
|
PRUint32 argc = ccx.GetArgc();
|
||||||
|
|
||||||
#ifdef DEBUG_stats_jband
|
#ifdef DEBUG_stats_jband
|
||||||
PRIntervalTime startTime = PR_IntervalNow();
|
PRIntervalTime startTime = PR_IntervalNow();
|
||||||
|
@ -1904,10 +1905,16 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
|
||||||
requiredArgs = paramCount;
|
requiredArgs = paramCount;
|
||||||
if(paramCount && methodInfo->GetParam(paramCount-1).IsRetval())
|
if(paramCount && methodInfo->GetParam(paramCount-1).IsRetval())
|
||||||
requiredArgs--;
|
requiredArgs--;
|
||||||
if(ccx.GetArgc() < requiredArgs)
|
if(argc < requiredArgs)
|
||||||
{
|
{
|
||||||
Throw(NS_ERROR_XPC_NOT_ENOUGH_ARGS, ccx);
|
// skip over any optional arguments
|
||||||
goto done;
|
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
|
// setup variant array pointer
|
||||||
|
@ -1941,6 +1948,7 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
|
||||||
const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
|
const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
|
||||||
const nsXPTType& type = paramInfo.GetType();
|
const nsXPTType& type = paramInfo.GetType();
|
||||||
uint8 type_tag = type.TagPart();
|
uint8 type_tag = type.TagPart();
|
||||||
|
jsval arg = paramInfo.IsOptional() && argc < i ? JSVAL_NULL : argv[i];
|
||||||
|
|
||||||
if(type.IsDependent())
|
if(type.IsDependent())
|
||||||
{
|
{
|
||||||
|
@ -1961,8 +1969,8 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
|
||||||
|
|
||||||
if((paramInfo.IsOut() || paramInfo.IsDipper()) &&
|
if((paramInfo.IsOut() || paramInfo.IsDipper()) &&
|
||||||
!paramInfo.IsRetval() &&
|
!paramInfo.IsRetval() &&
|
||||||
(JSVAL_IS_PRIMITIVE(argv[i]) ||
|
(JSVAL_IS_PRIMITIVE(arg) ||
|
||||||
!OBJ_GET_PROPERTY(ccx, JSVAL_TO_OBJECT(argv[i]),
|
!OBJ_GET_PROPERTY(ccx, JSVAL_TO_OBJECT(arg),
|
||||||
rt->GetStringID(XPCJSRuntime::IDX_VALUE),
|
rt->GetStringID(XPCJSRuntime::IDX_VALUE),
|
||||||
&src)))
|
&src)))
|
||||||
{
|
{
|
||||||
|
@ -2057,9 +2065,9 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do this *after* the above because in the case where we have a
|
// 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.
|
// is really an 'out' param masquerading as an 'in' param.
|
||||||
src = argv[i];
|
src = arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type_tag == nsXPTType::T_INTERFACE &&
|
if(type_tag == nsXPTType::T_INTERFACE &&
|
||||||
|
@ -2085,6 +2093,7 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
|
||||||
{
|
{
|
||||||
const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
|
const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
|
||||||
const nsXPTType& type = paramInfo.GetType();
|
const nsXPTType& type = paramInfo.GetType();
|
||||||
|
jsval arg = paramInfo.IsOptional() && argc < i ? JSVAL_NULL : argv[i];
|
||||||
|
|
||||||
if(!type.IsDependent())
|
if(!type.IsDependent())
|
||||||
continue;
|
continue;
|
||||||
|
@ -2131,8 +2140,8 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
|
||||||
dp->ptr = &dp->val;
|
dp->ptr = &dp->val;
|
||||||
|
|
||||||
if(!paramInfo.IsRetval() &&
|
if(!paramInfo.IsRetval() &&
|
||||||
(JSVAL_IS_PRIMITIVE(argv[i]) ||
|
(JSVAL_IS_PRIMITIVE(arg) ||
|
||||||
!OBJ_GET_PROPERTY(ccx, JSVAL_TO_OBJECT(argv[i]),
|
!OBJ_GET_PROPERTY(ccx, JSVAL_TO_OBJECT(arg),
|
||||||
rt->GetStringID(XPCJSRuntime::IDX_VALUE), &src)))
|
rt->GetStringID(XPCJSRuntime::IDX_VALUE), &src)))
|
||||||
{
|
{
|
||||||
ThrowBadParam(NS_ERROR_XPC_NEED_OUT_OBJECT, i, ccx);
|
ThrowBadParam(NS_ERROR_XPC_NEED_OUT_OBJECT, i, ccx);
|
||||||
|
@ -2152,7 +2161,7 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
src = argv[i];
|
src = arg;
|
||||||
|
|
||||||
if(datum_type.IsPointer() &&
|
if(datum_type.IsPointer() &&
|
||||||
datum_type.TagPart() == nsXPTType::T_IID)
|
datum_type.TagPart() == nsXPTType::T_IID)
|
||||||
|
@ -2328,7 +2337,7 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
|
||||||
if(!ccx.GetReturnValueWasSet())
|
if(!ccx.GetReturnValueWasSet())
|
||||||
ccx.SetRetVal(v);
|
ccx.SetRetVal(v);
|
||||||
}
|
}
|
||||||
else
|
else if (!paramInfo.IsOptional() || argc > i)
|
||||||
{
|
{
|
||||||
// we actually assured this before doing the invoke
|
// we actually assured this before doing the invoke
|
||||||
NS_ASSERTION(JSVAL_IS_OBJECT(argv[i]), "out var is not object");
|
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 IsRetval() const {return 0 != (XPT_PD_IS_RETVAL(flags));}
|
||||||
PRBool IsShared() const {return 0 != (XPT_PD_IS_SHARED(flags));}
|
PRBool IsShared() const {return 0 != (XPT_PD_IS_SHARED(flags));}
|
||||||
PRBool IsDipper() const {return 0 != (XPT_PD_IS_DIPPER(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;}
|
const nsXPTType GetType() const {return type.prefix;}
|
||||||
|
|
||||||
// NOTE: other activities on types are done via methods on nsIInterfaceInfo
|
// 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;
|
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 */
|
/* stick param where we can see it later */
|
||||||
state->tree = tree;
|
state->tree = tree;
|
||||||
return fill_pd_from_type(state, pd, flags,
|
return fill_pd_from_type(state, pd, flags,
|
||||||
|
|
|
@ -559,6 +559,7 @@ verify_method_declaration(IDL_tree method_tree)
|
||||||
gboolean scriptable_interface;
|
gboolean scriptable_interface;
|
||||||
gboolean scriptable_method;
|
gboolean scriptable_method;
|
||||||
gboolean seen_retval = FALSE;
|
gboolean seen_retval = FALSE;
|
||||||
|
gboolean hasoptional = PR_FALSE;
|
||||||
const char *method_name = IDL_IDENT(IDL_OP_DCL(method_tree).ident).str;
|
const char *method_name = IDL_IDENT(IDL_OP_DCL(method_tree).ident).str;
|
||||||
|
|
||||||
/* We don't support attributes named IID, conflicts with static GetIID
|
/* 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"
|
* inout is not allowed with "domstring", "UTF8String", "CString"
|
||||||
* and "AString" types
|
* and "AString" types
|
||||||
|
|
|
@ -452,13 +452,15 @@ struct XPTParamDescriptor {
|
||||||
#define XPT_PD_RETVAL 0x20
|
#define XPT_PD_RETVAL 0x20
|
||||||
#define XPT_PD_SHARED 0x10
|
#define XPT_PD_SHARED 0x10
|
||||||
#define XPT_PD_DIPPER 0x08
|
#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_IN(flags) (flags & XPT_PD_IN)
|
||||||
#define XPT_PD_IS_OUT(flags) (flags & XPT_PD_OUT)
|
#define XPT_PD_IS_OUT(flags) (flags & XPT_PD_OUT)
|
||||||
#define XPT_PD_IS_RETVAL(flags) (flags & XPT_PD_RETVAL)
|
#define XPT_PD_IS_RETVAL(flags) (flags & XPT_PD_RETVAL)
|
||||||
#define XPT_PD_IS_SHARED(flags) (flags & XPT_PD_SHARED)
|
#define XPT_PD_IS_SHARED(flags) (flags & XPT_PD_SHARED)
|
||||||
#define XPT_PD_IS_DIPPER(flags) (flags & XPT_PD_DIPPER)
|
#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)
|
extern XPT_PUBLIC_API(PRBool)
|
||||||
XPT_FillParamDescriptor(XPTArena *arena,
|
XPT_FillParamDescriptor(XPTArena *arena,
|
||||||
|
|
|
@ -605,6 +605,9 @@ XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
|
||||||
fprintf(stdout, "retval ");
|
fprintf(stdout, "retval ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (XPT_PD_IS_OPTIONAL(pd->flags)) {
|
||||||
|
fprintf(stdout, "optional ");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (XPT_PD_IS_OUT(pd->flags)) {
|
if (XPT_PD_IS_OUT(pd->flags)) {
|
||||||
fprintf(stdout, "out ");
|
fprintf(stdout, "out ");
|
||||||
|
@ -614,6 +617,9 @@ XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
|
||||||
if (XPT_PD_IS_SHARED(pd->flags)) {
|
if (XPT_PD_IS_SHARED(pd->flags)) {
|
||||||
fprintf(stdout, "shared ");
|
fprintf(stdout, "shared ");
|
||||||
}
|
}
|
||||||
|
if (XPT_PD_IS_OPTIONAL(pd->flags)) {
|
||||||
|
fprintf(stdout, "optional ");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
param_problems = PR_TRUE;
|
param_problems = PR_TRUE;
|
||||||
fprintf(stdout, "XXX ");
|
fprintf(stdout, "XXX ");
|
||||||
|
@ -737,6 +743,12 @@ XPT_DumpParamDescriptor(XPTHeader *header, XPTParamDescriptor *pd,
|
||||||
else
|
else
|
||||||
fprintf(stdout, "FALSE\n");
|
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, " ");
|
fprintf(stdout, "%*sType Descriptor:\n", indent, " ");
|
||||||
if (!XPT_DumpTypeDescriptor(&pd->type, id, new_indent, verbose_mode))
|
if (!XPT_DumpTypeDescriptor(&pd->type, id, new_indent, verbose_mode))
|
||||||
|
|
Загрузка…
Ссылка в новой задаче