164f5c95fSŁukasz Kosmaty // Copyright © 2021-present 650 Industries, Inc. (aka Expo)
264f5c95fSŁukasz Kosmaty
364f5c95fSŁukasz Kosmaty #include "JSIInteropModuleRegistry.h"
464f5c95fSŁukasz Kosmaty #include "ExpoModulesHostObject.h"
5b7d1787dSŁukasz Kosmaty #include "JavaReferencesCache.h"
6b7d1787dSŁukasz Kosmaty #include "JSReferencesCache.h"
764f5c95fSŁukasz Kosmaty
864f5c95fSŁukasz Kosmaty #include <fbjni/detail/Meta.h>
964f5c95fSŁukasz Kosmaty #include <fbjni/fbjni.h>
1064f5c95fSŁukasz Kosmaty
1164f5c95fSŁukasz Kosmaty #include <memory>
1264f5c95fSŁukasz Kosmaty
1364f5c95fSŁukasz Kosmaty namespace jni = facebook::jni;
1464f5c95fSŁukasz Kosmaty namespace jsi = facebook::jsi;
1564f5c95fSŁukasz Kosmaty
1664f5c95fSŁukasz Kosmaty namespace expo {
17db6683c6SKudo Chien
18db6683c6SKudo Chien namespace {
19db6683c6SKudo Chien
20db6683c6SKudo Chien #if REACT_NATIVE_TARGET_VERSION >= 73
getNativeMethodCallInvokerHolderCompatible(jni::alias_ref<NativeMethodCallInvokerHolderCompatible::javaobject> holder)21db6683c6SKudo Chien std::shared_ptr<NativeMethodCallInvokerCompatible> getNativeMethodCallInvokerHolderCompatible(
22db6683c6SKudo Chien jni::alias_ref<NativeMethodCallInvokerHolderCompatible::javaobject> holder) {
23db6683c6SKudo Chien return holder->cthis()->getNativeMethodCallInvoker();
24db6683c6SKudo Chien }
25db6683c6SKudo Chien #else
26*12cf8561Slukmccall
27db6683c6SKudo Chien std::shared_ptr<NativeMethodCallInvokerCompatible> getNativeMethodCallInvokerHolderCompatible(
28db6683c6SKudo Chien jni::alias_ref<NativeMethodCallInvokerHolderCompatible::javaobject> holder) {
29db6683c6SKudo Chien return holder->cthis()->getCallInvoker();
30db6683c6SKudo Chien }
31*12cf8561Slukmccall
32db6683c6SKudo Chien #endif
33db6683c6SKudo Chien
34db6683c6SKudo Chien } // namespace
35db6683c6SKudo Chien
3664f5c95fSŁukasz Kosmaty jni::local_ref<JSIInteropModuleRegistry::jhybriddata>
initHybrid(jni::alias_ref<jhybridobject> jThis)3764f5c95fSŁukasz Kosmaty JSIInteropModuleRegistry::initHybrid(jni::alias_ref<jhybridobject> jThis) {
3864f5c95fSŁukasz Kosmaty return makeCxxInstance(jThis);
3964f5c95fSŁukasz Kosmaty }
4064f5c95fSŁukasz Kosmaty
registerNatives()4164f5c95fSŁukasz Kosmaty void JSIInteropModuleRegistry::registerNatives() {
4264f5c95fSŁukasz Kosmaty registerHybrid({
4364f5c95fSŁukasz Kosmaty makeNativeMethod("initHybrid", JSIInteropModuleRegistry::initHybrid),
44a416e6dbSŁukasz Kosmaty makeNativeMethod("installJSI", JSIInteropModuleRegistry::installJSI),
45a416e6dbSŁukasz Kosmaty makeNativeMethod("installJSIForTests",
46a416e6dbSŁukasz Kosmaty JSIInteropModuleRegistry::installJSIForTests),
47a416e6dbSŁukasz Kosmaty makeNativeMethod("evaluateScript", JSIInteropModuleRegistry::evaluateScript),
48a416e6dbSŁukasz Kosmaty makeNativeMethod("global", JSIInteropModuleRegistry::global),
49342f32d0SŁukasz Kosmaty makeNativeMethod("createObject", JSIInteropModuleRegistry::createObject),
50a89667b6SŁukasz Kosmaty makeNativeMethod("drainJSEventLoop", JSIInteropModuleRegistry::drainJSEventLoop),
5164f5c95fSŁukasz Kosmaty });
5264f5c95fSŁukasz Kosmaty }
5364f5c95fSŁukasz Kosmaty
JSIInteropModuleRegistry(jni::alias_ref<jhybridobject> jThis)5464f5c95fSŁukasz Kosmaty JSIInteropModuleRegistry::JSIInteropModuleRegistry(jni::alias_ref<jhybridobject> jThis)
5564f5c95fSŁukasz Kosmaty : javaPart_(jni::make_global(jThis)) {}
5664f5c95fSŁukasz Kosmaty
installJSI(jlong jsRuntimePointer,jni::alias_ref<JNIDeallocator::javaobject> jniDeallocator,jni::alias_ref<react::CallInvokerHolder::javaobject> jsInvokerHolder,jni::alias_ref<NativeMethodCallInvokerHolderCompatible::javaobject> nativeInvokerHolder)5764f5c95fSŁukasz Kosmaty void JSIInteropModuleRegistry::installJSI(
5864f5c95fSŁukasz Kosmaty jlong jsRuntimePointer,
5929e8b6f8SŁukasz Kosmaty jni::alias_ref<JNIDeallocator::javaobject> jniDeallocator,
6064f5c95fSŁukasz Kosmaty jni::alias_ref<react::CallInvokerHolder::javaobject> jsInvokerHolder,
61db6683c6SKudo Chien jni::alias_ref<NativeMethodCallInvokerHolderCompatible::javaobject> nativeInvokerHolder
6264f5c95fSŁukasz Kosmaty ) {
6329e8b6f8SŁukasz Kosmaty this->jniDeallocator = jni::make_global(jniDeallocator);
6429e8b6f8SŁukasz Kosmaty
6564f5c95fSŁukasz Kosmaty auto runtime = reinterpret_cast<jsi::Runtime *>(jsRuntimePointer);
66b7d1787dSŁukasz Kosmaty
67b7d1787dSŁukasz Kosmaty jsRegistry = std::make_unique<JSReferencesCache>(*runtime);
68b7d1787dSŁukasz Kosmaty
696095fdc7SŁukasz Kosmaty runtimeHolder = std::make_shared<JavaScriptRuntime>(
70879827bbSŁukasz Kosmaty this,
716095fdc7SŁukasz Kosmaty runtime,
726095fdc7SŁukasz Kosmaty jsInvokerHolder->cthis()->getCallInvoker(),
73db6683c6SKudo Chien getNativeMethodCallInvokerHolderCompatible(nativeInvokerHolder)
746095fdc7SŁukasz Kosmaty );
7564f5c95fSŁukasz Kosmaty
76*12cf8561Slukmccall runtimeHolder->installMainObject();
77*12cf8561Slukmccall
7864f5c95fSŁukasz Kosmaty auto expoModules = std::make_shared<ExpoModulesHostObject>(this);
7964f5c95fSŁukasz Kosmaty auto expoModulesObject = jsi::Object::createFromHostObject(*runtime, expoModules);
8064f5c95fSŁukasz Kosmaty
81dedc0ffdSŁukasz Kosmaty // Define the `global.expo.modules` object.
82dedc0ffdSŁukasz Kosmaty runtimeHolder
83dedc0ffdSŁukasz Kosmaty ->getMainObject()
84dedc0ffdSŁukasz Kosmaty ->setProperty(
85dedc0ffdSŁukasz Kosmaty *runtime,
86dedc0ffdSŁukasz Kosmaty "modules",
87dedc0ffdSŁukasz Kosmaty expoModulesObject
88dedc0ffdSŁukasz Kosmaty );
89dedc0ffdSŁukasz Kosmaty
90dedc0ffdSŁukasz Kosmaty // Also define `global.ExpoModules` for backwards compatibility (used before SDK47, can be removed in SDK48).
9164f5c95fSŁukasz Kosmaty runtime
9264f5c95fSŁukasz Kosmaty ->global()
9364f5c95fSŁukasz Kosmaty .setProperty(
9464f5c95fSŁukasz Kosmaty *runtime,
9564f5c95fSŁukasz Kosmaty "ExpoModules",
96dedc0ffdSŁukasz Kosmaty expoModulesObject
9764f5c95fSŁukasz Kosmaty );
9864f5c95fSŁukasz Kosmaty }
9964f5c95fSŁukasz Kosmaty
installJSIForTests(jni::alias_ref<JNIDeallocator::javaobject> jniDeallocator)10029e8b6f8SŁukasz Kosmaty void JSIInteropModuleRegistry::installJSIForTests(
10129e8b6f8SŁukasz Kosmaty jni::alias_ref<JNIDeallocator::javaobject> jniDeallocator
10229e8b6f8SŁukasz Kosmaty ) {
10357cd185aSKudo Chien #if !UNIT_TEST
10472841a14SŁukasz Kosmaty throw std::logic_error("The function is only available when UNIT_TEST is defined.");
10557cd185aSKudo Chien #else
10629e8b6f8SŁukasz Kosmaty this->jniDeallocator = jni::make_global(jniDeallocator);
10729e8b6f8SŁukasz Kosmaty
108879827bbSŁukasz Kosmaty runtimeHolder = std::make_shared<JavaScriptRuntime>(this);
109256b5942SŁukasz Kosmaty jsi::Runtime &jsiRuntime = runtimeHolder->get();
1105e5e73a5SŁukasz Kosmaty
111b7d1787dSŁukasz Kosmaty jsRegistry = std::make_unique<JSReferencesCache>(jsiRuntime);
112b7d1787dSŁukasz Kosmaty
113*12cf8561Slukmccall runtimeHolder->installMainObject();
114*12cf8561Slukmccall
1155e5e73a5SŁukasz Kosmaty auto expoModules = std::make_shared<ExpoModulesHostObject>(this);
1165e5e73a5SŁukasz Kosmaty auto expoModulesObject = jsi::Object::createFromHostObject(jsiRuntime, expoModules);
1175e5e73a5SŁukasz Kosmaty
118dedc0ffdSŁukasz Kosmaty runtimeHolder
119dedc0ffdSŁukasz Kosmaty ->getMainObject()
120dedc0ffdSŁukasz Kosmaty ->setProperty(
1215e5e73a5SŁukasz Kosmaty jsiRuntime,
122dedc0ffdSŁukasz Kosmaty "modules",
1235e5e73a5SŁukasz Kosmaty std::move(expoModulesObject)
1245e5e73a5SŁukasz Kosmaty );
12557cd185aSKudo Chien #endif // !UNIT_TEST
126a416e6dbSŁukasz Kosmaty }
127a416e6dbSŁukasz Kosmaty
12864f5c95fSŁukasz Kosmaty jni::local_ref<JavaScriptModuleObject::javaobject>
callGetJavaScriptModuleObjectMethod(const std::string & moduleName) const12964f5c95fSŁukasz Kosmaty JSIInteropModuleRegistry::callGetJavaScriptModuleObjectMethod(const std::string &moduleName) const {
13064f5c95fSŁukasz Kosmaty const static auto method = expo::JSIInteropModuleRegistry::javaClassLocal()
13164f5c95fSŁukasz Kosmaty ->getMethod<jni::local_ref<JavaScriptModuleObject::javaobject>(
13264f5c95fSŁukasz Kosmaty std::string)>(
13364f5c95fSŁukasz Kosmaty "getJavaScriptModuleObject"
13464f5c95fSŁukasz Kosmaty );
13564f5c95fSŁukasz Kosmaty
13664f5c95fSŁukasz Kosmaty return method(javaPart_, moduleName);
13764f5c95fSŁukasz Kosmaty }
13864f5c95fSŁukasz Kosmaty
139b702c83dSŁukasz Kosmaty jni::local_ref<JavaScriptModuleObject::javaobject>
callGetCoreModuleObject() const140b702c83dSŁukasz Kosmaty JSIInteropModuleRegistry::callGetCoreModuleObject() const {
141b702c83dSŁukasz Kosmaty const static auto method = expo::JSIInteropModuleRegistry::javaClassLocal()
142b702c83dSŁukasz Kosmaty ->getMethod<jni::local_ref<JavaScriptModuleObject::javaobject>()>(
143b702c83dSŁukasz Kosmaty "getCoreModuleObject"
144b702c83dSŁukasz Kosmaty );
145b702c83dSŁukasz Kosmaty
146b702c83dSŁukasz Kosmaty return method(javaPart_);
147b702c83dSŁukasz Kosmaty }
148b702c83dSŁukasz Kosmaty
14978b3dbc7SŁukasz Kosmaty jni::local_ref<jni::JArrayClass<jni::JString>>
callGetJavaScriptModulesNames() const15078b3dbc7SŁukasz Kosmaty JSIInteropModuleRegistry::callGetJavaScriptModulesNames() const {
15178b3dbc7SŁukasz Kosmaty const static auto method = expo::JSIInteropModuleRegistry::javaClassLocal()
15278b3dbc7SŁukasz Kosmaty ->getMethod<jni::local_ref<jni::JArrayClass<jni::JString>>()>(
15378b3dbc7SŁukasz Kosmaty "getJavaScriptModulesName"
15478b3dbc7SŁukasz Kosmaty );
15578b3dbc7SŁukasz Kosmaty return method(javaPart_);
15678b3dbc7SŁukasz Kosmaty }
15778b3dbc7SŁukasz Kosmaty
callHasModule(const std::string & moduleName) const158b627df43SŁukasz Kosmaty bool JSIInteropModuleRegistry::callHasModule(const std::string &moduleName) const {
159b627df43SŁukasz Kosmaty const static auto method = expo::JSIInteropModuleRegistry::javaClassLocal()
160b627df43SŁukasz Kosmaty ->getMethod<jboolean(std::string)>(
161b627df43SŁukasz Kosmaty "hasModule"
162b627df43SŁukasz Kosmaty );
163b627df43SŁukasz Kosmaty return (bool) method(javaPart_, moduleName);
164b627df43SŁukasz Kosmaty }
165b627df43SŁukasz Kosmaty
16664f5c95fSŁukasz Kosmaty jni::local_ref<JavaScriptModuleObject::javaobject>
getModule(const std::string & moduleName) const16764f5c95fSŁukasz Kosmaty JSIInteropModuleRegistry::getModule(const std::string &moduleName) const {
16864f5c95fSŁukasz Kosmaty return callGetJavaScriptModuleObjectMethod(moduleName);
16964f5c95fSŁukasz Kosmaty }
170a416e6dbSŁukasz Kosmaty
getCoreModule() const171b702c83dSŁukasz Kosmaty jni::local_ref<JavaScriptModuleObject::javaobject> JSIInteropModuleRegistry::getCoreModule() const {
172b702c83dSŁukasz Kosmaty return callGetCoreModuleObject();
173b702c83dSŁukasz Kosmaty }
174b702c83dSŁukasz Kosmaty
hasModule(const std::string & moduleName) const175b627df43SŁukasz Kosmaty bool JSIInteropModuleRegistry::hasModule(const std::string &moduleName) const {
176b627df43SŁukasz Kosmaty return callHasModule(moduleName);
177b627df43SŁukasz Kosmaty }
178b627df43SŁukasz Kosmaty
getModulesName() const17978b3dbc7SŁukasz Kosmaty jni::local_ref<jni::JArrayClass<jni::JString>> JSIInteropModuleRegistry::getModulesName() const {
18078b3dbc7SŁukasz Kosmaty return callGetJavaScriptModulesNames();
18178b3dbc7SŁukasz Kosmaty }
18278b3dbc7SŁukasz Kosmaty
evaluateScript(jni::JString script)183a416e6dbSŁukasz Kosmaty jni::local_ref<JavaScriptValue::javaobject> JSIInteropModuleRegistry::evaluateScript(
184a416e6dbSŁukasz Kosmaty jni::JString script
185a416e6dbSŁukasz Kosmaty ) {
186a416e6dbSŁukasz Kosmaty return runtimeHolder->evaluateScript(script.toStdString());
187a416e6dbSŁukasz Kosmaty }
188a416e6dbSŁukasz Kosmaty
global()189a416e6dbSŁukasz Kosmaty jni::local_ref<JavaScriptObject::javaobject> JSIInteropModuleRegistry::global() {
190a416e6dbSŁukasz Kosmaty return runtimeHolder->global();
191a416e6dbSŁukasz Kosmaty }
192342f32d0SŁukasz Kosmaty
createObject()193342f32d0SŁukasz Kosmaty jni::local_ref<JavaScriptObject::javaobject> JSIInteropModuleRegistry::createObject() {
194342f32d0SŁukasz Kosmaty return runtimeHolder->createObject();
195342f32d0SŁukasz Kosmaty }
196a89667b6SŁukasz Kosmaty
drainJSEventLoop()197a89667b6SŁukasz Kosmaty void JSIInteropModuleRegistry::drainJSEventLoop() {
198a89667b6SŁukasz Kosmaty runtimeHolder->drainJSEventLoop();
199ecb7f347SŁukasz Kosmaty }
200ecb7f347SŁukasz Kosmaty
registerSharedObject(jni::local_ref<jobject> native,jni::local_ref<JavaScriptObject::javaobject> js)201ecb7f347SŁukasz Kosmaty void JSIInteropModuleRegistry::registerSharedObject(
202ecb7f347SŁukasz Kosmaty jni::local_ref<jobject> native,
203ecb7f347SŁukasz Kosmaty jni::local_ref<JavaScriptObject::javaobject> js
204ecb7f347SŁukasz Kosmaty ) {
205ecb7f347SŁukasz Kosmaty const static auto method = expo::JSIInteropModuleRegistry::javaClassLocal()
206ecb7f347SŁukasz Kosmaty ->getMethod<void(jni::local_ref<jobject>, jni::local_ref<JavaScriptObject::javaobject>)>(
207ecb7f347SŁukasz Kosmaty "registerSharedObject"
208ecb7f347SŁukasz Kosmaty );
209ecb7f347SŁukasz Kosmaty method(javaPart_, std::move(native), std::move(js));
210a89667b6SŁukasz Kosmaty }
21164f5c95fSŁukasz Kosmaty } // namespace expo
212