expo-modules-core 1.2.7 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/CHANGELOG.md +28 -5
  2. package/ExpoModulesCore.podspec +1 -0
  3. package/README.md +1 -1
  4. package/android/ExpoModulesCorePlugin.gradle +16 -0
  5. package/android/build.gradle +3 -2
  6. package/android/src/main/cpp/Exceptions.cpp +8 -0
  7. package/android/src/main/cpp/Exceptions.h +11 -0
  8. package/android/src/main/cpp/ExpoModulesHostObject.cpp +22 -5
  9. package/android/src/main/cpp/ExpoModulesHostObject.h +5 -0
  10. package/android/src/main/cpp/JNIInjector.cpp +2 -0
  11. package/android/src/main/cpp/JSIInteropModuleRegistry.cpp +25 -1
  12. package/android/src/main/cpp/JSIInteropModuleRegistry.h +14 -0
  13. package/android/src/main/cpp/JSIObjectWrapper.h +15 -4
  14. package/android/src/main/cpp/JSITypeConverter.h +3 -2
  15. package/android/src/main/cpp/JavaReferencesCache.cpp +2 -0
  16. package/android/src/main/cpp/JavaScriptFunction.cpp +56 -0
  17. package/android/src/main/cpp/JavaScriptFunction.h +54 -0
  18. package/android/src/main/cpp/JavaScriptModuleObject.cpp +225 -105
  19. package/android/src/main/cpp/JavaScriptModuleObject.h +67 -34
  20. package/android/src/main/cpp/JavaScriptObject.cpp +55 -1
  21. package/android/src/main/cpp/JavaScriptObject.h +17 -13
  22. package/android/src/main/cpp/JavaScriptRuntime.cpp +12 -3
  23. package/android/src/main/cpp/JavaScriptRuntime.h +9 -1
  24. package/android/src/main/cpp/JavaScriptValue.cpp +9 -0
  25. package/android/src/main/cpp/JavaScriptValue.h +4 -0
  26. package/android/src/main/cpp/MethodMetadata.cpp +66 -87
  27. package/android/src/main/cpp/MethodMetadata.h +18 -16
  28. package/android/src/main/cpp/ObjectDeallocator.h +25 -0
  29. package/android/src/main/cpp/WeakRuntimeHolder.cpp +7 -0
  30. package/android/src/main/cpp/WeakRuntimeHolder.h +4 -0
  31. package/android/src/main/cpp/types/CppType.h +4 -1
  32. package/android/src/main/cpp/types/FrontendConverter.cpp +58 -0
  33. package/android/src/main/cpp/types/FrontendConverter.h +45 -0
  34. package/android/src/main/cpp/types/FrontendConverterProvider.cpp +3 -0
  35. package/android/src/main/cpp/types/JNIToJSIConverter.cpp +88 -0
  36. package/android/src/main/cpp/types/JNIToJSIConverter.h +22 -0
  37. package/android/src/main/java/com/facebook/react/uimanager/ReactStylesDiffMapHelper.kt +10 -0
  38. package/android/src/main/java/expo/modules/kotlin/AppContext.kt +8 -25
  39. package/android/src/main/java/expo/modules/kotlin/FilteredIterator.kt +37 -0
  40. package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +1 -1
  41. package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +30 -23
  42. package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +0 -3
  43. package/android/src/main/java/expo/modules/kotlin/Utils.kt +21 -0
  44. package/android/src/main/java/expo/modules/kotlin/activityresult/AppContextActivityResultCaller.kt +21 -1
  45. package/android/src/main/java/expo/modules/kotlin/classcomponent/ClassComponentBuilder.kt +112 -0
  46. package/android/src/main/java/expo/modules/kotlin/classcomponent/ClassDefinitionData.kt +10 -0
  47. package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +21 -0
  48. package/android/src/main/java/expo/modules/kotlin/exception/CommonExceptions.kt +15 -0
  49. package/android/src/main/java/expo/modules/kotlin/functions/AnyFunction.kt +17 -3
  50. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +38 -8
  51. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionComponent.kt +3 -2
  52. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromiseComponent.kt +3 -2
  53. package/android/src/main/java/expo/modules/kotlin/functions/SuspendFunctionComponent.kt +1 -0
  54. package/android/src/main/java/expo/modules/kotlin/functions/SyncFunctionComponent.kt +18 -11
  55. package/android/src/main/java/expo/modules/kotlin/jni/CppType.kt +4 -1
  56. package/android/src/main/java/expo/modules/kotlin/jni/JNIDeallocator.kt +73 -0
  57. package/android/src/main/java/expo/modules/kotlin/jni/JSIInteropModuleRegistry.kt +28 -2
  58. package/android/src/main/java/expo/modules/kotlin/jni/JavaCallback.kt +8 -1
  59. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptFunction.kt +48 -0
  60. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptModuleObject.kt +40 -3
  61. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptObject.kt +23 -3
  62. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptValue.kt +26 -1
  63. package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +0 -11
  64. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +26 -16
  65. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +3 -1
  66. package/android/src/main/java/expo/modules/kotlin/sharedobjects/SharedObject.kt +12 -0
  67. package/android/src/main/java/expo/modules/kotlin/sharedobjects/SharedObjectRegistry.kt +62 -0
  68. package/android/src/main/java/expo/modules/kotlin/sharedobjects/SharedObjectTypeConverter.kt +27 -0
  69. package/android/src/main/java/expo/modules/kotlin/types/AnyType.kt +2 -1
  70. package/android/src/main/java/expo/modules/kotlin/types/EitherTypeConverter.kt +7 -6
  71. package/android/src/main/java/expo/modules/kotlin/types/JavaScriptFunctionTypeConverter.kt +22 -0
  72. package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +30 -24
  73. package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +45 -1
  74. package/android/src/main/java/expo/modules/kotlin/types/TypedArrayTypeConverter.kt +3 -2
  75. package/android/src/main/java/expo/modules/kotlin/views/AnyViewProp.kt +3 -1
  76. package/android/src/main/java/expo/modules/kotlin/views/ConcreteViewProp.kt +3 -3
  77. package/android/src/main/java/expo/modules/kotlin/views/FilteredReadableMap.kt +53 -0
  78. package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +25 -5
  79. package/android/src/main/java/expo/modules/kotlin/views/SimpleViewManagerWrapper.kt +25 -5
  80. package/android/src/main/java/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +161 -10
  81. package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinitionBuilder.kt +0 -67
  82. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +6 -7
  83. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +40 -3
  84. package/android/src/main/java/expo/modules/kotlin/views/ViewTypeConverter.kt +44 -0
  85. package/android-annotation/build.gradle +45 -0
  86. package/android-annotation/src/main/java/expo/modules/annotation/Config.kt +7 -0
  87. package/android-annotation/src/main/java/expo/modules/annotation/ConverterBinder.kt +7 -0
  88. package/android-annotation-processor/build.gradle +51 -0
  89. package/android-annotation-processor/src/main/java/expo/modules/annotationprocessor/ExpoSymbolProcessor.kt +175 -0
  90. package/android-annotation-processor/src/main/java/expo/modules/annotationprocessor/ExpoSymbolProcessorProvider.kt +10 -0
  91. package/android-annotation-processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider +1 -0
  92. package/build/NativeViewManagerAdapter.native.d.ts.map +1 -1
  93. package/build/NativeViewManagerAdapter.native.js +36 -23
  94. package/build/NativeViewManagerAdapter.native.js.map +1 -1
  95. package/build/requireNativeModule.js +2 -2
  96. package/build/requireNativeModule.js.map +1 -1
  97. package/common/cpp/fabric/ExpoViewProps.cpp +18 -3
  98. package/common/cpp/fabric/ExpoViewProps.h +4 -1
  99. package/ios/Fabric/ExpoFabricView.swift +10 -10
  100. package/ios/Fabric/ExpoFabricViewObjC.h +2 -0
  101. package/ios/Fabric/ExpoFabricViewObjC.mm +17 -2
  102. package/ios/JSI/EXJSIInstaller.mm +1 -1
  103. package/ios/JSI/EXJSIUtils.h +5 -0
  104. package/ios/JSI/EXJSIUtils.mm +17 -0
  105. package/ios/JSI/EXJavaScriptRuntime.h +5 -0
  106. package/ios/JSI/EXJavaScriptRuntime.mm +6 -0
  107. package/ios/JSI/EXJavaScriptValue.h +2 -0
  108. package/ios/JSI/EXJavaScriptValue.mm +8 -0
  109. package/ios/JSI/EXJavaScriptWeakObject.mm +29 -8
  110. package/ios/JSI/EXRawJavaScriptFunction.h +24 -0
  111. package/ios/JSI/EXRawJavaScriptFunction.mm +52 -0
  112. package/ios/JSI/ExpoModulesHostObject.mm +1 -1
  113. package/ios/JSI/JavaScriptValue.swift +28 -1
  114. package/ios/ModuleRegistry/EXModuleRegistry.h +0 -4
  115. package/ios/ModuleRegistry/EXModuleRegistry.m +0 -23
  116. package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +0 -16
  117. package/ios/ModuleRegistryProvider/EXModuleRegistryProvider.m +0 -6
  118. package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +1 -31
  119. package/ios/Swift/AppContext.swift +46 -6
  120. package/ios/Swift/Arguments/Convertible.swift +3 -3
  121. package/ios/Swift/Arguments/Convertibles.swift +5 -5
  122. package/ios/Swift/Classes/ClassComponent.swift +18 -12
  123. package/ios/Swift/Classes/ClassRegistry.swift +31 -0
  124. package/ios/Swift/Conversions.swift +19 -3
  125. package/ios/Swift/Convertibles/Convertibles+Color.swift +3 -3
  126. package/ios/Swift/Convertibles/Either.swift +6 -4
  127. package/ios/Swift/DynamicTypes/AnyDynamicType.swift +18 -2
  128. package/ios/Swift/DynamicTypes/DynamicArrayType.swift +3 -3
  129. package/ios/Swift/DynamicTypes/DynamicConvertibleType.swift +2 -2
  130. package/ios/Swift/DynamicTypes/DynamicEnumType.swift +1 -1
  131. package/ios/Swift/DynamicTypes/DynamicJavaScriptType.swift +27 -0
  132. package/ios/Swift/DynamicTypes/DynamicOptionalType.swift +9 -2
  133. package/ios/Swift/DynamicTypes/DynamicRawType.swift +1 -1
  134. package/ios/Swift/DynamicTypes/DynamicSharedObjectType.swift +16 -2
  135. package/ios/Swift/DynamicTypes/DynamicType.swift +6 -0
  136. package/ios/Swift/DynamicTypes/DynamicTypedArrayType.swift +15 -4
  137. package/ios/Swift/DynamicTypes/DynamicViewType.swift +68 -0
  138. package/ios/Swift/ExpoBridgeModule.swift +1 -1
  139. package/ios/Swift/Functions/AnyFunction.swift +5 -4
  140. package/ios/Swift/Functions/AsyncFunctionComponent.swift +22 -19
  141. package/ios/Swift/Functions/ConcurrentFunctionDefinition.swift +29 -13
  142. package/ios/Swift/Functions/SyncFunctionComponent.swift +26 -15
  143. package/ios/Swift/JavaScriptFunction.swift +68 -0
  144. package/ios/Swift/JavaScriptUtils.swift +57 -18
  145. package/ios/Swift/ModuleHolder.swift +22 -10
  146. package/ios/Swift/Modules/ModuleDefinition.swift +8 -2
  147. package/ios/Swift/Objects/JavaScriptObjectBuilder.swift +8 -8
  148. package/ios/Swift/Objects/ObjectDefinition.swift +17 -15
  149. package/ios/Swift/Objects/PropertyComponent.swift +23 -17
  150. package/ios/Swift/Records/AnyField.swift +1 -1
  151. package/ios/Swift/Records/Field.swift +2 -2
  152. package/ios/Swift/Records/Record.swift +5 -5
  153. package/ios/Swift/SharedObjects/SharedObjectRegistry.swift +4 -0
  154. package/ios/Swift/Views/AnyViewProp.swift +1 -1
  155. package/ios/Swift/Views/ComponentData.swift +37 -2
  156. package/ios/Swift/Views/ConcreteViewProp.swift +2 -2
  157. package/ios/Swift/Views/ViewDefinition.swift +39 -0
  158. package/ios/Swift/Views/ViewModuleWrapper.swift +0 -29
  159. package/ios/Tests/ClassComponentSpec.swift +39 -27
  160. package/ios/Tests/ConvertiblesSpec.swift +75 -49
  161. package/ios/Tests/DynamicTypeSpec.swift +29 -27
  162. package/ios/Tests/EitherSpec.swift +9 -7
  163. package/ios/Tests/ExpoModulesSpec.swift +13 -13
  164. package/ios/Tests/FunctionSpec.swift +38 -22
  165. package/ios/Tests/JavaScriptRuntimeSpec.swift +4 -0
  166. package/ios/Tests/PropertyComponentSpec.swift +33 -30
  167. package/ios/Tests/RecordSpec.swift +7 -5
  168. package/ios/Tests/SharedObjectRegistrySpec.swift +12 -12
  169. package/ios/Tests/TypedArraysSpec.swift +1 -1
  170. package/ios/Tests/ViewDefinitionSpec.swift +4 -2
  171. package/package.json +2 -2
  172. package/src/NativeViewManagerAdapter.native.tsx +33 -29
  173. package/src/requireNativeModule.ts +2 -2
  174. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +0 -132
  175. package/ios/EXViewManager.h +0 -21
  176. package/ios/EXViewManager.m +0 -128
  177. package/ios/ModuleRegistryAdapter/EXViewManagerAdapterClassesRegistry.h +0 -17
  178. package/ios/ModuleRegistryAdapter/EXViewManagerAdapterClassesRegistry.m +0 -67
  179. package/ios/ViewManagerAdapter/EXViewManagerAdapter.h +0 -17
  180. package/ios/ViewManagerAdapter/EXViewManagerAdapter.m +0 -45
