Use new hybrid inheritance for NativeArray and descendants

Differential Revision: D2516708

fb-gh-sync-id: 75bc2d7095ffe2c397d5ffb34b621b322b858c3e
This commit is contained in:
Mike Armstrong 2015-10-07 00:32:05 -07:00 коммит произвёл facebook-github-bot-6
Родитель 8251f1c905
Коммит fb90ba6ded
5 изменённых файлов: 139 добавлений и 110 удалений

Просмотреть файл

@ -22,15 +22,13 @@ public abstract class NativeArray {
SoLoader.loadLibrary(ReactBridge.REACT_NATIVE_LIB); SoLoader.loadLibrary(ReactBridge.REACT_NATIVE_LIB);
} }
public NativeArray() { protected NativeArray(HybridData hybridData) {
mHybridData = initHybrid(); mHybridData = hybridData;
} }
@Override @Override
public native String toString(); public native String toString();
private native HybridData initHybrid();
@DoNotStrip @DoNotStrip
private HybridData mHybridData; private HybridData mHybridData;
} }

Просмотреть файл

@ -9,6 +9,7 @@
package com.facebook.react.bridge; package com.facebook.react.bridge;
import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.soloader.SoLoader; import com.facebook.soloader.SoLoader;
@ -23,6 +24,10 @@ public class ReadableNativeArray extends NativeArray implements ReadableArray {
SoLoader.loadLibrary(ReactBridge.REACT_NATIVE_LIB); SoLoader.loadLibrary(ReactBridge.REACT_NATIVE_LIB);
} }
protected ReadableNativeArray(HybridData hybridData) {
super(hybridData);
}
@Override @Override
public native int size(); public native int size();
@Override @Override

Просмотреть файл

@ -10,6 +10,7 @@
package com.facebook.react.bridge; package com.facebook.react.bridge;
import com.facebook.infer.annotation.Assertions; import com.facebook.infer.annotation.Assertions;
import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.soloader.SoLoader; import com.facebook.soloader.SoLoader;
@ -25,6 +26,10 @@ public class WritableNativeArray extends ReadableNativeArray implements Writable
SoLoader.loadLibrary(ReactBridge.REACT_NATIVE_LIB); SoLoader.loadLibrary(ReactBridge.REACT_NATIVE_LIB);
} }
public WritableNativeArray() {
super(initHybrid());
}
@Override @Override
public native void pushNull(); public native void pushNull();
@Override @Override
@ -52,6 +57,7 @@ public class WritableNativeArray extends ReadableNativeArray implements Writable
pushNativeMap((WritableNativeMap) map); pushNativeMap((WritableNativeMap) map);
} }
private native static HybridData initHybrid();
private native void pushNativeArray(WritableNativeArray array); private native void pushNativeArray(WritableNativeArray array);
private native void pushNativeMap(WritableNativeMap map); private native void pushNativeMap(WritableNativeMap map);
} }

Просмотреть файл

@ -8,25 +8,12 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
jni::local_ref<NativeArray::jhybridobject> NativeArray::NativeArray(folly::dynamic a)
createReadableNativeArrayWithContents(folly::dynamic array) { : array(std::move(a)) {
if (array.isNull()) {
return jni::local_ref<NativeArray::jhybridobject>();
}
if (!array.isArray()) { if (!array.isArray()) {
jni::throwNewJavaException("com/facebook/react/bridge/UnexpectedNativeTypeException", jni::throwNewJavaException("com/facebook/react/bridge/UnexpectedNativeTypeException",
"expected Array, got a %s", array.typeName()); "expected Array, got a %s", array.typeName());
} }
static auto readableNativeArrayClass =
jni::findClassStatic("com/facebook/react/bridge/ReadableNativeArray");
static auto readableNativeArrayCtor =
readableNativeArrayClass->getConstructor<NativeArray::jhybridobject()>();
auto jnewArray = readableNativeArrayClass->newObject(readableNativeArrayCtor);
jni::cthis(jnewArray)->array = std::move(array);
return jnewArray;
} }
jstring NativeArray::toString() { jstring NativeArray::toString() {
@ -37,5 +24,11 @@ jstring NativeArray::toString() {
return jni::make_jstring(folly::toJson(array).c_str()).release(); return jni::make_jstring(folly::toJson(array).c_str()).release();
} }
void NativeArray::registerNatives() {
registerHybrid({
makeNativeMethod("toString", NativeArray::toString),
});
}
} }
} }

Просмотреть файл

