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
@@ -1,9 +1,7 @@
1
1
  // Copyright 2022-present 650 Industries. All rights reserved.
2
2
 
3
3
  open class Exception: CodedError, ChainableException, CustomStringConvertible, CustomDebugStringConvertible {
4
- open var name: String {
5
- return String(describing: Self.self)
6
- }
4
+ open lazy var name: String = String(describing: Self.self)
7
5
 
8
6
  /**
9
7
  String describing the reason of the exception.
@@ -25,15 +23,19 @@ open class Exception: CodedError, ChainableException, CustomStringConvertible, C
25
23
  self.origin = ExceptionOrigin(file: file, line: line, function: function)
26
24
  }
27
25
 
26
+ public init(name: String, description: String, file: String = #fileID, line: UInt = #line, function: String = #function) {
27
+ self.origin = ExceptionOrigin(file: file, line: line, function: function)
28
+ self.name = name
29
+ self.description = description
30
+ }
31
+
28
32
  // MARK: ChainableException
29
33
 
30
34
  open var cause: Error?
31
35
 
32
36
  // MARK: CustomStringConvertible
33
37
 
34
- open var description: String {
35
- return concatDescription(reason, withCause: cause, debug: false)
36
- }
38
+ open lazy var description: String = concatDescription(reason, withCause: cause, debug: false)
37
39
 
38
40
  // MARK: CustomDebugStringConvertible
39
41
 
@@ -6,8 +6,9 @@
6
6
  public class UnexpectedException: Exception {
7
7
  private let errorDescription: String
8
8
 
9
- public init(_ error: Error) {
9
+ public init(_ error: Error, file: String = #fileID, line: UInt = #line, function: String = #function) {
10
10
  self.errorDescription = error.localizedDescription
11
+ super.init(file: file, line: line, function: function)
11
12
  }
12
13
 
13
14
  public override var reason: String {
@@ -0,0 +1,5 @@
1
+ #import <React/RCTBridgeModule.h>
2
+
3
+ @interface RCT_EXTERN_MODULE(ExpoBridgeModule, NSObject)
4
+
5
+ @end
@@ -0,0 +1,65 @@
1
+ // Copyright 2022-present 650 Industries. All rights reserved.
2
+
3
+ import React
4
+ import Foundation
5
+
6
+ /**
7
+ The classic bridge module that is responsible for:
8
+ - Creating and owning the `AppContext` when the Expo modules architecture is automatically initialized
9
+ by React Native (as opposed to native unit tests, where React Native is not used at all).
10
+ - Installing the host object to the runtime.
11
+ */
12
+ @objc(ExpoBridgeModule)
13
+ public final class ExpoBridgeModule: NSObject, RCTBridgeModule {
14
+ @objc
15
+ public let appContext: AppContext
16
+
17
+ /**
18
+ The initializer that is used by React Native when it loads bridge modules.
19
+ In this scenario, we create an `AppContext` that manages the
20
+ architecture of Expo modules and the app itself.
21
+ */
22
+ override init() {
23
+ appContext = AppContext().useModulesProvider("ExpoModulesProvider")
24
+ appContext.moduleRegistry.register(moduleType: NativeModulesProxyModule.self)
25
+ super.init()
26
+
27
+ // Listen to React Native notifications posted just before the JS is executed.
28
+ NotificationCenter.default.addObserver(self,
29
+ selector: #selector(javaScriptWillStartExecutingNotification(_:)),
30
+ name: NSNotification.Name.RCTJavaScriptWillStartExecuting,
31
+ object: nil)
32
+ }
33
+
34
+ deinit {
35
+ NotificationCenter.default.removeObserver(self)
36
+ }
37
+
38
+ // MARK: - RCTBridgeModule
39
+
40
+ public static func moduleName() -> String! {
41
+ return "Expo"
42
+ }
43
+
44
+ public static func requiresMainQueueSetup() -> Bool {
45
+ return true
46
+ }
47
+
48
+ public var bridge: RCTBridge! {
49
+ didSet {
50
+ appContext.reactBridge = bridge
51
+ }
52
+ }
53
+
54
+ // MARK: - Notifications
55
+
56
+ @objc
57
+ public func javaScriptWillStartExecutingNotification(_ notification: Notification) {
58
+ if (notification.object as? RCTBridge)?.batched == bridge {
59
+ // The JavaScript bundle will start executing in a moment,
60
+ // so the runtime is already initialized and we can get it from the bridge.
61
+ // This should automatically install the ExpoModules host object.
62
+ appContext.runtime = EXJavaScriptRuntimeManager.runtime(fromBridge: bridge)
63
+ }
64
+ }
65
+ }
@@ -1,57 +1,59 @@
1
- import Dispatch
1
+ /**
2
+ An alias to `Result<Any, Exception>` which can be passed to the function callback.
3
+ */
4
+ public typealias FunctionCallResult = Result<Any, Exception>
2
5
 
3
6
  /**
4
7
  A protocol for any type-erased function.
5
8
  */
6
- public protocol AnyFunction: AnyDefinition {
9
+ internal protocol AnyFunction: AnyDefinition, JavaScriptObjectBuilder {
7
10
  /**
8
11
  Name of the function. JavaScript refers to the function by this name.
9
12
  */
10
13
  var name: String { get }
11
14
 
12
15
  /**
13
- Bool value indicating whether the function takes promise as the last argument.
14
- */
15
- var takesPromise: Bool { get }
16
-
17
- /**
18
- An array of argument types that the function takes. If the last type is `Promise`, it's not included.
16
+ An array of the dynamic types that the function takes. If the last type is `Promise`, it's not included.
19
17
  */
20
- var argumentTypes: [AnyArgumentType] { get }
18
+ var dynamicArgumentTypes: [AnyDynamicType] { get }
21
19
 
22
20
  /**
23
- A number of arguments the function takes. If the last argument is of type `Promise`, it is not counted.
21
+ A number of arguments the function takes. If the function expects to receive an owner (`this`) as the first argument, it's not counted.
22
+ Similarly, if the last argument is of type `Promise`, it is not counted.
24
23
  */
25
24
  var argumentsCount: Int { get }
26
25
 
27
26
  /**
28
- Dispatch queue on which each function's call is run.
29
- */
30
- var queue: DispatchQueue? { get }
31
-
32
- /**
33
- Whether the function needs to be called asynchronously from JavaScript.
27
+ Indicates whether the function's arguments starts from the owner that calls this function.
34
28
  */
35
- var isAsync: Bool { get }
29
+ var takesOwner: Bool { get set }
36
30
 
37
31
  /**
38
- Calls the function on given module with arguments and a promise.
32
+ Calls the function with a given owner and arguments and returns a result through the callback block.
33
+ - Parameters:
34
+ - owner: An object that calls this function. If the `takesOwner` property is true
35
+ and type of the first argument matches the owner type, it's being passed as the argument.
36
+ - args: An array of arguments to pass to the function. They could be Swift primitives
37
+ when invoked through the bridge and in unit tests or `JavaScriptValue`s
38
+ when the function is called through the JSI.
39
+ - callback: A callback that receives a result of the function execution.
39
40
  */
40
- func call(args: [Any], promise: Promise)
41
-
42
- /**
43
- Synchronously calls the function with given arguments. If the function takes a promise,
44
- the current thread will be locked until the promise rejects or resolves with the return value.
45
- */
46
- func callSync(args: [Any]) -> Any
41
+ func call(by owner: AnyObject?, withArguments args: [Any], callback: @escaping (FunctionCallResult) -> ())
42
+ }
47
43
 
44
+ extension AnyFunction {
48
45
  /**
49
- Specifies on which queue the function should run.
46
+ Calls the function just like `call(by:withArguments:callback:)`, but without an owner
47
+ and with an empty callback. Might be useful when you only want to call the function,
48
+ but don't care about the result.
50
49
  */
51
- func runOnQueue(_ queue: DispatchQueue?) -> Self
50
+ func call(withArguments args: [Any]) {
51
+ call(by: nil, withArguments: args, callback: { _ in })
52
+ }
53
+ }
52
54
 
53
- /**
54
- Makes the JavaScript function synchronous.
55
- */
56
- func runSynchronously() -> Self
55
+ internal class FunctionCallException: GenericException<String> {
56
+ override var reason: String {
57
+ "Calling the '\(param)' function has failed"
58
+ }
57
59
  }
@@ -1,31 +1,160 @@
1
1
  // Copyright 2022-present 650 Industries. All rights reserved.
2
2
 
3
+ import Dispatch
4
+
3
5
  /**
4
- Represents a function that can only be called asynchronously, thus its JavaScript equivalent returns a Promise.
6
+ Type-erased protocol for asynchronous functions.
7
+ */
8
+ internal protocol AnyAsyncFunctionComponent: AnyFunction {
9
+ /**
10
+ Specifies on which queue the function should run.
11
+ */
12
+ func runOnQueue(_ queue: DispatchQueue?) -> Self
13
+ }
5
14
 
6
- - ToDo: Move some asynchronous logic from `ConcreteFunction` (like `call(args:promise:)`) to this class and drop the `isAsync` property.
15
+ /**
16
+ Represents a function that can only be called asynchronously, thus its JavaScript equivalent returns a Promise.
7
17
  */
8
- internal final class AsyncFunctionComponent<Args, ReturnType>: ConcreteFunction<Args, ReturnType> {
9
- override init(
18
+ public final class AsyncFunctionComponent<Args, FirstArgType, ReturnType>: AnyAsyncFunctionComponent {
19
+ typealias ClosureType = (Args) throws -> ReturnType
20
+
21
+ /**
22
+ The underlying closure to run when the function is called.
23
+ */
24
+ let body: ClosureType
25
+
26
+ /**
27
+ Bool value indicating whether the function takes promise as the last argument.
28
+ */
29
+ let takesPromise: Bool
30
+
31
+ /**
32
+ Dispatch queue on which each function's call is run.
33
+ */
34
+ var queue: DispatchQueue?
35
+
36
+ init(
10
37
  _ name: String,
11
- argTypes: [AnyArgumentType],
12
- _ closure: @escaping ConcreteFunction<Args, ReturnType>.ClosureType
38
+ firstArgType: FirstArgType.Type,
39
+ dynamicArgumentTypes: [AnyDynamicType],
40
+ _ body: @escaping ClosureType
13
41
  ) {
14
- super.init(name, argTypes: argTypes, closure)
15
- self.isAsync = true
42
+ self.name = name
43
+ self.takesPromise = dynamicArgumentTypes.last?.wraps(Promise.self) ?? false
44
+ self.body = body
45
+
46
+ // Drop the last argument type if it's the `Promise`.
47
+ self.dynamicArgumentTypes = takesPromise ? dynamicArgumentTypes.dropLast(1) : dynamicArgumentTypes
48
+ }
49
+
50
+ // MARK: - AnyFunction
51
+
52
+ let name: String
53
+
54
+ let dynamicArgumentTypes: [AnyDynamicType]
55
+
56
+ var argumentsCount: Int {
57
+ return dynamicArgumentTypes.count - (takesOwner ? 1 : 0)
58
+ }
59
+
60
+ var takesOwner: Bool = false
61
+
62
+ func call(by owner: AnyObject?, withArguments args: [Any], callback: @escaping (FunctionCallResult) -> ()) {
63
+ let promise = Promise { value in
64
+ callback(.success(value as Any))
65
+ } rejecter: { exception in
66
+ callback(.failure(exception))
67
+ }
68
+ var arguments: [Any] = []
69
+
70
+ do {
71
+ arguments = concat(
72
+ arguments: try cast(arguments: args, forFunction: self),
73
+ withOwner: owner,
74
+ forFunction: self
75
+ )
76
+ } catch let error as Exception {
77
+ callback(.failure(error))
78
+ return
79
+ } catch {
80
+ callback(.failure(UnexpectedException(error)))
81
+ return
82
+ }
83
+
84
+ // Add promise to the array of arguments if necessary.
85
+ if takesPromise {
86
+ arguments.append(promise)
87
+ }
88
+
89
+ let queue = queue ?? DispatchQueue.global(qos: .default)
90
+
91
+ queue.async { [body, name] in
92
+ let returnedValue: ReturnType?
93
+
94
+ do {
95
+ let argumentsTuple = try Conversions.toTuple(arguments) as! Args
96
+ returnedValue = try body(argumentsTuple)
97
+ } catch let error as Exception {
98
+ promise.reject(FunctionCallException(name).causedBy(error))
99
+ return
100
+ } catch {
101
+ promise.reject(UnexpectedException(error))
102
+ return
103
+ }
104
+ if !self.takesPromise {
105
+ promise.resolve(returnedValue)
106
+ }
107
+ }
108
+ }
109
+
110
+ // MARK: - JavaScriptObjectBuilder
111
+
112
+ func build(inRuntime runtime: JavaScriptRuntime) -> JavaScriptObject {
113
+ return runtime.createAsyncFunction(name, argsCount: argumentsCount) { [weak self, name] this, args, resolve, reject in
114
+ guard let self = self else {
115
+ let exception = NativeFunctionUnavailableException(name)
116
+ return reject(exception.code, exception.description, nil)
117
+ }
118
+ self.call(by: this, withArguments: args) { result in
119
+ switch result {
120
+ case .failure(let error):
121
+ reject(error.code, error.description, nil)
122
+ case .success(let value):
123
+ resolve(value)
124
+ }
125
+ }
126
+ }
127
+ }
128
+
129
+ // MARK: - AnyAsyncFunctionComponent
130
+
131
+ public func runOnQueue(_ queue: DispatchQueue?) -> Self {
132
+ self.queue = queue
133
+ return self
134
+ }
135
+ }
136
+
137
+ // MARK: - Exceptions
138
+
139
+ internal final class NativeFunctionUnavailableException: GenericException<String> {
140
+ override var reason: String {
141
+ return "Native function '\(param)' is no longer available in memory"
16
142
  }
17
143
  }
18
144
 
145
+ // MARK: - Factories
146
+
19
147
  /**
20
148
  Asynchronous function without arguments.
21
149
  */
22
150
  public func AsyncFunction<R>(
23
151
  _ name: String,
24
152
  _ closure: @escaping () throws -> R
25
- ) -> AnyFunction {
153
+ ) -> AsyncFunctionComponent<(), Void, R> {
26
154
  return AsyncFunctionComponent(
27
155
  name,
28
- argTypes: [],
156
+ firstArgType: Void.self,
157
+ dynamicArgumentTypes: [],
29
158
  closure
30
159
  )
31
160
  }
@@ -36,10 +165,11 @@ public func AsyncFunction<R>(
36
165
  public func AsyncFunction<R, A0: AnyArgument>(
37
166
  _ name: String,
38
167
  _ closure: @escaping (A0) throws -> R
39
- ) -> AnyFunction {
168
+ ) -> AsyncFunctionComponent<(A0), A0, R> {
40
169
  return AsyncFunctionComponent(
41
170
  name,
42
- argTypes: [ArgumentType(A0.self)],
171
+ firstArgType: A0.self,
172
+ dynamicArgumentTypes: [~A0.self],
43
173
  closure
44
174
  )
45
175
  }
@@ -50,10 +180,11 @@ public func AsyncFunction<R, A0: AnyArgument>(
50
180
  public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument>(
51
181
  _ name: String,
52
182
  _ closure: @escaping (A0, A1) throws -> R
53
- ) -> AnyFunction {
183
+ ) -> AsyncFunctionComponent<(A0, A1), A0, R> {
54
184
  return AsyncFunctionComponent(
55
185
  name,
56
- argTypes: [ArgumentType(A0.self), ArgumentType(A1.self)],
186
+ firstArgType: A0.self,
187
+ dynamicArgumentTypes: [~A0.self, ~A1.self],
57
188
  closure
58
189
  )
59
190
  }
@@ -64,13 +195,14 @@ public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument>(
64
195
  public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument>(
65
196
  _ name: String,
66
197
  _ closure: @escaping (A0, A1, A2) throws -> R
67
- ) -> AnyFunction {
198
+ ) -> AsyncFunctionComponent<(A0, A1, A2), A0, R> {
68
199
  return AsyncFunctionComponent(
69
200
  name,
70
- argTypes: [
71
- ArgumentType(A0.self),
72
- ArgumentType(A1.self),
73
- ArgumentType(A2.self)
201
+ firstArgType: A0.self,
202
+ dynamicArgumentTypes: [
203
+ ~A0.self,
204
+ ~A1.self,
205
+ ~A2.self
74
206
  ],
75
207
  closure
76
208
  )
@@ -82,14 +214,15 @@ public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument>(
82
214
  public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument>(
83
215
  _ name: String,
84
216
  _ closure: @escaping (A0, A1, A2, A3) throws -> R
85
- ) -> AnyFunction {
217
+ ) -> AsyncFunctionComponent<(A0, A1, A2, A3), A0, R> {
86
218
  return AsyncFunctionComponent(
87
219
  name,
88
- argTypes: [
89
- ArgumentType(A0.self),
90
- ArgumentType(A1.self),
91
- ArgumentType(A2.self),
92
- ArgumentType(A3.self)
220
+ firstArgType: A0.self,
221
+ dynamicArgumentTypes: [
222
+ ~A0.self,
223
+ ~A1.self,
224
+ ~A2.self,
225
+ ~A3.self
93
226
  ],
94
227
  closure
95
228
  )
@@ -101,15 +234,16 @@ public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument,
101
234
  public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument>(
102
235
  _ name: String,
103
236
  _ closure: @escaping (A0, A1, A2, A3, A4) throws -> R
104
- ) -> AnyFunction {
237
+ ) -> AsyncFunctionComponent<(A0, A1, A2, A3, A4), A0, R> {
105
238
  return AsyncFunctionComponent(
106
239
  name,
107
- argTypes: [
108
- ArgumentType(A0.self),
109
- ArgumentType(A1.self),
110
- ArgumentType(A2.self),
111
- ArgumentType(A3.self),
112
- ArgumentType(A4.self)
240
+ firstArgType: A0.self,
241
+ dynamicArgumentTypes: [
242
+ ~A0.self,
243
+ ~A1.self,
244
+ ~A2.self,
245
+ ~A3.self,
246
+ ~A4.self
113
247
  ],
114
248
  closure
115
249
  )
@@ -121,16 +255,17 @@ public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument,
121
255
  public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument, A5: AnyArgument>(
122
256
  _ name: String,
123
257
  _ closure: @escaping (A0, A1, A2, A3, A4, A5) throws -> R
124
- ) -> AnyFunction {
258
+ ) -> AsyncFunctionComponent<(A0, A1, A2, A3, A4, A5), A0, R> {
125
259
  return AsyncFunctionComponent(
126
260
  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)
261
+ firstArgType: A0.self,
262
+ dynamicArgumentTypes: [
263
+ ~A0.self,
264
+ ~A1.self,
265
+ ~A2.self,
266
+ ~A3.self,
267
+ ~A4.self,
268
+ ~A5.self
134
269
  ],
135
270
  closure
136
271
  )
@@ -142,17 +277,18 @@ public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument,
142
277
  public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument, A5: AnyArgument, A6: AnyArgument>(
143
278
  _ name: String,
144
279
  _ closure: @escaping (A0, A1, A2, A3, A4, A5, A6) throws -> R
145
- ) -> AnyFunction {
280
+ ) -> AsyncFunctionComponent<(A0, A1, A2, A3, A4, A5, A6), A0, R> {
146
281
  return AsyncFunctionComponent(
147
282
  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)
283
+ firstArgType: A0.self,
284
+ dynamicArgumentTypes: [
285
+ ~A0.self,
286
+ ~A1.self,
287
+ ~A2.self,
288
+ ~A3.self,
289
+ ~A4.self,
290
+ ~A5.self,
291
+ ~A6.self
156
292
  ],
157
293
  closure
158
294
  )
@@ -164,18 +300,19 @@ public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument,
164
300
  public func AsyncFunction<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument, A5: AnyArgument, A6: AnyArgument, A7: AnyArgument>(
165
301
  _ name: String,
166
302
  _ closure: @escaping (A0, A1, A2, A3, A4, A5, A6, A7) throws -> R
167
- ) -> AnyFunction {
303
+ ) -> AsyncFunctionComponent<(A0, A1, A2, A3, A4, A5, A6, A7), A0, R> {
168
304
  return AsyncFunctionComponent(
169
305
  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)
306
+ firstArgType: A0.self,
307
+ dynamicArgumentTypes: [
308
+ ~A0.self,
309
+ ~A1.self,
310
+ ~A2.self,
311
+ ~A3.self,
312
+ ~A4.self,
313
+ ~A5.self,
314
+ ~A6.self,
315
+ ~A7.self
179
316
  ],
180
317
  closure
181
318
  )