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