@@ -9,6 +9,7 @@
9
9
  #include "../JSIInteropModuleRegistry.h"
10
10
  #include "../JavaScriptObject.h"
11
11
  #include "../JavaScriptValue.h"
12
+ #include "../JavaScriptFunction.h"
12
13
  #include "../javaclasses/Collections.h"
13
14
 
14
15
  #include "react/jni/ReadableNativeMap.h"
@@ -207,6 +208,25 @@ bool JavaScriptObjectFrontendConverter::canConvert(
207
208
  return value.isObject();
208
209
  }
209
210
 
211
+ jobject JavaScriptFunctionFrontendConverter::convert(
212
+ jsi::Runtime &rt,
213
+ JNIEnv *env,
214
+ JSIInteropModuleRegistry *moduleRegistry,
215
+ const jsi::Value &value
216
+ ) const {
217
+ return JavaScriptFunction::newObjectCxxArgs(
218
+ moduleRegistry->runtimeHolder->weak_from_this(),
219
+ std::make_shared<jsi::Function>(value.getObject(rt).asFunction(rt))
220
+ ).release();
221
+ }
222
+
223
+ bool JavaScriptFunctionFrontendConverter::canConvert(
224
+ jsi::Runtime &rt,
225
+ const jsi::Value &value
226
+ ) const {
227
+ return value.isObject() && value.asObject(rt).isFunction(rt);
228
+ }
229
+
210
230
  jobject UnknownFrontendConverter::convert(
211
231
  jsi::Runtime &rt,
212
232
  JNIEnv *env,
@@ -429,4 +449,42 @@ bool MapFrontendConverter::canConvert(
429
449
  ) const {
430
450
  return value.isObject();
431
451
  }
452
+
453
+ jobject ViewTagFrontendConverter::convert(jsi::Runtime &rt, JNIEnv *env,
454
+ JSIInteropModuleRegistry *moduleRegistry,
455
+ const jsi::Value &value) const {
456
+ auto nativeTag = value.getObject(rt).getProperty(rt, "nativeTag");
457
+ if (nativeTag.isNull()) {
458
+ return nullptr;
459
+ }
460
+
461
+ auto viewTag = (int) nativeTag.getNumber();
462
+ auto &integerClass = JavaReferencesCache::instance()
463
+ ->getJClass("java/lang/Integer");
464
+ jmethodID integerConstructor = integerClass.getMethod("<init>", "(I)V");
465
+ return env->NewObject(integerClass.clazz, integerConstructor, viewTag);
466
+ }
467
+
468
+ bool ViewTagFrontendConverter::canConvert(jsi::Runtime &rt, const jsi::Value &value) const {
469
+ return value.isObject() && value.getObject(rt).hasProperty(rt, "nativeTag");
470
+ }
471
+
472
+ jobject SharedObjectIdConverter::convert(jsi::Runtime &rt, JNIEnv *env,
473
+ JSIInteropModuleRegistry *moduleRegistry,
474
+ const jsi::Value &value) const {
475
+ auto objectId = value.getObject(rt).getProperty(rt, "__expo_shared_object_id__");
476
+ if (objectId.isNull()) {
477
+ return nullptr;
478
+ }
479
+
480
+ auto viewTag = (int) objectId.getNumber();
481
+ auto &integerClass = JavaReferencesCache::instance()
482
+ ->getJClass("java/lang/Integer");
483
+ jmethodID integerConstructor = integerClass.getMethod("<init>", "(I)V");
484
+ return env->NewObject(integerClass.clazz, integerConstructor, viewTag);
485
+ }
486
+
487
+ bool SharedObjectIdConverter::canConvert(jsi::Runtime &rt, const jsi::Value &value) const {
488
+ return value.isObject() && value.getObject(rt).hasProperty(rt, "__expo_shared_object_id__");
489
+ }
432
490
  } // namespace expo
