From 0e7d0ebd9a6bcfda4cd04eab71903fdfc99cd1be Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Mon, 30 Jan 2017 09:33:09 -0800 Subject: [PATCH] Delete ModuleRegistryHolder Reviewed By: mhorowitz Differential Revision: D4411478 fbshipit-source-id: 03f48f92f0d97bd5e3318f60c8357242fe9792cf --- .../react/cxxbridge/CatalystInstanceImpl.java | 6 +- .../react/cxxbridge/ModuleRegistryHolder.java | 28 --- .../react/cxxbridge/NativeModuleRegistry.java | 26 ++- ReactAndroid/src/main/jni/xreact/Android.mk | 2 +- .../src/main/jni/xreact/jni/Android.mk | 2 +- .../jni/xreact/jni/CatalystInstanceImpl.cpp | 23 +- .../jni/xreact/jni/CatalystInstanceImpl.h | 6 +- .../main/jni/xreact/jni/JavaModuleWrapper.cpp | 159 +++++++++++++ .../main/jni/xreact/jni/JavaModuleWrapper.h | 83 +++++++ .../src/main/jni/xreact/jni/MethodInvoker.h | 19 +- .../jni/xreact/jni/ModuleRegistryHolder.cpp | 216 ------------------ .../jni/xreact/jni/ModuleRegistryHolder.h | 83 ------- .../src/main/jni/xreact/jni/OnLoad.cpp | 2 - 13 files changed, 300 insertions(+), 355 deletions(-) delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/cxxbridge/ModuleRegistryHolder.java create mode 100644 ReactAndroid/src/main/jni/xreact/jni/JavaModuleWrapper.cpp create mode 100644 ReactAndroid/src/main/jni/xreact/jni/JavaModuleWrapper.h delete mode 100644 ReactAndroid/src/main/jni/xreact/jni/ModuleRegistryHolder.cpp delete mode 100644 ReactAndroid/src/main/jni/xreact/jni/ModuleRegistryHolder.h diff --git a/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/CatalystInstanceImpl.java b/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/CatalystInstanceImpl.java index 1bc07aa44eb..9599b17cf8c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/CatalystInstanceImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/CatalystInstanceImpl.java @@ -128,7 +128,8 @@ public class CatalystInstanceImpl implements CatalystInstance { jsExecutor, mReactQueueConfiguration.getJSQueueThread(), mReactQueueConfiguration.getNativeModulesQueueThread(), - mJavaRegistry.getModuleRegistryHolder(this)); + mJavaRegistry.getJavaModules(this), + mJavaRegistry.getCxxModules()); mMainExecutorToken = getMainExecutorToken(); } @@ -179,7 +180,8 @@ public class CatalystInstanceImpl implements CatalystInstance { JavaScriptExecutor jsExecutor, MessageQueueThread jsQueue, MessageQueueThread moduleQueue, - ModuleRegistryHolder registryHolder); + Collection javaModules, + Collection cxxModules); /** * This API is used in situations where the JS bundle is being executed not on diff --git a/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/ModuleRegistryHolder.java b/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/ModuleRegistryHolder.java deleted file mode 100644 index da271d27ad7..00000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/ModuleRegistryHolder.java +++ /dev/null @@ -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 javaModules, - Collection cxxModules); - - public ModuleRegistryHolder(CatalystInstanceImpl catalystInstanceImpl, - Collection javaModules, - Collection cxxModules) { - mHybridData = initHybrid(catalystInstanceImpl, javaModules, cxxModules); - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/NativeModuleRegistry.java b/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/NativeModuleRegistry.java index 2cb0149bab9..c8a02744cf3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/NativeModuleRegistry.java +++ b/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/NativeModuleRegistry.java @@ -10,6 +10,7 @@ package com.facebook.react.cxxbridge; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Map; @@ -36,22 +37,27 @@ public class NativeModuleRegistry { mBatchCompleteListenerModules = batchCompleteListenerModules; } - /* package */ ModuleRegistryHolder getModuleRegistryHolder( - CatalystInstanceImpl catalystInstanceImpl) { + /* package */ Collection getJavaModules( + CatalystInstanceImpl catalystInstanceImpl) { ArrayList javaModules = new ArrayList<>(); + for (Map.Entry, ModuleHolder> entry : mModules.entrySet()) { + Class type = entry.getKey(); + if (!CxxModuleWrapper.class.isAssignableFrom(type)) { + javaModules.add(new JavaModuleWrapper(catalystInstanceImpl, entry.getValue())); + } + } + return javaModules; + } + + /* package */ Collection getCxxModules() { ArrayList cxxModules = new ArrayList<>(); for (Map.Entry, ModuleHolder> entry : mModules.entrySet()) { Class type = entry.getKey(); - ModuleHolder moduleHolder = entry.getValue(); - if (BaseJavaModule.class.isAssignableFrom(type)) { - 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); + if (CxxModuleWrapper.class.isAssignableFrom(type)) { + cxxModules.add((CxxModuleWrapper) entry.getValue().getModule()); } } - return new ModuleRegistryHolder(catalystInstanceImpl, javaModules, cxxModules); + return cxxModules; } /* package */ void notifyCatalystInstanceDestroy() { diff --git a/ReactAndroid/src/main/jni/xreact/Android.mk b/ReactAndroid/src/main/jni/xreact/Android.mk index 4491326e1c0..03f9be8c573 100644 --- a/ReactAndroid/src/main/jni/xreact/Android.mk +++ b/ReactAndroid/src/main/jni/xreact/Android.mk @@ -7,6 +7,7 @@ LOCAL_MODULE := reactnativejnifb LOCAL_SRC_FILES := \ CatalystInstanceImpl.cpp \ CxxModuleWrapper.cpp \ + JavaModuleWrapper.cpp \ JExecutorToken.cpp \ JMessageQueueThread.cpp \ JniJSModulesUnbundle.cpp \ @@ -14,7 +15,6 @@ LOCAL_SRC_FILES := \ JSLoader.cpp \ JSLogging.cpp \ MethodInvoker.cpp \ - ModuleRegistryHolder.cpp \ OnLoad.cpp \ ProxyExecutor.cpp \ diff --git a/ReactAndroid/src/main/jni/xreact/jni/Android.mk b/ReactAndroid/src/main/jni/xreact/jni/Android.mk index 49d282ad8d7..ea700e03ab6 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/Android.mk +++ b/ReactAndroid/src/main/jni/xreact/jni/Android.mk @@ -7,6 +7,7 @@ LOCAL_MODULE := libreactnativejnifb LOCAL_SRC_FILES := \ CatalystInstanceImpl.cpp \ CxxModuleWrapper.cpp \ + JavaModuleWrapper.cpp \ JExecutorToken.cpp \ JMessageQueueThread.cpp \ JSCPerfLogging.cpp \ @@ -14,7 +15,6 @@ LOCAL_SRC_FILES := \ JSLogging.cpp \ JniJSModulesUnbundle.cpp \ MethodInvoker.cpp \ - ModuleRegistryHolder.cpp \ NativeArray.cpp \ NativeCommon.cpp \ NativeMap.cpp \ diff --git a/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.cpp b/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.cpp index bb0ed35b006..f632831b48c 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.cpp +++ b/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.cpp @@ -18,13 +18,13 @@ #include #include #include +#include -#include "JSLoader.h" #include "JavaScriptExecutorHolder.h" #include "JniJSModulesUnbundle.h" -#include "ModuleRegistryHolder.h" -#include "NativeArray.h" #include "JNativeRunnable.h" +#include "JSLoader.h" +#include "NativeArray.h" using namespace facebook::jni; @@ -33,7 +33,6 @@ namespace react { namespace { - class Exception : public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Ljava/lang/Exception;"; @@ -130,10 +129,22 @@ void CatalystInstanceImpl::initializeBridge( JavaScriptExecutorHolder* jseh, jni::alias_ref jsQueue, jni::alias_ref moduleQueue, - ModuleRegistryHolder* mrh) { + jni::alias_ref::javaobject> javaModules, + jni::alias_ref::javaobject> cxxModules) { // TODO mhorowitz: how to assert here? // Assertions.assertCondition(mBridge == null, "initializeBridge should be called once"); + std::vector> modules; + std::weak_ptr winstance(instance_); + for (const auto& jm : *javaModules) { + modules.emplace_back(folly::make_unique(winstance, jm)); + } + for (const auto& cm : *cxxModules) { + modules.emplace_back( + folly::make_unique(winstance, std::move(cthis(cm)->getModule()))); + } + auto moduleRegistry = std::make_shared(std::move(modules)); + // This used to be: // // Java CatalystInstanceImpl -> C++ CatalystInstanceImpl -> Bridge -> Bridge::Callback @@ -154,7 +165,7 @@ void CatalystInstanceImpl::initializeBridge( jseh->getExecutorFactory(), folly::make_unique(jsQueue), folly::make_unique(moduleQueue), - mrh->getModuleRegistry()); + moduleRegistry); } void CatalystInstanceImpl::jniSetSourceURL(const std::string& sourceURL) { diff --git a/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.h b/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.h index 78adfc65676..7d32f0097d5 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.h +++ b/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.h @@ -5,16 +5,17 @@ #include #include +#include "CxxModuleWrapper.h" #include "JExecutorToken.h" #include "JMessageQueueThread.h" #include "JSLoader.h" +#include "JavaModuleWrapper.h" namespace facebook { namespace react { class Instance; class JavaScriptExecutorHolder; -class ModuleRegistryHolder; class NativeArray; struct ReactCallback : public jni::JavaClass { @@ -46,7 +47,8 @@ class CatalystInstanceImpl : public jni::HybridClass { JavaScriptExecutorHolder* jseh, jni::alias_ref jsQueue, jni::alias_ref moduleQueue, - ModuleRegistryHolder* mrh); + jni::alias_ref::javaobject> javaModules, + jni::alias_ref::javaobject> cxxModules); /** * Sets the source URL of the underlying bridge without loading any JS code. diff --git a/ReactAndroid/src/main/jni/xreact/jni/JavaModuleWrapper.cpp b/ReactAndroid/src/main/jni/xreact/jni/JavaModuleWrapper.cpp new file mode 100644 index 00000000000..3f51455107a --- /dev/null +++ b/ReactAndroid/src/main/jni/xreact/jni/JavaModuleWrapper.cpp @@ -0,0 +1,159 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "JavaModuleWrapper.h" + +#include + +#include + +#include +#include +#include +#include +#include + +#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("signature"); + return getFieldValue(signature)->toStdString(); +} + +std::string JMethodDescriptor::getName() const { + static auto name = javaClassStatic()->getField("name"); + return getFieldValue(name)->toStdString(); +} + +std::string JMethodDescriptor::getType() const { + static auto type = javaClassStatic()->getField("type"); + return getFieldValue(type)->toStdString(); +} + +std::string JavaNativeModule::getName() { + static auto getNameMethod = wrapper_->getClass()->getMethod("getName"); + return getNameMethod(wrapper_)->toStdString(); +} + +std::vector JavaNativeModule::getMethods() { + std::vector 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("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("supportsWebWorkers"); + return supportsWebWorkersMethod(wrapper_); +} + +void JavaNativeModule::invoke(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) { + static auto invokeMethod = + wrapper_->getClass()->getMethod("invoke"); + invokeMethod(wrapper_, JExecutorToken::extractJavaPartFromToken(token).get(), static_cast(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, + jni::alias_ref 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("getName"); + return getNameMethod(wrapper_)->toStdString(); +} + +std::vector NewJavaNativeModule::getMethods() { + return methodDescriptors_; +} + +folly::dynamic NewJavaNativeModule::getConstants() { + static auto constantsMethod = + wrapper_->getClass()->getMethod("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("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("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("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 JMethodDescriptor::getMethod() const { + static auto method = javaClassStatic()->getField("method"); + return getFieldValue(method); +} + +} +} diff --git a/ReactAndroid/src/main/jni/xreact/jni/JavaModuleWrapper.h b/ReactAndroid/src/main/jni/xreact/jni/JavaModuleWrapper.h new file mode 100644 index 00000000000..8d7fc50b6f1 --- /dev/null +++ b/ReactAndroid/src/main/jni/xreact/jni/JavaModuleWrapper.h @@ -0,0 +1,83 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include +#include + +#include "MethodInvoker.h" + +namespace facebook { +namespace react { + +class Instance; + +struct JMethodDescriptor : public jni::JavaClass { + static constexpr auto kJavaDescriptor = + "Lcom/facebook/react/cxxbridge/JavaModuleWrapper$MethodDescriptor;"; + + jni::local_ref getMethod() const; + std::string getSignature() const; + std::string getName() const; + std::string getType() const; +}; + +struct JavaModuleWrapper : jni::JavaClass { + static constexpr auto kJavaDescriptor = "Lcom/facebook/react/cxxbridge/JavaModuleWrapper;"; + + jni::local_ref getModule() { + static auto getModule = javaClassStatic()->getMethod("getModule"); + return getModule(self()); + } + + jni::local_ref::javaobject> getMethodDescriptors() { + static auto getMethods = getClass() + ->getMethod::javaobject()>("getMethodDescriptors"); + return getMethods(self()); + } +}; + +class JavaNativeModule : public NativeModule { + public: + JavaNativeModule( + std::weak_ptr instance, + jni::alias_ref wrapper) + : instance_(std::move(instance)), wrapper_(make_global(wrapper)) {} + + std::string getName() override; + folly::dynamic getConstants() override; + std::vector 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_; + jni::global_ref wrapper_; +}; + +// Experimental new implementation that uses direct method invocation +class NewJavaNativeModule : public NativeModule { + public: + NewJavaNativeModule( + std::weak_ptr instance, + jni::alias_ref wrapper); + + std::string getName() override; + std::vector 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_; + jni::global_ref wrapper_; + jni::global_ref module_; + std::vector methods_; + std::vector methodDescriptors_; + + MethodCallResult invokeInner(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params); +}; + +}} diff --git a/ReactAndroid/src/main/jni/xreact/jni/MethodInvoker.h b/ReactAndroid/src/main/jni/xreact/jni/MethodInvoker.h index ef78213d6aa..bf06f2140a5 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/MethodInvoker.h +++ b/ReactAndroid/src/main/jni/xreact/jni/MethodInvoker.h @@ -4,18 +4,29 @@ #include +#include #include #include -#include - -#include "ModuleRegistryHolder.h" - namespace facebook { namespace react { class Instance; +struct JReflectMethod : public jni::JavaClass { + 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 { + static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/BaseJavaModule;"; +}; + class MethodInvoker { public: MethodInvoker(jni::alias_ref method, std::string signature, std::string traceName, bool isSync); diff --git a/ReactAndroid/src/main/jni/xreact/jni/ModuleRegistryHolder.cpp b/ReactAndroid/src/main/jni/xreact/jni/ModuleRegistryHolder.cpp deleted file mode 100644 index 7fb73011a68..00000000000 --- a/ReactAndroid/src/main/jni/xreact/jni/ModuleRegistryHolder.cpp +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#include "ModuleRegistryHolder.h" - -#include - -#include - -#include -#include -#include -#include -#include - -#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 wrapper) - : wrapper_(make_global(wrapper)) {} - - std::string getName() override { - static auto getNameMethod = wrapper_->getClass()->getMethod("getName"); - return getNameMethod(wrapper_)->toStdString(); - } - - std::vector getMethods() override { - static auto getMDMethod = - wrapper_->getClass()->getMethod::javaobject()>( - "getMethodDescriptors"); - - std::vector ret; - auto descs = getMDMethod(wrapper_); - for (const auto& desc : *descs) { - static auto nameField = - JMethodDescriptor::javaClassStatic()->getField("name"); - static auto typeField = - JMethodDescriptor::javaClassStatic()->getField("type"); - - ret.emplace_back( - desc->getFieldValue(nameField)->toStdString(), - desc->getFieldValue(typeField)->toStdString() - ); - } - return ret; - } - - folly::dynamic getConstants() override { - static auto constantsMethod = - wrapper_->getClass()->getMethod("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("supportsWebWorkers"); - return supportsWebWorkersMethod(wrapper_); - } - - void invoke(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) override { - static auto invokeMethod = - wrapper_->getClass()->getMethod("invoke"); - invokeMethod(wrapper_, JExecutorToken::extractJavaPartFromToken(token).get(), static_cast(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 wrapper_; -}; - -class NewJavaNativeModule : public NativeModule { - public: - NewJavaNativeModule(std::weak_ptr instance, jni::alias_ref 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("getName"); - return getNameMethod(wrapper_)->toStdString(); - } - - std::vector getMethods() override { - return methodDescriptors_; - } - - folly::dynamic getConstants() override { - static auto constantsMethod = - wrapper_->getClass()->getMethod("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("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("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("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_; - jni::global_ref wrapper_; - jni::global_ref module_; - std::vector methods_; - std::vector methodDescriptors_; - - MethodCallResult invokeInner(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) { - return methods_[reactMethodId].invoke(instance_, module_.get(), token, params); - } -}; - -} - -jni::local_ref JMethodDescriptor::getMethod() const { - static auto method = javaClassStatic()->getField("method"); - return getFieldValue(method); -} - -std::string JMethodDescriptor::getSignature() const { - static auto signature = javaClassStatic()->getField("signature"); - return getFieldValue(signature)->toStdString(); -} - -std::string JMethodDescriptor::getName() const { - static auto name = javaClassStatic()->getField("name"); - return getFieldValue(name)->toStdString(); -} - -std::string JMethodDescriptor::getType() const { - static auto type = javaClassStatic()->getField("type"); - return getFieldValue(type)->toStdString(); -} - -void ModuleRegistryHolder::registerNatives() { - registerHybrid({ - makeNativeMethod("initHybrid", ModuleRegistryHolder::initHybrid), - }); -} - -ModuleRegistryHolder::ModuleRegistryHolder( - CatalystInstanceImpl* catalystInstanceImpl, - jni::alias_ref::javaobject> javaModules, - jni::alias_ref::javaobject> cxxModules) { - std::vector> modules; - std::weak_ptr winstance(catalystInstanceImpl->getInstance()); - for (const auto& jm : *javaModules) { - modules.emplace_back(folly::make_unique(jm)); - } - for (const auto& cm : *cxxModules) { - modules.emplace_back( - folly::make_unique(winstance, std::move(cthis(cm)->getModule()))); - } - - registry_ = std::make_shared(std::move(modules)); -} - -} -} diff --git a/ReactAndroid/src/main/jni/xreact/jni/ModuleRegistryHolder.h b/ReactAndroid/src/main/jni/xreact/jni/ModuleRegistryHolder.h deleted file mode 100644 index dfaf6df7b68..00000000000 --- a/ReactAndroid/src/main/jni/xreact/jni/ModuleRegistryHolder.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - -#pragma once - -#include -#include - -#include "CxxModuleWrapper.h" - -namespace facebook { -namespace react { - -class Instance; -class CatalystInstanceImpl; - -struct JReflectMethod : public jni::JavaClass { - 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 { - static constexpr auto kJavaDescriptor = - "Lcom/facebook/react/cxxbridge/JavaModuleWrapper$MethodDescriptor;"; - - jni::local_ref getMethod() const; - std::string getSignature() const; - std::string getName() const; - std::string getType() const; -}; - -struct JBaseJavaModule : public jni::JavaClass { - static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/BaseJavaModule;"; -}; - -struct JavaModuleWrapper : jni::JavaClass { - static constexpr auto kJavaDescriptor = "Lcom/facebook/react/cxxbridge/JavaModuleWrapper;"; - - jni::local_ref getModule() { - static auto getModule = javaClassStatic()->getMethod("getModule"); - return getModule(self()); - } - - jni::local_ref::javaobject> getMethodDescriptors() { - static auto getMethods = - getClass()->getMethod::javaobject()>("getMethodDescriptors"); - return getMethods(self()); - } -}; - -class ModuleRegistryHolder : public jni::HybridClass { - public: - static constexpr auto kJavaDescriptor = "Lcom/facebook/react/cxxbridge/ModuleRegistryHolder;"; - - std::shared_ptr getModuleRegistry() { - return registry_; - } - - static jni::local_ref initHybrid( - jni::alias_ref, - CatalystInstanceImpl* catalystInstanceImpl, - jni::alias_ref::javaobject> javaModules, - jni::alias_ref::javaobject> cxxModules) { - return makeCxxInstance(catalystInstanceImpl, javaModules, cxxModules); - } - - static void registerNatives(); - - private: - friend HybridBase; - ModuleRegistryHolder( - CatalystInstanceImpl* catalystInstanceImpl, - jni::alias_ref::javaobject> javaModules, - jni::alias_ref::javaobject> cxxModules); - - std::shared_ptr registry_; -}; - -}} diff --git a/ReactAndroid/src/main/jni/xreact/jni/OnLoad.cpp b/ReactAndroid/src/main/jni/xreact/jni/OnLoad.cpp index a062f1ccfdb..d069edaad31 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/OnLoad.cpp +++ b/ReactAndroid/src/main/jni/xreact/jni/OnLoad.cpp @@ -11,7 +11,6 @@ #include "JavaScriptExecutorHolder.h" #include "JSCPerfLogging.h" #include "JSLoader.h" -#include "ModuleRegistryHolder.h" #include "ProxyExecutor.h" #include "WebWorkers.h" #include "JCallback.h" @@ -160,7 +159,6 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { JSCJavaScriptExecutorHolder::registerNatives(); ProxyJavaScriptExecutorHolder::registerNatives(); CatalystInstanceImpl::registerNatives(); - ModuleRegistryHolder::registerNatives(); CxxModuleWrapper::registerNatives(); JCallbackImpl::registerNatives(); #ifdef WITH_INSPECTOR