164f5c95fSŁukasz Kosmaty // Copyright © 2021-present 650 Industries, Inc. (aka Expo)
264f5c95fSŁukasz Kosmaty 
364f5c95fSŁukasz Kosmaty #pragma once
464f5c95fSŁukasz Kosmaty 
564f5c95fSŁukasz Kosmaty #include "JavaScriptRuntime.h"
664f5c95fSŁukasz Kosmaty #include "JavaScriptModuleObject.h"
7a416e6dbSŁukasz Kosmaty #include "JavaScriptValue.h"
8a416e6dbSŁukasz Kosmaty #include "JavaScriptObject.h"
9b7d1787dSŁukasz Kosmaty #include "JavaReferencesCache.h"
10b7d1787dSŁukasz Kosmaty #include "JSReferencesCache.h"
1129e8b6f8SŁukasz Kosmaty #include "JNIDeallocator.h"
1264f5c95fSŁukasz Kosmaty 
1364f5c95fSŁukasz Kosmaty #include <fbjni/fbjni.h>
1464f5c95fSŁukasz Kosmaty #include <jsi/jsi.h>
1564f5c95fSŁukasz Kosmaty #include <ReactCommon/CallInvokerHolder.h>
1664f5c95fSŁukasz Kosmaty #include <ReactCommon/CallInvoker.h>
17*db6683c6SKudo Chien #if REACT_NATIVE_TARGET_VERSION >= 73
18*db6683c6SKudo Chien #include <ReactCommon/NativeMethodCallInvokerHolder.h>
19*db6683c6SKudo Chien #endif
2064f5c95fSŁukasz Kosmaty 
2164f5c95fSŁukasz Kosmaty #include <memory>
2264f5c95fSŁukasz Kosmaty 
2364f5c95fSŁukasz Kosmaty namespace jni = facebook::jni;
2464f5c95fSŁukasz Kosmaty namespace jsi = facebook::jsi;
2564f5c95fSŁukasz Kosmaty namespace react = facebook::react;
2664f5c95fSŁukasz Kosmaty 
2764f5c95fSŁukasz Kosmaty namespace expo {
28*db6683c6SKudo Chien 
29*db6683c6SKudo Chien #if REACT_NATIVE_TARGET_VERSION >= 73
30*db6683c6SKudo Chien using NativeMethodCallInvokerHolderCompatible = react::NativeMethodCallInvokerHolder;
31*db6683c6SKudo Chien #else
32*db6683c6SKudo Chien using NativeMethodCallInvokerHolderCompatible = react::CallInvokerHolder;
33*db6683c6SKudo Chien #endif
34*db6683c6SKudo Chien 
3564f5c95fSŁukasz Kosmaty /**
3664f5c95fSŁukasz Kosmaty  * A JNI wrapper to initialize CPP part of modules and access all data from the module registry.
3764f5c95fSŁukasz Kosmaty  */
3864f5c95fSŁukasz Kosmaty class JSIInteropModuleRegistry : public jni::HybridClass<JSIInteropModuleRegistry> {
3964f5c95fSŁukasz Kosmaty public:
4064f5c95fSŁukasz Kosmaty   static auto constexpr
4164f5c95fSŁukasz Kosmaty     kJavaDescriptor = "Lexpo/modules/kotlin/jni/JSIInteropModuleRegistry;";
4264f5c95fSŁukasz Kosmaty   static auto constexpr TAG = "JSIInteropModuleRegistry";
4364f5c95fSŁukasz Kosmaty 
4464f5c95fSŁukasz Kosmaty   static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis);
4564f5c95fSŁukasz Kosmaty 
4664f5c95fSŁukasz Kosmaty   static void registerNatives();
4764f5c95fSŁukasz Kosmaty 
4864f5c95fSŁukasz Kosmaty   /**
4964f5c95fSŁukasz Kosmaty    * Initializes the `ExpoModulesHostObject` and adds it to the global object.
5064f5c95fSŁukasz Kosmaty    */
5164f5c95fSŁukasz Kosmaty   void installJSI(
5264f5c95fSŁukasz Kosmaty     jlong jsRuntimePointer,
5329e8b6f8SŁukasz Kosmaty     jni::alias_ref<JNIDeallocator::javaobject> jniDeallocator,
5464f5c95fSŁukasz Kosmaty     jni::alias_ref<react::CallInvokerHolder::javaobject> jsInvokerHolder,
55*db6683c6SKudo Chien     jni::alias_ref<NativeMethodCallInvokerHolderCompatible::javaobject> nativeInvokerHolder
5664f5c95fSŁukasz Kosmaty   );
5764f5c95fSŁukasz Kosmaty 
5864f5c95fSŁukasz Kosmaty   /**
59a416e6dbSŁukasz Kosmaty    * Initializes the test runtime. Shouldn't be used in the production.
60a416e6dbSŁukasz Kosmaty    */
6129e8b6f8SŁukasz Kosmaty   void installJSIForTests(
6229e8b6f8SŁukasz Kosmaty     jni::alias_ref<JNIDeallocator::javaobject> jniDeallocator
6329e8b6f8SŁukasz Kosmaty   );
64a416e6dbSŁukasz Kosmaty 
65a416e6dbSŁukasz Kosmaty   /**
6664f5c95fSŁukasz Kosmaty    * Gets a module for a given name. It will throw an exception if the module doesn't exist.
6764f5c95fSŁukasz Kosmaty    *
6864f5c95fSŁukasz Kosmaty    * @param moduleName
6964f5c95fSŁukasz Kosmaty    * @return An instance of `JavaScriptModuleObject`
7064f5c95fSŁukasz Kosmaty    */
7164f5c95fSŁukasz Kosmaty   jni::local_ref<JavaScriptModuleObject::javaobject> getModule(const std::string &moduleName) const;
7264f5c95fSŁukasz Kosmaty 
73b627df43SŁukasz Kosmaty   bool hasModule(const std::string &moduleName) const;
74b627df43SŁukasz Kosmaty 
75a416e6dbSŁukasz Kosmaty   /**
7678b3dbc7SŁukasz Kosmaty    * Gets names of all available modules.
7778b3dbc7SŁukasz Kosmaty    */
7878b3dbc7SŁukasz Kosmaty   jni::local_ref<jni::JArrayClass<jni::JString>> getModulesName() const;
7978b3dbc7SŁukasz Kosmaty 
8078b3dbc7SŁukasz Kosmaty   /**
81a416e6dbSŁukasz Kosmaty    * Exposes a `JavaScriptRuntime::evaluateScript` function to Kotlin
82a416e6dbSŁukasz Kosmaty    */
83a416e6dbSŁukasz Kosmaty   jni::local_ref<JavaScriptValue::javaobject> evaluateScript(jni::JString script);
84a416e6dbSŁukasz Kosmaty 
85a416e6dbSŁukasz Kosmaty   /**
86a416e6dbSŁukasz Kosmaty    * Exposes a `JavaScriptRuntime::global` function to Kotlin
87a416e6dbSŁukasz Kosmaty    */
88a416e6dbSŁukasz Kosmaty   jni::local_ref<JavaScriptObject::javaobject> global();
89a416e6dbSŁukasz Kosmaty 
90342f32d0SŁukasz Kosmaty   /**
91342f32d0SŁukasz Kosmaty    * Exposes a `JavaScriptRuntime::createObject` function to Kotlin
92342f32d0SŁukasz Kosmaty    */
93342f32d0SŁukasz Kosmaty   jni::local_ref<JavaScriptObject::javaobject> createObject();
94342f32d0SŁukasz Kosmaty 
95a89667b6SŁukasz Kosmaty   /**
96b702c83dSŁukasz Kosmaty   * Gets a core module.
97b702c83dSŁukasz Kosmaty   */
98b702c83dSŁukasz Kosmaty   jni::local_ref<JavaScriptModuleObject::javaobject> getCoreModule() const;
99b702c83dSŁukasz Kosmaty 
100b702c83dSŁukasz Kosmaty   /**
101ecb7f347SŁukasz Kosmaty    * Adds a shared object to the internal registry
102ecb7f347SŁukasz Kosmaty    * @param native part of the shared object
103ecb7f347SŁukasz Kosmaty    * @param js part of the shared object
104ecb7f347SŁukasz Kosmaty    */
105ecb7f347SŁukasz Kosmaty   void registerSharedObject(
106ecb7f347SŁukasz Kosmaty     jni::local_ref<jobject> native,
107ecb7f347SŁukasz Kosmaty     jni::local_ref<JavaScriptObject::javaobject> js
108ecb7f347SŁukasz Kosmaty   );
109ecb7f347SŁukasz Kosmaty 
110ecb7f347SŁukasz Kosmaty   /**
111a89667b6SŁukasz Kosmaty    * Exposes a `JavaScriptRuntime::drainJSEventLoop` function to Kotlin
112a89667b6SŁukasz Kosmaty    */
113a89667b6SŁukasz Kosmaty   void drainJSEventLoop();
114a89667b6SŁukasz Kosmaty 
11564f5c95fSŁukasz Kosmaty   std::shared_ptr<react::CallInvoker> jsInvoker;
11664f5c95fSŁukasz Kosmaty   std::shared_ptr<react::CallInvoker> nativeInvoker;
1176095fdc7SŁukasz Kosmaty   std::shared_ptr<JavaScriptRuntime> runtimeHolder;
118b7d1787dSŁukasz Kosmaty   std::unique_ptr<JSReferencesCache> jsRegistry;
11929e8b6f8SŁukasz Kosmaty   jni::global_ref<JNIDeallocator::javaobject> jniDeallocator;
12064f5c95fSŁukasz Kosmaty private:
12164f5c95fSŁukasz Kosmaty   friend HybridBase;
12264f5c95fSŁukasz Kosmaty   jni::global_ref<JSIInteropModuleRegistry::javaobject> javaPart_;
12364f5c95fSŁukasz Kosmaty 
12464f5c95fSŁukasz Kosmaty   explicit JSIInteropModuleRegistry(jni::alias_ref<jhybridobject> jThis);
12564f5c95fSŁukasz Kosmaty 
12664f5c95fSŁukasz Kosmaty   inline jni::local_ref<JavaScriptModuleObject::javaobject>
12764f5c95fSŁukasz Kosmaty   callGetJavaScriptModuleObjectMethod(const std::string &moduleName) const;
12878b3dbc7SŁukasz Kosmaty 
12978b3dbc7SŁukasz Kosmaty   inline jni::local_ref<jni::JArrayClass<jni::JString>> callGetJavaScriptModulesNames() const;
130b627df43SŁukasz Kosmaty 
131b702c83dSŁukasz Kosmaty   inline jni::local_ref<JavaScriptModuleObject::javaobject> callGetCoreModuleObject() const;
132b702c83dSŁukasz Kosmaty 
133b627df43SŁukasz Kosmaty   inline bool callHasModule(const std::string &moduleName) const;
13464f5c95fSŁukasz Kosmaty };
13564f5c95fSŁukasz Kosmaty } // namespace expo
136