164f5c95fSŁukasz Kosmaty // Copyright © 2021-present 650 Industries, Inc. (aka Expo)
264f5c95fSŁukasz Kosmaty 
364f5c95fSŁukasz Kosmaty #pragma once
464f5c95fSŁukasz Kosmaty 
564f5c95fSŁukasz Kosmaty #include <fbjni/fbjni.h>
664f5c95fSŁukasz Kosmaty #include <jsi/jsi.h>
764f5c95fSŁukasz Kosmaty #include <react/jni/ReadableNativeArray.h>
864f5c95fSŁukasz Kosmaty #include <jni/JCallback.h>
964f5c95fSŁukasz Kosmaty 
10e6ec10dbSŁukasz Kosmaty #include <unordered_map>
1164f5c95fSŁukasz Kosmaty 
1264f5c95fSŁukasz Kosmaty #include "MethodMetadata.h"
1364f5c95fSŁukasz Kosmaty #include "JNIFunctionBody.h"
1465a981ddSŁukasz Kosmaty #include "types/ExpectedType.h"
1564f5c95fSŁukasz Kosmaty 
1664f5c95fSŁukasz Kosmaty namespace jni = facebook::jni;
1764f5c95fSŁukasz Kosmaty namespace jsi = facebook::jsi;
1864f5c95fSŁukasz Kosmaty namespace react = facebook::react;
1964f5c95fSŁukasz Kosmaty 
2064f5c95fSŁukasz Kosmaty namespace expo {
2164f5c95fSŁukasz Kosmaty class JSIInteropModuleRegistry;
2264f5c95fSŁukasz Kosmaty 
23cf4fff55SŁukasz Kosmaty class JavaScriptModuleObject;
24cf4fff55SŁukasz Kosmaty 
25cf4fff55SŁukasz Kosmaty void decorateObjectWithFunctions(
26cf4fff55SŁukasz Kosmaty   jsi::Runtime &runtime,
27cf4fff55SŁukasz Kosmaty   JSIInteropModuleRegistry *jsiInteropModuleRegistry,
28cf4fff55SŁukasz Kosmaty   jsi::Object *jsObject,
29cf4fff55SŁukasz Kosmaty   JavaScriptModuleObject *objectData
30cf4fff55SŁukasz Kosmaty );
31cf4fff55SŁukasz Kosmaty 
32cf4fff55SŁukasz Kosmaty void decorateObjectWithProperties(
33cf4fff55SŁukasz Kosmaty   jsi::Runtime &runtime,
34cf4fff55SŁukasz Kosmaty   JSIInteropModuleRegistry *jsiInteropModuleRegistry,
35cf4fff55SŁukasz Kosmaty   jsi::Object *jsObject,
36cf4fff55SŁukasz Kosmaty   JavaScriptModuleObject *objectData
37cf4fff55SŁukasz Kosmaty );
38cf4fff55SŁukasz Kosmaty 
39cf4fff55SŁukasz Kosmaty void decorateObjectWithConstants(
40cf4fff55SŁukasz Kosmaty   jsi::Runtime &runtime,
41cf4fff55SŁukasz Kosmaty   JSIInteropModuleRegistry *jsiInteropModuleRegistry,
42cf4fff55SŁukasz Kosmaty   jsi::Object *jsObject,
43cf4fff55SŁukasz Kosmaty   JavaScriptModuleObject *objectData
44cf4fff55SŁukasz Kosmaty );
45cf4fff55SŁukasz Kosmaty 
4664f5c95fSŁukasz Kosmaty /**
4764f5c95fSŁukasz Kosmaty  * A CPP part of the module.
4864f5c95fSŁukasz Kosmaty  *
4964f5c95fSŁukasz Kosmaty  * Right now objects of this class are stored by the ModuleHolder to ensure they will live
5064f5c95fSŁukasz Kosmaty  * as long as the RN context.
5164f5c95fSŁukasz Kosmaty  */
5264f5c95fSŁukasz Kosmaty class JavaScriptModuleObject : public jni::HybridClass<JavaScriptModuleObject> {
5364f5c95fSŁukasz Kosmaty public:
5464f5c95fSŁukasz Kosmaty   static auto constexpr
5564f5c95fSŁukasz Kosmaty     kJavaDescriptor = "Lexpo/modules/kotlin/jni/JavaScriptModuleObject;";
5664f5c95fSŁukasz Kosmaty   static auto constexpr TAG = "JavaScriptModuleObject";
5764f5c95fSŁukasz Kosmaty 
5864f5c95fSŁukasz Kosmaty   static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis);
5964f5c95fSŁukasz Kosmaty 
6064f5c95fSŁukasz Kosmaty   static void registerNatives();
6164f5c95fSŁukasz Kosmaty 
6264f5c95fSŁukasz Kosmaty   /**
6364f5c95fSŁukasz Kosmaty    * Pointer to the module registry interop.
6464f5c95fSŁukasz Kosmaty    */
6564f5c95fSŁukasz Kosmaty   JSIInteropModuleRegistry *jsiInteropModuleRegistry;
6664f5c95fSŁukasz Kosmaty 
6764f5c95fSŁukasz Kosmaty   /**
6864f5c95fSŁukasz Kosmaty    * Returns a cached instance of jsi::Object representing this module.
6964f5c95fSŁukasz Kosmaty    * @param runtime
7064f5c95fSŁukasz Kosmaty    * @return Wrapped instance of JavaScriptModuleObject::HostObject
7164f5c95fSŁukasz Kosmaty    */
7264f5c95fSŁukasz Kosmaty   std::shared_ptr<jsi::Object> getJSIObject(jsi::Runtime &runtime);
7364f5c95fSŁukasz Kosmaty 
7464f5c95fSŁukasz Kosmaty   /**
75a764be12SŁukasz Kosmaty    * Exports constants that will be assigned to the underlying HostObject.
76a764be12SŁukasz Kosmaty    */
77a764be12SŁukasz Kosmaty   void exportConstants(jni::alias_ref<react::NativeMap::javaobject> constants);
78a764be12SŁukasz Kosmaty 
79a764be12SŁukasz Kosmaty   /**
8064f5c95fSŁukasz Kosmaty    * Registers a sync function.
8164f5c95fSŁukasz Kosmaty    * That function can be called via the `JavaScriptModuleObject.callSyncMethod` method.
8264f5c95fSŁukasz Kosmaty    */
8364f5c95fSŁukasz Kosmaty   void registerSyncFunction(
8464f5c95fSŁukasz Kosmaty     jni::alias_ref<jstring> name,
85cf4fff55SŁukasz Kosmaty     jboolean takesOwner,
8664f5c95fSŁukasz Kosmaty     jint args,
8765a981ddSŁukasz Kosmaty     jni::alias_ref<jni::JArrayClass<ExpectedType>> expectedArgTypes,
8847a022e6SŁukasz Kosmaty     jni::alias_ref<JNIFunctionBody::javaobject> body
8964f5c95fSŁukasz Kosmaty   );
9064f5c95fSŁukasz Kosmaty 
9164f5c95fSŁukasz Kosmaty   /**
9264f5c95fSŁukasz Kosmaty    * Registers a async function.
9364f5c95fSŁukasz Kosmaty    * That function can be called via the `JavaScriptModuleObject.callAsyncMethod` method.
9464f5c95fSŁukasz Kosmaty    */
9564f5c95fSŁukasz Kosmaty   void registerAsyncFunction(
9664f5c95fSŁukasz Kosmaty     jni::alias_ref<jstring> name,
97cf4fff55SŁukasz Kosmaty     jboolean takesOwner,
9864f5c95fSŁukasz Kosmaty     jint args,
9965a981ddSŁukasz Kosmaty     jni::alias_ref<jni::JArrayClass<ExpectedType>> expectedArgTypes,
10047a022e6SŁukasz Kosmaty     jni::alias_ref<JNIAsyncFunctionBody::javaobject> body
10147a022e6SŁukasz Kosmaty   );
10247a022e6SŁukasz Kosmaty 
103cf4fff55SŁukasz Kosmaty   void registerClass(
104cf4fff55SŁukasz Kosmaty     jni::alias_ref<jstring> name,
105ecb7f347SŁukasz Kosmaty     jni::alias_ref<JavaScriptModuleObject::javaobject> classObject,
106ecb7f347SŁukasz Kosmaty     jboolean takesOwner,
107ecb7f347SŁukasz Kosmaty     jint args,
108ecb7f347SŁukasz Kosmaty     jni::alias_ref<jni::JArrayClass<ExpectedType>> expectedArgTypes,
109ecb7f347SŁukasz Kosmaty     jni::alias_ref<JNIFunctionBody::javaobject> body
110cf4fff55SŁukasz Kosmaty   );
111cf4fff55SŁukasz Kosmaty 
1123852c14fSŁukasz Kosmaty   void registerViewPrototype(
1133852c14fSŁukasz Kosmaty     jni::alias_ref<JavaScriptModuleObject::javaobject> viewPrototype
1143852c14fSŁukasz Kosmaty   );
1153852c14fSŁukasz Kosmaty 
11647a022e6SŁukasz Kosmaty   /**
11747a022e6SŁukasz Kosmaty    * Registers a property
11847a022e6SŁukasz Kosmaty    * @param name of the property
11947a022e6SŁukasz Kosmaty    * @param desiredType of the setter argument
12047a022e6SŁukasz Kosmaty    * @param getter body for the get method - can be nullptr
12147a022e6SŁukasz Kosmaty    * @param setter body for the set method - can be nullptr
12247a022e6SŁukasz Kosmaty    */
12347a022e6SŁukasz Kosmaty   void registerProperty(
12447a022e6SŁukasz Kosmaty     jni::alias_ref<jstring> name,
125*b1cbccf5SŁukasz Kosmaty     jboolean getterTakesOwner,
126*b1cbccf5SŁukasz Kosmaty     jni::alias_ref<jni::JArrayClass<ExpectedType>> getterExpectedArgsTypes,
12747a022e6SŁukasz Kosmaty     jni::alias_ref<JNIFunctionBody::javaobject> getter,
128*b1cbccf5SŁukasz Kosmaty     jboolean setterTakesOwner,
129*b1cbccf5SŁukasz Kosmaty     jni::alias_ref<jni::JArrayClass<ExpectedType>> setterExpectedArgsTypes,
13047a022e6SŁukasz Kosmaty     jni::alias_ref<JNIFunctionBody::javaobject> setter
13164f5c95fSŁukasz Kosmaty   );
13264f5c95fSŁukasz Kosmaty 
13364f5c95fSŁukasz Kosmaty private:
134aaf1c10dSKudo Chien   explicit JavaScriptModuleObject(jni::alias_ref<jhybridobject> jThis);
135aaf1c10dSKudo Chien 
136aaf1c10dSKudo Chien private:
13764f5c95fSŁukasz Kosmaty   friend HybridBase;
138cf4fff55SŁukasz Kosmaty 
139cf4fff55SŁukasz Kosmaty   friend void decorateObjectWithFunctions(
140cf4fff55SŁukasz Kosmaty     jsi::Runtime &runtime,
141cf4fff55SŁukasz Kosmaty     JSIInteropModuleRegistry *jsiInteropModuleRegistry,
142cf4fff55SŁukasz Kosmaty     jsi::Object *jsObject,
143cf4fff55SŁukasz Kosmaty     JavaScriptModuleObject *objectData
144cf4fff55SŁukasz Kosmaty   );
145cf4fff55SŁukasz Kosmaty 
146cf4fff55SŁukasz Kosmaty   friend void decorateObjectWithProperties(
147cf4fff55SŁukasz Kosmaty     jsi::Runtime &runtime,
148cf4fff55SŁukasz Kosmaty     JSIInteropModuleRegistry *jsiInteropModuleRegistry,
149cf4fff55SŁukasz Kosmaty     jsi::Object *jsObject,
150cf4fff55SŁukasz Kosmaty     JavaScriptModuleObject *objectData
151cf4fff55SŁukasz Kosmaty   );
152cf4fff55SŁukasz Kosmaty 
153cf4fff55SŁukasz Kosmaty   friend void decorateObjectWithConstants(
154cf4fff55SŁukasz Kosmaty     jsi::Runtime &runtime,
155cf4fff55SŁukasz Kosmaty     JSIInteropModuleRegistry *jsiInteropModuleRegistry,
156cf4fff55SŁukasz Kosmaty     jsi::Object *jsObject,
157cf4fff55SŁukasz Kosmaty     JavaScriptModuleObject *objectData
158cf4fff55SŁukasz Kosmaty   );
159cf4fff55SŁukasz Kosmaty 
16064f5c95fSŁukasz Kosmaty   /**
161b627df43SŁukasz Kosmaty    * A reference to the `jsi::Object`.
16264f5c95fSŁukasz Kosmaty    * Simple we cached that value to return the same object each time.
163cb63a94cSŁukasz Kosmaty    * It's a weak reference because the JS runtime holds the actual object.
164cb63a94cSŁukasz Kosmaty    * Doing that allows the runtime to deallocate jsi::Object if it's not needed anymore.
16564f5c95fSŁukasz Kosmaty    */
166cb63a94cSŁukasz Kosmaty   std::weak_ptr<jsi::Object> jsiObject;
16764f5c95fSŁukasz Kosmaty   jni::global_ref<JavaScriptModuleObject::javaobject> javaPart_;
16864f5c95fSŁukasz Kosmaty 
16964f5c95fSŁukasz Kosmaty   /**
17064f5c95fSŁukasz Kosmaty    * Metadata map that stores information about all available methods on this module.
17164f5c95fSŁukasz Kosmaty    */
172e6ec10dbSŁukasz Kosmaty   std::unordered_map<std::string, MethodMetadata> methodsMetadata;
17364f5c95fSŁukasz Kosmaty 
174a764be12SŁukasz Kosmaty   /**
175a764be12SŁukasz Kosmaty    * A constants map.
176a764be12SŁukasz Kosmaty    */
177e6ec10dbSŁukasz Kosmaty   std::unordered_map<std::string, folly::dynamic> constants;
178a764be12SŁukasz Kosmaty 
17947a022e6SŁukasz Kosmaty   /**
18047a022e6SŁukasz Kosmaty    * A registry of properties
18147a022e6SŁukasz Kosmaty    * The first MethodMetadata points to the getter and the second one to the setter.
18247a022e6SŁukasz Kosmaty    */
18347a022e6SŁukasz Kosmaty   std::map<std::string, std::pair<MethodMetadata, MethodMetadata>> properties;
18447a022e6SŁukasz Kosmaty 
185ecb7f347SŁukasz Kosmaty   std::map<
186ecb7f347SŁukasz Kosmaty     std::string,
187ecb7f347SŁukasz Kosmaty     std::pair<jni::global_ref<JavaScriptModuleObject::javaobject>, MethodMetadata>
188ecb7f347SŁukasz Kosmaty   > classes;
1893852c14fSŁukasz Kosmaty 
1903852c14fSŁukasz Kosmaty   jni::global_ref<JavaScriptModuleObject::javaobject> viewPrototype;
19164f5c95fSŁukasz Kosmaty };
19264f5c95fSŁukasz Kosmaty } // namespace expo
193