expo-modules-core 0.9.2 → 0.10.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 (167) hide show
  1. package/CHANGELOG.md +18 -5
  2. package/android/CMakeLists.txt +154 -0
  3. package/android/build.gradle +293 -5
  4. package/android/src/main/cpp/Exceptions.cpp +22 -0
  5. package/android/src/main/cpp/Exceptions.h +38 -0
  6. package/android/src/main/cpp/ExpoModulesHostObject.cpp +47 -0
  7. package/android/src/main/cpp/ExpoModulesHostObject.h +32 -0
  8. package/android/src/main/cpp/JNIFunctionBody.cpp +29 -0
  9. package/android/src/main/cpp/JNIFunctionBody.h +50 -0
  10. package/android/src/main/cpp/JNIInjector.cpp +19 -0
  11. package/android/src/main/cpp/JSIInteropModuleRegistry.cpp +122 -0
  12. package/android/src/main/cpp/JSIInteropModuleRegistry.h +96 -0
  13. package/android/src/main/cpp/JSIObjectWrapper.h +33 -0
  14. package/android/src/main/cpp/JSITypeConverter.h +84 -0
  15. package/android/src/main/cpp/JavaScriptModuleObject.cpp +138 -0
  16. package/android/src/main/cpp/JavaScriptModuleObject.h +122 -0
  17. package/android/src/main/cpp/JavaScriptObject.cpp +125 -0
  18. package/android/src/main/cpp/JavaScriptObject.h +131 -0
  19. package/android/src/main/cpp/JavaScriptRuntime.cpp +127 -0
  20. package/android/src/main/cpp/JavaScriptRuntime.h +87 -0
  21. package/android/src/main/cpp/JavaScriptValue.cpp +172 -0
  22. package/android/src/main/cpp/JavaScriptValue.h +78 -0
  23. package/android/src/main/cpp/MethodMetadata.cpp +230 -0
  24. package/android/src/main/cpp/MethodMetadata.h +92 -0
  25. package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +2 -0
  26. package/android/src/main/java/expo/modules/core/errors/ContextDestroyedException.kt +7 -0
  27. package/android/src/main/java/expo/modules/interfaces/permissions/Permissions.java +30 -0
  28. package/android/src/main/java/expo/modules/kotlin/AppContext.kt +49 -1
  29. package/android/src/main/java/expo/modules/kotlin/ConcatIterator.kt +18 -0
  30. package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +15 -12
  31. package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +39 -3
  32. package/android/src/main/java/expo/modules/kotlin/defaultmodules/ErrorManagerModule.kt +2 -2
  33. package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +13 -0
  34. package/android/src/main/java/expo/modules/kotlin/exception/ExceptionDecorator.kt +2 -0
  35. package/android/src/main/java/expo/modules/kotlin/functions/AnyFunction.kt +19 -14
  36. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +29 -7
  37. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +13 -13
  38. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionComponent.kt +18 -0
  39. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromiseComponent.kt +18 -0
  40. package/android/src/main/java/expo/modules/kotlin/functions/SuspendFunctionComponent.kt +56 -0
  41. package/android/src/main/java/expo/modules/kotlin/functions/SyncFunctionComponent.kt +28 -0
  42. package/android/src/main/java/expo/modules/kotlin/jni/CppType.kt +18 -0
  43. package/android/src/main/java/expo/modules/kotlin/jni/JNIFunctionBody.kt +39 -0
  44. package/android/src/main/java/expo/modules/kotlin/jni/JSIInteropModuleRegistry.kt +89 -0
  45. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptModuleObject.kt +44 -0
  46. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptObject.kt +113 -0
  47. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptValue.kt +35 -0
  48. package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +15 -5
  49. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +65 -111
  50. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +35 -2
  51. package/android/src/main/java/expo/modules/kotlin/providers/AppContextProvider.kt +14 -0
  52. package/android/src/main/java/expo/modules/kotlin/providers/CurrentActivityProvider.kt +22 -0
  53. package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +19 -2
  54. package/android/src/main/java/expo/modules/kotlin/types/AnyType.kt +3 -2
  55. package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +7 -2
  56. package/android/src/main/java/expo/modules/kotlin/types/BasicTypeConverters.kt +68 -20
  57. package/android/src/main/java/expo/modules/kotlin/types/EnumTypeConverter.kt +50 -22
  58. package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +18 -2
  59. package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +18 -2
  60. package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +17 -2
  61. package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +43 -3
  62. package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +5 -0
  63. package/build/NativeModulesProxy.native.d.ts.map +1 -1
  64. package/build/NativeModulesProxy.native.js +9 -3
  65. package/build/NativeModulesProxy.native.js.map +1 -1
  66. package/ios/AppDelegates/EXAppDelegatesLoader.m +1 -2
  67. package/ios/ExpoModulesCore.podspec +1 -1
  68. package/ios/JSI/EXJSIConversions.mm +6 -0
  69. package/ios/JSI/EXJSIInstaller.h +15 -21
  70. package/ios/JSI/EXJSIInstaller.mm +39 -3
  71. package/ios/JSI/EXJSIUtils.h +47 -3
  72. package/ios/JSI/EXJSIUtils.mm +88 -4
  73. package/ios/JSI/EXJavaScriptObject.h +11 -18
  74. package/ios/JSI/EXJavaScriptObject.mm +37 -18
  75. package/ios/JSI/EXJavaScriptRuntime.h +43 -9
  76. package/ios/JSI/EXJavaScriptRuntime.mm +70 -27
  77. package/ios/JSI/EXJavaScriptTypedArray.h +30 -0
  78. package/ios/JSI/EXJavaScriptTypedArray.mm +29 -0
  79. package/ios/JSI/EXJavaScriptValue.h +3 -2
  80. package/ios/JSI/EXJavaScriptValue.mm +17 -20
  81. package/ios/JSI/EXJavaScriptWeakObject.h +23 -0
  82. package/ios/JSI/EXJavaScriptWeakObject.mm +53 -0
  83. package/ios/JSI/EXObjectDeallocator.h +27 -0
  84. package/ios/JSI/ExpoModulesHostObject.h +3 -3
  85. package/ios/JSI/ExpoModulesHostObject.mm +4 -4
  86. package/ios/JSI/JavaScriptRuntime.swift +38 -1
  87. package/ios/JSI/JavaScriptValue.swift +7 -0
  88. package/ios/JSI/TypedArray.cpp +67 -0
  89. package/ios/JSI/TypedArray.h +46 -0
  90. package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +0 -11
  91. package/ios/NativeModulesProxy/EXNativeModulesProxy.h +17 -10
  92. package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +85 -77
  93. package/ios/NativeModulesProxy/NativeModulesProxyModule.swift +17 -0
  94. package/ios/Services/EXReactNativeEventEmitter.h +2 -2
  95. package/ios/Services/EXReactNativeEventEmitter.m +11 -6
  96. package/ios/Swift/AppContext.swift +208 -28
  97. package/ios/Swift/Arguments/AnyArgument.swift +18 -0
  98. package/ios/Swift/Arguments/{Types/EnumArgumentType.swift → EnumArgument.swift} +2 -17
  99. package/ios/Swift/Classes/ClassComponent.swift +95 -0
  100. package/ios/Swift/Classes/ClassComponentElement.swift +33 -0
  101. package/ios/Swift/Classes/ClassComponentElementsBuilder.swift +34 -0
  102. package/ios/Swift/Classes/ClassComponentFactories.swift +96 -0
  103. package/ios/Swift/DynamicTypes/AnyDynamicType.swift +44 -0
  104. package/ios/Swift/DynamicTypes/DynamicArrayType.swift +56 -0
  105. package/ios/Swift/DynamicTypes/DynamicConvertibleType.swift +27 -0
  106. package/ios/Swift/DynamicTypes/DynamicEnumType.swift +27 -0
  107. package/ios/Swift/DynamicTypes/DynamicOptionalType.swift +63 -0
  108. package/ios/Swift/DynamicTypes/DynamicRawType.swift +33 -0
  109. package/ios/Swift/DynamicTypes/DynamicSharedObjectType.swift +37 -0
  110. package/ios/Swift/DynamicTypes/DynamicType.swift +39 -0
  111. package/ios/Swift/DynamicTypes/DynamicTypedArrayType.swift +46 -0
  112. package/ios/Swift/Exceptions/CodedError.swift +1 -1
  113. package/ios/Swift/Exceptions/Exception.swift +8 -6
  114. package/ios/Swift/Exceptions/UnexpectedException.swift +2 -1
  115. package/ios/Swift/ExpoBridgeModule.m +5 -0
  116. package/ios/Swift/ExpoBridgeModule.swift +65 -0
  117. package/ios/Swift/Functions/AnyFunction.swift +33 -31
  118. package/ios/Swift/Functions/AsyncFunctionComponent.swift +196 -59
  119. package/ios/Swift/Functions/SyncFunctionComponent.swift +142 -58
  120. package/ios/Swift/JavaScriptUtils.swift +32 -57
  121. package/ios/Swift/Logging/LogHandlers.swift +39 -0
  122. package/ios/Swift/Logging/LogType.swift +62 -0
  123. package/ios/Swift/Logging/Logger.swift +198 -0
  124. package/ios/Swift/ModuleHolder.swift +19 -54
  125. package/ios/Swift/ModuleRegistry.swift +7 -1
  126. package/ios/Swift/Modules/AnyModule.swift +3 -3
  127. package/ios/Swift/ModulesProvider.swift +2 -0
  128. package/ios/Swift/Objects/JavaScriptObjectBuilder.swift +37 -0
  129. package/ios/Swift/Objects/ObjectDefinition.swift +74 -1
  130. package/ios/Swift/Objects/ObjectDefinitionComponents.swift +77 -68
  131. package/ios/Swift/Objects/PropertyComponent.swift +147 -0
  132. package/ios/Swift/Promise.swift +12 -3
  133. package/ios/Swift/Records/Field.swift +2 -2
  134. package/ios/Swift/SharedObjects/SharedObject.swift +20 -0
  135. package/ios/Swift/SharedObjects/SharedObjectRegistry.swift +129 -0
  136. package/ios/Swift/TypedArrays/AnyTypedArray.swift +11 -0
  137. package/ios/Swift/TypedArrays/ConcreteTypedArrays.swift +56 -0
  138. package/ios/Swift/TypedArrays/GenericTypedArray.swift +49 -0
  139. package/ios/Swift/TypedArrays/TypedArray.swift +80 -0
  140. package/ios/Swift/Utilities.swift +28 -0
  141. package/ios/Swift/Views/ConcreteViewProp.swift +3 -3
  142. package/ios/Swift/Views/ViewManagerDefinitionComponents.swift +2 -2
  143. package/ios/Tests/ClassComponentSpec.swift +210 -0
  144. package/ios/Tests/DynamicTypeSpec.swift +336 -0
  145. package/ios/Tests/EnumArgumentSpec.swift +48 -0
  146. package/ios/Tests/ExpoModulesSpec.swift +17 -3
  147. package/ios/Tests/FunctionSpec.swift +167 -118
  148. package/ios/Tests/Mocks/ModuleMocks.swift +1 -1
  149. package/ios/Tests/PropertyComponentSpec.swift +95 -0
  150. package/ios/Tests/SharedObjectRegistrySpec.swift +109 -0
  151. package/ios/Tests/TypedArraysSpec.swift +136 -0
  152. package/package.json +2 -2
  153. package/src/NativeModulesProxy.native.ts +13 -3
  154. package/src/ts-declarations/ExpoModules.d.ts +7 -0
  155. package/tsconfig.json +1 -1
  156. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromise.kt +0 -15
  157. package/android/src/main/java/expo/modules/kotlin/functions/AsyncSuspendFunction.kt +0 -36
  158. package/ios/Swift/Arguments/AnyArgumentType.swift +0 -13
  159. package/ios/Swift/Arguments/ArgumentType.swift +0 -28
  160. package/ios/Swift/Arguments/Types/ArrayArgumentType.swift +0 -42
  161. package/ios/Swift/Arguments/Types/ConvertibleArgumentType.swift +0 -16
  162. package/ios/Swift/Arguments/Types/OptionalArgumentType.swift +0 -49
  163. package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +0 -15
  164. package/ios/Swift/Arguments/Types/RawArgumentType.swift +0 -25
  165. package/ios/Swift/Functions/ConcreteFunction.swift +0 -103
  166. package/ios/Swift/SwiftInteropBridge.swift +0 -155
  167. package/ios/Tests/ArgumentTypeSpec.swift +0 -143
