Bug 574872 - 'Allow XPConnect to pass the JSContext through XPIDL when requested'. r=jst

This commit is contained in:
Ben Turner 2010-06-28 15:22:39 -07:00
Родитель 41bf7c2d61
Коммит 24407948af
8 изменённых файлов: 87 добавлений и 11 удалений

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

@ -202,7 +202,7 @@ def removeStubMember(memberId, member):
def addStubMember(memberId, member, traceable):
mayTrace = False
if member.kind == 'method':
if member.kind == 'method' and not member.implicit_jscontext:
# This code MUST match writeTraceableQuickStub
haveCallee = memberNeedsCallee(member)
# Traceable natives support up to MAX_TRACEABLE_NATIVE_ARGS
@ -255,7 +255,8 @@ def checkStubMember(member, isCustom):
# Check for unknown properties.
for attrname, value in vars(member).items():
if value is True and attrname not in ('readonly','optional_argc','traceable'):
if value is True and attrname not in ('readonly','optional_argc',
'traceable','implicit_jscontext'):
raise UserError("%s %s: unrecognized property %r"
% (member.kind.capitalize(), memberId,
attrname))
@ -940,6 +941,8 @@ def writeQuickStub(f, customMethodCalls, member, stubName, isSetter=False):
if isMethod:
comName = header.methodNativeName(member)
argv = ['arg' + str(i) for i, p in enumerate(member.params)]
if member.implicit_jscontext:
argv.append('cx')
if member.optional_argc:
argv.append('argc - %d' % requiredArgs)
if not isVoidType(member.realtype):
@ -951,6 +954,8 @@ def writeQuickStub(f, customMethodCalls, member, stubName, isSetter=False):
args = outParamForm(resultname, member.realtype)
else:
args = "arg0"
if member.implicit_jscontext:
args = "cx, " + args
f.write(" ")
if canFail or debugGetter:

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