@ -14,7 +14,7 @@
#include <react/Executor.h> #include <react/Executor.h>
#include <react/JSCExecutor.h> #include <react/JSCExecutor.h>
#include "JSLoader.h" #include "JSLoader.h"
#include "NativeArray.h" #include "ReadableNativeArray.h"
#include "ProxyExecutor.h" #include "ProxyExecutor.h"
#ifdef WITH_FBSYSTRACE #ifdef WITH_FBSYSTRACE
@ -131,83 +131,105 @@ static jobject getType(folly::dynamic::Type type) {
} }
struct ReadableNativeArray : public NativeArray { // This attribute exports the ctor symbol, so ReadableNativeArray to be
static void mapException(const std::exception& ex) { // constructed from other DSOs.
if (dynamic_cast<const folly::TypeError*>(&ex) != 0) { __attribute__((visibility("default")))
throwNewJavaException(exceptions::gUnexpectedNativeTypeExceptionClass, ex.what()); ReadableNativeArray::ReadableNativeArray(folly::dynamic array)
} : HybridBase(std::move(array)) {}
void ReadableNativeArray::mapException(const std::exception& ex) {
if (dynamic_cast<const folly::TypeError*>(&ex) != nullptr) {
throwNewJavaException(exceptions::gUnexpectedNativeTypeExceptionClass, ex.what());
}
}
jint ReadableNativeArray::getSize() {
return array.size();
}
jboolean ReadableNativeArray::isNull(jint index) {
return array.at(index).isNull() ? JNI_TRUE : JNI_FALSE;
}
jboolean ReadableNativeArray::getBoolean(jint index) {
return array.at(index).getBool() ? JNI_TRUE : JNI_FALSE;
}
jdouble ReadableNativeArray::getDouble(jint index) {
const folly::dynamic& val = array.at(index);
if (val.isInt()) {
return val.getInt();
}
return val.getDouble();
}
jint ReadableNativeArray::getInt(jint index) {
auto integer = array.at(index).getInt();
static_assert(std::is_same<decltype(integer), int64_t>::value,
"folly::dynamic int is not int64_t");
jint javaint = static_cast<jint>(integer);
if (integer != javaint) {
throwNewJavaException(
exceptions::gUnexpectedNativeTypeExceptionClass,
"Value '%lld' doesn't fit into a 32 bit signed int", integer);
}
return javaint;
}
const char* ReadableNativeArray::getString(jint index) {
const folly::dynamic& dyn = array.at(index);
if (dyn.isNull()) {
return nullptr;
}
return dyn.getString().c_str();
}
jni::local_ref<ReadableNativeArray::jhybridobject> ReadableNativeArray::getArray(jint index) {
auto& elem = array.at(index);
if (elem.isNull()) {
return jni::local_ref<ReadableNativeArray::jhybridobject>(nullptr);
} else {
return ReadableNativeArray::newObjectCxxArgs(elem);
}
}
jobject ReadableNativeArray::getMap(jint index) {
return createReadableNativeMapWithContents(Environment::current(), array.at(index));
}
jobject ReadableNativeArray::getType(jint index) {
return type::getType(array.at(index).type());
}
void ReadableNativeArray::registerNatives() {
jni::registerNatives("com/facebook/react/bridge/ReadableNativeArray", {
makeNativeMethod("size", ReadableNativeArray::getSize),
makeNativeMethod("isNull", ReadableNativeArray::isNull),
makeNativeMethod("getBoolean", ReadableNativeArray::getBoolean),
makeNativeMethod("getDouble", ReadableNativeArray::getDouble),
makeNativeMethod("getInt", ReadableNativeArray::getInt),
makeNativeMethod("getString", ReadableNativeArray::getString),
makeNativeMethod("getArray", ReadableNativeArray::getArray),
makeNativeMethod("getMap", "(I)Lcom/facebook/react/bridge/ReadableNativeMap;",
ReadableNativeArray::getMap),
makeNativeMethod("getType", "(I)Lcom/facebook/react/bridge/ReadableType;",
ReadableNativeArray::getType),
});
}
namespace {
struct WritableNativeArray
: public jni::HybridClass<WritableNativeArray, ReadableNativeArray> {
static constexpr const char* kJavaDescriptor = "Lcom/facebook/react/bridge/WritableNativeArray;";
WritableNativeArray()
: HybridBase(folly::dynamic({})) {}
static local_ref<jhybriddata> initHybrid(alias_ref<jclass>) {
return makeCxxInstance();
} }
jint getSize() {
return array.size();
}
jboolean isNull(jint index) {
return array.at(index).isNull() ? JNI_TRUE : JNI_FALSE;
}
jboolean getBoolean(jint index) {
return array.at(index).getBool() ? JNI_TRUE : JNI_FALSE;
}
jdouble getDouble(jint index) {
const folly::dynamic& val = array.at(index);
if (val.isInt()) {
return val.getInt();
}
return val.getDouble();
}
jint getInt(jint index) {
auto integer = array.at(index).getInt();
jint javaint = static_cast<jint>(integer);
if (integer != javaint) {
throwNewJavaException(
exceptions::gUnexpectedNativeTypeExceptionClass,
"Value '%lld' doesn't fit into a 32 bit signed int", integer);
}
return javaint;
}
jstring getString(jint index) {
const folly::dynamic& dyn = array.at(index);
if (dyn.isNull()) {
return nullptr;
}
return make_jstring(dyn.getString().c_str()).release();
}
jobject getArray(jint index) {
return createReadableNativeArrayWithContents(array.at(index)).release();
}
jobject getMap(jint index) {
return createReadableNativeMapWithContents(Environment::current(), array.at(index));
}
jobject getType(jint index) {
return type::getType(array.at(index).type());
}
static void registerNatives() {
jni::registerNatives("com/facebook/react/bridge/ReadableNativeArray", {
makeNativeMethod("size", ReadableNativeArray::getSize),
makeNativeMethod("isNull", ReadableNativeArray::isNull),
makeNativeMethod("getBoolean", ReadableNativeArray::getBoolean),
makeNativeMethod("getDouble", ReadableNativeArray::getDouble),
makeNativeMethod("getInt", ReadableNativeArray::getInt),
makeNativeMethod("getString", ReadableNativeArray::getString),
makeNativeMethod("getArray", "(I)Lcom/facebook/react/bridge/ReadableNativeArray;",
ReadableNativeArray::getArray),
makeNativeMethod("getMap", "(I)Lcom/facebook/react/bridge/ReadableNativeMap;",
ReadableNativeArray::getMap),
makeNativeMethod("getType", "(I)Lcom/facebook/react/bridge/ReadableType;",
ReadableNativeArray::getType),
});
}
};
struct WritableNativeArray : public ReadableNativeArray {
void pushNull() { void pushNull() {
exceptions::throwIfObjectAlreadyConsumed(this, "Array already consumed"); exceptions::throwIfObjectAlreadyConsumed(this, "Array already consumed");
array.push_back(nullptr); array.push_back(nullptr);
@ -237,7 +259,7 @@ struct WritableNativeArray : public ReadableNativeArray {
array.push_back(wrap_alias(value)->toStdString()); array.push_back(wrap_alias(value)->toStdString());
} }
void pushArray(NativeArray* otherArray) { void pushNativeArray(WritableNativeArray* otherArray) {
if (otherArray == NULL) { if (otherArray == NULL) {
pushNull(); pushNull();
return; return;
@ -248,7 +270,7 @@ struct WritableNativeArray : public ReadableNativeArray {
otherArray->isConsumed = true; otherArray->isConsumed = true;
} }
void pushMap(jobject jmap) { void pushNativeMap(jobject jmap) {
if (jmap == NULL) { if (jmap == NULL) {
pushNull(); pushNull();
return; return;
@ -262,19 +284,21 @@ struct WritableNativeArray : public ReadableNativeArray {
static void registerNatives() { static void registerNatives() {
jni::registerNatives("com/facebook/react/bridge/WritableNativeArray", { jni::registerNatives("com/facebook/react/bridge/WritableNativeArray", {
makeNativeMethod("initHybrid", WritableNativeArray::initHybrid),
makeNativeMethod("pushNull", WritableNativeArray::pushNull), makeNativeMethod("pushNull", WritableNativeArray::pushNull),
makeNativeMethod("pushBoolean", WritableNativeArray::pushBoolean), makeNativeMethod("pushBoolean", WritableNativeArray::pushBoolean),
makeNativeMethod("pushDouble", WritableNativeArray::pushDouble), makeNativeMethod("pushDouble", WritableNativeArray::pushDouble),
makeNativeMethod("pushInt", WritableNativeArray::pushInt), makeNativeMethod("pushInt", WritableNativeArray::pushInt),
makeNativeMethod("pushString", WritableNativeArray::pushString), makeNativeMethod("pushString", WritableNativeArray::pushString),
makeNativeMethod("pushNativeArray", "(Lcom/facebook/react/bridge/WritableNativeArray;)V", makeNativeMethod("pushNativeArray", WritableNativeArray::pushNativeArray),
WritableNativeArray::pushArray),
makeNativeMethod("pushNativeMap", "(Lcom/facebook/react/bridge/WritableNativeMap;)V", makeNativeMethod("pushNativeMap", "(Lcom/facebook/react/bridge/WritableNativeMap;)V",
WritableNativeArray::pushMap), WritableNativeArray::pushNativeMap),
}); });
} }
}; };
}
namespace map { namespace map {
static void initialize(JNIEnv* env, jobject obj) { static void initialize(JNIEnv* env, jobject obj) {
@ -326,7 +350,8 @@ static void putString(JNIEnv* env, jobject obj, jstring key, jstring value) {
map->map.insert(fromJString(env, key), fromJString(env, value)); map->map.insert(fromJString(env, key), fromJString(env, value));
} }
static void putArray(JNIEnv* env, jobject obj, jstring key, NativeArray::jhybridobject value) { static void putArray(JNIEnv* env, jobject obj, jstring key,
WritableNativeArray::jhybridobject value) {
if (value == NULL) { if (value == NULL) {
putNull(env, obj, key); putNull(env, obj, key);
return; return;
@ -441,8 +466,14 @@ static jstring getStringKey(JNIEnv* env, jobject obj, jstring keyName) {
} }
} }
static jobject getArrayKey(JNIEnv* env, jobject obj, jstring keyName) { static jni::local_ref<ReadableNativeArray::jhybridobject> getArrayKey(
return createReadableNativeArrayWithContents(getMapValue(env, obj, keyName)).release(); jni::alias_ref<jobject> obj, jstring keyName) {
auto& value = getMapValue(Environment::current(), obj.get(), keyName);
if (value.isNull()) {
return jni::local_ref<ReadableNativeArray::jhybridobject>(nullptr);
} else {
return ReadableNativeArray::newObjectCxxArgs(value);
}
} }
static jobject getMapKey(JNIEnv* env, jobject obj, jstring keyName) { static jobject getMapKey(JNIEnv* env, jobject obj, jstring keyName) {
@ -526,7 +557,7 @@ static void makeJavaCall(JNIEnv* env, jobject callback, MethodCall&& call) {
if (call.arguments.isNull()) { if (call.arguments.isNull()) {
return; return;
} }
auto newArray = createReadableNativeArrayWithContents(std::move(call.arguments)); auto newArray = ReadableNativeArray::newObjectCxxArgs(std::move(call.arguments));
env->CallVoidMethod(callback, gCallbackMethod, call.moduleId, call.methodId, newArray.get()); env->CallVoidMethod(callback, gCallbackMethod, call.moduleId, call.methodId, newArray.get());
} }
@ -708,9 +739,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
makeNativeMethod("getDouble", map::readable::getDoubleKey), makeNativeMethod("getDouble", map::readable::getDoubleKey),
makeNativeMethod("getInt", map::readable::getIntKey), makeNativeMethod("getInt", map::readable::getIntKey),
makeNativeMethod("getString", map::readable::getStringKey), makeNativeMethod("getString", map::readable::getStringKey),
makeNativeMethod( makeNativeMethod("getArray", map::readable::getArrayKey),
"getArray", "(Ljava/lang/String;)Lcom/facebook/react/bridge/ReadableNativeArray;",
map::readable::getArrayKey),
makeNativeMethod( makeNativeMethod(
"getMap", "(Ljava/lang/String;)Lcom/facebook/react/bridge/ReadableNativeMap;", "getMap", "(Ljava/lang/String;)Lcom/facebook/react/bridge/ReadableNativeMap;",
map::readable::getMapKey), map::readable::getMapKey),
@ -725,9 +754,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
makeNativeMethod("putDouble", map::writable::putDouble), makeNativeMethod("putDouble", map::writable::putDouble),
makeNativeMethod("putInt", map::writable::putInt), makeNativeMethod("putInt", map::writable::putInt),
makeNativeMethod("putString", map::writable::putString), makeNativeMethod("putString", map::writable::putString),
makeNativeMethod( makeNativeMethod("putNativeArray", map::writable::putArray),
"putNativeArray", "(Ljava/lang/String;Lcom/facebook/react/bridge/WritableNativeArray;)V",
map::writable::putArray),
makeNativeMethod( makeNativeMethod(
"putNativeMap", "(Ljava/lang/String;Lcom/facebook/react/bridge/WritableNativeMap;)V", "putNativeMap", "(Ljava/lang/String;Lcom/facebook/react/bridge/WritableNativeMap;)V",
map::writable::putMap), map::writable::putMap),