Bug 868715 part 4. Use on-stack Rooted<JSObject*> for 'object' arguments in WebIDL bindings. r=peterv

This commit is contained in:
Boris Zbarsky 2013-05-16 12:36:55 -04:00
parent a0ca41113d
commit 44bd3f768a
10 changed files with 88 additions and 79 deletions

View File

@ -1199,10 +1199,9 @@ ObjectToMatrix(JSContext* cx, JS::Handle<JSObject*> obj, Matrix& matrix,
void
CanvasRenderingContext2D::SetMozCurrentTransform(JSContext* cx,
JSObject& currentTransform_,
JS::Handle<JSObject*> currentTransform,
ErrorResult& error)
{
JS::Rooted<JSObject*> currentTransform(cx, &currentTransform_);
EnsureTarget();
if (!IsTargetValid()) {
error.Throw(NS_ERROR_FAILURE);
@ -1224,10 +1223,9 @@ CanvasRenderingContext2D::GetMozCurrentTransform(JSContext* cx,
void
CanvasRenderingContext2D::SetMozCurrentTransformInverse(JSContext* cx,
JSObject& currentTransform_,
JS::Handle<JSObject*> currentTransform,
ErrorResult& error)
{
JS::Rooted<JSObject*> currentTransform(cx, &currentTransform_);
EnsureTarget();
if (!IsTargetValid()) {
error.Throw(NS_ERROR_FAILURE);

View File

@ -307,11 +307,13 @@ public:
JSObject* GetMozCurrentTransform(JSContext* cx,
mozilla::ErrorResult& error) const;
void SetMozCurrentTransform(JSContext* cx, JSObject& currentTransform,
void SetMozCurrentTransform(JSContext* cx,
JS::Handle<JSObject*> currentTransform,
mozilla::ErrorResult& error);
JSObject* GetMozCurrentTransformInverse(JSContext* cx,
mozilla::ErrorResult& error) const;
void SetMozCurrentTransformInverse(JSContext* cx, JSObject& currentTransform,
void SetMozCurrentTransformInverse(JSContext* cx,
JS::Handle<JSObject*> currentTransform,
mozilla::ErrorResult& error);
void GetFillRule(nsAString& fillRule);
void SetFillRule(const nsAString& fillRule);
@ -472,7 +474,7 @@ protected:
// Some helpers. Doesn't modify a color on failure.
void SetStyleFromJSValue(JSContext* cx, JS::Handle<JS::Value> value,
Style whichStyle);
Style whichStyle);
void SetStyleFromString(const nsAString& str, Style whichStyle);
void SetStyleFromGradient(CanvasGradient *gradient, Style whichStyle)

View File

@ -1564,6 +1564,12 @@ public:
new (storage.addr()) T();
return *storage.addr();
}
template <typename T1, typename T2>
T& SetValue(const T1 &t1, const T2 &t2)
{
new (storage.addr()) T(t1, t2);
return *storage.addr();
}
const T& Value() const {
return *storage.addr();
}

View File

@ -2616,9 +2616,18 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
return templateBody
# A helper function for converting things that look like JSObject*
# when nullable and JSObject& when not nullable.
# A helper function for converting things that look like a JSObject*.
def handleJSObjectType(type, isMember, failureCode):
if not isMember:
declType = CGGeneric("JS::Rooted<JSObject*>")
templateBody = "${declName} = &${valHandle}.toObject();"
setToNullCode = "${declName} = nullptr;"
template = wrapObjectTemplate(templateBody, type, setToNullCode,
failureCode)
return JSToNativeConversionInfo(template, declType=declType,
dealWithOptional=isOptional,
declArgs="cx")
if type.nullable():
declType = CGGeneric("LazyRootedObject")
else:
@ -4200,9 +4209,6 @@ class CGCallGenerator(CGThing):
args = CGList([CGGeneric(arg) for arg in argsPre], ", ")
for (a, name) in arguments:
# This is a workaround for a bug in Apple's clang.
if a.type.isObject() and not a.type.nullable() and not a.optional:
name = "(JSObject&)" + name
arg = CGGeneric(name)
# Now constify the things that need it
def needsConst(a):
@ -4210,7 +4216,12 @@ class CGCallGenerator(CGThing):
return True
if a.type.isSequence():
return True
if a.type.nullable():
# isObject() types are always a JS::Rooted, whether
# nullable or not, and it turns out a const JS::Rooted
# is not very helpful at all (in particular, it won't
# even convert to a JS::Handle).
# XXX bz Well, why not???
if a.type.nullable() and not a.type.isObject():
return True
if a.type.isString():
return True
@ -4284,7 +4295,9 @@ def wrapTypeIntoCurrentCompartment(type, value, isMember=True):
"}" % value)
if type.isObject():
if not type.nullable():
if not isMember:
value = value + ".address()"
elif not type.nullable():
value = "%s.Slot()" % value
else:
value = "&%s" % value
@ -5592,12 +5605,7 @@ def getUnionAccessorSignatureType(type, descriptorProvider):
return CGGeneric("JS::Value")
if type.isObject():
typeName = CGGeneric("JSObject")
if type.nullable():
typeName = CGWrapper(typeName, post="*")
else:
typeName = CGWrapper(typeName, post="&")
return typeName
return CGGeneric("JSObject*")
if not type.isPrimitive():
raise TypeError("Need native type for argument type '%s'" % str(type))
@ -5644,7 +5652,7 @@ return true;"""
if type.isObject():
setter = CGGeneric("void SetToObject(JSContext* cx, JSObject* obj)\n"
"{\n"
" mUnion.mValue.mObject.SetValue().construct(cx, obj);\n"
" mUnion.mValue.mObject.SetValue(cx, obj);\n"
" mUnion.mType = mUnion.eObject;\n"
"}")
else:
@ -5723,13 +5731,17 @@ class CGUnionStruct(CGThing):
{
MOZ_ASSERT(Is${name}(), "Wrong type!");
return const_cast<${structType}&>(mValue.m${name}.Value());
}
${structType}& SetAs${name}()
}"""
methods.extend(mapTemplate(methodTemplate, templateVars))
# Now have to be careful: we do not want the SetAsObject() method!
setterTemplate = """ ${structType}& SetAs${name}()
{
mType = e${name};
return mValue.m${name}.SetValue();
}"""
methods.extend(mapTemplate(methodTemplate, templateVars))
methods.extend(mapTemplate(setterTemplate,
filter(lambda v: v["name"] != "Object",
templateVars)))
values = mapTemplate("UnionMember<${structType} > m${name};", templateVars)
return string.Template("""
class ${structName} {
@ -5812,12 +5824,7 @@ ${doConversionsToJS}
(templateVars, type) = arg
assert not type.nullable() # flatMemberTypes never has nullable types
val = "mValue.m%(name)s.Value()" % templateVars
if type.isObject():
# We'll have a NonNullLazyRootedObject while the wrapping code wants
# a JSObject*. But our .ref() is a JS::Rooted<JSObject*>, which can
# convert to a JSObject*.
val = "%s.ref()" % val
elif type.isSpiderMonkeyInterface():
if type.isSpiderMonkeyInterface():
# We have a NonNull<TypedArray> object while the wrapping code
# wants a JSObject*. Cheat with .get() so we don't have to
# figure out the right reference type to cast to.
@ -5859,11 +5866,14 @@ class CGUnionConversionStruct(CGThing):
structName = self.type.__str__()
setters.extend(mapTemplate("${setter}", templateVars))
# Don't generate a SetAsObject, since we don't use it
private = "\n".join(mapTemplate(""" ${structType}& SetAs${name}()
{
mUnion.mType = mUnion.e${name};
return mUnion.mValue.m${name}.SetValue();
}""", templateVars))
}""",
filter(lambda v: v["name"] != "Object",
templateVars)))
private += "\n\n"
holders = filter(lambda v: v["holderType"] is not None, templateVars)
if len(holders) > 0:
@ -8236,11 +8246,7 @@ class CGNativeMember(ClassMethod):
if type.isAny():
return "JS::Value", "JS::UndefinedValue()", "return ${declName};"
if type.isObject():
if type.nullable():
returnCode = "return ${declName};"
else:
returnCode = "return ${declName}.ref();"
return "JSObject*", "nullptr", returnCode
return "JSObject*", "nullptr", "return ${declName};"
if type.isSpiderMonkeyInterface():
if type.nullable():
returnCode = "return ${declName} ? ${declName}->Obj() : nullptr;"
@ -8408,15 +8414,12 @@ class CGNativeMember(ClassMethod):
return declType, False, False
if type.isObject():
if optional:
if type.nullable():
declType = "LazyRootedObject"
else:
declType = "NonNullLazyRootedObject"
elif type.nullable() or self.jsObjectsArePtr:
if isMember:
declType = "JSObject*"
elif optional:
declType = "JS::Rooted<JSObject*>"
else:
declType = "JSObject&"
declType = "JS::Handle<JSObject*>"
return declType, False, False
if type.isDictionary():

View File

@ -137,12 +137,12 @@ public:
JSContext*,
const DictForConstructor&,
JS::Value,
JSObject&,
JSObject*,
JS::Handle<JSObject*>,
JS::Handle<JSObject*>,
const Sequence<Dict>&,
const Optional<JS::Rooted<JS::Value> >&,
const Optional<NonNullLazyRootedObject>&,
const Optional<LazyRootedObject>&,
const Optional<JS::Rooted<JSObject*> >&,
const Optional<JS::Rooted<JSObject*> >&,
ErrorResult&);
// Integer types
@ -434,23 +434,23 @@ public:
JS::Value ReceiveAny(JSContext*);
// object types
void PassObject(JSContext*, JSObject&);
void PassNullableObject(JSContext*, JSObject*);
void PassOptionalObject(JSContext*, const Optional<NonNullLazyRootedObject>&);
void PassOptionalNullableObject(JSContext*, const Optional<LazyRootedObject>&);
void PassOptionalNullableObjectWithDefaultValue(JSContext*, JSObject*);
void PassObject(JSContext*, JS::Handle<JSObject*>);
void PassNullableObject(JSContext*, JS::Handle<JSObject*>);
void PassOptionalObject(JSContext*, const Optional<JS::Rooted<JSObject*> >&);
void PassOptionalNullableObject(JSContext*, const Optional<JS::Rooted<JSObject*> >&);
void PassOptionalNullableObjectWithDefaultValue(JSContext*, JS::Handle<JSObject*>);
JSObject* ReceiveObject(JSContext*);
JSObject* ReceiveNullableObject(JSContext*);
// Union types
void PassUnion(JSContext*, const ObjectOrLong& arg);
void PassUnionWithNullable(JSContext*, const ObjectOrNullOrLong& arg)
void PassUnionWithNullable(JSContext* cx, const ObjectOrNullOrLong& arg)
{
ObjectOrLong returnValue;
if (arg.IsNull()) {
} else if (arg.IsObject()) {
JSObject& obj = (JSObject&)arg.GetAsObject();
JS_GetClass(&obj);
JS::Rooted<JSObject*> obj(cx, arg.GetAsObject());
JS_GetClass(obj);
//returnValue.SetAsObject(&obj);
} else {
int32_t i = arg.GetAsLong();
@ -698,8 +698,8 @@ private:
void PassOptionalArrayBuffer(Optional<ArrayBuffer>&) MOZ_DELETE;
void PassOptionalNullableArrayBuffer(Optional<ArrayBuffer*>&) MOZ_DELETE;
void PassOptionalEnum(Optional<TestEnum>&) MOZ_DELETE;
void PassOptionalCallback(JSContext*, Optional<JSObject*>&) MOZ_DELETE;
void PassOptionalNullableCallback(JSContext*, Optional<JSObject*>&) MOZ_DELETE;
void PassOptionalCallback(JSContext*, Optional<OwningNonNull<TestCallback> >&) MOZ_DELETE;
void PassOptionalNullableCallback(JSContext*, Optional<nsRefPtr<TestCallback> >&) MOZ_DELETE;
void PassOptionalAny(Optional<JS::Rooted<JS::Value> >&) MOZ_DELETE;
// And test that string stuff is always const

View File

@ -22,9 +22,9 @@ enum MyTestEnum {
[Constructor(DOMString str, unsigned long num, boolean? boolArg,
TestInterface? iface, long arg1,
DictForConstructor dict, any any1,
/* (BUG 856911) object obj1,*/
object obj1,
object? obj2, sequence<Dict> seq, optional any any2,
/* (BUG 856911) optional object obj3, */
optional object obj3,
optional object? obj4),
JSImplementation="@mozilla.org/test-js-impl-interface;1"]
interface TestJSImplInterface {
@ -322,12 +322,9 @@ interface TestJSImplInterface {
void passAnyDefaultNull(optional any arg = null);
any receiveAny();
// object types. Unfortunately, non-nullable object is inconsistently
// represented as either JSObject* (for callbacks) or JSObject& (for
// non-callbacks), so we can't handle those yet. See bug 856911.
//(BUG 856911) void passObject(object arg);
void passObject(object arg);
void passNullableObject(object? arg);
//(BUG 856911) void passOptionalObject(optional object arg);
void passOptionalObject(optional object arg);
void passOptionalNullableObject(optional object? arg);
void passOptionalNullableObjectWithDefaultValue(optional object? arg = null);
object receiveObject();

View File

@ -46,9 +46,9 @@ public:
bool aCapture, ErrorResult& aRv);
bool
DispatchEvent(JSObject& aEvent, ErrorResult& aRv) const
DispatchEvent(JS::Handle<JSObject*> aEvent, ErrorResult& aRv) const
{
return mListenerManager.DispatchEvent(GetJSContext(), *this, &aEvent, aRv);
return mListenerManager.DispatchEvent(GetJSContext(), *this, aEvent, aRv);
}
JSObject*

View File

@ -71,10 +71,10 @@ FileReaderSync::Constructor(const WorkerGlobalObject& aGlobal, ErrorResult& aRv)
}
JSObject*
FileReaderSync::ReadAsArrayBuffer(JSContext* aCx, JSObject& aBlob,
FileReaderSync::ReadAsArrayBuffer(JSContext* aCx, JS::Handle<JSObject*> aBlob,
ErrorResult& aRv)
{
nsIDOMBlob* blob = file::GetDOMBlobFromJSObject(&aBlob);
nsIDOMBlob* blob = file::GetDOMBlobFromJSObject(aBlob);
if (!blob) {
aRv.Throw(NS_ERROR_INVALID_ARG);
return nullptr;
@ -117,10 +117,11 @@ FileReaderSync::ReadAsArrayBuffer(JSContext* aCx, JSObject& aBlob,
}
void
FileReaderSync::ReadAsBinaryString(JSObject& aBlob, nsAString& aResult,
FileReaderSync::ReadAsBinaryString(JS::Handle<JSObject*> aBlob,
nsAString& aResult,
ErrorResult& aRv)
{
nsIDOMBlob* blob = file::GetDOMBlobFromJSObject(&aBlob);
nsIDOMBlob* blob = file::GetDOMBlobFromJSObject(aBlob);
if (!blob) {
aRv.Throw(NS_ERROR_INVALID_ARG);
return;
@ -152,12 +153,12 @@ FileReaderSync::ReadAsBinaryString(JSObject& aBlob, nsAString& aResult,
}
void
FileReaderSync::ReadAsText(JSObject& aBlob,
FileReaderSync::ReadAsText(JS::Handle<JSObject*> aBlob,
const Optional<nsAString>& aEncoding,
nsAString& aResult,
ErrorResult& aRv)
{
nsIDOMBlob* blob = file::GetDOMBlobFromJSObject(&aBlob);
nsIDOMBlob* blob = file::GetDOMBlobFromJSObject(aBlob);
if (!blob) {
aRv.Throw(NS_ERROR_INVALID_ARG);
return;
@ -208,10 +209,10 @@ FileReaderSync::ReadAsText(JSObject& aBlob,
}
void
FileReaderSync::ReadAsDataURL(JSObject& aBlob, nsAString& aResult,
FileReaderSync::ReadAsDataURL(JS::Handle<JSObject*> aBlob, nsAString& aResult,
ErrorResult& aRv)
{
nsIDOMBlob* blob = file::GetDOMBlobFromJSObject(&aBlob);
nsIDOMBlob* blob = file::GetDOMBlobFromJSObject(aBlob);
if (!blob) {
aRv.Throw(NS_ERROR_INVALID_ARG);
return;

View File

@ -42,13 +42,15 @@ public:
FileReaderSync(JSContext* aCx);
JSObject* ReadAsArrayBuffer(JSContext* aCx, JSObject& aBlob,
JSObject* ReadAsArrayBuffer(JSContext* aCx, JS::Handle<JSObject*> aBlob,
ErrorResult& aRv);
void ReadAsBinaryString(JSObject& aBlob, nsAString& aResult,
void ReadAsBinaryString(JS::Handle<JSObject*> aBlob, nsAString& aResult,
ErrorResult& aRv);
void ReadAsText(JSObject& aBlob, const Optional<nsAString>& aEncoding,
void ReadAsText(JS::Handle<JSObject*> aBlob,
const Optional<nsAString>& aEncoding,
nsAString& aResult, ErrorResult& aRv);
void ReadAsDataURL(JSObject& aBlob, nsAString& aResult, ErrorResult& aRv);
void ReadAsDataURL(JS::Handle<JSObject*> aBlob, nsAString& aResult,
ErrorResult& aRv);
// From nsICharsetDetectionObserver
NS_IMETHOD Notify(const char *aCharset, nsDetectionConfident aConf);

View File

@ -241,7 +241,7 @@ public:
}
JS::Value
GetInterface(JSContext* cx, JSObject& aIID, ErrorResult& aRv)
GetInterface(JSContext* cx, JS::Handle<JSObject*> aIID, ErrorResult& aRv)
{
aRv.Throw(NS_ERROR_FAILURE);
return JSVAL_NULL;