From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- widget/android/jni/Refs.h | 953 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 953 insertions(+) create mode 100644 widget/android/jni/Refs.h (limited to 'widget/android/jni/Refs.h') diff --git a/widget/android/jni/Refs.h b/widget/android/jni/Refs.h new file mode 100644 index 000000000..9f54ee5cd --- /dev/null +++ b/widget/android/jni/Refs.h @@ -0,0 +1,953 @@ +#ifndef mozilla_jni_Refs_h__ +#define mozilla_jni_Refs_h__ + +#include + +#include "mozilla/Move.h" +#include "mozilla/jni/Utils.h" + +#include "nsError.h" // for nsresult +#include "nsString.h" +#include "nsTArray.h" + +namespace mozilla { +namespace jni { + +// Wrapped object reference (e.g. jobject, jclass, etc...) +template class Ref; +// Represents a calling context for JNI methods. +template class Context; +// Wrapped local reference that inherits from Ref. +template class LocalRef; +// Wrapped global reference that inherits from Ref. +template class GlobalRef; +// Wrapped dangling reference that's owned by someone else. +template class DependentRef; + + +// Class to hold the native types of a method's arguments. +// For example, if a method has signature (ILjava/lang/String;)V, +// its arguments class would be jni::Args +template +struct Args {}; + + +class Object; + +// Base class for Ref and its specializations. +template +class Ref +{ + template friend class Ref; + + using Self = Ref; + using bool_type = void (Self::*)() const; + void non_null_reference() const {} + + // A Cls-derivative that allows copying + // (e.g. when acting as a return value). + struct CopyableCtx : public Context + { + CopyableCtx(JNIEnv* env, Type instance) + : Context(env, instance) + {} + + CopyableCtx(const CopyableCtx& cls) + : Context(cls.Env(), cls.Get()) + {} + }; + + // Private copy constructor so that there's no danger of assigning a + // temporary LocalRef/GlobalRef to a Ref, and potentially use the Ref + // after the source had been freed. + Ref(const Ref&) = default; + +protected: + static JNIEnv* FindEnv() + { + return Cls::callingThread == CallingThread::GECKO ? + GetGeckoThreadEnv() : GetEnvForThread(); + } + + Type mInstance; + + // Protected jobject constructor because outside code should be using + // Ref::From. Using Ref::From makes it very easy to see which code is using + // raw JNI types for future refactoring. + explicit Ref(Type instance) : mInstance(instance) {} + +public: + using JNIType = Type; + + // Construct a Ref form a raw JNI reference. + static Ref From(JNIType obj) + { + return Ref(obj); + } + + // Construct a Ref form a generic object reference. + static Ref From(const Ref& obj) + { + return Ref(JNIType(obj.Get())); + } + + MOZ_IMPLICIT Ref(decltype(nullptr)) : mInstance(nullptr) {} + + // Get the raw JNI reference. + JNIType Get() const + { + return mInstance; + } + + bool operator==(const Ref& other) const + { + // Treat two references of the same object as being the same. + return mInstance == other.mInstance || JNI_FALSE != + FindEnv()->IsSameObject(mInstance, other.mInstance); + } + + bool operator!=(const Ref& other) const + { + return !operator==(other); + } + + bool operator==(decltype(nullptr)) const + { + return !mInstance; + } + + bool operator!=(decltype(nullptr)) const + { + return !!mInstance; + } + + CopyableCtx operator->() const + { + return CopyableCtx(FindEnv(), mInstance); + } + + // Any ref can be cast to an object ref. + operator Ref() const + { + return Ref(mInstance); + } + + // Null checking (e.g. !!ref) using the safe-bool idiom. + operator bool_type() const + { + return mInstance ? &Self::non_null_reference : nullptr; + } + + // We don't allow implicit conversion to jobject because that can lead + // to easy mistakes such as assigning a temporary LocalRef to a jobject, + // and using the jobject after the LocalRef has been freed. + + // We don't allow explicit conversion, to make outside code use Ref::Get. + // Using Ref::Get makes it very easy to see which code is using raw JNI + // types to make future refactoring easier. + + // operator JNIType() const = delete; +}; + + +// Represents a calling context for JNI methods. +template +class Context : public Ref +{ + using Ref = jni::Ref; + + static jclass sClassRef; // global reference + +protected: + JNIEnv* const mEnv; + +public: + static jclass RawClassRef() + { + return sClassRef; + } + + Context() + : Ref(nullptr) + , mEnv(Ref::FindEnv()) + {} + + Context(JNIEnv* env, Type instance) + : Ref(instance) + , mEnv(env) + {} + + jclass ClassRef() const + { + if (!sClassRef) { + const jclass cls = GetClassRef(mEnv, Cls::name); + sClassRef = jclass(mEnv->NewGlobalRef(cls)); + mEnv->DeleteLocalRef(cls); + } + return sClassRef; + } + + JNIEnv* Env() const + { + return mEnv; + } + + bool operator==(const Ref& other) const + { + // Treat two references of the same object as being the same. + return Ref::mInstance == other.mInstance || JNI_FALSE != + mEnv->IsSameObject(Ref::mInstance, other.mInstance); + } + + bool operator!=(const Ref& other) const + { + return !operator==(other); + } + + bool operator==(decltype(nullptr)) const + { + return !Ref::mInstance; + } + + bool operator!=(decltype(nullptr)) const + { + return !!Ref::mInstance; + } + + Cls operator->() const + { + MOZ_ASSERT(Ref::mInstance, "Null jobject"); + return Cls(*this); + } +}; + + +template +class ObjectBase +{ +protected: + const jni::Context& mCtx; + + jclass ClassRef() const { return mCtx.ClassRef(); } + JNIEnv* Env() const { return mCtx.Env(); } + Type Instance() const { return mCtx.Get(); } + +public: + using Ref = jni::Ref; + using Context = jni::Context; + using LocalRef = jni::LocalRef; + using GlobalRef = jni::GlobalRef; + using Param = const Ref&; + + static const CallingThread callingThread = CallingThread::ANY; + static const char name[]; + + explicit ObjectBase(const Context& ctx) : mCtx(ctx) {} + + Cls* operator->() + { + return static_cast(this); + } +}; + +// Binding for a plain jobject. +class Object : public ObjectBase +{ +public: + explicit Object(const Context& ctx) : ObjectBase(ctx) {} +}; + +// Binding for a built-in object reference other than jobject. +template +class TypedObject : public ObjectBase, T> +{ +public: + explicit TypedObject(const Context, T>& ctx) + : ObjectBase, T>(ctx) + {} +}; + + +// Define bindings for built-in types. +using String = TypedObject; +using Class = TypedObject; +using Throwable = TypedObject; + +using BooleanArray = TypedObject; +using ByteArray = TypedObject; +using CharArray = TypedObject; +using ShortArray = TypedObject; +using IntArray = TypedObject; +using LongArray = TypedObject; +using FloatArray = TypedObject; +using DoubleArray = TypedObject; +using ObjectArray = TypedObject; + + +namespace detail { + +// See explanation in LocalRef. +template struct GenericObject { using Type = Object; }; +template<> struct GenericObject +{ + struct Type { + using Ref = jni::Ref; + using Context = jni::Context; + }; +}; +template struct GenericLocalRef +{ + template struct Type : jni::Object {}; +}; +template<> struct GenericLocalRef +{ + template using Type = jni::LocalRef; +}; + +} // namespace + +template +class LocalRef : public Cls::Context +{ + template friend class LocalRef; + + using Ctx = typename Cls::Context; + using Ref = typename Cls::Ref; + using JNIType = typename Ref::JNIType; + + // In order to be able to convert LocalRef to LocalRef, we + // need constructors and copy assignment operators that take in a + // LocalRef argument. However, if Cls *is* Object, we would have + // duplicated constructors and operators with LocalRef arguments. To + // avoid this conflict, we use GenericObject, which is defined as Object for + // LocalRef and defined as a dummy class for LocalRef. + using GenericObject = typename detail::GenericObject::Type; + + // Similarly, GenericLocalRef is useed to convert LocalRef to, + // LocalRef. It's defined as LocalRef for Cls == Object, + // and defined as a dummy template class for Cls != Object. + template using GenericLocalRef + = typename detail::GenericLocalRef::template Type; + + static JNIType NewLocalRef(JNIEnv* env, JNIType obj) + { + return JNIType(obj ? env->NewLocalRef(obj) : nullptr); + } + + LocalRef(JNIEnv* env, JNIType instance) : Ctx(env, instance) {} + + LocalRef& swap(LocalRef& other) + { + auto instance = other.mInstance; + other.mInstance = Ctx::mInstance; + Ctx::mInstance = instance; + return *this; + } + +public: + // Construct a LocalRef from a raw JNI local reference. Unlike Ref::From, + // LocalRef::Adopt returns a LocalRef that will delete the local reference + // when going out of scope. + static LocalRef Adopt(JNIType instance) + { + return LocalRef(Ref::FindEnv(), instance); + } + + static LocalRef Adopt(JNIEnv* env, JNIType instance) + { + return LocalRef(env, instance); + } + + // Copy constructor. + LocalRef(const LocalRef& ref) + : Ctx(ref.mEnv, NewLocalRef(ref.mEnv, ref.mInstance)) + {} + + // Move constructor. + LocalRef(LocalRef&& ref) + : Ctx(ref.mEnv, ref.mInstance) + { + ref.mInstance = nullptr; + } + + explicit LocalRef(JNIEnv* env = Ref::FindEnv()) + : Ctx(env, nullptr) + {} + + // Construct a LocalRef from any Ref, + // which means creating a new local reference. + MOZ_IMPLICIT LocalRef(const Ref& ref) + : Ctx(Ref::FindEnv(), nullptr) + { + Ctx::mInstance = NewLocalRef(Ctx::mEnv, ref.Get()); + } + + LocalRef(JNIEnv* env, const Ref& ref) + : Ctx(env, NewLocalRef(env, ref.Get())) + {} + + // Move a LocalRef into a LocalRef without + // creating/deleting local references. + MOZ_IMPLICIT LocalRef(LocalRef&& ref) + : Ctx(ref.mEnv, JNIType(ref.mInstance)) + { + ref.mInstance = nullptr; + } + + template + MOZ_IMPLICIT LocalRef(GenericLocalRef&& ref) + : Ctx(ref.mEnv, ref.mInstance) + { + ref.mInstance = nullptr; + } + + // Implicitly converts nullptr to LocalRef. + MOZ_IMPLICIT LocalRef(decltype(nullptr)) + : Ctx(Ref::FindEnv(), nullptr) + {} + + ~LocalRef() + { + if (Ctx::mInstance) { + Ctx::mEnv->DeleteLocalRef(Ctx::mInstance); + Ctx::mInstance = nullptr; + } + } + + // Get the raw JNI reference that can be used as a return value. + // Returns the same JNI type (jobject, jstring, etc.) as the underlying Ref. + typename Ref::JNIType Forget() + { + const auto obj = Ctx::Get(); + Ctx::mInstance = nullptr; + return obj; + } + + LocalRef& operator=(LocalRef ref) + { + return swap(ref); + } + + LocalRef& operator=(const Ref& ref) + { + LocalRef newRef(Ctx::mEnv, ref); + return swap(newRef); + } + + LocalRef& operator=(LocalRef&& ref) + { + LocalRef newRef(mozilla::Move(ref)); + return swap(newRef); + } + + template + LocalRef& operator=(GenericLocalRef&& ref) + { + LocalRef newRef(mozilla::Move(ref)); + return swap(newRef); + } + + LocalRef& operator=(decltype(nullptr)) + { + LocalRef newRef(Ctx::mEnv, nullptr); + return swap(newRef); + } +}; + + +template +class GlobalRef : public Cls::Ref +{ + using Ref = typename Cls::Ref; + using JNIType = typename Ref::JNIType; + + static JNIType NewGlobalRef(JNIEnv* env, JNIType instance) + { + return JNIType(instance ? env->NewGlobalRef(instance) : nullptr); + } + + GlobalRef& swap(GlobalRef& other) + { + auto instance = other.mInstance; + other.mInstance = Ref::mInstance; + Ref::mInstance = instance; + return *this; + } + +public: + GlobalRef() + : Ref(nullptr) + {} + + // Copy constructor + GlobalRef(const GlobalRef& ref) + : Ref(NewGlobalRef(GetEnvForThread(), ref.mInstance)) + {} + + // Move constructor + GlobalRef(GlobalRef&& ref) + : Ref(ref.mInstance) + { + ref.mInstance = nullptr; + } + + MOZ_IMPLICIT GlobalRef(const Ref& ref) + : Ref(NewGlobalRef(GetEnvForThread(), ref.Get())) + {} + + GlobalRef(JNIEnv* env, const Ref& ref) + : Ref(NewGlobalRef(env, ref.Get())) + {} + + MOZ_IMPLICIT GlobalRef(const LocalRef& ref) + : Ref(NewGlobalRef(ref.Env(), ref.Get())) + {} + + // Implicitly converts nullptr to GlobalRef. + MOZ_IMPLICIT GlobalRef(decltype(nullptr)) + : Ref(nullptr) + {} + + ~GlobalRef() + { + if (Ref::mInstance) { + Clear(GetEnvForThread()); + } + } + + // Get the raw JNI reference that can be used as a return value. + // Returns the same JNI type (jobject, jstring, etc.) as the underlying Ref. + typename Ref::JNIType Forget() + { + const auto obj = Ref::Get(); + Ref::mInstance = nullptr; + return obj; + } + + void Clear(JNIEnv* env) + { + if (Ref::mInstance) { + env->DeleteGlobalRef(Ref::mInstance); + Ref::mInstance = nullptr; + } + } + + GlobalRef& operator=(GlobalRef ref) + { + return swap(ref); + } + + GlobalRef& operator=(const Ref& ref) + { + GlobalRef newRef(ref); + return swap(newRef); + } + + GlobalRef& operator=(const LocalRef& ref) + { + GlobalRef newRef(ref); + return swap(newRef); + } + + GlobalRef& operator=(decltype(nullptr)) + { + GlobalRef newRef(nullptr); + return swap(newRef); + } +}; + + +template +class DependentRef : public Cls::Ref +{ + using Ref = typename Cls::Ref; + +public: + DependentRef(typename Ref::JNIType instance) + : Ref(instance) + {} + + DependentRef(const DependentRef& ref) + : Ref(ref.Get()) + {} +}; + + +class StringParam; + +template<> +class TypedObject : public ObjectBase, jstring> +{ + using Base = ObjectBase, jstring>; + +public: + using Param = const StringParam&; + + explicit TypedObject(const Context& ctx) : Base(ctx) {} + + size_t Length() const + { + const size_t ret = Base::Env()->GetStringLength(Base::Instance()); + MOZ_CATCH_JNI_EXCEPTION(Base::Env()); + return ret; + } + + nsString ToString() const + { + const jchar* const str = Base::Env()->GetStringChars( + Base::Instance(), nullptr); + const jsize len = Base::Env()->GetStringLength(Base::Instance()); + + nsString result(reinterpret_cast(str), len); + Base::Env()->ReleaseStringChars(Base::Instance(), str); + return result; + } + + nsCString ToCString() const + { + return NS_ConvertUTF16toUTF8(ToString()); + } + + // Convert jstring to a nsString. + operator nsString() const + { + return ToString(); + } + + // Convert jstring to a nsCString. + operator nsCString() const + { + return ToCString(); + } +}; + +// Define a custom parameter type for String, +// which accepts both String::Ref and nsAString/nsACString +class StringParam : public String::Ref +{ + using Ref = String::Ref; + +private: + // Not null if we should delete ref on destruction. + JNIEnv* const mEnv; + + static jstring GetString(JNIEnv* env, const nsAString& str) + { + const jstring result = env->NewString( + reinterpret_cast(str.BeginReading()), + str.Length()); + MOZ_CATCH_JNI_EXCEPTION(env); + return result; + } + +public: + MOZ_IMPLICIT StringParam(decltype(nullptr)) + : Ref(nullptr) + , mEnv(nullptr) + {} + + MOZ_IMPLICIT StringParam(const Ref& ref) + : Ref(ref.Get()) + , mEnv(nullptr) + {} + + MOZ_IMPLICIT StringParam(const nsAString& str, JNIEnv* env = Ref::FindEnv()) + : Ref(GetString(env, str)) + , mEnv(env) + {} + + MOZ_IMPLICIT StringParam(const char16_t* str, JNIEnv* env = Ref::FindEnv()) + : Ref(GetString(env, nsDependentString(str))) + , mEnv(env) + {} + + MOZ_IMPLICIT StringParam(const nsACString& str, JNIEnv* env = Ref::FindEnv()) + : Ref(GetString(env, NS_ConvertUTF8toUTF16(str))) + , mEnv(env) + {} + + MOZ_IMPLICIT StringParam(const char* str, JNIEnv* env = Ref::FindEnv()) + : Ref(GetString(env, NS_ConvertUTF8toUTF16(str))) + , mEnv(env) + {} + + StringParam(StringParam&& other) + : Ref(other.Get()) + , mEnv(other.mEnv) + { + other.mInstance = nullptr; + } + + ~StringParam() + { + if (mEnv && Get()) { + mEnv->DeleteLocalRef(Get()); + } + } + + operator String::LocalRef() const + { + // We can't return our existing ref because the returned + // LocalRef could be freed first, so we need a new local ref. + return String::LocalRef(mEnv ? mEnv : Ref::FindEnv(), *this); + } +}; + + +namespace detail { + template struct TypeAdapter; +} + +// Ref specialization for arrays. +template +class ArrayRefBase : public ObjectBase, JNIType> +{ + using Base = ObjectBase, JNIType>; + +public: + explicit ArrayRefBase(const Context, JNIType>& ctx) + : Base(ctx) + {} + + static typename Base::LocalRef New(const ElementType* data, size_t length) { + using JNIElemType = typename detail::TypeAdapter::JNIType; + static_assert(sizeof(ElementType) == sizeof(JNIElemType), + "Size of native type must match size of JNI type"); + JNIEnv* const jenv = mozilla::jni::GetEnvForThread(); + auto result = + (jenv->*detail::TypeAdapter::NewArray)(length); + MOZ_CATCH_JNI_EXCEPTION(jenv); + (jenv->*detail::TypeAdapter::SetArray)( + result, jsize(0), length, + reinterpret_cast(data)); + MOZ_CATCH_JNI_EXCEPTION(jenv); + return Base::LocalRef::Adopt(jenv, result); + } + + size_t Length() const + { + const size_t ret = Base::Env()->GetArrayLength(Base::Instance()); + MOZ_CATCH_JNI_EXCEPTION(Base::Env()); + return ret; + } + + ElementType GetElement(size_t index) const + { + using JNIElemType = typename detail::TypeAdapter::JNIType; + static_assert(sizeof(ElementType) == sizeof(JNIElemType), + "Size of native type must match size of JNI type"); + + ElementType ret; + (Base::Env()->*detail::TypeAdapter::GetArray)( + Base::Instance(), jsize(index), 1, + reinterpret_cast(&ret)); + MOZ_CATCH_JNI_EXCEPTION(Base::Env()); + return ret; + } + + nsTArray GetElements() const + { + using JNIElemType = typename detail::TypeAdapter::JNIType; + static_assert(sizeof(ElementType) == sizeof(JNIElemType), + "Size of native type must match size of JNI type"); + + const jsize len = size_t(Base::Env()->GetArrayLength(Base::Instance())); + + nsTArray array((size_t(len))); + array.SetLength(size_t(len)); + (Base::Env()->*detail::TypeAdapter::GetArray)( + Base::Instance(), 0, len, + reinterpret_cast(array.Elements())); + return array; + } + + ElementType operator[](size_t index) const + { + return GetElement(index); + } + + operator nsTArray() const + { + return GetElements(); + } +}; + +#define DEFINE_PRIMITIVE_ARRAY_REF(JNIType, ElementType) \ + template<> \ + class TypedObject : public ArrayRefBase \ + { \ + public: \ + explicit TypedObject(const Context& ctx) \ + : ArrayRefBase(ctx) \ + {} \ + } + +DEFINE_PRIMITIVE_ARRAY_REF(jbooleanArray, bool); +DEFINE_PRIMITIVE_ARRAY_REF(jbyteArray, int8_t); +DEFINE_PRIMITIVE_ARRAY_REF(jcharArray, char16_t); +DEFINE_PRIMITIVE_ARRAY_REF(jshortArray, int16_t); +DEFINE_PRIMITIVE_ARRAY_REF(jintArray, int32_t); +DEFINE_PRIMITIVE_ARRAY_REF(jlongArray, int64_t); +DEFINE_PRIMITIVE_ARRAY_REF(jfloatArray, float); +DEFINE_PRIMITIVE_ARRAY_REF(jdoubleArray, double); + +#undef DEFINE_PRIMITIVE_ARRAY_REF + + +class ByteBuffer : public ObjectBase +{ +public: + explicit ByteBuffer(const Context& ctx) + : ObjectBase(ctx) + {} + + static LocalRef New(void* data, size_t capacity) + { + JNIEnv* const env = GetEnvForThread(); + const auto ret = LocalRef::Adopt( + env, env->NewDirectByteBuffer(data, jlong(capacity))); + MOZ_CATCH_JNI_EXCEPTION(env); + return ret; + } + + void* Address() + { + void* const ret = Env()->GetDirectBufferAddress(Instance()); + MOZ_CATCH_JNI_EXCEPTION(Env()); + return ret; + } + + size_t Capacity() + { + const size_t ret = size_t(Env()->GetDirectBufferCapacity(Instance())); + MOZ_CATCH_JNI_EXCEPTION(Env()); + return ret; + } +}; + + +template<> +class TypedObject + : public ObjectBase, jobjectArray> +{ + using Base = ObjectBase, jobjectArray>; + +public: + explicit TypedObject(const Context& ctx) : Base(ctx) {} + + size_t Length() const + { + const size_t ret = Base::Env()->GetArrayLength(Base::Instance()); + MOZ_CATCH_JNI_EXCEPTION(Base::Env()); + return ret; + } + + Object::LocalRef GetElement(size_t index) const + { + auto ret = Object::LocalRef::Adopt( + Base::Env(), Base::Env()->GetObjectArrayElement( + Base::Instance(), jsize(index))); + MOZ_CATCH_JNI_EXCEPTION(Base::Env()); + return ret; + } + + nsTArray GetElements() const + { + const jsize len = size_t(Base::Env()->GetArrayLength(Base::Instance())); + + nsTArray array((size_t(len))); + for (jsize i = 0; i < len; i++) { + array.AppendElement(Object::LocalRef::Adopt( + Base::Env(), Base::Env()->GetObjectArrayElement( + Base::Instance(), i))); + MOZ_CATCH_JNI_EXCEPTION(Base::Env()); + } + return array; + } + + Object::LocalRef operator[](size_t index) const + { + return GetElement(index); + } + + operator nsTArray() const + { + return GetElements(); + } + + void SetElement(size_t index, Object::Param element) const + { + Base::Env()->SetObjectArrayElement( + Base::Instance(), jsize(index), element.Get()); + MOZ_CATCH_JNI_EXCEPTION(Base::Env()); + } +}; + + +// Support conversion from LocalRef* to LocalRef*: +// LocalRef foo; +// Foo::GetFoo(&foo); // error because parameter type is LocalRef*. +// Foo::GetFoo(ReturnTo(&foo)); // OK because ReturnTo converts the argument. +template +class ReturnToLocal +{ +private: + LocalRef* const localRef; + LocalRef objRef; + +public: + explicit ReturnToLocal(LocalRef* ref) : localRef(ref) {} + operator LocalRef*() { return &objRef; } + + ~ReturnToLocal() + { + if (objRef) { + *localRef = mozilla::Move(objRef); + } + } +}; + +template +ReturnToLocal ReturnTo(LocalRef* ref) +{ + return ReturnToLocal(ref); +} + + +// Support conversion from GlobalRef* to LocalRef*: +// GlobalRef foo; +// Foo::GetFoo(&foo); // error because parameter type is LocalRef*. +// Foo::GetFoo(ReturnTo(&foo)); // OK because ReturnTo converts the argument. +template +class ReturnToGlobal +{ +private: + GlobalRef* const globalRef; + LocalRef objRef; + LocalRef clsRef; + +public: + explicit ReturnToGlobal(GlobalRef* ref) : globalRef(ref) {} + operator LocalRef*() { return &objRef; } + operator LocalRef*() { return &clsRef; } + + ~ReturnToGlobal() + { + if (objRef) { + *globalRef = (clsRef = mozilla::Move(objRef)); + } else if (clsRef) { + *globalRef = clsRef; + } + } +}; + +template +ReturnToGlobal ReturnTo(GlobalRef* ref) +{ + return ReturnToGlobal(ref); +} + +} // namespace jni +} // namespace mozilla + +#endif // mozilla_jni_Refs_h__ -- cgit v1.2.3