1 // Copyright © 2021-present 650 Industries, Inc. (aka Expo)
2 
3 #include "JSIInteropModuleRegistry.h"
4 #include "ExpoModulesHostObject.h"
5 
6 #include <fbjni/detail/Meta.h>
7 #include <fbjni/fbjni.h>
8 
9 #include <memory>
10 
11 namespace jni = facebook::jni;
12 namespace jsi = facebook::jsi;
13 
14 namespace expo {
15 jni::local_ref<JSIInteropModuleRegistry::jhybriddata>
16 JSIInteropModuleRegistry::initHybrid(jni::alias_ref<jhybridobject> jThis) {
17   return makeCxxInstance(jThis);
18 }
19 
20 void JSIInteropModuleRegistry::registerNatives() {
21   registerHybrid({
22                    makeNativeMethod("initHybrid", JSIInteropModuleRegistry::initHybrid),
23                    makeNativeMethod("installJSI", JSIInteropModuleRegistry::installJSI),
24                    makeNativeMethod("installJSIForTests",
25                                     JSIInteropModuleRegistry::installJSIForTests),
26                    makeNativeMethod("evaluateScript", JSIInteropModuleRegistry::evaluateScript),
27                    makeNativeMethod("global", JSIInteropModuleRegistry::global),
28                    makeNativeMethod("createObject", JSIInteropModuleRegistry::createObject),
29                  });
30 }
31 
32 JSIInteropModuleRegistry::JSIInteropModuleRegistry(jni::alias_ref<jhybridobject> jThis)
33   : javaPart_(jni::make_global(jThis)) {}
34 
35 void JSIInteropModuleRegistry::installJSI(
36   jlong jsRuntimePointer,
37   jni::alias_ref<react::CallInvokerHolder::javaobject> jsInvokerHolder,
38   jni::alias_ref<react::CallInvokerHolder::javaobject> nativeInvokerHolder
39 ) {
40   auto runtime = reinterpret_cast<jsi::Runtime *>(jsRuntimePointer);
41   runtimeHolder = std::make_shared<JavaScriptRuntime>(
42     runtime,
43     jsInvokerHolder->cthis()->getCallInvoker(),
44     nativeInvokerHolder->cthis()->getCallInvoker()
45   );
46 
47   auto expoModules = std::make_shared<ExpoModulesHostObject>(this);
48   auto expoModulesObject = jsi::Object::createFromHostObject(*runtime, expoModules);
49 
50   runtime
51     ->global()
52     .setProperty(
53       *runtime,
54       "ExpoModules",
55       std::move(expoModulesObject)
56     );
57 }
58 
59 void JSIInteropModuleRegistry::installJSIForTests() {
60   runtimeHolder = std::make_shared<JavaScriptRuntime>();
61   jsi::Runtime &jsiRuntime = *runtimeHolder->get();
62 
63   auto expoModules = std::make_shared<ExpoModulesHostObject>(this);
64   auto expoModulesObject = jsi::Object::createFromHostObject(jsiRuntime, expoModules);
65 
66   jsiRuntime
67     .global()
68     .setProperty(
69       jsiRuntime,
70       "ExpoModules",
71       std::move(expoModulesObject)
72     );
73 }
74 
75 jni::local_ref<JavaScriptModuleObject::javaobject>
76 JSIInteropModuleRegistry::callGetJavaScriptModuleObjectMethod(const std::string &moduleName) const {
77   const static auto method = expo::JSIInteropModuleRegistry::javaClassLocal()
78     ->getMethod<jni::local_ref<JavaScriptModuleObject::javaobject>(
79       std::string)>(
80       "getJavaScriptModuleObject"
81     );
82 
83   return method(javaPart_, moduleName);
84 }
85 
86 jni::local_ref<jni::JArrayClass<jni::JString>>
87 JSIInteropModuleRegistry::callGetJavaScriptModulesNames() const {
88   const static auto method = expo::JSIInteropModuleRegistry::javaClassLocal()
89     ->getMethod<jni::local_ref<jni::JArrayClass<jni::JString>>()>(
90       "getJavaScriptModulesName"
91     );
92   return method(javaPart_);
93 }
94 
95 jni::local_ref<JavaScriptModuleObject::javaobject>
96 JSIInteropModuleRegistry::getModule(const std::string &moduleName) const {
97   return callGetJavaScriptModuleObjectMethod(moduleName);
98 }
99 
100 jni::local_ref<jni::JArrayClass<jni::JString>> JSIInteropModuleRegistry::getModulesName() const {
101   return callGetJavaScriptModulesNames();
102 }
103 
104 jni::local_ref<JavaScriptValue::javaobject> JSIInteropModuleRegistry::evaluateScript(
105   jni::JString script
106 ) {
107   return runtimeHolder->evaluateScript(script.toStdString());
108 }
109 
110 jni::local_ref<JavaScriptObject::javaobject> JSIInteropModuleRegistry::global() {
111   return runtimeHolder->global();
112 }
113 
114 jni::local_ref<JavaScriptObject::javaobject> JSIInteropModuleRegistry::createObject() {
115   return runtimeHolder->createObject();
116 }
117 } // namespace expo
118