Move Android TurboModules to github
Summary: This commit moves all the turbo module files for Android to Github. Note that gradle build is not yet enabled. Sample Turbo Modules will be added in a later commit. Other missing features - Support for `CxxModule` - Remove usage of folly::dynamic for arguments and result conversion - Support for Promise return types. Reviewed By: mdvacca Differential Revision: D13647438 fbshipit-source-id: 5f1188556d6c64bfa2b2fd2146ac72b0fb456891
This commit is contained in:
parent
8a8a11b77a
commit
e6f7d69428
|
@ -0,0 +1,25 @@
|
|||
load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library")
|
||||
|
||||
rn_android_library(
|
||||
name = "core",
|
||||
srcs = glob(
|
||||
[
|
||||
"*.java",
|
||||
],
|
||||
),
|
||||
required_for_source_only_abi = True,
|
||||
visibility = [
|
||||
"PUBLIC",
|
||||
],
|
||||
deps = [
|
||||
react_native_target("java/com/facebook/react/turbomodule/core/interfaces:interfaces"),
|
||||
react_native_dep("java/com/facebook/systrace:systrace"),
|
||||
react_native_dep("libraries/soloader/java/com/facebook/soloader:soloader"),
|
||||
react_native_dep("third-party/java/infer-annotations:infer-annotations"),
|
||||
react_native_dep("third-party/java/jsr-305:jsr-305"),
|
||||
react_native_target("java/com/facebook/react/turbomodule/core/jni:jni"),
|
||||
react_native_target("java/com/facebook/debug/holder:holder"),
|
||||
react_native_target("java/com/facebook/react/bridge:interfaces"),
|
||||
react_native_target("java/com/facebook/react/bridge:bridge"),
|
||||
],
|
||||
)
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.turbomodule.core;
|
||||
|
||||
import com.facebook.jni.HybridData;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.react.bridge.JSIModule;
|
||||
import com.facebook.react.bridge.JavaScriptContextHolder;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.queue.MessageQueueThread;
|
||||
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
|
||||
/**
|
||||
* This is the main class and entry point for TurboModules.
|
||||
* Note that this is a hybrid class, and has a C++ counterpart
|
||||
* This class installs the JSI bindings. It also implements the method to get a Java module, that the C++ counterpart calls.
|
||||
*/
|
||||
public class TurboModuleManager implements JSIModule {
|
||||
static {
|
||||
SoLoader.loadLibrary("turbomodulejsijni");
|
||||
}
|
||||
|
||||
private final ReactApplicationContext mReactApplicationContext;
|
||||
|
||||
@DoNotStrip
|
||||
@SuppressWarnings("unused")
|
||||
private final HybridData mHybridData;
|
||||
private final ModuleProvider mModuleProvider;
|
||||
|
||||
public TurboModuleManager(
|
||||
ReactApplicationContext reactApplicationContext, JavaScriptContextHolder jsContext, ModuleProvider moduleProvider) {
|
||||
mReactApplicationContext = reactApplicationContext;
|
||||
MessageQueueThread jsMessageQueueThread =
|
||||
mReactApplicationContext
|
||||
.getCatalystInstance()
|
||||
.getReactQueueConfiguration()
|
||||
.getJSQueueThread();
|
||||
mHybridData = initHybrid(jsContext.get(), jsMessageQueueThread);
|
||||
mModuleProvider = moduleProvider;
|
||||
}
|
||||
|
||||
@DoNotStrip
|
||||
@SuppressWarnings("unused")
|
||||
protected TurboModule getJavaModule(String name) {
|
||||
return mModuleProvider.getModule(name, mReactApplicationContext);
|
||||
}
|
||||
|
||||
protected native HybridData initHybrid(long jsContext, MessageQueueThread jsQueue);
|
||||
|
||||
protected native void installJSIBindings();
|
||||
|
||||
public void installBindings() {
|
||||
installJSIBindings();
|
||||
}
|
||||
|
||||
protected ReactApplicationContext getReactApplicationContext() {
|
||||
return mReactApplicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {}
|
||||
|
||||
@Override
|
||||
public void onCatalystInstanceDestroy() {}
|
||||
|
||||
/** All applications must implement this interface, and provide the Java TurboModule class */
|
||||
public interface ModuleProvider {
|
||||
TurboModule getModule(String name, ReactApplicationContext reactApplicationContext);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
load("//tools/build_defs/oss:rn_defs.bzl", "rn_android_library")
|
||||
|
||||
rn_android_library(
|
||||
name = "interfaces",
|
||||
srcs = [
|
||||
"TurboModule.java",
|
||||
],
|
||||
required_for_source_only_abi = True,
|
||||
visibility = [
|
||||
"PUBLIC",
|
||||
],
|
||||
)
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.turbomodule.core.interfaces;
|
||||
|
||||
/**
|
||||
* All turbo modules should inherit from this interface
|
||||
*/
|
||||
public interface TurboModule {
|
||||
/** When CatalystInstance is destroyed, this method will be called. All implementing TurboModules can perform cleanup here. */
|
||||
void invalidate();
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
load("@fbsource//tools/build_defs:glob_defs.bzl", "subdir_glob")
|
||||
load("@fbsource//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "react_native_target", "react_native_xplat_target", "rn_xplat_cxx_library")
|
||||
|
||||
rn_xplat_cxx_library(
|
||||
name = "jni",
|
||||
srcs = glob(["**/*.cpp"]),
|
||||
header_namespace = "",
|
||||
exported_headers = subdir_glob(
|
||||
[
|
||||
("", "**/*.h"),
|
||||
],
|
||||
prefix = "jsireact",
|
||||
),
|
||||
compiler_flags = [
|
||||
"-fexceptions",
|
||||
"-frtti",
|
||||
"-std=c++14",
|
||||
"-Wall",
|
||||
],
|
||||
force_static = True,
|
||||
platforms = ANDROID,
|
||||
preprocessor_flags = [
|
||||
"-DLOG_TAG=\"ReactNative\"",
|
||||
"-DWITH_FBSYSTRACE=1",
|
||||
],
|
||||
visibility = [
|
||||
"PUBLIC",
|
||||
],
|
||||
deps = [
|
||||
react_native_target("jni/react/jni:jni"),
|
||||
"xplat//jsi:JSIDynamic",
|
||||
"xplat//jsi:jsi",
|
||||
],
|
||||
exported_deps = [
|
||||
"xplat//jsi:jsi",
|
||||
react_native_xplat_target("turbomodule/core:core"),
|
||||
],
|
||||
)
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <fb/fbjni.h>
|
||||
#include <jsi/jsi.h>
|
||||
|
||||
#include <jsireact/TurboModuleBinding.h>
|
||||
|
||||
#include <react/jni/JMessageQueueThread.h>
|
||||
|
||||
#include "TurboModuleManager.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
static JTurboModuleProviderFunctionType moduleProvider_ = nullptr;
|
||||
|
||||
TurboModuleManager::TurboModuleManager(
|
||||
jni::alias_ref<TurboModuleManager::javaobject> jThis,
|
||||
jsi::Runtime* rt,
|
||||
std::shared_ptr<JMessageQueueThread> jsMessageQueueThread
|
||||
):
|
||||
javaPart_(make_global(jThis)),
|
||||
runtime_(rt),
|
||||
jsMessageQueueThread_(jsMessageQueueThread)
|
||||
{}
|
||||
|
||||
jni::local_ref<TurboModuleManager::jhybriddata> TurboModuleManager::initHybrid(
|
||||
jni::alias_ref<jhybridobject> jThis,
|
||||
jlong jsContext,
|
||||
jni::alias_ref<JavaMessageQueueThread::javaobject> jsQueue
|
||||
) {
|
||||
auto sharedJSMessageQueueThread = std::make_shared<JMessageQueueThread> (jsQueue);
|
||||
return makeCxxInstance(jThis, (jsi::Runtime *) jsContext, sharedJSMessageQueueThread);
|
||||
}
|
||||
|
||||
void TurboModuleManager::registerNatives() {
|
||||
registerHybrid({
|
||||
makeNativeMethod("initHybrid", TurboModuleManager::initHybrid),
|
||||
makeNativeMethod("installJSIBindings", TurboModuleManager::installJSIBindings),
|
||||
});
|
||||
}
|
||||
|
||||
void TurboModuleManager::installJSIBindings() {
|
||||
if (!runtime_) {
|
||||
return; // Runtime doesn't exist when attached to Chrome debugger.
|
||||
}
|
||||
TurboModuleBinding::install(*runtime_, std::make_shared<TurboModuleBinding>(
|
||||
[this](const std::string &name) {
|
||||
const auto moduleInstance = getJavaModule(name);
|
||||
const auto jsInvoker = std::make_shared<react::JSCallInvoker>(jsMessageQueueThread_);
|
||||
return moduleProvider_(name, moduleInstance, jsInvoker);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
jni::global_ref<JTurboModule> TurboModuleManager::getJavaModule(std::string name) {
|
||||
static auto method = javaClassStatic()->getMethod<jni::alias_ref<JTurboModule>(const std::string&)>("getJavaModule");
|
||||
return make_global(method(javaPart_.get(), name));
|
||||
}
|
||||
|
||||
void TurboModuleManager::setModuleProvider(JTurboModuleProviderFunctionType fn) {
|
||||
moduleProvider_ = fn;
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <fb/fbjni.h>
|
||||
#include <jsi/jsi.h>
|
||||
#include <jsireact/TurboModule.h>
|
||||
#include <jsireact/JavaTurboModule.h>
|
||||
#include <react/jni/JMessageQueueThread.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
using JTurboModuleProviderFunctionType = std::function<std::shared_ptr<TurboModule>(
|
||||
const std::string &name, jni::global_ref<JTurboModule> moduleInstance, std::shared_ptr<JSCallInvoker> jsInvoker)>;
|
||||
|
||||
class TurboModuleManager : public jni::HybridClass<TurboModuleManager> {
|
||||
public:
|
||||
static auto constexpr kJavaDescriptor = "Lcom/facebook/react/turbomodule/core/TurboModuleManager;";
|
||||
static jni::local_ref<jhybriddata> initHybrid(
|
||||
jni::alias_ref<jhybridobject> jThis,
|
||||
jlong jsContext,
|
||||
jni::alias_ref<JavaMessageQueueThread::javaobject> jsQueue
|
||||
);
|
||||
static void registerNatives();
|
||||
static void setModuleProvider(JTurboModuleProviderFunctionType moduleProvider);
|
||||
private:
|
||||
friend HybridBase;
|
||||
jni::global_ref<TurboModuleManager::javaobject> javaPart_;
|
||||
jsi::Runtime* runtime_;
|
||||
std::shared_ptr<JMessageQueueThread> jsMessageQueueThread_;
|
||||
|
||||
jni::global_ref<JTurboModule> getJavaModule(std::string name);
|
||||
void installJSIBindings();
|
||||
explicit TurboModuleManager(
|
||||
jni::alias_ref<TurboModuleManager::jhybridobject> jThis,
|
||||
jsi::Runtime* rt,
|
||||
std::shared_ptr<JMessageQueueThread> jsMessageQueueThread
|
||||
);
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -1,5 +1,5 @@
|
|||
load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "OBJC_ARC_PREPROCESSOR_FLAGS", "get_debug_preprocessor_flags", "get_static_library_ios_flags")
|
||||
load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "react_native_xplat_target", "rn_xplat_cxx_library", "subdir_glob")
|
||||
load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "react_native_target", "react_native_xplat_target", "rn_xplat_cxx_library", "subdir_glob")
|
||||
|
||||
rn_xplat_cxx_library(
|
||||
name = "core",
|
||||
|
@ -17,6 +17,20 @@ rn_xplat_cxx_library(
|
|||
"-std=c++14",
|
||||
"-Wall",
|
||||
],
|
||||
fbandroid_deps = [
|
||||
react_native_target("jni/react/jni:jni"),
|
||||
],
|
||||
fbandroid_exported_headers = subdir_glob(
|
||||
[
|
||||
("platform/android", "*.h"),
|
||||
],
|
||||
prefix = "jsireact",
|
||||
),
|
||||
fbandroid_srcs = glob(
|
||||
[
|
||||
"platform/android/**/*.cpp",
|
||||
],
|
||||
),
|
||||
fbobjc_compiler_flags = [
|
||||
"-Wall",
|
||||
"-fobjc-arc-exceptions",
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <fb/fbjni.h>
|
||||
#include <jsi/jsi.h>
|
||||
|
||||
#include <jsireact/TurboModule.h>
|
||||
#import <jsireact/TurboModuleUtils.h>
|
||||
|
||||
#include <jsi/JSIDynamic.h>
|
||||
#include <react/jni/ReadableNativeMap.h>
|
||||
#include <react/jni/WritableNativeMap.h>
|
||||
#include <react/jni/NativeMap.h>
|
||||
#include <react/jni/JCallback.h>
|
||||
|
||||
#include "JavaTurboModule.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
JavaTurboModule::JavaTurboModule(const std::string &name, jni::global_ref<JTurboModule> instance, std::shared_ptr<JSCallInvoker> jsInvoker)
|
||||
: TurboModule(name, jsInvoker), instance_(instance) {}
|
||||
|
||||
// fnjni already does this conversion, but since we are using plain JNI, this needs to be done again
|
||||
// TODO (axe) Reuse existing implementation as needed - the exist in MethodInvoker.cpp
|
||||
// TODO (axe) If at runtime, JS sends incorrect arguments and this is not typechecked, conversion here will fail. Check for that case (OSS)
|
||||
std::unique_ptr<jvalue[]> convertFromJValueArgsToJNIArgs(
|
||||
JNIEnv *env,
|
||||
jsi::Runtime &rt,
|
||||
const jsi::Value *args,
|
||||
size_t count,
|
||||
std::shared_ptr<JSCallInvoker> jsInvoker
|
||||
) {
|
||||
auto jargs = std::make_unique<jvalue[]>(count);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
const jsi::Value *arg = &args[i];
|
||||
if (arg->isBool()) {
|
||||
jargs[i].z = arg->getBool();
|
||||
} else if (arg->isNumber()) {
|
||||
jargs[i].d = arg->getNumber();
|
||||
} else if (arg->isNull() || arg->isUndefined()) {
|
||||
// What happens if Java is expecting a bool or a number, and JS sends a null or undefined?
|
||||
jargs[i].l = nullptr;
|
||||
} else if (arg->isString()) {
|
||||
// We are basically creating a whole new string here
|
||||
// TODO (axe) Is there a way to copy this instead of creating a whole new string ?
|
||||
jargs[i].l = env->NewStringUTF(arg->getString(rt).utf8(rt).c_str());
|
||||
} else if (arg->isObject()) {
|
||||
auto objectArg = arg->getObject(rt);
|
||||
// We are currently using folly:dynamic to convert JSON to Writable Map
|
||||
// TODO (axe) Don't use folly:dynamic, instead construct Java map directly
|
||||
if (objectArg.isArray(rt)) {
|
||||
auto dynamicFromValue = jsi::dynamicFromValue(rt, args[i]);
|
||||
auto jParams = ReadableNativeArray::newObjectCxxArgs(std::move(dynamicFromValue));
|
||||
jargs[i].l = jParams.release();
|
||||
} else if (objectArg.isFunction(rt)) {
|
||||
auto wrapper = std::make_shared<react::CallbackWrapper>(objectArg.getFunction(rt), rt, jsInvoker);
|
||||
std::function<void(folly::dynamic)> fn = [wrapper](folly::dynamic responses){
|
||||
if (wrapper == nullptr) {
|
||||
throw std::runtime_error("callback arg cannot be called more than once");
|
||||
}
|
||||
std::shared_ptr<react::CallbackWrapper> rw = wrapper;
|
||||
wrapper->jsInvoker->invokeAsync([rw, responses]() {
|
||||
// TODO (axe) valueFromDynamic already returns a Value array. Don't iterate again
|
||||
jsi::Value args = jsi::valueFromDynamic(rw->runtime, responses);
|
||||
auto argsArray = args.getObject(rw->runtime).asArray(rw->runtime);
|
||||
std::vector<jsi::Value> result;
|
||||
for (size_t i = 0; i < argsArray.size(rw->runtime); i++) {
|
||||
result.emplace_back(rw->runtime, argsArray.getValueAtIndex(rw->runtime, i));
|
||||
}
|
||||
rw->callback.call(rw->runtime, (const jsi::Value *)result.data(), result.size());
|
||||
});
|
||||
};
|
||||
wrapper = nullptr;
|
||||
// TODO Use our own implementation of callback instead of relying on JCxxCallbackImpl
|
||||
auto callback = JCxxCallbackImpl::newObjectCxxArgs(fn);
|
||||
jargs[i].l = callback.release();
|
||||
} else {
|
||||
auto dynamicFromValue = jsi::dynamicFromValue(rt, args[i]);
|
||||
auto jParams = ReadableNativeMap::createWithContents(std::move(dynamicFromValue));
|
||||
jargs[i].l = jParams.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
return jargs;
|
||||
}
|
||||
|
||||
jsi::Value convertFromJMapToValue(JNIEnv *env, jsi::Runtime &rt, jobject arg) {
|
||||
// We currently use Java Argument.makeNativeMap() method to do this conversion
|
||||
// This could also be done purely in C++, but iterative over map methods
|
||||
// but those may end up calling reflection methods anyway
|
||||
// TODO (axe) Investigate the best way to convert Java Map to Value
|
||||
static jclass jArguments = env->FindClass("com/facebook/react/bridge/Arguments");
|
||||
static jmethodID jMakeNativeMap = env->GetStaticMethodID(jArguments, "makeNativeMap", "(Ljava/util/Map;)Lcom/facebook/react/bridge/WritableNativeMap;");
|
||||
auto constants = (jobject) env->CallStaticObjectMethod(jArguments, jMakeNativeMap, arg);
|
||||
auto jResult = jni::adopt_local(constants);
|
||||
auto result = jni::static_ref_cast<NativeMap::jhybridobject>(jResult);
|
||||
return jsi::valueFromDynamic(rt, result->cthis()->consume());
|
||||
}
|
||||
|
||||
jsi::Value JavaTurboModule::get(jsi::Runtime& runtime, const jsi::PropNameID& propName) {
|
||||
std::string propNameUtf8 = propName.utf8(runtime);
|
||||
if (propNameUtf8 == "getConstants") {
|
||||
// This is the special method to get the constants from the module.
|
||||
// Since `getConstants` in Java only returns a Map, this function takes the map
|
||||
// and converts it to a WritableMap.
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
propName,
|
||||
0,
|
||||
[this](jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, size_t count) {
|
||||
JNIEnv *env = jni::Environment::current();
|
||||
jclass cls = env->FindClass(jClassName_.c_str());
|
||||
static jmethodID methodID = env->GetMethodID(cls, "getConstants", "()Ljava/util/Map;");
|
||||
auto constantsMap = (jobject) env->CallObjectMethod(instance_.get(), methodID);
|
||||
if (constantsMap == nullptr) {
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
return convertFromJMapToValue(env, rt, constantsMap);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
return TurboModule::get(runtime, propName);
|
||||
}
|
||||
}
|
||||
|
||||
jsi::Value JavaTurboModule::invokeJavaMethod(
|
||||
jsi::Runtime &rt,
|
||||
TurboModuleMethodValueKind valueKind,
|
||||
const std::string &methodName,
|
||||
const std::string &methodSignature,
|
||||
const jsi::Value *args,
|
||||
size_t count) {
|
||||
|
||||
// We are using JNI directly instead of fbjni since we don't want template functiosn
|
||||
// when finding methods.
|
||||
JNIEnv *env = jni::Environment::current();
|
||||
// TODO (axe) Memoize this class, so that we don't have to find it for every calls
|
||||
jclass cls = env->FindClass(jClassName_.c_str());
|
||||
|
||||
// TODO (axe) Memoize method call, so we don't look it up each time the method is called
|
||||
jmethodID methodID = env->GetMethodID(cls, methodName.c_str(), methodSignature.c_str());
|
||||
|
||||
std::unique_ptr<jvalue[]>jargs = convertFromJValueArgsToJNIArgs(env, rt, args, count, jsInvoker_);
|
||||
auto instance = instance_.get();
|
||||
|
||||
switch (valueKind) {
|
||||
case VoidKind: {
|
||||
env->CallVoidMethodA(instance, methodID, jargs.get());
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
case BooleanKind: {
|
||||
return jsi::Value((bool)env->CallBooleanMethodA(instance, methodID, jargs.get()));
|
||||
}
|
||||
case NumberKind: {
|
||||
return jsi::Value((double)env->CallDoubleMethodA(instance, methodID, jargs.get()));
|
||||
}
|
||||
case StringKind: {
|
||||
auto returnString = (jstring) env->CallObjectMethodA(instance, methodID, jargs.get());
|
||||
if (returnString == nullptr) {
|
||||
return jsi::Value::null();
|
||||
}
|
||||
const char *js = env->GetStringUTFChars(returnString, nullptr);
|
||||
std::string result = js;
|
||||
env->ReleaseStringUTFChars(returnString, js);
|
||||
return jsi::Value(rt, jsi::String::createFromUtf8(rt, result));
|
||||
}
|
||||
case ObjectKind: {
|
||||
auto returnObject = (jobject) env->CallObjectMethodA(instance, methodID, jargs.get());
|
||||
if (returnObject == nullptr) {
|
||||
return jsi::Value::null();
|
||||
}
|
||||
auto jResult = jni::adopt_local(returnObject);
|
||||
auto result = jni::static_ref_cast<NativeMap::jhybridobject>(jResult);
|
||||
return jsi::valueFromDynamic(rt, result->cthis()->consume());
|
||||
}
|
||||
case ArrayKind: {
|
||||
auto returnObject = (jobject) env->CallObjectMethodA(instance, methodID, jargs.get());
|
||||
if (returnObject == nullptr) {
|
||||
return jsi::Value::null();
|
||||
}
|
||||
auto jResult = jni::adopt_local(returnObject);
|
||||
auto result = jni::static_ref_cast<NativeArray::jhybridobject>(jResult);
|
||||
return jsi::valueFromDynamic(rt, result->cthis()->consume());
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error("Unable to find method module: " + methodName + "(" + methodSignature + ")" + "in module " + jClassName_);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <fb/fbjni.h>
|
||||
#include <jsi/jsi.h>
|
||||
#include <jsireact/TurboModule.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
struct JTurboModule : jni::JavaClass<JTurboModule> {
|
||||
static auto constexpr kJavaDescriptor = "Lcom/facebook/react/turbomodule/core/interfaces/TurboModule;";
|
||||
};
|
||||
|
||||
class JSI_EXPORT JavaTurboModule : public TurboModule {
|
||||
public:
|
||||
JavaTurboModule(const std::string &name, jni::global_ref<JTurboModule> instance, std::shared_ptr<JSCallInvoker> jsInvoker);
|
||||
jsi::Value invokeJavaMethod(
|
||||
jsi::Runtime &runtime,
|
||||
TurboModuleMethodValueKind valueKind,
|
||||
const std::string &methodName,
|
||||
const std::string &methodSignature,
|
||||
const jsi::Value *args,
|
||||
size_t count);
|
||||
|
||||
virtual facebook::jsi::Value get(facebook::jsi::Runtime& runtime, const facebook::jsi::PropNameID& propName) override;
|
||||
|
||||
protected:
|
||||
// TODO (axe) Specify class name as kJavaDescriptor instead of a class variable
|
||||
std::string jClassName_;
|
||||
private:
|
||||
jni::global_ref<JTurboModule> instance_;
|
||||
jclass findClass(JNIEnv *env) const;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
Loading…
Reference in New Issue