зеркало из https://github.com/mozilla/gecko-dev.git
Part 1 of fix for bug 459452 (Add support for optional arg count for IDL methods): add support for [optional_argc] to xpidl and XPConnect. r=sicking.
--HG-- extra : rebase_source : 3057c5af37ccb1bbdb022a0a3070122df3019d13
This commit is contained in:
Родитель
6cdb481cc2
Коммит
e9cead7751
|
@ -2227,6 +2227,8 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
|
||||||
const nsXPTMethodInfo* methodInfo;
|
const nsXPTMethodInfo* methodInfo;
|
||||||
uint8 requiredArgs;
|
uint8 requiredArgs;
|
||||||
uint8 paramCount;
|
uint8 paramCount;
|
||||||
|
uint8 wantsOptArgc;
|
||||||
|
uint8 optArgcIndex = PR_UINT8_MAX;
|
||||||
jsval src;
|
jsval src;
|
||||||
nsresult invokeResult;
|
nsresult invokeResult;
|
||||||
nsID param_iid;
|
nsID param_iid;
|
||||||
|
@ -2339,16 +2341,22 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wantsOptArgc = methodInfo->WantsOptArgc() ? 1 : 0;
|
||||||
|
|
||||||
// XXX ASSUMES that retval is last arg. The xpidl compiler ensures this.
|
// XXX ASSUMES that retval is last arg. The xpidl compiler ensures this.
|
||||||
paramCount = methodInfo->GetParamCount();
|
paramCount = methodInfo->GetParamCount();
|
||||||
requiredArgs = paramCount;
|
requiredArgs = paramCount;
|
||||||
if(paramCount && methodInfo->GetParam(paramCount-1).IsRetval())
|
if(paramCount && methodInfo->GetParam(paramCount-1).IsRetval())
|
||||||
requiredArgs--;
|
requiredArgs--;
|
||||||
if(argc < requiredArgs)
|
|
||||||
|
if(argc < requiredArgs || wantsOptArgc)
|
||||||
{
|
{
|
||||||
|
if(wantsOptArgc)
|
||||||
|
optArgcIndex = requiredArgs;
|
||||||
|
|
||||||
// skip over any optional arguments
|
// skip over any optional arguments
|
||||||
while(requiredArgs && methodInfo->GetParam(requiredArgs-1).IsOptional())
|
while(requiredArgs && methodInfo->GetParam(requiredArgs-1).IsOptional())
|
||||||
requiredArgs--;
|
requiredArgs--;
|
||||||
|
|
||||||
if(argc < requiredArgs) {
|
if(argc < requiredArgs) {
|
||||||
Throw(NS_ERROR_XPC_NOT_ENOUGH_ARGS, ccx);
|
Throw(NS_ERROR_XPC_NOT_ENOUGH_ARGS, ccx);
|
||||||
|
@ -2357,9 +2365,9 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup variant array pointer
|
// setup variant array pointer
|
||||||
if(paramCount > PARAM_BUFFER_COUNT)
|
if(paramCount + wantsOptArgc > PARAM_BUFFER_COUNT)
|
||||||
{
|
{
|
||||||
if(!(dispatchParams = new nsXPTCVariant[paramCount]))
|
if(!(dispatchParams = new nsXPTCVariant[paramCount + wantsOptArgc]))
|
||||||
{
|
{
|
||||||
JS_ReportOutOfMemory(ccx);
|
JS_ReportOutOfMemory(ccx);
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -2690,11 +2698,29 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fill in the optional_argc argument
|
||||||
|
if(wantsOptArgc)
|
||||||
|
{
|
||||||
|
nsXPTCVariant* dp = &dispatchParams[optArgcIndex];
|
||||||
|
|
||||||
|
if(optArgcIndex != paramCount)
|
||||||
|
{
|
||||||
|
// The method has a return value, the return value must be
|
||||||
|
// last so push it out one so that we'll have room to
|
||||||
|
// insert the optional argc argument.
|
||||||
|
dispatchParams[paramCount] = *dp;
|
||||||
|
}
|
||||||
|
|
||||||
|
dp->ClearFlags();
|
||||||
|
dp->type = nsXPTType::T_U8;
|
||||||
|
dp->val.u8 = argc - requiredArgs;
|
||||||
|
}
|
||||||
|
|
||||||
// do the invoke
|
// do the invoke
|
||||||
{
|
{
|
||||||
AutoJSSuspendNonMainThreadRequest req(ccx.GetJSContext());
|
AutoJSSuspendNonMainThreadRequest req(ccx.GetJSContext());
|
||||||
invokeResult = NS_InvokeByIndex(callee, vtblIndex, paramCount,
|
invokeResult = NS_InvokeByIndex(callee, vtblIndex,
|
||||||
|
paramCount + wantsOptArgc,
|
||||||
dispatchParams);
|
dispatchParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2713,12 +2739,17 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
|
||||||
// now we iterate through the native params to gather and convert results
|
// now we iterate through the native params to gather and convert results
|
||||||
for(i = 0; i < paramCount; i++)
|
for(i = 0; i < paramCount; i++)
|
||||||
{
|
{
|
||||||
|
uint8 dispatchParamIndex = i;
|
||||||
|
|
||||||
|
if (i >= optArgcIndex)
|
||||||
|
dispatchParamIndex++;
|
||||||
|
|
||||||
const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
|
const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
|
||||||
if(!paramInfo.IsOut() && !paramInfo.IsDipper())
|
if(!paramInfo.IsOut() && !paramInfo.IsDipper())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const nsXPTType& type = paramInfo.GetType();
|
const nsXPTType& type = paramInfo.GetType();
|
||||||
nsXPTCVariant* dp = &dispatchParams[i];
|
nsXPTCVariant* dp = &dispatchParams[dispatchParamIndex];
|
||||||
jsval v = JSVAL_NULL;
|
jsval v = JSVAL_NULL;
|
||||||
AUTO_MARK_JSVAL(ccx, &v);
|
AUTO_MARK_JSVAL(ccx, &v);
|
||||||
JSUint32 array_count;
|
JSUint32 array_count;
|
||||||
|
@ -2821,7 +2852,12 @@ done:
|
||||||
{
|
{
|
||||||
for(i = 0; i < paramCount; i++)
|
for(i = 0; i < paramCount; i++)
|
||||||
{
|
{
|
||||||
nsXPTCVariant* dp = &dispatchParams[i];
|
uint8 dispatchParamIndex = i;
|
||||||
|
|
||||||
|
if (i >= optArgcIndex)
|
||||||
|
dispatchParamIndex++;
|
||||||
|
|
||||||
|
nsXPTCVariant* dp = &dispatchParams[dispatchParamIndex];
|
||||||
void* p = dp->val.p;
|
void* p = dp->val.p;
|
||||||
if(!p)
|
if(!p)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -721,6 +721,7 @@ class Method(object):
|
||||||
noscript = False
|
noscript = False
|
||||||
notxpcom = False
|
notxpcom = False
|
||||||
binaryname = None
|
binaryname = None
|
||||||
|
optional_argc = False
|
||||||
|
|
||||||
def __init__(self, type, name, attlist, paramlist, location, doccomments, raises):
|
def __init__(self, type, name, attlist, paramlist, location, doccomments, raises):
|
||||||
self.type = type
|
self.type = type
|
||||||
|
@ -747,6 +748,8 @@ class Method(object):
|
||||||
self.noscript = True
|
self.noscript = True
|
||||||
elif name == 'notxpcom':
|
elif name == 'notxpcom':
|
||||||
self.notxpcom = True
|
self.notxpcom = True
|
||||||
|
elif name == 'optional_argc':
|
||||||
|
self.optional_argc = True
|
||||||
else:
|
else:
|
||||||
raise IDLError("Unexpected attribute '%s'", aloc)
|
raise IDLError("Unexpected attribute '%s'", aloc)
|
||||||
|
|
||||||
|
|
|
@ -181,6 +181,7 @@ public:
|
||||||
PRBool IsNotXPCOM() const {return 0 != (XPT_MD_IS_NOTXPCOM(flags));}
|
PRBool IsNotXPCOM() const {return 0 != (XPT_MD_IS_NOTXPCOM(flags));}
|
||||||
PRBool IsConstructor() const {return 0 != (XPT_MD_IS_CTOR(flags) );}
|
PRBool IsConstructor() const {return 0 != (XPT_MD_IS_CTOR(flags) );}
|
||||||
PRBool IsHidden() const {return 0 != (XPT_MD_IS_HIDDEN(flags) );}
|
PRBool IsHidden() const {return 0 != (XPT_MD_IS_HIDDEN(flags) );}
|
||||||
|
PRBool WantsOptArgc() const {return 0 != (XPT_MD_WANTS_OPT_ARGC(flags));}
|
||||||
const char* GetName() const {return name;}
|
const char* GetName() const {return name;}
|
||||||
PRUint8 GetParamCount() const {return num_args;}
|
PRUint8 GetParamCount() const {return num_args;}
|
||||||
/* idx was index before I got _sick_ of the warnings on Unix, sorry jband */
|
/* idx was index before I got _sick_ of the warnings on Unix, sorry jband */
|
||||||
|
|
|
@ -1039,6 +1039,8 @@ write_method_signature(IDL_tree method_tree, FILE *outfile, int mode,
|
||||||
gboolean no_generated_args = TRUE;
|
gboolean no_generated_args = TRUE;
|
||||||
gboolean op_notxpcom =
|
gboolean op_notxpcom =
|
||||||
(IDL_tree_property_get(op->ident, "notxpcom") != NULL);
|
(IDL_tree_property_get(op->ident, "notxpcom") != NULL);
|
||||||
|
gboolean op_opt_argc =
|
||||||
|
(IDL_tree_property_get(op->ident, "optional_argc") != NULL);
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *binaryname;
|
const char *binaryname;
|
||||||
IDL_tree iter;
|
IDL_tree iter;
|
||||||
|
@ -1095,6 +1097,19 @@ write_method_signature(IDL_tree method_tree, FILE *outfile, int mode,
|
||||||
no_generated_args = FALSE;
|
no_generated_args = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (op_opt_argc) {
|
||||||
|
if ((op_notxpcom || !op->op_type_spec) && !op->f_varargs)
|
||||||
|
fputs(", ", outfile);
|
||||||
|
|
||||||
|
if (mode == AS_DECL || mode == AS_IMPL)
|
||||||
|
fputs("PRUint8 ", outfile);
|
||||||
|
|
||||||
|
fputs("_argc", outfile);
|
||||||
|
|
||||||
|
if ((!op_notxpcom && op->op_type_spec) || op->f_varargs)
|
||||||
|
fputs(", ", outfile);
|
||||||
|
}
|
||||||
|
|
||||||
/* make IDL return value into trailing out argument */
|
/* make IDL return value into trailing out argument */
|
||||||
if (op->op_type_spec && !op_notxpcom) {
|
if (op->op_type_spec && !op_notxpcom) {
|
||||||
IDL_tree fake_param = IDL_param_dcl_new(IDL_PARAM_OUT,
|
IDL_tree fake_param = IDL_param_dcl_new(IDL_PARAM_OUT,
|
||||||
|
|
|
@ -1083,6 +1083,8 @@ typelib_op_dcl(TreeState *state)
|
||||||
!= NULL);
|
!= NULL);
|
||||||
gboolean op_noscript = (IDL_tree_property_get(op->ident, "noscript")
|
gboolean op_noscript = (IDL_tree_property_get(op->ident, "noscript")
|
||||||
!= NULL);
|
!= NULL);
|
||||||
|
gboolean op_opt_argc = (IDL_tree_property_get(op->ident, "optional_argc")
|
||||||
|
!= NULL);
|
||||||
|
|
||||||
if (!verify_method_declaration(state->tree))
|
if (!verify_method_declaration(state->tree))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -1101,6 +1103,8 @@ typelib_op_dcl(TreeState *state)
|
||||||
op_flags |= XPT_MD_HIDDEN;
|
op_flags |= XPT_MD_HIDDEN;
|
||||||
if (op_notxpcom)
|
if (op_notxpcom)
|
||||||
op_flags |= XPT_MD_NOTXPCOM;
|
op_flags |= XPT_MD_NOTXPCOM;
|
||||||
|
if (op_opt_argc)
|
||||||
|
op_flags |= XPT_MD_OPT_ARGC;
|
||||||
|
|
||||||
/* XXXshaver constructor? */
|
/* XXXshaver constructor? */
|
||||||
|
|
||||||
|
|
|
@ -719,7 +719,7 @@ verify_method_declaration(IDL_tree method_tree)
|
||||||
else if (hasoptional && IDL_tree_property_get(simple_decl, "retval") == NULL) {
|
else if (hasoptional && IDL_tree_property_get(simple_decl, "retval") == NULL) {
|
||||||
IDL_tree_error(method_tree,
|
IDL_tree_error(method_tree,
|
||||||
"non-optional non-retval parameter used after one marked [optional]");
|
"non-optional non-retval parameter used after one marked [optional]");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -768,6 +768,14 @@ verify_method_declaration(IDL_tree method_tree)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IDL_tree_property_get(op->ident, "optional_argc") != NULL &&
|
||||||
|
!hasoptional) {
|
||||||
|
IDL_tree_error(method_tree,
|
||||||
|
"[optional_argc] method must contain [optional] "
|
||||||
|
"arguments");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* XXX q: can return type be nsid? */
|
/* XXX q: can return type be nsid? */
|
||||||
/* Native return type? */
|
/* Native return type? */
|
||||||
|
|
|
@ -485,13 +485,15 @@ struct XPTMethodDescriptor {
|
||||||
#define XPT_MD_NOTXPCOM 0x20
|
#define XPT_MD_NOTXPCOM 0x20
|
||||||
#define XPT_MD_CTOR 0x10
|
#define XPT_MD_CTOR 0x10
|
||||||
#define XPT_MD_HIDDEN 0x08
|
#define XPT_MD_HIDDEN 0x08
|
||||||
#define XPT_MD_FLAGMASK 0xf8
|
#define XPT_MD_OPT_ARGC 0x04
|
||||||
|
#define XPT_MD_FLAGMASK 0xfc
|
||||||
|
|
||||||
#define XPT_MD_IS_GETTER(flags) (flags & XPT_MD_GETTER)
|
#define XPT_MD_IS_GETTER(flags) (flags & XPT_MD_GETTER)
|
||||||
#define XPT_MD_IS_SETTER(flags) (flags & XPT_MD_SETTER)
|
#define XPT_MD_IS_SETTER(flags) (flags & XPT_MD_SETTER)
|
||||||
#define XPT_MD_IS_NOTXPCOM(flags) (flags & XPT_MD_NOTXPCOM)
|
#define XPT_MD_IS_NOTXPCOM(flags) (flags & XPT_MD_NOTXPCOM)
|
||||||
#define XPT_MD_IS_CTOR(flags) (flags & XPT_MD_CTOR)
|
#define XPT_MD_IS_CTOR(flags) (flags & XPT_MD_CTOR)
|
||||||
#define XPT_MD_IS_HIDDEN(flags) (flags & XPT_MD_HIDDEN)
|
#define XPT_MD_IS_HIDDEN(flags) (flags & XPT_MD_HIDDEN)
|
||||||
|
#define XPT_MD_WANTS_OPT_ARGC(flags) (flags & XPT_MD_OPT_ARGC)
|
||||||
|
|
||||||
extern XPT_PUBLIC_API(PRBool)
|
extern XPT_PUBLIC_API(PRBool)
|
||||||
XPT_FillMethodDescriptor(XPTArena *arena,
|
XPT_FillMethodDescriptor(XPTArena *arena,
|
||||||
|
|
|
@ -571,7 +571,13 @@ XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
|
||||||
fprintf(stdout, "TRUE\n");
|
fprintf(stdout, "TRUE\n");
|
||||||
else
|
else
|
||||||
fprintf(stdout, "FALSE\n");
|
fprintf(stdout, "FALSE\n");
|
||||||
|
|
||||||
|
fprintf(stdout, "%*sWants Optional Argc? ", indent, " ");
|
||||||
|
if (XPT_MD_WANTS_OPT_ARGC(md->flags))
|
||||||
|
fprintf(stdout, "TRUE\n");
|
||||||
|
else
|
||||||
|
fprintf(stdout, "FALSE\n");
|
||||||
|
|
||||||
fprintf(stdout, "%*s# of arguments: %d\n", indent, " ", md->num_args);
|
fprintf(stdout, "%*s# of arguments: %d\n", indent, " ", md->num_args);
|
||||||
fprintf(stdout, "%*sParameter Descriptors:\n", indent, " ");
|
fprintf(stdout, "%*sParameter Descriptors:\n", indent, " ");
|
||||||
|
|
||||||
|
@ -595,12 +601,13 @@ XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
|
||||||
if (!XPT_GetStringForType(header, &md->result->type, id, ¶m_type)) {
|
if (!XPT_GetStringForType(header, &md->result->type, id, ¶m_type)) {
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
fprintf(stdout, "%*s%c%c%c%c%c %s %s(", indent - 6, " ",
|
fprintf(stdout, "%*s%c%c%c%c%c%c %s %s(", indent - 6, " ",
|
||||||
XPT_MD_IS_GETTER(md->flags) ? 'G' : ' ',
|
XPT_MD_IS_GETTER(md->flags) ? 'G' : ' ',
|
||||||
XPT_MD_IS_SETTER(md->flags) ? 'S' : ' ',
|
XPT_MD_IS_SETTER(md->flags) ? 'S' : ' ',
|
||||||
XPT_MD_IS_HIDDEN(md->flags) ? 'H' : ' ',
|
XPT_MD_IS_HIDDEN(md->flags) ? 'H' : ' ',
|
||||||
XPT_MD_IS_NOTXPCOM(md->flags) ? 'N' : ' ',
|
XPT_MD_IS_NOTXPCOM(md->flags) ? 'N' : ' ',
|
||||||
XPT_MD_IS_CTOR(md->flags) ? 'C' : ' ',
|
XPT_MD_IS_CTOR(md->flags) ? 'C' : ' ',
|
||||||
|
XPT_MD_WANTS_OPT_ARGC(md->flags) ? 'O' : ' ',
|
||||||
param_type, md->name);
|
param_type, md->name);
|
||||||
for (i=0; i<md->num_args; i++) {
|
for (i=0; i<md->num_args; i++) {
|
||||||
if (i!=0) {
|
if (i!=0) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче