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
registerNatives()9 void JavaScriptFunction::registerNatives() {
10 registerHybrid({
11 makeNativeMethod("invoke", JavaScriptFunction::invoke),
12 });
13 }
14
JavaScriptFunction(std::weak_ptr<JavaScriptRuntime> runtime,std::shared_ptr<jsi::Function> jsFunction)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
JavaScriptFunction(WeakRuntimeHolder runtime,std::shared_ptr<jsi::Function> jsFunction)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
get()29 std::shared_ptr<jsi::Function> JavaScriptFunction::get() {
30 return jsFunction;
31 }
32
invoke(jni::alias_ref<jni::JArrayClass<jni::JObject>> args,jni::alias_ref<ExpectedType::javaobject> expectedReturnType)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
newInstance(JSIInteropModuleRegistry * jsiInteropModuleRegistry,std::weak_ptr<JavaScriptRuntime> runtime,std::shared_ptr<jsi::Function> jsFunction)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