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