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                    makeNativeMethod("drainJSEventLoop", JSIInteropModuleRegistry::drainJSEventLoop),
30                  });
31 }
32 
33 JSIInteropModuleRegistry::JSIInteropModuleRegistry(jni::alias_ref<jhybridobject> jThis)
34   : javaPart_(jni::make_global(jThis)) {}
35 
36 void JSIInteropModuleRegistry::installJSI(
37   jlong jsRuntimePointer,
38   jni::alias_ref<react::CallInvokerHolder::javaobject> jsInvokerHolder,
39   jni::alias_ref<react::CallInvokerHolder::javaobject> nativeInvokerHolder
40 ) {
41   auto runtime = reinterpret_cast<jsi::Runtime *>(jsRuntimePointer);
42   runtimeHolder = std::make_shared<JavaScriptRuntime>(
43     runtime,
44     jsInvokerHolder->cthis()->getCallInvoker(),
45     nativeInvokerHolder->cthis()->getCallInvoker()
46   );
47 
48   auto expoModules = std::make_shared<ExpoModulesHostObject>(this);
49   auto expoModulesObject = jsi::Object::createFromHostObject(*runtime, expoModules);
50 
51   runtime
52     ->global()
53     .setProperty(
54       *runtime,
55       "ExpoModules",
56       std::move(expoModulesObject)
57     );
58 }
59 
60 void JSIInteropModuleRegistry::installJSIForTests() {
61   runtimeHolder = std::make_shared<JavaScriptRuntime>();
62   jsi::Runtime &jsiRuntime = *runtimeHolder->get();
63 
64   auto expoModules = std::make_shared<ExpoModulesHostObject>(this);
65   auto expoModulesObject = jsi::Object::createFromHostObject(jsiRuntime, expoModules);
66 
67   jsiRuntime
68     .global()
69     .setProperty(
70       jsiRuntime,
71       "ExpoModules",
72       std::move(expoModulesObject)
73     );
74 }
75 
76 jni::local_ref<JavaScriptModuleObject::javaobject>
77 JSIInteropModuleRegistry::callGetJavaScriptModuleObjectMethod(const std::string &moduleName) const {
78   const static auto method = expo::JSIInteropModuleRegistry::javaClassLocal()
79     ->getMethod<jni::local_ref<JavaScriptModuleObject::javaobject>(
80       std::string)>(
81       "getJavaScriptModuleObject"
82     );
83 
84   return method(javaPart_, moduleName);
85 }
86 
87 jni::local_ref<jni::JArrayClass<jni::JString>>
88 JSIInteropModuleRegistry::callGetJavaScriptModulesNames() const {
89   const static auto method = expo::JSIInteropModuleRegistry::javaClassLocal()
90     ->getMethod<jni::local_ref<jni::JArrayClass<jni::JString>>()>(
91       "getJavaScriptModulesName"
92     );
93   return method(javaPart_);
94 }
95 
96 jni::local_ref<JavaScriptModuleObject::javaobject>
97 JSIInteropModuleRegistry::getModule(const std::string &moduleName) const {
98   return callGetJavaScriptModuleObjectMethod(moduleName);
99 }
100 
101 jni::local_ref<jni::JArrayClass<jni::JString>> JSIInteropModuleRegistry::getModulesName() const {
102   return callGetJavaScriptModulesNames();
103 }
104 
105 jni::local_ref<JavaScriptValue::javaobject> JSIInteropModuleRegistry::evaluateScript(
106   jni::JString script
107 ) {
108   return runtimeHolder->evaluateScript(script.toStdString());
109 }
110 
111 jni::local_ref<JavaScriptObject::javaobject> JSIInteropModuleRegistry::global() {
112   return runtimeHolder->global();
113 }
114 
115 jni::local_ref<JavaScriptObject::javaobject> JSIInteropModuleRegistry::createObject() {
116   return runtimeHolder->createObject();
117 }
118 
119 void JSIInteropModuleRegistry::drainJSEventLoop() {
120   runtimeHolder->drainJSEventLoop();
121 }
122 } // namespace expo
123