@ -2120,6 +2120,7 @@ class CallMethodHelper
const jsid mIdxValueId;
nsAutoTArray<nsXPTCVariant, 8> mDispatchParams;
uint8 mJSContextIndex; // TODO make const
uint8 mOptArgcIndex; // TODO make const
// Reserve space for one nsAutoString. We don't want the string itself
@ -2169,6 +2170,8 @@ class CallMethodHelper
nsXPTCVariant*
GetDispatchParam(uint8 paramIndex)
{
if (paramIndex >= mJSContextIndex)
paramIndex += 1;
if (paramIndex >= mOptArgcIndex)
paramIndex += 1;
return &mDispatchParams[paramIndex];
@ -2195,6 +2198,7 @@ public:
, mCallee(ccx.GetTearOff()->GetNative())
, mVTableIndex(ccx.GetMethodIndex())
, mIdxValueId(ccx.GetRuntime()->GetStringID(XPCJSRuntime::IDX_VALUE))
, mJSContextIndex(PR_UINT8_MAX)
, mOptArgcIndex(PR_UINT8_MAX)
, mArgv(ccx.GetArgv())
, mArgc(ccx.GetArgc())
@ -2656,12 +2660,17 @@ JSBool
CallMethodHelper::InitializeDispatchParams()
{
const uint8 wantsOptArgc = mMethodInfo->WantsOptArgc() ? 1 : 0;
const uint8 wantsJSContext = mMethodInfo->WantsContext() ? 1 : 0;
const uint8 paramCount = mMethodInfo->GetParamCount();
uint8 requiredArgs = paramCount;
uint8 hasRetval = 0;
// XXX ASSUMES that retval is last arg. The xpidl compiler ensures this.
if(paramCount && mMethodInfo->GetParam(paramCount-1).IsRetval())
{
hasRetval = 1;
requiredArgs--;
}
if(mArgc < requiredArgs || wantsOptArgc)
{
@ -2678,14 +2687,31 @@ CallMethodHelper::InitializeDispatchParams()
}
}
if(wantsJSContext)
{
if(wantsOptArgc)
// Need to bump mOptArgcIndex up one here.
mJSContextIndex = mOptArgcIndex++;
else
mJSContextIndex = paramCount - hasRetval;
}
// iterate through the params to clear flags (for safe cleanup later)
for(uint8 i = 0; i < paramCount + wantsOptArgc; i++)
for(uint8 i = 0; i < paramCount + wantsJSContext + wantsOptArgc; i++)
{
nsXPTCVariant* dp = mDispatchParams.AppendElement();
dp->ClearFlags();
dp->val.p = nsnull;
}
// Fill in the JSContext argument
if(wantsJSContext)
{
nsXPTCVariant* dp = &mDispatchParams[mJSContextIndex];
dp->type = nsXPTType::T_VOID;
dp->val.p = mCallContext;
}
// Fill in the optional_argc argument
if(wantsOptArgc)
{

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

@ -640,6 +640,7 @@ class Attribute(object):
noscript = False
notxpcom = False
readonly = False
implicit_jscontext = False
binaryname = None
null = None
undefined = None
@ -689,6 +690,8 @@ class Attribute(object):
self.noscript = True
elif name == 'notxpcom':
self.notxpcom = True
elif name == 'implicit_jscontext':
self.implicit_jscontext = True
else:
raise IDLError("Unexpected attribute '%s'", aloc)
@ -722,6 +725,7 @@ class Method(object):
noscript = False
notxpcom = False
binaryname = None
implicit_jscontext = False
optional_argc = False
def __init__(self, type, name, attlist, paramlist, location, doccomments, raises):
@ -749,6 +753,8 @@ class Method(object):
self.noscript = True
elif name == 'notxpcom':
self.notxpcom = True
elif name == 'implicit_jscontext':
self.implicit_jscontext = True
elif name == 'optional_argc':
self.optional_argc = True
else:

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

@ -183,6 +183,7 @@ public:
PRBool IsConstructor() const {return 0 != (XPT_MD_IS_CTOR(flags) );}
PRBool IsHidden() const {return 0 != (XPT_MD_IS_HIDDEN(flags) );}
PRBool WantsOptArgc() const {return 0 != (XPT_MD_WANTS_OPT_ARGC(flags));}
PRBool WantsContext() const {return 0 != (XPT_MD_WANTS_CONTEXT(flags));}
const char* GetName() const {return name;}
PRUint8 GetParamCount() const {return num_args;}
/* idx was index before I got _sick_ of the warnings on Unix, sorry jband */

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

@ -778,6 +778,11 @@ write_attr_accessor(IDL_tree attr_tree, FILE * outfile,
toupper(*attrname),
attrname + 1);
}
if (IDL_tree_property_get(ident, "implicit_jscontext")) {
if (mode == AS_DECL || mode == AS_IMPL)
fputs("JSContext *", outfile);
fputs("cx, ", outfile);
}
if (mode == AS_DECL || mode == AS_IMPL) {
/* Setters for string, wstring, nsid, domstring, utf8string,
* cstring and astring get const.
@ -1041,6 +1046,8 @@ write_method_signature(IDL_tree method_tree, FILE *outfile, int mode,
(IDL_tree_property_get(op->ident, "notxpcom") != NULL);
gboolean op_opt_argc =
(IDL_tree_property_get(op->ident, "optional_argc") != NULL);
gboolean op_context =
(IDL_tree_property_get(op->ident, "implicit_jscontext") != NULL);
const char *name;
const char *binaryname;
IDL_tree iter;
@ -1097,6 +1104,19 @@ write_method_signature(IDL_tree method_tree, FILE *outfile, int mode,
no_generated_args = FALSE;
}
if (op_context) {
if ((op_notxpcom || !op->op_type_spec) && !op->f_varargs)
fputs(", ", outfile);
if (mode == AS_DECL || mode == AS_IMPL)
fputs("JSContext *", outfile);
fputs("cx", outfile);
if ((!op_notxpcom && op->op_type_spec) || op->f_varargs)
fputs(", ", outfile);
}
if (op_opt_argc) {
if ((op_notxpcom || !op->op_type_spec) && !op->f_varargs)
fputs(", ", outfile);

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

@ -1017,13 +1017,14 @@ fill_pd_as_nsresult(XPTParamDescriptor *pd)
static gboolean
typelib_attr_accessor(TreeState *state, XPTMethodDescriptor *meth,
gboolean getter, gboolean hidden)
gboolean getter, gboolean hidden, gboolean wantsJSContext)
{
uint8 methflags = 0;
uint8 pdflags = 0;
methflags |= getter ? XPT_MD_GETTER : XPT_MD_SETTER;
methflags |= hidden ? XPT_MD_HIDDEN : 0;
methflags |= wantsJSContext ? XPT_MD_CONTEXT : 0;
if (!XPT_FillMethodDescriptor(ARENA(state), meth, methflags,
ATTR_IDENT(state->tree).str, 1))
return FALSE;
@ -1061,6 +1062,9 @@ typelib_attr_dcl(TreeState *state)
/* If it's marked [noscript], mark it as hidden in the typelib. */
gboolean hidden = (IDL_tree_property_get(ident, "noscript") != NULL);
gboolean wantsJSContext =
(IDL_tree_property_get(ident, "implicit_jscontext") != NULL);
if (!verify_attribute_declaration(state->tree))
return FALSE;
@ -1070,8 +1074,9 @@ typelib_attr_dcl(TreeState *state)
meth = &id->method_descriptors[NEXT_METH(state)];
return typelib_attr_accessor(state, meth, TRUE, hidden) &&
(read_only || typelib_attr_accessor(state, meth + 1, FALSE, hidden));
return typelib_attr_accessor(state, meth, TRUE, hidden, wantsJSContext) &&
(read_only ||
typelib_attr_accessor(state, meth + 1, FALSE, hidden, wantsJSContext));
}
static gboolean
@ -1087,6 +1092,8 @@ typelib_op_dcl(TreeState *state)
!= NULL);
gboolean op_noscript = (IDL_tree_property_get(op->ident, "noscript")
!= NULL);
gboolean op_context = (IDL_tree_property_get(op->ident,
"implicit_jscontext") != NULL);
gboolean op_opt_argc = (IDL_tree_property_get(op->ident, "optional_argc")
!= NULL);
@ -1109,6 +1116,8 @@ typelib_op_dcl(TreeState *state)
op_flags |= XPT_MD_NOTXPCOM;
if (op_opt_argc)
op_flags |= XPT_MD_OPT_ARGC;
if (op_context)
op_flags |= XPT_MD_CONTEXT;
/* XXXshaver constructor? */

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

