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
@@ -0,0 +1,53 @@
1
+ package expo.modules.kotlin.views
2
+
3
+ import com.facebook.react.bridge.ReadableMap
4
+ import com.facebook.react.bridge.ReadableMapKeySetIterator
5
+ import expo.modules.kotlin.Filter
6
+ import expo.modules.kotlin.FilteredIterator
7
+
8
+ class FilteredReadableMapKeySetIterator(
9
+ private val iterator: ReadableMapKeySetIterator,
10
+ private val filter: Filter<String>
11
+ ) : ReadableMapKeySetIterator {
12
+ private var next: String? = null
13
+
14
+ init {
15
+ this.findNext()
16
+ }
17
+
18
+ override fun hasNextKey(): Boolean {
19
+ return next != null
20
+ }
21
+
22
+ override fun nextKey(): String {
23
+ val returnValue = next!!
24
+ this.findNext()
25
+ return returnValue
26
+ }
27
+
28
+ private fun findNext() {
29
+ while (iterator.hasNextKey()) {
30
+ val next = iterator.nextKey()
31
+ this.next = next
32
+ if (filter.apply(next)) {
33
+ return
34
+ }
35
+ }
36
+ next = null
37
+ }
38
+ }
39
+
40
+ class FilteredReadableMap(
41
+ private val backingMap: ReadableMap,
42
+ private val filteredKeys: List<String>
43
+ ) : ReadableMap by backingMap {
44
+ override fun getEntryIterator(): Iterator<Map.Entry<String, Any>> =
45
+ FilteredIterator(backingMap.entryIterator) {
46
+ !filteredKeys.contains(it.key)
47
+ }
48
+
49
+ override fun keySetIterator(): ReadableMapKeySetIterator =
50
+ FilteredReadableMapKeySetIterator(backingMap.keySetIterator()) {
51
+ !filteredKeys.contains(it)
52
+ }
53
+ }
@@ -2,11 +2,11 @@ package expo.modules.kotlin.views
2
2
 
3
3
  import android.view.View
4
4
  import android.view.ViewGroup
5
- import com.facebook.react.bridge.ReadableMap
6
5
  import com.facebook.react.common.MapBuilder
6
+ import com.facebook.react.uimanager.ReactStylesDiffMap
7
7
  import com.facebook.react.uimanager.ThemedReactContext
8
8
  import com.facebook.react.uimanager.ViewGroupManager
9
- import com.facebook.react.uimanager.annotations.ReactProp
9
+ import com.facebook.react.uimanager.getBackingMap
10
10
  import expo.modules.core.utilities.ifNull
11
11
 