@@ -205,6 +205,51 @@ public:
205
205
  bool canConvert(jsi::Runtime &rt, const jsi::Value &value) const override;
206
206
  };
207
207
 
208
+ /**
209
+ * Converter from js function to [expo.modules.kotlin.jni.JavaScriptFunction].
210
+ */
211
+ class JavaScriptFunctionFrontendConverter : public FrontendConverter {
212
+ public:
213
+ jobject convert(
214
+ jsi::Runtime &rt,
215
+ JNIEnv *env,
216
+ JSIInteropModuleRegistry *moduleRegistry,
217
+ const jsi::Value &value
218
+ ) const override;
219
+
220
+ bool canConvert(jsi::Runtime &rt, const jsi::Value &value) const override;
221
+ };
222
+
223
+ /**
224
+ * Converter from js view object to int.
225
+ */
226
+ class ViewTagFrontendConverter : public FrontendConverter {
227
+ public:
228
+ jobject convert(
229
+ jsi::Runtime &rt,
230
+ JNIEnv *env,
231
+ JSIInteropModuleRegistry *moduleRegistry,
232
+ const jsi::Value &value
233
+ ) const override;
234
+
235
+ bool canConvert(jsi::Runtime &rt, const jsi::Value &value) const override;
236
+ };
237
+
238
+ /**
239
+ * Converter from js shared object to int.
240
+ */
241
+ class SharedObjectIdConverter : public FrontendConverter {
242
+ public:
243
+ jobject convert(
244
+ jsi::Runtime &rt,
245
+ JNIEnv *env,
246
+ JSIInteropModuleRegistry *moduleRegistry,
247
+ const jsi::Value &value
248
+ ) const override;
249
+
250
+ bool canConvert(jsi::Runtime &rt, const jsi::Value &value) const override;
251
+ };
252
+
208
253
  /**
209
254
  * Converter that always fails.
210
255
  * Used to not fail when the function is created.
@@ -19,9 +19,12 @@ void FrontendConverterProvider::createConverters() {
19
19
  RegisterConverter(CppType::TYPED_ARRAY, TypedArrayFrontendConverter);
20
20
  RegisterConverter(CppType::JS_OBJECT, JavaScriptObjectFrontendConverter);
21
21
  RegisterConverter(CppType::JS_VALUE, JavaScriptValueFrontendConverter);
22
+ RegisterConverter(CppType::JS_FUNCTION, JavaScriptFunctionFrontendConverter);
22
23
  RegisterConverter(CppType::STRING, StringFrontendConverter);
23
24
  RegisterConverter(CppType::READABLE_MAP, ReadableNativeMapArrayFrontendConverter);
24
25
  RegisterConverter(CppType::READABLE_ARRAY, ReadableNativeArrayFrontendConverter);
26
+ RegisterConverter(CppType::VIEW_TAG, ViewTagFrontendConverter);
27
+ RegisterConverter(CppType::SHARED_OBJECT_ID, SharedObjectIdConverter);
25
28
  #undef RegisterConverter
26
29
 
27
30
  auto registerPolyConverter = [this](const std::vector<CppType> &types) {
@@ -0,0 +1,88 @@
1
+ // Copyright © 2021-present 650 Industries, Inc. (aka Expo)
2
+
3
+ #include "JNIToJSIConverter.h"
4
+ #include "../JavaReferencesCache.h"
5
+ #include "../ObjectDeallocator.h"
6
+
7
+ #include <react/jni/ReadableNativeMap.h>
8
+ #include <react/jni/ReadableNativeArray.h>
9
+ #include <react/jni/WritableNativeArray.h>
10
+ #include <react/jni/WritableNativeMap.h>
11
+
12
+ namespace react = facebook::react;
13
+
14
+ namespace expo {
15
+
16
+ jsi::Value convert(
17
+ JSIInteropModuleRegistry *moduleRegistry,
18
+ JNIEnv *env,
19
+ jsi::Runtime &rt,
20
+ jni::local_ref<jobject> value
21
+ ) {
22
+ if (value == nullptr) {
23
+ return jsi::Value::undefined();
24
+ }
25
+ auto unpackedValue = value.get();
26
+ auto cache = JavaReferencesCache::instance();
27
+ if (env->IsInstanceOf(unpackedValue, cache->getJClass("java/lang/Double").clazz)) {
28
+ return {jni::static_ref_cast<jni::JDouble>(value)->value()};
29
+ }
30
+ if (env->IsInstanceOf(unpackedValue, cache->getJClass("java/lang/Integer").clazz)) {
31
+ return {jni::static_ref_cast<jni::JInteger>(value)->value()};
32
+ }
33
+ if (env->IsInstanceOf(unpackedValue, cache->getJClass("java/lang/Long").clazz)) {
34
+ return {(double) jni::static_ref_cast<jni::JLong>(value)->value()};
35
+ }
36
+ if (env->IsInstanceOf(unpackedValue, cache->getJClass("java/lang/String").clazz)) {
37
+ return jsi::String::createFromUtf8(
38
+ rt,
39
+ jni::static_ref_cast<jni::JString>(value)->toStdString()
40
+ );
41
+ }
42
+ if (env->IsInstanceOf(unpackedValue, cache->getJClass("java/lang/Boolean").clazz)) {
43
+ return {(bool) jni::static_ref_cast<jni::JBoolean>(value)->value()};
44
+ }
45
+ if (env->IsInstanceOf(unpackedValue, cache->getJClass("java/lang/Float").clazz)) {
46
+ return {(double) jni::static_ref_cast<jni::JFloat>(value)->value()};
47
+ }
48
+ if (env->IsInstanceOf(
49
+ unpackedValue,
50
+ cache->getJClass("com/facebook/react/bridge/WritableNativeArray").clazz
51
+ )) {
52
+ auto dynamic = jni::static_ref_cast<react::WritableNativeArray::javaobject>(value)
53
+ ->cthis()
54
+ ->consume();
55
+ return jsi::valueFromDynamic(rt, dynamic);
56
+ }
57
+ if (env->IsInstanceOf(
58
+ unpackedValue,
59
+ cache->getJClass("com/facebook/react/bridge/WritableNativeMap").clazz
60
+ )) {
61
+ auto dynamic = jni::static_ref_cast<react::WritableNativeMap::javaobject>(value)
62
+ ->cthis()
63
+ ->consume();
64
+ return jsi::valueFromDynamic(rt, dynamic);
65
+ }
66
+ if (env->IsInstanceOf(unpackedValue, JavaScriptModuleObject::javaClassStatic().get())) {
67
+ auto anonymousObject = jni::static_ref_cast<JavaScriptModuleObject::javaobject>(value)
68
+ ->cthis();
69
+ anonymousObject->jsiInteropModuleRegistry = moduleRegistry;
70
+ auto jsiObject = anonymousObject->getJSIObject(rt);
71
+
72
+ jni::global_ref<jobject> globalRef = jni::make_global(value);
73
+ std::shared_ptr<expo::ObjectDeallocator> deallocator = std::make_shared<ObjectDeallocator>(
74
+ [globalRef = std::move(globalRef)]() mutable {
75
+ globalRef.reset();
76
+ });
77
+
78
+ auto descriptor = JavaScriptObject::preparePropertyDescriptor(rt, 0);
79
+ descriptor.setProperty(rt, "value", jsi::Object::createFromHostObject(rt, deallocator));
80
+ JavaScriptObject::defineProperty(rt, jsiObject.get(), "__expo_object_deallocator__",
81
+ std::move(descriptor));
82
+
83
+ return jsi::Value(rt, *jsiObject);
84
+ }
85
+
86
+ return jsi::Value::undefined();
87
+ }
88
+ } // namespace expo
@@ -0,0 +1,22 @@
1
+ // Copyright © 2021-present 650 Industries, Inc. (aka Expo)
2
+
3
+ #pragma once
4
+
5
+ #include "../JSIInteropModuleRegistry.h"
6
+
7
+ #include <fbjni/fbjni.h>
8
+ #include <jsi/jsi.h>
9
+
10
+ namespace jni = facebook::jni;
11
+ namespace jsi = facebook::jsi;
12
+
13
+ namespace expo {
14
+
15
+ jsi::Value convert(
16
+ JSIInteropModuleRegistry *moduleRegistry,
17
+ JNIEnv *env,
18
+ jsi::Runtime &rt,
19
+ jni::local_ref<jobject> value
20
+ );
21
+
22
+ } // namespace expo
@@ -0,0 +1,10 @@
1
+ package com.facebook.react.uimanager
2
+
3
+ import com.facebook.react.bridge.ReadableMap
4
+
5
+ /**
6
+ * Access the package private property declared inside of [ReactStylesDiffMap]
7
+ */
8
+ fun ReactStylesDiffMap.getBackingMap(): ReadableMap {
9
+ return mBackingMap
10
+ }
@@ -6,7 +6,6 @@ import android.content.Intent
6
6
  import android.os.Handler
