164f5c95fSŁukasz Kosmaty // Copyright © 2021-present 650 Industries, Inc. (aka Expo)
264f5c95fSŁukasz Kosmaty 
364f5c95fSŁukasz Kosmaty #include "JavaScriptModuleObject.h"
464f5c95fSŁukasz Kosmaty #include "JSIInteropModuleRegistry.h"
5e1f25825SŁukasz Kosmaty #include "JSIUtils.h"
664f5c95fSŁukasz Kosmaty 
764f5c95fSŁukasz Kosmaty #include <folly/dynamic.h>
864f5c95fSŁukasz Kosmaty #include <jsi/JSIDynamic.h>
964f5c95fSŁukasz Kosmaty #include <react/jni/ReadableNativeArray.h>
1064f5c95fSŁukasz Kosmaty #include <fbjni/detail/Hybrid.h>
1164f5c95fSŁukasz Kosmaty #include <ReactCommon/TurboModuleUtils.h>
1264f5c95fSŁukasz Kosmaty #include <jni/JCallback.h>
1364f5c95fSŁukasz Kosmaty #include <jsi/JSIDynamic.h>
1464f5c95fSŁukasz Kosmaty #include <fbjni/fbjni.h>
1564f5c95fSŁukasz Kosmaty #include <jsi/jsi.h>
1664f5c95fSŁukasz Kosmaty 
1764f5c95fSŁukasz Kosmaty #include <utility>
1864f5c95fSŁukasz Kosmaty #include <tuple>
1964f5c95fSŁukasz Kosmaty #include <algorithm>
20cf4fff55SŁukasz Kosmaty #include <sstream>
2164f5c95fSŁukasz Kosmaty 
2264f5c95fSŁukasz Kosmaty namespace jni = facebook::jni;
2364f5c95fSŁukasz Kosmaty namespace jsi = facebook::jsi;
2464f5c95fSŁukasz Kosmaty namespace react = facebook::react;
2564f5c95fSŁukasz Kosmaty 
2664f5c95fSŁukasz Kosmaty namespace expo {
2764f5c95fSŁukasz Kosmaty 
decorateObjectWithFunctions(jsi::Runtime & runtime,JSIInteropModuleRegistry * jsiInteropModuleRegistry,jsi::Object * jsObject,JavaScriptModuleObject * objectData)28cf4fff55SŁukasz Kosmaty void decorateObjectWithFunctions(
29cf4fff55SŁukasz Kosmaty   jsi::Runtime &runtime,
30cf4fff55SŁukasz Kosmaty   JSIInteropModuleRegistry *jsiInteropModuleRegistry,
31cf4fff55SŁukasz Kosmaty   jsi::Object *jsObject,
32cf4fff55SŁukasz Kosmaty   JavaScriptModuleObject *objectData) {
33cf4fff55SŁukasz Kosmaty   for (auto &[name, method]: objectData->methodsMetadata) {
34cf4fff55SŁukasz Kosmaty     jsObject->setProperty(
35cf4fff55SŁukasz Kosmaty       runtime,
36cf4fff55SŁukasz Kosmaty       jsi::String::createFromUtf8(runtime, name),
37cf4fff55SŁukasz Kosmaty       jsi::Value(runtime, *method.toJSFunction(runtime, jsiInteropModuleRegistry))
38cf4fff55SŁukasz Kosmaty     );
39cf4fff55SŁukasz Kosmaty   }
40cf4fff55SŁukasz Kosmaty }
41cf4fff55SŁukasz Kosmaty 
decorateObjectWithProperties(jsi::Runtime & runtime,JSIInteropModuleRegistry * jsiInteropModuleRegistry,jsi::Object * jsObject,JavaScriptModuleObject * objectData)42cf4fff55SŁukasz Kosmaty void decorateObjectWithProperties(
43cf4fff55SŁukasz Kosmaty   jsi::Runtime &runtime,
44cf4fff55SŁukasz Kosmaty   JSIInteropModuleRegistry *jsiInteropModuleRegistry,
45cf4fff55SŁukasz Kosmaty   jsi::Object *jsObject,
46cf4fff55SŁukasz Kosmaty   JavaScriptModuleObject *objectData) {
47cf4fff55SŁukasz Kosmaty   for (auto &[name, property]: objectData->properties) {
48cf4fff55SŁukasz Kosmaty     auto &[getter, setter] = property;
49cf4fff55SŁukasz Kosmaty 
50cf4fff55SŁukasz Kosmaty     auto descriptor = JavaScriptObject::preparePropertyDescriptor(runtime,
51cf4fff55SŁukasz Kosmaty                                                                   1 << 1 /* enumerable */);
52cf4fff55SŁukasz Kosmaty     descriptor.setProperty(
53cf4fff55SŁukasz Kosmaty       runtime,
54cf4fff55SŁukasz Kosmaty       "get",
55cf4fff55SŁukasz Kosmaty       jsi::Value(runtime, *getter.toJSFunction(runtime,
56cf4fff55SŁukasz Kosmaty                                                jsiInteropModuleRegistry))
57cf4fff55SŁukasz Kosmaty     );
58cf4fff55SŁukasz Kosmaty     descriptor.setProperty(
59cf4fff55SŁukasz Kosmaty       runtime,
60cf4fff55SŁukasz Kosmaty       "set",
61cf4fff55SŁukasz Kosmaty       jsi::Value(runtime, *setter.toJSFunction(runtime,
62cf4fff55SŁukasz Kosmaty                                                jsiInteropModuleRegistry))
63cf4fff55SŁukasz Kosmaty     );
64e1f25825SŁukasz Kosmaty     common::definePropertyOnJSIObject(runtime, jsObject, name.c_str(), std::move(descriptor));
65cf4fff55SŁukasz Kosmaty   }
66cf4fff55SŁukasz Kosmaty }
67cf4fff55SŁukasz Kosmaty 
decorateObjectWithConstants(jsi::Runtime & runtime,JSIInteropModuleRegistry * jsiInteropModuleRegistry,jsi::Object * jsObject,JavaScriptModuleObject * objectData)68cf4fff55SŁukasz Kosmaty void decorateObjectWithConstants(
69cf4fff55SŁukasz Kosmaty   jsi::Runtime &runtime,
70cf4fff55SŁukasz Kosmaty   JSIInteropModuleRegistry *jsiInteropModuleRegistry,
71cf4fff55SŁukasz Kosmaty   jsi::Object *jsObject,
72cf4fff55SŁukasz Kosmaty   JavaScriptModuleObject *objectData) {
73cf4fff55SŁukasz Kosmaty   for (const auto &[name, value]: objectData->constants) {
74cf4fff55SŁukasz Kosmaty     jsObject->setProperty(
75cf4fff55SŁukasz Kosmaty       runtime,
76cf4fff55SŁukasz Kosmaty       jsi::String::createFromUtf8(runtime, name),
77cf4fff55SŁukasz Kosmaty       jsi::valueFromDynamic(runtime, value)
78cf4fff55SŁukasz Kosmaty     );
79cf4fff55SŁukasz Kosmaty   }
80cf4fff55SŁukasz Kosmaty }
81cf4fff55SŁukasz Kosmaty 
8264f5c95fSŁukasz Kosmaty jni::local_ref<jni::HybridClass<JavaScriptModuleObject>::jhybriddata>
initHybrid(jni::alias_ref<jhybridobject> jThis)8364f5c95fSŁukasz Kosmaty JavaScriptModuleObject::initHybrid(jni::alias_ref<jhybridobject> jThis) {
8464f5c95fSŁukasz Kosmaty   return makeCxxInstance(jThis);
8564f5c95fSŁukasz Kosmaty }
8664f5c95fSŁukasz Kosmaty 
registerNatives()8764f5c95fSŁukasz Kosmaty void JavaScriptModuleObject::registerNatives() {
8864f5c95fSŁukasz Kosmaty   registerHybrid({
8964f5c95fSŁukasz Kosmaty                    makeNativeMethod("initHybrid", JavaScriptModuleObject::initHybrid),
90a764be12SŁukasz Kosmaty                    makeNativeMethod("exportConstants", JavaScriptModuleObject::exportConstants),
9164f5c95fSŁukasz Kosmaty                    makeNativeMethod("registerSyncFunction",
9264f5c95fSŁukasz Kosmaty                                     JavaScriptModuleObject::registerSyncFunction),
9364f5c95fSŁukasz Kosmaty                    makeNativeMethod("registerAsyncFunction",
9464f5c95fSŁukasz Kosmaty                                     JavaScriptModuleObject::registerAsyncFunction),
9547a022e6SŁukasz Kosmaty                    makeNativeMethod("registerProperty",
9647a022e6SŁukasz Kosmaty                                     JavaScriptModuleObject::registerProperty),
97cf4fff55SŁukasz Kosmaty                    makeNativeMethod("registerClass",
983852c14fSŁukasz Kosmaty                                     JavaScriptModuleObject::registerClass),
993852c14fSŁukasz Kosmaty                    makeNativeMethod("registerViewPrototype",
1003852c14fSŁukasz Kosmaty                                     JavaScriptModuleObject::registerViewPrototype)
10164f5c95fSŁukasz Kosmaty                  });
10264f5c95fSŁukasz Kosmaty }
10364f5c95fSŁukasz Kosmaty 
getJSIObject(jsi::Runtime & runtime)10464f5c95fSŁukasz Kosmaty std::shared_ptr<jsi::Object> JavaScriptModuleObject::getJSIObject(jsi::Runtime &runtime) {
105cb63a94cSŁukasz Kosmaty   if (auto object = jsiObject.lock()) {
106cb63a94cSŁukasz Kosmaty     return object;
10764f5c95fSŁukasz Kosmaty   }
10864f5c95fSŁukasz Kosmaty 
109b627df43SŁukasz Kosmaty   auto moduleObject = std::make_shared<jsi::Object>(runtime);
110b627df43SŁukasz Kosmaty 
111cf4fff55SŁukasz Kosmaty   decorateObjectWithConstants(
112b627df43SŁukasz Kosmaty     runtime,
113cf4fff55SŁukasz Kosmaty     jsiInteropModuleRegistry,
114cf4fff55SŁukasz Kosmaty     moduleObject.get(),
115cf4fff55SŁukasz Kosmaty     this
116b627df43SŁukasz Kosmaty   );
117cf4fff55SŁukasz Kosmaty   decorateObjectWithProperties(
118cf4fff55SŁukasz Kosmaty     runtime,
119cf4fff55SŁukasz Kosmaty     jsiInteropModuleRegistry,
120cf4fff55SŁukasz Kosmaty     moduleObject.get(),
121cf4fff55SŁukasz Kosmaty     this
122cf4fff55SŁukasz Kosmaty   );
123cf4fff55SŁukasz Kosmaty   decorateObjectWithFunctions(
124cf4fff55SŁukasz Kosmaty     runtime,
125cf4fff55SŁukasz Kosmaty     jsiInteropModuleRegistry,
126cf4fff55SŁukasz Kosmaty     moduleObject.get(),
127cf4fff55SŁukasz Kosmaty     this
128cf4fff55SŁukasz Kosmaty   );
129b627df43SŁukasz Kosmaty 
1303852c14fSŁukasz Kosmaty   if (viewPrototype) {
1313852c14fSŁukasz Kosmaty     auto viewPrototypeObject = viewPrototype->cthis();
1323852c14fSŁukasz Kosmaty     viewPrototypeObject->jsiInteropModuleRegistry = jsiInteropModuleRegistry;
1333852c14fSŁukasz Kosmaty     auto viewPrototypeJSIObject = viewPrototypeObject->getJSIObject(runtime);
1343852c14fSŁukasz Kosmaty     moduleObject->setProperty(
1353852c14fSŁukasz Kosmaty       runtime,
1363852c14fSŁukasz Kosmaty       "ViewPrototype",
1373852c14fSŁukasz Kosmaty       jsi::Value(runtime, *viewPrototypeJSIObject)
1383852c14fSŁukasz Kosmaty     );
1393852c14fSŁukasz Kosmaty   }
1403852c14fSŁukasz Kosmaty 
141ecb7f347SŁukasz Kosmaty   for (auto &[name, classInfo]: classes) {
142ecb7f347SŁukasz Kosmaty     auto &[classRef, constructor] = classInfo;
143ecb7f347SŁukasz Kosmaty     auto classObject = classRef->cthis();
1443852c14fSŁukasz Kosmaty     classObject->jsiInteropModuleRegistry = jsiInteropModuleRegistry;
145b627df43SŁukasz Kosmaty 
146cf4fff55SŁukasz Kosmaty     std::string nativeConstructorKey("__native_constructor__");
147b627df43SŁukasz Kosmaty 
148cf4fff55SŁukasz Kosmaty     // Create a string buffer of the source code to evaluate.
149cf4fff55SŁukasz Kosmaty     std::stringstream source;
150cf4fff55SŁukasz Kosmaty     source << "(function " << name << "(...args) { this." << nativeConstructorKey
151cf4fff55SŁukasz Kosmaty            << "(...args); return this; })";
152cf4fff55SŁukasz Kosmaty     std::shared_ptr<jsi::StringBuffer> sourceBuffer = std::make_shared<jsi::StringBuffer>(
153cf4fff55SŁukasz Kosmaty       source.str());
154cf4fff55SŁukasz Kosmaty 
155cf4fff55SŁukasz Kosmaty     // Evaluate the code and obtain returned value (the constructor function).
156cf4fff55SŁukasz Kosmaty     jsi::Object klass = runtime.evaluateJavaScript(sourceBuffer, "").asObject(runtime);
157cf4fff55SŁukasz Kosmaty 
158cf4fff55SŁukasz Kosmaty     // Set the native constructor in the prototype.
159cf4fff55SŁukasz Kosmaty     jsi::Object prototype = klass.getPropertyAsObject(runtime, "prototype");
160cf4fff55SŁukasz Kosmaty     jsi::PropNameID nativeConstructorPropId = jsi::PropNameID::forAscii(runtime,
161cf4fff55SŁukasz Kosmaty                                                                         nativeConstructorKey);
162cf4fff55SŁukasz Kosmaty     jsi::Function nativeConstructor = jsi::Function::createFromHostFunction(
163cf4fff55SŁukasz Kosmaty       runtime,
164cf4fff55SŁukasz Kosmaty       nativeConstructorPropId,
165cf4fff55SŁukasz Kosmaty       // The paramCount is not obligatory to match, it only affects the `length` property of the function.
166cf4fff55SŁukasz Kosmaty       0,
167ecb7f347SŁukasz Kosmaty       [classObject, &constructor = constructor, jsiInteropModuleRegistry = jsiInteropModuleRegistry](
168cf4fff55SŁukasz Kosmaty         jsi::Runtime &runtime,
169cf4fff55SŁukasz Kosmaty         const jsi::Value &thisValue,
170cf4fff55SŁukasz Kosmaty         const jsi::Value *args,
171cf4fff55SŁukasz Kosmaty         size_t count
172cf4fff55SŁukasz Kosmaty       ) -> jsi::Value {
173ecb7f347SŁukasz Kosmaty         auto thisObject = std::make_shared<jsi::Object>(thisValue.asObject(runtime));
174ecb7f347SŁukasz Kosmaty         decorateObjectWithProperties(runtime, jsiInteropModuleRegistry, thisObject.get(),
175ecb7f347SŁukasz Kosmaty                                      classObject);
176ecb7f347SŁukasz Kosmaty         try {
177ecb7f347SŁukasz Kosmaty           JNIEnv *env = jni::Environment::current();
178ecb7f347SŁukasz Kosmaty           /**
179ecb7f347SŁukasz Kosmaty           * This will push a new JNI stack frame for the LocalReferences in this
180ecb7f347SŁukasz Kosmaty           * function call. When the stack frame for this lambda is popped,
181ecb7f347SŁukasz Kosmaty           * all LocalReferences are deleted.
182ecb7f347SŁukasz Kosmaty           */
183ecb7f347SŁukasz Kosmaty           jni::JniLocalScope scope(env, (int) count);
184ecb7f347SŁukasz Kosmaty           auto result = constructor.callJNISync(
185ecb7f347SŁukasz Kosmaty             env,
186ecb7f347SŁukasz Kosmaty             runtime,
187ecb7f347SŁukasz Kosmaty             jsiInteropModuleRegistry,
188ecb7f347SŁukasz Kosmaty             thisValue,
189ecb7f347SŁukasz Kosmaty             args,
190ecb7f347SŁukasz Kosmaty             count
191ecb7f347SŁukasz Kosmaty           );
192ecb7f347SŁukasz Kosmaty           if (result == nullptr) {
193ecb7f347SŁukasz Kosmaty             return jsi::Value::undefined();
194ecb7f347SŁukasz Kosmaty           }
195ecb7f347SŁukasz Kosmaty           jobject unpackedResult = result.get();
196ecb7f347SŁukasz Kosmaty           jclass resultClass = env->GetObjectClass(unpackedResult);
197ecb7f347SŁukasz Kosmaty           if (env->IsAssignableFrom(
198ecb7f347SŁukasz Kosmaty             resultClass,
199ecb7f347SŁukasz Kosmaty             JavaReferencesCache::instance()->getJClass(
200ecb7f347SŁukasz Kosmaty               "expo/modules/kotlin/sharedobjects/SharedObject").clazz
201ecb7f347SŁukasz Kosmaty           )) {
20229e8b6f8SŁukasz Kosmaty             auto jsThisObject = JavaScriptObject::newInstance(
20329e8b6f8SŁukasz Kosmaty               jsiInteropModuleRegistry,
204ecb7f347SŁukasz Kosmaty               jsiInteropModuleRegistry->runtimeHolder,
205ecb7f347SŁukasz Kosmaty               thisObject
206ecb7f347SŁukasz Kosmaty             );
207ecb7f347SŁukasz Kosmaty             jsiInteropModuleRegistry->registerSharedObject(result, jsThisObject);
208ecb7f347SŁukasz Kosmaty           }
209ecb7f347SŁukasz Kosmaty         } catch (jni::JniException &jniException) {
210ecb7f347SŁukasz Kosmaty           rethrowAsCodedError(runtime, jniException);
211ecb7f347SŁukasz Kosmaty         }
212cf4fff55SŁukasz Kosmaty         return jsi::Value::undefined();
213cf4fff55SŁukasz Kosmaty       });
214cf4fff55SŁukasz Kosmaty 
215cf4fff55SŁukasz Kosmaty     auto descriptor = JavaScriptObject::preparePropertyDescriptor(runtime, 0);
216cf4fff55SŁukasz Kosmaty     descriptor.setProperty(runtime, "value", jsi::Value(runtime, nativeConstructor));
217cf4fff55SŁukasz Kosmaty 
218*b1cbccf5SŁukasz Kosmaty     common::definePropertyOnJSIObject(runtime, &prototype, nativeConstructorKey.c_str(),
219*b1cbccf5SŁukasz Kosmaty                                       std::move(descriptor));
220cf4fff55SŁukasz Kosmaty 
221b627df43SŁukasz Kosmaty     moduleObject->setProperty(
222b627df43SŁukasz Kosmaty       runtime,
223b627df43SŁukasz Kosmaty       jsi::String::createFromUtf8(runtime, name),
224cf4fff55SŁukasz Kosmaty       jsi::Value(runtime, klass.asFunction(runtime))
225cf4fff55SŁukasz Kosmaty     );
226cf4fff55SŁukasz Kosmaty 
227cf4fff55SŁukasz Kosmaty     decorateObjectWithFunctions(
228cf4fff55SŁukasz Kosmaty       runtime,
229cf4fff55SŁukasz Kosmaty       jsiInteropModuleRegistry,
230cf4fff55SŁukasz Kosmaty       &prototype,
231cf4fff55SŁukasz Kosmaty       classObject
232b627df43SŁukasz Kosmaty     );
233b627df43SŁukasz Kosmaty   }
234b627df43SŁukasz Kosmaty 
235b627df43SŁukasz Kosmaty   jsiObject = moduleObject;
236b627df43SŁukasz Kosmaty   return moduleObject;
23764f5c95fSŁukasz Kosmaty }
23864f5c95fSŁukasz Kosmaty 
exportConstants(jni::alias_ref<react::NativeMap::javaobject> constants)2399ebf31e6SŁukasz Kosmaty void JavaScriptModuleObject::exportConstants(
2409ebf31e6SŁukasz Kosmaty   jni::alias_ref<react::NativeMap::javaobject> constants
2419ebf31e6SŁukasz Kosmaty ) {
242a764be12SŁukasz Kosmaty   auto dynamic = constants->cthis()->consume();
243a764be12SŁukasz Kosmaty   assert(dynamic.isObject());
244a764be12SŁukasz Kosmaty 
245a764be12SŁukasz Kosmaty   for (const auto &[key, value]: dynamic.items()) {
246a764be12SŁukasz Kosmaty     this->constants[key.asString()] = value;
247a764be12SŁukasz Kosmaty   }
248a764be12SŁukasz Kosmaty }
249a764be12SŁukasz Kosmaty 
registerSyncFunction(jni::alias_ref<jstring> name,jboolean takesOwner,jint args,jni::alias_ref<jni::JArrayClass<ExpectedType>> expectedArgTypes,jni::alias_ref<JNIFunctionBody::javaobject> body)25064f5c95fSŁukasz Kosmaty void JavaScriptModuleObject::registerSyncFunction(
25164f5c95fSŁukasz Kosmaty   jni::alias_ref<jstring> name,
252cf4fff55SŁukasz Kosmaty   jboolean takesOwner,
25364f5c95fSŁukasz Kosmaty   jint args,
25465a981ddSŁukasz Kosmaty   jni::alias_ref<jni::JArrayClass<ExpectedType>> expectedArgTypes,
25564f5c95fSŁukasz Kosmaty   jni::alias_ref<JNIFunctionBody::javaobject> body
25664f5c95fSŁukasz Kosmaty ) {
2579ebf31e6SŁukasz Kosmaty   std::string cName = name->toStdString();
2586f5b8a20SŁukasz Kosmaty 
2599ebf31e6SŁukasz Kosmaty   methodsMetadata.try_emplace(
2609ebf31e6SŁukasz Kosmaty     cName,
2619ebf31e6SŁukasz Kosmaty     cName,
262cf4fff55SŁukasz Kosmaty     takesOwner,
2639ebf31e6SŁukasz Kosmaty     args,
2649ebf31e6SŁukasz Kosmaty     false,
26565a981ddSŁukasz Kosmaty     jni::make_local(expectedArgTypes),
2669ebf31e6SŁukasz Kosmaty     jni::make_global(body)
2679ebf31e6SŁukasz Kosmaty   );
26864f5c95fSŁukasz Kosmaty }
26964f5c95fSŁukasz Kosmaty 
registerAsyncFunction(jni::alias_ref<jstring> name,jboolean takesOwner,jint args,jni::alias_ref<jni::JArrayClass<ExpectedType>> expectedArgTypes,jni::alias_ref<JNIAsyncFunctionBody::javaobject> body)27064f5c95fSŁukasz Kosmaty void JavaScriptModuleObject::registerAsyncFunction(
27164f5c95fSŁukasz Kosmaty   jni::alias_ref<jstring> name,
272cf4fff55SŁukasz Kosmaty   jboolean takesOwner,
27364f5c95fSŁukasz Kosmaty   jint args,
27465a981ddSŁukasz Kosmaty   jni::alias_ref<jni::JArrayClass<ExpectedType>> expectedArgTypes,
27564f5c95fSŁukasz Kosmaty   jni::alias_ref<JNIAsyncFunctionBody::javaobject> body
27664f5c95fSŁukasz Kosmaty ) {
27765a981ddSŁukasz Kosmaty   std::string cName = name->toStdString();
2789ebf31e6SŁukasz Kosmaty 
2799ebf31e6SŁukasz Kosmaty   methodsMetadata.try_emplace(
2809ebf31e6SŁukasz Kosmaty     cName,
2819ebf31e6SŁukasz Kosmaty     cName,
282cf4fff55SŁukasz Kosmaty     takesOwner,
2839ebf31e6SŁukasz Kosmaty     args,
2849ebf31e6SŁukasz Kosmaty     true,
28565a981ddSŁukasz Kosmaty     jni::make_local(expectedArgTypes),
2869ebf31e6SŁukasz Kosmaty     jni::make_global(body)
2879ebf31e6SŁukasz Kosmaty   );
28864f5c95fSŁukasz Kosmaty }
28964f5c95fSŁukasz Kosmaty 
registerClass(jni::alias_ref<jstring> name,jni::alias_ref<JavaScriptModuleObject::javaobject> classObject,jboolean takesOwner,jint args,jni::alias_ref<jni::JArrayClass<ExpectedType>> expectedArgTypes,jni::alias_ref<JNIFunctionBody::javaobject> body)290cf4fff55SŁukasz Kosmaty void JavaScriptModuleObject::registerClass(
291cf4fff55SŁukasz Kosmaty   jni::alias_ref<jstring> name,
292ecb7f347SŁukasz Kosmaty   jni::alias_ref<JavaScriptModuleObject::javaobject> classObject,
293ecb7f347SŁukasz Kosmaty   jboolean takesOwner,
294ecb7f347SŁukasz Kosmaty   jint args,
295ecb7f347SŁukasz Kosmaty   jni::alias_ref<jni::JArrayClass<ExpectedType>> expectedArgTypes,
296ecb7f347SŁukasz Kosmaty   jni::alias_ref<JNIFunctionBody::javaobject> body
297cf4fff55SŁukasz Kosmaty ) {
298cf4fff55SŁukasz Kosmaty   std::string cName = name->toStdString();
299ecb7f347SŁukasz Kosmaty   MethodMetadata constructor(
300ecb7f347SŁukasz Kosmaty     "constructor",
301ecb7f347SŁukasz Kosmaty     takesOwner,
302ecb7f347SŁukasz Kosmaty     args,
303ecb7f347SŁukasz Kosmaty     false,
304ecb7f347SŁukasz Kosmaty     jni::make_local(expectedArgTypes),
305ecb7f347SŁukasz Kosmaty     jni::make_global(body)
306ecb7f347SŁukasz Kosmaty   );
307ecb7f347SŁukasz Kosmaty 
308ecb7f347SŁukasz Kosmaty   auto pair = std::make_pair(jni::make_global(classObject), std::move(constructor));
309ecb7f347SŁukasz Kosmaty 
310ecb7f347SŁukasz Kosmaty   classes.try_emplace(
311ecb7f347SŁukasz Kosmaty     cName,
312ecb7f347SŁukasz Kosmaty     std::move(pair)
313ecb7f347SŁukasz Kosmaty   );
314cf4fff55SŁukasz Kosmaty }
315cf4fff55SŁukasz Kosmaty 
registerViewPrototype(jni::alias_ref<JavaScriptModuleObject::javaobject> viewPrototype)3163852c14fSŁukasz Kosmaty void JavaScriptModuleObject::registerViewPrototype(
3173852c14fSŁukasz Kosmaty   jni::alias_ref<JavaScriptModuleObject::javaobject> viewPrototype
3183852c14fSŁukasz Kosmaty ) {
3193852c14fSŁukasz Kosmaty   this->viewPrototype = jni::make_global(viewPrototype);
3203852c14fSŁukasz Kosmaty }
3213852c14fSŁukasz Kosmaty 
registerProperty(jni::alias_ref<jstring> name,jboolean getterTakesOwner,jni::alias_ref<jni::JArrayClass<ExpectedType>> getterExpectedArgsTypes,jni::alias_ref<JNIFunctionBody::javaobject> getter,jboolean setterTakesOwner,jni::alias_ref<jni::JArrayClass<ExpectedType>> setterExpectedArgsTypes,jni::alias_ref<JNIFunctionBody::javaobject> setter)32247a022e6SŁukasz Kosmaty void JavaScriptModuleObject::registerProperty(
32347a022e6SŁukasz Kosmaty   jni::alias_ref<jstring> name,
324*b1cbccf5SŁukasz Kosmaty   jboolean getterTakesOwner,
325*b1cbccf5SŁukasz Kosmaty   jni::alias_ref<jni::JArrayClass<ExpectedType>> getterExpectedArgsTypes,
32647a022e6SŁukasz Kosmaty   jni::alias_ref<JNIFunctionBody::javaobject> getter,
327*b1cbccf5SŁukasz Kosmaty   jboolean setterTakesOwner,
328*b1cbccf5SŁukasz Kosmaty   jni::alias_ref<jni::JArrayClass<ExpectedType>> setterExpectedArgsTypes,
32947a022e6SŁukasz Kosmaty   jni::alias_ref<JNIFunctionBody::javaobject> setter
33047a022e6SŁukasz Kosmaty ) {
33147a022e6SŁukasz Kosmaty   auto cName = name->toStdString();
33247a022e6SŁukasz Kosmaty 
33347a022e6SŁukasz Kosmaty   auto getterMetadata = MethodMetadata(
33447a022e6SŁukasz Kosmaty     cName,
335*b1cbccf5SŁukasz Kosmaty     getterTakesOwner,
336*b1cbccf5SŁukasz Kosmaty     getterExpectedArgsTypes->size(),
337cf4fff55SŁukasz Kosmaty     false,
338*b1cbccf5SŁukasz Kosmaty     jni::make_local(getterExpectedArgsTypes),
33947a022e6SŁukasz Kosmaty     jni::make_global(getter)
34047a022e6SŁukasz Kosmaty   );
34147a022e6SŁukasz Kosmaty 
34247a022e6SŁukasz Kosmaty   auto setterMetadata = MethodMetadata(
34347a022e6SŁukasz Kosmaty     cName,
344*b1cbccf5SŁukasz Kosmaty     setterTakesOwner,
345*b1cbccf5SŁukasz Kosmaty     setterExpectedArgsTypes->size(),
346cf4fff55SŁukasz Kosmaty     false,
347*b1cbccf5SŁukasz Kosmaty     jni::make_local(setterExpectedArgsTypes),
34847a022e6SŁukasz Kosmaty     jni::make_global(setter)
34947a022e6SŁukasz Kosmaty   );
35047a022e6SŁukasz Kosmaty 
35147a022e6SŁukasz Kosmaty   auto functions = std::make_pair(
35247a022e6SŁukasz Kosmaty     std::move(getterMetadata),
35347a022e6SŁukasz Kosmaty     std::move(setterMetadata)
35447a022e6SŁukasz Kosmaty   );
35547a022e6SŁukasz Kosmaty 
35647a022e6SŁukasz Kosmaty   properties.insert({cName, std::move(functions)});
35747a022e6SŁukasz Kosmaty }
35847a022e6SŁukasz Kosmaty 
JavaScriptModuleObject(jni::alias_ref<jhybridobject> jThis)359aaf1c10dSKudo Chien JavaScriptModuleObject::JavaScriptModuleObject(jni::alias_ref<jhybridobject> jThis)
360aaf1c10dSKudo Chien   : javaPart_(jni::make_global(jThis)) {
361aaf1c10dSKudo Chien }
36264f5c95fSŁukasz Kosmaty } // namespace expo
363