Bug 865969 part 2. Better rooting in bindings for 'any' arguments. r=smaug

This commit is contained in:
Boris Zbarsky 2013-05-03 19:29:07 -04:00
parent 4d5cf6450f
commit bb2222c08c
7 changed files with 56 additions and 22 deletions

View File

@ -1254,7 +1254,7 @@ CanvasRenderingContext2D::GetMozCurrentTransformInverse(JSContext* cx,
void
CanvasRenderingContext2D::SetStyleFromJSValue(JSContext* cx,
JS::Value& value,
JS::Handle<JS::Value> value,
Style whichStyle)
{
if (value.isString()) {
@ -1269,9 +1269,10 @@ CanvasRenderingContext2D::SetStyleFromJSValue(JSContext* cx,
nsCOMPtr<nsISupports> holder;
CanvasGradient* gradient;
JS::Rooted<JS::Value> rootedVal(cx, value);
nsresult rv = xpc_qsUnwrapArg<CanvasGradient>(cx, value, &gradient,
static_cast<nsISupports**>(getter_AddRefs(holder)),
&value);
rootedVal.address());
if (NS_SUCCEEDED(rv)) {
SetStyleFromGradient(gradient, whichStyle);
return;
@ -1280,7 +1281,7 @@ CanvasRenderingContext2D::SetStyleFromJSValue(JSContext* cx,
CanvasPattern* pattern;
rv = xpc_qsUnwrapArg<CanvasPattern>(cx, value, &pattern,
static_cast<nsISupports**>(getter_AddRefs(holder)),
&value);
rootedVal.address());
if (NS_SUCCEEDED(rv)) {
SetStyleFromPattern(pattern, whichStyle);
return;

View File

@ -92,14 +92,14 @@ public:
mozilla::ErrorResult& error);
JS::Value GetStrokeStyle(JSContext* cx, mozilla::ErrorResult& error);
void SetStrokeStyle(JSContext* cx, JS::Value& value)
void SetStrokeStyle(JSContext* cx, JS::Handle<JS::Value> value)
{
SetStyleFromJSValue(cx, value, STYLE_STROKE);
}
JS::Value GetFillStyle(JSContext* cx, mozilla::ErrorResult& error);
void SetFillStyle(JSContext* cx, JS::Value& value)
void SetFillStyle(JSContext* cx, JS::Handle<JS::Value> value)
{
SetStyleFromJSValue(cx, value, STYLE_FILL);
}
@ -471,7 +471,8 @@ protected:
static mozilla::gfx::DrawTarget* sErrorTarget;
// Some helpers. Doesn't modify a color on failure.
void SetStyleFromJSValue(JSContext* cx, JS::Value& value, Style whichStyle);
void SetStyleFromJSValue(JSContext* cx, JS::Handle<JS::Value> value,
Style whichStyle);
void SetStyleFromString(const nsAString& str, Style whichStyle);
void SetStyleFromGradient(CanvasGradient *gradient, Style whichStyle)

View File

@ -54,7 +54,7 @@ public:
const nsAString& aType,
bool aCanBubble,
bool aCancelable,
JS::Value& aData,
JS::Value aData,
const nsAString& aOrigin,
const nsAString& aLastEventId,
nsIDOMWindow* aSource,

View File

@ -92,7 +92,7 @@ public:
}
already_AddRefed<nsISupports>
GetContext(JSContext* aCx, const nsAString& aContextId,
const Optional<JS::Value>& aContextOptions, ErrorResult& aRv)
const Optional<LazyRootedValue>& aContextOptions, ErrorResult& aRv)
{
JS::Value contextOptions = aContextOptions.WasPassed()
? aContextOptions.Value()
@ -102,7 +102,7 @@ public:
return context.forget();
}
void ToDataURL(JSContext* aCx, const nsAString& aType,
const Optional<JS::Value>& aParams, nsAString& aDataURL,
const Optional<LazyRootedValue>& aParams, nsAString& aDataURL,
ErrorResult& aRv)
{
JS::Value params = aParams.WasPassed()

View File

@ -515,6 +515,34 @@ public:
}
};
class LazyRootedValue : public Maybe<JS::Rooted<JS::Value> >
{
public:
operator JS::Value() const
{
// Assert if we're empty, on purpose
return ref();
}
operator JS::Rooted<JS::Value>& ()
{
// Assert if we're empty, on purpose
return ref();
}
operator JS::Handle<JS::Value>()
{
// Assert if we're empty, on purpose
return ref();
}
JS::Value* operator&()
{
// Assert if we're empty, on purpose
return ref().address();
}
};
} // namespace dom
} // namespace mozilla

View File

@ -3222,20 +3222,19 @@ for (uint32_t i = 0; i < length; ++i) {
if type.isAny():
assert not isEnforceRange and not isClamp
if isMember == "Dictionary":
declType = "RootedJSValue"
templateBody = ("if (!${declName}.SetValue(cx, ${val})) {\n"
" return false;\n"
"}")
nullHandling = "${declName}.SetValue(nullptr, JS::NullValue())"
elif isMember and isMember != "Variadic":
# Variadic arguments are rooted by being in argv
if isMember == "Dictionary" or not isMember:
declType = "LazyRootedValue"
templateBody = "${declName}.construct(cx, ${val});"
nullHandling = "${declName}.construct(cx, JS::NullValue());"
elif isMember != "Variadic":
raise TypeError("Can't handle sequence member 'any'; need to sort "
"out rooting issues")
else:
# Variadic arguments are rooted by being in argv
declType = "JS::Value"
templateBody = "${declName} = ${val};"
nullHandling = "${declName} = JS::NullValue()"
templateBody = handleDefaultNull(templateBody, nullHandling)
return (templateBody, CGGeneric(declType), None, isOptional)
@ -8115,7 +8114,7 @@ class CGNativeMember(ClassMethod):
args.insert(0, Argument("const %s&" % globalObjectType, "global"))
return args
def doGetArgType(self, type, optional, isMember):
def doGetArgType(self, type, optional, variadic, isMember):
"""
The main work of getArgType. Returns a string type decl, whether this
is a const ref, as well as whether the type should be wrapped in
@ -8204,7 +8203,12 @@ class CGNativeMember(ClassMethod):
return declType % name, False, False
if type.isAny():
return "JS::Value", False, False
# Don't do the rooting stuff for variadics for now
if optional and not variadic:
declType = "LazyRootedValue"
else:
declType = "JS::Value"
return declType, False, False
if type.isObject():
if optional:
@ -8235,7 +8239,7 @@ class CGNativeMember(ClassMethod):
Get the type of an argument declaration. Returns the type CGThing, and
whether this should be a const ref.
"""
(decl, ref, handleNullable) = self.doGetArgType(type, optional,
(decl, ref, handleNullable) = self.doGetArgType(type, optional, variadic,
isMember or variadic)
decl = CGGeneric(decl)
if handleNullable and type.nullable():

View File

@ -140,7 +140,7 @@ public:
JSObject&,
JSObject*,
const Sequence<Dict>&,
const Optional<JS::Value>&,
const Optional<LazyRootedValue>&,
const Optional<NonNullLazyRootedObject>&,
const Optional<LazyRootedObject>&,
ErrorResult&);
@ -429,7 +429,7 @@ public:
// Any types
void PassAny(JSContext*, JS::Value);
void PassOptionalAny(JSContext*, const Optional<JS::Value>&);
void PassOptionalAny(JSContext*, const Optional<LazyRootedValue>&);
void PassAnyDefaultNull(JSContext*, JS::Value);
JS::Value ReceiveAny(JSContext*);