diff --git a/ReactAndroid/src/main/java/com/facebook/react/CompositeReactPackageTurboModuleManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/CompositeReactPackageTurboModuleManagerDelegate.java new file mode 100644 index 00000000000000..57e0199b98a5a8 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/CompositeReactPackageTurboModuleManagerDelegate.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) Meta Platforms, Inc. and 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; + +import androidx.annotation.NonNull; +import com.facebook.jni.HybridData; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.turbomodule.core.TurboModuleManagerDelegate; +import com.facebook.soloader.SoLoader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class CompositeReactPackageTurboModuleManagerDelegate + extends ReactPackageTurboModuleManagerDelegate { + + private static volatile boolean sIsSoLibraryLoaded; + + protected native HybridData initHybrid(); + + private final List mDelegates; + + private CompositeReactPackageTurboModuleManagerDelegate( + ReactApplicationContext context, + List packages, + List delegates) { + super(context, packages); + mDelegates = delegates; + for (TurboModuleManagerDelegate delegate : delegates) { + addTurboModuleManagerDelegate(delegate); + } + } + + private native void addTurboModuleManagerDelegate(TurboModuleManagerDelegate delegates); + + public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder { + private final List mDelegatesBuilder; + + public Builder(@NonNull List delegatesBuilder) { + mDelegatesBuilder = delegatesBuilder; + } + + protected ReactPackageTurboModuleManagerDelegate build( + ReactApplicationContext context, List packages) { + List delegates = new ArrayList<>(); + for (ReactPackageTurboModuleManagerDelegate.Builder delegatesBuilder : mDelegatesBuilder) { + delegates.add(delegatesBuilder.build(context, Collections.emptyList())); + } + return new CompositeReactPackageTurboModuleManagerDelegate(context, packages, delegates); + } + } + + protected synchronized void maybeLoadOtherSoLibraries() { + // Prevents issues with initializer interruptions. See T38996825 and D13793825 for more context. + if (!sIsSoLibraryLoaded) { + SoLoader.loadLibrary("turbomodulejsijni"); + sIsSoLibraryLoaded = true; + } + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/Android.mk b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/Android.mk index f590cb77f322b4..0ec7e419c9335a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/Android.mk +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/Android.mk @@ -55,7 +55,7 @@ LOCAL_SHARED_LIBRARIES = libfb libfbjni libreact_nativemodule_core libjsi LOCAL_STATIC_LIBRARIES = libcallinvokerholder libreactperfloggerjni # Compile all local c++ files -LOCAL_SRC_FILES := $(LOCAL_PATH)/ReactCommon/TurboModuleManager.cpp $(LOCAL_PATH)/ReactCommon/OnLoad.cpp +LOCAL_SRC_FILES := $(LOCAL_PATH)/ReactCommon/CompositeTurboModuleManagerDelegate.cpp $(LOCAL_PATH)/ReactCommon/OnLoad.cpp $(LOCAL_PATH)/ReactCommon/TurboModuleManager.cpp # Build the files in this directory as a shared library include $(BUILD_SHARED_LIBRARY) diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/BUCK b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/BUCK index 741c05949a77d3..06ed578353b43b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/BUCK @@ -3,11 +3,13 @@ load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "FBJNI_TARGET", "react_nat rn_xplat_cxx_library( name = "jni", srcs = [ + "ReactCommon/CompositeTurboModuleManagerDelegate.cpp", "ReactCommon/OnLoad.cpp", "ReactCommon/TurboModuleManager.cpp", ], header_namespace = "", exported_headers = { + "ReactCommon/CompositeTurboModuleManagerDelegate.h": "ReactCommon/CompositeTurboModuleManagerDelegate.h", "ReactCommon/TurboModuleManager.h": "ReactCommon/TurboModuleManager.h", "ReactCommon/TurboModuleManagerDelegate.h": "ReactCommon/TurboModuleManagerDelegate.h", }, diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/CMakeLists.txt b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/CMakeLists.txt index 02cfe42beeaea6..b5a9449bb9e1b1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/CMakeLists.txt +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/CMakeLists.txt @@ -43,8 +43,9 @@ target_link_libraries(callinvokerholder add_library( turbomodulejsijni SHARED - ReactCommon/TurboModuleManager.cpp + ReactCommon/CompositeTurboModuleManagerDelegate.cpp ReactCommon/OnLoad.cpp + ReactCommon/TurboModuleManager.cpp ) target_include_directories( diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/CompositeTurboModuleManagerDelegate.cpp b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/CompositeTurboModuleManagerDelegate.cpp new file mode 100644 index 00000000000000..a84c819e429435 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/CompositeTurboModuleManagerDelegate.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "CompositeTurboModuleManagerDelegate.h" + +namespace facebook { +namespace react { + +jni::local_ref +CompositeTurboModuleManagerDelegate::initHybrid(jni::alias_ref) { + return makeCxxInstance(); +} + +void CompositeTurboModuleManagerDelegate::registerNatives() { + registerHybrid({ + makeNativeMethod( + "initHybrid", CompositeTurboModuleManagerDelegate::initHybrid), + makeNativeMethod( + "addTurboModuleManagerDelegate", + CompositeTurboModuleManagerDelegate::addTurboModuleManagerDelegate), + }); +} + +std::shared_ptr +CompositeTurboModuleManagerDelegate::getTurboModule( + const std::string moduleName, + const std::shared_ptr jsInvoker) { + for (auto delegate : mDelegates_) { + if (auto turboModule = delegate->getTurboModule(moduleName, jsInvoker)) { + return turboModule; + } + } + return nullptr; +} + +std::shared_ptr +CompositeTurboModuleManagerDelegate::getTurboModule( + const std::string moduleName, + const JavaTurboModule::InitParams ¶ms) { + for (auto delegate : mDelegates_) { + if (auto turboModule = delegate->getTurboModule(moduleName, params)) { + return turboModule; + } + } + return nullptr; +} + +void CompositeTurboModuleManagerDelegate::addTurboModuleManagerDelegate( + jni::alias_ref + turboModuleManagerDelegate) { + mDelegates_.insert(turboModuleManagerDelegate->cthis()); +} + +} // namespace react +} // namespace facebook diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/CompositeTurboModuleManagerDelegate.h b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/CompositeTurboModuleManagerDelegate.h new file mode 100644 index 00000000000000..12b370d66c6c83 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/CompositeTurboModuleManagerDelegate.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) Meta Platforms, Inc. and 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 +#include +#include +#include +#include + +namespace facebook { +namespace react { + +class CompositeTurboModuleManagerDelegate + : public jni::HybridClass< + CompositeTurboModuleManagerDelegate, + TurboModuleManagerDelegate> { + public: + static auto constexpr kJavaDescriptor = + "Lcom/facebook/react/CompositeReactPackageTurboModuleManagerDelegate;"; + + static jni::local_ref initHybrid(jni::alias_ref); + + static void registerNatives(); + + std::shared_ptr getTurboModule( + const std::string moduleName, + const std::shared_ptr jsInvoker) override; + std::shared_ptr getTurboModule( + const std::string moduleName, + const JavaTurboModule::InitParams ¶ms) override; + + private: + friend HybridBase; + using HybridBase::HybridBase; + std::unordered_set mDelegates_; + + void addTurboModuleManagerDelegate( + jni::alias_ref + turboModuleManagerDelegate); +}; + +} // namespace react +} // namespace facebook diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/OnLoad.cpp b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/OnLoad.cpp index ac7f63afe6cdd2..f4c388428f20e2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/OnLoad.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/OnLoad.cpp @@ -9,6 +9,7 @@ #include #include +#include "CompositeTurboModuleManagerDelegate.h" #include "TurboModuleManager.h" void jniEnableCppLogging( @@ -25,6 +26,8 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { // "ComponentDescriptorFactory" is defined in Fabric facebook::react::TurboModuleManager::registerNatives(); + facebook::react::CompositeTurboModuleManagerDelegate::registerNatives(); + facebook::jni::registerNatives( "com/facebook/react/turbomodule/core/TurboModulePerfLogger", {makeNativeMethod("jniEnableCppLogging", jniEnableCppLogging)});