summaryrefslogtreecommitdiff
path: root/widget/android/NativeJSContainer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'widget/android/NativeJSContainer.cpp')
-rw-r--r--widget/android/NativeJSContainer.cpp881
1 files changed, 0 insertions, 881 deletions
diff --git a/widget/android/NativeJSContainer.cpp b/widget/android/NativeJSContainer.cpp
deleted file mode 100644
index b8c434656c..0000000000
--- a/widget/android/NativeJSContainer.cpp
+++ /dev/null
@@ -1,881 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "NativeJSContainer.h"
-
-#include <jni.h>
-
-#include "Bundle.h"
-#include "GeneratedJNINatives.h"
-#include "MainThreadUtils.h"
-#include "jsapi.h"
-#include "nsJSUtils.h"
-
-#include <mozilla/Vector.h>
-#include <mozilla/jni/Accessors.h>
-#include <mozilla/jni/Refs.h>
-#include <mozilla/jni/Utils.h>
-
-/**
- * NativeJSContainer.cpp implements the native methods in both
- * NativeJSContainer and NativeJSObject, using JSAPI to retrieve values from a
- * JSObject and using JNI to return those values to Java code.
- */
-
-namespace mozilla {
-namespace widget {
-
-namespace {
-
-bool CheckThread()
-{
- if (!NS_IsMainThread()) {
- jni::ThrowException("java/lang/IllegalThreadStateException",
- "Not on Gecko thread");
- return false;
- }
- return true;
-}
-
-template<class C, typename T> bool
-CheckJNIArgument(const jni::Ref<C, T>& arg)
-{
- if (!arg) {
- jni::ThrowException("java/lang/IllegalArgumentException",
- "Null argument");
- }
- return !!arg;
-}
-
-nsresult
-CheckSDKCall(nsresult rv)
-{
- if (NS_FAILED(rv)) {
- jni::ThrowException("java/lang/UnsupportedOperationException",
- "SDK JNI call failed");
- }
- return rv;
-}
-
-// Convert a JNI string to a char16_t string that JSAPI expects.
-class JSJNIString final
-{
- JNIEnv* const mEnv;
- jni::String::Param mJNIString;
- const char16_t* const mJSString;
-
-public:
- JSJNIString(JNIEnv* env, jni::String::Param str)
- : mEnv(env)
- , mJNIString(str)
- , mJSString(!str ? nullptr : reinterpret_cast<const char16_t*>(
- mEnv->GetStringChars(str.Get(), nullptr)))
- {}
-
- ~JSJNIString() {
- if (mJNIString) {
- mEnv->ReleaseStringChars(mJNIString.Get(),
- reinterpret_cast<const jchar*>(mJSString));
- }
- }
-
- operator const char16_t*() const {
- return mJSString;
- }
-
- size_t Length() const {
- return static_cast<size_t>(mEnv->GetStringLength(mJNIString.Get()));
- }
-};
-
-} // namepsace
-
-class NativeJSContainerImpl final
- : public NativeJSObject::Natives<NativeJSContainerImpl>
- , public NativeJSContainer::Natives<NativeJSContainerImpl>
-{
- typedef NativeJSContainerImpl Self;
- typedef NativeJSContainer::Natives<NativeJSContainerImpl> ContainerBase;
- typedef NativeJSObject::Natives<NativeJSContainerImpl> ObjectBase;
-
- typedef JS::PersistentRooted<JSObject*> PersistentObject;
-
- JNIEnv* const mEnv;
- // Context that the object is valid in
- JSContext* const mJSContext;
- // Root JS object
- PersistentObject mJSObject;
- // Children objects
- Vector<NativeJSObject::GlobalRef, 0> mChildren;
-
- bool CheckObject() const
- {
- if (!mJSObject) {
- jni::ThrowException("java/lang/NullPointerException",
- "Null JSObject");
- }
- return !!mJSObject;
- }
-
- bool CheckJSCall(bool result) const
- {
- if (!result) {
- JS_ClearPendingException(mJSContext);
- jni::ThrowException("java/lang/UnsupportedOperationException",
- "JSAPI call failed");
- }
- return result;
- }
-
- // Check that a JS Value contains a particular property type as indicaed by
- // the property's InValue method (e.g. StringProperty::InValue).
- bool CheckProperty(bool (Self::*InValue)(JS::HandleValue) const,
- JS::HandleValue val) const
- {
- if (!(this->*InValue)(val)) {
- // XXX this can happen when converting a double array inside a
- // Bundle, because double arrays can be misidentified as an int
- // array. The workaround is to add a dummy first element to the
- // array that is a floating point value, i.e. [0.5, ...].
- jni::ThrowException(
- "org/mozilla/gecko/util/NativeJSObject$InvalidPropertyException",
- "Property type mismatch");
- return false;
- }
- return true;
- }
-
- // Primitive properties
-
- template<bool (JS::Value::*IsType)() const> bool
- PrimitiveInValue(JS::HandleValue val) const
- {
- return (static_cast<const JS::Value&>(val).*IsType)();
- }
-
- template<typename U, U (JS::Value::*ToType)() const> U
- PrimitiveFromValue(JS::HandleValue val) const
- {
- return (static_cast<const JS::Value&>(val).*ToType)();
- }
-
- template<class Prop> typename Prop::NativeArray
- PrimitiveNewArray(JS::HandleObject array, size_t length) const
- {
- typedef typename Prop::JNIType JNIType;
-
- // Fill up a temporary buffer for our array, then use
- // JNIEnv::Set*ArrayRegion to fill out array in one go.
-
- UniquePtr<JNIType[]> buffer = MakeUnique<JNIType[]>(length);
- for (size_t i = 0; i < length; i++) {
- JS::RootedValue elem(mJSContext);
- if (!CheckJSCall(JS_GetElement(mJSContext, array, i, &elem)) ||
- !CheckProperty(Prop::InValue, elem)) {
- return nullptr;
- }
- buffer[i] = JNIType((this->*Prop::FromValue)(elem));
- }
- auto jarray = Prop::NativeArray::Adopt(
- mEnv, (mEnv->*Prop::NewJNIArray)(length));
- if (!jarray) {
- return nullptr;
- }
- (mEnv->*Prop::SetJNIArrayRegion)(
- jarray.Get(), 0, length, buffer.get());
- if (mEnv->ExceptionCheck()) {
- return nullptr;
- }
- return jarray;
- }
-
- template<typename U, typename UA, typename V, typename VA,
- bool (JS::Value::*IsType)() const,
- U (JS::Value::*ToType)() const,
- VA (JNIEnv::*NewArray_)(jsize),
- void (JNIEnv::*SetArrayRegion_)(VA, jsize, jsize, const V*)>
- struct PrimitiveProperty
- {
- // C++ type for a primitive property (e.g. bool)
- typedef U NativeType;
- // C++ type for the fallback value used in opt* methods
- typedef U NativeFallback;
- // Type for an array of the primitive type (e.g. BooleanArray::LocalRef)
- typedef typename UA::LocalRef NativeArray;
- // Type for the fallback value used in opt*Array methods
- typedef const typename UA::Ref ArrayFallback;
- // JNI type (e.g. jboolean)
- typedef V JNIType;
-
- // JNIEnv function to create a new JNI array of the primiive type
- typedef decltype(NewArray_) NewJNIArray_t;
- static constexpr NewJNIArray_t NewJNIArray = NewArray_;
-
- // JNIEnv function to fill a JNI array of the primiive type
- typedef decltype(SetArrayRegion_) SetJNIArrayRegion_t;
- static constexpr SetJNIArrayRegion_t SetJNIArrayRegion = SetArrayRegion_;
-
- // Function to determine if a JS Value contains the primitive type
- typedef decltype(&Self::PrimitiveInValue<IsType>) InValue_t;
- static constexpr InValue_t InValue = &Self::PrimitiveInValue<IsType>;
-
- // Function to convert a JS Value to the primitive type
- typedef decltype(&Self::PrimitiveFromValue<U, ToType>) FromValue_t;
- static constexpr FromValue_t FromValue
- = &Self::PrimitiveFromValue<U, ToType>;
-
- // Function to convert a JS array to a JNI array
- typedef decltype(&Self::PrimitiveNewArray<PrimitiveProperty>) NewArray_t;
- static constexpr NewArray_t NewArray
- = &Self::PrimitiveNewArray<PrimitiveProperty>;
- };
-
- // String properties
-
- bool StringInValue(JS::HandleValue val) const
- {
- return val.isString();
- }
-
- jni::String::LocalRef
- StringFromValue(const JS::HandleString str) const
- {
- nsAutoJSString autoStr;
- if (!CheckJSCall(autoStr.init(mJSContext, str))) {
- return nullptr;
- }
- // StringParam can automatically convert a nsString to jstring.
- return jni::StringParam(autoStr, mEnv);
- }
-
- jni::String::LocalRef
- StringFromValue(JS::HandleValue val)
- {
- const JS::RootedString str(mJSContext, val.toString());
- return StringFromValue(str);
- }
-
- // Bundle properties
-
- sdk::Bundle::LocalRef
- BundleFromValue(const JS::HandleObject obj)
- {
- JS::Rooted<JS::IdVector> ids(mJSContext, JS::IdVector(mJSContext));
- if (!CheckJSCall(JS_Enumerate(mJSContext, obj, &ids))) {
- return nullptr;
- }
-
- const size_t length = ids.length();
- sdk::Bundle::LocalRef newBundle(mEnv);
- NS_ENSURE_SUCCESS(CheckSDKCall(
- sdk::Bundle::New(length, &newBundle)), nullptr);
-
- // Iterate through each property of the JS object. For each property,
- // determine its type from a list of supported types, and convert that
- // proeprty to the supported type.
-
- for (size_t i = 0; i < ids.length(); i++) {
- const JS::RootedId id(mJSContext, ids[i]);
- JS::RootedValue idVal(mJSContext);
- if (!CheckJSCall(JS_IdToValue(mJSContext, id, &idVal))) {
- return nullptr;
- }
-
- const JS::RootedString idStr(mJSContext,
- JS::ToString(mJSContext, idVal));
- if (!CheckJSCall(!!idStr)) {
- return nullptr;
- }
-
- jni::String::LocalRef name = StringFromValue(idStr);
- JS::RootedValue val(mJSContext);
- if (!name ||
- !CheckJSCall(JS_GetPropertyById(mJSContext, obj, id, &val))) {
- return nullptr;
- }
-
-#define PUT_IN_BUNDLE_IF_TYPE_IS(TYPE) \
- if ((this->*TYPE##Property::InValue)(val)) { \
- auto jval = (this->*TYPE##Property::FromValue)(val); \
- if (mEnv->ExceptionCheck()) { \
- return nullptr; \
- } \
- NS_ENSURE_SUCCESS(CheckSDKCall( \
- newBundle->Put##TYPE(name, jval)), nullptr); \
- continue; \
- } \
- ((void) 0) // Accommodate trailing semicolon.
-
- // Scalar values are faster to check, so check them first.
- PUT_IN_BUNDLE_IF_TYPE_IS(Boolean);
- // Int can be casted to double, so check int first.
- PUT_IN_BUNDLE_IF_TYPE_IS(Int);
- PUT_IN_BUNDLE_IF_TYPE_IS(Double);
- PUT_IN_BUNDLE_IF_TYPE_IS(String);
- // There's no "putObject", so don't check ObjectProperty
-
- // Check for array types if scalar checks all failed.
- // XXX empty arrays are treated as boolean arrays. Workaround is
- // to always have a dummy element to create a non-empty array.
- PUT_IN_BUNDLE_IF_TYPE_IS(BooleanArray);
- // XXX because we only check the first element of an array,
- // a double array can potentially be seen as an int array.
- // When that happens, the Bundle conversion will fail.
- PUT_IN_BUNDLE_IF_TYPE_IS(IntArray);
- PUT_IN_BUNDLE_IF_TYPE_IS(DoubleArray);
- PUT_IN_BUNDLE_IF_TYPE_IS(StringArray);
- // There's no "putObjectArray", so don't check ObjectArrayProperty
- // There's no "putBundleArray", so don't check BundleArrayProperty
-
- // Use Bundle as the default catch-all for objects
- PUT_IN_BUNDLE_IF_TYPE_IS(Bundle);
-
-#undef PUT_IN_BUNDLE_IF_TYPE_IS
-
- // We tried all supported types; just bail.
- jni::ThrowException("java/lang/UnsupportedOperationException",
- "Unsupported property type");
- return nullptr;
- }
- return jni::Object::LocalRef::Adopt(newBundle.Env(),
- newBundle.Forget());
- }
-
- sdk::Bundle::LocalRef
- BundleFromValue(JS::HandleValue val)
- {
- if (val.isNull()) {
- return nullptr;
- }
- JS::RootedObject object(mJSContext, &val.toObject());
- return BundleFromValue(object);
- }
-
- // Object properties
-
- bool ObjectInValue(JS::HandleValue val) const
- {
- return val.isObjectOrNull();
- }
-
- NativeJSObject::LocalRef
- ObjectFromValue(JS::HandleValue val)
- {
- if (val.isNull()) {
- return nullptr;
- }
- JS::RootedObject object(mJSContext, &val.toObject());
- return CreateChild(object);
- }
-
- template<class Prop> typename Prop::NativeArray
- ObjectNewArray(JS::HandleObject array, size_t length)
- {
- auto jarray = Prop::NativeArray::Adopt(mEnv, mEnv->NewObjectArray(
- length, typename Prop::ClassType::Context().ClassRef(),
- nullptr));
- if (!jarray) {
- return nullptr;
- }
-
- // For object arrays, we have to set each element separately.
- for (size_t i = 0; i < length; i++) {
- JS::RootedValue elem(mJSContext);
- if (!CheckJSCall(JS_GetElement(mJSContext, array, i, &elem)) ||
- !CheckProperty(Prop::InValue, elem)) {
- return nullptr;
- }
- mEnv->SetObjectArrayElement(
- jarray.Get(), i, (this->*Prop::FromValue)(elem).Get());
- if (mEnv->ExceptionCheck()) {
- return nullptr;
- }
- }
- return jarray;
- }
-
- template<class Class,
- bool (Self::*InValue_)(JS::HandleValue) const,
- typename Class::LocalRef (Self::*FromValue_)(JS::HandleValue)>
- struct BaseObjectProperty
- {
- // JNI class for the object type (e.g. jni::String)
- typedef Class ClassType;
-
- // See comments in PrimitiveProperty.
- typedef typename ClassType::LocalRef NativeType;
- typedef const typename ClassType::Ref NativeFallback;
- typedef typename jni::ObjectArray::LocalRef NativeArray;
- typedef const jni::ObjectArray::Ref ArrayFallback;
-
- typedef decltype(InValue_) InValue_t;
- static constexpr InValue_t InValue = InValue_;
-
- typedef decltype(FromValue_) FromValue_t;
- static constexpr FromValue_t FromValue = FromValue_;
-
- typedef decltype(&Self::ObjectNewArray<BaseObjectProperty>) NewArray_t;
- static constexpr NewArray_t NewArray
- = &Self::ObjectNewArray<BaseObjectProperty>;
- };
-
- // Array properties
-
- template<class Prop> bool
- ArrayInValue(JS::HandleValue val) const
- {
- if (!val.isObject()) {
- return false;
- }
- JS::RootedObject obj(mJSContext, &val.toObject());
- bool isArray;
- uint32_t length = 0;
- if (!JS_IsArrayObject(mJSContext, obj, &isArray) ||
- !isArray ||
- !JS_GetArrayLength(mJSContext, obj, &length)) {
- JS_ClearPendingException(mJSContext);
- return false;
- }
- if (!length) {
- // Empty arrays are always okay.
- return true;
- }
- // We only check to see the first element is the target type. If the
- // array has mixed types, we'll throw an error during actual conversion.
- JS::RootedValue element(mJSContext);
- if (!JS_GetElement(mJSContext, obj, 0, &element)) {
- JS_ClearPendingException(mJSContext);
- return false;
- }
- return (this->*Prop::InValue)(element);
- }
-
- template<class Prop> typename Prop::NativeArray
- ArrayFromValue(JS::HandleValue val)
- {
- JS::RootedObject obj(mJSContext, &val.toObject());
- uint32_t length = 0;
- if (!CheckJSCall(JS_GetArrayLength(mJSContext, obj, &length))) {
- return nullptr;
- }
- return (this->*Prop::NewArray)(obj, length);
- }
-
- template<class Prop>
- struct ArrayProperty
- {
- // See comments in PrimitiveProperty.
- typedef typename Prop::NativeArray NativeType;
- typedef typename Prop::ArrayFallback NativeFallback;
-
- typedef decltype(&Self::ArrayInValue<Prop>) InValue_t;
- static constexpr InValue_t InValue
- = &Self::ArrayInValue<Prop>;
-
- typedef decltype(&Self::ArrayFromValue<Prop>) FromValue_t;
- static constexpr FromValue_t FromValue
- = &Self::ArrayFromValue<Prop>;
- };
-
- // "Has" property is a special property type that is used to implement
- // NativeJSObject.has, by returning true from InValue and FromValue for
- // every existing property, and having false as the fallback value for
- // when a property doesn't exist.
-
- bool HasValue(JS::HandleValue val) const
- {
- return true;
- }
-
- struct HasProperty
- {
- // See comments in PrimitiveProperty.
- typedef bool NativeType;
- typedef bool NativeFallback;
-
- typedef decltype(&Self::HasValue) HasValue_t;
- static constexpr HasValue_t InValue = &Self::HasValue;
- static constexpr HasValue_t FromValue = &Self::HasValue;
- };
-
- // Statically cast from bool to jboolean (unsigned char); it works
- // since false and JNI_FALSE have the same value (0), and true and
- // JNI_TRUE have the same value (1).
- typedef PrimitiveProperty<
- bool, jni::BooleanArray, jboolean, jbooleanArray,
- &JS::Value::isBoolean, &JS::Value::toBoolean,
- &JNIEnv::NewBooleanArray, &JNIEnv::SetBooleanArrayRegion>
- BooleanProperty;
-
- typedef PrimitiveProperty<
- double, jni::DoubleArray, jdouble, jdoubleArray,
- &JS::Value::isNumber, &JS::Value::toNumber,
- &JNIEnv::NewDoubleArray, &JNIEnv::SetDoubleArrayRegion>
- DoubleProperty;
-
- typedef PrimitiveProperty<
- int32_t, jni::IntArray, jint, jintArray,
- &JS::Value::isInt32, &JS::Value::toInt32,
- &JNIEnv::NewIntArray, &JNIEnv::SetIntArrayRegion>
- IntProperty;
-
- typedef BaseObjectProperty<
- jni::String, &Self::StringInValue, &Self::StringFromValue>
- StringProperty;
-
- typedef BaseObjectProperty<
- sdk::Bundle, &Self::ObjectInValue, &Self::BundleFromValue>
- BundleProperty;
-
- typedef BaseObjectProperty<
- NativeJSObject, &Self::ObjectInValue, &Self::ObjectFromValue>
- ObjectProperty;
-
- typedef ArrayProperty<BooleanProperty> BooleanArrayProperty;
- typedef ArrayProperty<DoubleProperty> DoubleArrayProperty;
- typedef ArrayProperty<IntProperty> IntArrayProperty;
- typedef ArrayProperty<StringProperty> StringArrayProperty;
- typedef ArrayProperty<BundleProperty> BundleArrayProperty;
- typedef ArrayProperty<ObjectProperty> ObjectArrayProperty;
-
- template<class Prop>
- typename Prop::NativeType
- GetProperty(jni::String::Param name,
- typename Prop::NativeFallback* fallback = nullptr)
- {
- if (!CheckThread() || !CheckObject()) {
- return typename Prop::NativeType();
- }
-
- const JSJNIString nameStr(mEnv, name);
- JS::RootedValue val(mJSContext);
-
- if (!CheckJNIArgument(name) ||
- !CheckJSCall(JS_GetUCProperty(
- mJSContext, mJSObject, nameStr, nameStr.Length(), &val))) {
- return typename Prop::NativeType();
- }
-
- // Strictly, null is different from undefined in JS. However, in
- // practice, null is often used to indicate a property doesn't exist in
- // the same manner as undefined. Therefore, we treat null in the same
- // way as undefined when checking property existence (bug 1014965).
- if (val.isUndefined() || val.isNull()) {
- if (fallback) {
- return mozilla::Move(*fallback);
- }
- jni::ThrowException(
- "org/mozilla/gecko/util/NativeJSObject$InvalidPropertyException",
- "Property does not exist");
- return typename Prop::NativeType();
- }
-
- if (!CheckProperty(Prop::InValue, val)) {
- return typename Prop::NativeType();
- }
- return (this->*Prop::FromValue)(val);
- }
-
- NativeJSObject::LocalRef CreateChild(JS::HandleObject object)
- {
- auto instance = NativeJSObject::New();
- mozilla::UniquePtr<NativeJSContainerImpl> impl(
- new NativeJSContainerImpl(instance.Env(), mJSContext, object));
-
- ObjectBase::AttachNative(instance, mozilla::Move(impl));
- if (!mChildren.append(NativeJSObject::GlobalRef(instance))) {
- MOZ_CRASH();
- }
- return instance;
- }
-
- NativeJSContainerImpl(JNIEnv* env, JSContext* cx, JS::HandleObject object)
- : mEnv(env)
- , mJSContext(cx)
- , mJSObject(cx, object)
- {}
-
-public:
- ~NativeJSContainerImpl()
- {
- // Dispose of all children on destruction. The children will in turn
- // dispose any of their children (i.e. our grandchildren) and so on.
- NativeJSObject::LocalRef child(mEnv);
- for (size_t i = 0; i < mChildren.length(); i++) {
- child = mChildren[i];
- ObjectBase::GetNative(child)->ObjectBase::DisposeNative(child);
- }
- }
-
- static NativeJSContainer::LocalRef
- CreateInstance(JSContext* cx, JS::HandleObject object)
- {
- auto instance = NativeJSContainer::New();
- mozilla::UniquePtr<NativeJSContainerImpl> impl(
- new NativeJSContainerImpl(instance.Env(), cx, object));
-
- ContainerBase::AttachNative(instance, mozilla::Move(impl));
- return instance;
- }
-
- // NativeJSContainer methods
-
- void DisposeNative(const NativeJSContainer::LocalRef& instance)
- {
- if (!CheckThread()) {
- return;
- }
- ContainerBase::DisposeNative(instance);
- }
-
- NativeJSContainer::LocalRef Clone()
- {
- if (!CheckThread()) {
- return nullptr;
- }
- return CreateInstance(mJSContext, mJSObject);
- }
-
- // NativeJSObject methods
-
- bool GetBoolean(jni::String::Param name)
- {
- return GetProperty<BooleanProperty>(name);
- }
-
- bool OptBoolean(jni::String::Param name, bool fallback)
- {
- return GetProperty<BooleanProperty>(name, &fallback);
- }
-
- jni::BooleanArray::LocalRef
- GetBooleanArray(jni::String::Param name)
- {
- return GetProperty<BooleanArrayProperty>(name);
- }
-
- jni::BooleanArray::LocalRef
- OptBooleanArray(jni::String::Param name, jni::BooleanArray::Param fallback)
- {
- return GetProperty<BooleanArrayProperty>(name, &fallback);
- }
-
- jni::Object::LocalRef
- GetBundle(jni::String::Param name)
- {
- return GetProperty<BundleProperty>(name);
- }
-
- jni::Object::LocalRef
- OptBundle(jni::String::Param name, jni::Object::Param fallback)
- {
- // Because the GetProperty expects a sdk::Bundle::Param,
- // we have to do conversions here from jni::Object::Param.
- const auto& fb = sdk::Bundle::Ref::From(fallback.Get());
- return GetProperty<BundleProperty>(name, &fb);
- }
-
- jni::ObjectArray::LocalRef
- GetBundleArray(jni::String::Param name)
- {
- return GetProperty<BundleArrayProperty>(name);
- }
-
- jni::ObjectArray::LocalRef
- OptBundleArray(jni::String::Param name, jni::ObjectArray::Param fallback)
- {
- return GetProperty<BundleArrayProperty>(name, &fallback);
- }
-
- double GetDouble(jni::String::Param name)
- {
- return GetProperty<DoubleProperty>(name);
- }
-
- double OptDouble(jni::String::Param name, double fallback)
- {
- return GetProperty<DoubleProperty>(name, &fallback);
- }
-
- jni::DoubleArray::LocalRef
- GetDoubleArray(jni::String::Param name)
- {
- return GetProperty<DoubleArrayProperty>(name);
- }
-
- jni::DoubleArray::LocalRef
- OptDoubleArray(jni::String::Param name, jni::DoubleArray::Param fallback)
- {
- jni::DoubleArray::LocalRef fb(fallback);
- return GetProperty<DoubleArrayProperty>(name, &fb);
- }
-
- int GetInt(jni::String::Param name)
- {
- return GetProperty<IntProperty>(name);
- }
-
- int OptInt(jni::String::Param name, int fallback)
- {
- return GetProperty<IntProperty>(name, &fallback);
- }
-
- jni::IntArray::LocalRef
- GetIntArray(jni::String::Param name)
- {
- return GetProperty<IntArrayProperty>(name);
- }
-
- jni::IntArray::LocalRef
- OptIntArray(jni::String::Param name, jni::IntArray::Param fallback)
- {
- jni::IntArray::LocalRef fb(fallback);
- return GetProperty<IntArrayProperty>(name, &fb);
- }
-
- NativeJSObject::LocalRef
- GetObject(jni::String::Param name)
- {
- return GetProperty<ObjectProperty>(name);
- }
-
- NativeJSObject::LocalRef
- OptObject(jni::String::Param name, NativeJSObject::Param fallback)
- {
- return GetProperty<ObjectProperty>(name, &fallback);
- }
-
- jni::ObjectArray::LocalRef
- GetObjectArray(jni::String::Param name)
- {
- return GetProperty<ObjectArrayProperty>(name);
- }
-
- jni::ObjectArray::LocalRef
- OptObjectArray(jni::String::Param name, jni::ObjectArray::Param fallback)
- {
- return GetProperty<ObjectArrayProperty>(name, &fallback);
- }
-
- jni::String::LocalRef
- GetString(jni::String::Param name)
- {
- return GetProperty<StringProperty>(name);
- }
-
- jni::String::LocalRef
- OptString(jni::String::Param name, jni::String::Param fallback)
- {
- return GetProperty<StringProperty>(name, &fallback);
- }
-
- jni::ObjectArray::LocalRef
- GetStringArray(jni::String::Param name)
- {
- return GetProperty<StringArrayProperty>(name);
- }
-
- jni::ObjectArray::LocalRef
- OptStringArray(jni::String::Param name, jni::ObjectArray::Param fallback)
- {
- return GetProperty<StringArrayProperty>(name, &fallback);
- }
-
- bool Has(jni::String::Param name)
- {
- bool no = false;
- // Fallback to false indicating no such property.
- return GetProperty<HasProperty>(name, &no);
- }
-
- jni::Object::LocalRef ToBundle()
- {
- if (!CheckThread() || !CheckObject()) {
- return nullptr;
- }
- return BundleFromValue(mJSObject);
- }
-
-private:
- static bool AppendJSON(const char16_t* buf, uint32_t len, void* data)
- {
- static_cast<nsAutoString*>(data)->Append(buf, len);
- return true;
- }
-
-public:
- jni::String::LocalRef ToString()
- {
- if (!CheckThread() || !CheckObject()) {
- return nullptr;
- }
-
- JS::RootedValue value(mJSContext, JS::ObjectValue(*mJSObject));
- nsAutoString json;
- if (!CheckJSCall(JS_Stringify(mJSContext, &value, nullptr,
- JS::NullHandleValue, AppendJSON, &json))) {
- return nullptr;
- }
- return jni::StringParam(json, mEnv);
- }
-};
-
-
-// Define the "static constexpr" members of our property types (e.g.
-// PrimitiveProperty<>::InValue). This is tricky because there are a lot of
-// template parameters, so we use macros to make it simpler.
-
-#define DEFINE_PRIMITIVE_PROPERTY_MEMBER(Name) \
- template<typename U, typename UA, typename V, typename VA, \
- bool (JS::Value::*I)() const, \
- U (JS::Value::*T)() const, \
- VA (JNIEnv::*N)(jsize), \
- void (JNIEnv::*S)(VA, jsize, jsize, const V*)> \
- constexpr typename NativeJSContainerImpl \
- ::PrimitiveProperty<U, UA, V, VA, I, T, N, S>::Name##_t \
- NativeJSContainerImpl::PrimitiveProperty<U, UA, V, VA, I, T, N, S>::Name
-
-DEFINE_PRIMITIVE_PROPERTY_MEMBER(NewJNIArray);
-DEFINE_PRIMITIVE_PROPERTY_MEMBER(SetJNIArrayRegion);
-DEFINE_PRIMITIVE_PROPERTY_MEMBER(InValue);
-DEFINE_PRIMITIVE_PROPERTY_MEMBER(FromValue);
-DEFINE_PRIMITIVE_PROPERTY_MEMBER(NewArray);
-
-#undef DEFINE_PRIMITIVE_PROPERTY_MEMBER
-
-#define DEFINE_OBJECT_PROPERTY_MEMBER(Name) \
- template<class C, \
- bool (NativeJSContainerImpl::*I)(JS::HandleValue) const, \
- typename C::LocalRef (NativeJSContainerImpl::*F)(JS::HandleValue)> \
- constexpr typename NativeJSContainerImpl \
- ::BaseObjectProperty<C, I, F>::Name##_t \
- NativeJSContainerImpl::BaseObjectProperty<C, I, F>::Name
-
-DEFINE_OBJECT_PROPERTY_MEMBER(InValue);
-DEFINE_OBJECT_PROPERTY_MEMBER(FromValue);
-DEFINE_OBJECT_PROPERTY_MEMBER(NewArray);
-
-#undef DEFINE_OBJECT_PROPERTY_MEMBER
-
-template<class P> constexpr typename NativeJSContainerImpl::ArrayProperty<P>
- ::InValue_t NativeJSContainerImpl::ArrayProperty<P>::InValue;
-template<class P> constexpr typename NativeJSContainerImpl::ArrayProperty<P>
- ::FromValue_t NativeJSContainerImpl::ArrayProperty<P>::FromValue;
-
-constexpr NativeJSContainerImpl::HasProperty::HasValue_t
- NativeJSContainerImpl::HasProperty::InValue;
-constexpr NativeJSContainerImpl::HasProperty::HasValue_t
- NativeJSContainerImpl::HasProperty::FromValue;
-
-
-NativeJSContainer::LocalRef
-CreateNativeJSContainer(JSContext* cx, JS::HandleObject object)
-{
- return NativeJSContainerImpl::CreateInstance(cx, object);
-}
-
-} // namespace widget
-} // namespace mozilla
-