7
7
  import android.os.HandlerThread
8
8
  import android.view.View
9
- import androidx.annotation.MainThread
10
9
  import androidx.annotation.UiThread
11
10
  import androidx.appcompat.app.AppCompatActivity
12
11
  import com.facebook.react.bridge.ReactApplicationContext
@@ -28,10 +27,7 @@ import expo.modules.interfaces.permissions.Permissions
28
27
  import expo.modules.interfaces.sensors.SensorServiceInterface
29
28
  import expo.modules.interfaces.taskManager.TaskManagerInterface
30
29
  import expo.modules.kotlin.activityresult.ActivityResultsManager
31
- import expo.modules.kotlin.activityresult.AppContextActivityResultCaller
32
- import expo.modules.kotlin.activityresult.AppContextActivityResultContract
33
- import expo.modules.kotlin.activityresult.AppContextActivityResultFallbackCallback
34
- import expo.modules.kotlin.activityresult.AppContextActivityResultLauncher
30
+ import expo.modules.kotlin.activityresult.DefaultAppContextActivityResultCaller
35
31
  import expo.modules.kotlin.defaultmodules.ErrorManagerModule
36
32
  import expo.modules.kotlin.defaultmodules.NativeModulesProxyModule
37
33
  import expo.modules.kotlin.events.EventEmitter
