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.
Files changed (219) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.md +1 -1
  3. package/android/ExpoModulesCorePlugin.gradle +15 -0
  4. package/android/build.gradle +31 -15
  5. package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +5 -5
  6. package/android/src/main/java/expo/modules/adapters/react/services/UIManagerModuleWrapper.java +13 -0
  7. package/android/src/main/java/expo/modules/core/ViewManager.java +9 -0
  8. package/android/src/main/java/expo/modules/core/interfaces/JavaScriptContextProvider.java +4 -0
  9. package/android/src/main/java/expo/modules/core/interfaces/ReactActivityHandler.java +37 -1
  10. package/android/src/main/java/expo/modules/core/interfaces/ReactNativeHostHandler.java +30 -0
  11. package/android/src/main/java/expo/modules/core/interfaces/services/UIManager.java +2 -0
  12. package/android/src/main/java/expo/modules/kotlin/AppContext.kt +23 -5
  13. package/android/src/main/java/expo/modules/kotlin/DynamicExtenstions.kt +5 -3
  14. package/android/src/main/java/expo/modules/kotlin/KPromiseWrapper.kt +3 -8
  15. package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +24 -9
  16. package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +12 -7
  17. package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +23 -1
  18. package/android/src/main/java/expo/modules/kotlin/Promise.kt +1 -1
  19. package/android/src/main/java/expo/modules/kotlin/callbacks/Callback.kt +5 -0
  20. package/android/src/main/java/expo/modules/kotlin/callbacks/ViewCallback.kt +39 -0
  21. package/android/src/main/java/expo/modules/kotlin/callbacks/ViewCallbackDelegate.kt +27 -0
  22. package/android/src/main/java/expo/modules/kotlin/defaultmodules/ErrorManagerModule.kt +25 -0
  23. package/android/src/main/java/expo/modules/kotlin/events/EventEmitter.kt +13 -0
  24. package/android/src/main/java/expo/modules/kotlin/events/KModuleEventEmitterWrapper.kt +102 -0
  25. package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +93 -9
  26. package/android/src/main/java/expo/modules/kotlin/exception/ExceptionDecorator.kt +11 -0
  27. package/android/src/main/java/expo/modules/kotlin/{methods/AnyMethod.kt → functions/AnyFunction.kt} +18 -18
  28. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +15 -0
  29. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +170 -0
  30. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromise.kt +15 -0
  31. package/android/src/main/java/expo/modules/kotlin/functions/AsyncSuspendFunction.kt +36 -0
  32. package/android/src/main/java/expo/modules/kotlin/modules/DefinitionMarker.kt +4 -0
  33. package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +17 -2
  34. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +416 -43
  35. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +2 -2
  36. package/android/src/main/java/expo/modules/kotlin/records/FieldValidator.kt +139 -0
  37. package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +71 -15
  38. package/android/src/main/java/expo/modules/kotlin/records/Required.kt +5 -0
  39. package/android/src/main/java/expo/modules/kotlin/records/ValidationBinder.kt +110 -0
  40. package/android/src/main/java/expo/modules/kotlin/records/Validators.kt +61 -0
  41. package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +11 -5
  42. package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverter.kt +35 -0
  43. package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverterHelper.kt +148 -0
  44. package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +10 -4
  45. package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +12 -6
  46. package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +29 -13
  47. package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +2 -1
  48. package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +9 -1
  49. package/android/src/main/java/expo/modules/kotlin/views/CallbacksDefinition.kt +3 -0
  50. package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +71 -0
  51. package/android/src/main/java/expo/modules/kotlin/views/SimpleViewManagerWrapper.kt +22 -0
  52. package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinition.kt +18 -0
  53. package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinitionBuilder.kt +114 -0
  54. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +30 -2
  55. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +81 -2
  56. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +62 -2
  57. package/build/EventEmitter.d.ts +1 -0
  58. package/build/EventEmitter.d.ts.map +1 -0
  59. package/build/NativeModulesProxy.d.ts +1 -0
  60. package/build/NativeModulesProxy.d.ts.map +1 -0
  61. package/build/NativeModulesProxy.native.d.ts +1 -4
  62. package/build/NativeModulesProxy.native.d.ts.map +1 -0
  63. package/build/NativeModulesProxy.native.js +1 -14
  64. package/build/NativeModulesProxy.native.js.map +1 -1
  65. package/build/NativeModulesProxy.types.d.ts +1 -3
  66. package/build/NativeModulesProxy.types.d.ts.map +1 -0
  67. package/build/NativeModulesProxy.types.js.map +1 -1
  68. package/build/NativeViewManagerAdapter.d.ts +1 -0
  69. package/build/NativeViewManagerAdapter.d.ts.map +1 -0
  70. package/build/NativeViewManagerAdapter.native.d.ts +1 -0
  71. package/build/NativeViewManagerAdapter.native.d.ts.map +1 -0
  72. package/build/NativeViewManagerAdapter.native.js +9 -33
  73. package/build/NativeViewManagerAdapter.native.js.map +1 -1
  74. package/build/PermissionsHook.d.ts +1 -0
  75. package/build/PermissionsHook.d.ts.map +1 -0
  76. package/build/PermissionsInterface.d.ts +1 -0
  77. package/build/PermissionsInterface.d.ts.map +1 -0
  78. package/build/Platform.d.ts +1 -0
  79. package/build/Platform.d.ts.map +1 -0
  80. package/build/SyntheticPlatformEmitter.d.ts +1 -0
  81. package/build/SyntheticPlatformEmitter.d.ts.map +1 -0
  82. package/build/SyntheticPlatformEmitter.web.d.ts +1 -0
  83. package/build/SyntheticPlatformEmitter.web.d.ts.map +1 -0
  84. package/build/deprecate.d.ts +1 -0
  85. package/build/deprecate.d.ts.map +1 -0
  86. package/build/environment/browser.d.ts +1 -0
  87. package/build/environment/browser.d.ts.map +1 -0
  88. package/build/environment/browser.web.d.ts +1 -0
  89. package/build/environment/browser.web.d.ts.map +1 -0
  90. package/build/errors/CodedError.d.ts +1 -0
  91. package/build/errors/CodedError.d.ts.map +1 -0
  92. package/build/errors/UnavailabilityError.d.ts +1 -0
  93. package/build/errors/UnavailabilityError.d.ts.map +1 -0
  94. package/build/index.d.ts +3 -0
  95. package/build/index.d.ts.map +1 -0
  96. package/build/index.js +2 -0
  97. package/build/index.js.map +1 -1
  98. package/build/requireNativeModule.d.ts +16 -0
  99. package/build/requireNativeModule.d.ts.map +1 -0
  100. package/build/requireNativeModule.js +18 -0
  101. package/build/requireNativeModule.js.map +1 -0
  102. package/build/sweet/NativeErrorManager.d.ts +3 -0
  103. package/build/sweet/NativeErrorManager.d.ts.map +1 -0
  104. package/build/sweet/NativeErrorManager.js +3 -0
  105. package/build/sweet/NativeErrorManager.js.map +1 -0
  106. package/build/sweet/setUpErrorManager.fx.d.ts +2 -0
  107. package/build/sweet/setUpErrorManager.fx.d.ts.map +1 -0
  108. package/build/sweet/setUpErrorManager.fx.js +11 -0
  109. package/build/sweet/setUpErrorManager.fx.js.map +1 -0
  110. package/ios/AppDelegates/EXAppDelegatesLoader.m +4 -8
  111. package/ios/AppDelegates/ExpoAppDelegate.swift +22 -20
  112. package/ios/EXAppDefines.h +1 -0
  113. package/ios/EXAppDefines.m +6 -0
  114. package/ios/EXUtilities.h +2 -0
  115. package/ios/EXUtilities.m +12 -0
  116. package/ios/ExpoModulesCore.h +4 -0
  117. package/ios/ExpoModulesCore.podspec +4 -2
  118. package/ios/Interfaces/FileSystem/EXFileSystemInterface.h +1 -1
  119. package/ios/Interfaces/TaskManager/EXTaskServiceInterface.h +1 -0
  120. package/ios/JSI/{JSIConversions.h → EXJSIConversions.h} +5 -0
  121. package/ios/JSI/{JSIConversions.mm → EXJSIConversions.mm} +21 -1
  122. package/ios/JSI/{JSIInstaller.h → EXJSIInstaller.h} +10 -0
  123. package/ios/JSI/EXJSIInstaller.mm +17 -0
  124. package/ios/JSI/EXJSIUtils.h +19 -0
  125. package/ios/JSI/EXJSIUtils.mm +89 -0
  126. package/ios/JSI/EXJavaScriptObject.h +97 -0
  127. package/ios/JSI/EXJavaScriptObject.mm +121 -0
  128. package/ios/JSI/EXJavaScriptRuntime.h +73 -0
  129. package/ios/JSI/EXJavaScriptRuntime.mm +153 -0
  130. package/ios/JSI/EXJavaScriptValue.h +57 -0
  131. package/ios/JSI/EXJavaScriptValue.mm +166 -0
  132. package/ios/JSI/ExpoModulesHostObject.h +33 -0
  133. package/ios/JSI/ExpoModulesHostObject.mm +41 -0
  134. package/ios/JSI/JavaScriptRuntime.swift +32 -0
  135. package/ios/JSI/JavaScriptValue.swift +94 -0
  136. package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +3 -23
  137. package/ios/NativeModulesProxy/EXNativeModulesProxy.h +2 -2
  138. package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +101 -75
  139. package/ios/RCTComponentData+Privates.h +12 -0
  140. package/ios/ReactDelegates/EXReactCompatibleHelpers.h +18 -0
  141. package/ios/ReactDelegates/EXReactCompatibleHelpers.m +19 -0
  142. package/ios/ReactDelegates/ExpoReactDelegate.swift +3 -3
  143. package/ios/ReactDelegates/ExpoReactDelegateHandler.swift +4 -4
  144. package/ios/ReactDelegates/ModulePriorities.swift +1 -1
  145. package/ios/Swift/AppContext.swift +57 -4
  146. package/ios/Swift/Arguments/AnyArgumentType.swift +1 -1
  147. package/ios/Swift/Arguments/ArgumentType.swift +4 -0
  148. package/ios/Swift/Arguments/Convertibles.swift +13 -13
  149. package/ios/Swift/Arguments/Types/EnumArgumentType.swift +11 -17
  150. package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +1 -1
  151. package/ios/Swift/Arguments/Types/RawArgumentType.swift +2 -2
  152. package/ios/Swift/Conversions.swift +51 -56
  153. package/ios/Swift/EventListener.swift +8 -10
  154. package/ios/Swift/Events/Callback.swift +66 -0
  155. package/ios/Swift/Events/Event.swift +43 -0
  156. package/ios/Swift/Exceptions/ChainableException.swift +51 -0
  157. package/ios/Swift/{CodedError.swift → Exceptions/CodedError.swift} +1 -12
  158. package/ios/Swift/Exceptions/Exception.swift +62 -0
  159. package/ios/Swift/Exceptions/ExceptionOrigin.swift +28 -0
  160. package/ios/Swift/Exceptions/GenericException.swift +20 -0
  161. package/ios/Swift/Exceptions/UnexpectedException.swift +16 -0
  162. package/ios/Swift/Functions/AnyFunction.swift +16 -1
  163. package/ios/Swift/Functions/AsyncFunctionComponent.swift +182 -0
  164. package/ios/Swift/Functions/ConcreteFunction.swift +52 -59
  165. package/ios/Swift/Functions/SyncFunctionComponent.swift +181 -0
  166. package/ios/Swift/JavaScriptUtils.swift +99 -0
  167. package/ios/Swift/ModuleHolder.swift +69 -18
  168. package/ios/Swift/ModuleRegistry.swift +4 -1
  169. package/ios/Swift/Modules/AnyModule.swift +0 -1
  170. package/ios/Swift/Modules/ModuleDefinition.swift +4 -13
  171. package/ios/Swift/Modules/ModuleDefinitionBuilder.swift +0 -1
  172. package/ios/Swift/Modules/ModuleDefinitionComponents.swift +54 -220
  173. package/ios/Swift/ModulesProvider.swift +3 -11
  174. package/ios/Swift/Objects/ObjectDefinition.swift +30 -0
  175. package/ios/Swift/Objects/ObjectDefinitionComponents.swift +257 -0
  176. package/ios/Swift/Promise.swift +8 -3
  177. package/ios/Swift/Records/AnyField.swift +7 -0
  178. package/ios/Swift/Records/Field.swift +24 -19
  179. package/ios/Swift/Records/FieldOption.swift +1 -1
  180. package/ios/Swift/Records/Record.swift +12 -4
  181. package/ios/Swift/SwiftInteropBridge.swift +53 -15
  182. package/ios/Swift/Views/AnyViewProp.swift +1 -1
  183. package/ios/Swift/Views/ComponentData.swift +96 -0
  184. package/ios/Swift/Views/ConcreteViewProp.swift +6 -8
  185. package/ios/Swift/Views/ExpoView.swift +8 -0
  186. package/ios/Swift/Views/ViewFactory.swift +1 -1
  187. package/ios/Swift/Views/ViewManagerDefinition.swift +23 -2
  188. package/ios/Swift/Views/ViewManagerDefinitionBuilder.swift +0 -1
  189. package/ios/Swift/Views/ViewManagerDefinitionComponents.swift +49 -0
  190. package/ios/Swift/Views/ViewModuleWrapper.swift +5 -2
  191. package/ios/Swift.h +5 -0
  192. package/ios/Tests/ArgumentTypeSpec.swift +5 -7
  193. package/ios/Tests/ConstantsSpec.swift +6 -7
  194. package/ios/Tests/ConvertiblesSpec.swift +35 -36
  195. package/ios/Tests/ExceptionsSpec.swift +111 -0
  196. package/ios/Tests/ExpoModulesSpec.swift +75 -0
  197. package/ios/Tests/FunctionSpec.swift +21 -25
  198. package/ios/Tests/FunctionWithConvertiblesSpec.swift +4 -5
  199. package/ios/Tests/JavaScriptObjectSpec.swift +97 -0
  200. package/ios/Tests/JavaScriptRuntimeSpec.swift +94 -0
  201. package/ios/Tests/Mocks/ModuleMocks.swift +1 -1
  202. package/ios/Tests/Mocks/ModulesProviderMock.swift +0 -1
  203. package/ios/Tests/ModuleEventListenersSpec.swift +16 -17
  204. package/ios/Tests/ModuleRegistrySpec.swift +2 -3
  205. package/ios/Tests/RecordSpec.swift +9 -20
  206. package/package.json +3 -3
  207. package/src/NativeModulesProxy.native.ts +2 -22
  208. package/src/NativeModulesProxy.types.ts +0 -8
  209. package/src/NativeViewManagerAdapter.native.tsx +12 -28
  210. package/src/index.ts +4 -0
  211. package/src/requireNativeModule.ts +29 -0
  212. package/src/sweet/NativeErrorManager.ts +2 -0
  213. package/src/sweet/setUpErrorManager.fx.ts +12 -0
  214. package/android/src/main/java/expo/modules/kotlin/events/KEventEmitterWrapper.kt +0 -26
  215. package/android/src/main/java/expo/modules/kotlin/methods/Method.kt +0 -14
  216. package/android/src/main/java/expo/modules/kotlin/methods/PromiseMethod.kt +0 -15
  217. package/ios/JSI/ExpoModulesProxySpec.h +0 -24
  218. package/ios/JSI/ExpoModulesProxySpec.mm +0 -135
  219. package/ios/JSI/JSIInstaller.mm +0 -22
