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 
10 #include <fbjni/fbjni.h>
11 #include <jsi/jsi.h>
12 #include <ReactCommon/CallInvokerHolder.h>
13 #include <ReactCommon/CallInvoker.h>
14 
15 #include <memory>
16 
17 namespace jni = facebook::jni;
18 namespace jsi = facebook::jsi;
19 namespace react = facebook::react;
20 
21 namespace expo {
22 /**
23  * A JNI wrapper to initialize CPP part of modules and access all data from the module registry.
24  */
25 class JSIInteropModuleRegistry : public jni::HybridClass<JSIInteropModuleRegistry> {
26 public:
27   static auto constexpr
28     kJavaDescriptor = "Lexpo/modules/kotlin/jni/JSIInteropModuleRegistry;";
29   static auto constexpr TAG = "JSIInteropModuleRegistry";
30 
31   static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis);
32 
33   static void registerNatives();
34 
35   /**
36    * Initializes the `ExpoModulesHostObject` and adds it to the global object.
37    */
38   void installJSI(
39     jlong jsRuntimePointer,
40     jni::alias_ref<react::CallInvokerHolder::javaobject> jsInvokerHolder,
41     jni::alias_ref<react::CallInvokerHolder::javaobject> nativeInvokerHolder
42   );
43 
44   /**
45    * Initializes the test runtime. Shouldn't be used in the production.
46    */
47   void installJSIForTests();
48 
49   /**
50    * Gets a module for a given name. It will throw an exception if the module doesn't exist.
51    *
52    * @param moduleName
53    * @return An instance of `JavaScriptModuleObject`
54    */
55   jni::local_ref<JavaScriptModuleObject::javaobject> getModule(const std::string &moduleName) const;
56 
57   /**
58    * Exposes a `JavaScriptRuntime::evaluateScript` function to Kotlin
59    */
60   jni::local_ref<JavaScriptValue::javaobject> evaluateScript(jni::JString script);
61 
62   /**
63    * Exposes a `JavaScriptRuntime::global` function to Kotlin
64    */
65   jni::local_ref<JavaScriptObject::javaobject> global();
66 
67   std::shared_ptr<react::CallInvoker> jsInvoker;
68   std::shared_ptr<react::CallInvoker> nativeInvoker;
69 
70 private:
71   friend HybridBase;
72   std::shared_ptr<JavaScriptRuntime> runtimeHolder;
73   jni::global_ref<JSIInteropModuleRegistry::javaobject> javaPart_;
74 
75   explicit JSIInteropModuleRegistry(jni::alias_ref<jhybridobject> jThis);
76 
77   inline jni::local_ref<JavaScriptModuleObject::javaobject>
78   callGetJavaScriptModuleObjectMethod(const std::string &moduleName) const;
79 };
80 } // namespace expo
81