@@ -39,9 +35,11 @@ import expo.modules.kotlin.events.EventName
39
35
  import expo.modules.kotlin.events.KEventEmitterWrapper
40
36
  import expo.modules.kotlin.events.KModuleEventEmitterWrapper
41
37
  import expo.modules.kotlin.events.OnActivityResultPayload
38
+ import expo.modules.kotlin.jni.JNIDeallocator
42
39
  import expo.modules.kotlin.jni.JSIInteropModuleRegistry
43
40
  import expo.modules.kotlin.modules.Module
44
41
  import expo.modules.kotlin.providers.CurrentActivityProvider
42
+ import expo.modules.kotlin.sharedobjects.SharedObjectRegistry
45
43
  import kotlinx.coroutines.CoroutineName
46
44
  import kotlinx.coroutines.CoroutineScope
47
45
  import kotlinx.coroutines.Dispatchers
@@ -49,20 +47,21 @@ import kotlinx.coroutines.SupervisorJob
49
47
  import kotlinx.coroutines.android.asCoroutineDispatcher
50
48
  import kotlinx.coroutines.cancel
51
49
  import java.io.File
52
- import java.io.Serializable
53
50
  import java.lang.ref.WeakReference
54
51
 
55
52
  class AppContext(
56
53
  modulesProvider: ModulesProvider,
57
54
  val legacyModuleRegistry: expo.modules.core.ModuleRegistry,
58
55
  private val reactContextHolder: WeakReference<ReactApplicationContext>
59
- ) : CurrentActivityProvider, AppContextActivityResultCaller {
56
+ ) : CurrentActivityProvider {
60
57
  val registry = ModuleRegistry(WeakReference(this))
61
58
  private val reactLifecycleDelegate = ReactLifecycleDelegate(this)
62
59
 
63
60
  // We postpone creating the `JSIInteropModuleRegistry` to not load so files in unit tests.
64
61
  private lateinit var jsiInterop: JSIInteropModuleRegistry
65
62
 
63
+ internal val sharedObjectRegistry = SharedObjectRegistry()
64
+
66
65
  private val modulesQueueDispatcher = HandlerThread("expo.modules.AsyncFunctionQueue")
67
66
  .apply { start() }
68
67
  .looper.let { Handler(it) }
@@ -95,6 +94,7 @@ class AppContext(
95
94
  internal var legacyModulesProxyHolder: WeakReference<NativeModulesProxy>? = null
96
95
 
97
96
  private val activityResultsManager = ActivityResultsManager(this)
97
+ internal val appContextActivityResultCaller = DefaultAppContextActivityResultCaller(activityResultsManager)
98
98
 
99
99
  init {
100
100
  requireNotNull(reactContextHolder.get()) {
@@ -275,6 +275,7 @@ class AppContext(
275
275
  modulesQueue.cancel(ContextDestroyedException())
276
276
  mainQueue.cancel(ContextDestroyedException())
277
277
  backgroundCoroutineScope.cancel(ContextDestroyedException())
278
+ JNIDeallocator.deallocate()
278
279
  logger.info("✅ AppContext was destroyed")
279
280
  }
280
281
 
@@ -344,23 +345,5 @@ class AppContext(
344
345
  return activityProvider?.currentActivity
345
346
  }
346
347
 
347
- // endregion
348
-
349
- // region AppContextActivityResultCaller
350
-
351
- /**
352
- * For the time being [fallbackCallback] is not working.
353
- * There are some problems with saving and restoring the state of [activityResultsManager]
354
- * connected with [Activity]'s lifecycle and [AppContext] lifespan. So far, we've failed with identifying
355
- * what parts of the application outlives the Activity destruction (especially [AppContext] and other [Bridge]-related parts).
356
- */
357
- @MainThread
358
- @Deprecated(message = "`registerForActivityResult` was deprecated. Please use `RegisterActivityContracts` component instead.")
359
- override suspend fun <I : Serializable, O> registerForActivityResult(
360
- contract: AppContextActivityResultContract<I, O>,
361
- fallbackCallback: AppContextActivityResultFallbackCallback<I, O>
362
- ): AppContextActivityResultLauncher<I, O> =
363
- activityResultsManager.registerForActivityResult(contract, fallbackCallback)
364
-
365
348
  // endregion
366
349
  }
@@ -0,0 +1,37 @@
1
+ package expo.modules.kotlin
2
+
3
+ fun interface Filter<T> {
4
+ fun apply(type: T): Boolean
5
+ }
6
+
7
+ class FilteredIterator<E>(
8
+ private val iterator: Iterator<E>,
9
+ private val filter: Filter<E>
10
+ ) : Iterator<E> {
11
+ private var next: E? = null
12
+
13
+ init {
14
+ this.findNext()
15
+ }
16
+
17
+ override fun hasNext(): Boolean {
18
+ return next != null
19
+ }
20
+
21
+ override fun next(): E {
22
+ val returnValue = next!!
23
+ this.findNext()
24
+ return returnValue
25
+ }
26
+
27
+ private fun findNext() {
28
+ while (iterator.hasNext()) {
29
+ val next = iterator.next()
30
+ this.next = next
31
+ if (filter.apply(next)) {
32
+ return
33
+ }
34
+ }
35
+ next = null
36
+ }
37
+ }
@@ -22,7 +22,7 @@ class KotlinInteropModuleRegistry(
22
22
  legacyModuleRegistry: expo.modules.core.ModuleRegistry,
23
23
  reactContext: WeakReference<ReactApplicationContext>
24
24
  ) {
25
- internal val appContext = AppContext(modulesProvider, legacyModuleRegistry, reactContext)
25
+ val appContext = AppContext(modulesProvider, legacyModuleRegistry, reactContext)
26
26
 
27
27
  private val registry: ModuleRegistry
28
28
  get() = appContext.registry
@@ -1,7 +1,6 @@
1
1
  package expo.modules.kotlin
2
2
 
3
3
  import android.view.View
4
- import com.facebook.react.bridge.Arguments
5
4
  import com.facebook.react.bridge.ReadableArray
6
5
  import expo.modules.kotlin.events.BasicEventListener
7
6
  import expo.modules.kotlin.events.EventListenerWithPayload
@@ -24,24 +23,36 @@ class ModuleHolder(val module: Module) {
24
23
  * Cached instance of HybridObject used by CPP to interact with underlying [expo.modules.kotlin.modules.Module] object.
25
24
  */
26
25
  val jsObject by lazy {
27
- JavaScriptModuleObject(name)
28
- .apply {
29
- val constants = definition.constantsProvider()
30
- val convertedConstants = Arguments.makeNativeMap(constants)
31
- exportConstants(convertedConstants)
32
-
33
- definition
34
- .functions
35
- .forEach { function ->
36
- function.attachToJSObject(module.appContext, this)
37
- }
38
-
39
- definition
40
- .properties
41
- .forEach { (_, prop) ->
42
- prop.attachToJSObject(this)
43
- }
26
+ val appContext = module.appContext
27
+
28
+ JavaScriptModuleObject(name).apply {
29
+ initUsingObjectDefinition(appContext, definition.objectDefinition)
30
+
31
+ val viewFunctions = definition.viewManagerDefinition?.asyncFunctions
32
+ if (viewFunctions?.isNotEmpty() == true) {
33
+ val viewPrototype = JavaScriptModuleObject("${name}_${definition.viewManagerDefinition?.viewType?.name}")
34
+ viewFunctions.forEach { function ->
35
+ function.attachToJSObject(appContext, viewPrototype)
36
+ }
37
+
38
+ registerViewPrototype(viewPrototype)
39
+ }
40
+
41
+ definition.classData.forEach { clazz ->
42
+ val clazzModuleObject = JavaScriptModuleObject(clazz.name)
43
+ .initUsingObjectDefinition(module.appContext, clazz.objectDefinition)
44
+
45
+ val constructor = clazz.constructor
46
+ registerClass(
47
+ clazz.name,
48
+ clazzModuleObject,
49
+ constructor.takesOwner,
50
+ constructor.argsCount,
51
+ constructor.getCppRequiredTypes().toTypedArray(),
52
+ constructor.getJNIFunctionBody(clazz.name, appContext)
53
+ )
44
54
  }
55
+ }
45
56
  }
46
57
 
47
58
  /**
@@ -87,15 +98,11 @@ class ModuleHolder(val module: Module) {
87
98
  fun registerContracts() {
88
99
  definition.registerContracts?.let {
89
100
  module.appContext.mainQueue.launch {
90
- it.invoke(module.appContext)
101
+ it.invoke(module.appContext.appContextActivityResultCaller)
91
102
  }
92
103
  }
93
104
  }
94
105
 
95
- fun cleanUp() {
96
- module.cleanUp()
97
- }
98
-
99
106
  fun viewClass(): KClass<out View>? {
100
107
  return definition.viewManagerDefinition?.viewType?.kotlin
101
108
  }
@@ -85,9 +85,6 @@ class ModuleRegistry(
85
85
  override fun iterator(): Iterator<ModuleHolder> = registry.values.iterator()
86
86
 
87
87
  fun cleanUp() {
88
- forEach {
89
- it.cleanUp()
90
- }
91
88
  registry.clear()
92
89
  logger.info("✅ ModuleRegistry was destroyed")
93
90
  }
@@ -0,0 +1,21 @@
1
+ package expo.modules.kotlin
2
+
3
+ import android.os.Looper
4
+ import expo.modules.kotlin.exception.Exceptions
5
+
6
+ object Utils {
7
+ @Suppress("UseExpressionBody")
8
+ inline fun assertMainThread() {
9
+ if (Thread.currentThread() !== Looper.getMainLooper().thread) {
10
+ throw Exceptions.IncorrectThreadException(
11
+ Thread.currentThread().name,
12
+ Looper.getMainLooper().thread.name
13
+ )
14
+ }
15
+ }
16
+ }
17
+
18
+ @Suppress("NOTHING_TO_INLINE")
19
+ inline fun AppContext?.toStrongReference(): AppContext {
20
+ return this ?: throw Exceptions.AppContextLost()
21
+ }
@@ -1,6 +1,8 @@
1
1
  package expo.modules.kotlin.activityresult
2
2
 
3
+ import android.app.Activity
3
4
  import androidx.annotation.MainThread
5
+ import expo.modules.kotlin.AppContext
4
6
  import java.io.Serializable
5
7
 
6
8
  /**
@@ -20,6 +22,24 @@ interface AppContextActivityResultCaller {
20
22
  @MainThread
21
23
  suspend fun <I : Serializable, O> registerForActivityResult(
22
24
  contract: AppContextActivityResultContract<I, O>,
23
- fallbackCallback: AppContextActivityResultFallbackCallback<I, O>,
25
+ fallbackCallback: AppContextActivityResultFallbackCallback<I, O> = AppContextActivityResultFallbackCallback { _, _ -> /* NOOP */ },
24
26
  ): AppContextActivityResultLauncher<I, O>
25
27
  }
28
+
29
+ internal class DefaultAppContextActivityResultCaller(
30
+ private val activityResultsManager: ActivityResultsManager
31
+ ) : AppContextActivityResultCaller {
32
+
33
+ /**
34
+ * For the time being [fallbackCallback] is not working.
35
+ * There are some problems with saving and restoring the state of [activityResultsManager]
36
+ * connected with [Activity]'s lifecycle and [AppContext] lifespan. So far, we've failed with identifying
37
+ * what parts of the application outlives the Activity destruction (especially [AppContext] and other [Bridge]-related parts).
38
+ */
39
+ override suspend fun <I : Serializable, O> registerForActivityResult(
40
+ contract: AppContextActivityResultContract<I, O>,
41
+ fallbackCallback: AppContextActivityResultFallbackCallback<I, O>
42
+ ): AppContextActivityResultLauncher<I, O> {
43
+ return activityResultsManager.registerForActivityResult(contract, fallbackCallback)
44
+ }
45
+ }
@@ -0,0 +1,112 @@
1
+ @file:Suppress("FunctionName")
2
+
3
+ package expo.modules.kotlin.classcomponent
4
+
5
+ import expo.modules.kotlin.functions.SyncFunctionComponent
6
+ import expo.modules.kotlin.objects.ObjectDefinitionBuilder
7
+ import expo.modules.kotlin.types.toAnyType
8
+ import kotlin.reflect.KClass
9
+ import kotlin.reflect.KType
10
+ import kotlin.reflect.typeOf
11
+
12
+ class ClassComponentBuilder<SharedObjectType : Any>(
13
+ val name: String,
14
+ private val ownerClass: KClass<SharedObjectType>,
15
+ private val ownerType: KType
16
+ ) : ObjectDefinitionBuilder() {
17
+ var constructor: SyncFunctionComponent? = null
18
+
19
+ fun buildClass(): ClassDefinitionData {
20
+ val objectData = buildObject()
21
+ objectData.functions.forEach {
22
+ it.ownerType = ownerType
23
+ it.canTakeOwner = true
24
+ }
25
+
26
+ val hasSharedObject = ownerClass !== Unit::class
27
+ if (hasSharedObject && constructor == null) {
28
+ throw IllegalArgumentException("constructor cannot be null")
29
+ }
30
+
31
+ val constructor = constructor ?: SyncFunctionComponent("constructor", arrayOf()) {}
32
+ constructor.canTakeOwner = true
33
+
34
+ return ClassDefinitionData(
35
+ name,
36
+ constructor,
37
+ objectData,
38
+ )
39
+ }
40
+
41
+ inline fun Constructor(
42
+ crossinline body: () -> SharedObjectType
43
+ ): SyncFunctionComponent {
44
+ return SyncFunctionComponent("constructor", arrayOf()) { body() }.also {
45
+ constructor = it
46
+ }
47
+ }
48
+
49
+ inline fun <reified P0> Constructor(
50
+ crossinline body: (p0: P0) -> SharedObjectType
51
+ ): SyncFunctionComponent {
52
+ return SyncFunctionComponent("constructor", arrayOf(typeOf<P0>().toAnyType())) { body(it[0] as P0) }.also {
53
+ constructor = it
54
+ }
55
+ }
56
+
57
+ inline fun <reified P0, reified P1> Constructor(
58
+ crossinline body: (p0: P0, p1: P1) -> SharedObjectType
59
+ ): SyncFunctionComponent {
60
+ return SyncFunctionComponent("constructor", arrayOf(typeOf<P0>().toAnyType(), typeOf<P1>().toAnyType())) { body(it[0] as P0, it[1] as P1) }.also {
61
+ constructor = it
62
+ }
63
+ }
64
+
65
+ inline fun <reified P0, reified P1, reified P2> Constructor(
66
+ crossinline body: (p0: P0, p1: P1, p2: P2) -> SharedObjectType
67
+ ): SyncFunctionComponent {
68
+ return SyncFunctionComponent("constructor", arrayOf(typeOf<P0>().toAnyType(), typeOf<P1>().toAnyType(), typeOf<P2>().toAnyType())) { body(it[0] as P0, it[1] as P1, it[2] as P2) }.also {
69
+ constructor = it
70
+ }
71
+ }
72
+
73
+ inline fun <reified P0, reified P1, reified P2, reified P3> Constructor(
74
+ crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3) -> SharedObjectType
75
+ ): SyncFunctionComponent {
76
+ return SyncFunctionComponent("constructor", arrayOf(typeOf<P0>().toAnyType(), typeOf<P1>().toAnyType(), typeOf<P2>().toAnyType(), typeOf<P3>().toAnyType())) { body(it[0] as P0, it[1] as P1, it[2] as P2, it[3] as P3) }.also {
77
+ constructor = it
78
+ }
79
+ }
80
+
81
+ inline fun <reified P0, reified P1, reified P2, reified P3, reified P4> Constructor(
82
+ crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4) -> SharedObjectType
83
+ ): SyncFunctionComponent {
84
+ return SyncFunctionComponent("constructor", arrayOf(typeOf<P0>().toAnyType(), typeOf<P1>().toAnyType(), typeOf<P2>().toAnyType(), typeOf<P3>().toAnyType(), typeOf<P4>().toAnyType())) { body(it[0] as P0, it[1] as P1, it[2] as P2, it[3] as P3, it[4] as P4) }.also {
85
+ constructor = it
86
+ }
87
+ }
88
+
89
+ inline fun <reified P0, reified P1, reified P2, reified P3, reified P4, reified P5> Constructor(
90
+ crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5) -> SharedObjectType
91
+ ): SyncFunctionComponent {
92
+ return SyncFunctionComponent("constructor", arrayOf(typeOf<P0>().toAnyType(), typeOf<P1>().toAnyType(), typeOf<P2>().toAnyType(), typeOf<P3>().toAnyType(), typeOf<P4>().toAnyType(), typeOf<P5>().toAnyType())) { body(it[0] as P0, it[1] as P1, it[2] as P2, it[3] as P3, it[4] as P4, it[5] as P5) }.also {
93
+ constructor = it
94
+ }
95
+ }
96
+
97
+ inline fun <reified P0, reified P1, reified P2, reified P3, reified P4, reified P5, reified P6> Constructor(
98
+ crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6) -> SharedObjectType
99
+ ): SyncFunctionComponent {
100
+ return SyncFunctionComponent("constructor", arrayOf(typeOf<P0>().toAnyType(), typeOf<P1>().toAnyType(), typeOf<P2>().toAnyType(), typeOf<P3>().toAnyType(), typeOf<P4>().toAnyType(), typeOf<P5>().toAnyType(), typeOf<P6>().toAnyType())) { body(it[0] as P0, it[1] as P1, it[2] as P2, it[3] as P3, it[4] as P4, it[5] as P5, it[6] as P6) }.also {
101
+ constructor = it
102
+ }
103
+ }
104
+
105
+ inline fun <reified P0, reified P1, reified P2, reified P3, reified P4, reified P5, reified P6, reified P7> Constructor(
106
+ crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7) -> SharedObjectType
107
+ ): SyncFunctionComponent {
108
+ return SyncFunctionComponent("constructor", arrayOf(typeOf<P0>().toAnyType(), typeOf<P1>().toAnyType(), typeOf<P2>().toAnyType(), typeOf<P3>().toAnyType(), typeOf<P4>().toAnyType(), typeOf<P5>().toAnyType(), typeOf<P6>().toAnyType(), typeOf<P7>().toAnyType())) { body(it[0] as P0, it[1] as P1, it[2] as P2, it[3] as P3, it[4] as P4, it[5] as P5, it[6] as P6, it[7] as P7) }.also {
109
+ constructor = it
110
+ }
111
+ }
112
+ }
@@ -0,0 +1,10 @@
1
+ package expo.modules.kotlin.classcomponent
2
+
3
+ import expo.modules.kotlin.functions.SyncFunctionComponent
4
+ import expo.modules.kotlin.objects.ObjectDefinitionData
5
+
6
+ class ClassDefinitionData(
7
+ val name: String,
8
+ val constructor: SyncFunctionComponent,
9
+ val objectDefinition: ObjectDefinitionData
10
+ )