Bug 779048 part 9. Give JS-to-native conversion an object pointer to work with so it can convert callback objects. r=peterv

This commit is contained in:
Boris Zbarsky 2012-11-09 07:43:58 -08:00
parent 499ff69d95
commit 2cca8f2c52
4 changed files with 37 additions and 22 deletions

View File

@ -184,14 +184,14 @@ nsDOMMultipartFile::InitInternal(JSContext* aCx,
if (aArgc > 1) {
if (NS_IsMainThread()) {
BlobPropertyBag d;
if (!d.Init(aCx, aArgv[1])) {
if (!d.Init(aCx, nullptr, aArgv[1])) {
return NS_ERROR_TYPE_ERR;
}
mContentType = d.type;
nativeEOL = d.endings == EndingTypesValues::Native;
} else {
BlobPropertyBagWorkers d;
if (!d.Init(aCx, aArgv[1])) {
if (!d.Init(aCx, nullptr, aArgv[1])) {
return NS_ERROR_TYPE_ERR;
}
mContentType = d.type;

View File

@ -183,7 +183,7 @@ public:
{
// Pretend like someone passed null, so we can pick up the default values
mozilla::dom::MozXMLHttpRequestParameters params;
if (!params.Init(aCx, JS::NullValue())) {
if (!params.Init(aCx, nullptr, JS::NullValue())) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}

View File

@ -2012,6 +2012,10 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
${haveValue} replaced by an expression that evaluates to a boolean
for whether we have a JS::Value. Only used when
defaultValue is not None.
${obj} replaced by an object which, when unwrapped, tells us which
compartment we really want to be working with here, in case
that matters for our conversion. This is allowed to be null if
we just want to work with the compartment we're already in.
2) A CGThing representing the native C++ type we're converting to
(declType). This is allowed to be None if the conversion code is
@ -2211,7 +2215,9 @@ for (uint32_t i = 0; i < length; ++i) {
{
"val" : "temp",
"valPtr": "&temp",
"declName" : "(*arr.AppendElement())"
"declName" : "(*arr.AppendElement())",
# Use the same ${obj} as for the sequence itself
"obj": "${obj}"
}
))).define()
@ -2246,7 +2252,7 @@ for (uint32_t i = 0; i < length; ++i) {
name = memberType.inner.identifier.name
else:
name = memberType.name
interfaceObject.append(CGGeneric("(failed = !%s.TrySetTo%s(cx, ${val}, ${valPtr}, tryNext)) || !tryNext" % (unionArgumentObj, name)))
interfaceObject.append(CGGeneric("(failed = !%s.TrySetTo%s(cx, ${obj}, ${val}, ${valPtr}, tryNext)) || !tryNext" % (unionArgumentObj, name)))
names.append(name)
interfaceObject = CGWrapper(CGList(interfaceObject, " ||\n"), pre="done = ", post=";\n", reindent=True)
else:
@ -2257,7 +2263,7 @@ for (uint32_t i = 0; i < length; ++i) {
assert len(arrayObjectMemberTypes) == 1
memberType = arrayObjectMemberTypes[0]
name = memberType.name
arrayObject = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${val}, ${valPtr}, tryNext)) || !tryNext;" % (unionArgumentObj, name))
arrayObject = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${obj}, ${val}, ${valPtr}, tryNext)) || !tryNext;" % (unionArgumentObj, name))
# XXX Now we're supposed to check for an array or a platform object
# that supports indexed properties... skip that last for now. It's a
# bit of a pain.
@ -2287,7 +2293,7 @@ for (uint32_t i = 0; i < length; ++i) {
assert len(callbackMemberTypes) == 1
memberType = callbackMemberTypes[0]
name = memberType.name
callbackObject = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${val}, ${valPtr}, tryNext)) || !tryNext;" % (unionArgumentObj, name))
callbackObject = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${obj}, ${val}, ${valPtr}, tryNext)) || !tryNext;" % (unionArgumentObj, name))
names.append(name)
else:
callbackObject = None
@ -2357,7 +2363,7 @@ for (uint32_t i = 0; i < length; ++i) {
name = memberType.inner.identifier.name
else:
name = memberType.name
other = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${val}, ${valPtr}, tryNext)) || !tryNext;" % (unionArgumentObj, name))
other = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${obj}, ${val}, ${valPtr}, tryNext)) || !tryNext;" % (unionArgumentObj, name))
names.append(name)
if hasObjectTypes:
other = CGWrapper(CGIndenter(other), "{\n", post="\n}")
@ -2804,7 +2810,7 @@ for (uint32_t i = 0; i < length; ++i) {
else:
val = "${val}"
template = ("if (!%s.Init(cx, %s)) {\n"
template = ("if (!%s.Init(cx, ${obj}, %s)) {\n"
"%s\n"
"}" % (selfRef, val, exceptionCodeIndented.define()))
@ -2994,7 +3000,8 @@ class CGArgumentConverter(CGThing):
}
self.replacementVariables = {
"declName" : "arg%d" % index,
"holderName" : ("arg%d" % index) + "_holder"
"holderName" : ("arg%d" % index) + "_holder",
"obj" : "obj"
}
self.replacementVariables["val"] = string.Template(
"${argv}[${index}]"
@ -3740,7 +3747,8 @@ class CGMethodCall(CGThing):
{
"declName" : "arg%d" % distinguishingIndex,
"holderName" : ("arg%d" % distinguishingIndex) + "_holder",
"val" : distinguishingArg
"val" : distinguishingArg,
"obj" : "obj"
})
caseBody.append(CGIndenter(testCode, indent));
# If we got this far, we know we unwrapped to the right
@ -4521,14 +4529,15 @@ return true;"""
"val": "value",
"valPtr": "pvalue",
"declName": "SetAs" + name + "()",
"holderName": "m" + name + "Holder"
"holderName": "m" + name + "Holder",
"obj": "scopeObj"
}
)
jsConversion = CGWrapper(CGGeneric(jsConversion),
post="\n"
"return true;")
setter = CGWrapper(CGIndenter(jsConversion),
pre="bool TrySetTo" + name + "(JSContext* cx, const JS::Value& value, JS::Value* pvalue, bool& tryNext)\n"
pre="bool TrySetTo" + name + "(JSContext* cx, JSObject* scopeObj, const JS::Value& value, JS::Value* pvalue, bool& tryNext)\n"
"{\n"
" tryNext = false;\n",
post="\n"
@ -5254,7 +5263,8 @@ class CGProxySpecialOperation(CGPerSignatureCall):
"declName": argument.identifier.name,
"holderName": argument.identifier.name + "_holder",
"val": "desc->value",
"valPtr": "&desc->value"
"valPtr": "&desc->value",
"obj": "obj"
}
self.cgRoot.prepend(instantiateJSToNativeConversionTemplate(template, templateValues))
elif operation.isGetter() or operation.isDeleter():
@ -6117,7 +6127,7 @@ class CGDictionary(CGThing):
return (string.Template(
"struct ${selfName} ${inheritance}{\n"
" ${selfName}() {}\n"
" bool Init(JSContext* cx, const JS::Value& val);\n"
" bool Init(JSContext* cx, JSObject* scopeObj, const JS::Value& val);\n"
" bool ToObject(JSContext* cx, JSObject* parentObject, JS::Value *vp);\n"
"\n" +
(" bool Init(const nsAString& aJSON)\n"
@ -6127,7 +6137,7 @@ class CGDictionary(CGThing):
" jsval json = JSVAL_VOID;\n"
" JSContext* cx = ParseJSON(aJSON, ar, ac, json);\n"
" NS_ENSURE_TRUE(cx, false);\n"
" return Init(cx, json);\n"
" return Init(cx, nullptr, json);\n"
" }\n" if not self.workers else "") +
"\n" +
"\n".join(memberDecls) + "\n"
@ -6144,7 +6154,7 @@ class CGDictionary(CGThing):
"struct ${selfName}Initializer : public ${selfName} {\n"
" ${selfName}Initializer() {\n"
" // Safe to pass a null context if we pass a null value\n"
" Init(nullptr, JS::NullValue());\n"
" Init(nullptr, nullptr, JS::NullValue());\n"
" }\n"
"};").substitute( { "selfName": self.makeClassName(d),
"inheritance": inheritance }))
@ -6155,7 +6165,7 @@ class CGDictionary(CGThing):
d = self.dictionary
if d.parent:
initParent = ("// Per spec, we init the parent's members first\n"
"if (!%s::Init(cx, val)) {\n"
"if (!%s::Init(cx, scopeObj, val)) {\n"
" return false;\n"
"}\n" % self.makeClassName(d.parent))
toObjectParent = ("// Per spec, we define the parent's members first\n"
@ -6203,7 +6213,7 @@ class CGDictionary(CGThing):
"}\n"
"\n" if self.needToInitIds else "") +
"bool\n"
"${selfName}::Init(JSContext* cx, const JS::Value& val)\n"
"${selfName}::Init(JSContext* cx, JSObject* scopeObj, const JS::Value& val)\n"
"{\n"
" // Passing a null JSContext is OK only if we're initing from null,\n"
" // Since in that case we will not have to do any property gets\n"
@ -6281,7 +6291,8 @@ class CGDictionary(CGThing):
# We need a holder name for external interfaces, but
# it's scoped down to the conversion so we can just use
# anything we want.
"holderName": "holder"}
"holderName": "holder",
"obj": "scopeObj" }
# We can't handle having a holderType here
assert holderType is None
if dealWithOptional:
@ -7272,7 +7283,11 @@ class CallCallback(CGNativeMember):
"val": "rval",
"valPtr": "&rval",
"holderName" : "rvalHolder",
"declName" : "rvalDecl"
"declName" : "rvalDecl",
# We actually want to pass in a null scope object here, because
# wrapping things into our current compartment (that of mCallable)
# is what we want.
"obj": "nullptr"
}
convertType = instantiateJSToNativeConversionTemplate(

View File

@ -84,7 +84,7 @@ public:
{
// Pretend like someone passed null, so we can pick up the default values
MozXMLHttpRequestParametersWorkers params;
if (!params.Init(aCx, JS::NullValue())) {
if (!params.Init(aCx, nullptr, JS::NullValue())) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}