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.
Files changed (129) hide show
  1. package/CHANGELOG.md +14 -1
  2. package/android/build.gradle +30 -2
  3. package/android/src/main/java/expo/modules/adapters/react/ModuleRegistryAdapter.java +27 -5
  4. package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +49 -5
  5. package/android/src/main/java/expo/modules/core/BasePackage.java +6 -0
  6. package/android/src/main/java/expo/modules/core/ModulePriorities.kt +25 -0
  7. package/android/src/main/java/expo/modules/core/interfaces/ActivityEventListener.java +3 -1
  8. package/android/src/main/java/expo/modules/core/interfaces/Package.java +4 -0
  9. package/android/src/main/java/expo/modules/core/interfaces/ReactActivityHandler.kt +18 -0
  10. package/android/src/main/java/expo/modules/core/interfaces/ReactNativeHostHandler.kt +14 -0
  11. package/android/src/main/java/expo/modules/core/utilities/KotlinUtilities.kt +23 -0
  12. package/android/src/main/java/expo/modules/kotlin/AppContext.kt +166 -0
  13. package/android/src/main/java/expo/modules/kotlin/DynamicExtenstions.kt +9 -0
  14. package/android/src/main/java/expo/modules/kotlin/ExpoModulesHelper.kt +18 -0
  15. package/android/src/main/java/expo/modules/kotlin/KPromiseWrapper.kt +23 -0
  16. package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +98 -0
  17. package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +41 -0
  18. package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +56 -0
  19. package/android/src/main/java/expo/modules/kotlin/ModulesProvider.kt +7 -0
  20. package/android/src/main/java/expo/modules/kotlin/Promise.kt +13 -0
  21. package/android/src/main/java/expo/modules/kotlin/ReactLifecycleDelegate.kt +39 -0
  22. package/android/src/main/java/expo/modules/kotlin/ReadableArrayIterator.kt +14 -0
  23. package/android/src/main/java/expo/modules/kotlin/ReadableTypeExtensions.kt +18 -0
  24. package/android/src/main/java/expo/modules/kotlin/allocators/ObjectConstructor.kt +5 -0
  25. package/android/src/main/java/expo/modules/kotlin/allocators/ObjectConstructorFactory.kt +31 -0
  26. package/android/src/main/java/expo/modules/kotlin/allocators/UnsafeAllocator.kt +49 -0
  27. package/android/src/main/java/expo/modules/kotlin/events/EventListener.kt +39 -0
  28. package/android/src/main/java/expo/modules/kotlin/events/EventName.kt +31 -0
  29. package/android/src/main/java/expo/modules/kotlin/events/EventsDefinition.kt +3 -0
  30. package/android/src/main/java/expo/modules/kotlin/events/KEventEmitterWrapper.kt +26 -0
  31. package/android/src/main/java/expo/modules/kotlin/events/OnActivityResultPayload.kt +8 -0
  32. package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +70 -0
  33. package/android/src/main/java/expo/modules/kotlin/methods/AnyMethod.kt +50 -0
  34. package/android/src/main/java/expo/modules/kotlin/methods/Method.kt +14 -0
  35. package/android/src/main/java/expo/modules/kotlin/methods/PromiseMethod.kt +15 -0
  36. package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +24 -0
  37. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +227 -0
  38. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +16 -0
  39. package/android/src/main/java/expo/modules/kotlin/records/Field.kt +5 -0
  40. package/android/src/main/java/expo/modules/kotlin/records/Record.kt +3 -0
  41. package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +55 -0
  42. package/android/src/main/java/expo/modules/kotlin/types/AnyType.kt +14 -0
  43. package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +44 -0
  44. package/android/src/main/java/expo/modules/kotlin/types/BasicTypeConverters.kt +60 -0
  45. package/android/src/main/java/expo/modules/kotlin/types/EnumTypeConverter.kt +84 -0
  46. package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +25 -0
  47. package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +39 -0
  48. package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +28 -0
  49. package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +19 -0
  50. package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +107 -0
  51. package/android/src/main/java/expo/modules/kotlin/views/AnyViewProp.kt +10 -0
  52. package/android/src/main/java/expo/modules/kotlin/views/ConcreteViewProp.kt +17 -0
  53. package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +22 -0
  54. package/android/src/main/java/expo/modules/kotlin/views/SimpleViewManagerWrapper.kt +21 -0
  55. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +36 -0
  56. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +40 -0
  57. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +21 -0
  58. package/android/src/main/java/expo/modules/kotlin/views/ViewWrapperDelegateHolder.kt +5 -0
  59. package/build/NativeModulesProxy.native.d.ts +4 -0
  60. package/build/NativeModulesProxy.native.js +14 -1
  61. package/build/NativeModulesProxy.native.js.map +1 -1
  62. package/build/NativeModulesProxy.types.d.ts +3 -0
  63. package/build/NativeModulesProxy.types.js.map +1 -1
  64. package/ios/AppDelegates/EXAppDelegateWrapper.h +16 -0
  65. package/ios/AppDelegates/EXAppDelegateWrapper.m +42 -0
  66. package/ios/AppDelegates/EXAppDelegatesLoader.h +15 -0
  67. package/ios/AppDelegates/EXAppDelegatesLoader.m +29 -0
  68. package/ios/AppDelegates/EXLegacyAppDelegateWrapper.h +16 -0
  69. package/ios/{EXAppDelegateWrapper.m → AppDelegates/EXLegacyAppDelegateWrapper.m} +2 -2
  70. package/ios/AppDelegates/ExpoAppDelegate.swift +264 -0
  71. package/ios/AppDelegates/ExpoAppDelegateSubscriber.swift +24 -0
  72. package/ios/ExpoModulesCore.podspec +7 -2
  73. package/ios/JSI/ExpoModulesProxySpec.h +24 -0
  74. package/ios/JSI/ExpoModulesProxySpec.mm +135 -0
  75. package/ios/JSI/JSIConversions.h +42 -0
  76. package/ios/JSI/JSIConversions.mm +164 -0
  77. package/ios/JSI/JSIInstaller.h +19 -0
  78. package/ios/JSI/JSIInstaller.mm +22 -0
  79. package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +1 -6
  80. package/ios/NativeModulesProxy/EXNativeModulesProxy.h +6 -0
  81. package/ios/NativeModulesProxy/{EXNativeModulesProxy.m → EXNativeModulesProxy.mm} +45 -12
  82. package/ios/Services/EXReactNativeEventEmitter.h +6 -0
  83. package/ios/Services/EXReactNativeEventEmitter.m +15 -0
  84. package/ios/Swift/AppContext.swift +14 -1
  85. package/ios/Swift/Arguments/AnyArgument.swift +14 -0
  86. package/ios/Swift/Arguments/AnyArgumentType.swift +13 -0
  87. package/ios/Swift/Arguments/ArgumentType.swift +24 -0
  88. package/ios/Swift/Arguments/ConvertibleArgument.swift +15 -0
  89. package/ios/Swift/Arguments/Convertibles.swift +93 -0
  90. package/ios/Swift/Arguments/Types/ArrayArgumentType.swift +42 -0
  91. package/ios/Swift/Arguments/Types/ConvertibleArgumentType.swift +16 -0
  92. package/ios/Swift/Arguments/Types/EnumArgumentType.swift +105 -0
  93. package/ios/Swift/Arguments/Types/OptionalArgumentType.swift +49 -0
  94. package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +15 -0
  95. package/ios/Swift/Arguments/Types/RawArgumentType.swift +25 -0
  96. package/ios/Swift/Conversions.swift +199 -7
  97. package/ios/Swift/EventListener.swift +37 -5
  98. package/ios/Swift/Functions/AnyFunction.swift +42 -0
  99. package/ios/Swift/{Methods/ConcreteMethod.swift → Functions/ConcreteFunction.swift} +32 -34
  100. package/ios/Swift/ModuleHolder.swift +75 -20
  101. package/ios/Swift/ModuleRegistry.swift +19 -8
  102. package/ios/Swift/Modules/AnyModule.swift +8 -8
  103. package/ios/Swift/Modules/Module.swift +7 -0
  104. package/ios/Swift/Modules/ModuleDefinition.swift +52 -8
  105. package/ios/Swift/Modules/ModuleDefinitionBuilder.swift +1 -1
  106. package/ios/Swift/Modules/ModuleDefinitionComponents.swift +140 -52
  107. package/ios/Swift/ModulesProvider.swift +9 -0
  108. package/ios/Swift/Promise.swift +1 -1
  109. package/ios/Swift/Records/Field.swift +1 -1
  110. package/ios/Swift/Records/Record.swift +8 -1
  111. package/ios/Swift/SwiftInteropBridge.swift +45 -16
  112. package/ios/Swift/Views/AnyViewProp.swift +2 -2
  113. package/ios/Swift/Views/ConcreteViewProp.swift +37 -10
  114. package/ios/Swift/Views/ViewModuleWrapper.swift +9 -4
  115. package/ios/Swift.h +9 -0
  116. package/ios/Tests/ArgumentTypeSpec.swift +145 -0
  117. package/ios/Tests/ConvertiblesSpec.swift +231 -0
  118. package/ios/Tests/{MethodSpec.swift → FunctionSpec.swift} +69 -54
  119. package/ios/Tests/FunctionWithConvertiblesSpec.swift +66 -0
  120. package/ios/Tests/Mocks/ModuleMocks.swift +21 -7
  121. package/ios/Tests/ModuleEventListenersSpec.swift +17 -16
  122. package/ios/Tests/ModuleRegistrySpec.swift +4 -7
  123. package/package.json +3 -3
  124. package/src/NativeModulesProxy.native.ts +22 -2
  125. package/src/NativeModulesProxy.types.ts +8 -0
  126. package/ios/EXAppDelegateWrapper.h +0 -13
  127. package/ios/Swift/Methods/AnyArgumentType.swift +0 -48
  128. package/ios/Swift/Methods/AnyMethod.swift +0 -31
  129. 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
- 'DEFINES_MODULE' => 'YES'
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