expo-modules-core 0.4.8 → 0.5.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 +14 -1
- package/android/build.gradle +30 -2
- package/android/src/main/java/expo/modules/adapters/react/ModuleRegistryAdapter.java +27 -5
- package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +49 -5
- package/android/src/main/java/expo/modules/core/BasePackage.java +6 -0
- package/android/src/main/java/expo/modules/core/ModulePriorities.kt +25 -0
- package/android/src/main/java/expo/modules/core/interfaces/ActivityEventListener.java +3 -1
- package/android/src/main/java/expo/modules/core/interfaces/Package.java +4 -0
- package/android/src/main/java/expo/modules/core/interfaces/ReactActivityHandler.kt +18 -0
- package/android/src/main/java/expo/modules/core/interfaces/ReactNativeHostHandler.kt +14 -0
- package/android/src/main/java/expo/modules/core/utilities/KotlinUtilities.kt +23 -0
- package/android/src/main/java/expo/modules/kotlin/AppContext.kt +166 -0
- package/android/src/main/java/expo/modules/kotlin/DynamicExtenstions.kt +9 -0
- package/android/src/main/java/expo/modules/kotlin/ExpoModulesHelper.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/KPromiseWrapper.kt +23 -0
- package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +98 -0
- package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +41 -0
- package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +56 -0
- package/android/src/main/java/expo/modules/kotlin/ModulesProvider.kt +7 -0
- package/android/src/main/java/expo/modules/kotlin/Promise.kt +13 -0
- package/android/src/main/java/expo/modules/kotlin/ReactLifecycleDelegate.kt +39 -0
- package/android/src/main/java/expo/modules/kotlin/ReadableArrayIterator.kt +14 -0
- package/android/src/main/java/expo/modules/kotlin/ReadableTypeExtensions.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/allocators/ObjectConstructor.kt +5 -0
- package/android/src/main/java/expo/modules/kotlin/allocators/ObjectConstructorFactory.kt +31 -0
- package/android/src/main/java/expo/modules/kotlin/allocators/UnsafeAllocator.kt +49 -0
- package/android/src/main/java/expo/modules/kotlin/events/EventListener.kt +39 -0
- package/android/src/main/java/expo/modules/kotlin/events/EventName.kt +31 -0
- package/android/src/main/java/expo/modules/kotlin/events/EventsDefinition.kt +3 -0
- package/android/src/main/java/expo/modules/kotlin/events/KEventEmitterWrapper.kt +26 -0
- package/android/src/main/java/expo/modules/kotlin/events/OnActivityResultPayload.kt +8 -0
- package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +70 -0
- package/android/src/main/java/expo/modules/kotlin/methods/AnyMethod.kt +50 -0
- package/android/src/main/java/expo/modules/kotlin/methods/Method.kt +14 -0
- package/android/src/main/java/expo/modules/kotlin/methods/PromiseMethod.kt +15 -0
- package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +24 -0
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +227 -0
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +16 -0
- package/android/src/main/java/expo/modules/kotlin/records/Field.kt +5 -0
- package/android/src/main/java/expo/modules/kotlin/records/Record.kt +3 -0
- package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +55 -0
- package/android/src/main/java/expo/modules/kotlin/types/AnyType.kt +14 -0
- package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +44 -0
- package/android/src/main/java/expo/modules/kotlin/types/BasicTypeConverters.kt +60 -0
- package/android/src/main/java/expo/modules/kotlin/types/EnumTypeConverter.kt +84 -0
- package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +25 -0
- package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +39 -0
- package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +28 -0
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +19 -0
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +107 -0
- package/android/src/main/java/expo/modules/kotlin/views/AnyViewProp.kt +10 -0
- package/android/src/main/java/expo/modules/kotlin/views/ConcreteViewProp.kt +17 -0
- package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +22 -0
- package/android/src/main/java/expo/modules/kotlin/views/SimpleViewManagerWrapper.kt +21 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +36 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +40 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +21 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewWrapperDelegateHolder.kt +5 -0
- package/build/NativeModulesProxy.native.d.ts +4 -0
- package/build/NativeModulesProxy.native.js +14 -1
- package/build/NativeModulesProxy.native.js.map +1 -1
- package/build/NativeModulesProxy.types.d.ts +3 -0
- package/build/NativeModulesProxy.types.js.map +1 -1
- package/ios/AppDelegates/EXAppDelegateWrapper.h +16 -0
- package/ios/AppDelegates/EXAppDelegateWrapper.m +42 -0
- package/ios/AppDelegates/EXAppDelegatesLoader.h +15 -0
- package/ios/AppDelegates/EXAppDelegatesLoader.m +29 -0
- package/ios/AppDelegates/EXLegacyAppDelegateWrapper.h +16 -0
- package/ios/{EXAppDelegateWrapper.m → AppDelegates/EXLegacyAppDelegateWrapper.m} +2 -2
- package/ios/AppDelegates/ExpoAppDelegate.swift +264 -0
- package/ios/AppDelegates/ExpoAppDelegateSubscriber.swift +24 -0
- package/ios/ExpoModulesCore.podspec +7 -2
- package/ios/JSI/ExpoModulesProxySpec.h +24 -0
- package/ios/JSI/ExpoModulesProxySpec.mm +135 -0
- package/ios/JSI/JSIConversions.h +42 -0
- package/ios/JSI/JSIConversions.mm +164 -0
- package/ios/JSI/JSIInstaller.h +19 -0
- package/ios/JSI/JSIInstaller.mm +22 -0
- package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +1 -6
- package/ios/NativeModulesProxy/EXNativeModulesProxy.h +6 -0
- package/ios/NativeModulesProxy/{EXNativeModulesProxy.m → EXNativeModulesProxy.mm} +45 -12
- package/ios/Services/EXReactNativeEventEmitter.h +6 -0
- package/ios/Services/EXReactNativeEventEmitter.m +15 -0
- package/ios/Swift/AppContext.swift +14 -1
- package/ios/Swift/Arguments/AnyArgument.swift +14 -0
- package/ios/Swift/Arguments/AnyArgumentType.swift +13 -0
- package/ios/Swift/Arguments/ArgumentType.swift +24 -0
- package/ios/Swift/Arguments/ConvertibleArgument.swift +15 -0
- package/ios/Swift/Arguments/Convertibles.swift +93 -0
- package/ios/Swift/Arguments/Types/ArrayArgumentType.swift +42 -0
- package/ios/Swift/Arguments/Types/ConvertibleArgumentType.swift +16 -0
- package/ios/Swift/Arguments/Types/EnumArgumentType.swift +105 -0
- package/ios/Swift/Arguments/Types/OptionalArgumentType.swift +49 -0
- package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +15 -0
- package/ios/Swift/Arguments/Types/RawArgumentType.swift +25 -0
- package/ios/Swift/Conversions.swift +199 -7
- package/ios/Swift/EventListener.swift +37 -5
- package/ios/Swift/Functions/AnyFunction.swift +42 -0
- package/ios/Swift/{Methods/ConcreteMethod.swift → Functions/ConcreteFunction.swift} +32 -34
- package/ios/Swift/ModuleHolder.swift +75 -20
- package/ios/Swift/ModuleRegistry.swift +19 -8
- package/ios/Swift/Modules/AnyModule.swift +8 -8
- package/ios/Swift/Modules/Module.swift +7 -0
- package/ios/Swift/Modules/ModuleDefinition.swift +52 -8
- package/ios/Swift/Modules/ModuleDefinitionBuilder.swift +1 -1
- package/ios/Swift/Modules/ModuleDefinitionComponents.swift +140 -52
- package/ios/Swift/ModulesProvider.swift +9 -0
- package/ios/Swift/Promise.swift +1 -1
- package/ios/Swift/Records/Field.swift +1 -1
- package/ios/Swift/Records/Record.swift +8 -1
- package/ios/Swift/SwiftInteropBridge.swift +45 -16
- package/ios/Swift/Views/AnyViewProp.swift +2 -2
- package/ios/Swift/Views/ConcreteViewProp.swift +37 -10
- package/ios/Swift/Views/ViewModuleWrapper.swift +9 -4
- package/ios/Swift.h +9 -0
- package/ios/Tests/ArgumentTypeSpec.swift +145 -0
- package/ios/Tests/ConvertiblesSpec.swift +231 -0
- package/ios/Tests/{MethodSpec.swift → FunctionSpec.swift} +69 -54
- package/ios/Tests/FunctionWithConvertiblesSpec.swift +66 -0
- package/ios/Tests/Mocks/ModuleMocks.swift +21 -7
- package/ios/Tests/ModuleEventListenersSpec.swift +17 -16
- package/ios/Tests/ModuleRegistrySpec.swift +4 -7
- package/package.json +3 -3
- package/src/NativeModulesProxy.native.ts +22 -2
- package/src/NativeModulesProxy.types.ts +8 -0
- package/ios/EXAppDelegateWrapper.h +0 -13
- package/ios/Swift/Methods/AnyArgumentType.swift +0 -48
- package/ios/Swift/Methods/AnyMethod.swift +0 -31
- package/ios/Swift/Methods/AnyMethodArgument.swift +0 -13
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import UIKit
|
|
2
|
+
import Dispatch
|
|
3
|
+
import Foundation
|
|
4
|
+
|
|
5
|
+
var subscribers = [ExpoAppDelegateSubscriberProtocol]()
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
Allows classes extending `ExpoAppDelegateSubscriber` to hook into project's app delegate
|
|
9
|
+
by forwarding `UIApplicationDelegate` events to the subscribers.
|
|
10
|
+
|
|
11
|
+
Keep functions and markers in sync with https://developer.apple.com/documentation/uikit/uiapplicationdelegate
|
|
12
|
+
*/
|
|
13
|
+
@objc(EXExpoAppDelegate)
|
|
14
|
+
open class ExpoAppDelegate: UIResponder, UIApplicationDelegate {
|
|
15
|
+
open var window: UIWindow?
|
|
16
|
+
|
|
17
|
+
// MARK: - Initializing the App
|
|
18
|
+
|
|
19
|
+
open func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
|
20
|
+
return subscribers.reduce(false) { result, subscriber in
|
|
21
|
+
return subscriber.application?(application, willFinishLaunchingWithOptions: launchOptions) ?? false || result
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
open func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
|
26
|
+
return subscribers.reduce(false) { result, subscriber in
|
|
27
|
+
return subscriber.application?(application, didFinishLaunchingWithOptions: launchOptions) ?? false || result
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// TODO: - Configuring and Discarding Scenes
|
|
32
|
+
|
|
33
|
+
// MARK: - Responding to App Life-Cycle Events
|
|
34
|
+
|
|
35
|
+
@objc
|
|
36
|
+
open func applicationDidBecomeActive(_ application: UIApplication) {
|
|
37
|
+
subscribers.forEach { $0.applicationDidBecomeActive?(application) }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@objc
|
|
41
|
+
open func applicationWillResignActive(_ application: UIApplication) {
|
|
42
|
+
subscribers.forEach { $0.applicationWillResignActive?(application) }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@objc
|
|
46
|
+
open func applicationDidEnterBackground(_ application: UIApplication) {
|
|
47
|
+
subscribers.forEach { $0.applicationDidEnterBackground?(application) }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
open func applicationWillEnterForeground(_ application: UIApplication) {
|
|
51
|
+
subscribers.forEach { $0.applicationWillEnterForeground?(application) }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
open func applicationWillTerminate(_ application: UIApplication) {
|
|
55
|
+
subscribers.forEach { $0.applicationWillTerminate?(application) }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// TODO: - Responding to Environment Changes
|
|
59
|
+
|
|
60
|
+
// TODO: - Managing App State Restoration
|
|
61
|
+
|
|
62
|
+
// MARK: - Downloading Data in the Background
|
|
63
|
+
|
|
64
|
+
open func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
|
|
65
|
+
let selector = #selector(application(_:handleEventsForBackgroundURLSession:completionHandler:))
|
|
66
|
+
let subs = subscribers.filter { $0.responds(to: selector) }
|
|
67
|
+
var subscribersLeft = subs.count
|
|
68
|
+
let dispatchQueue = DispatchQueue(label: "expo.application.handleBackgroundEvents")
|
|
69
|
+
|
|
70
|
+
let handler = {
|
|
71
|
+
dispatchQueue.sync {
|
|
72
|
+
subscribersLeft -= 1
|
|
73
|
+
|
|
74
|
+
if subscribersLeft == 0 {
|
|
75
|
+
completionHandler()
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
subs.forEach {
|
|
81
|
+
$0.application?(application, handleEventsForBackgroundURLSession: identifier, completionHandler: handler)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// MARK: - Handling Remote Notification Registration
|
|
86
|
+
|
|
87
|
+
open func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
|
|
88
|
+
subscribers.forEach { $0.application?(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken) }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
open func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
|
|
92
|
+
subscribers.forEach { $0.application?(application, didFailToRegisterForRemoteNotificationsWithError: error) }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
open func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
|
|
96
|
+
let selector = #selector(application(_:didReceiveRemoteNotification:fetchCompletionHandler:))
|
|
97
|
+
let subs = subscribers.filter { $0.responds(to: selector) }
|
|
98
|
+
var subscribersLeft = subs.count
|
|
99
|
+
var fetchResult: UIBackgroundFetchResult = .noData
|
|
100
|
+
let dispatchQueue = DispatchQueue(label: "expo.application.remoteNotification", qos: .userInteractive)
|
|
101
|
+
|
|
102
|
+
let handler = { (result: UIBackgroundFetchResult) in
|
|
103
|
+
dispatchQueue.sync {
|
|
104
|
+
if result == .failed {
|
|
105
|
+
fetchResult = .failed
|
|
106
|
+
} else if fetchResult != .failed && result == .newData {
|
|
107
|
+
fetchResult = .newData
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
subscribersLeft -= 1
|
|
111
|
+
|
|
112
|
+
if subscribersLeft == 0 {
|
|
113
|
+
completionHandler(fetchResult)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
subs.forEach { subscriber in
|
|
119
|
+
subscriber.application?(application, didReceiveRemoteNotification: userInfo, fetchCompletionHandler: handler)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// MARK: - Continuing User Activity and Handling Quick Actions
|
|
124
|
+
|
|
125
|
+
open func application(_ application: UIApplication, willContinueUserActivityWithType userActivityType: String) -> Bool {
|
|
126
|
+
return subscribers.reduce(false) { result, subscriber in
|
|
127
|
+
return subscriber.application?(application, willContinueUserActivityWithType: userActivityType) ?? false || result
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
open func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
|
|
132
|
+
let selector = #selector(application(_:continue:restorationHandler:))
|
|
133
|
+
let subs = subscribers.filter { $0.responds(to: selector) }
|
|
134
|
+
var subscribersLeft = subs.count
|
|
135
|
+
let dispatchQueue = DispatchQueue(label: "expo.application.continueUserActivity", qos: .userInteractive)
|
|
136
|
+
var allRestorableObjects = [UIUserActivityRestoring]()
|
|
137
|
+
|
|
138
|
+
let handler = { (restorableObjects: [UIUserActivityRestoring]?) in
|
|
139
|
+
dispatchQueue.sync {
|
|
140
|
+
if let restorableObjects = restorableObjects {
|
|
141
|
+
allRestorableObjects.append(contentsOf: restorableObjects)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
subscribersLeft -= 1
|
|
145
|
+
|
|
146
|
+
if subscribersLeft == 0 {
|
|
147
|
+
restorationHandler(allRestorableObjects)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return subs.reduce(false) { result, subscriber in
|
|
153
|
+
return subscriber.application?(application, continue: userActivity, restorationHandler: handler) ?? false || result
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
open func application(_ application: UIApplication, didUpdate userActivity: NSUserActivity) {
|
|
158
|
+
return subscribers.forEach { $0.application?(application, didUpdate: userActivity) }
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
open func application(_ application: UIApplication, didFailToContinueUserActivityWithType userActivityType: String, error: Error) {
|
|
162
|
+
return subscribers.forEach {
|
|
163
|
+
$0.application?(application, didFailToContinueUserActivityWithType: userActivityType, error: error)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
open func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
|
|
168
|
+
let selector = #selector(application(_:performActionFor:completionHandler:))
|
|
169
|
+
let subs = subscribers.filter { $0.responds(to: selector) }
|
|
170
|
+
var subscribersLeft = subs.count
|
|
171
|
+
var result: Bool = false
|
|
172
|
+
let dispatchQueue = DispatchQueue(label: "expo.application.performAction", qos: .userInteractive)
|
|
173
|
+
|
|
174
|
+
let handler = { (succeeded: Bool) in
|
|
175
|
+
dispatchQueue.sync {
|
|
176
|
+
result = result || succeeded
|
|
177
|
+
subscribersLeft -= 1
|
|
178
|
+
|
|
179
|
+
if subscribersLeft == 0 {
|
|
180
|
+
completionHandler(result)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
subs.forEach { subscriber in
|
|
186
|
+
subscriber.application?(application, performActionFor: shortcutItem, completionHandler: handler)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// MARK: - Background Fetch
|
|
191
|
+
|
|
192
|
+
open func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
|
|
193
|
+
let selector = #selector(application(_:performFetchWithCompletionHandler:))
|
|
194
|
+
let subs = subscribers.filter { $0.responds(to: selector) }
|
|
195
|
+
var subscribersLeft = subs.count
|
|
196
|
+
var fetchResult: UIBackgroundFetchResult = .noData
|
|
197
|
+
let dispatchQueue = DispatchQueue(label: "expo.application.performFetch", qos: .userInteractive)
|
|
198
|
+
|
|
199
|
+
let handler = { (result: UIBackgroundFetchResult) in
|
|
200
|
+
dispatchQueue.sync {
|
|
201
|
+
if result == .failed {
|
|
202
|
+
fetchResult = .failed
|
|
203
|
+
} else if fetchResult != .failed && result == .newData {
|
|
204
|
+
fetchResult = .newData
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
subscribersLeft -= 1
|
|
208
|
+
|
|
209
|
+
if subscribersLeft == 0 {
|
|
210
|
+
completionHandler(fetchResult)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
subs.forEach { subscriber in
|
|
216
|
+
subscriber.application?(application, performFetchWithCompletionHandler: handler)
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// TODO: - Interacting With WatchKit
|
|
221
|
+
|
|
222
|
+
// TODO: - Interacting With HealthKit
|
|
223
|
+
|
|
224
|
+
// MARK: - Opening a URL-Specified Resource
|
|
225
|
+
|
|
226
|
+
open func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
|
|
227
|
+
return subscribers.contains { subscriber in
|
|
228
|
+
return subscriber.application?(app, open: url, options: options) ?? false
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// TODO: - Disallowing Specified App Extension Types
|
|
233
|
+
|
|
234
|
+
// TODO: - Handling SiriKit Intents
|
|
235
|
+
|
|
236
|
+
// TODO: - Handling CloudKit Invitations
|
|
237
|
+
|
|
238
|
+
// TODO: - Managing Interface Geometry
|
|
239
|
+
|
|
240
|
+
// MARK: - Statics
|
|
241
|
+
|
|
242
|
+
@objc
|
|
243
|
+
public static func registerSubscribersFrom(modulesProvider: ModulesProviderObjCProtocol) {
|
|
244
|
+
guard let provider = modulesProvider as? ModulesProviderProtocol else {
|
|
245
|
+
fatalError("Expo modules provider must implement `ModulesProviderProtocol`.")
|
|
246
|
+
}
|
|
247
|
+
provider.getAppDelegateSubscribers().forEach { subscriberType in
|
|
248
|
+
registerSubscriber(subscriberType.init())
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
@objc
|
|
253
|
+
public static func registerSubscriber(_ subscriber: ExpoAppDelegateSubscriberProtocol) {
|
|
254
|
+
if subscribers.contains(where: { $0 === subscriber }) {
|
|
255
|
+
fatalError("Given app delegate subscriber `\(String(describing: subscriber))` is already registered.")
|
|
256
|
+
}
|
|
257
|
+
subscribers.append(subscriber)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
@objc
|
|
261
|
+
public static func getSubscriber(_ name: String) -> ExpoAppDelegateSubscriberProtocol? {
|
|
262
|
+
return subscribers.first { String(describing: $0) == name }
|
|
263
|
+
}
|
|
264
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Copyright 2018-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import UIKit
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
Base class for app delegate subscribers. Ensures the class
|
|
7
|
+
inherits from `UIResponder` and has `required init()` initializer.
|
|
8
|
+
*/
|
|
9
|
+
@objc(EXBaseAppDelegateSubscriber)
|
|
10
|
+
open class BaseExpoAppDelegateSubscriber: UIResponder {
|
|
11
|
+
public override required init() {}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
Typealias to `UIApplicationDelegate` protocol.
|
|
16
|
+
Might be useful for compatibility reasons if we decide to add more things here.
|
|
17
|
+
*/
|
|
18
|
+
@objc(EXAppDelegateSubscriberProtocol)
|
|
19
|
+
public protocol ExpoAppDelegateSubscriberProtocol: UIApplicationDelegate {}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
Typealias merging the base class for app delegate subscribers and protocol inheritance to `UIApplicationDelegate`.
|
|
23
|
+
*/
|
|
24
|
+
public typealias ExpoAppDelegateSubscriber = BaseExpoAppDelegateSubscriber & ExpoAppDelegateSubscriberProtocol
|
|
@@ -18,19 +18,24 @@ Pod::Spec.new do |s|
|
|
|
18
18
|
|
|
19
19
|
# Swift/Objective-C compatibility
|
|
20
20
|
s.pod_target_xcconfig = {
|
|
21
|
-
'
|
|
21
|
+
'USE_HEADERMAP' => 'YES',
|
|
22
|
+
'DEFINES_MODULE' => 'YES',
|
|
23
|
+
'CLANG_CXX_LANGUAGE_STANDARD' => 'c++14',
|
|
24
|
+
'SWIFT_COMPILATION_MODE' => 'wholemodule'
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
s.dependency 'React-Core'
|
|
28
|
+
s.dependency 'ReactCommon/turbomodule/core'
|
|
25
29
|
|
|
26
30
|
if !$ExpoUseSources&.include?(package['name']) && ENV['EXPO_USE_SOURCE'].to_i == 0 && File.exist?("#{s.name}.xcframework") && Gem::Version.new(Pod::VERSION) >= Gem::Version.new('1.10.0')
|
|
27
31
|
s.source_files = '**/*.h'
|
|
28
32
|
s.vendored_frameworks = "#{s.name}.xcframework"
|
|
29
33
|
else
|
|
30
|
-
s.source_files = '**/*.{h,m,swift}'
|
|
34
|
+
s.source_files = '**/*.{h,m,mm,swift}'
|
|
31
35
|
end
|
|
32
36
|
|
|
33
37
|
s.exclude_files = 'Tests/'
|
|
38
|
+
s.private_header_files = '**/Swift.h'
|
|
34
39
|
|
|
35
40
|
s.test_spec 'Tests' do |test_spec|
|
|
36
41
|
test_spec.dependency 'Quick'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Copyright 2018-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
#ifdef __cplusplus
|
|
4
|
+
|
|
5
|
+
#import <jsi/jsi.h>
|
|
6
|
+
#import <ReactCommon/RCTTurboModule.h>
|
|
7
|
+
|
|
8
|
+
#import <ExpoModulesCore/EXNativeModulesProxy.h>
|
|
9
|
+
|
|
10
|
+
using namespace facebook;
|
|
11
|
+
using namespace react;
|
|
12
|
+
|
|
13
|
+
namespace expo {
|
|
14
|
+
|
|
15
|
+
class JSI_EXPORT ExpoModulesProxySpec : public TurboModule {
|
|
16
|
+
public:
|
|
17
|
+
ExpoModulesProxySpec(std::shared_ptr<CallInvoker> callInvoker, EXNativeModulesProxy *nativeModulesProxy);
|
|
18
|
+
|
|
19
|
+
EXNativeModulesProxy *nativeModulesProxy;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
} // namespace expo
|
|
23
|
+
|
|
24
|
+
#endif
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// Copyright 2018-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
#import <React/RCTUtils.h>
|
|
4
|
+
|
|
5
|
+
#import <ExpoModulesCore/JSIConversions.h>
|
|
6
|
+
#import <ExpoModulesCore/ExpoModulesProxySpec.h>
|
|
7
|
+
|
|
8
|
+
namespace expo {
|
|
9
|
+
|
|
10
|
+
using PromiseInvocationBlock = void (^)(RCTPromiseResolveBlock resolveWrapper, RCTPromiseRejectBlock rejectWrapper);
|
|
11
|
+
|
|
12
|
+
static void callPromiseSetupWithBlock(jsi::Runtime &runtime, std::shared_ptr<CallInvoker> jsInvoker, std::shared_ptr<Promise> promise, PromiseInvocationBlock setupBlock)
|
|
13
|
+
{
|
|
14
|
+
auto weakResolveWrapper = CallbackWrapper::createWeak(promise->resolve_.getFunction(runtime), runtime, jsInvoker);
|
|
15
|
+
auto weakRejectWrapper = CallbackWrapper::createWeak(promise->reject_.getFunction(runtime), runtime, jsInvoker);
|
|
16
|
+
|
|
17
|
+
__block BOOL resolveWasCalled = NO;
|
|
18
|
+
__block BOOL rejectWasCalled = NO;
|
|
19
|
+
|
|
20
|
+
RCTPromiseResolveBlock resolveBlock = ^(id result) {
|
|
21
|
+
if (rejectWasCalled) {
|
|
22
|
+
throw std::runtime_error("Tried to resolve a promise after it's already been rejected.");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (resolveWasCalled) {
|
|
26
|
+
throw std::runtime_error("Tried to resolve a promise more than once.");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
auto strongResolveWrapper = weakResolveWrapper.lock();
|
|
30
|
+
auto strongRejectWrapper = weakRejectWrapper.lock();
|
|
31
|
+
if (!strongResolveWrapper || !strongRejectWrapper) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
strongResolveWrapper->jsInvoker().invokeAsync([weakResolveWrapper, weakRejectWrapper, result]() {
|
|
36
|
+
auto strongResolveWrapper2 = weakResolveWrapper.lock();
|
|
37
|
+
auto strongRejectWrapper2 = weakRejectWrapper.lock();
|
|
38
|
+
if (!strongResolveWrapper2 || !strongRejectWrapper2) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
jsi::Runtime &rt = strongResolveWrapper2->runtime();
|
|
43
|
+
jsi::Value arg = convertObjCObjectToJSIValue(rt, result);
|
|
44
|
+
strongResolveWrapper2->callback().call(rt, arg);
|
|
45
|
+
|
|
46
|
+
strongResolveWrapper2->destroy();
|
|
47
|
+
strongRejectWrapper2->destroy();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
resolveWasCalled = YES;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
RCTPromiseRejectBlock rejectBlock = ^(NSString *code, NSString *message, NSError *error) {
|
|
54
|
+
if (resolveWasCalled) {
|
|
55
|
+
throw std::runtime_error("Tried to reject a promise after it's already been resolved.");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (rejectWasCalled) {
|
|
59
|
+
throw std::runtime_error("Tried to reject a promise more than once.");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
auto strongResolveWrapper = weakResolveWrapper.lock();
|
|
63
|
+
auto strongRejectWrapper = weakRejectWrapper.lock();
|
|
64
|
+
if (!strongResolveWrapper || !strongRejectWrapper) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
NSDictionary *jsError = RCTJSErrorFromCodeMessageAndNSError(code, message, error);
|
|
69
|
+
strongRejectWrapper->jsInvoker().invokeAsync([weakResolveWrapper, weakRejectWrapper, jsError]() {
|
|
70
|
+
auto strongResolveWrapper2 = weakResolveWrapper.lock();
|
|
71
|
+
auto strongRejectWrapper2 = weakRejectWrapper.lock();
|
|
72
|
+
if (!strongResolveWrapper2 || !strongRejectWrapper2) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
jsi::Runtime &rt = strongRejectWrapper2->runtime();
|
|
77
|
+
jsi::Value arg = convertNSDictionaryToJSIObject(rt, jsError);
|
|
78
|
+
strongRejectWrapper2->callback().call(rt, arg);
|
|
79
|
+
|
|
80
|
+
strongResolveWrapper2->destroy();
|
|
81
|
+
strongRejectWrapper2->destroy();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
rejectWasCalled = YES;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
setupBlock(resolveBlock, rejectBlock);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
static jsi::Value __hostFunction_ExpoModulesProxySpec_callMethodAsync(jsi::Runtime &runtime, TurboModule &turboModule, const jsi::Value *args, size_t count)
|
|
91
|
+
{
|
|
92
|
+
auto expoModulesProxy = static_cast<ExpoModulesProxySpec *>(&turboModule);
|
|
93
|
+
|
|
94
|
+
// The function that is invoked as a setup of the JS `Promise`.
|
|
95
|
+
auto promiseSetupFunc = [expoModulesProxy, args](jsi::Runtime &runtime, std::shared_ptr<Promise> promise) {
|
|
96
|
+
callPromiseSetupWithBlock(runtime, expoModulesProxy->jsInvoker_, promise, ^(RCTPromiseResolveBlock resolver, RCTPromiseRejectBlock rejecter) {
|
|
97
|
+
NSString *moduleName = convertJSIStringToNSString(runtime, args[0].getString(runtime));
|
|
98
|
+
NSString *methodName = convertJSIStringToNSString(runtime, args[1].getString(runtime));
|
|
99
|
+
NSArray *arguments = convertJSIArrayToNSArray(runtime, args[2].getObject(runtime).asArray(runtime), expoModulesProxy->jsInvoker_);
|
|
100
|
+
|
|
101
|
+
[expoModulesProxy->nativeModulesProxy callMethod:moduleName
|
|
102
|
+
methodNameOrKey:methodName
|
|
103
|
+
arguments:arguments
|
|
104
|
+
resolver:resolver
|
|
105
|
+
rejecter:rejecter];
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
return createPromiseAsJSIValue(runtime, promiseSetupFunc);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
static jsi::Value __hostFunction_ExpoModulesProxySpec_callMethodSync(jsi::Runtime &runtime, TurboModule &turboModule, const jsi::Value *args, size_t count)
|
|
113
|
+
{
|
|
114
|
+
auto expoModulesProxy = static_cast<ExpoModulesProxySpec *>(&turboModule);
|
|
115
|
+
NSString *moduleName = convertJSIStringToNSString(runtime, args[0].getString(runtime));
|
|
116
|
+
NSString *methodName = convertJSIStringToNSString(runtime, args[1].getString(runtime));
|
|
117
|
+
NSArray *arguments = convertJSIArrayToNSArray(runtime, args[2].getObject(runtime).asArray(runtime), expoModulesProxy->jsInvoker_);
|
|
118
|
+
|
|
119
|
+
id result = [expoModulesProxy->nativeModulesProxy callMethodSync:moduleName
|
|
120
|
+
methodName:methodName
|
|
121
|
+
arguments:arguments];
|
|
122
|
+
|
|
123
|
+
return convertObjCObjectToJSIValue(runtime, result);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
ExpoModulesProxySpec::ExpoModulesProxySpec(std::shared_ptr<CallInvoker> callInvoker, EXNativeModulesProxy *nativeModulesProxy) :
|
|
127
|
+
TurboModule("ExpoModulesProxy", callInvoker),
|
|
128
|
+
nativeModulesProxy(nativeModulesProxy)
|
|
129
|
+
{
|
|
130
|
+
methodMap_["callMethodAsync"] = MethodMetadata {3, __hostFunction_ExpoModulesProxySpec_callMethodAsync};
|
|
131
|
+
|
|
132
|
+
methodMap_["callMethodSync"] = MethodMetadata {3, __hostFunction_ExpoModulesProxySpec_callMethodSync};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
} // namespace expo
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Copyright 2018-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
#ifdef __cplusplus
|
|
4
|
+
|
|
5
|
+
#import <Foundation/Foundation.h>
|
|
6
|
+
|
|
7
|
+
#import <jsi/jsi.h>
|
|
8
|
+
#import <React/RCTBridgeModule.h>
|
|
9
|
+
#import <ReactCommon/CallInvoker.h>
|
|
10
|
+
|
|
11
|
+
using namespace facebook;
|
|
12
|
+
using namespace react;
|
|
13
|
+
|
|
14
|
+
namespace expo {
|
|
15
|
+
|
|
16
|
+
jsi::Value convertNSNumberToJSIBoolean(jsi::Runtime &runtime, NSNumber *value);
|
|
17
|
+
|
|
18
|
+
jsi::Value convertNSNumberToJSINumber(jsi::Runtime &runtime, NSNumber *value);
|
|
19
|
+
|
|
20
|
+
jsi::String convertNSStringToJSIString(jsi::Runtime &runtime, NSString *value);
|
|
21
|
+
|
|
22
|
+
jsi::Object convertNSDictionaryToJSIObject(jsi::Runtime &runtime, NSDictionary *value);
|
|
23
|
+
|
|
24
|
+
jsi::Array convertNSArrayToJSIArray(jsi::Runtime &runtime, NSArray *value);
|
|
25
|
+
|
|
26
|
+
std::vector<jsi::Value> convertNSArrayToStdVector(jsi::Runtime &runtime, NSArray *value);
|
|
27
|
+
|
|
28
|
+
jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value);
|
|
29
|
+
|
|
30
|
+
NSString *convertJSIStringToNSString(jsi::Runtime &runtime, const jsi::String &value);
|
|
31
|
+
|
|
32
|
+
NSArray *convertJSIArrayToNSArray(jsi::Runtime &runtime, const jsi::Array &value, std::shared_ptr<CallInvoker> jsInvoker);
|
|
33
|
+
|
|
34
|
+
NSDictionary *convertJSIObjectToNSDictionary(jsi::Runtime &runtime, const jsi::Object &value, std::shared_ptr<CallInvoker> jsInvoker);
|
|
35
|
+
|
|
36
|
+
id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr<CallInvoker> jsInvoker);
|
|
37
|
+
|
|
38
|
+
RCTResponseSenderBlock convertJSIFunctionToCallback(jsi::Runtime &runtime, const jsi::Function &value, std::shared_ptr<CallInvoker> jsInvoker);
|
|
39
|
+
|
|
40
|
+
} // namespace expo
|
|
41
|
+
|
|
42
|
+
#endif
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// Copyright 2018-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
#import <ReactCommon/TurboModuleUtils.h>
|
|
4
|
+
#import <ExpoModulesCore/JSIConversions.h>
|
|
5
|
+
|
|
6
|
+
namespace expo {
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* All static helper functions are ObjC++ specific.
|
|
10
|
+
*/
|
|
11
|
+
jsi::Value convertNSNumberToJSIBoolean(jsi::Runtime &runtime, NSNumber *value)
|
|
12
|
+
{
|
|
13
|
+
return jsi::Value((bool)[value boolValue]);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
jsi::Value convertNSNumberToJSINumber(jsi::Runtime &runtime, NSNumber *value)
|
|
17
|
+
{
|
|
18
|
+
return jsi::Value([value doubleValue]);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
jsi::String convertNSStringToJSIString(jsi::Runtime &runtime, NSString *value)
|
|
22
|
+
{
|
|
23
|
+
return jsi::String::createFromUtf8(runtime, [value UTF8String] ?: "");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
jsi::Object convertNSDictionaryToJSIObject(jsi::Runtime &runtime, NSDictionary *value)
|
|
27
|
+
{
|
|
28
|
+
jsi::Object result = jsi::Object(runtime);
|
|
29
|
+
for (NSString *k in value) {
|
|
30
|
+
result.setProperty(runtime, [k UTF8String], convertObjCObjectToJSIValue(runtime, value[k]));
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
jsi::Array convertNSArrayToJSIArray(jsi::Runtime &runtime, NSArray *value)
|
|
36
|
+
{
|
|
37
|
+
jsi::Array result = jsi::Array(runtime, value.count);
|
|
38
|
+
for (size_t i = 0; i < value.count; i++) {
|
|
39
|
+
result.setValueAtIndex(runtime, i, convertObjCObjectToJSIValue(runtime, value[i]));
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
std::vector<jsi::Value> convertNSArrayToStdVector(jsi::Runtime &runtime, NSArray *value)
|
|
45
|
+
{
|
|
46
|
+
std::vector<jsi::Value> result;
|
|
47
|
+
for (size_t i = 0; i < value.count; i++) {
|
|
48
|
+
result.emplace_back(convertObjCObjectToJSIValue(runtime, value[i]));
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value)
|
|
54
|
+
{
|
|
55
|
+
if ([value isKindOfClass:[NSString class]]) {
|
|
56
|
+
return convertNSStringToJSIString(runtime, (NSString *)value);
|
|
57
|
+
} else if ([value isKindOfClass:[NSNumber class]]) {
|
|
58
|
+
if ([value isKindOfClass:[@YES class]]) {
|
|
59
|
+
return convertNSNumberToJSIBoolean(runtime, (NSNumber *)value);
|
|
60
|
+
}
|
|
61
|
+
return convertNSNumberToJSINumber(runtime, (NSNumber *)value);
|
|
62
|
+
} else if ([value isKindOfClass:[NSDictionary class]]) {
|
|
63
|
+
return convertNSDictionaryToJSIObject(runtime, (NSDictionary *)value);
|
|
64
|
+
} else if ([value isKindOfClass:[NSArray class]]) {
|
|
65
|
+
return convertNSArrayToJSIArray(runtime, (NSArray *)value);
|
|
66
|
+
} else if (value == (id)kCFNull) {
|
|
67
|
+
return jsi::Value::null();
|
|
68
|
+
}
|
|
69
|
+
return jsi::Value::undefined();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
NSString *convertJSIStringToNSString(jsi::Runtime &runtime, const jsi::String &value)
|
|
73
|
+
{
|
|
74
|
+
return [NSString stringWithUTF8String:value.utf8(runtime).c_str()];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
NSArray *convertJSIArrayToNSArray(jsi::Runtime &runtime, const jsi::Array &value, std::shared_ptr<CallInvoker> jsInvoker)
|
|
78
|
+
{
|
|
79
|
+
size_t size = value.size(runtime);
|
|
80
|
+
NSMutableArray *result = [NSMutableArray new];
|
|
81
|
+
for (size_t i = 0; i < size; i++) {
|
|
82
|
+
// Insert kCFNull when it's `undefined` value to preserve the indices.
|
|
83
|
+
[result
|
|
84
|
+
addObject:convertJSIValueToObjCObject(runtime, value.getValueAtIndex(runtime, i), jsInvoker) ?: (id)kCFNull];
|
|
85
|
+
}
|
|
86
|
+
return [result copy];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
NSDictionary *convertJSIObjectToNSDictionary(jsi::Runtime &runtime, const jsi::Object &value, std::shared_ptr<CallInvoker> jsInvoker)
|
|
90
|
+
{
|
|
91
|
+
jsi::Array propertyNames = value.getPropertyNames(runtime);
|
|
92
|
+
size_t size = propertyNames.size(runtime);
|
|
93
|
+
NSMutableDictionary *result = [NSMutableDictionary new];
|
|
94
|
+
for (size_t i = 0; i < size; i++) {
|
|
95
|
+
jsi::String name = propertyNames.getValueAtIndex(runtime, i).getString(runtime);
|
|
96
|
+
NSString *k = convertJSIStringToNSString(runtime, name);
|
|
97
|
+
id v = convertJSIValueToObjCObject(runtime, value.getProperty(runtime, name), jsInvoker);
|
|
98
|
+
if (v) {
|
|
99
|
+
result[k] = v;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return [result copy];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr<CallInvoker> jsInvoker)
|
|
106
|
+
{
|
|
107
|
+
if (value.isUndefined() || value.isNull()) {
|
|
108
|
+
return nil;
|
|
109
|
+
}
|
|
110
|
+
if (value.isBool()) {
|
|
111
|
+
return @(value.getBool());
|
|
112
|
+
}
|
|
113
|
+
if (value.isNumber()) {
|
|
114
|
+
return @(value.getNumber());
|
|
115
|
+
}
|
|
116
|
+
if (value.isString()) {
|
|
117
|
+
return convertJSIStringToNSString(runtime, value.getString(runtime));
|
|
118
|
+
}
|
|
119
|
+
if (value.isObject()) {
|
|
120
|
+
jsi::Object o = value.getObject(runtime);
|
|
121
|
+
if (o.isArray(runtime)) {
|
|
122
|
+
return convertJSIArrayToNSArray(runtime, o.getArray(runtime), jsInvoker);
|
|
123
|
+
}
|
|
124
|
+
if (o.isFunction(runtime)) {
|
|
125
|
+
return convertJSIFunctionToCallback(runtime, std::move(o.getFunction(runtime)), jsInvoker);
|
|
126
|
+
}
|
|
127
|
+
return convertJSIObjectToNSDictionary(runtime, o, jsInvoker);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
throw std::runtime_error("Unsupported jsi::jsi::Value kind");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
RCTResponseSenderBlock convertJSIFunctionToCallback(jsi::Runtime &runtime, const jsi::Function &value, std::shared_ptr<CallInvoker> jsInvoker)
|
|
134
|
+
{
|
|
135
|
+
auto weakWrapper = CallbackWrapper::createWeak(value.getFunction(runtime), runtime, jsInvoker);
|
|
136
|
+
BOOL __block wrapperWasCalled = NO;
|
|
137
|
+
RCTResponseSenderBlock callback = ^(NSArray *responses) {
|
|
138
|
+
if (wrapperWasCalled) {
|
|
139
|
+
throw std::runtime_error("callback arg cannot be called more than once");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
auto strongWrapper = weakWrapper.lock();
|
|
143
|
+
if (!strongWrapper) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
strongWrapper->jsInvoker().invokeAsync([weakWrapper, responses]() {
|
|
148
|
+
auto strongWrapper2 = weakWrapper.lock();
|
|
149
|
+
if (!strongWrapper2) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
std::vector<jsi::Value> args = convertNSArrayToStdVector(strongWrapper2->runtime(), responses);
|
|
154
|
+
strongWrapper2->callback().call(strongWrapper2->runtime(), (const jsi::Value *)args.data(), args.size());
|
|
155
|
+
strongWrapper2->destroy();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
wrapperWasCalled = YES;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
return callback;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
} // namespace expo
|