1 // Copyright © 2021-present 650 Industries, Inc. (aka Expo) 2 3 #include "JavaScriptFunction.h" 4 #include "types/JNIToJSIConverter.h" 5 #include "types/AnyType.h" 6 7 namespace expo { 8 9 void JavaScriptFunction::registerNatives() { 10 registerHybrid({ 11 makeNativeMethod("invoke", JavaScriptFunction::invoke), 12 }); 13 } 14 15 JavaScriptFunction::JavaScriptFunction( 16 std::weak_ptr<JavaScriptRuntime> runtime, 17 std::shared_ptr<jsi::Function> jsFunction 18 ) : runtimeHolder(std::move(runtime)), jsFunction(std::move(jsFunction)) { 19 runtimeHolder.ensureRuntimeIsValid(); 20 } 21 22 JavaScriptFunction::JavaScriptFunction( 23 WeakRuntimeHolder runtime, 24 std::shared_ptr<jsi::Function> jsFunction 25 ) : runtimeHolder(std::move(runtime)), jsFunction(std::move(jsFunction)) { 26 runtimeHolder.ensureRuntimeIsValid(); 27 } 28 29 std::shared_ptr<jsi::Function> JavaScriptFunction::get() { 30 return jsFunction; 31 } 32 33 jobject JavaScriptFunction::invoke( 34 jni::alias_ref<jni::JArrayClass<jni::JObject>> args, 35 jni::alias_ref<ExpectedType::javaobject> expectedReturnType 36 ) { 37 auto &rt = runtimeHolder.getJSRuntime(); 38 auto moduleRegistry = runtimeHolder.getModuleRegistry(); 39 JNIEnv *env = jni::Environment::current(); 40 41 size_t size = args->size(); 42 std::vector<jsi::Value> convertedArgs; 43 convertedArgs.reserve(size); 44 45 for (size_t i = 0; i < size; i++) { 46 jni::local_ref<jni::JObject> arg = args->getElement(i); 47 convertedArgs.push_back(convert(moduleRegistry, env, rt, std::move(arg))); 48 } 49 50 // TODO(@lukmccall): add better error handling 51 jsi::Value result = jsFunction->call(rt, (const jsi::Value *) convertedArgs.data(), size); 52 auto converter = AnyType(jni::make_local(expectedReturnType)).converter; 53 auto convertedResult = converter->convert(rt, env, moduleRegistry, result); 54 return convertedResult; 55 } 56 57 jni::local_ref<JavaScriptFunction::javaobject> JavaScriptFunction::newInstance( 58 JSIInteropModuleRegistry *jsiInteropModuleRegistry, 59 std::weak_ptr<JavaScriptRuntime> runtime, 60 std::shared_ptr<jsi::Function> jsFunction 61 ) { 62 auto function = JavaScriptFunction::newObjectCxxArgs( 63 std::move(runtime), 64 std::move(jsFunction) 65 ); 66 jsiInteropModuleRegistry->jniDeallocator->addReference(function); 67 return function; 68 } 69 } // namespace expo 70