Delete ModuleRegistryHolder

Reviewed By: mhorowitz

Differential Revision: D4411478

fbshipit-source-id: 03f48f92f0d97bd5e3318f60c8357242fe9792cf
This commit is contained in:
Pieter De Baets 2017-01-30 09:33:09 -08:00 committed by Facebook Github Bot
parent bf930e473a
commit 0e7d0ebd9a
13 changed files with 300 additions and 355 deletions

View File

@ -128,7 +128,8 @@ public class CatalystInstanceImpl implements CatalystInstance {
jsExecutor, jsExecutor,
mReactQueueConfiguration.getJSQueueThread(), mReactQueueConfiguration.getJSQueueThread(),
mReactQueueConfiguration.getNativeModulesQueueThread(), mReactQueueConfiguration.getNativeModulesQueueThread(),
mJavaRegistry.getModuleRegistryHolder(this)); mJavaRegistry.getJavaModules(this),
mJavaRegistry.getCxxModules());
mMainExecutorToken = getMainExecutorToken(); mMainExecutorToken = getMainExecutorToken();
} }
@ -179,7 +180,8 @@ public class CatalystInstanceImpl implements CatalystInstance {
JavaScriptExecutor jsExecutor, JavaScriptExecutor jsExecutor,
MessageQueueThread jsQueue, MessageQueueThread jsQueue,
MessageQueueThread moduleQueue, MessageQueueThread moduleQueue,
ModuleRegistryHolder registryHolder); Collection<JavaModuleWrapper> javaModules,
Collection<CxxModuleWrapper> cxxModules);
/** /**
* This API is used in situations where the JS bundle is being executed not on * This API is used in situations where the JS bundle is being executed not on

View File

@ -1,28 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.react.cxxbridge;
import java.util.Collection;
import com.facebook.jni.HybridData;
public class ModuleRegistryHolder {
private final HybridData mHybridData;
private static native HybridData initHybrid(
CatalystInstanceImpl catalystInstanceImpl,
Collection<JavaModuleWrapper> javaModules,
Collection<CxxModuleWrapper> cxxModules);
public ModuleRegistryHolder(CatalystInstanceImpl catalystInstanceImpl,
Collection<JavaModuleWrapper> javaModules,
Collection<CxxModuleWrapper> cxxModules) {
mHybridData = initHybrid(catalystInstanceImpl, javaModules, cxxModules);
}
}

View File

@ -10,6 +10,7 @@
package com.facebook.react.cxxbridge; package com.facebook.react.cxxbridge;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -36,22 +37,27 @@ public class NativeModuleRegistry {
mBatchCompleteListenerModules = batchCompleteListenerModules; mBatchCompleteListenerModules = batchCompleteListenerModules;
} }
/* package */ ModuleRegistryHolder getModuleRegistryHolder( /* package */ Collection<JavaModuleWrapper> getJavaModules(
CatalystInstanceImpl catalystInstanceImpl) { CatalystInstanceImpl catalystInstanceImpl) {
ArrayList<JavaModuleWrapper> javaModules = new ArrayList<>(); ArrayList<JavaModuleWrapper> javaModules = new ArrayList<>();
for (Map.Entry<Class<? extends NativeModule>, ModuleHolder> entry : mModules.entrySet()) {
Class<?> type = entry.getKey();
if (!CxxModuleWrapper.class.isAssignableFrom(type)) {
javaModules.add(new JavaModuleWrapper(catalystInstanceImpl, entry.getValue()));
}
}
return javaModules;
}
/* package */ Collection<CxxModuleWrapper> getCxxModules() {
ArrayList<CxxModuleWrapper> cxxModules = new ArrayList<>(); ArrayList<CxxModuleWrapper> cxxModules = new ArrayList<>();
for (Map.Entry<Class<? extends NativeModule>, ModuleHolder> entry : mModules.entrySet()) { for (Map.Entry<Class<? extends NativeModule>, ModuleHolder> entry : mModules.entrySet()) {
Class<?> type = entry.getKey(); Class<?> type = entry.getKey();
ModuleHolder moduleHolder = entry.getValue(); if (CxxModuleWrapper.class.isAssignableFrom(type)) {
if (BaseJavaModule.class.isAssignableFrom(type)) { cxxModules.add((CxxModuleWrapper) entry.getValue().getModule());
javaModules.add(new JavaModuleWrapper(catalystInstanceImpl, moduleHolder));
} else if (CxxModuleWrapper.class.isAssignableFrom(type)) {
cxxModules.add((CxxModuleWrapper) moduleHolder.getModule());
} else {
throw new IllegalArgumentException("Unknown module type " + type);
} }
} }
return new ModuleRegistryHolder(catalystInstanceImpl, javaModules, cxxModules); return cxxModules;
} }
/* package */ void notifyCatalystInstanceDestroy() { /* package */ void notifyCatalystInstanceDestroy() {

View File

@ -7,6 +7,7 @@ LOCAL_MODULE := reactnativejnifb
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \
CatalystInstanceImpl.cpp \ CatalystInstanceImpl.cpp \
CxxModuleWrapper.cpp \ CxxModuleWrapper.cpp \
JavaModuleWrapper.cpp \
JExecutorToken.cpp \ JExecutorToken.cpp \
JMessageQueueThread.cpp \ JMessageQueueThread.cpp \
JniJSModulesUnbundle.cpp \ JniJSModulesUnbundle.cpp \
@ -14,7 +15,6 @@ LOCAL_SRC_FILES := \
JSLoader.cpp \ JSLoader.cpp \
JSLogging.cpp \ JSLogging.cpp \
MethodInvoker.cpp \ MethodInvoker.cpp \
ModuleRegistryHolder.cpp \
OnLoad.cpp \ OnLoad.cpp \
ProxyExecutor.cpp \ ProxyExecutor.cpp \

View File

@ -7,6 +7,7 @@ LOCAL_MODULE := libreactnativejnifb
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \
CatalystInstanceImpl.cpp \ CatalystInstanceImpl.cpp \
CxxModuleWrapper.cpp \ CxxModuleWrapper.cpp \
JavaModuleWrapper.cpp \
JExecutorToken.cpp \ JExecutorToken.cpp \
JMessageQueueThread.cpp \ JMessageQueueThread.cpp \
JSCPerfLogging.cpp \ JSCPerfLogging.cpp \
@ -14,7 +15,6 @@ LOCAL_SRC_FILES := \
JSLogging.cpp \ JSLogging.cpp \
JniJSModulesUnbundle.cpp \ JniJSModulesUnbundle.cpp \
MethodInvoker.cpp \ MethodInvoker.cpp \
ModuleRegistryHolder.cpp \
NativeArray.cpp \ NativeArray.cpp \
NativeCommon.cpp \ NativeCommon.cpp \
NativeMap.cpp \ NativeMap.cpp \

View File

@ -18,13 +18,13 @@
#include <cxxreact/JSIndexedRAMBundle.h> #include <cxxreact/JSIndexedRAMBundle.h>
#include <cxxreact/MethodCall.h> #include <cxxreact/MethodCall.h>
#include <cxxreact/ModuleRegistry.h> #include <cxxreact/ModuleRegistry.h>
#include <cxxreact/CxxNativeModule.h>
#include "JSLoader.h"
#include "JavaScriptExecutorHolder.h" #include "JavaScriptExecutorHolder.h"
#include "JniJSModulesUnbundle.h" #include "JniJSModulesUnbundle.h"
#include "ModuleRegistryHolder.h"
#include "NativeArray.h"
#include "JNativeRunnable.h" #include "JNativeRunnable.h"
#include "JSLoader.h"
#include "NativeArray.h"
using namespace facebook::jni; using namespace facebook::jni;
@ -33,7 +33,6 @@ namespace react {
namespace { namespace {
class Exception : public jni::JavaClass<Exception> { class Exception : public jni::JavaClass<Exception> {
public: public:
static auto constexpr kJavaDescriptor = "Ljava/lang/Exception;"; static auto constexpr kJavaDescriptor = "Ljava/lang/Exception;";
@ -130,10 +129,22 @@ void CatalystInstanceImpl::initializeBridge(
JavaScriptExecutorHolder* jseh, JavaScriptExecutorHolder* jseh,
jni::alias_ref<JavaMessageQueueThread::javaobject> jsQueue, jni::alias_ref<JavaMessageQueueThread::javaobject> jsQueue,
jni::alias_ref<JavaMessageQueueThread::javaobject> moduleQueue, jni::alias_ref<JavaMessageQueueThread::javaobject> moduleQueue,
ModuleRegistryHolder* mrh) { jni::alias_ref<jni::JCollection<JavaModuleWrapper::javaobject>::javaobject> javaModules,
jni::alias_ref<jni::JCollection<CxxModuleWrapper::javaobject>::javaobject> cxxModules) {
// TODO mhorowitz: how to assert here? // TODO mhorowitz: how to assert here?
// Assertions.assertCondition(mBridge == null, "initializeBridge should be called once"); // Assertions.assertCondition(mBridge == null, "initializeBridge should be called once");
std::vector<std::unique_ptr<NativeModule>> modules;
std::weak_ptr<Instance> winstance(instance_);
for (const auto& jm : *javaModules) {
modules.emplace_back(folly::make_unique<JavaNativeModule>(winstance, jm));
}
for (const auto& cm : *cxxModules) {
modules.emplace_back(
folly::make_unique<CxxNativeModule>(winstance, std::move(cthis(cm)->getModule())));
}
auto moduleRegistry = std::make_shared<ModuleRegistry>(std::move(modules));
// This used to be: // This used to be:
// //
// Java CatalystInstanceImpl -> C++ CatalystInstanceImpl -> Bridge -> Bridge::Callback // Java CatalystInstanceImpl -> C++ CatalystInstanceImpl -> Bridge -> Bridge::Callback
@ -154,7 +165,7 @@ void CatalystInstanceImpl::initializeBridge(
jseh->getExecutorFactory(), jseh->getExecutorFactory(),
folly::make_unique<JMessageQueueThread>(jsQueue), folly::make_unique<JMessageQueueThread>(jsQueue),
folly::make_unique<JMessageQueueThread>(moduleQueue), folly::make_unique<JMessageQueueThread>(moduleQueue),
mrh->getModuleRegistry()); moduleRegistry);
} }
void CatalystInstanceImpl::jniSetSourceURL(const std::string& sourceURL) { void CatalystInstanceImpl::jniSetSourceURL(const std::string& sourceURL) {

View File

@ -5,16 +5,17 @@
#include <fb/fbjni.h> #include <fb/fbjni.h>
#include <folly/Memory.h> #include <folly/Memory.h>
#include "CxxModuleWrapper.h"
#include "JExecutorToken.h" #include "JExecutorToken.h"
#include "JMessageQueueThread.h" #include "JMessageQueueThread.h"
#include "JSLoader.h" #include "JSLoader.h"
#include "JavaModuleWrapper.h"
namespace facebook { namespace facebook {
namespace react { namespace react {
class Instance; class Instance;
class JavaScriptExecutorHolder; class JavaScriptExecutorHolder;
class ModuleRegistryHolder;
class NativeArray; class NativeArray;
struct ReactCallback : public jni::JavaClass<ReactCallback> { struct ReactCallback : public jni::JavaClass<ReactCallback> {
@ -46,7 +47,8 @@ class CatalystInstanceImpl : public jni::HybridClass<CatalystInstanceImpl> {
JavaScriptExecutorHolder* jseh, JavaScriptExecutorHolder* jseh,
jni::alias_ref<JavaMessageQueueThread::javaobject> jsQueue, jni::alias_ref<JavaMessageQueueThread::javaobject> jsQueue,
jni::alias_ref<JavaMessageQueueThread::javaobject> moduleQueue, jni::alias_ref<JavaMessageQueueThread::javaobject> moduleQueue,
ModuleRegistryHolder* mrh); jni::alias_ref<jni::JCollection<JavaModuleWrapper::javaobject>::javaobject> javaModules,
jni::alias_ref<jni::JCollection<CxxModuleWrapper::javaobject>::javaobject> cxxModules);
/** /**
* Sets the source URL of the underlying bridge without loading any JS code. * Sets the source URL of the underlying bridge without loading any JS code.

View File

@ -0,0 +1,159 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#include "JavaModuleWrapper.h"
#include <folly/json.h>
#include <fb/fbjni.h>
#include <cxxreact/CxxModule.h>
#include <cxxreact/CxxNativeModule.h>
#include <cxxreact/Instance.h>
#include <cxxreact/JsArgumentHelpers.h>
#include <cxxreact/NativeModule.h>
#include "CatalystInstanceImpl.h"
#include "ReadableNativeArray.h"
using facebook::xplat::module::CxxModule;
namespace facebook {
namespace react {
std::string JMethodDescriptor::getSignature() const {
static auto signature = javaClassStatic()->getField<jstring>("signature");
return getFieldValue(signature)->toStdString();
}
std::string JMethodDescriptor::getName() const {
static auto name = javaClassStatic()->getField<jstring>("name");
return getFieldValue(name)->toStdString();
}
std::string JMethodDescriptor::getType() const {
static auto type = javaClassStatic()->getField<jstring>("type");
return getFieldValue(type)->toStdString();
}
std::string JavaNativeModule::getName() {
static auto getNameMethod = wrapper_->getClass()->getMethod<jstring()>("getName");
return getNameMethod(wrapper_)->toStdString();
}
std::vector<MethodDescriptor> JavaNativeModule::getMethods() {
std::vector<MethodDescriptor> ret;
auto descs = wrapper_->getMethodDescriptors();
for (const auto& desc : *descs) {
ret.emplace_back(desc->getName(), desc->getType());
}
return ret;
}
folly::dynamic JavaNativeModule::getConstants() {
static auto constantsMethod =
wrapper_->getClass()->getMethod<NativeArray::javaobject()>("getConstants");
auto constants = constantsMethod(wrapper_);
if (!constants) {
return nullptr;
} else {
// See JavaModuleWrapper#getConstants for the other side of this hack.
return cthis(constants)->array[0];
}
}
bool JavaNativeModule::supportsWebWorkers() {
static auto supportsWebWorkersMethod =
wrapper_->getClass()->getMethod<jboolean()>("supportsWebWorkers");
return supportsWebWorkersMethod(wrapper_);
}
void JavaNativeModule::invoke(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) {
static auto invokeMethod =
wrapper_->getClass()->getMethod<void(JExecutorToken::javaobject, jint, ReadableNativeArray::javaobject)>("invoke");
invokeMethod(wrapper_, JExecutorToken::extractJavaPartFromToken(token).get(), static_cast<jint>(reactMethodId),
ReadableNativeArray::newObjectCxxArgs(std::move(params)).get());
}
MethodCallResult JavaNativeModule::callSerializableNativeHook(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) {
throw std::runtime_error("Unsupported operation.");
}
NewJavaNativeModule::NewJavaNativeModule(
std::weak_ptr<Instance> instance,
jni::alias_ref<JavaModuleWrapper::javaobject> wrapper)
: instance_(std::move(instance)),
wrapper_(make_global(wrapper)),
module_(make_global(wrapper->getModule())) {
auto descs = wrapper_->getMethodDescriptors();
std::string moduleName = getName();
methods_.reserve(descs->size());
for (const auto& desc : *descs) {
auto type = desc->getType();
auto name = desc->getName();
methods_.emplace_back(
desc->getMethod(),
desc->getSignature(),
moduleName + "." + name,
type == "syncHook");
methodDescriptors_.emplace_back(name, type);
}
}
std::string NewJavaNativeModule::getName() {
static auto getNameMethod = wrapper_->getClass()->getMethod<jstring()>("getName");
return getNameMethod(wrapper_)->toStdString();
}
std::vector<MethodDescriptor> NewJavaNativeModule::getMethods() {
return methodDescriptors_;
}
folly::dynamic NewJavaNativeModule::getConstants() {
static auto constantsMethod =
wrapper_->getClass()->getMethod<NativeArray::javaobject()>("getConstants");
auto constants = constantsMethod(wrapper_);
if (!constants) {
return nullptr;
} else {
// See JavaModuleWrapper#getConstants for the other side of this hack.
return cthis(constants)->array[0];
}
}
bool NewJavaNativeModule::supportsWebWorkers() {
static auto supportsWebWorkersMethod =
wrapper_->getClass()->getMethod<jboolean()>("supportsWebWorkers");
return supportsWebWorkersMethod(wrapper_);
}
void NewJavaNativeModule::invoke(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) {
if (reactMethodId >= methods_.size()) {
throw std::invalid_argument(
folly::to<std::string>("methodId ", reactMethodId, " out of range [0..", methods_.size(), "]"));
}
CHECK(!methods_[reactMethodId].isSyncHook()) << "Trying to invoke a synchronous hook asynchronously";
invokeInner(token, reactMethodId, std::move(params));
}
MethodCallResult NewJavaNativeModule::callSerializableNativeHook(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) {
if (reactMethodId >= methods_.size()) {
throw std::invalid_argument(
folly::to<std::string>("methodId ", reactMethodId, " out of range [0..", methods_.size(), "]"));
}
CHECK(methods_[reactMethodId].isSyncHook()) << "Trying to invoke a asynchronous method as synchronous hook";
return invokeInner(token, reactMethodId, std::move(params));
}
MethodCallResult NewJavaNativeModule::invokeInner(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) {
return methods_[reactMethodId].invoke(instance_, module_.get(), token, params);
}
jni::local_ref<JReflectMethod::javaobject> JMethodDescriptor::getMethod() const {
static auto method = javaClassStatic()->getField<JReflectMethod::javaobject>("method");
return getFieldValue(method);
}
}
}

View File

@ -0,0 +1,83 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#pragma once
#include <cxxreact/NativeModule.h>
#include <fb/fbjni.h>
#include "MethodInvoker.h"
namespace facebook {
namespace react {
class Instance;
struct JMethodDescriptor : public jni::JavaClass<JMethodDescriptor> {
static constexpr auto kJavaDescriptor =
"Lcom/facebook/react/cxxbridge/JavaModuleWrapper$MethodDescriptor;";
jni::local_ref<JReflectMethod::javaobject> getMethod() const;
std::string getSignature() const;
std::string getName() const;
std::string getType() const;
};
struct JavaModuleWrapper : jni::JavaClass<JavaModuleWrapper> {
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/cxxbridge/JavaModuleWrapper;";
jni::local_ref<JBaseJavaModule::javaobject> getModule() {
static auto getModule = javaClassStatic()->getMethod<JBaseJavaModule::javaobject()>("getModule");
return getModule(self());
}
jni::local_ref<jni::JList<JMethodDescriptor::javaobject>::javaobject> getMethodDescriptors() {
static auto getMethods = getClass()
->getMethod<jni::JList<JMethodDescriptor::javaobject>::javaobject()>("getMethodDescriptors");
return getMethods(self());
}
};
class JavaNativeModule : public NativeModule {
public:
JavaNativeModule(
std::weak_ptr<Instance> instance,
jni::alias_ref<JavaModuleWrapper::javaobject> wrapper)
: instance_(std::move(instance)), wrapper_(make_global(wrapper)) {}
std::string getName() override;
folly::dynamic getConstants() override;
std::vector<MethodDescriptor> getMethods() override;
bool supportsWebWorkers() override;
void invoke(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) override;
MethodCallResult callSerializableNativeHook(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) override;
private:
std::weak_ptr<Instance> instance_;
jni::global_ref<JavaModuleWrapper::javaobject> wrapper_;
};
// Experimental new implementation that uses direct method invocation
class NewJavaNativeModule : public NativeModule {
public:
NewJavaNativeModule(
std::weak_ptr<Instance> instance,
jni::alias_ref<JavaModuleWrapper::javaobject> wrapper);
std::string getName() override;
std::vector<MethodDescriptor> getMethods() override;
folly::dynamic getConstants() override;
bool supportsWebWorkers() override;
void invoke(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) override;
MethodCallResult callSerializableNativeHook(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) override;
private:
std::weak_ptr<Instance> instance_;
jni::global_ref<JavaModuleWrapper::javaobject> wrapper_;
jni::global_ref<JBaseJavaModule::javaobject> module_;
std::vector<MethodInvoker> methods_;
std::vector<MethodDescriptor> methodDescriptors_;
MethodCallResult invokeInner(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params);
};
}}

View File

@ -4,18 +4,29 @@
#include <vector> #include <vector>
#include <cxxreact/ExecutorToken.h>
#include <fb/fbjni.h> #include <fb/fbjni.h>
#include <folly/dynamic.h> #include <folly/dynamic.h>
#include <cxxreact/ExecutorToken.h>
#include "ModuleRegistryHolder.h"
namespace facebook { namespace facebook {
namespace react { namespace react {
class Instance; class Instance;
struct JReflectMethod : public jni::JavaClass<JReflectMethod> {
static constexpr auto kJavaDescriptor = "Ljava/lang/reflect/Method;";
jmethodID getMethodID() {
auto id = jni::Environment::current()->FromReflectedMethod(self());
jni::throwPendingJniExceptionAsCppException();
return id;
}
};
struct JBaseJavaModule : public jni::JavaClass<JBaseJavaModule> {
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/BaseJavaModule;";
};
class MethodInvoker { class MethodInvoker {
public: public:
MethodInvoker(jni::alias_ref<JReflectMethod::javaobject> method, std::string signature, std::string traceName, bool isSync); MethodInvoker(jni::alias_ref<JReflectMethod::javaobject> method, std::string signature, std::string traceName, bool isSync);

View File

@ -1,216 +0,0 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#include "ModuleRegistryHolder.h"
#include <folly/json.h>
#include <fb/fbjni.h>
#include <cxxreact/CxxModule.h>
#include <cxxreact/CxxNativeModule.h>
#include <cxxreact/Instance.h>
#include <cxxreact/JsArgumentHelpers.h>
#include <cxxreact/NativeModule.h>
#include "CatalystInstanceImpl.h"
#include "MethodInvoker.h"
#include "ReadableNativeArray.h"
using facebook::xplat::module::CxxModule;
namespace facebook {
namespace react {
namespace {
class JavaNativeModule : public NativeModule {
public:
JavaNativeModule(jni::alias_ref<JavaModuleWrapper::javaobject> wrapper)
: wrapper_(make_global(wrapper)) {}
std::string getName() override {
static auto getNameMethod = wrapper_->getClass()->getMethod<jstring()>("getName");
return getNameMethod(wrapper_)->toStdString();
}
std::vector<MethodDescriptor> getMethods() override {
static auto getMDMethod =
wrapper_->getClass()->getMethod<jni::JList<JMethodDescriptor::javaobject>::javaobject()>(
"getMethodDescriptors");
std::vector<MethodDescriptor> ret;
auto descs = getMDMethod(wrapper_);
for (const auto& desc : *descs) {
static auto nameField =
JMethodDescriptor::javaClassStatic()->getField<jstring>("name");
static auto typeField =
JMethodDescriptor::javaClassStatic()->getField<jstring>("type");
ret.emplace_back(
desc->getFieldValue(nameField)->toStdString(),
desc->getFieldValue(typeField)->toStdString()
);
}
return ret;
}
folly::dynamic getConstants() override {
static auto constantsMethod =
wrapper_->getClass()->getMethod<NativeArray::javaobject()>("getConstants");
auto constants = constantsMethod(wrapper_);
if (!constants) {
return nullptr;
} else {
// See JavaModuleWrapper#getConstants for the other side of this hack.
return cthis(constants)->array[0];
}
}
virtual bool supportsWebWorkers() override {
static auto supportsWebWorkersMethod =
wrapper_->getClass()->getMethod<jboolean()>("supportsWebWorkers");
return supportsWebWorkersMethod(wrapper_);
}
void invoke(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) override {
static auto invokeMethod =
wrapper_->getClass()->getMethod<void(JExecutorToken::javaobject, jint, ReadableNativeArray::javaobject)>("invoke");
invokeMethod(wrapper_, JExecutorToken::extractJavaPartFromToken(token).get(), static_cast<jint>(reactMethodId),
ReadableNativeArray::newObjectCxxArgs(std::move(params)).get());
}
MethodCallResult callSerializableNativeHook(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) override {
throw std::runtime_error("Unsupported operation.");
}
private:
jni::global_ref<JavaModuleWrapper::javaobject> wrapper_;
};
class NewJavaNativeModule : public NativeModule {
public:
NewJavaNativeModule(std::weak_ptr<Instance> instance, jni::alias_ref<JavaModuleWrapper::javaobject> wrapper)
: instance_(std::move(instance)),
wrapper_(make_global(wrapper)),
module_(make_global(wrapper->getModule())) {
auto descs = wrapper_->getMethodDescriptors();
std::string moduleName = getName();
methods_.reserve(descs->size());
for (const auto& desc : *descs) {
auto type = desc->getType();
auto name = desc->getName();
methods_.emplace_back(
desc->getMethod(),
desc->getSignature(),
moduleName + "." + name,
type == "syncHook");
methodDescriptors_.emplace_back(name, type);
}
}
std::string getName() override {
static auto getNameMethod = wrapper_->getClass()->getMethod<jstring()>("getName");
return getNameMethod(wrapper_)->toStdString();
}
std::vector<MethodDescriptor> getMethods() override {
return methodDescriptors_;
}
folly::dynamic getConstants() override {
static auto constantsMethod =
wrapper_->getClass()->getMethod<NativeArray::javaobject()>("getConstants");
auto constants = constantsMethod(wrapper_);
if (!constants) {
return nullptr;
} else {
// See JavaModuleWrapper#getConstants for the other side of this hack.
return cthis(constants)->array[0];
}
}
virtual bool supportsWebWorkers() override {
static auto supportsWebWorkersMethod =
wrapper_->getClass()->getMethod<jboolean()>("supportsWebWorkers");
return supportsWebWorkersMethod(wrapper_);
}
void invoke(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) override {
if (reactMethodId >= methods_.size()) {
throw std::invalid_argument(
folly::to<std::string>("methodId ", reactMethodId, " out of range [0..", methods_.size(), "]"));
}
CHECK(!methods_[reactMethodId].isSyncHook()) << "Trying to invoke a synchronous hook asynchronously";
invokeInner(token, reactMethodId, std::move(params));
}
MethodCallResult callSerializableNativeHook(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) override {
if (reactMethodId >= methods_.size()) {
throw std::invalid_argument(
folly::to<std::string>("methodId ", reactMethodId, " out of range [0..", methods_.size(), "]"));
}
CHECK(methods_[reactMethodId].isSyncHook()) << "Trying to invoke a asynchronous method as synchronous hook";
return invokeInner(token, reactMethodId, std::move(params));
}
private:
std::weak_ptr<Instance> instance_;
jni::global_ref<JavaModuleWrapper::javaobject> wrapper_;
jni::global_ref<JBaseJavaModule::javaobject> module_;
std::vector<MethodInvoker> methods_;
std::vector<MethodDescriptor> methodDescriptors_;
MethodCallResult invokeInner(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) {
return methods_[reactMethodId].invoke(instance_, module_.get(), token, params);
}
};
}
jni::local_ref<JReflectMethod::javaobject> JMethodDescriptor::getMethod() const {
static auto method = javaClassStatic()->getField<JReflectMethod::javaobject>("method");
return getFieldValue(method);
}
std::string JMethodDescriptor::getSignature() const {
static auto signature = javaClassStatic()->getField<jstring>("signature");
return getFieldValue(signature)->toStdString();
}
std::string JMethodDescriptor::getName() const {
static auto name = javaClassStatic()->getField<jstring>("name");
return getFieldValue(name)->toStdString();
}
std::string JMethodDescriptor::getType() const {
static auto type = javaClassStatic()->getField<jstring>("type");
return getFieldValue(type)->toStdString();
}
void ModuleRegistryHolder::registerNatives() {
registerHybrid({
makeNativeMethod("initHybrid", ModuleRegistryHolder::initHybrid),
});
}
ModuleRegistryHolder::ModuleRegistryHolder(
CatalystInstanceImpl* catalystInstanceImpl,
jni::alias_ref<jni::JCollection<JavaModuleWrapper::javaobject>::javaobject> javaModules,
jni::alias_ref<jni::JCollection<CxxModuleWrapper::javaobject>::javaobject> cxxModules) {
std::vector<std::unique_ptr<NativeModule>> modules;
std::weak_ptr<Instance> winstance(catalystInstanceImpl->getInstance());
for (const auto& jm : *javaModules) {
modules.emplace_back(folly::make_unique<JavaNativeModule>(jm));
}
for (const auto& cm : *cxxModules) {
modules.emplace_back(
folly::make_unique<CxxNativeModule>(winstance, std::move(cthis(cm)->getModule())));
}
registry_ = std::make_shared<ModuleRegistry>(std::move(modules));
}
}
}

View File

@ -1,83 +0,0 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#pragma once
#include <cxxreact/ModuleRegistry.h>
#include <fb/fbjni.h>
#include "CxxModuleWrapper.h"
namespace facebook {
namespace react {
class Instance;
class CatalystInstanceImpl;
struct JReflectMethod : public jni::JavaClass<JReflectMethod> {
static constexpr auto kJavaDescriptor = "Ljava/lang/reflect/Method;";
jmethodID getMethodID() {
auto id = jni::Environment::current()->FromReflectedMethod(self());
jni::throwPendingJniExceptionAsCppException();
return id;
}
};
struct JMethodDescriptor : public jni::JavaClass<JMethodDescriptor> {
static constexpr auto kJavaDescriptor =
"Lcom/facebook/react/cxxbridge/JavaModuleWrapper$MethodDescriptor;";
jni::local_ref<JReflectMethod::javaobject> getMethod() const;
std::string getSignature() const;
std::string getName() const;
std::string getType() const;
};
struct JBaseJavaModule : public jni::JavaClass<JBaseJavaModule> {
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/BaseJavaModule;";
};
struct JavaModuleWrapper : jni::JavaClass<JavaModuleWrapper> {
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/cxxbridge/JavaModuleWrapper;";
jni::local_ref<JBaseJavaModule::javaobject> getModule() {
static auto getModule = javaClassStatic()->getMethod<JBaseJavaModule::javaobject()>("getModule");
return getModule(self());
}
jni::local_ref<jni::JList<JMethodDescriptor::javaobject>::javaobject> getMethodDescriptors() {
static auto getMethods =
getClass()->getMethod<jni::JList<JMethodDescriptor::javaobject>::javaobject()>("getMethodDescriptors");
return getMethods(self());
}
};
class ModuleRegistryHolder : public jni::HybridClass<ModuleRegistryHolder> {
public:
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/cxxbridge/ModuleRegistryHolder;";
std::shared_ptr<ModuleRegistry> getModuleRegistry() {
return registry_;
}
static jni::local_ref<jhybriddata> initHybrid(
jni::alias_ref<jclass>,
CatalystInstanceImpl* catalystInstanceImpl,
jni::alias_ref<jni::JCollection<JavaModuleWrapper::javaobject>::javaobject> javaModules,
jni::alias_ref<jni::JCollection<CxxModuleWrapper::javaobject>::javaobject> cxxModules) {
return makeCxxInstance(catalystInstanceImpl, javaModules, cxxModules);
}
static void registerNatives();
private:
friend HybridBase;
ModuleRegistryHolder(
CatalystInstanceImpl* catalystInstanceImpl,
jni::alias_ref<jni::JCollection<JavaModuleWrapper::javaobject>::javaobject> javaModules,
jni::alias_ref<jni::JCollection<CxxModuleWrapper::javaobject>::javaobject> cxxModules);
std::shared_ptr<ModuleRegistry> registry_;
};
}}

View File

@ -11,7 +11,6 @@
#include "JavaScriptExecutorHolder.h" #include "JavaScriptExecutorHolder.h"
#include "JSCPerfLogging.h" #include "JSCPerfLogging.h"
#include "JSLoader.h" #include "JSLoader.h"
#include "ModuleRegistryHolder.h"
#include "ProxyExecutor.h" #include "ProxyExecutor.h"
#include "WebWorkers.h" #include "WebWorkers.h"
#include "JCallback.h" #include "JCallback.h"
@ -160,7 +159,6 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JSCJavaScriptExecutorHolder::registerNatives(); JSCJavaScriptExecutorHolder::registerNatives();
ProxyJavaScriptExecutorHolder::registerNatives(); ProxyJavaScriptExecutorHolder::registerNatives();
CatalystInstanceImpl::registerNatives(); CatalystInstanceImpl::registerNatives();
ModuleRegistryHolder::registerNatives();
CxxModuleWrapper::registerNatives(); CxxModuleWrapper::registerNatives();
JCallbackImpl::registerNatives(); JCallbackImpl::registerNatives();
#ifdef WITH_INSPECTOR #ifdef WITH_INSPECTOR