@@ -0,0 +1,136 @@
1
+ // Copyright 2022-present 650 Industries. All rights reserved.
2
+
3
+ import ExpoModulesTestCore
4
+
5
+ @testable import ExpoModulesCore
6
+
7
+ final class TypedArraysSpec: ExpoSpec {
8
+ override func spec() {
9
+ describe("module") {
10
+ let appContext = AppContext.create()
11
+ let runtime = appContext.runtime!
12
+
13
+ beforeSuite {
14
+ appContext.moduleRegistry.register(moduleType: TypedArraysModule.self)
15
+ }
16
+
17
+ // Gets the value at index 3 from the array
18
+ it("reads from Int8Array") {
19
+ let intValue = try runtime
20
+ .eval([
21
+ "typedArray = new Int8Array([2, 1, 3, 7])",
22
+ "ExpoModules.TypedArrays.int8_subscript_get(typedArray, 3)",
23
+ ])
24
+ .asInt()
25
+
26
+ expect(intValue) == 7
27
+ }
28
+
29
+ // Sets the value at index 1 to the random int
30
+ it("writes to Int8Array") {
31
+ let randomInt = Int.random(in: -128...127)
32
+ let array = try runtime
33
+ .eval([
34
+ "typedArray = new Int8Array(3)",
35
+ "ExpoModules.TypedArrays.int8_subscript_set(typedArray, 1, \(randomInt))",
36
+ "Array.from(typedArray)",
37
+ ])
38
+ .asArray()
39
+
40
+ expect(array[0]?.getInt()) == 0 // Remains unset
41
+ expect(array[1]?.getInt()) == randomInt
42
+ expect(array[2]?.getInt()) == 0 // Remains unset
43
+ }
44
+
45
+ // Gets a slice from the array from index 1 to 3
46
+ it("reads from UInt16Array slice") {
47
+ let values = try runtime
48
+ .eval([
49
+ "typedArray = new Uint16Array([0, 8, 4, 1])",
50
+ "ExpoModules.TypedArrays.uint16_subscript_range_get(typedArray, 1, 3)"
51
+ ])
52
+ .asArray()
53
+ .map({ try $0?.asInt() })
54
+
55
+ expect(values.count) == 3
56
+ expect(values[0]) == 8
57
+ expect(values[1]) == 4
58
+ expect(values[2]) == 1
59
+ }
60
+
61
+ // Sets a slice of the array from index x to y
62
+ it("writes to UInt16Array slice") {
63
+ let random1 = Int.random(in: 0...65535)
64
+ let random2 = Int.random(in: 0...65535)
65
+ let values = try runtime
66
+ .eval([
67
+ "typedArray = new Uint16Array(4)",
68
+ "ExpoModules.TypedArrays.uint16_subscript_range_set(typedArray, 1, 2, [\(random1), \(random2)])",
69
+ "Array.from(typedArray)",
70
+ ])
71
+ .asArray()
72
+
73
+ expect(values[0]?.getInt()) == 0 // Remains unset
74
+ expect(values[1]?.getInt()) == random1
75
+ expect(values[2]?.getInt()) == random2
76
+ expect(values[3]?.getInt()) == 0 // Remains unset
77
+ }
78
+
79
+ it("returns itself") {
80
+ let input = try runtime.eval("typedArray = new Float32Array([1.2, 3.4]); typedArray").asTypedArray()
81
+ let output = try runtime.eval("ExpoModules.TypedArrays.return(typedArray)").asTypedArray()
82
+
83
+ expect(input.getProperty("0").getDouble()) == output.getProperty("0").getDouble()
84
+ expect(input.getProperty("1").getDouble()) == output.getProperty("1").getDouble()
85
+ expect(input.getUnsafeMutableRawPointer()) == output.getUnsafeMutableRawPointer()
86
+ }
87
+
88
+ it("writes to unsafe raw pointer") {
89
+ let count = 6
90
+ let values = try runtime
91
+ .eval([
92
+ "typedArray = new Uint8Array(\(count))",
93
+ "Array.from(ExpoModules.TypedArrays.writeToUnsafeRawPointer(typedArray))",
94
+ ])
95
+ .asArray()
96
+ .map({ $0?.getInt() ?? 0 })
97
+
98
+ // Assume that at least one element should have changed
99
+ expect(values.filter({ $0 != 0 }).count) >= 1
100
+ }
101
+
102
+ // TODO: Test throwing NotTypedArrayException and ArrayTypeMismatchException
103
+ }
104
+ }
105
+ }
106
+
107
+ fileprivate final class TypedArraysModule: Module {
108
+ func definition() -> ModuleDefinition {
109
+ Name("TypedArrays")
110
+
111
+ Function("int8_subscript_get") { (array: Int8Array, index: Int) in
112
+ return array[index]
113
+ }
114
+
115
+ Function("int8_subscript_set") { (array: Int8Array, index: Int, value: Int8) in
116
+ array[index] = value
117
+ }
118
+
119
+ Function("uint16_subscript_range_get") { (array: Uint16Array, start: Int, end: Int) in
120
+ return array[start...end]
121
+ }
122
+
123
+ Function("uint16_subscript_range_set") { (array: Uint16Array, start: Int, end: Int, values: [UInt16]) in
124
+ array[start...end] = values
125
+ }
126
+
127
+ Function("return") { (array: TypedArray) -> JavaScriptTypedArray in
128
+ return array.jsTypedArray
129
+ }
130
+
131
+ Function("writeToUnsafeRawPointer") { (array: TypedArray) -> JavaScriptTypedArray in
132
+ let _ = SecRandomCopyBytes(kSecRandomDefault, array.byteLength, array.rawPointer)
133
+ return array.jsTypedArray
134
+ }
135
+ }
136
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-modules-core",
3
- "version": "0.9.2",
3
+ "version": "0.10.0",
4
4
  "description": "The core of Expo Modules architecture",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -42,5 +42,5 @@
42
42
  "@testing-library/react-hooks": "^7.0.1",
43
43
  "expo-module-scripts": "^2.0.0"
44
44
  },