12
12
  class GroupViewManagerWrapper(
@@ -17,9 +17,29 @@ class GroupViewManagerWrapper(
17
17
  override fun createViewInstance(reactContext: ThemedReactContext): ViewGroup =
18
18
  viewWrapperDelegate.createView(reactContext) as ViewGroup
19
19
 
20
- @ReactProp(name = "proxiedProperties")
21
- fun setProxiedProperties(view: View, proxiedProperties: ReadableMap) {
22
- viewWrapperDelegate.setProxiedProperties(view, proxiedProperties)
20
+ override fun updateProperties(viewToUpdate: ViewGroup, props: ReactStylesDiffMap) {
21
+ val propsMap = props.getBackingMap()
22
+ // Updates expo related properties.
23
+ val handledProps = viewWrapperDelegate.updateProperties(viewToUpdate, propsMap)
24
+ // Updates remaining props using RN implementation.
25
+ // To not triggered undefined setters we filtrated already handled properties.
26
+ super.updateProperties(
27
+ viewToUpdate,
28
+ ReactStylesDiffMap(FilteredReadableMap(propsMap, handledProps))
29
+ )
30
+ }
31
+
32
+ override fun onAfterUpdateTransaction(view: ViewGroup) {
33
+ super.onAfterUpdateTransaction(view)
34
+ viewWrapperDelegate.onViewDidUpdateProps(view)
35
+ }
36
+
37
+ override fun getNativeProps(): MutableMap<String, String> {
38
+ val props = super.getNativeProps()
39
+ viewWrapperDelegate.props.forEach { (key, prop) ->
40
+ props[key] = prop.type.kType.toString()
41
+ }
42
+ return props
23
43
  }
24
44
 
25
45
  override fun onDropViewInstance(view: ViewGroup) {
@@ -1,11 +1,11 @@
1
1
  package expo.modules.kotlin.views
2
2
 
3
3
  import android.view.View
4
- import com.facebook.react.bridge.ReadableMap
5
4
  import com.facebook.react.common.MapBuilder
5
+ import com.facebook.react.uimanager.ReactStylesDiffMap
6
6
  import com.facebook.react.uimanager.SimpleViewManager
7
7
  import com.facebook.react.uimanager.ThemedReactContext
8
- import com.facebook.react.uimanager.annotations.ReactProp
8
+ import com.facebook.react.uimanager.getBackingMap
9
9
 
10
10
  class SimpleViewManagerWrapper(
11
11
  override val viewWrapperDelegate: ViewManagerWrapperDelegate
@@ -15,9 +15,29 @@ class SimpleViewManagerWrapper(
15
15
  override fun createViewInstance(reactContext: ThemedReactContext): View =
16
16
  viewWrapperDelegate.createView(reactContext)
17
17
 
18
- @ReactProp(name = "proxiedProperties")
19
- fun setProxiedProperties(view: View, proxiedProperties: ReadableMap) {
20
- viewWrapperDelegate.setProxiedProperties(view, proxiedProperties)
18
+ override fun updateProperties(viewToUpdate: View, props: ReactStylesDiffMap) {
19
+ val propsMap = props.getBackingMap()
20
+ // Updates expo related properties.
21
+ val handledProps = viewWrapperDelegate.updateProperties(viewToUpdate, propsMap)
22
+ // Updates remaining props using RN implementation.
23
+ // To not triggered undefined setters we filtrated already handled properties.
24
+ super.updateProperties(
25
+ viewToUpdate,
26
+ ReactStylesDiffMap(FilteredReadableMap(propsMap, handledProps))
27
+ )
28
+ }
29
+
30
+ override fun onAfterUpdateTransaction(view: View) {
31
+ super.onAfterUpdateTransaction(view)
32
+ viewWrapperDelegate.onViewDidUpdateProps(view)
33
+ }
34
+
35
+ override fun getNativeProps(): MutableMap<String, String> {
36
+ val props = super.getNativeProps()
37
+ viewWrapperDelegate.props.forEach { (key, prop) ->
38
+ props[key] = prop.type.kType.toString()
39
+ }
40
+ return props
21
41
  }
22
42
 
23
43
  override fun onDropViewInstance(view: View) {
@@ -8,17 +8,27 @@ import android.util.Log
8
8
  import android.view.View
9
9
  import android.view.ViewGroup
10
10
  import expo.modules.kotlin.AppContext
11
+ import expo.modules.kotlin.Promise
11
12
  import expo.modules.kotlin.exception.CodedException
12
13
  import expo.modules.kotlin.exception.UnexpectedException
14
+ import expo.modules.kotlin.functions.AsyncFunction
15
+ import expo.modules.kotlin.functions.AsyncFunctionBuilder
16
+ import expo.modules.kotlin.functions.AsyncFunctionComponent
17
+ import expo.modules.kotlin.functions.AsyncFunctionWithPromiseComponent
18
+ import expo.modules.kotlin.functions.Queues
13
19
  import expo.modules.kotlin.modules.DefinitionMarker
14
20
  import expo.modules.kotlin.types.toAnyType
15
21
  import kotlin.reflect.KClass
16
22
  import kotlin.reflect.KFunction
23
+ import kotlin.reflect.KType
17
24
  import kotlin.reflect.full.primaryConstructor
18
25
  import kotlin.reflect.typeOf
19
26
 
20
27
  @DefinitionMarker
21
- class ViewDefinitionBuilder<T : View>(@PublishedApi internal val viewType: KClass<T>) {
28
+ class ViewDefinitionBuilder<T : View>(
29
+ @PublishedApi internal val viewClass: KClass<T>,
30
+ @PublishedApi internal val viewType: KType
31
+ ) {
22
32
  @PublishedApi
23
33
  internal var props = mutableMapOf<String, AnyViewProp>()
24
34
 
@@ -32,16 +42,29 @@ class ViewDefinitionBuilder<T : View>(@PublishedApi internal val viewType: KClas
32
42
  internal var viewGroupDefinition: ViewGroupDefinition? = null
33
43
  private var callbacksDefinition: CallbacksDefinition? = null
34
44
 
35
- fun build(): ViewManagerDefinition =
36
- ViewManagerDefinition(
45
+ @PublishedApi
46
+ internal var asyncFunctions = mutableMapOf<String, AsyncFunction>()
47
+
48
+ private var functionBuilders = mutableMapOf<String, AsyncFunctionBuilder>()
49
+
50
+ fun build(): ViewManagerDefinition {
51
+ val asyncFunctions = asyncFunctions + functionBuilders.mapValues { (_, value) -> value.build() }
52
+ asyncFunctions.forEach { (_, function) ->
53
+ function.runOnQueue(Queues.MAIN)
54
+ function.ownerType = viewType
55
+ }
56
+
57
+ return ViewManagerDefinition(
37
58
  viewFactory = createViewFactory(),
38
- viewType = viewType.java,
59
+ viewType = viewClass.java,
39
60
  props = props,
40
61
  onViewDestroys = onViewDestroys,
41
62
  callbacksDefinition = callbacksDefinition,
42
63
  viewGroupDefinition = viewGroupDefinition,
43
- onViewDidUpdateProps = onViewDidUpdateProps
64
+ onViewDidUpdateProps = onViewDidUpdateProps,
65
+ asyncFunctions = asyncFunctions.values.toList(),
44
66
  )
67
+ }
45
68
 
46
69
  /**
47
70
  * Creates view's lifecycle listener that is called right after the view isn't longer used by React Native.
@@ -127,7 +150,7 @@ class ViewDefinitionBuilder<T : View>(@PublishedApi internal val viewType: KClas
127
150
  * Creates the group view definition that scopes group view-related definitions.
128
151
  */
129
152
  inline fun <reified ParentType : ViewGroup> GroupView(body: ViewGroupDefinitionBuilder<ParentType>.() -> Unit) {
130
- assert(viewType == ParentType::class) { "Provided type and view type have to be the same." }
153
+ assert(viewClass == ParentType::class) { "Provided type and view type have to be the same." }
131
154
  require(viewGroupDefinition == null) { "The viewManager definition may have exported only one groupView definition." }
132
155
 
133
156
  val groupViewDefinitionBuilder = ViewGroupDefinitionBuilder<ParentType>()
@@ -135,8 +158,136 @@ class ViewDefinitionBuilder<T : View>(@PublishedApi internal val viewType: KClas
135
158
  viewGroupDefinition = groupViewDefinitionBuilder.build()
136
159
  }
137
160
 
161
+ @JvmName("AsyncFunctionWithoutArgs")
162
+ inline fun AsyncFunction(
163
+ name: String,
164
+ crossinline body: () -> Any?
165
+ ): AsyncFunction {
166
+ return AsyncFunctionComponent(name, arrayOf()) { body() }.also {
167
+ asyncFunctions[name] = it
168
+ }
169
+ }
170
+
171
+ inline fun <reified R> AsyncFunction(
172
+ name: String,
173
+ crossinline body: () -> R
174
+ ): AsyncFunction {
175
+ return AsyncFunctionComponent(name, arrayOf()) { body() }.also {
176
+ asyncFunctions[name] = it
177
+ }
178
+ }
179
+
180
+ inline fun <reified R, reified P0> AsyncFunction(
181
+ name: String,
182
+ crossinline body: (p0: P0) -> R
183
+ ): AsyncFunction {
184
+ return if (P0::class == Promise::class) {
185
+ AsyncFunctionWithPromiseComponent(name, arrayOf()) { _, promise -> body(promise as P0) }
186
+ } else {
187
+ AsyncFunctionComponent(name, arrayOf(typeOf<P0>().toAnyType())) { body(it[0] as P0) }
188
+ }.also {
189
+ it.ownerType = viewType
190
+ asyncFunctions[name] = it
191
+ }
192
+ }
193
+
194
+ inline fun <reified R, reified P0, reified P1> AsyncFunction(
195
+ name: String,
196
+ crossinline body: (p0: P0, p1: P1) -> R
197
+ ): AsyncFunction {
198
+ return if (P1::class == Promise::class) {
199
+ AsyncFunctionWithPromiseComponent(name, arrayOf(typeOf<P0>().toAnyType())) { args, promise -> body(args[0] as P0, promise as P1) }
200
+ } else {
201
+ AsyncFunctionComponent(name, arrayOf(typeOf<P0>().toAnyType(), typeOf<P1>().toAnyType())) { body(it[0] as P0, it[1] as P1) }
202
+ }.also {
203
+ asyncFunctions[name] = it
204
+ }
205
+ }
206
+
207
+ inline fun <reified R, reified P0, reified P1, reified P2> AsyncFunction(
208
+ name: String,
209
+ crossinline body: (p0: P0, p1: P1, p2: P2) -> R
210
+ ): AsyncFunction {
211
+ return if (P2::class == Promise::class) {
212
+ AsyncFunctionWithPromiseComponent(name, arrayOf(typeOf<P0>().toAnyType(), typeOf<P1>().toAnyType())) { args, promise -> body(args[0] as P0, args[1] as P1, promise as P2) }
213
+ } else {
214
+ AsyncFunctionComponent(name, arrayOf(typeOf<P0>().toAnyType(), typeOf<P1>().toAnyType(), typeOf<P2>().toAnyType())) { body(it[0] as P0, it[1] as P1, it[2] as P2) }
215
+ }.also {
216
+ asyncFunctions[name] = it
217
+ }
218
+ }
219
+
220
+ inline fun <reified R, reified P0, reified P1, reified P2, reified P3> AsyncFunction(
221
+ name: String,
222
+ crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3) -> R
223
+ ): AsyncFunction {
224
+ return if (P3::class == Promise::class) {
225
+ AsyncFunctionWithPromiseComponent(name, arrayOf(typeOf<P0>().toAnyType(), typeOf<P1>().toAnyType(), typeOf<P2>().toAnyType())) { args, promise -> body(args[0] as P0, args[1] as P1, args[2] as P2, promise as P3) }
226
+ } else {
227
+ AsyncFunctionComponent(name, 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) }
228
+ }.also {
229
+ asyncFunctions[name] = it
230
+ }
231
+ }
232
+
233
+ inline fun <reified R, reified P0, reified P1, reified P2, reified P3, reified P4> AsyncFunction(
234
+ name: String,
235
+ crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4) -> R
236
+ ): AsyncFunction {
237
+ return if (P4::class == Promise::class) {
238
+ AsyncFunctionWithPromiseComponent(name, arrayOf(typeOf<P0>().toAnyType(), typeOf<P1>().toAnyType(), typeOf<P2>().toAnyType(), typeOf<P3>().toAnyType())) { args, promise -> body(args[0] as P0, args[1] as P1, args[2] as P2, args[3] as P3, promise as P4) }
239
+ } else {
240
+ AsyncFunctionComponent(name, 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) }
241
+ }.also {
242
+ asyncFunctions[name] = it
243
+ }
244
+ }
245
+
246
+ inline fun <reified R, reified P0, reified P1, reified P2, reified P3, reified P4, reified P5> AsyncFunction(
247
+ name: String,
248
+ crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5) -> R
249
+ ): AsyncFunction {
250
+ return if (P5::class == Promise::class) {
251
+ AsyncFunctionWithPromiseComponent(name, arrayOf(typeOf<P0>().toAnyType(), typeOf<P1>().toAnyType(), typeOf<P2>().toAnyType(), typeOf<P3>().toAnyType(), typeOf<P4>().toAnyType())) { args, promise -> body(args[0] as P0, args[1] as P1, args[2] as P2, args[3] as P3, args[4] as P4, promise as P5) }
252
+ } else {
253
+ AsyncFunctionComponent(name, 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) }
254
+ }.also {
255
+ asyncFunctions[name] = it
256
+ }
257
+ }
258
+
259
+ inline fun <reified R, reified P0, reified P1, reified P2, reified P3, reified P4, reified P5, reified P6> AsyncFunction(
260
+ name: String,
261
+ crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6) -> R
262
+ ): AsyncFunction {
263
+ return if (P6::class == Promise::class) {
264
+ AsyncFunctionWithPromiseComponent(name, arrayOf(typeOf<P0>().toAnyType(), typeOf<P1>().toAnyType(), typeOf<P2>().toAnyType(), typeOf<P3>().toAnyType(), typeOf<P4>().toAnyType(), typeOf<P5>().toAnyType())) { args, promise -> body(args[0] as P0, args[1] as P1, args[2] as P2, args[3] as P3, args[4] as P4, args[5] as P5, promise as P6) }
265
+ } else {
266
+ AsyncFunctionComponent(name, 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) }
267
+ }.also {
268
+ asyncFunctions[name] = it
269
+ }
270
+ }
271
+
272
+ inline fun <reified R, reified P0, reified P1, reified P2, reified P3, reified P4, reified P5, reified P6, reified P7> AsyncFunction(
273
+ name: String,
274
+ crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7) -> R
275
+ ): AsyncFunction {
276
+ return if (P7::class == Promise::class) {
277
+ AsyncFunctionWithPromiseComponent(name, arrayOf(typeOf<P0>().toAnyType(), typeOf<P1>().toAnyType(), typeOf<P2>().toAnyType(), typeOf<P3>().toAnyType(), typeOf<P4>().toAnyType(), typeOf<P5>().toAnyType(), typeOf<P6>().toAnyType())) { args, promise -> body(args[0] as P0, args[1] as P1, args[2] as P2, args[3] as P3, args[4] as P4, args[5] as P5, args[6] as P6, promise as P7) }
278
+ } else {
279
+ AsyncFunctionComponent(name, 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) }
280
+ }.also {
281
+ asyncFunctions[name] = it
282
+ }
283
+ }
284
+
285
+ fun AsyncFunction(
286
+ name: String
287
+ ) = AsyncFunctionBuilder(name).also { functionBuilders[name] = it }
288
+
138
289
  private fun createViewFactory(): (Context, AppContext) -> View = viewFactory@{ context: Context, appContext: AppContext ->
139
- val primaryConstructor = requireNotNull(getPrimaryConstructor()) { "$viewType doesn't have a primary constructor" }
290
+ val primaryConstructor = requireNotNull(getPrimaryConstructor()) { "$viewClass doesn't have a primary constructor" }
140
291
  val args = primaryConstructor.parameters
141
292
 
142
293
  if (args.isEmpty()) {
@@ -174,7 +325,7 @@ class ViewDefinitionBuilder<T : View>(@PublishedApi internal val viewType: KClas
174
325
  }
175
326
 
176
327
  private fun handleFailureDuringViewCreation(context: Context, appContext: AppContext, e: Throwable): View {
177
- Log.e("ExpoModulesCore", "Couldn't create view of type $viewType", e)
328
+ Log.e("ExpoModulesCore", "Couldn't create view of type $viewClass", e)
178
329
 
179
330
  appContext.errorManager?.reportExceptionToLogBox(
180
331
  if (e is CodedException) {
@@ -187,12 +338,12 @@ class ViewDefinitionBuilder<T : View>(@PublishedApi internal val viewType: KClas
187
338
  }
188
339
 
189
340
  private fun getPrimaryConstructor(): KFunction<T>? {
190
- val kotlinContractor = viewType.primaryConstructor
341
+ val kotlinContractor = viewClass.primaryConstructor
191
342
  if (kotlinContractor != null) {
192
343
  return kotlinContractor
193
344
  }
194
345
 
195
346
  // Add compatibility with Java
196
- return viewType.constructors.firstOrNull()
347
+ return viewClass.constructors.firstOrNull()
197
348
  }
198
349
  }
@@ -76,70 +76,3 @@ class ViewGroupDefinitionBuilder<ParentType : ViewGroup> {
76
76
  }
77
77
  }
78
78
  }
79
-
80
- @Deprecated("Use `ViewGroupDefinitionBuilder` instead.")
81
- @DefinitionMarker
82
- class ViewGroupDefinitionLegacyBuilder {
83
- @PublishedApi
84
- internal var addViewAction: AddViewAction? = null
85
-
86
- @PublishedApi
87
- internal var getChildAtAction: GetChildAtAction? = null
88
-
89
- @PublishedApi
90
- internal var getChildCountAction: GetChildCountAction? = null
91
-
92
- @PublishedApi
93
- internal var removeViewAction: RemoveViewAction? = null
94
-
95
- @PublishedApi
96
- internal var removeViewAtAction: RemoveViewAtAction? = null
97
-
98
- fun build() = ViewGroupDefinition(
99
- addViewAction,
100
- getChildAtAction,
101
- getChildCountAction,
102
- removeViewAction,
103
- removeViewAtAction
104
- )
105
-
106
- inline fun <reified ParentViewType : ViewGroup, reified ChildViewType : View> AddChildView(
107
- noinline body: (parent: ParentViewType, child: ChildViewType, index: Int) -> Unit
108
- ) {
109
- addViewAction = { parent, child, index ->
110
- body(parent as ParentViewType, child as ChildViewType, index)
111
- }
112
- }
113
-
114
- inline fun <reified ParentViewType : ViewGroup> GetChildCount(
115
- noinline body: (view: ParentViewType) -> Int
116
- ) {
117
- getChildCountAction = { view ->
118
- body(view as ParentViewType)
119
- }
120
- }
121
-
122
- inline fun <reified ParentViewType : ViewGroup, reified ChildViewType : View> GetChildViewAt(
123
- noinline body: (view: ParentViewType, index: Int) -> ChildViewType?
124
- ) {
125
- getChildAtAction = { view, index ->
126
- body(view as ParentViewType, index)
127
- }
128
- }
129
-
130
- inline fun <reified ParentViewType : ViewGroup> RemoveChildViewAt(
131
- noinline body: (view: ParentViewType, index: Int) -> Unit
132
- ) {
133
- removeViewAtAction = { view, index ->
134
- body(view as ParentViewType, index)
135
- }
136
- }
137
-
138
- inline fun <reified ParentViewType : ViewGroup, reified ChildViewType : View> RemoveChildView(
139
- noinline body: (parent: ParentViewType, child: ChildViewType) -> Unit
140
- ) {
141
- removeViewAction = { view, child ->
142
- body(view as ParentViewType, child as ChildViewType)
143
- }
144
- }
145
- }
@@ -10,18 +10,20 @@ import expo.modules.core.ViewManager
10
10
  import expo.modules.kotlin.AppContext
11
11
  import expo.modules.kotlin.DynamicNull
12
12
  import expo.modules.kotlin.exception.CodedException
13
- import expo.modules.kotlin.exception.UnexpectedException
13
+ import expo.modules.kotlin.exception.toCodedException
14
+ import expo.modules.kotlin.functions.BaseAsyncFunctionComponent
14
15
  import expo.modules.kotlin.logger
15
16
  import expo.modules.kotlin.recycle
16
17
 
17
18
  class ViewManagerDefinition(
18
19
  private val viewFactory: (Context, AppContext) -> View,
19
20
  internal val viewType: Class<out View>,
20
- private val props: Map<String, AnyViewProp>,
21
+ internal val props: Map<String, AnyViewProp>,
21
22
  val onViewDestroys: ((View) -> Unit)? = null,
22
23
  val callbacksDefinition: CallbacksDefinition? = null,
23
24
  val viewGroupDefinition: ViewGroupDefinition? = null,
24
- val onViewDidUpdateProps: ((View) -> Unit)? = null
25
+ val onViewDidUpdateProps: ((View) -> Unit)? = null,
26
+ val asyncFunctions: List<BaseAsyncFunctionComponent> = emptyList()
25
27
  ) {
26
28
 
27
29
  fun createView(context: Context, appContext: AppContext): View = viewFactory(context, appContext)
@@ -53,10 +55,7 @@ class ViewManagerDefinition(
53
55
 
54
56
  handleException(
55
57
  onView,
56
- when (exception) {
57
- is CodedException -> exception
58
- else -> UnexpectedException(exception)
59
- }
58
+ exception.toCodedException()
60
59
  )
61
60
  }
62
61
  }
@@ -7,6 +7,9 @@ import com.facebook.react.common.MapBuilder
7
7
  import expo.modules.core.utilities.ifNull
8
8
  import expo.modules.kotlin.ModuleHolder
9
9
  import expo.modules.kotlin.events.normalizeEventName
10
+ import expo.modules.kotlin.exception.CodedException
11
+ import expo.modules.kotlin.exception.OnViewDidUpdatePropsException
12
+ import expo.modules.kotlin.exception.exceptionDecorator
10
13
  import expo.modules.kotlin.logger
11
14
  import expo.modules.kotlin.viewevent.ViewEventDelegate
12
15
  import kotlin.reflect.full.declaredMemberProperties
@@ -22,6 +25,9 @@ class ViewManagerWrapperDelegate(internal var moduleHolder: ModuleHolder) {
22
25
  val name: String
23
26
  get() = moduleHolder.name
24
27
 
28
+ val props: Map<String, AnyViewProp>
29
+ get() = definition.props
30
+
25
31
  fun createView(context: Context): View {
26
32
  return definition
27
33
  .createView(context, moduleHolder.module.appContext)
@@ -30,9 +36,40 @@ class ViewManagerWrapperDelegate(internal var moduleHolder: ModuleHolder) {
30
36
  }
31
37
  }
32
38
 
33
- fun setProxiedProperties(view: View, proxiedProperties: ReadableMap) {
34
- definition.setProps(proxiedProperties, view)
35
- definition.onViewDidUpdateProps?.invoke(view)
39
+ fun onViewDidUpdateProps(view: View) {
40
+ definition.onViewDidUpdateProps?.let {
41
+ try {
42
+ exceptionDecorator({ OnViewDidUpdatePropsException(view.javaClass.kotlin, it) }) {
43
+ it.invoke(view)
44
+ }
45
+ } catch (exception: CodedException) {
46
+ logger.error("❌ Error occurred when invoking 'onViewDidUpdateProps' on '${view.javaClass.simpleName}'", exception)
47
+ definition.handleException(view, exception)
48
+ }
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Updates the expo related properties of a given View based on a ReadableMap of property values.
54
+ *
55
+ * @param view The View whose properties should be updated.
56
+ * @param propsMap A ReadableMap of property values.
57
+ *
58
+ * @return A List of property names that were successfully updated.
59
+ */
60
+ fun updateProperties(view: View, propsMap: ReadableMap): List<String> {
61
+ val expoProps = props
62
+ val handledProps = mutableListOf<String>()
63
+ val iterator = propsMap.keySetIterator()
64
+
65
+ while (iterator.hasNextKey()) {
66
+ val key = iterator.nextKey()
67
+ expoProps[key]?.let { expoProp ->
68
+ expoProp.set(propsMap.getDynamic(key), view)
69
+ handledProps.add(key)
70
+ }
71
+ }
72
+ return handledProps
36
73
  }
37
74
 
38
75
  fun onDestroy(view: View) =
@@ -0,0 +1,44 @@
1
+ package expo.modules.kotlin.views
2
+
3
+ import android.view.View
4
+ import expo.modules.kotlin.AppContext
5
+ import expo.modules.kotlin.Utils
6
+ import expo.modules.kotlin.exception.Exceptions
7
+ import expo.modules.kotlin.exception.NullArgumentException
8
+ import expo.modules.kotlin.jni.CppType
9
+ import expo.modules.kotlin.jni.ExpectedType
10
+ import expo.modules.kotlin.toStrongReference
11
+ import expo.modules.kotlin.types.TypeConverter
12
+ import kotlin.reflect.KClass
13
+ import kotlin.reflect.KType
14
+
15
+ class ViewTypeConverter<T : View>(
16
+ val type: KType
17
+ ) : TypeConverter<T>() {
18
+
19
+ override fun convert(value: Any?, context: AppContext?): T? {
20
+ Utils.assertMainThread()
21
+ if (value == null) {
22
+ if (type.isMarkedNullable) {
23
+ return null
24
+ }
25
+ throw NullArgumentException()
26
+ }
27
+
28
+ val appContext = context.toStrongReference()
29
+ val viewTag = value as Int
30
+ val view = appContext.findView<T>(viewTag)
31
+ if (!type.isMarkedNullable && view == null) {
32
+ throw Exceptions.ViewNotFound(type.classifier as KClass<*>, viewTag)
33
+ }
34
+
35
+ return view
36
+ }
37
+
38
+ override fun getCppRequiredTypes(): ExpectedType = ExpectedType(
39
+ CppType.INT,
40
+ CppType.VIEW_TAG
41
+ )
42
+
43
+ override fun isTrivial(): Boolean = false
44
+ }
@@ -0,0 +1,45 @@
1
+ apply plugin: 'java-library'
2
+ apply plugin: 'org.jetbrains.kotlin.jvm'
3
+ apply plugin: 'kotlin'
4
+
5
+ group = 'host.exp.exponent'
6
+ version = '1.1.1'
7
+
8
+ buildscript {
9
+ def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
10
+ if (expoModulesCorePlugin.exists()) {
11
+ apply from: expoModulesCorePlugin
12
+ applyKotlinExpoModulesCorePlugin()
13
+ }
14
+
15
+ // Simple helper that allows the root project to override versions declared by this library.
16
+ ext.safeExtGet = { prop, fallback ->
17
+ rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
18
+ }
19
+
20
+ // Ensures backward compatibility
21
+ ext.getKotlinVersion = {
22
+ if (ext.has("kotlinVersion")) {
23
+ ext.kotlinVersion()
24
+ } else {
25
+ ext.safeExtGet("kotlinVersion", "1.6.10")
26
+ }
27
+ }
28
+
29
+ repositories {
30
+ mavenCentral()
31
+ }
32
+
33
+ dependencies {
34
+ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${getKotlinVersion()}")
35
+ }
36
+ }
37
+
38
+ java {
39
+ sourceCompatibility = JavaVersion.VERSION_1_8
40
+ targetCompatibility = JavaVersion.VERSION_1_8
41
+ }
42
+
43
+ dependencies {
44
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
45
+ }
@@ -0,0 +1,7 @@
1
+ package expo.modules.annotation
2
+
3
+ object Config {
4
+ const val packageNamePrefix = "expo.modules.generated."
5
+ const val classNameSuffix = "_ExpoTypeConverterProvider"
6
+ const val converterProviderFunctionName = "converter"
7
+ }
@@ -0,0 +1,7 @@
1
+ package expo.modules.annotation
2
+
3
+ import kotlin.reflect.KClass
4
+
5
+ @Retention(AnnotationRetention.SOURCE)
6
+ @Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
7
+ annotation class ConverterBinder(val clazz: KClass<*> = Nothing::class)