Bug 868715 part 10. Create specializations of Optional for 'any' and 'object' types so that we can have those look like Optional<Handle<Value> > and Optional<Handle<JSObject*> > respectively. r=peterv,sfink

This commit is contained in:
Boris Zbarsky 2013-05-16 12:36:56 -04:00
parent f4608593ae
commit cab8324d5a
5 changed files with 65 additions and 26 deletions

View File

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

View File

@ -225,18 +225,24 @@ private:
};
// Class for representing optional arguments.
template<typename T>
class Optional
template<typename T, typename InternalType>
class Optional_base
{
public:
Optional()
Optional_base()
{}
explicit Optional(const T& aValue)
explicit Optional_base(const T& aValue)
{
mImpl.construct(aValue);
}
template<typename T1, typename T2>
explicit Optional_base(const T1& aValue1, const T2& aValue2)
{
mImpl.construct(aValue1, aValue2);
}
bool WasPassed() const
{
return !mImpl.empty();
@ -259,12 +265,12 @@ public:
mImpl.construct(t1, t2);
}
const T& Value() const
const InternalType& Value() const
{
return mImpl.ref();
}
T& Value()
InternalType& Value()
{
return mImpl.ref();
}
@ -275,10 +281,37 @@ public:
private:
// Forbid copy-construction and assignment
Optional(const Optional& other) MOZ_DELETE;
const Optional &operator=(const Optional &other) MOZ_DELETE;
Optional_base(const Optional_base& other) MOZ_DELETE;
const Optional_base &operator=(const Optional_base &other) MOZ_DELETE;
Maybe<T> mImpl;
Maybe<InternalType> mImpl;
};
template<typename T>
class Optional : public Optional_base<T, T>
{
public:
Optional() :
Optional_base<T, T>()
{}
explicit Optional(const T& aValue) :
Optional_base<T, T>(aValue)
{}
};
template<typename T>
class Optional<JS::Handle<T> > :
public Optional_base<JS::Handle<T>, JS::Rooted<T> >
{
public:
Optional() :
Optional_base<JS::Handle<T>, JS::Rooted<T> >()
{}
Optional(JSContext* cx, const T& aValue) :
Optional_base<JS::Handle<T>, JS::Rooted<T> >(cx, aValue)
{}
};
// Specialization for strings.

View File

@ -2619,7 +2619,12 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
# A helper function for converting things that look like a JSObject*.
def handleJSObjectType(type, isMember, failureCode):
if not isMember:
declType = CGGeneric("JS::Rooted<JSObject*>")
if isOptional:
# We have a specialization of Optional that will use a
# Rooted for the storage here.
declType = CGGeneric("JS::Handle<JSObject*>")
else:
declType = CGGeneric("JS::Rooted<JSObject*>")
else:
assert (isMember == "Sequence" or isMember == "Variadic" or
isMember == "Dictionary")
@ -3328,7 +3333,12 @@ for (uint32_t i = 0; i < length; ++i) {
declType = "JS::Value"
else:
assert not isMember
declType = "JS::Rooted<JS::Value>"
if isOptional:
# We have a specialization of Optional that will use a
# Rooted for the storage here.
declType = "JS::Handle<JS::Value>"
else:
declType = "JS::Rooted<JS::Value>"
declArgs = "cx"
templateBody = "${declName} = ${val};"
@ -8482,8 +8492,6 @@ class CGNativeMember(ClassMethod):
# Don't do the rooting stuff for variadics for now
if isMember:
declType = "JS::Value"
elif optional:
declType = "JS::Rooted<JS::Value>"
else:
declType = "JS::Handle<JS::Value>"
return declType, False, False
@ -8491,8 +8499,6 @@ class CGNativeMember(ClassMethod):
if type.isObject():
if isMember:
declType = "JSObject*"
elif optional:
declType = "JS::Rooted<JSObject*>"
else:
declType = "JS::Handle<JSObject*>"
return declType, False, False

View File

@ -140,9 +140,9 @@ public:
JS::Handle<JSObject*>,
JS::Handle<JSObject*>,
const Sequence<Dict>&,
const Optional<JS::Rooted<JS::Value> >&,
const Optional<JS::Rooted<JSObject*> >&,
const Optional<JS::Rooted<JSObject*> >&,
const Optional<JS::Handle<JS::Value> >&,
const Optional<JS::Handle<JSObject*> >&,
const Optional<JS::Handle<JSObject*> >&,
ErrorResult&);
// Integer types
@ -434,7 +434,7 @@ public:
// Any types
void PassAny(JSContext*, JS::Handle<JS::Value>);
void PassVariadicAny(JSContext*, const Sequence<JS::Value>&);
void PassOptionalAny(JSContext*, const Optional<JS::Rooted<JS::Value> >&);
void PassOptionalAny(JSContext*, const Optional<JS::Handle<JS::Value> >&);
void PassAnyDefaultNull(JSContext*, JS::Handle<JS::Value>);
void PassSequenceOfAny(JSContext*, const Sequence<JS::Value>&);
void PassNullableSequenceOfAny(JSContext*, const Nullable<Sequence<JS::Value> >&);
@ -452,8 +452,8 @@ public:
void PassVariadicObject(JSContext*, const Sequence<JSObject*>&);
void PassNullableObject(JSContext*, JS::Handle<JSObject*>);
void PassVariadicNullableObject(JSContext*, const Sequence<JSObject*>&);
void PassOptionalObject(JSContext*, const Optional<JS::Rooted<JSObject*> >&);
void PassOptionalNullableObject(JSContext*, const Optional<JS::Rooted<JSObject*> >&);
void PassOptionalObject(JSContext*, const Optional<JS::Handle<JSObject*> >&);
void PassOptionalNullableObject(JSContext*, const Optional<JS::Handle<JSObject*> >&);
void PassOptionalNullableObjectWithDefaultValue(JSContext*, JS::Handle<JSObject*>);
void PassSequenceOfObject(JSContext*, const Sequence<JSObject*>&);
void PassSequenceOfNullableObject(JSContext*, const Sequence<JSObject*>&);
@ -734,7 +734,7 @@ private:
void PassOptionalEnum(Optional<TestEnum>&) 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;
void PassOptionalAny(Optional<JS::Handle<JS::Value> >&) MOZ_DELETE;
// And test that string stuff is always const
void PassString(nsAString&) MOZ_DELETE;

View File

@ -220,7 +220,7 @@ class MOZ_STACK_CLASS Handle : public js::HandleBase<T>
*/
template <typename S>
inline
Handle(Rooted<S> &root,
Handle(const Rooted<S> &root,
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
/* Construct a read only handle from a mutable handle. */
@ -743,7 +743,7 @@ namespace JS {
template <typename T> template <typename S>
inline
Handle<T>::Handle(Rooted<S> &root,
Handle<T>::Handle(const Rooted<S> &root,
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
{
ptr = reinterpret_cast<const T *>(root.address());