Introduce TurboModuleManagerDelegate

Summary:
`TurboModuleManagerDelegate` is an abstract base class with the following API:

```
  public TurboModule getModule(String name, ReactApplicationContext reactApplicationContext);
  public CxxModuleWrapper getLegacyCxxModule(String name, ReactApplicationContext reactApplicationContext);
```

```
  std::shared_ptr<TurboModule> getTurboModule(std::string name, jni::global_ref<JTurboModule> turboModule, std::shared_ptr<JSCallInvoker> jsInvoker) override;
  std::shared_ptr<TurboModule> getTurboModule(std::string name, std::shared_ptr<JSCallInvoker> jsInvoker) override;
```

On the C++ side, when asked to provide a TurboModule with name `name`:

1. First, is this a CxxModule? If so:
    1. Create the CxxModule and return
2. Otherwise:
    1. Somehow get a Java instance of the TurboModule
    2. If this Java object represents a CxxModule, like `FbReactLibSodiumModule`:
        1. Grab the C++ part of this object, and wrap it in a `TurboCxxModule.cpp` and return.
    3. Otherwise:
        1. Wrap the Java object in a C++ HostObject and return.

This pseudocode demonstrates how we'd use `TurboModuleManagerDelegate` to implement `__turboModuleProxy`.
```
__turboModuleProxy(name, jsCallInvoker):
  let cxxModule = TurboModuleManagerDelegate::getTurboModule(name, jsCallInvoker)
  if (!cxxModule) {
    return cxxModule;
  }

  // JNI Call that forwards to TurboModuleManagerDelegate.getLegacyCxxModule
  let javaCxxModule : CxxModuleWrapper = TurboModuleManager.getLegacyCxxModule(name)

  if (!javaCxxModule) {
    return std::shared_ptr<react::TurboCxxModule>(javaCxxModule.getModule())
  }

  // JNI Call that forwards to TurboModuleManagerDelegate.getModule
  let javaModule : TurboModule = TurboModuleManager.getModule(name)

  if (!javaCxxModule) {
    return TurboModuleManagerDelegate::getTurboModule(name, javaModule, jsCallInvoker)
  }

  return null
```

Reviewed By: mdvacca

Differential Revision: D15111335

fbshipit-source-id: c7b0aeda0e4565e3a2729e7f9604775782b6f893
This commit is contained in:
Ramanpreet Nara
2019-05-03 13:25:56 -07:00
committed by Facebook Github Bot
parent ef4955fefe
commit cba205b82c
8 changed files with 123 additions and 54 deletions

View File