45
- "gitHead": "464933d2189a33b02375b47cd655e87f5694afb4"
45
+ "gitHead": "72253d4b18b62d329bbc6785d996e227f185d533"
46
46
  }
@@ -2,15 +2,23 @@ import { NativeModules } from 'react-native';
2
2
 
3
3
  import { ProxyNativeModule } from './NativeModulesProxy.types';
4
4
 
5
- const NativeProxy = NativeModules.NativeUnimoduleProxy;
5
+ const ExpoNativeProxy = global.ExpoModules?.NativeModulesProxy;
6
+ const LegacyNativeProxy = NativeModules.NativeUnimoduleProxy;
7
+
6
8
  const modulesConstantsKey = 'modulesConstants';
7
9
  const exportedMethodsKey = 'exportedMethods';
8
10
 
9
11
  const NativeModulesProxy: { [moduleName: string]: ProxyNativeModule } = {};
10
12
 
11
- if (NativeProxy) {
13
+ if (LegacyNativeProxy) {
14
+ // use JSI proxy if available, fallback to legacy RN proxy
15
+ const NativeProxy = ExpoNativeProxy ?? LegacyNativeProxy;
16
+
12
17
  Object.keys(NativeProxy[exportedMethodsKey]).forEach((moduleName) => {
18
+ // copy constants
13
19
  NativeModulesProxy[moduleName] = NativeProxy[modulesConstantsKey][moduleName] || {};
20
+
21
+ // copy methods
14
22
  NativeProxy[exportedMethodsKey][moduleName].forEach((methodInfo) => {
15
23
  NativeModulesProxy[moduleName][methodInfo.name] = (...args: unknown[]): Promise<any> => {
16
24
  const { key, argumentsCount } = methodInfo;
@@ -23,7 +31,9 @@ if (NativeProxy) {
23
31
  )
24
32
  );
25
33
  }
26
- return NativeProxy.callMethod(moduleName, key, args);
34
+
35
+ // We still want to call methods using the legacy proxy in SDK 46
36
+ return LegacyNativeProxy.callMethod(moduleName, key, args);
27
37
  };
28
38
  });
29
39
 
@@ -0,0 +1,7 @@
1
+ declare let global: {
2
+ ExpoModules:
3
+ | undefined
4
+ | {
5
+ [key: string]: any;
6
+ };
7
+ };
package/tsconfig.json CHANGED
@@ -5,5 +5,5 @@
5
5
  "outDir": "./build"
6
6
  },
7
7
  "include": ["./src"],
8
- "exclude": ["**/__mocks__/*", "**/__tests__/*"]
8
+ "exclude": ["**/__mocks__/*", "**/__tests__/*", "**/__stories__/*"]
9
9
  }
