expo-modules-core 0.6.5 → 0.9.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.
- package/CHANGELOG.md +57 -0
- package/README.md +1 -1
- package/android/ExpoModulesCorePlugin.gradle +15 -0
- package/android/build.gradle +31 -15
- package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +5 -5
- package/android/src/main/java/expo/modules/adapters/react/services/UIManagerModuleWrapper.java +13 -0
- package/android/src/main/java/expo/modules/core/ViewManager.java +9 -0
- package/android/src/main/java/expo/modules/core/interfaces/JavaScriptContextProvider.java +4 -0
- package/android/src/main/java/expo/modules/core/interfaces/ReactActivityHandler.java +37 -1
- package/android/src/main/java/expo/modules/core/interfaces/ReactNativeHostHandler.java +30 -0
- package/android/src/main/java/expo/modules/core/interfaces/services/UIManager.java +2 -0
- package/android/src/main/java/expo/modules/kotlin/AppContext.kt +23 -5
- package/android/src/main/java/expo/modules/kotlin/DynamicExtenstions.kt +5 -3
- package/android/src/main/java/expo/modules/kotlin/KPromiseWrapper.kt +3 -8
- package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +24 -9
- package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +12 -7
- package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +23 -1
- package/android/src/main/java/expo/modules/kotlin/Promise.kt +1 -1
- package/android/src/main/java/expo/modules/kotlin/callbacks/Callback.kt +5 -0
- package/android/src/main/java/expo/modules/kotlin/callbacks/ViewCallback.kt +39 -0
- package/android/src/main/java/expo/modules/kotlin/callbacks/ViewCallbackDelegate.kt +27 -0
- package/android/src/main/java/expo/modules/kotlin/defaultmodules/ErrorManagerModule.kt +25 -0
- package/android/src/main/java/expo/modules/kotlin/events/EventEmitter.kt +13 -0
- package/android/src/main/java/expo/modules/kotlin/events/KModuleEventEmitterWrapper.kt +102 -0
- package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +93 -9
- package/android/src/main/java/expo/modules/kotlin/exception/ExceptionDecorator.kt +11 -0
- package/android/src/main/java/expo/modules/kotlin/{methods/AnyMethod.kt → functions/AnyFunction.kt} +18 -18
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +15 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +170 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromise.kt +15 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncSuspendFunction.kt +36 -0
- package/android/src/main/java/expo/modules/kotlin/modules/DefinitionMarker.kt +4 -0
- package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +17 -2
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +416 -43
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +2 -2
- package/android/src/main/java/expo/modules/kotlin/records/FieldValidator.kt +139 -0
- package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +71 -15
- package/android/src/main/java/expo/modules/kotlin/records/Required.kt +5 -0
- package/android/src/main/java/expo/modules/kotlin/records/ValidationBinder.kt +110 -0
- package/android/src/main/java/expo/modules/kotlin/records/Validators.kt +61 -0
- package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +11 -5
- package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverter.kt +35 -0
- package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverterHelper.kt +148 -0
- package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +10 -4
- package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +12 -6
- package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +29 -13
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +2 -1
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +9 -1
- package/android/src/main/java/expo/modules/kotlin/views/CallbacksDefinition.kt +3 -0
- package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +71 -0
- package/android/src/main/java/expo/modules/kotlin/views/SimpleViewManagerWrapper.kt +22 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinition.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinitionBuilder.kt +114 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +30 -2
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +81 -2
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +62 -2
- package/build/EventEmitter.d.ts +1 -0
- package/build/EventEmitter.d.ts.map +1 -0
- package/build/NativeModulesProxy.d.ts +1 -0
- package/build/NativeModulesProxy.d.ts.map +1 -0
- package/build/NativeModulesProxy.native.d.ts +1 -4
- package/build/NativeModulesProxy.native.d.ts.map +1 -0
- package/build/NativeModulesProxy.native.js +1 -14
- package/build/NativeModulesProxy.native.js.map +1 -1
- package/build/NativeModulesProxy.types.d.ts +1 -3
- package/build/NativeModulesProxy.types.d.ts.map +1 -0
- package/build/NativeModulesProxy.types.js.map +1 -1
- package/build/NativeViewManagerAdapter.d.ts +1 -0
- package/build/NativeViewManagerAdapter.d.ts.map +1 -0
- package/build/NativeViewManagerAdapter.native.d.ts +1 -0
- package/build/NativeViewManagerAdapter.native.d.ts.map +1 -0
- package/build/NativeViewManagerAdapter.native.js +9 -33
- package/build/NativeViewManagerAdapter.native.js.map +1 -1
- package/build/PermissionsHook.d.ts +1 -0
- package/build/PermissionsHook.d.ts.map +1 -0
- package/build/PermissionsInterface.d.ts +1 -0
- package/build/PermissionsInterface.d.ts.map +1 -0
- package/build/Platform.d.ts +1 -0
- package/build/Platform.d.ts.map +1 -0
- package/build/SyntheticPlatformEmitter.d.ts +1 -0
- package/build/SyntheticPlatformEmitter.d.ts.map +1 -0
- package/build/SyntheticPlatformEmitter.web.d.ts +1 -0
- package/build/SyntheticPlatformEmitter.web.d.ts.map +1 -0
- package/build/deprecate.d.ts +1 -0
- package/build/deprecate.d.ts.map +1 -0
- package/build/environment/browser.d.ts +1 -0
- package/build/environment/browser.d.ts.map +1 -0
- package/build/environment/browser.web.d.ts +1 -0
- package/build/environment/browser.web.d.ts.map +1 -0
- package/build/errors/CodedError.d.ts +1 -0
- package/build/errors/CodedError.d.ts.map +1 -0
- package/build/errors/UnavailabilityError.d.ts +1 -0
- package/build/errors/UnavailabilityError.d.ts.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +2 -0
- package/build/index.js.map +1 -1
- package/build/requireNativeModule.d.ts +16 -0
- package/build/requireNativeModule.d.ts.map +1 -0
- package/build/requireNativeModule.js +18 -0
- package/build/requireNativeModule.js.map +1 -0
- package/build/sweet/NativeErrorManager.d.ts +3 -0
- package/build/sweet/NativeErrorManager.d.ts.map +1 -0
- package/build/sweet/NativeErrorManager.js +3 -0
- package/build/sweet/NativeErrorManager.js.map +1 -0
- package/build/sweet/setUpErrorManager.fx.d.ts +2 -0
- package/build/sweet/setUpErrorManager.fx.d.ts.map +1 -0
- package/build/sweet/setUpErrorManager.fx.js +11 -0
- package/build/sweet/setUpErrorManager.fx.js.map +1 -0
- package/ios/AppDelegates/EXAppDelegatesLoader.m +4 -8
- package/ios/AppDelegates/ExpoAppDelegate.swift +22 -20
- package/ios/EXAppDefines.h +1 -0
- package/ios/EXAppDefines.m +6 -0
- package/ios/EXUtilities.h +2 -0
- package/ios/EXUtilities.m +12 -0
- package/ios/ExpoModulesCore.h +4 -0
- package/ios/ExpoModulesCore.podspec +4 -2
- package/ios/Interfaces/FileSystem/EXFileSystemInterface.h +1 -1
- package/ios/Interfaces/TaskManager/EXTaskServiceInterface.h +1 -0
- package/ios/JSI/{JSIConversions.h → EXJSIConversions.h} +5 -0
- package/ios/JSI/{JSIConversions.mm → EXJSIConversions.mm} +21 -1
- package/ios/JSI/{JSIInstaller.h → EXJSIInstaller.h} +10 -0
- package/ios/JSI/EXJSIInstaller.mm +17 -0
- package/ios/JSI/EXJSIUtils.h +19 -0
- package/ios/JSI/EXJSIUtils.mm +89 -0
- package/ios/JSI/EXJavaScriptObject.h +97 -0
- package/ios/JSI/EXJavaScriptObject.mm +121 -0
- package/ios/JSI/EXJavaScriptRuntime.h +73 -0
- package/ios/JSI/EXJavaScriptRuntime.mm +153 -0
- package/ios/JSI/EXJavaScriptValue.h +57 -0
- package/ios/JSI/EXJavaScriptValue.mm +166 -0
- package/ios/JSI/ExpoModulesHostObject.h +33 -0
- package/ios/JSI/ExpoModulesHostObject.mm +41 -0
- package/ios/JSI/JavaScriptRuntime.swift +32 -0
- package/ios/JSI/JavaScriptValue.swift +94 -0
- package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +3 -23
- package/ios/NativeModulesProxy/EXNativeModulesProxy.h +2 -2
- package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +101 -75
- package/ios/RCTComponentData+Privates.h +12 -0
- package/ios/ReactDelegates/EXReactCompatibleHelpers.h +18 -0
- package/ios/ReactDelegates/EXReactCompatibleHelpers.m +19 -0
- package/ios/ReactDelegates/ExpoReactDelegate.swift +3 -3
- package/ios/ReactDelegates/ExpoReactDelegateHandler.swift +4 -4
- package/ios/ReactDelegates/ModulePriorities.swift +1 -1
- package/ios/Swift/AppContext.swift +57 -4
- package/ios/Swift/Arguments/AnyArgumentType.swift +1 -1
- package/ios/Swift/Arguments/ArgumentType.swift +4 -0
- package/ios/Swift/Arguments/Convertibles.swift +13 -13
- package/ios/Swift/Arguments/Types/EnumArgumentType.swift +11 -17
- package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +1 -1
- package/ios/Swift/Arguments/Types/RawArgumentType.swift +2 -2
- package/ios/Swift/Conversions.swift +51 -56
- package/ios/Swift/EventListener.swift +8 -10
- package/ios/Swift/Events/Callback.swift +66 -0
- package/ios/Swift/Events/Event.swift +43 -0
- package/ios/Swift/Exceptions/ChainableException.swift +51 -0
- package/ios/Swift/{CodedError.swift → Exceptions/CodedError.swift} +1 -12
- package/ios/Swift/Exceptions/Exception.swift +62 -0
- package/ios/Swift/Exceptions/ExceptionOrigin.swift +28 -0
- package/ios/Swift/Exceptions/GenericException.swift +20 -0
- package/ios/Swift/Exceptions/UnexpectedException.swift +16 -0
- package/ios/Swift/Functions/AnyFunction.swift +16 -1
- package/ios/Swift/Functions/AsyncFunctionComponent.swift +182 -0
- package/ios/Swift/Functions/ConcreteFunction.swift +52 -59
- package/ios/Swift/Functions/SyncFunctionComponent.swift +181 -0
- package/ios/Swift/JavaScriptUtils.swift +99 -0
- package/ios/Swift/ModuleHolder.swift +69 -18
- package/ios/Swift/ModuleRegistry.swift +4 -1
- package/ios/Swift/Modules/AnyModule.swift +0 -1
- package/ios/Swift/Modules/ModuleDefinition.swift +4 -13
- package/ios/Swift/Modules/ModuleDefinitionBuilder.swift +0 -1
- package/ios/Swift/Modules/ModuleDefinitionComponents.swift +54 -220
- package/ios/Swift/ModulesProvider.swift +3 -11
- package/ios/Swift/Objects/ObjectDefinition.swift +30 -0
- package/ios/Swift/Objects/ObjectDefinitionComponents.swift +257 -0
- package/ios/Swift/Promise.swift +8 -3
- package/ios/Swift/Records/AnyField.swift +7 -0
- package/ios/Swift/Records/Field.swift +24 -19
- package/ios/Swift/Records/FieldOption.swift +1 -1
- package/ios/Swift/Records/Record.swift +12 -4
- package/ios/Swift/SwiftInteropBridge.swift +53 -15
- package/ios/Swift/Views/AnyViewProp.swift +1 -1
- package/ios/Swift/Views/ComponentData.swift +96 -0
- package/ios/Swift/Views/ConcreteViewProp.swift +6 -8
- package/ios/Swift/Views/ExpoView.swift +8 -0
- package/ios/Swift/Views/ViewFactory.swift +1 -1
- package/ios/Swift/Views/ViewManagerDefinition.swift +23 -2
- package/ios/Swift/Views/ViewManagerDefinitionBuilder.swift +0 -1
- package/ios/Swift/Views/ViewManagerDefinitionComponents.swift +49 -0
- package/ios/Swift/Views/ViewModuleWrapper.swift +5 -2
- package/ios/Swift.h +5 -0
- package/ios/Tests/ArgumentTypeSpec.swift +5 -7
- package/ios/Tests/ConstantsSpec.swift +6 -7
- package/ios/Tests/ConvertiblesSpec.swift +35 -36
- package/ios/Tests/ExceptionsSpec.swift +111 -0
- package/ios/Tests/ExpoModulesSpec.swift +75 -0
- package/ios/Tests/FunctionSpec.swift +21 -25
- package/ios/Tests/FunctionWithConvertiblesSpec.swift +4 -5
- package/ios/Tests/JavaScriptObjectSpec.swift +97 -0
- package/ios/Tests/JavaScriptRuntimeSpec.swift +94 -0
- package/ios/Tests/Mocks/ModuleMocks.swift +1 -1
- package/ios/Tests/Mocks/ModulesProviderMock.swift +0 -1
- package/ios/Tests/ModuleEventListenersSpec.swift +16 -17
- package/ios/Tests/ModuleRegistrySpec.swift +2 -3
- package/ios/Tests/RecordSpec.swift +9 -20
- package/package.json +3 -3
- package/src/NativeModulesProxy.native.ts +2 -22
- package/src/NativeModulesProxy.types.ts +0 -8
- package/src/NativeViewManagerAdapter.native.tsx +12 -28
- package/src/index.ts +4 -0
- package/src/requireNativeModule.ts +29 -0
- package/src/sweet/NativeErrorManager.ts +2 -0
- package/src/sweet/setUpErrorManager.fx.ts +12 -0
- package/android/src/main/java/expo/modules/kotlin/events/KEventEmitterWrapper.kt +0 -26
- package/android/src/main/java/expo/modules/kotlin/methods/Method.kt +0 -14
- package/android/src/main/java/expo/modules/kotlin/methods/PromiseMethod.kt +0 -15
- package/ios/JSI/ExpoModulesProxySpec.h +0 -24
- package/ios/JSI/ExpoModulesProxySpec.mm +0 -135
- package/ios/JSI/JSIInstaller.mm +0 -22
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
package expo.modules.kotlin.records
|
|
2
|
+
|
|
3
|
+
import expo.modules.kotlin.exception.ValidationException
|
|
4
|
+
|
|
5
|
+
interface FieldValidator<T> {
|
|
6
|
+
fun validate(value: T)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
class NumericRangeValidator<T : Comparable<T>>(
|
|
10
|
+
private val from: T,
|
|
11
|
+
private val to: T,
|
|
12
|
+
private val fromInclusive: Boolean,
|
|
13
|
+
private val toInclusive: Boolean
|
|
14
|
+
) : FieldValidator<T> {
|
|
15
|
+
override fun validate(value: T) {
|
|
16
|
+
if (
|
|
17
|
+
value < from ||
|
|
18
|
+
to < value ||
|
|
19
|
+
value == from && !fromInclusive ||
|
|
20
|
+
value == to && !toInclusive
|
|
21
|
+
) {
|
|
22
|
+
throw ValidationException("Value should be in range $from ${if (fromInclusive) "<=" else "<"} 'value' ${if (toInclusive) "<=" else "<"} $to, got $value")
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
class IsNotEmptyCollectionValidator : FieldValidator<Collection<*>> {
|
|
28
|
+
override fun validate(value: Collection<*>) {
|
|
29
|
+
if (value.isEmpty()) {
|
|
30
|
+
throw ValidationException("Collection is empty")
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
class IsNotEmptyIntArrayValidator : FieldValidator<IntArray> {
|
|
36
|
+
override fun validate(value: IntArray) {
|
|
37
|
+
if (value.isEmpty()) {
|
|
38
|
+
throw ValidationException("Array is empty")
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
class IsNotEmptyFloatArrayValidator : FieldValidator<FloatArray> {
|
|
44
|
+
override fun validate(value: FloatArray) {
|
|
45
|
+
if (value.isEmpty()) {
|
|
46
|
+
throw ValidationException("Array is empty")
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
class IsNotEmptyDoubleArrayValidator : FieldValidator<DoubleArray> {
|
|
52
|
+
override fun validate(value: DoubleArray) {
|
|
53
|
+
if (value.isEmpty()) {
|
|
54
|
+
throw ValidationException("Array is empty")
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
class IsNotEmptyArrayValidator : FieldValidator<Array<*>> {
|
|
60
|
+
override fun validate(value: Array<*>) {
|
|
61
|
+
if (value.isEmpty()) {
|
|
62
|
+
throw ValidationException("Array is empty")
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
class CollectionSizeValidator(
|
|
68
|
+
private val min: Int,
|
|
69
|
+
private val max: Int
|
|
70
|
+
) : FieldValidator<Collection<*>> {
|
|
71
|
+
override fun validate(value: Collection<*>) {
|
|
72
|
+
if (value.size < min || value.size > max) {
|
|
73
|
+
throw ValidationException("Number of elements in the collection should be between $min and $max, got ${value.size}")
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
class IntArraySizeValidator(
|
|
79
|
+
private val min: Int,
|
|
80
|
+
private val max: Int
|
|
81
|
+
) : FieldValidator<IntArray> {
|
|
82
|
+
override fun validate(value: IntArray) {
|
|
83
|
+
if (value.size < min || value.size > max) {
|
|
84
|
+
throw ValidationException("Number of elements in the array should be between $min and $max, got ${value.size}")
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
class DoubleArraySizeValidator(
|
|
90
|
+
private val min: Int,
|
|
91
|
+
private val max: Int
|
|
92
|
+
) : FieldValidator<DoubleArray> {
|
|
93
|
+
override fun validate(value: DoubleArray) {
|
|
94
|
+
if (value.size < min || value.size > max) {
|
|
95
|
+
throw ValidationException("Number of elements in the array should be between $min and $max, got ${value.size}")
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
class FloatArraySizeValidator(
|
|
101
|
+
private val min: Int,
|
|
102
|
+
private val max: Int
|
|
103
|
+
) : FieldValidator<FloatArray> {
|
|
104
|
+
override fun validate(value: FloatArray) {
|
|
105
|
+
if (value.size < min || value.size > max) {
|
|
106
|
+
throw ValidationException("Number of elements in the array should be between $min and $max, got ${value.size}")
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
class ArraySizeValidator(
|
|
112
|
+
private val min: Int,
|
|
113
|
+
private val max: Int
|
|
114
|
+
) : FieldValidator<Array<*>> {
|
|
115
|
+
override fun validate(value: Array<*>) {
|
|
116
|
+
if (value.size < min || value.size > max) {
|
|
117
|
+
throw ValidationException("Number of elements in the array should be between $min and $max, got ${value.size}")
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
class StringSizeValidator(
|
|
123
|
+
private val min: Int,
|
|
124
|
+
private val max: Int
|
|
125
|
+
) : FieldValidator<String> {
|
|
126
|
+
override fun validate(value: String) {
|
|
127
|
+
if (value.length < min || value.length > max) {
|
|
128
|
+
throw ValidationException("Length of the string should be between $min and $max, got $value (${value.length} characters)")
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
class RegexValidator(private val regex: Regex) : FieldValidator<CharSequence> {
|
|
134
|
+
override fun validate(value: CharSequence) {
|
|
135
|
+
if (!regex.matches(value)) {
|
|
136
|
+
throw ValidationException("Provided string $value didn't match regex $regex")
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -3,46 +3,80 @@ package expo.modules.kotlin.records
|
|
|
3
3
|
import com.facebook.react.bridge.Dynamic
|
|
4
4
|
import expo.modules.kotlin.allocators.ObjectConstructor
|
|
5
5
|
import expo.modules.kotlin.allocators.ObjectConstructorFactory
|
|
6
|
+
import expo.modules.kotlin.exception.FieldCastException
|
|
7
|
+
import expo.modules.kotlin.exception.FieldRequiredException
|
|
8
|
+
import expo.modules.kotlin.exception.RecordCastException
|
|
9
|
+
import expo.modules.kotlin.exception.exceptionDecorator
|
|
10
|
+
import expo.modules.kotlin.recycle
|
|
6
11
|
import expo.modules.kotlin.types.TypeConverter
|
|
7
12
|
import expo.modules.kotlin.types.TypeConverterProvider
|
|
8
13
|
import kotlin.reflect.KClass
|
|
14
|
+
import kotlin.reflect.KProperty1
|
|
9
15
|
import kotlin.reflect.KType
|
|
16
|
+
import kotlin.reflect.full.createInstance
|
|
10
17
|
import kotlin.reflect.full.findAnnotation
|
|
11
18
|
import kotlin.reflect.full.memberProperties
|
|
12
19
|
import kotlin.reflect.jvm.javaField
|
|
13
20
|
|
|
14
|
-
// TODO(@lukmccall): create all converters during initialization
|
|
15
21
|
class RecordTypeConverter<T : Record>(
|
|
16
22
|
private val converterProvider: TypeConverterProvider,
|
|
17
23
|
val type: KType,
|
|
18
24
|
) : TypeConverter<T>(type.isMarkedNullable) {
|
|
19
25
|
private val objectConstructorFactory = ObjectConstructorFactory()
|
|
26
|
+
private val propertyDescriptors: Map<KProperty1<out Any, *>, PropertyDescriptor> =
|
|
27
|
+
(type.classifier as KClass<*>)
|
|
28
|
+
.memberProperties
|
|
29
|
+
.map { property ->
|
|
30
|
+
val fieldAnnotation = property.findAnnotation<Field>() ?: return@map null
|
|
31
|
+
val typeConverter = converterProvider.obtainTypeConverter(property.returnType)
|
|
32
|
+
|
|
33
|
+
return@map property to PropertyDescriptor(
|
|
34
|
+
typeConverter,
|
|
35
|
+
fieldAnnotation,
|
|
36
|
+
isRequired = property.findAnnotation<Required>() != null,
|
|
37
|
+
validators = getValidators(property)
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
.filterNotNull()
|
|
41
|
+
.toMap()
|
|
20
42
|
|
|
21
|
-
override fun convertNonOptional(value: Dynamic): T {
|
|
43
|
+
override fun convertNonOptional(value: Dynamic): T = exceptionDecorator({ cause -> RecordCastException(type, cause) }) {
|
|
22
44
|
val jsMap = value.asMap()
|
|
23
45
|
|
|
24
46
|
val kClass = type.classifier as KClass<*>
|
|
25
47
|
val instance = getObjectConstructor(kClass.java).construct()
|
|
26
48
|
|
|
27
|
-
|
|
28
|
-
.
|
|
29
|
-
|
|
30
|
-
val filedInformation = property.findAnnotation<Field>() ?: return@map
|
|
31
|
-
val jsKey = filedInformation.key.takeUnless { it == "" } ?: property.name
|
|
49
|
+
propertyDescriptors
|
|
50
|
+
.forEach { (property, descriptor) ->
|
|
51
|
+
val jsKey = descriptor.fieldAnnotation.key.takeUnless { it.isBlank() } ?: property.name
|
|
32
52
|
|
|
33
53
|
if (!jsMap.hasKey(jsKey)) {
|
|
34
|
-
|
|
35
|
-
|
|
54
|
+
if (descriptor.isRequired) {
|
|
55
|
+
throw FieldRequiredException(property)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return@forEach
|
|
36
59
|
}
|
|
37
60
|
|
|
38
|
-
|
|
39
|
-
|
|
61
|
+
jsMap.getDynamic(jsKey).recycle {
|
|
62
|
+
val javaField = property.javaField!!
|
|
40
63
|
|
|
41
|
-
|
|
42
|
-
|
|
64
|
+
val casted = exceptionDecorator({ cause -> FieldCastException(property.name, property.returnType, type, cause) }) {
|
|
65
|
+
descriptor.typeConverter.convert(this)
|
|
66
|
+
}
|
|
43
67
|
|
|
44
|
-
|
|
45
|
-
|
|
68
|
+
if (casted != null) {
|
|
69
|
+
descriptor
|
|
70
|
+
.validators
|
|
71
|
+
.forEach { validator ->
|
|
72
|
+
@Suppress("UNCHECKED_CAST")
|
|
73
|
+
(validator as FieldValidator<Any>).validate(casted)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
javaField.isAccessible = true
|
|
78
|
+
javaField.set(instance, casted)
|
|
79
|
+
}
|
|
46
80
|
}
|
|
47
81
|
|
|
48
82
|
@Suppress("UNCHECKED_CAST")
|
|
@@ -52,4 +86,26 @@ class RecordTypeConverter<T : Record>(
|
|
|
52
86
|
private fun <T> getObjectConstructor(clazz: Class<T>): ObjectConstructor<T> {
|
|
53
87
|
return objectConstructorFactory.get(clazz)
|
|
54
88
|
}
|
|
89
|
+
|
|
90
|
+
private fun getValidators(property: KProperty1<out Any, *>): List<FieldValidator<*>> {
|
|
91
|
+
return property
|
|
92
|
+
.annotations
|
|
93
|
+
.map findValidators@{ annotation ->
|
|
94
|
+
val binderAnnotation = annotation.annotationClass.findAnnotation<BindUsing>()
|
|
95
|
+
?: return@findValidators null
|
|
96
|
+
annotation to binderAnnotation
|
|
97
|
+
}
|
|
98
|
+
.filterNotNull()
|
|
99
|
+
.map { (annotation, binderAnnotation) ->
|
|
100
|
+
val binderInstance = binderAnnotation.binder.createInstance() as ValidationBinder
|
|
101
|
+
binderInstance.bind(annotation, property.returnType)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private data class PropertyDescriptor(
|
|
106
|
+
val typeConverter: TypeConverter<*>,
|
|
107
|
+
val fieldAnnotation: Field,
|
|
108
|
+
val isRequired: Boolean,
|
|
109
|
+
val validators: List<FieldValidator<*>>
|
|
110
|
+
)
|
|
55
111
|
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
package expo.modules.kotlin.records
|
|
2
|
+
|
|
3
|
+
import kotlin.reflect.KClass
|
|
4
|
+
import kotlin.reflect.KType
|
|
5
|
+
import kotlin.reflect.full.createType
|
|
6
|
+
import kotlin.reflect.full.isSubclassOf
|
|
7
|
+
|
|
8
|
+
interface ValidationBinder {
|
|
9
|
+
fun bind(annotation: Annotation, fieldType: KType): FieldValidator<*>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@Retention(AnnotationRetention.RUNTIME)
|
|
13
|
+
@Target(AnnotationTarget.ANNOTATION_CLASS)
|
|
14
|
+
annotation class BindUsing(val binder: KClass<*>)
|
|
15
|
+
|
|
16
|
+
internal class IntRangeBinder : ValidationBinder {
|
|
17
|
+
override fun bind(annotation: Annotation, fieldType: KType): FieldValidator<*> {
|
|
18
|
+
val rangeAnnotation = annotation as IntRange
|
|
19
|
+
return NumericRangeValidator(
|
|
20
|
+
rangeAnnotation.from,
|
|
21
|
+
rangeAnnotation.to,
|
|
22
|
+
rangeAnnotation.fromInclusive,
|
|
23
|
+
rangeAnnotation.toInclusive
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
internal class LongRangeBinder : ValidationBinder {
|
|
29
|
+
override fun bind(annotation: Annotation, fieldType: KType): FieldValidator<*> {
|
|
30
|
+
val rangeAnnotation = annotation as LongRange
|
|
31
|
+
return NumericRangeValidator(
|
|
32
|
+
rangeAnnotation.from,
|
|
33
|
+
rangeAnnotation.to,
|
|
34
|
+
rangeAnnotation.fromInclusive,
|
|
35
|
+
rangeAnnotation.toInclusive
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
internal class FloatRangeBinder : ValidationBinder {
|
|
41
|
+
override fun bind(annotation: Annotation, fieldType: KType): FieldValidator<*> {
|
|
42
|
+
val rangeAnnotation = annotation as FloatRange
|
|
43
|
+
return NumericRangeValidator(
|
|
44
|
+
rangeAnnotation.from,
|
|
45
|
+
rangeAnnotation.to,
|
|
46
|
+
rangeAnnotation.fromInclusive,
|
|
47
|
+
rangeAnnotation.toInclusive
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
internal class DoubleRangeBinder : ValidationBinder {
|
|
53
|
+
override fun bind(annotation: Annotation, fieldType: KType): FieldValidator<*> {
|
|
54
|
+
val rangeAnnotation = annotation as DoubleRange
|
|
55
|
+
return NumericRangeValidator(
|
|
56
|
+
rangeAnnotation.from,
|
|
57
|
+
rangeAnnotation.to,
|
|
58
|
+
rangeAnnotation.fromInclusive,
|
|
59
|
+
rangeAnnotation.toInclusive
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
internal class IsCollectionNotEmptyBinder : ValidationBinder {
|
|
65
|
+
override fun bind(annotation: Annotation, fieldType: KType): FieldValidator<*> {
|
|
66
|
+
assert(annotation is IsNotEmpty)
|
|
67
|
+
|
|
68
|
+
when (fieldType) {
|
|
69
|
+
IntArray::class.createType() -> return IsNotEmptyIntArrayValidator()
|
|
70
|
+
DoubleArray::class.createType() -> return IsNotEmptyDoubleArrayValidator()
|
|
71
|
+
FloatArray::class.createType() -> return IsNotEmptyFloatArrayValidator()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
val kClass = fieldType.classifier as KClass<*>
|
|
75
|
+
if (kClass.isSubclassOf(Array::class) || kClass.java.isArray) {
|
|
76
|
+
return IsNotEmptyArrayValidator()
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return IsNotEmptyCollectionValidator()
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
internal class SizeBinder : ValidationBinder {
|
|
84
|
+
override fun bind(annotation: Annotation, fieldType: KType): FieldValidator<*> {
|
|
85
|
+
val sizeAnnotation = annotation as Size
|
|
86
|
+
|
|
87
|
+
when (fieldType) {
|
|
88
|
+
IntArray::class.createType() -> return IntArraySizeValidator(sizeAnnotation.min, sizeAnnotation.max)
|
|
89
|
+
DoubleArray::class.createType() -> return DoubleArraySizeValidator(sizeAnnotation.min, sizeAnnotation.max)
|
|
90
|
+
FloatArray::class.createType() -> return FloatArraySizeValidator(sizeAnnotation.min, sizeAnnotation.max)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
val kClass = fieldType.classifier as KClass<*>
|
|
94
|
+
|
|
95
|
+
if (kClass.isSubclassOf(String::class)) {
|
|
96
|
+
return StringSizeValidator(sizeAnnotation.min, sizeAnnotation.max)
|
|
97
|
+
} else if (kClass.isSubclassOf(Array::class) || kClass.java.isArray) {
|
|
98
|
+
return ArraySizeValidator(sizeAnnotation.min, sizeAnnotation.max)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return CollectionSizeValidator(sizeAnnotation.min, sizeAnnotation.max)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
internal class RegexBinder : ValidationBinder {
|
|
106
|
+
override fun bind(annotation: Annotation, fieldType: KType): FieldValidator<*> {
|
|
107
|
+
val regexAnnotation = annotation as RegularExpression
|
|
108
|
+
return RegexValidator(regexAnnotation.regex.toRegex())
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
package expo.modules.kotlin.records
|
|
2
|
+
|
|
3
|
+
@Retention(AnnotationRetention.RUNTIME)
|
|
4
|
+
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.TYPE, AnnotationTarget.VALUE_PARAMETER)
|
|
5
|
+
@BindUsing(IntRangeBinder::class)
|
|
6
|
+
annotation class IntRange(
|
|
7
|
+
val from: Int,
|
|
8
|
+
val to: Int,
|
|
9
|
+
val fromInclusive: Boolean = true,
|
|
10
|
+
val toInclusive: Boolean = true,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
@Retention(AnnotationRetention.RUNTIME)
|
|
14
|
+
@Target(AnnotationTarget.PROPERTY)
|
|
15
|
+
@BindUsing(LongRangeBinder::class)
|
|
16
|
+
annotation class LongRange(
|
|
17
|
+
val from: Long,
|
|
18
|
+
val to: Long,
|
|
19
|
+
val fromInclusive: Boolean = true,
|
|
20
|
+
val toInclusive: Boolean = true
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
@Retention(AnnotationRetention.RUNTIME)
|
|
24
|
+
@Target(AnnotationTarget.PROPERTY)
|
|
25
|
+
@BindUsing(FloatRangeBinder::class)
|
|
26
|
+
annotation class FloatRange(
|
|
27
|
+
val from: Float,
|
|
28
|
+
val to: Float,
|
|
29
|
+
val fromInclusive: Boolean = true,
|
|
30
|
+
val toInclusive: Boolean = true
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
@Retention(AnnotationRetention.RUNTIME)
|
|
34
|
+
@Target(AnnotationTarget.PROPERTY)
|
|
35
|
+
@BindUsing(DoubleRangeBinder::class)
|
|
36
|
+
annotation class DoubleRange(
|
|
37
|
+
val from: Double,
|
|
38
|
+
val to: Double,
|
|
39
|
+
val fromInclusive: Boolean = true,
|
|
40
|
+
val toInclusive: Boolean = true
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
@Retention(AnnotationRetention.RUNTIME)
|
|
44
|
+
@Target(AnnotationTarget.PROPERTY)
|
|
45
|
+
@BindUsing(IsCollectionNotEmptyBinder::class)
|
|
46
|
+
annotation class IsNotEmpty
|
|
47
|
+
|
|
48
|
+
@Retention(AnnotationRetention.RUNTIME)
|
|
49
|
+
@Target(AnnotationTarget.PROPERTY)
|
|
50
|
+
@BindUsing(SizeBinder::class)
|
|
51
|
+
annotation class Size(
|
|
52
|
+
val min: Int = 0,
|
|
53
|
+
val max: Int = Int.MAX_VALUE
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
@Retention(AnnotationRetention.RUNTIME)
|
|
57
|
+
@Target(AnnotationTarget.PROPERTY)
|
|
58
|
+
@BindUsing(RegexBinder::class)
|
|
59
|
+
annotation class RegularExpression(
|
|
60
|
+
val regex: String
|
|
61
|
+
)
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
package expo.modules.kotlin.types
|
|
2
2
|
|
|
3
3
|
import com.facebook.react.bridge.Dynamic
|
|
4
|
+
import expo.modules.kotlin.exception.CollectionElementCastException
|
|
5
|
+
import expo.modules.kotlin.exception.exceptionDecorator
|
|
4
6
|
import expo.modules.kotlin.recycle
|
|
5
7
|
import kotlin.reflect.KClass
|
|
6
8
|
import kotlin.reflect.KType
|
|
7
9
|
|
|
8
10
|
class ArrayTypeConverter(
|
|
9
11
|
converterProvider: TypeConverterProvider,
|
|
10
|
-
private val
|
|
11
|
-
) : TypeConverter<Array<*>>(
|
|
12
|
+
private val arrayType: KType,
|
|
13
|
+
) : TypeConverter<Array<*>>(arrayType.isMarkedNullable) {
|
|
12
14
|
private val arrayElementConverter = converterProvider.obtainTypeConverter(
|
|
13
|
-
requireNotNull(
|
|
15
|
+
requireNotNull(arrayType.arguments.first().type) {
|
|
14
16
|
"The array type should contain the type of the elements."
|
|
15
17
|
}
|
|
16
18
|
)
|
|
@@ -22,7 +24,11 @@ class ArrayTypeConverter(
|
|
|
22
24
|
array[i] = jsArray
|
|
23
25
|
.getDynamic(i)
|
|
24
26
|
.recycle {
|
|
25
|
-
|
|
27
|
+
exceptionDecorator({ cause ->
|
|
28
|
+
CollectionElementCastException(arrayType, arrayType.arguments.first().type!!, type, cause)
|
|
29
|
+
}) {
|
|
30
|
+
arrayElementConverter.convert(this)
|
|
31
|
+
}
|
|
26
32
|
}
|
|
27
33
|
}
|
|
28
34
|
return array
|
|
@@ -37,7 +43,7 @@ class ArrayTypeConverter(
|
|
|
37
43
|
@Suppress("UNCHECKED_CAST")
|
|
38
44
|
private fun createTypedArray(size: Int): Array<Any?> {
|
|
39
45
|
return java.lang.reflect.Array.newInstance(
|
|
40
|
-
(
|
|
46
|
+
(arrayType.arguments.first().type!!.classifier as KClass<*>).java,
|
|
41
47
|
size
|
|
42
48
|
) as Array<Any?>
|
|
43
49
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
package expo.modules.kotlin.types
|
|
2
|
+
|
|
3
|
+
import android.os.Bundle
|
|
4
|
+
import com.facebook.react.bridge.Arguments
|
|
5
|
+
import com.facebook.react.bridge.WritableArray
|
|
6
|
+
import com.facebook.react.bridge.WritableMap
|
|
7
|
+
import expo.modules.kotlin.records.Record
|
|
8
|
+
|
|
9
|
+
object JSTypeConverter {
|
|
10
|
+
interface ContainerProvider {
|
|
11
|
+
fun createMap(): WritableMap
|
|
12
|
+
fun createArray(): WritableArray
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
internal object DefaultContainerProvider : ContainerProvider {
|
|
16
|
+
override fun createMap(): WritableMap = Arguments.createMap()
|
|
17
|
+
override fun createArray(): WritableArray = Arguments.createArray()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
fun convertToJSValue(value: Any?, containerProvider: ContainerProvider = DefaultContainerProvider): Any? {
|
|
21
|
+
return when (value) {
|
|
22
|
+
null, is Unit -> null
|
|
23
|
+
is Bundle -> value.toJSValue(containerProvider)
|
|
24
|
+
is Iterable<*> -> value.toJSValue(containerProvider)
|
|
25
|
+
is Array<*> -> value.toJSValue(containerProvider)
|
|
26
|
+
is IntArray -> value.toJSValue(containerProvider)
|
|
27
|
+
is FloatArray -> value.toJSValue(containerProvider)
|
|
28
|
+
is DoubleArray -> value.toJSValue(containerProvider)
|
|
29
|
+
is Map<*, *> -> value.toJSValue(containerProvider)
|
|
30
|
+
is Enum<*> -> value.toJSValue()
|
|
31
|
+
is Record -> value.toJSValue(containerProvider)
|
|
32
|
+
else -> value
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
package expo.modules.kotlin.types
|
|
2
|
+
|
|
3
|
+
import android.os.Bundle
|
|
4
|
+
import com.facebook.react.bridge.ReadableArray
|
|
5
|
+
import com.facebook.react.bridge.ReadableMap
|
|
6
|
+
import com.facebook.react.bridge.WritableArray
|
|
7
|
+
import com.facebook.react.bridge.WritableMap
|
|
8
|
+
import expo.modules.kotlin.records.Field
|
|
9
|
+
import expo.modules.kotlin.records.Record
|
|
10
|
+
import kotlin.reflect.KProperty1
|
|
11
|
+
import kotlin.reflect.full.declaredMemberProperties
|
|
12
|
+
import kotlin.reflect.full.findAnnotation
|
|
13
|
+
import kotlin.reflect.full.memberProperties
|
|
14
|
+
import kotlin.reflect.full.primaryConstructor
|
|
15
|
+
import kotlin.reflect.jvm.isAccessible
|
|
16
|
+
|
|
17
|
+
fun Record.toJSValue(containerProvider: JSTypeConverter.ContainerProvider): WritableMap {
|
|
18
|
+
val result = containerProvider.createMap()
|
|
19
|
+
|
|
20
|
+
javaClass
|
|
21
|
+
.kotlin
|
|
22
|
+
.memberProperties.map { property ->
|
|
23
|
+
val fieldInformation = property.findAnnotation<Field>() ?: return@map
|
|
24
|
+
val jsKey = fieldInformation.key.takeUnless { it == "" } ?: property.name
|
|
25
|
+
|
|
26
|
+
property.isAccessible = true
|
|
27
|
+
|
|
28
|
+
val value = property.get(this)
|
|
29
|
+
val convertedValue = JSTypeConverter.convertToJSValue(value, containerProvider)
|
|
30
|
+
result.putGeneric(jsKey, convertedValue)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return result
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
fun Bundle.toJSValue(containerProvider: JSTypeConverter.ContainerProvider): WritableMap {
|
|
37
|
+
val result = containerProvider.createMap()
|
|
38
|
+
|
|
39
|
+
for (key in keySet()) {
|
|
40
|
+
val value = get(key)
|
|
41
|
+
val convertedValue = JSTypeConverter.convertToJSValue(value, containerProvider)
|
|
42
|
+
result.putGeneric(key, convertedValue)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return result
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
fun <K, V> Map<K, V>.toJSValue(containerProvider: JSTypeConverter.ContainerProvider): WritableMap {
|
|
49
|
+
val result = containerProvider.createMap()
|
|
50
|
+
|
|
51
|
+
for ((key, value) in entries) {
|
|
52
|
+
val convertedValue = JSTypeConverter.convertToJSValue(value, containerProvider)
|
|
53
|
+
result.putGeneric(key.toString(), convertedValue)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return result
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
fun <T> Iterable<T>.toJSValue(containerProvider: JSTypeConverter.ContainerProvider): WritableArray {
|
|
60
|
+
val result = containerProvider.createArray()
|
|
61
|
+
|
|
62
|
+
for (value in this) {
|
|
63
|
+
val convertedValue = JSTypeConverter.convertToJSValue(value, containerProvider)
|
|
64
|
+
result.putGeneric(convertedValue)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return result
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
fun <T> Array<T>.toJSValue(containerProvider: JSTypeConverter.ContainerProvider): WritableArray {
|
|
71
|
+
val result = containerProvider.createArray()
|
|
72
|
+
|
|
73
|
+
for (value in this) {
|
|
74
|
+
val convertedValue = JSTypeConverter.convertToJSValue(value, containerProvider)
|
|
75
|
+
result.putGeneric(convertedValue)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return result
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
fun IntArray.toJSValue(containerProvider: JSTypeConverter.ContainerProvider): WritableArray {
|
|
82
|
+
return containerProvider.createArray().also {
|
|
83
|
+
for (value in this) {
|
|
84
|
+
it.pushInt(value)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
fun FloatArray.toJSValue(containerProvider: JSTypeConverter.ContainerProvider): WritableArray {
|
|
90
|
+
return containerProvider.createArray().also {
|
|
91
|
+
for (value in this) {
|
|
92
|
+
it.pushDouble(value.toDouble())
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
fun DoubleArray.toJSValue(containerProvider: JSTypeConverter.ContainerProvider): WritableArray {
|
|
98
|
+
return containerProvider.createArray().also {
|
|
99
|
+
for (value in this) {
|
|
100
|
+
it.pushDouble(value)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
fun Enum<*>.toJSValue(): Any? {
|
|
106
|
+
val primaryConstructor = requireNotNull(this::class.primaryConstructor) {
|
|
107
|
+
"Cannot convert enum without the primary constructor to js value"
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (primaryConstructor.parameters.isEmpty()) {
|
|
111
|
+
return this.name
|
|
112
|
+
} else if (primaryConstructor.parameters.size == 1) {
|
|
113
|
+
val parameterName = primaryConstructor.parameters.first().name!!
|
|
114
|
+
@Suppress("UNCHECKED_CAST")
|
|
115
|
+
val parameterProperty = this::class.declaredMemberProperties
|
|
116
|
+
.find { it.name == parameterName } as KProperty1<Enum<*>, *>
|
|
117
|
+
|
|
118
|
+
return parameterProperty.get(this)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
throw IllegalStateException("Enum '$javaClass' cannot be used as return type (incompatible with JS)")
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
internal fun WritableMap.putGeneric(key: String, value: Any?) {
|
|
125
|
+
when (value) {
|
|
126
|
+
null, is Unit -> putNull(key)
|
|
127
|
+
is ReadableArray -> putArray(key, value)
|
|
128
|
+
is ReadableMap -> putMap(key, value)
|
|
129
|
+
is String -> putString(key, value)
|
|
130
|
+
is Int -> putInt(key, value)
|
|
131
|
+
is Number -> putDouble(key, value.toDouble())
|
|
132
|
+
is Boolean -> putBoolean(key, value)
|
|
133
|
+
else -> throw IllegalArgumentException("Could not put '${value.javaClass}' to WritableMap")
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
internal fun WritableArray.putGeneric(value: Any?) {
|
|
138
|
+
when (value) {
|
|
139
|
+
null, is Unit -> pushNull()
|
|
140
|
+
is ReadableArray -> pushArray(value)
|
|
141
|
+
is ReadableMap -> pushMap(value)
|
|
142
|
+
is String -> pushString(value)
|
|
143
|
+
is Int -> pushInt(value)
|
|
144
|
+
is Number -> pushDouble(value.toDouble())
|
|
145
|
+
is Boolean -> pushBoolean(value)
|
|
146
|
+
else -> throw IllegalArgumentException("Could not put '${value.javaClass}' to WritableArray")
|
|
147
|
+
}
|
|
148
|
+
}
|