@@ -0,0 +1,28 @@
1
+ // Copyright 2022-present 650 Industries. All rights reserved.
2
+
3
+ /**
4
+ Represents the place in code where the exception was created.
5
+ */
6
+ public struct ExceptionOrigin: CustomStringConvertible {
7
+ /**
8
+ The path to the file in which the exception was created.
9
+ */
10
+ let file: String
11
+
12
+ /**
13
+ The line number on which the exception was created.
14
+ */
15
+ let line: UInt
16
+
17
+ /**
18
+ The name (selector) of the declaration in which the exception was created.
19
+ */
20
+ let function: String
21
+
22
+ /**
23
+ Stringified representation of the exception origin.
24
+ */
25
+ public var description: String {
26
+ "at \(file):\(line) in \(function)"
27
+ }
28
+ }
@@ -0,0 +1,20 @@
1
+ // Copyright 2022-present 650 Industries. All rights reserved.
2
+
3
+ /**
4
+ The exception that needs some additional parameters to be best described.
5
+ */
6
+ open class GenericException<ParamType>: Exception {
7
+ /**
8
+ The additional parameter passed to the initializer.
9
+ */
10
+ public let param: ParamType
11
+
12
+ /**
13
+ The default initializer that takes a param and captures the place in the code where the exception was created.
14
+ - Warning: Call it only with one argument! If you need to pass more parameters, use a tuple instead.
15
+ */
16
+ public init(_ param: ParamType, file: String = #fileID, line: UInt = #line, function: String = #function) {
17
+ self.param = param
18
+ super.init(file: file, line: line, function: function)
19
+ }
20
+ }
@@ -0,0 +1,16 @@
1
+ // Copyright 2022-present 650 Industries. All rights reserved.
2
+
3
+ /**
4
+ Exception wrapper used to handle unexpected internal native errors.
5
+ */
6
+ public class UnexpectedException: Exception {
7
+ private let errorDescription: String
8
+
9
+ public init(_ error: Error) {
10
+ self.errorDescription = error.localizedDescription
11
+ }
12
+
13
+ public override var reason: String {
14
+ return errorDescription
15
+ }
16
+ }
@@ -14,6 +14,11 @@ public protocol AnyFunction: AnyDefinition {
14
14
  */
15
15
  var takesPromise: Bool { get }
16
16
 
17
+ /**
18
+ An array of argument types that the function takes. If the last type is `Promise`, it's not included.
19
+ */
20
+ var argumentTypes: [AnyArgumentType] { get }
21
+
17
22
  /**
18
23
  A number of arguments the function takes. If the last argument is of type `Promise`, it is not counted.
19
24
  */
@@ -24,10 +29,15 @@ public protocol AnyFunction: AnyDefinition {
24
29
  */
25
30
  var queue: DispatchQueue? { get }
26
31
 
32
+ /**
33
+ Whether the function needs to be called asynchronously from JavaScript.
34
+ */
35
+ var isAsync: Bool { get }
36
+
27
37
  /**
28
38
  Calls the function on given module with arguments and a promise.
29
39
  */
30
- func call(args: [Any], promise: Promise) -> Void
40
+ func call(args: [Any], promise: Promise)
31
41
 
32
42
  /**
33
43
  Synchronously calls the function with given arguments. If the function takes a promise,
@@ -39,4 +49,9 @@ public protocol AnyFunction: AnyDefinition {
39
49
  Specifies on which queue the function should run.
40
50
  */
41
51
  func runOnQueue(_ queue: DispatchQueue?) -> Self
52
+
53
+ /**
54
+ Makes the JavaScript function synchronous.
55
+ */
56
+ func runSynchronously() -> Self
42
57
  }
@@ -0,0 +1,182 @@
1
+ // Copyright 2022-present 650 Industries. All rights reserved.
2
+
3
+ /**
4
+ Represents a function that can only be called asynchronously, thus its JavaScript equivalent returns a Promise.
5
+
6
+ - ToDo: Move some asynchronous logic from `ConcreteFunction` (like `call(args:promise:)`) to this class and drop the `isAsync` property.
7
+ */
8
+ internal final class AsyncFunctionComponent<Args, ReturnType>: ConcreteFunction<Args, ReturnType> {
9
+ override init(
10
+ _ name: String,
11
+ argTypes: [AnyArgumentType],
12
+ _ closure: @escaping ConcreteFunction<Args, ReturnType>.ClosureType
13
+ ) {
14
+ super.init(name, argTypes: argTypes, closure)
15
+ self.isAsync = true
16
+ }
17
+ }
18
+
19
+ /**
20
+ Asynchronous function without arguments.
21
+ */
22
+ public func AsyncFunction<R>(
23
+ _ name: String,
24
+ _ closure: @escaping () throws -> R
25
+ ) -> AnyFunction {
26
+ return AsyncFunctionComponent(
27
+ name,
28
+ argTypes: [],
29
+ closure
30
+ )
31
+ }
32
+
33
+ /**
34
+ Asynchronous function with one argument.
35
+ */
36
+ public func AsyncFunction<R, A0: AnyArgument>(
37
+ _ name: String,
38
+ _ closure: @escaping (A0) throws -> R
39
+ ) -> AnyFunction {
40
+ return AsyncFunctionComponent(
41
+ name,
42
+ argTypes: [ArgumentType(A0.self)],
43
+ closure
44
+ )
45
+ }
46
+
47
+ /**
48
+ Asynchronous function with two arguments.
49
+ */
50
+ public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument>(
51
+ _ name: String,
52
+ _ closure: @escaping (A0, A1) throws -> R
53
+ ) -> AnyFunction {
54
+ return AsyncFunctionComponent(
55
+ name,
56
+ argTypes: [ArgumentType(A0.self), ArgumentType(A1.self)],
57
+ closure
58
+ )
59
+ }
60
+
61
+ /**
62
+ Asynchronous function with three arguments.
63
+ */
64
+ public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument>(
65
+ _ name: String,
66
+ _ closure: @escaping (A0, A1, A2) throws -> R
67
+ ) -> AnyFunction {
68
+ return AsyncFunctionComponent(
69
+ name,
70
+ argTypes: [
71
+ ArgumentType(A0.self),
72
+ ArgumentType(A1.self),
73
+ ArgumentType(A2.self)
74
+ ],
75
+ closure
76
+ )
77
+ }
78
+
79
+ /**
80
+ Asynchronous function with four arguments.
81
+ */
82
+ public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument>(
83
+ _ name: String,
84
+ _ closure: @escaping (A0, A1, A2, A3) throws -> R
85
+ ) -> AnyFunction {
86
+ return AsyncFunctionComponent(
87
+ name,
88
+ argTypes: [
89
+ ArgumentType(A0.self),
90
+ ArgumentType(A1.self),
91
+ ArgumentType(A2.self),
92
+ ArgumentType(A3.self)
93
+ ],
94
+ closure
95
+ )
96
+ }
97
+
98
+ /**
99
+ Asynchronous function with five arguments.
100
+ */
101
+ public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument>(
102
+ _ name: String,
103
+ _ closure: @escaping (A0, A1, A2, A3, A4) throws -> R
104
+ ) -> AnyFunction {
105
+ return AsyncFunctionComponent(
106
+ name,
107
+ argTypes: [
108
+ ArgumentType(A0.self),
109
+ ArgumentType(A1.self),
110
+ ArgumentType(A2.self),
111
+ ArgumentType(A3.self),
112
+ ArgumentType(A4.self)
113
+ ],
114
+ closure
115
+ )
116
+ }
117
+
118
+ /**
119
+ Asynchronous function with six arguments.
120
+ */
121
+ public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument, A5: AnyArgument>(
122
+ _ name: String,
123
+ _ closure: @escaping (A0, A1, A2, A3, A4, A5) throws -> R
124
+ ) -> AnyFunction {
125
+ return AsyncFunctionComponent(
126
+ name,
127
+ argTypes: [
128
+ ArgumentType(A0.self),
129
+ ArgumentType(A1.self),
130
+ ArgumentType(A2.self),
131
+ ArgumentType(A3.self),
132
+ ArgumentType(A4.self),
133
+ ArgumentType(A5.self)
134
+ ],
135
+ closure
136
+ )
137
+ }
138
+
139
+ /**
140
+ Asynchronous function with seven arguments.
141
+ */
142
+ public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument, A5: AnyArgument, A6: AnyArgument>(
143
+ _ name: String,
144
+ _ closure: @escaping (A0, A1, A2, A3, A4, A5, A6) throws -> R
145
+ ) -> AnyFunction {
146
+ return AsyncFunctionComponent(
147
+ name,
148
+ argTypes: [
149
+ ArgumentType(A0.self),
150
+ ArgumentType(A1.self),
151
+ ArgumentType(A2.self),
152
+ ArgumentType(A3.self),
153
+ ArgumentType(A4.self),
154
+ ArgumentType(A5.self),
155
+ ArgumentType(A6.self)
156
+ ],
157
+ closure
158
+ )
159
+ }
160
+
161
+ /**
162
+ Asynchronous function with eight arguments.
163
+ */
164
+ public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument, A5: AnyArgument, A6: AnyArgument, A7: AnyArgument>(
165
+ _ name: String,
166
+ _ closure: @escaping (A0, A1, A2, A3, A4, A5, A6, A7) throws -> R
167
+ ) -> AnyFunction {
168
+ return AsyncFunctionComponent(
169
+ name,
170
+ argTypes: [
171
+ ArgumentType(A0.self),
172
+ ArgumentType(A1.self),
173
+ ArgumentType(A2.self),
174
+ ArgumentType(A3.self),
175
+ ArgumentType(A4.self),
176
+ ArgumentType(A5.self),
177
+ ArgumentType(A6.self),
178
+ ArgumentType(A7.self)
179
+ ],
180
+ closure
181
+ )
182
+ }
@@ -1,23 +1,23 @@
1
1
  import Dispatch
2
2
 
3
- public final class ConcreteFunction<Args, ReturnType>: AnyFunction {
4
- public typealias ClosureType = (Args) -> ReturnType
3
+ public class ConcreteFunction<Args, ReturnType>: AnyFunction {
4
+ public typealias ClosureType = (Args) throws -> ReturnType
5
5
 
6
6
  public let name: String
7
7
 
8
- public var takesPromise: Bool {
9
- return argTypes.last is PromiseArgumentType
10
- }
8
+ public var takesPromise: Bool
11
9
 
12
10
  public var argumentsCount: Int {
13
- return argTypes.count - (takesPromise ? 1 : 0)
11
+ return argumentTypes.count
14
12
  }
15
13
 
16
14
  public var queue: DispatchQueue?
17
15
 
16
+ public var isAsync: Bool = true
17
+
18
18
  let closure: ClosureType
19
19
 
20
- let argTypes: [AnyArgumentType]
20
+ public let argumentTypes: [AnyArgumentType]
21
21
 
22
22
  init(
23
23
  _ name: String,
@@ -25,28 +25,38 @@ public final class ConcreteFunction<Args, ReturnType>: AnyFunction {
25
25
  _ closure: @escaping ClosureType
26
26
  ) {
27
27
  self.name = name
28
- self.argTypes = argTypes
28
+ self.takesPromise = argTypes.last is PromiseArgumentType
29
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")
30
38
  }
31
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
+ */
32
47
  public func call(args: [Any], promise: Promise) {
33
- let takesPromise = self.takesPromise
48
+ // Add promise to the array of arguments if necessary.
49
+ let arguments = takesPromise ? args + [promise] : args
34
50
  let returnedValue: ReturnType?
35
51
 
36
52
  do {
37
- var finalArgs = try castArguments(args)
38
-
39
- if takesPromise {
40
- finalArgs.append(promise)
41
- }
42
-
43
- let tuple = try Conversions.toTuple(finalArgs) as! Args
44
- returnedValue = closure(tuple)
53
+ let argumentsTuple = try Conversions.toTuple(arguments) as! Args
54
+ returnedValue = try closure(argumentsTuple)
45
55
  } catch let error as CodedError {
46
- promise.reject(error)
56
+ promise.reject(FunctionCallException(name).causedBy(error))
47
57
  return
48
- } catch let error {
49
- promise.reject(UnexpectedError(error))
58
+ } catch {
59
+ promise.reject(UnexpectedException(error))
50
60
  return
51
61
  }
52
62
  if !takesPromise {
@@ -54,28 +64,24 @@ public final class ConcreteFunction<Args, ReturnType>: AnyFunction {
54
64
  }
55
65
  }
56
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
+ */
57
74
  public func callSync(args: [Any]) -> Any {
58
75
  if takesPromise {
59
- var result: Any?
60
- let semaphore = DispatchSemaphore(value: 0)
61
-
62
- let promise = Promise {
63
- result = $0
64
- semaphore.signal()
65
- } rejecter: { error in
66
- semaphore.signal()
67
- }
68
- call(args: args, promise: promise)
69
- semaphore.wait()
70
- return result as Any
71
- } else {
72
- do {
73
- let finalArgs = try castArguments(args)
74
- let tuple = try Conversions.toTuple(finalArgs) as! Args
75
- return closure(tuple)
76
- } catch let error {
77
- return error
78
- }
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
79
85
  }
80
86
  }
81
87
 
@@ -84,27 +90,14 @@ public final class ConcreteFunction<Args, ReturnType>: AnyFunction {
84
90
  return self
85
91
  }
86
92
 
87
- private func argumentType(atIndex index: Int) -> AnyArgumentType? {
88
- return (0..<argTypes.count).contains(index) ? argTypes[index] : nil
89
- }
90
-
91
- private func castArguments(_ args: [Any]) throws -> [Any] {
92
- if args.count != argumentsCount {
93
- throw InvalidArgsNumberError(received: args.count, expected: argumentsCount)
94
- }
95
- return try args.enumerated().map { (index, arg) in
96
- let expectedType = argumentType(atIndex: index)
97
-
98
- // It's safe to unwrap since the arguments count matches.
99
- return try expectedType!.cast(arg)
100
- }
93
+ public func runSynchronously() -> Self {
94
+ self.isAsync = false
95
+ return self
101
96
  }
102
97
  }
103
98
 
104
- internal struct InvalidArgsNumberError: CodedError {
105
- let received: Int
106
- let expected: Int
107
- var description: String {
108
- "Received \(received) arguments, but \(expected) was expected."
99
+ internal class FunctionCallException: GenericException<String> {
100
+ override var reason: String {
101
+ "Call to function '\(param)' has been rejected"
109
102
  }
110
103
  }
@@ -0,0 +1,181 @@
1
+ // Copyright 2022-present 650 Industries. All rights reserved.
2
+
3
+ /**
4
+ Represents a function that can only be called synchronously.
5
+ - ToDo: Move some synchronous logic from `ConcreteFunction` (like `call(args:)`) to this class and drop the `isAsync` property.
6
+ */
7
+ internal final class SyncFunctionComponent<Args, ReturnType>: ConcreteFunction<Args, ReturnType> {
8
+ override init(
9
+ _ name: String,
10
+ argTypes: [AnyArgumentType],
11
+ _ closure: @escaping ConcreteFunction<Args, ReturnType>.ClosureType
12
+ ) {
13
+ super.init(name, argTypes: argTypes, closure)
14
+ self.isAsync = false
15
+ }
16
+ }
17
+
18
+ /**
19
+ Synchronous function without arguments.
20
+ */
21
+ public func Function<R>(
22
+ _ name: String,
23
+ _ closure: @escaping () throws -> R
24
+ ) -> AnyFunction {
25
+ return SyncFunctionComponent(
26
+ name,
27
+ argTypes: [],
28
+ closure
29
+ )
30
+ }
31
+
32
+ /**
33
+ Synchronous function with one argument.
34
+ */
35
+ public func Function<R, A0: AnyArgument>(
36
+ _ name: String,
37
+ _ closure: @escaping (A0) throws -> R
38
+ ) -> AnyFunction {
39
+ return SyncFunctionComponent(
40
+ name,
41
+ argTypes: [ArgumentType(A0.self)],
42
+ closure
43
+ )
44
+ }
45
+
46
+ /**
47
+ Synchronous function with two arguments.
48
+ */
49
+ public func Function<R, A0: AnyArgument, A1: AnyArgument>(
50
+ _ name: String,
51
+ _ closure: @escaping (A0, A1) throws -> R
52
+ ) -> AnyFunction {
53
+ return SyncFunctionComponent(
54
+ name,
55
+ argTypes: [ArgumentType(A0.self), ArgumentType(A1.self)],
56
+ closure
57
+ )
58
+ }
59
+
60
+ /**
61
+ Synchronous function with three arguments.
62
+ */
63
+ public func Function<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument>(
64
+ _ name: String,
65
+ _ closure: @escaping (A0, A1, A2) throws -> R
66
+ ) -> AnyFunction {
67
+ return SyncFunctionComponent(
68
+ name,
69
+ argTypes: [
70
+ ArgumentType(A0.self),
71
+ ArgumentType(A1.self),
72
+ ArgumentType(A2.self)
73
+ ],
74
+ closure
75
+ )
76
+ }
77
+
78
+ /**
79
+ Synchronous function with four arguments.
80
+ */
81
+ public func Function<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument>(
82
+ _ name: String,
83
+ _ closure: @escaping (A0, A1, A2, A3) throws -> R
84
+ ) -> AnyFunction {
85
+ return SyncFunctionComponent(
86
+ name,
87
+ argTypes: [
88
+ ArgumentType(A0.self),
89
+ ArgumentType(A1.self),
90
+ ArgumentType(A2.self),
91
+ ArgumentType(A3.self)
92
+ ],
93
+ closure
94
+ )
95
+ }
96
+
97
+ /**
98
+ Synchronous function with five arguments.
99
+ */
100
+ public func Function<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument>(
101
+ _ name: String,
102
+ _ closure: @escaping (A0, A1, A2, A3, A4) throws -> R
103
+ ) -> AnyFunction {
104
+ return SyncFunctionComponent(
105
+ name,
106
+ argTypes: [
107
+ ArgumentType(A0.self),
108
+ ArgumentType(A1.self),
109
+ ArgumentType(A2.self),
110
+ ArgumentType(A3.self),
111
+ ArgumentType(A4.self)
112
+ ],
113
+ closure
114
+ )
115
+ }
116
+
117
+ /**
118
+ Synchronous function with six arguments.
119
+ */
120
+ public func Function<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument, A5: AnyArgument>(
121
+ _ name: String,
122
+ _ closure: @escaping (A0, A1, A2, A3, A4, A5) throws -> R
123
+ ) -> AnyFunction {
124
+ return SyncFunctionComponent(
125
+ name,
126
+ argTypes: [
127
+ ArgumentType(A0.self),
128
+ ArgumentType(A1.self),
129
+ ArgumentType(A2.self),
130
+ ArgumentType(A3.self),
131
+ ArgumentType(A4.self),
132
+ ArgumentType(A5.self)
133
+ ],
134
+ closure
135
+ )
136
+ }
137
+
138
+ /**
139
+ Synchronous function with seven arguments.
140
+ */
141
+ public func Function<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument, A5: AnyArgument, A6: AnyArgument>(
142
+ _ name: String,
143
+ _ closure: @escaping (A0, A1, A2, A3, A4, A5, A6) throws -> R
144
+ ) -> AnyFunction {
145
+ return SyncFunctionComponent(
146
+ name,
147
+ argTypes: [
148
+ ArgumentType(A0.self),
149
+ ArgumentType(A1.self),
150
+ ArgumentType(A2.self),
151
+ ArgumentType(A3.self),
152
+ ArgumentType(A4.self),
153
+ ArgumentType(A5.self),
154
+ ArgumentType(A6.self)
155
+ ],
156
+ closure
157
+ )
158
+ }
159
+
160
+ /**
161
+ Synchronous function with eight arguments.
162
+ */
163
+ public func Function<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument, A5: AnyArgument, A6: AnyArgument, A7: AnyArgument>(
164
+ _ name: String,
165
+ _ closure: @escaping (A0, A1, A2, A3, A4, A5, A6, A7) throws -> R
166
+ ) -> AnyFunction {
167
+ return SyncFunctionComponent(
168
+ name,
169
+ argTypes: [
170
+ ArgumentType(A0.self),
171
+ ArgumentType(A1.self),
172
+ ArgumentType(A2.self),
173
+ ArgumentType(A3.self),
174
+ ArgumentType(A4.self),
175
+ ArgumentType(A5.self),
176
+ ArgumentType(A6.self),
177
+ ArgumentType(A7.self)
178
+ ],
179
+ closure
180
+ )
181
+ }