1b7d1787dSŁukasz Kosmaty // Copyright © 2021-present 650 Industries, Inc. (aka Expo)
2b7d1787dSŁukasz Kosmaty
3b7d1787dSŁukasz Kosmaty #include "JavaReferencesCache.h"
4b7d1787dSŁukasz Kosmaty
575c7ead1SKudo Chien #include <vector>
675c7ead1SKudo Chien
7b7d1787dSŁukasz Kosmaty namespace expo {
instance()8b7d1787dSŁukasz Kosmaty std::shared_ptr<JavaReferencesCache> JavaReferencesCache::instance() {
9b7d1787dSŁukasz Kosmaty static std::shared_ptr<JavaReferencesCache> singleton{new JavaReferencesCache};
10b7d1787dSŁukasz Kosmaty return singleton;
11b7d1787dSŁukasz Kosmaty }
12b7d1787dSŁukasz Kosmaty
loadJClasses(JNIEnv * env)13b7d1787dSŁukasz Kosmaty void JavaReferencesCache::loadJClasses(JNIEnv *env) {
14b7d1787dSŁukasz Kosmaty loadJClass(env, "java/lang/Double", {
15b7d1787dSŁukasz Kosmaty {"<init>", "(D)V"}
16b7d1787dSŁukasz Kosmaty });
17b7d1787dSŁukasz Kosmaty
18b7d1787dSŁukasz Kosmaty loadJClass(env, "java/lang/Boolean", {
19b7d1787dSŁukasz Kosmaty {"<init>", "(Z)V"}
20b7d1787dSŁukasz Kosmaty });
21b7d1787dSŁukasz Kosmaty
226f5b8a20SŁukasz Kosmaty loadJClass(env, "java/lang/Integer", {
236f5b8a20SŁukasz Kosmaty {"<init>", "(I)V"}
246f5b8a20SŁukasz Kosmaty });
256f5b8a20SŁukasz Kosmaty
26e95df2f4SŁukasz Kosmaty loadJClass(env, "java/lang/Long", {
27e95df2f4SŁukasz Kosmaty {"<init>", "(J)V"}
28e95df2f4SŁukasz Kosmaty });
29e95df2f4SŁukasz Kosmaty
306f5b8a20SŁukasz Kosmaty loadJClass(env, "java/lang/Float", {
316f5b8a20SŁukasz Kosmaty {"<init>", "(F)V"}
326f5b8a20SŁukasz Kosmaty });
336f5b8a20SŁukasz Kosmaty
34b7d1787dSŁukasz Kosmaty loadJClass(env, "com/facebook/react/bridge/PromiseImpl", {
35b7d1787dSŁukasz Kosmaty {"<init>", "(Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V"}
36b7d1787dSŁukasz Kosmaty });
37b7d1787dSŁukasz Kosmaty
385e538c67SŁukasz Kosmaty loadJClass(env, "expo/modules/kotlin/jni/PromiseImpl", {
395e538c67SŁukasz Kosmaty {"<init>", "(Lexpo/modules/kotlin/jni/JavaCallback;Lexpo/modules/kotlin/jni/JavaCallback;)V"}
405e538c67SŁukasz Kosmaty });
415e538c67SŁukasz Kosmaty
42b7d1787dSŁukasz Kosmaty loadJClass(env, "java/lang/Object", {});
438d89495bSŁukasz Kosmaty loadJClass(env, "java/lang/String", {});
448d89495bSŁukasz Kosmaty loadJClass(env, "expo/modules/kotlin/jni/JavaScriptObject", {});
458d89495bSŁukasz Kosmaty loadJClass(env, "expo/modules/kotlin/jni/JavaScriptValue", {});
468d89495bSŁukasz Kosmaty loadJClass(env, "expo/modules/kotlin/jni/JavaScriptTypedArray", {});
478d89495bSŁukasz Kosmaty loadJClass(env, "com/facebook/react/bridge/ReadableNativeArray", {});
488d89495bSŁukasz Kosmaty loadJClass(env, "com/facebook/react/bridge/ReadableNativeMap", {});
495e538c67SŁukasz Kosmaty loadJClass(env, "com/facebook/react/bridge/WritableNativeArray", {});
505e538c67SŁukasz Kosmaty loadJClass(env, "com/facebook/react/bridge/WritableNativeMap", {});
51*ecb7f347SŁukasz Kosmaty
52*ecb7f347SŁukasz Kosmaty loadJClass(env, "expo/modules/kotlin/sharedobjects/SharedObject", {});
53b7d1787dSŁukasz Kosmaty }
54b7d1787dSŁukasz Kosmaty
loadJClass(JNIEnv * env,const std::string & name,const std::vector<std::pair<std::string,std::string>> & methodsNames)55b7d1787dSŁukasz Kosmaty void JavaReferencesCache::loadJClass(
56b7d1787dSŁukasz Kosmaty JNIEnv *env,
57b7d1787dSŁukasz Kosmaty const std::string &name,
58b7d1787dSŁukasz Kosmaty const std::vector<std::pair<std::string, std::string>> &methodsNames
59b7d1787dSŁukasz Kosmaty ) {
60b7d1787dSŁukasz Kosmaty // Note this clazz variable points to a leaked global reference.
61b7d1787dSŁukasz Kosmaty // This is appropriate for classes that are never unloaded which is any class in an Android app.
62b7d1787dSŁukasz Kosmaty auto clazz = (jclass) env->NewGlobalRef(env->FindClass(name.c_str()));
63b7d1787dSŁukasz Kosmaty
64b7d1787dSŁukasz Kosmaty MethodHashMap methods;
65b7d1787dSŁukasz Kosmaty methods.reserve(methodsNames.size());
66b7d1787dSŁukasz Kosmaty
67b7d1787dSŁukasz Kosmaty for (auto &method: methodsNames) {
68b7d1787dSŁukasz Kosmaty methods.insert(
69b7d1787dSŁukasz Kosmaty {method, env->GetMethodID(clazz, method.first.c_str(), method.second.c_str())}
70b7d1787dSŁukasz Kosmaty );
71b7d1787dSŁukasz Kosmaty }
72b7d1787dSŁukasz Kosmaty
73b7d1787dSŁukasz Kosmaty jClassRegistry.insert(
74b7d1787dSŁukasz Kosmaty {name, CachedJClass(clazz, std::move(methods))}
75b7d1787dSŁukasz Kosmaty );
76b7d1787dSŁukasz Kosmaty }
77b7d1787dSŁukasz Kosmaty
getJClass(const std::string & className)78b7d1787dSŁukasz Kosmaty JavaReferencesCache::CachedJClass &JavaReferencesCache::getJClass(
79b7d1787dSŁukasz Kosmaty const std::string &className
80b7d1787dSŁukasz Kosmaty ) {
81b7d1787dSŁukasz Kosmaty return jClassRegistry.at(className);
82b7d1787dSŁukasz Kosmaty }
83b7d1787dSŁukasz Kosmaty
getOrLoadJClass(JNIEnv * env,const std::string & className)848d89495bSŁukasz Kosmaty JavaReferencesCache::CachedJClass &JavaReferencesCache::getOrLoadJClass(
858d89495bSŁukasz Kosmaty JNIEnv *env,
868d89495bSŁukasz Kosmaty const std::string &className
878d89495bSŁukasz Kosmaty ) {
888d89495bSŁukasz Kosmaty auto result = jClassRegistry.find(className);
898d89495bSŁukasz Kosmaty if (result == jClassRegistry.end()) {
908d89495bSŁukasz Kosmaty loadJClass(env, className, {});
918d89495bSŁukasz Kosmaty return jClassRegistry.at(className);
928d89495bSŁukasz Kosmaty }
938d89495bSŁukasz Kosmaty
948d89495bSŁukasz Kosmaty return result->second;
958d89495bSŁukasz Kosmaty }
968d89495bSŁukasz Kosmaty
getMethod(const std::string & name,const std::string & signature)97b7d1787dSŁukasz Kosmaty jmethodID JavaReferencesCache::CachedJClass::getMethod(
98b7d1787dSŁukasz Kosmaty const std::string &name,
99b7d1787dSŁukasz Kosmaty const std::string &signature
100b7d1787dSŁukasz Kosmaty ) {
101b7d1787dSŁukasz Kosmaty return methods.at({name, signature});
102b7d1787dSŁukasz Kosmaty }
103b7d1787dSŁukasz Kosmaty
CachedJClass(jclass clazz,MethodHashMap methods)104b7d1787dSŁukasz Kosmaty JavaReferencesCache::CachedJClass::CachedJClass(
105b7d1787dSŁukasz Kosmaty jclass clazz,
106b7d1787dSŁukasz Kosmaty MethodHashMap methods
107b7d1787dSŁukasz Kosmaty ) : clazz(clazz), methods(std::move(methods)) {}
108b7d1787dSŁukasz Kosmaty } // namespace expo
109