1 // Copyright © 2021-present 650 Industries, Inc. (aka Expo) 2 3 #pragma once 4 5 #include "JavaScriptRuntime.h" 6 #include "JavaScriptModuleObject.h" 7 #include "JavaScriptValue.h" 8 #include "JavaScriptObject.h" 9 #include "JavaReferencesCache.h" 10 #include "JSReferencesCache.h" 11 #include "JNIDeallocator.h" 12 13 #include <fbjni/fbjni.h> 14 #include <jsi/jsi.h> 15 #include <ReactCommon/CallInvokerHolder.h> 16 #include <ReactCommon/CallInvoker.h> 17 #if REACT_NATIVE_TARGET_VERSION >= 73 18 #include <ReactCommon/NativeMethodCallInvokerHolder.h> 19 #endif 20 21 #include <memory> 22 23 namespace jni = facebook::jni; 24 namespace jsi = facebook::jsi; 25 namespace react = facebook::react; 26 27 namespace expo { 28 29 #if REACT_NATIVE_TARGET_VERSION >= 73 30 using NativeMethodCallInvokerHolderCompatible = react::NativeMethodCallInvokerHolder; 31 #else 32 using NativeMethodCallInvokerHolderCompatible = react::CallInvokerHolder; 33 #endif 34 35 /** 36 * A JNI wrapper to initialize CPP part of modules and access all data from the module registry. 37 */ 38 class JSIInteropModuleRegistry : public jni::HybridClass<JSIInteropModuleRegistry> { 39 public: 40 static auto constexpr 41 kJavaDescriptor = "Lexpo/modules/kotlin/jni/JSIInteropModuleRegistry;"; 42 static auto constexpr TAG = "JSIInteropModuleRegistry"; 43 44 static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis); 45 46 static void registerNatives(); 47 48 /** 49 * Initializes the `ExpoModulesHostObject` and adds it to the global object. 50 */ 51 void installJSI( 52 jlong jsRuntimePointer, 53 jni::alias_ref<JNIDeallocator::javaobject> jniDeallocator, 54 jni::alias_ref<react::CallInvokerHolder::javaobject> jsInvokerHolder, 55 jni::alias_ref<NativeMethodCallInvokerHolderCompatible::javaobject> nativeInvokerHolder 56 ); 57 58 /** 59 * Initializes the test runtime. Shouldn't be used in the production. 60 */ 61 void installJSIForTests( 62 jni::alias_ref<JNIDeallocator::javaobject> jniDeallocator 63 ); 64 65 /** 66 * Gets a module for a given name. It will throw an exception if the module doesn't exist. 67 * 68 * @param moduleName 69 * @return An instance of `JavaScriptModuleObject` 70 */ 71 jni::local_ref<JavaScriptModuleObject::javaobject> getModule(const std::string &moduleName) const; 72 73 bool hasModule(const std::string &moduleName) const; 74 75 /** 76 * Gets names of all available modules. 77 */ 78 jni::local_ref<jni::JArrayClass<jni::JString>> getModulesName() const; 79 80 /** 81 * Exposes a `JavaScriptRuntime::evaluateScript` function to Kotlin 82 */ 83 jni::local_ref<JavaScriptValue::javaobject> evaluateScript(jni::JString script); 84 85 /** 86 * Exposes a `JavaScriptRuntime::global` function to Kotlin 87 */ 88 jni::local_ref<JavaScriptObject::javaobject> global(); 89 90 /** 91 * Exposes a `JavaScriptRuntime::createObject` function to Kotlin 92 */ 93 jni::local_ref<JavaScriptObject::javaobject> createObject(); 94 95 /** 96 * Gets a core module. 97 */ 98 jni::local_ref<JavaScriptModuleObject::javaobject> getCoreModule() const; 99 100 /** 101 * Adds a shared object to the internal registry 102 * @param native part of the shared object 103 * @param js part of the shared object 104 */ 105 void registerSharedObject( 106 jni::local_ref<jobject> native, 107 jni::local_ref<JavaScriptObject::javaobject> js 108 ); 109 110 /** 111 * Exposes a `JavaScriptRuntime::drainJSEventLoop` function to Kotlin 112 */ 113 void drainJSEventLoop(); 114 115 std::shared_ptr<react::CallInvoker> jsInvoker; 116 std::shared_ptr<react::CallInvoker> nativeInvoker; 117 std::shared_ptr<JavaScriptRuntime> runtimeHolder; 118 std::unique_ptr<JSReferencesCache> jsRegistry; 119 jni::global_ref<JNIDeallocator::javaobject> jniDeallocator; 120 private: 121 friend HybridBase; 122 jni::global_ref<JSIInteropModuleRegistry::javaobject> javaPart_; 123 124 explicit JSIInteropModuleRegistry(jni::alias_ref<jhybridobject> jThis); 125 126 inline jni::local_ref<JavaScriptModuleObject::javaobject> 127 callGetJavaScriptModuleObjectMethod(const std::string &moduleName) const; 128 129 inline jni::local_ref<jni::JArrayClass<jni::JString>> callGetJavaScriptModulesNames() const; 130 131 inline jni::local_ref<JavaScriptModuleObject::javaobject> callGetCoreModuleObject() const; 132 133 inline bool callHasModule(const std::string &moduleName) const; 134 }; 135 } // namespace expo 136