@@ -27,41 +27,37 @@ public class TurboModuleManager implements JSIModule {
}
private final ReactApplicationContext mReactApplicationContext;
private final TurboModuleManagerDelegate mTurbomoduleManagerDelegate;
@DoNotStrip
@SuppressWarnings("unused")
private final HybridData mHybridData;
private final ModuleProvider mModuleProvider;
public TurboModuleManager(
ReactApplicationContext reactApplicationContext, JavaScriptContextHolder jsContext, ModuleProvider moduleProvider) {
ReactApplicationContext reactApplicationContext, JavaScriptContextHolder jsContext, TurboModuleManagerDelegate tmmDelegate) {
mReactApplicationContext = reactApplicationContext;
JSCallInvokerHolderImpl instanceHolder =
(JSCallInvokerHolderImpl) mReactApplicationContext
.getCatalystInstance()
.getJSCallInvokerHolder();
mHybridData = initHybrid(jsContext.get(), instanceHolder);
mModuleProvider = moduleProvider;
mHybridData = initHybrid(jsContext.get(), instanceHolder, tmmDelegate);
mTurbomoduleManagerDelegate = tmmDelegate;
}
@DoNotStrip
@SuppressWarnings("unused")
protected TurboModule getJavaModule(String name) {
return mModuleProvider.getModule(name, mReactApplicationContext);
private TurboModule getJavaModule(String name) {
return mTurbomoduleManagerDelegate.getModule(name);
}
protected native HybridData initHybrid(long jsContext, JSCallInvokerHolderImpl jsQueue);
private native HybridData initHybrid(long jsContext, JSCallInvokerHolderImpl jsQueue, TurboModuleManagerDelegate tmmDelegate);
protected native void installJSIBindings();
private native void installJSIBindings();
public void installBindings() {
installJSIBindings();
}
protected ReactApplicationContext getReactApplicationContext() {
return mReactApplicationContext;
}
@Override
public void initialize() {}

View File

@@ -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.
*/
package com.facebook.react.turbomodule.core;
import com.facebook.jni.HybridData;
import com.facebook.react.bridge.CxxModuleWrapper;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import com.facebook.soloader.SoLoader;
import javax.annotation.Nullable;
public abstract class TurboModuleManagerDelegate {
static {
SoLoader.loadLibrary("turbomodulejsijni");
}
private final HybridData mHybridData;
private final ReactApplicationContext mReactApplicationContext;
protected abstract HybridData initHybrid();
protected TurboModuleManagerDelegate(ReactApplicationContext rac) {
mHybridData = initHybrid();
mReactApplicationContext = rac;
}
protected ReactApplicationContext getReactApplicationContext() {
return mReactApplicationContext;
}
/**
* Create and return a TurboModule Java object with name `moduleName`.
* If `moduleName` isn't a TurboModule, return null.
*/
@Nullable
public abstract TurboModule getModule(String moduleName);
/**
* Create an return a CxxModuleWrapper NativeModule with name `moduleName`.
* If `moduleName` isn't a CxxModule, return null.
*/
@Nullable
public abstract CxxModuleWrapper getLegacyCxxModule(String moduleName);
}

View File

@@ -2,24 +2,14 @@ load("@fbsource//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "FBJNI_TARGET", "
rn_xplat_cxx_library(
name = "jni",
platforms = ANDROID,
preferred_linkage = "static",
visibility = [
"PUBLIC",
],
exported_deps = [
":turbomodulemanager",
],
)
rn_xplat_cxx_library(
name = "turbomodulemanager",
srcs = [
"OnLoad.cpp",
"TurboModuleManager.cpp",
],
header_namespace = "",
exported_headers = {
"jsireact/TurboModuleManager.h": "TurboModuleManager.h",
"jsireact/TurboModuleManagerDelegate.h": "TurboModuleManagerDelegate.h",
},
compiler_flags = [
"-fexceptions",
@@ -28,23 +18,20 @@ rn_xplat_cxx_library(
"-Wall",
],
platforms = ANDROID,
preferred_linkage = "static",
preprocessor_flags = [
"-DLOG_TAG=\"ReactNative\"",
"-DWITH_FBSYSTRACE=1",
],
soname = "libturbomodulejsijni.$(ext)",
visibility = [
"PUBLIC",
],
deps = [
react_native_target("jni/react/jni:jni"),
"fbsource//xplat/jsi:JSIDynamic",
"fbsource//xplat/jsi:jsi",
":jscallinvokerholder",
],
exported_deps = [
"fbsource//xplat/jsi:jsi",
react_native_xplat_target("cxxreact:bridge"),
":jscallinvokerholder",
react_native_xplat_target("turbomodule/core:core"),
],
)
@@ -76,9 +63,6 @@ rn_xplat_cxx_library(
visibility = [
"PUBLIC",
],
deps = [
react_native_xplat_target("cxxreact:bridge"),
],
exported_deps = [
react_native_xplat_target("jscallinvoker:jscallinvoker"),
],

View File

@@ -0,0 +1,13 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#include <fb/fbjni.h>
#include <fb/xplat_init.h>
#include "TurboModuleManager.h"
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
return facebook::xplat::initialize(vm, [] {
// TODO: dvacca ramanpreet unify this with the way "ComponentDescriptorFactory" is defined in Fabric
facebook::react::TurboModuleManager::registerNatives();
});
}

View File

@@ -11,7 +11,6 @@
#include <fb/fbjni.h>
#include <jsi/jsi.h>
#include <cxxreact/Instance.h>
#include <jsireact/TurboModuleBinding.h>
#include <react/jni/JMessageQueueThread.h>
@@ -21,26 +20,27 @@
namespace facebook {
namespace react {
static JTurboModuleProviderFunctionType moduleProvider_ = nullptr;
TurboModuleManager::TurboModuleManager(
jni::alias_ref<TurboModuleManager::javaobject> jThis,
jsi::Runtime* rt,
std::shared_ptr<JSCallInvoker> jsCallInvoker
std::shared_ptr<JSCallInvoker> jsCallInvoker,
jni::alias_ref<TurboModuleManagerDelegate::javaobject> tmmDelegate
):
javaPart_(jni::make_global(jThis)),
runtime_(rt),
jsCallInvoker_(jsCallInvoker)
jsCallInvoker_(jsCallInvoker),
turboModuleManagerDelegate_(jni::make_global(tmmDelegate))
{}
jni::local_ref<TurboModuleManager::jhybriddata> TurboModuleManager::initHybrid(
jni::alias_ref<jhybridobject> jThis,
jlong jsContext,
jni::alias_ref<JSCallInvokerHolder::javaobject> jsCallInvokerHolder
jni::alias_ref<JSCallInvokerHolder::javaobject> jsCallInvokerHolder,
jni::alias_ref<TurboModuleManagerDelegate::javaobject> tmmDelegate
) {
auto jsCallInvoker = jsCallInvokerHolder->cthis()->getJSCallInvoker();
return makeCxxInstance(jThis, (jsi::Runtime *) jsContext, jsCallInvoker);
return makeCxxInstance(jThis, (jsi::Runtime *) jsContext, jsCallInvoker, tmmDelegate);
}
void TurboModuleManager::registerNatives() {
@@ -57,18 +57,17 @@ void TurboModuleManager::installJSIBindings() {
TurboModuleBinding::install(*runtime_, std::make_shared<TurboModuleBinding>(
[this](const std::string &name) {
const auto moduleInstance = getJavaModule(name);
return moduleProvider_(name, moduleInstance, jsCallInvoker_);
return turboModuleManagerDelegate_->cthis()->getTurboModule(name, moduleInstance, jsCallInvoker_);
})
);
}
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;
auto module = jni::make_global(method(javaPart_.get(), name));
return module;
}
} // namespace react

View File

@@ -14,35 +14,35 @@
#include <jsireact/JavaTurboModule.h>
#include <react/jni/JMessageQueueThread.h>
#include <jsireact/JSCallInvokerHolder.h>
#include <jsireact/TurboModuleManagerDelegate.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<JSCallInvokerHolder::javaobject> jsCallInvokerHolder
jni::alias_ref<JSCallInvokerHolder::javaobject> jsCallInvokerHolder,
jni::alias_ref<TurboModuleManagerDelegate::javaobject> tmmDelegate
);
static void registerNatives();
static void setModuleProvider(JTurboModuleProviderFunctionType moduleProvider);
private:
friend HybridBase;
jni::global_ref<TurboModuleManager::javaobject> javaPart_;
jsi::Runtime* runtime_;
std::shared_ptr<JSCallInvoker> jsCallInvoker_;
jni::global_ref<TurboModuleManagerDelegate::javaobject> turboModuleManagerDelegate_;
jni::global_ref<JTurboModule> getJavaModule(std::string name);
void installJSIBindings();
explicit TurboModuleManager(
jni::alias_ref<TurboModuleManager::jhybridobject> jThis,
jsi::Runtime *rt,
std::shared_ptr<JSCallInvoker> jsCallInvoker
std::shared_ptr<JSCallInvoker> jsCallInvoker,
jni::alias_ref<TurboModuleManagerDelegate::javaobject> tmmDelegate
);
};

View File

@@ -0,0 +1,31 @@
/**
* 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 <fb/fbjni.h>
#include <jsireact/JavaTurboModule.h>
#include <jsireact/JSCallInvoker.h>
#include <string>
#include <memory>
namespace facebook {
namespace react {
class TurboModuleManagerDelegate : public jni::HybridClass<TurboModuleManagerDelegate> {
public:
static auto constexpr kJavaDescriptor = "Lcom/facebook/react/turbomodule/core/TurboModuleManagerDelegate;";
virtual std::shared_ptr<TurboModule> getTurboModule(std::string name, jni::global_ref<JTurboModule> turboModule, std::shared_ptr<JSCallInvoker> jsInvoker) = 0;
virtual std::shared_ptr<TurboModule> getTurboModule(std::string name, std::shared_ptr<JSCallInvoker> jsInvoker) = 0;
private:
friend HybridBase;
};
} // namespace react
} // namespace facebook

View File

@@ -1,4 +1,4 @@
load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "FBJNI_TARGET", "react_native_xplat_target", "rn_xplat_cxx_library", "subdir_glob")
load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "react_native_xplat_target", "rn_xplat_cxx_library", "subdir_glob")
rn_xplat_cxx_library(
name = "jscallinvoker",
@@ -18,9 +18,6 @@ rn_xplat_cxx_library(
"-std=c++14",
"-Wall",
],
fbandroid_deps = [
FBJNI_TARGET,
],
platforms = (ANDROID, APPLE),
preferred_linkage = "static",
preprocessor_flags = [