expo-modules-core 1.2.6 → 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 +33 -4
  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 +18 -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 +34 -21
  42. package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +13 -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 -4
  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 +7 -8
  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
@@ -1,8 +1,11 @@
1
1
  package expo.modules.kotlin.jni
2
2
 
3
3
  import com.facebook.jni.HybridData
4
+ import com.facebook.react.bridge.Arguments
4
5
  import com.facebook.react.bridge.NativeMap
5
6
  import expo.modules.core.interfaces.DoNotStrip
7
+ import expo.modules.kotlin.AppContext
8
+ import expo.modules.kotlin.objects.ObjectDefinitionData
6
9
 
7
10
  /**
8
11
  * A class to communicate with CPP part of the [expo.modules.kotlin.modules.Module] class.
@@ -13,13 +16,35 @@ import expo.modules.core.interfaces.DoNotStrip
13
16
  */
14
17
  @Suppress("KotlinJniMissingFunction")
15
18
  @DoNotStrip
16
- class JavaScriptModuleObject(val name: String) {
19
+ class JavaScriptModuleObject(val name: String) : Destructible {
17
20
  // Has to be called "mHybridData" - fbjni uses it via reflection
18
21
  @DoNotStrip
19
22
  private val mHybridData = initHybrid()
20
23
 
21
24
  private external fun initHybrid(): HybridData
22
25
 
26
+ init {
27
+ JNIDeallocator.addReference(this)
28
+ }
29
+
30
+ fun initUsingObjectDefinition(appContext: AppContext, definition: ObjectDefinitionData) = apply {
31
+ val constants = definition.constantsProvider()
32
+ val convertedConstants = Arguments.makeNativeMap(constants)
33
+ exportConstants(convertedConstants)
34
+
35
+ definition
36
+ .functions
37
+ .forEach { function ->
38
+ function.attachToJSObject(appContext, this)
39
+ }
40
+
41
+ definition
42
+ .properties
43
+ .forEach { (_, prop) ->
44
+ prop.attachToJSObject(this)
45
+ }
46
+ }
47
+
23
48
  /**
24
49
  * Exports constants
25
50
  */
@@ -29,18 +54,30 @@ class JavaScriptModuleObject(val name: String) {
29
54
  * Register a promise-less function on the CPP module representation.
30
55
  * After calling this function, user can access the exported function in the JS code.
31
56
  */
32
- external fun registerSyncFunction(name: String, args: Int, desiredTypes: Array<ExpectedType>, body: JNIFunctionBody)
57
+ external fun registerSyncFunction(name: String, takesOwner: Boolean, args: Int, desiredTypes: Array<ExpectedType>, body: JNIFunctionBody)
33
58
 
34
59
  /**
35
60
  * Register a promise function on the CPP module representation.
36
61
  * After calling this function, user can access the exported function in the JS code.
37
62
  */
38
- external fun registerAsyncFunction(name: String, args: Int, desiredTypes: Array<ExpectedType>, body: JNIAsyncFunctionBody)
63
+ external fun registerAsyncFunction(name: String, takesOwner: Boolean, args: Int, desiredTypes: Array<ExpectedType>, body: JNIAsyncFunctionBody)
39
64
 
40
65
  external fun registerProperty(name: String, desiredType: ExpectedType, getter: JNIFunctionBody?, setter: JNIFunctionBody?)
41
66
 
67
+ external fun registerClass(name: String, classModule: JavaScriptModuleObject, takesOwner: Boolean, args: Int, desiredTypes: Array<ExpectedType>, body: JNIFunctionBody)
68
+
69
+ external fun registerViewPrototype(viewPrototype: JavaScriptModuleObject)
70
+
42
71
  @Throws(Throwable::class)
43
72
  protected fun finalize() {
73
+ deallocate()
74
+ }
75
+
76
+ override fun deallocate() {
44
77
  mHybridData.resetNative()
45
78
  }
79
+
80
+ override fun toString(): String {
81
+ return "JavaScriptModuleObject_$name"
82
+ }
46
83
  }
@@ -9,7 +9,12 @@ import expo.modules.core.interfaces.DoNotStrip
9
9
  */
10
10
  @Suppress("KotlinJniMissingFunction")
11
11
  @DoNotStrip
12
- open class JavaScriptObject @DoNotStrip internal constructor(@DoNotStrip private val mHybridData: HybridData) {
12
+ open class JavaScriptObject @DoNotStrip internal constructor(@DoNotStrip private val mHybridData: HybridData) : Destructible {
13
+ init {
14
+ @Suppress("LeakingThis")
15
+ JNIDeallocator.addReference(this)
16
+ }
17
+
13
18
  /**
14
19
  * The property descriptor options for the property being defined or modified.
15
20
  */
@@ -30,23 +35,34 @@ open class JavaScriptObject @DoNotStrip internal constructor(@DoNotStrip private
30
35
  Writable(1 shl 2),
31
36
  }
32
37
 
38
+ fun isValid() = mHybridData.isValid
39
+
33
40
  external fun hasProperty(name: String): Boolean
34
41
  external fun getProperty(name: String): JavaScriptValue
35
- external fun getPropertyNames(): Array<String>
36
42
 
43
+ external fun getPropertyNames(): Array<String>
37
44
  private external fun setBoolProperty(name: String, value: Boolean)
38
45
  private external fun setDoubleProperty(name: String, value: Double)
39
46
  private external fun setStringProperty(name: String, value: String?)
40
47
  private external fun setJSValueProperty(name: String, value: JavaScriptValue?)
41
48
  private external fun setJSObjectProperty(name: String, value: JavaScriptObject?)
42
- private external fun unsetProperty(name: String)
43
49
 
50
+ private external fun unsetProperty(name: String)
44
51
  private external fun defineBoolProperty(name: String, value: Boolean, options: Int)
45
52
  private external fun defineDoubleProperty(name: String, value: Double, options: Int)
46
53
  private external fun defineStringProperty(name: String, value: String?, options: Int)
47
54
  private external fun defineJSValueProperty(name: String, value: JavaScriptValue?, options: Int)
55
+
48
56
  private external fun defineJSObjectProperty(name: String, value: JavaScriptObject?, options: Int)
49
57
 
58
+ private external fun defineNativeDeallocator(deallocator: JNIFunctionBody)
59
+
60
+ internal fun defineDeallocator(deallocator: () -> Unit) {
61
+ defineNativeDeallocator {
62
+ deallocator()
63
+ }
64
+ }
65
+
50
66
  fun setProperty(name: String, value: Boolean) = setBoolProperty(name, value)
51
67
  fun setProperty(name: String, value: Int) = setDoubleProperty(name, value.toDouble())
52
68
  fun setProperty(name: String, value: Double) = setDoubleProperty(name, value)
@@ -103,6 +119,10 @@ open class JavaScriptObject @DoNotStrip internal constructor(@DoNotStrip private
103
119
 
104
120
  @Throws(Throwable::class)
105
121
  protected fun finalize() {
122
+ deallocate()
123
+ }
124
+
125
+ override fun deallocate() {
106
126
  mHybridData.resetNative()
107
127
  }
108
128
  }
@@ -2,6 +2,7 @@ package expo.modules.kotlin.jni
2
2
 
3
3
  import com.facebook.jni.HybridData
4
4
  import expo.modules.core.interfaces.DoNotStrip
5
+ import kotlin.reflect.typeOf
5
6
 
6
7
  /**
7
8
  * A Kotlin representation of jsi::Value.
@@ -9,7 +10,12 @@ import expo.modules.core.interfaces.DoNotStrip
9
10
  */
10
11
  @Suppress("KotlinJniMissingFunction")
11
12
  @DoNotStrip
12
- class JavaScriptValue @DoNotStrip private constructor(@DoNotStrip private val mHybridData: HybridData) {
13
+ class JavaScriptValue @DoNotStrip private constructor(@DoNotStrip private val mHybridData: HybridData) : Destructible {
14
+ init {
15
+ JNIDeallocator.addReference(this)
16
+ }
17
+
18
+ fun isValid() = mHybridData.isValid
13
19
  external fun kind(): String
14
20
 
15
21
  external fun isNull(): Boolean
@@ -30,12 +36,31 @@ class JavaScriptValue @DoNotStrip private constructor(@DoNotStrip private val mH
30
36
  external fun getArray(): Array<JavaScriptValue>
31
37
  external fun getTypedArray(): JavaScriptTypedArray
32
38
 
39
+ private external fun <T : Any?> jniGetFunction(): JavaScriptFunction<T>
40
+ @PublishedApi
41
+ internal fun <T : Any?> internalJniGetFunction(): JavaScriptFunction<T> = jniGetFunction()
42
+ inline fun <reified ReturnType : Any?> getFunction(): JavaScriptFunction<ReturnType> {
43
+ return internalJniGetFunction<ReturnType>().apply {
44
+ returnType = typeOf<ReturnType>()
45
+ }
46
+ }
47
+ @JvmName("getVoidFunction")
48
+ fun getFunction(): JavaScriptFunction<Unit> {
49
+ return internalJniGetFunction<Unit>().apply {
50
+ returnType = typeOf<Unit>()
51
+ }
52
+ }
53
+
33
54
  fun getInt() = getDouble().toInt()
34
55
  fun getLong() = getDouble().toLong()
35
56
  fun getFloat() = getDouble().toFloat()
36
57
 
37
58
  @Throws(Throwable::class)
38
59
  protected fun finalize() {
60
+ deallocate()
61
+ }
62
+
63
+ override fun deallocate() {
39
64
  mHybridData.resetNative()
40
65
  }
41
66
  }
@@ -1,11 +1,9 @@
1
1
  package expo.modules.kotlin.modules
2
2
 
3
3
  import android.os.Bundle
4
- import expo.modules.core.errors.ModuleDestroyedException
5
4
  import expo.modules.kotlin.AppContext
6
5
  import expo.modules.kotlin.providers.AppContextProvider
7
6
  import kotlinx.coroutines.CoroutineScope
8
- import kotlinx.coroutines.cancel
9
7
 
10
8
  abstract class Module : AppContextProvider {
11
9
 
@@ -25,9 +23,6 @@ abstract class Module : AppContextProvider {
25
23
  @PublishedApi
26
24
  internal lateinit var coroutineScopeDelegate: Lazy<CoroutineScope>
27
25
 
28
- @Deprecated(message = "Use a scope from the AppContext", replaceWith = ReplaceWith("appContext.modulesQueue"))
29
- val coroutineScope get() = coroutineScopeDelegate.value
30
-
31
26
  fun sendEvent(name: String, body: Bundle? = Bundle.EMPTY) {
32
27
  moduleEventEmitter?.emit(name, body)
33
28
  }
@@ -37,12 +32,6 @@ abstract class Module : AppContextProvider {
37
32
  }
38
33
 
39
34
  abstract fun definition(): ModuleDefinitionData
40
-
41
- internal fun cleanUp() {
42
- if (coroutineScopeDelegate.isInitialized()) {
43
- coroutineScope.cancel(ModuleDestroyedException())
44
- }
45
- }
46
35
  }
47
36
 
48
37
  @Suppress("FunctionName")
@@ -6,6 +6,8 @@ import android.app.Activity
6
6
  import android.content.Intent
7
7
  import android.view.View
8
8
  import expo.modules.kotlin.activityresult.AppContextActivityResultCaller
9
+ import expo.modules.kotlin.classcomponent.ClassComponentBuilder
10
+ import expo.modules.kotlin.classcomponent.ClassDefinitionData
9
11
  import expo.modules.kotlin.events.BasicEventListener
10
12
  import expo.modules.kotlin.events.EventListener
11
13
  import expo.modules.kotlin.events.EventListenerWithPayload
@@ -13,10 +15,11 @@ import expo.modules.kotlin.events.EventListenerWithSenderAndPayload
13
15
  import expo.modules.kotlin.events.EventName
14
16
  import expo.modules.kotlin.events.OnActivityResultPayload
15
17
  import expo.modules.kotlin.objects.ObjectDefinitionBuilder
18
+ import expo.modules.kotlin.sharedobjects.SharedObject
16
19
  import expo.modules.kotlin.views.ViewDefinitionBuilder
17
20
  import expo.modules.kotlin.views.ViewManagerDefinition
18
- import expo.modules.kotlin.views.ViewManagerDefinitionBuilder
19
21
  import kotlin.reflect.KClass
22
+ import kotlin.reflect.typeOf
20
23
 
21
24
  @DefinitionMarker
22
25
  class ModuleDefinitionBuilder(@PublishedApi internal val module: Module? = null) : ObjectDefinitionBuilder() {
@@ -31,6 +34,9 @@ class ModuleDefinitionBuilder(@PublishedApi internal val module: Module? = null)
31
34
  @PublishedApi
32
35
  internal var registerContracts: (suspend AppContextActivityResultCaller.() -> Unit)? = null
33
36
 
37
+ @PublishedApi
38
+ internal var classData = mutableListOf<ClassDefinitionData>()
39
+
34
40
  fun buildModule(): ModuleDefinitionData {
35
41
  val moduleName = name ?: module?.javaClass?.simpleName
36
42
 
@@ -39,7 +45,8 @@ class ModuleDefinitionBuilder(@PublishedApi internal val module: Module? = null)
39
45
  buildObject(),
40
46
  viewManagerDefinition,
41
47
  eventListeners,
42
- registerContracts
48
+ registerContracts,
49
+ classData
43
50
  )
44
51
  }
45
52
 
@@ -53,22 +60,10 @@ class ModuleDefinitionBuilder(@PublishedApi internal val module: Module? = null)
53
60
  /**
54
61
  * Creates the view manager definition that scopes other view-related definitions.
55
62
  */
56
- @Deprecated(message = "Use a `View` component instead.")
57
- inline fun ViewManager(body: ViewManagerDefinitionBuilder.() -> Unit) {
63
+ inline fun <reified T : View> View(viewClass: KClass<T>, body: ViewDefinitionBuilder<T>.() -> Unit) {
58
64
  require(viewManagerDefinition == null) { "The module definition may have exported only one view manager." }
59
65
 
60
- val viewManagerDefinitionBuilder = ViewManagerDefinitionBuilder()
61
- body.invoke(viewManagerDefinitionBuilder)
62
- viewManagerDefinition = viewManagerDefinitionBuilder.build()
63
- }
64
-
65
- /**
66
- * Creates the view manager definition that scopes other view-related definitions.
67
- */
68
- inline fun <T : View> View(viewType: KClass<T>, body: ViewDefinitionBuilder<T>.() -> Unit) {
69
- require(viewManagerDefinition == null) { "The module definition may have exported only one view manager." }
70
-
71
- val viewDefinitionBuilder = ViewDefinitionBuilder(viewType)
66
+ val viewDefinitionBuilder = ViewDefinitionBuilder(viewClass, typeOf<T>())
72
67
  body.invoke(viewDefinitionBuilder)
73
68
  viewManagerDefinition = viewDefinitionBuilder.build()
74
69
  }
@@ -129,4 +124,19 @@ class ModuleDefinitionBuilder(@PublishedApi internal val module: Module? = null)
129
124
  eventListeners[EventName.ON_ACTIVITY_RESULT] =
130
125
  EventListenerWithSenderAndPayload<Activity, OnActivityResultPayload>(EventName.ON_ACTIVITY_RESULT) { sender, payload -> body(sender, payload) }
131
126
  }
127
+
128
+ inline fun Class(name: String, body: ClassComponentBuilder<Unit>.() -> Unit = {}) {
129
+ val clazzBuilder = ClassComponentBuilder(name, Unit::class, typeOf<Unit>())
130
+ body.invoke(clazzBuilder)
131
+ classData.add(clazzBuilder.buildClass())
132
+ }
133
+
134
+ inline fun <reified SharedObjectType : SharedObject> Class(
135
+ sharedObjectClass: KClass<SharedObjectType>,
136
+ body: ClassComponentBuilder<SharedObjectType>.() -> Unit = {}
137
+ ) {
138
+ val clazzBuilder = ClassComponentBuilder(sharedObjectClass.java.simpleName, sharedObjectClass, typeOf<SharedObjectType>())
139
+ body.invoke(clazzBuilder)
140
+ classData.add(clazzBuilder.buildClass())
141
+ }
132
142
  }
@@ -1,6 +1,7 @@
1
1
  package expo.modules.kotlin.modules
2
2
 
3
3
  import expo.modules.kotlin.activityresult.AppContextActivityResultCaller
4
+ import expo.modules.kotlin.classcomponent.ClassDefinitionData
4
5
  import expo.modules.kotlin.events.EventListener
5
6
  import expo.modules.kotlin.events.EventName
6
7
  import expo.modules.kotlin.objects.ObjectDefinitionData
@@ -11,7 +12,8 @@ class ModuleDefinitionData(
11
12
  val objectDefinition: ObjectDefinitionData,
12
13
  val viewManagerDefinition: ViewManagerDefinition? = null,
13
14
  val eventListeners: Map<EventName, EventListener> = emptyMap(),
14
- val registerContracts: (suspend AppContextActivityResultCaller.() -> Unit)? = null
15
+ val registerContracts: (suspend AppContextActivityResultCaller.() -> Unit)? = null,
16
+ val classData: List<ClassDefinitionData> = emptyList()
15
17
  ) {
16
18
 
17
19
  val constantsProvider = objectDefinition.constantsProvider
@@ -0,0 +1,12 @@
1
+ package expo.modules.kotlin.sharedobjects
2
+
3
+ import expo.modules.core.interfaces.DoNotStrip
4
+
5
+ @DoNotStrip
6
+ open class SharedObject {
7
+ /**
8
+ * An identifier of the native shared object that maps to the JavaScript object.
9
+ * When the object is not linked with any JavaScript object, its value is 0.
10
+ */
11
+ internal var sharedObjectId: SharedObjectId = SharedObjectId(0)
12
+ }
@@ -0,0 +1,62 @@
1
+ package expo.modules.kotlin.sharedobjects
2
+
3
+ import expo.modules.kotlin.jni.JavaScriptObject
4
+
5
+ @JvmInline
6
+ value class SharedObjectId(val value: Int)
7
+
8
+ // TODO(@lukmccall): use weak ref to hold js object
9
+ typealias SharedObjectPair = Pair<SharedObject, JavaScriptObject>
10
+
11
+ const val sharedObjectIdPropertyName = "__expo_shared_object_id__"
12
+
13
+ class SharedObjectRegistry {
14
+ private var currentId: SharedObjectId = SharedObjectId(1)
15
+
16
+ internal var pairs = mutableMapOf<SharedObjectId, SharedObjectPair>()
17
+
18
+ private fun pullNextId(): SharedObjectId {
19
+ val current = currentId
20
+ currentId = SharedObjectId(current.value + 1)
21
+ return current
22
+ }
23
+
24
+ internal fun add(native: SharedObject, js: JavaScriptObject): SharedObjectId {
25
+ val id = pullNextId()
26
+ native.sharedObjectId = id
27
+ js.defineProperty(sharedObjectIdPropertyName, id.value)
28
+
29
+ js.defineDeallocator {
30
+ delete(id)
31
+ }
32
+
33
+ pairs[id] = native to js
34
+ return id
35
+ }
36
+
37
+ internal fun delete(id: SharedObjectId) {
38
+ pairs.remove(id)?.let { (native, js) ->
39
+ native.sharedObjectId = SharedObjectId(0)
40
+ if (js.isValid()) {
41
+ js.defineProperty(sharedObjectIdPropertyName, 0)
42
+ }
43
+ }
44
+ }
45
+
46
+ internal fun toNativeObject(id: SharedObjectId): SharedObject? {
47
+ return pairs[id]?.first
48
+ }
49
+
50
+ internal fun toNativeObject(js: JavaScriptObject): SharedObject? {
51
+ if (!js.hasProperty(sharedObjectIdPropertyName)) {
52
+ return null
53
+ }
54
+
55
+ val id = SharedObjectId(js.getProperty(sharedObjectIdPropertyName).getInt())
56
+ return pairs[id]?.first
57
+ }
58
+
59
+ internal fun toJavaScriptObjet(native: SharedObject): JavaScriptObject? {
60
+ return pairs[native.sharedObjectId]?.second
61
+ }
62
+ }
@@ -0,0 +1,27 @@
1
+ package expo.modules.kotlin.sharedobjects
2
+
3
+ import expo.modules.kotlin.AppContext
4
+ import expo.modules.kotlin.exception.InvalidSharedObjectException
5
+ import expo.modules.kotlin.jni.CppType
6
+ import expo.modules.kotlin.jni.ExpectedType
7
+ import expo.modules.kotlin.toStrongReference
8
+ import expo.modules.kotlin.types.NullAwareTypeConverter
9
+ import kotlin.reflect.KType
10
+
11
+ class SharedObjectTypeConverter<T : SharedObject>(
12
+ val type: KType
13
+ ) : NullAwareTypeConverter<T>(type.isMarkedNullable) {
14
+ @Suppress("UNCHECKED_CAST")
15
+ override fun convertNonOptional(value: Any, context: AppContext?): T {
16
+ val id = SharedObjectId(value as Int)
17
+ val appContext = context.toStrongReference()
18
+ val result = appContext.sharedObjectRegistry.toNativeObject(id)
19
+ ?: throw InvalidSharedObjectException(type)
20
+
21
+ return result as T
22
+ }
23
+
24
+ override fun getCppRequiredTypes() = ExpectedType(CppType.SHARED_OBJECT_ID)
25
+
26
+ override fun isTrivial(): Boolean = false
27
+ }
@@ -1,5 +1,6 @@
1
1
  package expo.modules.kotlin.types
2
2
 
3
+ import expo.modules.kotlin.AppContext
3
4
  import expo.modules.kotlin.jni.ExpectedType
4
5
  import kotlin.reflect.KType
5
6
 
@@ -10,7 +11,7 @@ class AnyType(val kType: KType) {
10
11
  TypeConverterProviderImpl.obtainTypeConverter(kType)
11
12
  }
12
13
 
13
- fun convert(value: Any?): Any? = converter.convert(value)
14
+ fun convert(value: Any?, appContext: AppContext? = null): Any? = converter.convert(value, appContext)
14
15
 
15
16
  fun getCppRequiredTypes(): ExpectedType = converter.getCppRequiredTypes()
16
17
  }
@@ -1,5 +1,6 @@
1
1
  package expo.modules.kotlin.types
2
2
 
3
+ import expo.modules.kotlin.AppContext
3
4
  import expo.modules.kotlin.apifeatures.EitherType
4
5
  import expo.modules.kotlin.jni.ExpectedType
5
6
  import expo.modules.kotlin.jni.SingleType
@@ -9,7 +10,7 @@ import kotlin.reflect.KType
9
10
  class EitherTypeConverter<FirstType : Any, SecondType : Any>(
10
11
  converterProvider: TypeConverterProvider,
11
12
  eitherType: KType,
12
- ) : TypeConverter<Either<FirstType, SecondType>>(eitherType.isMarkedNullable) {
13
+ ) : NullAwareTypeConverter<Either<FirstType, SecondType>>(eitherType.isMarkedNullable) {
13
14
  private val firstJavaType = requireNotNull(eitherType.arguments.getOrNull(0)?.type)
14
15
  private val secondJavaType = requireNotNull(eitherType.arguments.getOrNull(1)?.type)
15
16
  private val firstTypeConverter = converterProvider.obtainTypeConverter(
@@ -21,7 +22,7 @@ class EitherTypeConverter<FirstType : Any, SecondType : Any>(
21
22
  private val firstType = firstTypeConverter.getCppRequiredTypes()
22
23
  private val secondType = secondTypeConverter.getCppRequiredTypes()
23
24
 
24
- override fun convertNonOptional(value: Any): Either<FirstType, SecondType> {
25
+ override fun convertNonOptional(value: Any, context: AppContext?): Either<FirstType, SecondType> {
25
26
  val convertValueIfNeeded = Convert@{ types: Array<out SingleType>, converter: TypeConverter<*> ->
26
27
  for (singleType in types) {
27
28
  if (singleType.expectedCppType.clazz.isInstance(value)) {
@@ -54,7 +55,7 @@ class EitherTypeConverter<FirstType : Any, SecondType : Any>(
54
55
  class EitherOfThreeTypeConverter<FirstType : Any, SecondType : Any, ThirdType : Any>(
55
56
  converterProvider: TypeConverterProvider,
56
57
  eitherType: KType,
57
- ) : TypeConverter<EitherOfThree<FirstType, SecondType, ThirdType>>(eitherType.isMarkedNullable) {
58
+ ) : NullAwareTypeConverter<EitherOfThree<FirstType, SecondType, ThirdType>>(eitherType.isMarkedNullable) {
58
59
  private val firstJavaType = requireNotNull(eitherType.arguments.getOrNull(0)?.type)
59
60
  private val secondJavaType = requireNotNull(eitherType.arguments.getOrNull(1)?.type)
60
61
  private val thirdJavaType = requireNotNull(eitherType.arguments.getOrNull(2)?.type)
@@ -71,7 +72,7 @@ class EitherOfThreeTypeConverter<FirstType : Any, SecondType : Any, ThirdType :
71
72
  private val secondType = secondTypeConverter.getCppRequiredTypes()
72
73
  private val thirdType = thirdTypeConverter.getCppRequiredTypes()
73
74
 
74
- override fun convertNonOptional(value: Any): EitherOfThree<FirstType, SecondType, ThirdType> {
75
+ override fun convertNonOptional(value: Any, context: AppContext?): EitherOfThree<FirstType, SecondType, ThirdType> {
75
76
  val convertValueIfNeeded = Convert@{ types: Array<out SingleType>, converter: TypeConverter<*> ->
76
77
  for (singleType in types) {
77
78
  if (singleType.expectedCppType.clazz.isInstance(value)) {
@@ -105,7 +106,7 @@ class EitherOfThreeTypeConverter<FirstType : Any, SecondType : Any, ThirdType :
105
106
  class EitherOfFourTypeConverter<FirstType : Any, SecondType : Any, ThirdType : Any, FourthType : Any>(
106
107
  converterProvider: TypeConverterProvider,
107
108
  eitherType: KType,
108
- ) : TypeConverter<EitherOfFour<FirstType, SecondType, ThirdType, FourthType>>(eitherType.isMarkedNullable) {
109
+ ) : NullAwareTypeConverter<EitherOfFour<FirstType, SecondType, ThirdType, FourthType>>(eitherType.isMarkedNullable) {
109
110
  private val firstJavaType = requireNotNull(eitherType.arguments.getOrNull(0)?.type)
110
111
  private val secondJavaType = requireNotNull(eitherType.arguments.getOrNull(1)?.type)
111
112
  private val thirdJavaType = requireNotNull(eitherType.arguments.getOrNull(2)?.type)
@@ -127,7 +128,7 @@ class EitherOfFourTypeConverter<FirstType : Any, SecondType : Any, ThirdType : A
127
128
  private val thirdType = thirdTypeConverter.getCppRequiredTypes()
128
129
  private val fourthType = fourthTypeConverter.getCppRequiredTypes()
129
130
 
130
- override fun convertNonOptional(value: Any): EitherOfFour<FirstType, SecondType, ThirdType, FourthType> {
131
+ override fun convertNonOptional(value: Any, context: AppContext?): EitherOfFour<FirstType, SecondType, ThirdType, FourthType> {
131
132
  val convertValueIfNeeded = Convert@{ types: Array<out SingleType>, converter: TypeConverter<*> ->
132
133
  for (singleType in types) {
133
134
  if (singleType.expectedCppType.clazz.isInstance(value)) {
@@ -0,0 +1,22 @@
1
+ package expo.modules.kotlin.types
2
+
3
+ import expo.modules.kotlin.AppContext
4
+ import expo.modules.kotlin.jni.CppType
5
+ import expo.modules.kotlin.jni.ExpectedType
6
+ import expo.modules.kotlin.jni.JavaScriptFunction
7
+ import kotlin.reflect.KType
8
+
9
+ class JavaScriptFunctionTypeConverter<T : Any>(
10
+ val type: KType
11
+ ) : NullAwareTypeConverter<JavaScriptFunction<T>>(type.isMarkedNullable) {
12
+ override fun convertNonOptional(value: Any, context: AppContext?): JavaScriptFunction<T> {
13
+ @Suppress("UNCHECKED_CAST")
14
+ val jsFunction = value as JavaScriptFunction<T>
15
+ jsFunction.returnType = requireNotNull(type.arguments.first().type)
16
+ return jsFunction
17
+ }
18
+
19
+ override fun getCppRequiredTypes(): ExpectedType = ExpectedType(CppType.JS_FUNCTION)
20
+
21
+ override fun isTrivial(): Boolean = false
22
+ }
@@ -1,6 +1,7 @@
1
1
  package expo.modules.kotlin.types
2
2
 
3
3
  import com.facebook.react.bridge.Dynamic
4
+ import expo.modules.kotlin.AppContext
4
5
  import expo.modules.kotlin.exception.NullArgumentException
5
6
  import expo.modules.kotlin.exception.UnsupportedClass
6
7
  import expo.modules.kotlin.jni.ExpectedType
@@ -9,30 +10,11 @@ import expo.modules.kotlin.jni.ExpectedType
9
10
  * Basic type converter. It has to handle two different inputs - [Dynamic] and [Any].
10
11
  * The first one is used in the bridge implementation. The second one is used in the JSI.
11
12
  */
12
- abstract class TypeConverter<Type : Any>(
13
- /**
14
- * Whether `null` can be assigned to the desired type.
15
- */
16
- private val isOptional: Boolean
17
- ) {
13
+ abstract class TypeConverter<Type : Any> {
18
14
  /**
19
15
  * Tries to convert from [Any]? (can be also [Dynamic]) to the desired type.
20
16
  */
21
- open fun convert(value: Any?): Type? {
22
- if (value == null || value is Dynamic && value.isNull) {
23
- if (isOptional) {
24
- return null
25
- }
26
- throw NullArgumentException()
27
- }
28
- return convertNonOptional(value)
29
- }
30
-
31
- /**
32
- * Tries to convert from [Any] to the desired type.
33
- * We know in that place that we're not dealing with `null`.
34
- */
35
- abstract fun convertNonOptional(value: Any): Type
17
+ abstract fun convert(value: Any?, context: AppContext? = null): Type?
36
18
 
37
19
  /**
38
20
  * Returns a list of [ExpectedType] types that can be converted to the desired type.
@@ -40,7 +22,7 @@ abstract class TypeConverter<Type : Any>(
40
22
  * For instance js object can be pass as [Map] or [expo.modules.kotlin.jni.JavaScriptObject].
41
23
  * This value tells us which one we should choose.
42
24
  */
43
- abstract fun getCppRequiredTypes(): ExpectedType
25
+ open fun getCppRequiredTypes(): ExpectedType = ExpectedType.forAny()
44
26
 
45
27
  /**
46
28
  * Checks if the current converter is a trivial one.
@@ -50,13 +32,36 @@ abstract class TypeConverter<Type : Any>(
50
32
  open fun isTrivial(): Boolean = true
51
33
  }
52
34
 
35
+ abstract class NullAwareTypeConverter<Type : Any>(
36
+ /**
37
+ * Whether `null` can be assigned to the desired type.
38
+ */
39
+ private val isOptional: Boolean
40
+ ) : TypeConverter<Type>() {
41
+ override fun convert(value: Any?, context: AppContext?): Type? {
42
+ if (value == null || value is Dynamic && value.isNull) {
43
+ if (isOptional) {
44
+ return null
45
+ }
46
+ throw NullArgumentException()
47
+ }
48
+ return convertNonOptional(value, context)
49
+ }
50
+
51
+ /**
52
+ * Tries to convert from [Any] to the desired type.
53
+ * We know in that place that we're not dealing with `null`.
54
+ */
55
+ abstract fun convertNonOptional(value: Any, context: AppContext?): Type
56
+ }
57
+
53
58
  /**
54
59
  * A helper class to make a clear separation between [Any] and [Dynamic].
55
60
  * Right it is used as a default base class for all converters, but this will change when we
56
61
  * stop using the bridge to pass data between JS and Kotlin.
57
62
  */
58
- abstract class DynamicAwareTypeConverters<T : Any>(isOptional: Boolean) : TypeConverter<T>(isOptional) {
59
- override fun convertNonOptional(value: Any): T =
63
+ abstract class DynamicAwareTypeConverters<T : Any>(isOptional: Boolean) : NullAwareTypeConverter<T>(isOptional) {
64
+ override fun convertNonOptional(value: Any, context: AppContext?): T =
60
65
  if (value is Dynamic) {
61
66
  convertFromDynamic(value)
62
67
  } else {
@@ -75,6 +80,7 @@ inline fun <reified T : Any> createTrivialTypeConverter(
75
80
  return object : DynamicAwareTypeConverters<T>(isOptional) {
76
81
  override fun convertFromDynamic(value: Dynamic): T = dynamicFallback(value)
77
82
  override fun getCppRequiredTypes(): ExpectedType = cppRequireType
83
+
78
84
  @Suppress("UNCHECKED_CAST")
79
85
  override fun convertFromAny(value: Any): T = value as T
80
86
  }