1 // Copyright © 2021-present 650 Industries, Inc. (aka Expo) 2 3 #include "JSIInteropModuleRegistry.h" 4 #include "ExpoModulesHostObject.h" 5 #include "JavaReferencesCache.h" 6 #include "JSReferencesCache.h" 7 8 #include <fbjni/detail/Meta.h> 9 #include <fbjni/fbjni.h> 10 11 #include <memory> 12 13 namespace jni = facebook::jni; 14 namespace jsi = facebook::jsi; 15 16 namespace expo { 17 jni::local_ref<JSIInteropModuleRegistry::jhybriddata> 18 JSIInteropModuleRegistry::initHybrid(jni::alias_ref<jhybridobject> jThis) { 19 return makeCxxInstance(jThis); 20 } 21 22 void JSIInteropModuleRegistry::registerNatives() { 23 registerHybrid({ 24 makeNativeMethod("initHybrid", JSIInteropModuleRegistry::initHybrid), 25 makeNativeMethod("installJSI", JSIInteropModuleRegistry::installJSI), 26 makeNativeMethod("installJSIForTests", 27 JSIInteropModuleRegistry::installJSIForTests), 28 makeNativeMethod("evaluateScript", JSIInteropModuleRegistry::evaluateScript), 29 makeNativeMethod("global", JSIInteropModuleRegistry::global), 30 makeNativeMethod("createObject", JSIInteropModuleRegistry::createObject), 31 makeNativeMethod("drainJSEventLoop", JSIInteropModuleRegistry::drainJSEventLoop), 32 }); 33 } 34 35 JSIInteropModuleRegistry::JSIInteropModuleRegistry(jni::alias_ref<jhybridobject> jThis) 36 : javaPart_(jni::make_global(jThis)) {} 37 38 void JSIInteropModuleRegistry::installJSI( 39 jlong jsRuntimePointer, 40 jni::alias_ref<react::CallInvokerHolder::javaobject> jsInvokerHolder, 41 jni::alias_ref<react::CallInvokerHolder::javaobject> nativeInvokerHolder 42 ) { 43 auto runtime = reinterpret_cast<jsi::Runtime *>(jsRuntimePointer); 44 45 jsRegistry = std::make_unique<JSReferencesCache>(*runtime); 46 47 runtimeHolder = std::make_shared<JavaScriptRuntime>( 48 runtime, 49 jsInvokerHolder->cthis()->getCallInvoker(), 50 nativeInvokerHolder->cthis()->getCallInvoker() 51 ); 52 53 auto expoModules = std::make_shared<ExpoModulesHostObject>(this); 54 auto expoModulesObject = jsi::Object::createFromHostObject(*runtime, expoModules); 55 56 // Define the `global.expo.modules` object. 57 runtimeHolder 58 ->getMainObject() 59 ->setProperty( 60 *runtime, 61 "modules", 62 expoModulesObject 63 ); 64 65 // Also define `global.ExpoModules` for backwards compatibility (used before SDK47, can be removed in SDK48). 66 runtime 67 ->global() 68 .setProperty( 69 *runtime, 70 "ExpoModules", 71 expoModulesObject 72 ); 73 } 74 75 void JSIInteropModuleRegistry::installJSIForTests() { 76 #if !UNIT_TEST 77 throw std::logic_error("The function is only available when UNIT_TEST is defined."); 78 #else 79 runtimeHolder = std::make_shared<JavaScriptRuntime>(); 80 jsi::Runtime &jsiRuntime = runtimeHolder->get(); 81 82 jsRegistry = std::make_unique<JSReferencesCache>(jsiRuntime); 83 84 auto expoModules = std::make_shared<ExpoModulesHostObject>(this); 85 auto expoModulesObject = jsi::Object::createFromHostObject(jsiRuntime, expoModules); 86 87 runtimeHolder 88 ->getMainObject() 89 ->setProperty( 90 jsiRuntime, 91 "modules", 92 std::move(expoModulesObject) 93 ); 94 #endif // !UNIT_TEST 95 } 96 97 jni::local_ref<JavaScriptModuleObject::javaobject> 98 JSIInteropModuleRegistry::callGetJavaScriptModuleObjectMethod(const std::string &moduleName) const { 99 const static auto method = expo::JSIInteropModuleRegistry::javaClassLocal() 100 ->getMethod<jni::local_ref<JavaScriptModuleObject::javaobject>( 101 std::string)>( 102 "getJavaScriptModuleObject" 103 ); 104 105 return method(javaPart_, moduleName); 106 } 107 108 jni::local_ref<jni::JArrayClass<jni::JString>> 109 JSIInteropModuleRegistry::callGetJavaScriptModulesNames() const { 110 const static auto method = expo::JSIInteropModuleRegistry::javaClassLocal() 111 ->getMethod<jni::local_ref<jni::JArrayClass<jni::JString>>()>( 112 "getJavaScriptModulesName" 113 ); 114 return method(javaPart_); 115 } 116 117 jni::local_ref<JavaScriptModuleObject::javaobject> 118 JSIInteropModuleRegistry::getModule(const std::string &moduleName) const { 119 return callGetJavaScriptModuleObjectMethod(moduleName); 120 } 121 122 jni::local_ref<jni::JArrayClass<jni::JString>> JSIInteropModuleRegistry::getModulesName() const { 123 return callGetJavaScriptModulesNames(); 124 } 125 126 jni::local_ref<JavaScriptValue::javaobject> JSIInteropModuleRegistry::evaluateScript( 127 jni::JString script 128 ) { 129 return runtimeHolder->evaluateScript(script.toStdString()); 130 } 131 132 jni::local_ref<JavaScriptObject::javaobject> JSIInteropModuleRegistry::global() { 133 return runtimeHolder->global(); 134 } 135 136 jni::local_ref<JavaScriptObject::javaobject> JSIInteropModuleRegistry::createObject() { 137 return runtimeHolder->createObject(); 138 } 139 140 void JSIInteropModuleRegistry::drainJSEventLoop() { 141 runtimeHolder->drainJSEventLoop(); 142 } 143 } // namespace expo 144