@@ -1,15 +0,0 @@
1
- package expo.modules.kotlin.functions
2
-
3
- import expo.modules.kotlin.ModuleHolder
4
- import expo.modules.kotlin.Promise
5
- import expo.modules.kotlin.types.AnyType
6
-
7
- class AsyncFunctionWithPromise(
8
- name: String,
9
- argsType: Array<AnyType>,
10
- private val body: (args: Array<out Any?>, promise: Promise) -> Unit
11
- ) : AnyFunction(name, argsType) {
12
- override fun callImplementation(holder: ModuleHolder, args: Array<out Any?>, promise: Promise) {
13
- body(args, promise)
14
- }
15
- }
@@ -1,36 +0,0 @@
1
- package expo.modules.kotlin.functions
2
-
3
- import expo.modules.kotlin.ModuleHolder
4
- import expo.modules.kotlin.Promise
5
- import expo.modules.kotlin.exception.CodedException
6
- import expo.modules.kotlin.exception.FunctionCallException
7
- import expo.modules.kotlin.exception.UnexpectedException
8
- import expo.modules.kotlin.exception.exceptionDecorator
9
- import expo.modules.kotlin.types.AnyType
10
- import kotlinx.coroutines.CoroutineScope
11
- import kotlinx.coroutines.isActive
12
- import kotlinx.coroutines.launch
13
-
14
- class AsyncSuspendFunction(
15
- name: String,
16
- argsType: Array<AnyType>,
17
- private val body: suspend CoroutineScope.(args: Array<out Any?>) -> Any?
18
- ) : AnyFunction(name, argsType) {
19
- override fun callImplementation(holder: ModuleHolder, args: Array<out Any?>, promise: Promise) {
20
- val scope = holder.module.coroutineScopeDelegate.value
21
- scope.launch {
22
- try {
23
- val result = exceptionDecorator({ cause -> FunctionCallException(name, holder.name, cause) }) {
24
- body.invoke(scope, args)
25
- }
26
- if (isActive) {
27
- promise.resolve(result)
28
- }
29
- } catch (e: CodedException) {
30
- promise.reject(e)
31
- } catch (e: Throwable) {
32
- promise.reject(UnexpectedException(e))
33
- }
34
- }
35
- }
36
- }
@@ -1,13 +0,0 @@
1
- // Copyright 2021-present 650 Industries. All rights reserved.
2
-
3
- /**
4
- A protocol whose intention is to wrap function's argument type
5
- to keep its real signature and not type-erase it by the compiler.
6
- */
7
- public protocol AnyArgumentType: CustomStringConvertible {
8
- /**
9
- Casts given any value to the wrapped type and returns as `Any`.
10
- NOTE: It may not be just simple type-casting (e.g. when the wrapped type conforms to `ConvertibleArgument`).
11
- */
12
- func cast<ArgType>(_ value: ArgType) throws -> Any
13
- }
@@ -1,28 +0,0 @@
1
- // Copyright 2021-present 650 Industries. All rights reserved.
2
-
3
- // Function names should start with a lowercase character, but in this one case
4
- // we want it to be uppercase as we treat it more like a generic class.
5
- // swiftlint:disable identifier_name
6
-
7
- /**
8
- Factory creating an instance of the argument type wrapper conforming to `AnyArgumentType`.
9
- Depending on the given type, it may return one of `ArrayArgumentType`, `OptionalArgumentType`, `ConvertibleArgumentType`, etc.
10
- */
11
- internal func ArgumentType<T>(_ type: T.Type) -> AnyArgumentType {
12
- if let ArrayType = T.self as? AnyArrayArgument.Type {
13
- return ArrayArgumentType(elementType: ArrayType.getElementArgumentType())
14
- }
15
- if let OptionalType = T.self as? AnyOptionalArgument.Type {
16
- return OptionalArgumentType(wrappedType: OptionalType.getWrappedArgumentType())
17
- }
18
- if let ConvertibleType = T.self as? ConvertibleArgument.Type {
19
- return ConvertibleArgumentType(innerType: ConvertibleType)
20
- }
21
- if let EnumType = T.self as? EnumArgument.Type {
22
- return EnumArgumentType(innerType: EnumType)
23
- }
24
- if T.self is Promise.Type {
25
- return PromiseArgumentType()
26
- }
27
- return RawArgumentType(innerType: T.self)
28
- }
@@ -1,42 +0,0 @@
1
- // Copyright 2021-present 650 Industries. All rights reserved.
2
-
3
- /**
4
- An argument type representing array types. Requires the argument type for
5
- array's element type as it delegates casting to that type for each element in the array.
6
- */
7
- internal struct ArrayArgumentType: AnyArgumentType {
8
- let elementType: AnyArgumentType
9
-
10
- func cast<ArgType>(_ value: ArgType) throws -> Any {
11
- if let value = value as? [Any] {
12
- return try value.map { try elementType.cast($0) }
13
- }
14
- // We should probably throw an error if we get here. On the other side, the array type
15
- // requirement can be more loosen so we can try to arrayize values that are not arrays.
16
- return [try elementType.cast(value)]
17
- }
18
-
19
- var description: String {
20
- "[\(elementType.description)]"
21
- }
22
- }
23
-
24
- /**
25
- A type-erased protocol used to recognize arrays with elements of argument-compatible type.
26
- `Array` is a generic type, so it's impossible to check the inheritance directly.
27
- */
28
- internal protocol AnyArrayArgument: AnyArgument {
29
- /**
30
- Exposes the `Element` generic type wrapped by the argument type to preserve its metadata.
31
- */
32
- static func getElementArgumentType() -> AnyArgumentType
33
- }
34
-
35
- /**
36
- Extends the `Array` type to expose its generic `Element` as an argument type.
37
- */
38
- extension Array: AnyArrayArgument where Element: AnyArgument {
39
- static func getElementArgumentType() -> AnyArgumentType {
40
- return ArgumentType(Element.self)
41
- }
42
- }
@@ -1,16 +0,0 @@
1
- // Copyright 2021-present 650 Industries. All rights reserved.
2
-
3
- /**
4
- An argument type that wraps any type conforming to `ConvertibleArgument` protocol.
5
- */
6
- internal struct ConvertibleArgumentType: AnyArgumentType {
7
- let innerType: ConvertibleArgument.Type
8
-
9
- func cast<ArgType>(_ value: ArgType) throws -> Any {
10
- return try innerType.convert(from: value)
11
- }
12
-
13
- var description: String {
14
- String(describing: innerType.self)
15
- }
16
- }
@@ -1,49 +0,0 @@
1
- // Copyright 2021-present 650 Industries. All rights reserved.
2
-
3
- /**
4
- An argument type that represents an optional type, which allows `nil` to be passed when casting.
5
- Requires the argument type for optional's unwrapped type as it delegates casting to that type for non-nil values.
6
- */
7
- internal struct OptionalArgumentType: AnyArgumentType {
8
- let wrappedType: AnyArgumentType
9
-
10
- func cast<ArgType>(_ value: ArgType) throws -> Any {
11
- if Optional.isNil(value) {
12
- return Optional<Any>.none as Any
13
- }
14
- return try wrappedType.cast(value)
15
- }
16
-
17
- var description: String {
18
- "\(wrappedType)?"
19
- }
20
- }
21
-
22
- /**
23
- A type-erased protocol used to recognize if the generic type is an optional type.
24
- `Optional` is a generic enum, so it's impossible to check the inheritance directly.
25
- */
26
- internal protocol AnyOptionalArgument: AnyArgument {
27
- /**
28
- Exposes the `Wrapped` generic type wrapped by the argument type to preserve its metadata.`
29
- */
30
- static func getWrappedArgumentType() -> AnyArgumentType
31
- }
32
-
33
- /**
34
- Make generic `Optional` implement non-generic `AnyOptional` and add handy check against type-erased `nil`.
35
- */
36
- extension Optional: AnyOptionalArgument {
37
- static func getWrappedArgumentType() -> AnyArgumentType {
38
- return ArgumentType(Wrapped.self)
39
- }
40
-
41
- static func isNil(_ object: Wrapped) -> Bool {
42
- switch object as Any {
43
- case Optional<Any>.none:
44
- return true
45
- default:
46
- return false
47
- }
48
- }
49
- }
@@ -1,15 +0,0 @@
1
- // Copyright 2021-present 650 Industries. All rights reserved.
2
-
3
- /**
4
- An argument type that represents the `Promise` argument.
5
- */
6
- internal struct PromiseArgumentType: AnyArgumentType {
7
- func cast<ArgType>(_ value: ArgType) throws -> Any {
8
- if let value = value as? Promise {
9
- return value
10
- }
11
- throw Conversions.CastingException<Promise>(value)
12
- }
13
-
14
- var description: String = "Promise"
15
- }
@@ -1,25 +0,0 @@
1
- // Copyright 2021-present 650 Industries. All rights reserved.
2
-
3
- /**
4
- An argument type that can wrap any type, but it casts only type-compatible values using `as?` keyword.
5
- The innermost type of other argument types like `ArrayArgumentType` and `OptionalArgumentType`.
6
- */
7
- internal struct RawArgumentType<InnerType>: AnyArgumentType {
8
- let innerType: InnerType.Type
9
-
10
- func cast<ArgType>(_ value: ArgType) throws -> Any {
11
- if let value = value as? InnerType {
12
- return value
13
- }
14
- // Raw arguments are always non-optional, but they may receive `nil` values.
15
- // Let's throw more specific error in this case.
16
- if Optional.isNil(value) {
17
- throw Conversions.NullCastException<InnerType>()
18
- }
19
- throw Conversions.CastingException<InnerType>(value)
20
- }
21
-
22
- var description: String {
23
- String(describing: innerType.self)
24
- }
25
- }
@@ -1,103 +0,0 @@
1
- import Dispatch
2
-
3
- public class ConcreteFunction<Args, ReturnType>: AnyFunction {
4
- public typealias ClosureType = (Args) throws -> ReturnType
5
-
6
- public let name: String
7
-
8
- public var takesPromise: Bool
9
-
10
- public var argumentsCount: Int {
11
- return argumentTypes.count
12
- }
13
-
14
- public var queue: DispatchQueue?
15
-
16
- public var isAsync: Bool = true
17
-
18
- let closure: ClosureType
19
-
20
- public let argumentTypes: [AnyArgumentType]
21
-
22
- init(
23
- _ name: String,
24
- argTypes: [AnyArgumentType],
25
- _ closure: @escaping ClosureType
26
- ) {
27
- self.name = name
28
- self.takesPromise = argTypes.last is PromiseArgumentType
29
- self.closure = closure
30
-
31
- // Drop the last argument type if it's the `Promise`.
32
- self.argumentTypes = takesPromise ? argTypes.dropLast(1) : argTypes
33
-
34
- // This is temporary solution to keep backwards compatibility for existing functions — they all end with "Async".
35
- // `function` component that we've used so far was async by default, but we decided to replace it with `asyncFunction`
36
- // and make `function`s synchronous. Introduced in SDK45, can be removed in SDK46 after migrating all modules.
37
- self.isAsync = name.hasSuffix("Async")
38
- }
39
-
40
- /**
41
- Calls the function with given arguments.
42
- - Parameters:
43
- - args: An array of arguments to pass to the function. The arguments must be of the same type as in the underlying ``closure``.
44
- - promise: A promise to resolve or reject by the async ``closure`` when it finishes execution.
45
- - ToDo: Make it internal.
46
- */
47
- public func call(args: [Any], promise: Promise) {
48
- // Add promise to the array of arguments if necessary.
49
- let arguments = takesPromise ? args + [promise] : args
50
- let returnedValue: ReturnType?
51
-
52
- do {
53
- let argumentsTuple = try Conversions.toTuple(arguments) as! Args
54
- returnedValue = try closure(argumentsTuple)
55
- } catch let error as CodedError {
56
- promise.reject(FunctionCallException(name).causedBy(error))
57
- return
58
- } catch {
59
- promise.reject(UnexpectedException(error))
60
- return
61
- }
62
- if !takesPromise {
63
- promise.resolve(returnedValue)
64
- }
65
- }
66
-
67
- /**
68
- Calls the function synchronously with given arguments.
69
- - Parameters:
70
- - args: An array of arguments to pass to the function. The arguments must be of the same type as in the underlying ``closure``.
71
- - Returns: A value returned by the called function when succeeded or an error when it failed.
72
- - ToDo: Make it internal.
73
- */
74
- public func callSync(args: [Any]) -> Any {
75
- if takesPromise {
76
- // Using `Promise` in the synchronous function is prohibited. Probably should throw an exception here,
77
- // but for now let's return nil until we split async and sync functions.
78
- return Optional<Any>.none as Any
79
- }
80
- do {
81
- let argumentsTuple = try Conversions.toTuple(args) as! Args
82
- return try closure(argumentsTuple)
83
- } catch let error {
84
- return error
85
- }
86
- }
87
-
88
- public func runOnQueue(_ queue: DispatchQueue?) -> Self {
89
- self.queue = queue
90
- return self
91
- }
92
-
93
- public func runSynchronously() -> Self {
94
- self.isAsync = false
95
- return self
96
- }
97
- }
98
-
99
- internal class FunctionCallException: GenericException<String> {
100
- override var reason: String {
101
- "Call to function '\(param)' has been rejected"
102
- }
103
- }