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 }
59 
60 jni::local_ref<JavaScriptModuleObject::javaobject>
61 JSIInteropModuleRegistry::callGetJavaScriptModuleObjectMethod(const std::string &moduleName) const {
62   const static auto method = expo::JSIInteropModuleRegistry::javaClassLocal()
63     ->getMethod<jni::local_ref<JavaScriptModuleObject::javaobject>(
64       std::string)>(
65       "getJavaScriptModuleObject"
66     );
67 
68   return method(javaPart_, moduleName);
69 }
70 
71 jni::local_ref<JavaScriptModuleObject::javaobject>
72 JSIInteropModuleRegistry::getModule(const std::string &moduleName) const {
73   return callGetJavaScriptModuleObjectMethod(moduleName);
74 }
75 
76 jni::local_ref<JavaScriptValue::javaobject> JSIInteropModuleRegistry::evaluateScript(
77   jni::JString script
78 ) {
79   return runtimeHolder->evaluateScript(script.toStdString());
80 }
81 
82 jni::local_ref<JavaScriptObject::javaobject> JSIInteropModuleRegistry::global() {
83   return runtimeHolder->global();
84 }
85 } // namespace expo
86