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:
Johnny Stenback 2009-08-10 16:41:07 +02:00
Родитель 6cdb481cc2
Коммит e9cead7751
8 изменённых файлов: 92 добавлений и 16 удалений

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

@ -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, &param_type)) { if (!XPT_GetStringForType(header, &md->result->type, id, &param_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) {