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.
- package/CHANGELOG.md +18 -5
- package/android/CMakeLists.txt +154 -0
- package/android/build.gradle +293 -5
- package/android/src/main/cpp/Exceptions.cpp +22 -0
- package/android/src/main/cpp/Exceptions.h +38 -0
- package/android/src/main/cpp/ExpoModulesHostObject.cpp +47 -0
- package/android/src/main/cpp/ExpoModulesHostObject.h +32 -0
- package/android/src/main/cpp/JNIFunctionBody.cpp +29 -0
- package/android/src/main/cpp/JNIFunctionBody.h +50 -0
- package/android/src/main/cpp/JNIInjector.cpp +19 -0
- package/android/src/main/cpp/JSIInteropModuleRegistry.cpp +122 -0
- package/android/src/main/cpp/JSIInteropModuleRegistry.h +96 -0
- package/android/src/main/cpp/JSIObjectWrapper.h +33 -0
- package/android/src/main/cpp/JSITypeConverter.h +84 -0
- package/android/src/main/cpp/JavaScriptModuleObject.cpp +138 -0
- package/android/src/main/cpp/JavaScriptModuleObject.h +122 -0
- package/android/src/main/cpp/JavaScriptObject.cpp +125 -0
- package/android/src/main/cpp/JavaScriptObject.h +131 -0
- package/android/src/main/cpp/JavaScriptRuntime.cpp +127 -0
- package/android/src/main/cpp/JavaScriptRuntime.h +87 -0
- package/android/src/main/cpp/JavaScriptValue.cpp +172 -0
- package/android/src/main/cpp/JavaScriptValue.h +78 -0
- package/android/src/main/cpp/MethodMetadata.cpp +230 -0
- package/android/src/main/cpp/MethodMetadata.h +92 -0
- package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +2 -0
- package/android/src/main/java/expo/modules/core/errors/ContextDestroyedException.kt +7 -0
- package/android/src/main/java/expo/modules/interfaces/permissions/Permissions.java +30 -0
- package/android/src/main/java/expo/modules/kotlin/AppContext.kt +49 -1
- package/android/src/main/java/expo/modules/kotlin/ConcatIterator.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +15 -12
- package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +39 -3
- package/android/src/main/java/expo/modules/kotlin/defaultmodules/ErrorManagerModule.kt +2 -2
- package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +13 -0
- package/android/src/main/java/expo/modules/kotlin/exception/ExceptionDecorator.kt +2 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AnyFunction.kt +19 -14
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +29 -7
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +13 -13
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionComponent.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromiseComponent.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/functions/SuspendFunctionComponent.kt +56 -0
- package/android/src/main/java/expo/modules/kotlin/functions/SyncFunctionComponent.kt +28 -0
- package/android/src/main/java/expo/modules/kotlin/jni/CppType.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JNIFunctionBody.kt +39 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JSIInteropModuleRegistry.kt +89 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptModuleObject.kt +44 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptObject.kt +113 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptValue.kt +35 -0
- package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +15 -5
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +65 -111
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +35 -2
- package/android/src/main/java/expo/modules/kotlin/providers/AppContextProvider.kt +14 -0
- package/android/src/main/java/expo/modules/kotlin/providers/CurrentActivityProvider.kt +22 -0
- package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +19 -2
- package/android/src/main/java/expo/modules/kotlin/types/AnyType.kt +3 -2
- package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +7 -2
- package/android/src/main/java/expo/modules/kotlin/types/BasicTypeConverters.kt +68 -20
- package/android/src/main/java/expo/modules/kotlin/types/EnumTypeConverter.kt +50 -22
- package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +18 -2
- package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +18 -2
- package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +17 -2
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +43 -3
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +5 -0
- package/build/NativeModulesProxy.native.d.ts.map +1 -1
- package/build/NativeModulesProxy.native.js +9 -3
- package/build/NativeModulesProxy.native.js.map +1 -1
- package/ios/AppDelegates/EXAppDelegatesLoader.m +1 -2
- package/ios/ExpoModulesCore.podspec +1 -1
- package/ios/JSI/EXJSIConversions.mm +6 -0
- package/ios/JSI/EXJSIInstaller.h +15 -21
- package/ios/JSI/EXJSIInstaller.mm +39 -3
- package/ios/JSI/EXJSIUtils.h +47 -3
- package/ios/JSI/EXJSIUtils.mm +88 -4
- package/ios/JSI/EXJavaScriptObject.h +11 -18
- package/ios/JSI/EXJavaScriptObject.mm +37 -18
- package/ios/JSI/EXJavaScriptRuntime.h +43 -9
- package/ios/JSI/EXJavaScriptRuntime.mm +70 -27
- package/ios/JSI/EXJavaScriptTypedArray.h +30 -0
- package/ios/JSI/EXJavaScriptTypedArray.mm +29 -0
- package/ios/JSI/EXJavaScriptValue.h +3 -2
- package/ios/JSI/EXJavaScriptValue.mm +17 -20
- package/ios/JSI/EXJavaScriptWeakObject.h +23 -0
- package/ios/JSI/EXJavaScriptWeakObject.mm +53 -0
- package/ios/JSI/EXObjectDeallocator.h +27 -0
- package/ios/JSI/ExpoModulesHostObject.h +3 -3
- package/ios/JSI/ExpoModulesHostObject.mm +4 -4
- package/ios/JSI/JavaScriptRuntime.swift +38 -1
- package/ios/JSI/JavaScriptValue.swift +7 -0
- package/ios/JSI/TypedArray.cpp +67 -0
- package/ios/JSI/TypedArray.h +46 -0
- package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +0 -11
- package/ios/NativeModulesProxy/EXNativeModulesProxy.h +17 -10
- package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +85 -77
- package/ios/NativeModulesProxy/NativeModulesProxyModule.swift +17 -0
- package/ios/Services/EXReactNativeEventEmitter.h +2 -2
- package/ios/Services/EXReactNativeEventEmitter.m +11 -6
- package/ios/Swift/AppContext.swift +208 -28
- package/ios/Swift/Arguments/AnyArgument.swift +18 -0
- package/ios/Swift/Arguments/{Types/EnumArgumentType.swift → EnumArgument.swift} +2 -17
- package/ios/Swift/Classes/ClassComponent.swift +95 -0
- package/ios/Swift/Classes/ClassComponentElement.swift +33 -0
- package/ios/Swift/Classes/ClassComponentElementsBuilder.swift +34 -0
- package/ios/Swift/Classes/ClassComponentFactories.swift +96 -0
- package/ios/Swift/DynamicTypes/AnyDynamicType.swift +44 -0
- package/ios/Swift/DynamicTypes/DynamicArrayType.swift +56 -0
- package/ios/Swift/DynamicTypes/DynamicConvertibleType.swift +27 -0
- package/ios/Swift/DynamicTypes/DynamicEnumType.swift +27 -0
- package/ios/Swift/DynamicTypes/DynamicOptionalType.swift +63 -0
- package/ios/Swift/DynamicTypes/DynamicRawType.swift +33 -0
- package/ios/Swift/DynamicTypes/DynamicSharedObjectType.swift +37 -0
- package/ios/Swift/DynamicTypes/DynamicType.swift +39 -0
- package/ios/Swift/DynamicTypes/DynamicTypedArrayType.swift +46 -0
- package/ios/Swift/Exceptions/CodedError.swift +1 -1
- package/ios/Swift/Exceptions/Exception.swift +8 -6
- package/ios/Swift/Exceptions/UnexpectedException.swift +2 -1
- package/ios/Swift/ExpoBridgeModule.m +5 -0
- package/ios/Swift/ExpoBridgeModule.swift +65 -0
- package/ios/Swift/Functions/AnyFunction.swift +33 -31
- package/ios/Swift/Functions/AsyncFunctionComponent.swift +196 -59
- package/ios/Swift/Functions/SyncFunctionComponent.swift +142 -58
- package/ios/Swift/JavaScriptUtils.swift +32 -57
- package/ios/Swift/Logging/LogHandlers.swift +39 -0
- package/ios/Swift/Logging/LogType.swift +62 -0
- package/ios/Swift/Logging/Logger.swift +198 -0
- package/ios/Swift/ModuleHolder.swift +19 -54
- package/ios/Swift/ModuleRegistry.swift +7 -1
- package/ios/Swift/Modules/AnyModule.swift +3 -3
- package/ios/Swift/ModulesProvider.swift +2 -0
- package/ios/Swift/Objects/JavaScriptObjectBuilder.swift +37 -0
- package/ios/Swift/Objects/ObjectDefinition.swift +74 -1
- package/ios/Swift/Objects/ObjectDefinitionComponents.swift +77 -68
- package/ios/Swift/Objects/PropertyComponent.swift +147 -0
- package/ios/Swift/Promise.swift +12 -3
- package/ios/Swift/Records/Field.swift +2 -2
- package/ios/Swift/SharedObjects/SharedObject.swift +20 -0
- package/ios/Swift/SharedObjects/SharedObjectRegistry.swift +129 -0
- package/ios/Swift/TypedArrays/AnyTypedArray.swift +11 -0
- package/ios/Swift/TypedArrays/ConcreteTypedArrays.swift +56 -0
- package/ios/Swift/TypedArrays/GenericTypedArray.swift +49 -0
- package/ios/Swift/TypedArrays/TypedArray.swift +80 -0
- package/ios/Swift/Utilities.swift +28 -0
- package/ios/Swift/Views/ConcreteViewProp.swift +3 -3
- package/ios/Swift/Views/ViewManagerDefinitionComponents.swift +2 -2
- package/ios/Tests/ClassComponentSpec.swift +210 -0
- package/ios/Tests/DynamicTypeSpec.swift +336 -0
- package/ios/Tests/EnumArgumentSpec.swift +48 -0
- package/ios/Tests/ExpoModulesSpec.swift +17 -3
- package/ios/Tests/FunctionSpec.swift +167 -118
- package/ios/Tests/Mocks/ModuleMocks.swift +1 -1
- package/ios/Tests/PropertyComponentSpec.swift +95 -0
- package/ios/Tests/SharedObjectRegistrySpec.swift +109 -0
- package/ios/Tests/TypedArraysSpec.swift +136 -0
- package/package.json +2 -2
- package/src/NativeModulesProxy.native.ts +13 -3
- package/src/ts-declarations/ExpoModules.d.ts +7 -0
- package/tsconfig.json +1 -1
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromise.kt +0 -15
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncSuspendFunction.kt +0 -36
- package/ios/Swift/Arguments/AnyArgumentType.swift +0 -13
- package/ios/Swift/Arguments/ArgumentType.swift +0 -28
- package/ios/Swift/Arguments/Types/ArrayArgumentType.swift +0 -42
- package/ios/Swift/Arguments/Types/ConvertibleArgumentType.swift +0 -16
- package/ios/Swift/Arguments/Types/OptionalArgumentType.swift +0 -49
- package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +0 -15
- package/ios/Swift/Arguments/Types/RawArgumentType.swift +0 -25
- package/ios/Swift/Functions/ConcreteFunction.swift +0 -103
- package/ios/Swift/SwiftInteropBridge.swift +0 -155
- 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,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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
18
|
+
var dynamicArgumentTypes: [AnyDynamicType] { get }
|
|
21
19
|
|
|
22
20
|
/**
|
|
23
|
-
A number of arguments the function takes. If the
|
|
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
|
-
|
|
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
|
|
29
|
+
var takesOwner: Bool { get set }
|
|
36
30
|
|
|
37
31
|
/**
|
|
38
|
-
Calls the function
|
|
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],
|
|
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
|
-
|
|
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
|
|
50
|
+
func call(withArguments args: [Any]) {
|
|
51
|
+
call(by: nil, withArguments: args, callback: { _ in })
|
|
52
|
+
}
|
|
53
|
+
}
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
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
|
-
|
|
15
|
+
/**
|
|
16
|
+
Represents a function that can only be called asynchronously, thus its JavaScript equivalent returns a Promise.
|
|
7
17
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
12
|
-
|
|
38
|
+
firstArgType: FirstArgType.Type,
|
|
39
|
+
dynamicArgumentTypes: [AnyDynamicType],
|
|
40
|
+
_ body: @escaping ClosureType
|
|
13
41
|
) {
|
|
14
|
-
|
|
15
|
-
self.
|
|
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
|
-
) ->
|
|
153
|
+
) -> AsyncFunctionComponent<(), Void, R> {
|
|
26
154
|
return AsyncFunctionComponent(
|
|
27
155
|
name,
|
|
28
|
-
|
|
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
|
-
) ->
|
|
168
|
+
) -> AsyncFunctionComponent<(A0), A0, R> {
|
|
40
169
|
return AsyncFunctionComponent(
|
|
41
170
|
name,
|
|
42
|
-
|
|
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
|
-
) ->
|
|
183
|
+
) -> AsyncFunctionComponent<(A0, A1), A0, R> {
|
|
54
184
|
return AsyncFunctionComponent(
|
|
55
185
|
name,
|
|
56
|
-
|
|
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
|
-
) ->
|
|
198
|
+
) -> AsyncFunctionComponent<(A0, A1, A2), A0, R> {
|
|
68
199
|
return AsyncFunctionComponent(
|
|
69
200
|
name,
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
) ->
|
|
217
|
+
) -> AsyncFunctionComponent<(A0, A1, A2, A3), A0, R> {
|
|
86
218
|
return AsyncFunctionComponent(
|
|
87
219
|
name,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
) ->
|
|
237
|
+
) -> AsyncFunctionComponent<(A0, A1, A2, A3, A4), A0, R> {
|
|
105
238
|
return AsyncFunctionComponent(
|
|
106
239
|
name,
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
) ->
|
|
258
|
+
) -> AsyncFunctionComponent<(A0, A1, A2, A3, A4, A5), A0, R> {
|
|
125
259
|
return AsyncFunctionComponent(
|
|
126
260
|
name,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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
|
-
) ->
|
|
280
|
+
) -> AsyncFunctionComponent<(A0, A1, A2, A3, A4, A5, A6), A0, R> {
|
|
146
281
|
return AsyncFunctionComponent(
|
|
147
282
|
name,
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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
|
-
) ->
|
|
303
|
+
) -> AsyncFunctionComponent<(A0, A1, A2, A3, A4, A5, A6, A7), A0, R> {
|
|
168
304
|
return AsyncFunctionComponent(
|
|
169
305
|
name,
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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
|
)
|