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