@ -487,7 +487,8 @@ struct XPTMethodDescriptor {
#define XPT_MD_CTOR 0x10
#define XPT_MD_HIDDEN 0x08
#define XPT_MD_OPT_ARGC 0x04
#define XPT_MD_FLAGMASK 0xfc
#define XPT_MD_CONTEXT 0x02
#define XPT_MD_FLAGMASK 0xfe
#define XPT_MD_IS_GETTER(flags) (flags & XPT_MD_GETTER)
#define XPT_MD_IS_SETTER(flags) (flags & XPT_MD_SETTER)
@ -495,6 +496,7 @@ struct XPTMethodDescriptor {
#define XPT_MD_IS_CTOR(flags) (flags & XPT_MD_CTOR)
#define XPT_MD_IS_HIDDEN(flags) (flags & XPT_MD_HIDDEN)
#define XPT_MD_WANTS_OPT_ARGC(flags) (flags & XPT_MD_OPT_ARGC)
#define XPT_MD_WANTS_CONTEXT(flags) (flags & XPT_MD_CONTEXT)
extern XPT_PUBLIC_API(PRBool)
XPT_FillMethodDescriptor(XPTArena *arena,

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

@ -63,7 +63,7 @@ static char *type_array[32] =
"wchar_t", "void", "reserved", "reserved",
"reserved", "reserved", "reserved", "reserved",
"reserved", "reserved", "reserved", "reserved",
"reserved", "reserved", "reserved", "reserved",
"reserved", "reserved", "jsval", "reserved",
"reserved", "reserved", "reserved", "reserved"};
static char *ptype_array[32] =
@ -73,7 +73,7 @@ static char *ptype_array[32] =
"wchar_t *", "void *", "nsIID *", "DOMString *",
"string", "wstring", "Interface *", "InterfaceIs *",
"array", "string_s", "wstring_s", "UTF8String *",
"CString *", "AString *", "reserved", "reserved",
"CString *", "AString *", "jsval *", "reserved",
"reserved", "reserved", "reserved", "reserved"};
static char *rtype_array[32] =
@ -83,7 +83,7 @@ static char *rtype_array[32] =
"wchar_t &", "void &", "nsIID &", "DOMString &",
"string &", "wstring &", "Interface &", "InterfaceIs &",
"array &", "string_s &", "wstring_s &", "UTF8String &",
"CString &", "AString &", "reserved", "reserved",
"CString &", "AString &", "jsval &", "reserved",
"reserved", "reserved", "reserved", "reserved"};
PRBool param_problems = PR_FALSE;
@ -579,6 +579,12 @@ XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
else
fprintf(stdout, "FALSE\n");
fprintf(stdout, "%*sWants JSContext? ", indent, " ");
if (XPT_MD_WANTS_CONTEXT(md->flags))
fprintf(stdout, "TRUE\n");
else
fprintf(stdout, "FALSE\n");
fprintf(stdout, "%*s# of arguments: %d\n", indent, " ", md->num_args);
fprintf(stdout, "%*sParameter Descriptors:\n", indent, " ");
@ -602,13 +608,14 @@ XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
if (!XPT_GetStringForType(header, &md->result->type, id, &param_type)) {
return PR_FALSE;
}
fprintf(stdout, "%*s%c%c%c%c%c%c %s %s(", indent - 6, " ",
fprintf(stdout, "%*s%c%c%c%c%c%c%c %s %s(", indent - 6, " ",
XPT_MD_IS_GETTER(md->flags) ? 'G' : ' ',
XPT_MD_IS_SETTER(md->flags) ? 'S' : ' ',
XPT_MD_IS_HIDDEN(md->flags) ? 'H' : ' ',
XPT_MD_IS_NOTXPCOM(md->flags) ? 'N' : ' ',
XPT_MD_IS_CTOR(md->flags) ? 'C' : ' ',
XPT_MD_WANTS_OPT_ARGC(md->flags) ? 'O' : ' ',
XPT_MD_WANTS_CONTEXT(md->flags) ? 'J' : ' ',
param_type, md->name);
for (i=0; i<md->num_args; i++) {
if (i!=0) {