expo-modules-core 0.6.5 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.md +1 -1
  3. package/android/ExpoModulesCorePlugin.gradle +15 -0
  4. package/android/build.gradle +31 -15
  5. package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +5 -5
  6. package/android/src/main/java/expo/modules/adapters/react/services/UIManagerModuleWrapper.java +13 -0
  7. package/android/src/main/java/expo/modules/core/ViewManager.java +9 -0
  8. package/android/src/main/java/expo/modules/core/interfaces/JavaScriptContextProvider.java +4 -0
  9. package/android/src/main/java/expo/modules/core/interfaces/ReactActivityHandler.java +37 -1
  10. package/android/src/main/java/expo/modules/core/interfaces/ReactNativeHostHandler.java +30 -0
  11. package/android/src/main/java/expo/modules/core/interfaces/services/UIManager.java +2 -0
  12. package/android/src/main/java/expo/modules/kotlin/AppContext.kt +23 -5
  13. package/android/src/main/java/expo/modules/kotlin/DynamicExtenstions.kt +5 -3
  14. package/android/src/main/java/expo/modules/kotlin/KPromiseWrapper.kt +3 -8
  15. package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +24 -9
  16. package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +12 -7
  17. package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +23 -1
  18. package/android/src/main/java/expo/modules/kotlin/Promise.kt +1 -1
  19. package/android/src/main/java/expo/modules/kotlin/callbacks/Callback.kt +5 -0
  20. package/android/src/main/java/expo/modules/kotlin/callbacks/ViewCallback.kt +39 -0
  21. package/android/src/main/java/expo/modules/kotlin/callbacks/ViewCallbackDelegate.kt +27 -0
  22. package/android/src/main/java/expo/modules/kotlin/defaultmodules/ErrorManagerModule.kt +25 -0
  23. package/android/src/main/java/expo/modules/kotlin/events/EventEmitter.kt +13 -0
  24. package/android/src/main/java/expo/modules/kotlin/events/KModuleEventEmitterWrapper.kt +102 -0
  25. package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +93 -9
  26. package/android/src/main/java/expo/modules/kotlin/exception/ExceptionDecorator.kt +11 -0
  27. package/android/src/main/java/expo/modules/kotlin/{methods/AnyMethod.kt → functions/AnyFunction.kt} +18 -18
  28. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +15 -0
  29. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +170 -0
  30. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromise.kt +15 -0
  31. package/android/src/main/java/expo/modules/kotlin/functions/AsyncSuspendFunction.kt +36 -0
  32. package/android/src/main/java/expo/modules/kotlin/modules/DefinitionMarker.kt +4 -0
  33. package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +17 -2
  34. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +416 -43
  35. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +2 -2
  36. package/android/src/main/java/expo/modules/kotlin/records/FieldValidator.kt +139 -0
  37. package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +71 -15
  38. package/android/src/main/java/expo/modules/kotlin/records/Required.kt +5 -0
  39. package/android/src/main/java/expo/modules/kotlin/records/ValidationBinder.kt +110 -0
  40. package/android/src/main/java/expo/modules/kotlin/records/Validators.kt +61 -0
  41. package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +11 -5
  42. package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverter.kt +35 -0
  43. package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverterHelper.kt +148 -0
  44. package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +10 -4
  45. package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +12 -6
  46. package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +29 -13
  47. package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +2 -1
  48. package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +9 -1
  49. package/android/src/main/java/expo/modules/kotlin/views/CallbacksDefinition.kt +3 -0
  50. package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +71 -0
  51. package/android/src/main/java/expo/modules/kotlin/views/SimpleViewManagerWrapper.kt +22 -0
  52. package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinition.kt +18 -0
  53. package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinitionBuilder.kt +114 -0
  54. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +30 -2
  55. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +81 -2
  56. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +62 -2
  57. package/build/EventEmitter.d.ts +1 -0
  58. package/build/EventEmitter.d.ts.map +1 -0
  59. package/build/NativeModulesProxy.d.ts +1 -0
  60. package/build/NativeModulesProxy.d.ts.map +1 -0
  61. package/build/NativeModulesProxy.native.d.ts +1 -4
  62. package/build/NativeModulesProxy.native.d.ts.map +1 -0
  63. package/build/NativeModulesProxy.native.js +1 -14
  64. package/build/NativeModulesProxy.native.js.map +1 -1
  65. package/build/NativeModulesProxy.types.d.ts +1 -3
  66. package/build/NativeModulesProxy.types.d.ts.map +1 -0
  67. package/build/NativeModulesProxy.types.js.map +1 -1
  68. package/build/NativeViewManagerAdapter.d.ts +1 -0
  69. package/build/NativeViewManagerAdapter.d.ts.map +1 -0
  70. package/build/NativeViewManagerAdapter.native.d.ts +1 -0
  71. package/build/NativeViewManagerAdapter.native.d.ts.map +1 -0
  72. package/build/NativeViewManagerAdapter.native.js +9 -33
  73. package/build/NativeViewManagerAdapter.native.js.map +1 -1
  74. package/build/PermissionsHook.d.ts +1 -0
  75. package/build/PermissionsHook.d.ts.map +1 -0
  76. package/build/PermissionsInterface.d.ts +1 -0
  77. package/build/PermissionsInterface.d.ts.map +1 -0
  78. package/build/Platform.d.ts +1 -0
  79. package/build/Platform.d.ts.map +1 -0
  80. package/build/SyntheticPlatformEmitter.d.ts +1 -0
  81. package/build/SyntheticPlatformEmitter.d.ts.map +1 -0
  82. package/build/SyntheticPlatformEmitter.web.d.ts +1 -0
  83. package/build/SyntheticPlatformEmitter.web.d.ts.map +1 -0
  84. package/build/deprecate.d.ts +1 -0
  85. package/build/deprecate.d.ts.map +1 -0
  86. package/build/environment/browser.d.ts +1 -0
  87. package/build/environment/browser.d.ts.map +1 -0
  88. package/build/environment/browser.web.d.ts +1 -0
  89. package/build/environment/browser.web.d.ts.map +1 -0
  90. package/build/errors/CodedError.d.ts +1 -0
  91. package/build/errors/CodedError.d.ts.map +1 -0
  92. package/build/errors/UnavailabilityError.d.ts +1 -0
  93. package/build/errors/UnavailabilityError.d.ts.map +1 -0
  94. package/build/index.d.ts +3 -0
  95. package/build/index.d.ts.map +1 -0
  96. package/build/index.js +2 -0
  97. package/build/index.js.map +1 -1
  98. package/build/requireNativeModule.d.ts +16 -0
  99. package/build/requireNativeModule.d.ts.map +1 -0
  100. package/build/requireNativeModule.js +18 -0
  101. package/build/requireNativeModule.js.map +1 -0
  102. package/build/sweet/NativeErrorManager.d.ts +3 -0
  103. package/build/sweet/NativeErrorManager.d.ts.map +1 -0
  104. package/build/sweet/NativeErrorManager.js +3 -0
  105. package/build/sweet/NativeErrorManager.js.map +1 -0
  106. package/build/sweet/setUpErrorManager.fx.d.ts +2 -0
  107. package/build/sweet/setUpErrorManager.fx.d.ts.map +1 -0
  108. package/build/sweet/setUpErrorManager.fx.js +11 -0
  109. package/build/sweet/setUpErrorManager.fx.js.map +1 -0
  110. package/ios/AppDelegates/EXAppDelegatesLoader.m +4 -8
  111. package/ios/AppDelegates/ExpoAppDelegate.swift +22 -20
  112. package/ios/EXAppDefines.h +1 -0
  113. package/ios/EXAppDefines.m +6 -0
  114. package/ios/EXUtilities.h +2 -0
  115. package/ios/EXUtilities.m +12 -0
  116. package/ios/ExpoModulesCore.h +4 -0
  117. package/ios/ExpoModulesCore.podspec +4 -2
  118. package/ios/Interfaces/FileSystem/EXFileSystemInterface.h +1 -1
  119. package/ios/Interfaces/TaskManager/EXTaskServiceInterface.h +1 -0
  120. package/ios/JSI/{JSIConversions.h → EXJSIConversions.h} +5 -0
  121. package/ios/JSI/{JSIConversions.mm → EXJSIConversions.mm} +21 -1
  122. package/ios/JSI/{JSIInstaller.h → EXJSIInstaller.h} +10 -0
  123. package/ios/JSI/EXJSIInstaller.mm +17 -0
  124. package/ios/JSI/EXJSIUtils.h +19 -0
  125. package/ios/JSI/EXJSIUtils.mm +89 -0
  126. package/ios/JSI/EXJavaScriptObject.h +97 -0
  127. package/ios/JSI/EXJavaScriptObject.mm +121 -0
  128. package/ios/JSI/EXJavaScriptRuntime.h +73 -0
  129. package/ios/JSI/EXJavaScriptRuntime.mm +153 -0
  130. package/ios/JSI/EXJavaScriptValue.h +57 -0
  131. package/ios/JSI/EXJavaScriptValue.mm +166 -0
  132. package/ios/JSI/ExpoModulesHostObject.h +33 -0
  133. package/ios/JSI/ExpoModulesHostObject.mm +41 -0
  134. package/ios/JSI/JavaScriptRuntime.swift +32 -0
  135. package/ios/JSI/JavaScriptValue.swift +94 -0
  136. package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +3 -23
  137. package/ios/NativeModulesProxy/EXNativeModulesProxy.h +2 -2
  138. package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +101 -75
  139. package/ios/RCTComponentData+Privates.h +12 -0
  140. package/ios/ReactDelegates/EXReactCompatibleHelpers.h +18 -0
  141. package/ios/ReactDelegates/EXReactCompatibleHelpers.m +19 -0
  142. package/ios/ReactDelegates/ExpoReactDelegate.swift +3 -3
  143. package/ios/ReactDelegates/ExpoReactDelegateHandler.swift +4 -4
  144. package/ios/ReactDelegates/ModulePriorities.swift +1 -1
  145. package/ios/Swift/AppContext.swift +57 -4
  146. package/ios/Swift/Arguments/AnyArgumentType.swift +1 -1
  147. package/ios/Swift/Arguments/ArgumentType.swift +4 -0
  148. package/ios/Swift/Arguments/Convertibles.swift +13 -13
  149. package/ios/Swift/Arguments/Types/EnumArgumentType.swift +11 -17
  150. package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +1 -1
  151. package/ios/Swift/Arguments/Types/RawArgumentType.swift +2 -2
  152. package/ios/Swift/Conversions.swift +51 -56
  153. package/ios/Swift/EventListener.swift +8 -10
  154. package/ios/Swift/Events/Callback.swift +66 -0
  155. package/ios/Swift/Events/Event.swift +43 -0
  156. package/ios/Swift/Exceptions/ChainableException.swift +51 -0
  157. package/ios/Swift/{CodedError.swift → Exceptions/CodedError.swift} +1 -12
  158. package/ios/Swift/Exceptions/Exception.swift +62 -0
  159. package/ios/Swift/Exceptions/ExceptionOrigin.swift +28 -0
  160. package/ios/Swift/Exceptions/GenericException.swift +20 -0
  161. package/ios/Swift/Exceptions/UnexpectedException.swift +16 -0
  162. package/ios/Swift/Functions/AnyFunction.swift +16 -1
  163. package/ios/Swift/Functions/AsyncFunctionComponent.swift +182 -0
  164. package/ios/Swift/Functions/ConcreteFunction.swift +52 -59
  165. package/ios/Swift/Functions/SyncFunctionComponent.swift +181 -0
  166. package/ios/Swift/JavaScriptUtils.swift +99 -0
  167. package/ios/Swift/ModuleHolder.swift +69 -18
  168. package/ios/Swift/ModuleRegistry.swift +4 -1
  169. package/ios/Swift/Modules/AnyModule.swift +0 -1
  170. package/ios/Swift/Modules/ModuleDefinition.swift +4 -13
  171. package/ios/Swift/Modules/ModuleDefinitionBuilder.swift +0 -1
  172. package/ios/Swift/Modules/ModuleDefinitionComponents.swift +54 -220
  173. package/ios/Swift/ModulesProvider.swift +3 -11
  174. package/ios/Swift/Objects/ObjectDefinition.swift +30 -0
  175. package/ios/Swift/Objects/ObjectDefinitionComponents.swift +257 -0
  176. package/ios/Swift/Promise.swift +8 -3
  177. package/ios/Swift/Records/AnyField.swift +7 -0
  178. package/ios/Swift/Records/Field.swift +24 -19
  179. package/ios/Swift/Records/FieldOption.swift +1 -1
  180. package/ios/Swift/Records/Record.swift +12 -4
  181. package/ios/Swift/SwiftInteropBridge.swift +53 -15
  182. package/ios/Swift/Views/AnyViewProp.swift +1 -1
  183. package/ios/Swift/Views/ComponentData.swift +96 -0
  184. package/ios/Swift/Views/ConcreteViewProp.swift +6 -8
  185. package/ios/Swift/Views/ExpoView.swift +8 -0
  186. package/ios/Swift/Views/ViewFactory.swift +1 -1
  187. package/ios/Swift/Views/ViewManagerDefinition.swift +23 -2
  188. package/ios/Swift/Views/ViewManagerDefinitionBuilder.swift +0 -1
  189. package/ios/Swift/Views/ViewManagerDefinitionComponents.swift +49 -0
  190. package/ios/Swift/Views/ViewModuleWrapper.swift +5 -2
  191. package/ios/Swift.h +5 -0
  192. package/ios/Tests/ArgumentTypeSpec.swift +5 -7
  193. package/ios/Tests/ConstantsSpec.swift +6 -7
  194. package/ios/Tests/ConvertiblesSpec.swift +35 -36
  195. package/ios/Tests/ExceptionsSpec.swift +111 -0
  196. package/ios/Tests/ExpoModulesSpec.swift +75 -0
  197. package/ios/Tests/FunctionSpec.swift +21 -25
  198. package/ios/Tests/FunctionWithConvertiblesSpec.swift +4 -5
  199. package/ios/Tests/JavaScriptObjectSpec.swift +97 -0
  200. package/ios/Tests/JavaScriptRuntimeSpec.swift +94 -0
  201. package/ios/Tests/Mocks/ModuleMocks.swift +1 -1
  202. package/ios/Tests/Mocks/ModulesProviderMock.swift +0 -1
  203. package/ios/Tests/ModuleEventListenersSpec.swift +16 -17
  204. package/ios/Tests/ModuleRegistrySpec.swift +2 -3
  205. package/ios/Tests/RecordSpec.swift +9 -20
  206. package/package.json +3 -3
  207. package/src/NativeModulesProxy.native.ts +2 -22
  208. package/src/NativeModulesProxy.types.ts +0 -8
  209. package/src/NativeViewManagerAdapter.native.tsx +12 -28
  210. package/src/index.ts +4 -0
  211. package/src/requireNativeModule.ts +29 -0
  212. package/src/sweet/NativeErrorManager.ts +2 -0
  213. package/src/sweet/setUpErrorManager.fx.ts +12 -0
  214. package/android/src/main/java/expo/modules/kotlin/events/KEventEmitterWrapper.kt +0 -26
  215. package/android/src/main/java/expo/modules/kotlin/methods/Method.kt +0 -14
  216. package/android/src/main/java/expo/modules/kotlin/methods/PromiseMethod.kt +0 -15
  217. package/ios/JSI/ExpoModulesProxySpec.h +0 -24
  218. package/ios/JSI/ExpoModulesProxySpec.mm +0 -135
  219. package/ios/JSI/JSIInstaller.mm +0 -22
@@ -0,0 +1,99 @@
1
+ // Copyright 2022-present 650 Industries. All rights reserved.
2
+
3
+ // FIXME: Calling module's functions needs solid refactoring to not reference the module holder.
4
+ // Instead, it should be possible to directly call the function instance from here. (added by @tsapeta)
5
+
6
+ /**
7
+ Creates a block that is executed when the module's async function is called.
8
+ */
9
+ internal func createAsyncFunctionBlock(holder: ModuleHolder, name functionName: String) -> JSAsyncFunctionBlock {
10
+ let moduleName = holder.name
11
+ return { [weak holder, moduleName] args, resolve, reject in
12
+ guard let holder = holder else {
13
+ let exception = ModuleUnavailableException(moduleName)
14
+ reject(exception.code, exception.description, exception)
15
+ return
16
+ }
17
+ holder.call(function: functionName, args: args) { result, error in
18
+ if let error = error {
19
+ reject(error.code, error.description, error)
20
+ } else {
21
+ resolve(result)
22
+ }
23
+ }
24
+ }
25
+ }
26
+
27
+ /**
28
+ Creates a block that is executed when the module's sync function is called.
29
+ */
30
+ internal func createSyncFunctionBlock(holder: ModuleHolder, name functionName: String) -> JSSyncFunctionBlock {
31
+ return { [weak holder] args in
32
+ guard let holder = holder else {
33
+ return nil
34
+ }
35
+ return holder.callSync(function: functionName, args: args)
36
+ }
37
+ }
38
+
39
+ // MARK: - Arguments
40
+
41
+ /**
42
+ Tries to cast given argument to the type that is wrapped by the argument type.
43
+ - Parameters:
44
+ - argument: A value to be cast. If it's a ``JavaScriptValue``, it's first unpacked to the raw value.
45
+ - argumentType: Something that implements ``AnyArgumentType`` and knows how to cast the argument.
46
+ - Returns: A new value converted according to the argument type.
47
+ - Throws: Rethrows various exceptions that could be thrown by the argument type wrappers.
48
+ */
49
+ internal func castArgument(_ argument: Any, toType argumentType: AnyArgumentType) throws -> Any {
50
+ // TODO: Accept JavaScriptValue and JavaScriptObject as argument types.
51
+ if let argument = argument as? JavaScriptValue {
52
+ return try argumentType.cast(argument.getRaw())
53
+ }
54
+ return try argumentType.cast(argument)
55
+ }
56
+
57
+ /**
58
+ Same as ``castArgument(_:argumentType:)`` but for an array of arguments.
59
+ - Parameters:
60
+ - arguments: An array of arguments to be cast.
61
+ - argumentTypes: An array of argument types in the same order as the array of arguments.
62
+ - Returns: An array of arguments after casting. Its size is the same as the input arrays.
63
+ - Throws: ``InvalidArgsNumberException`` when the sizes of arrays passed as parameters are not equal.
64
+ Rethrows exceptions thrown by ``castArgument(_:argumentType:)``.
65
+ */
66
+ internal func castArguments(_ arguments: [Any], toTypes argumentTypes: [AnyArgumentType]) throws -> [Any] {
67
+ if arguments.count != argumentTypes.count {
68
+ throw InvalidArgsNumberException((received: arguments.count, expected: argumentTypes.count))
69
+ }
70
+ return try arguments.enumerated().map { index, argument in
71
+ let argumentType = argumentTypes[index]
72
+
73
+ do {
74
+ return try castArgument(argument, toType: argumentType)
75
+ } catch {
76
+ throw ArgumentCastException((index: index, type: argumentType)).causedBy(error)
77
+ }
78
+ }
79
+ }
80
+
81
+ internal class InvalidArgsNumberException: GenericException<(received: Int, expected: Int)> {
82
+ override var reason: String {
83
+ "Received \(param.received) arguments, but \(param.expected) was expected"
84
+ }
85
+ }
86
+
87
+ internal class ArgumentCastException: GenericException<(index: Int, type: AnyArgumentType)> {
88
+ override var reason: String {
89
+ "Argument at index '\(param.index)' couldn't be cast to type \(param.type.description)"
90
+ }
91
+ }
92
+
93
+ // MARK: - Exceptions
94
+
95
+ private class ModuleUnavailableException: GenericException<String> {
96
+ override var reason: String {
97
+ "Module '\(param)' is no longer available"
98
+ }
99
+ }
@@ -14,6 +14,11 @@ public final class ModuleHolder {
14
14
  */
15
15
  private(set) weak var appContext: AppContext?
16
16
 
17
+ /**
18
+ JavaScript object that represents the module instance in the runtime.
19
+ */
20
+ public internal(set) lazy var javaScriptObject: JavaScriptObject? = createJavaScriptModuleObject()
21
+
17
22
  /**
18
23
  Caches the definition of the module type.
19
24
  */
@@ -26,6 +31,13 @@ public final class ModuleHolder {
26
31
  return definition.name.isEmpty ? String(describing: type(of: module)) : definition.name
27
32
  }
28
33
 
34
+ /**
35
+ Shortcut to get the underlying view manager definition.
36
+ */
37
+ var viewManager: ViewManagerDefinition? {
38
+ return definition.viewManager
39
+ }
40
+
29
41
  /**
30
42
  Number of JavaScript listeners attached to the module.
31
43
  */
@@ -54,17 +66,24 @@ public final class ModuleHolder {
54
66
  func call(function functionName: String, args: [Any], promise: Promise) {
55
67
  do {
56
68
  guard let function = definition.functions[functionName] else {
57
- throw FunctionNotFoundError(functionName: functionName, moduleName: self.name)
69
+ throw FunctionNotFoundException((functionName: functionName, moduleName: self.name))
58
70
  }
59
71
  let queue = function.queue ?? DispatchQueue.global(qos: .default)
60
72
 
73
+ // Given arguments can be:
74
+ // - Swift primitives when invoked through the bridge and in unit tests
75
+ // - `JavaScriptValue`s when the function is called through the JSI
76
+ // The latter need to be unpacked to Swift primitives on the JS thread,
77
+ // so we do the casting before the function call is scheduled on the queue.
78
+ let arguments = try castArguments(args, toTypes: function.argumentTypes)
79
+
61
80
  queue.async {
62
- function.call(args: args, promise: promise)
81
+ function.call(args: arguments, promise: promise)
63
82
  }
64
83
  } catch let error as CodedError {
65
84
  promise.reject(error)
66
85
  } catch {
67
- promise.reject(UnexpectedError(error))
86
+ promise.reject(UnexpectedException(error))
68
87
  }
69
88
  }
70
89
 
@@ -79,10 +98,45 @@ public final class ModuleHolder {
79
98
 
80
99
  @discardableResult
81
100
  func callSync(function functionName: String, args: [Any]) -> Any? {
82
- if let function = definition.functions[functionName] {
83
- return function.callSync(args: args)
101
+ guard let function = definition.functions[functionName] else {
102
+ return nil
103
+ }
104
+ do {
105
+ let arguments = try castArguments(args, toTypes: function.argumentTypes)
106
+ return function.callSync(args: arguments)
107
+ } catch {
108
+ return error
109
+ }
110
+ }
111
+
112
+ // MARK: JavaScript Module Object
113
+
114
+ /**
115
+ Creates the JavaScript object that will be used to communicate with the native module.
116
+ The object is prefilled with module's constants and functions.
117
+ JavaScript can access it through `global.ExpoModules[moduleName]`.
118
+ - Note: The object will be `nil` when the runtime is unavailable (e.g. remote debugger is enabled).
119
+ */
120
+ private func createJavaScriptModuleObject() -> JavaScriptObject? {
121
+ // It might be impossible to create any object at the moment (e.g. remote debugging, app context destroyed)
122
+ guard let object = appContext?.runtime?.createObject() else {
123
+ return nil
124
+ }
125
+
126
+ // Fill in with constants
127
+ for (key, value) in getConstants() {
128
+ object.setProperty(key, value: value)
129
+ }
130
+
131
+ // Fill in with functions
132
+ for (_, fn) in definition.functions {
133
+ if fn.isAsync {
134
+ object.setAsyncFunction(fn.name, argsCount: fn.argumentsCount, block: createAsyncFunctionBlock(holder: self, name: fn.name))
135
+ } else {
136
+ object.setSyncFunction(fn.name, argsCount: fn.argumentsCount, block: createSyncFunctionBlock(holder: self, name: fn.name))
137
+ }
84
138
  }
85
- return nil
139
+ return object
86
140
  }
87
141
 
88
142
  // MARK: Listening to native events
@@ -112,9 +166,9 @@ public final class ModuleHolder {
112
166
  */
113
167
  func modifyListenersCount(_ count: Int) {
114
168
  if count > 0 && listenersCount == 0 {
115
- let _ = definition.functions["startObserving"]?.callSync(args: [])
169
+ _ = definition.functions["startObserving"]?.callSync(args: [])
116
170
  } else if count < 0 && listenersCount + count <= 0 {
117
- let _ = definition.functions["stopObserving"]?.callSync(args: [])
171
+ _ = definition.functions["stopObserving"]?.callSync(args: [])
118
172
  }
119
173
  listenersCount = max(0, listenersCount + count)
120
174
  }
@@ -125,20 +179,17 @@ public final class ModuleHolder {
125
179
  post(event: .moduleDestroy)
126
180
  }
127
181
 
128
- // MARK: Errors
182
+ // MARK: - Exceptions
129
183
 
130
- struct ModuleNotFoundError: CodedError {
131
- let moduleName: String
132
- var description: String {
133
- "Cannot find module `\(moduleName)`"
184
+ internal class ModuleNotFoundException: GenericException<String> {
185
+ override var reason: String {
186
+ "Module '\(param)' not found"
134
187
  }
135
188
  }
136
189
 
137
- struct FunctionNotFoundError: CodedError {
138
- let functionName: String
139
- let moduleName: String
140
- var description: String {
141
- "Cannot find function `\(functionName)` in module `\(moduleName)`"
190
+ internal class FunctionNotFoundException: GenericException<(functionName: String, moduleName: String)> {
191
+ override var reason: String {
192
+ "Function '\(param.functionName)' not found in module '\(param.moduleName)'"
142
193
  }
143
194
  }
144
195
  }
@@ -1,4 +1,3 @@
1
-
2
1
  public final class ModuleRegistry: Sequence {
3
2
  public typealias Element = ModuleHolder
4
3
 
@@ -63,6 +62,10 @@ public final class ModuleRegistry: Sequence {
63
62
  return registry[moduleName]?.module
64
63
  }
65
64
 
65
+ public func getModuleNames() -> [String] {
66
+ return Array(registry.keys)
67
+ }
68
+
66
69
  public func makeIterator() -> IndexingIterator<[ModuleHolder]> {
67
70
  return registry.map({ $1 }).makeIterator()
68
71
  }
@@ -1,4 +1,3 @@
1
-
2
1
  /**
3
2
  A protocol for any type-erased module that provides functions used by the core.
4
3
  */
@@ -1,4 +1,3 @@
1
-
2
1
  /**
3
2
  A protocol that must be implemented to be a part of module's definition and the module definition itself.
4
3
  */
@@ -9,7 +8,7 @@ public protocol AnyDefinition {}
9
8
  of the module and what it exports to the JavaScript world.
10
9
  See `ModuleDefinitionBuilder` for more details on how to create it.
11
10
  */
12
- public final class ModuleDefinition: AnyDefinition {
11
+ public final class ModuleDefinition: ObjectDefinition {
13
12
  /**
14
13
  The module's type associated with the definition. It's used to create the module instance.
15
14
  */
@@ -20,8 +19,6 @@ public final class ModuleDefinition: AnyDefinition {
20
19
  */
21
20
  var name: String
22
21
 
23
- let functions: [String : AnyFunction]
24
- let constants: [ConstantsDefinition]
25
22
  let eventListeners: [EventListener]
26
23
  let viewManager: ViewManagerDefinition?
27
24
 
@@ -33,20 +30,12 @@ public final class ModuleDefinition: AnyDefinition {
33
30
  /**
34
31
  Initializer that is called by the `ModuleDefinitionBuilder` results builder.
35
32
  */
36
- init(definitions: [AnyDefinition]) {
33
+ override init(definitions: [AnyDefinition]) {
37
34
  self.name = definitions
38
35
  .compactMap { $0 as? ModuleNameDefinition }
39
36
  .last?
40
37
  .name ?? ""
41
38
 
42
- self.functions = definitions
43
- .compactMap { $0 as? AnyFunction }
44
- .reduce(into: [String : AnyFunction]()) { dict, function in
45
- dict[function.name] = function
46
- }
47
-
48
- self.constants = definitions.compactMap { $0 as? ConstantsDefinition }
49
-
50
39
  self.eventListeners = definitions.compactMap { $0 as? EventListener }
51
40
 
52
41
  self.viewManager = definitions
@@ -58,6 +47,8 @@ public final class ModuleDefinition: AnyDefinition {
58
47
  .compactMap { ($0 as? EventsDefinition)?.names }
59
48
  .joined()
60
49
  )
50
+
51
+ super.init(definitions: definitions)
61
52
  }
62
53
 
63
54
  /**
@@ -1,4 +1,3 @@
1
-
2
1
  #if swift(>=5.4)
3
2
  /**
4
3
  A function builder that provides DSL-like syntax. Thanks to this, the function doesn't need to explicitly return an array,
@@ -12,159 +12,17 @@ extension AnyModule {
12
12
  /**
13
13
  Sets the name of the module that is exported to the JavaScript world.
14
14
  */
15
+ @available(*, deprecated, renamed: "Name")
15
16
  public func name(_ name: String) -> AnyDefinition {
16
17
  return ModuleNameDefinition(name: name)
17
18
  }
18
19
 
19
- // MARK: - Constants
20
-
21
- /**
22
- Definition function setting the module's constants to export.
23
- */
24
- public func constants(_ body: @escaping () -> [String: Any?]) -> AnyDefinition {
25
- return ConstantsDefinition(body: body)
26
- }
27
-
28
- /**
29
- Definition function setting the module's constants to export.
30
- */
31
- public func constants(_ body: @autoclosure @escaping () -> [String: Any?]) -> AnyDefinition {
32
- return ConstantsDefinition(body: body)
33
- }
34
-
35
- // MARK: - Functions
36
-
37
- /**
38
- Function without arguments.
39
- */
40
- public func function<R>(
41
- _ name: String,
42
- _ closure: @escaping () -> R
43
- ) -> AnyFunction {
44
- return ConcreteFunction(
45
- name,
46
- argTypes: [],
47
- closure
48
- )
49
- }
50
-
51
- /**
52
- Function with one argument.
53
- */
54
- public func function<R, A0: AnyArgument>(
55
- _ name: String,
56
- _ closure: @escaping (A0) -> R
57
- ) -> AnyFunction {
58
- return ConcreteFunction(
59
- name,
60
- argTypes: [ArgumentType(A0.self)],
61
- closure
62
- )
63
- }
64
-
65
- /**
66
- Function with two arguments.
67
- */
68
- public func function<R, A0: AnyArgument, A1: AnyArgument>(
69
- _ name: String,
70
- _ closure: @escaping (A0, A1) -> R
71
- ) -> AnyFunction {
72
- return ConcreteFunction(
73
- name,
74
- argTypes: [ArgumentType(A0.self), ArgumentType(A1.self)],
75
- closure
76
- )
77
- }
78
-
79
- /**
80
- Function with three arguments.
81
- */
82
- public func function<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument>(
83
- _ name: String,
84
- _ closure: @escaping (A0, A1, A2) -> R
85
- ) -> AnyFunction {
86
- return ConcreteFunction(
87
- name,
88
- argTypes: [ArgumentType(A0.self), ArgumentType(A1.self), ArgumentType(A2.self)],
89
- closure
90
- )
91
- }
92
-
93
- /**
94
- Function with four arguments.
95
- */
96
- public func function<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument>(
97
- _ name: String,
98
- _ closure: @escaping (A0, A1, A2, A3) -> R
99
- ) -> AnyFunction {
100
- return ConcreteFunction(
101
- name,
102
- argTypes: [ArgumentType(A0.self), ArgumentType(A1.self), ArgumentType(A2.self), ArgumentType(A3.self)],
103
- closure
104
- )
105
- }
106
-
107
- /**
108
- Function with five arguments.
109
- */
110
- public func function<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument>(
111
- _ name: String,
112
- _ closure: @escaping (A0, A1, A2, A3, A4) -> R
113
- ) -> AnyFunction {
114
- return ConcreteFunction(
115
- name,
116
- argTypes: [ArgumentType(A0.self), ArgumentType(A1.self), ArgumentType(A2.self), ArgumentType(A3.self), ArgumentType(A4.self)],
117
- closure
118
- )
119
- }
120
-
121
- /**
122
- Function with six arguments.
123
- */
124
- public func function<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument, A5: AnyArgument>(
125
- _ name: String,
126
- _ closure: @escaping (A0, A1, A2, A3, A4, A5) -> R
127
- ) -> AnyFunction {
128
- return ConcreteFunction(
129
- name,
130
- argTypes: [ArgumentType(A0.self), ArgumentType(A1.self), ArgumentType(A2.self), ArgumentType(A3.self), ArgumentType(A4.self), ArgumentType(A5.self)],
131
- closure
132
- )
133
- }
134
-
135
- /**
136
- Function with seven arguments.
137
- */
138
- public func function<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument, A5: AnyArgument, A6: AnyArgument>(
139
- _ name: String,
140
- _ closure: @escaping (A0, A1, A2, A3, A4, A5, A6) -> R
141
- ) -> AnyFunction {
142
- return ConcreteFunction(
143
- name,
144
- argTypes: [ArgumentType(A0.self), ArgumentType(A1.self), ArgumentType(A2.self), ArgumentType(A3.self), ArgumentType(A4.self), ArgumentType(A5.self), ArgumentType(A6.self)],
145
- closure
146
- )
147
- }
148
-
149
- /**
150
- Function with eight arguments.
151
- */
152
- public func function<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument, A5: AnyArgument, A6: AnyArgument, A7: AnyArgument>(
153
- _ name: String,
154
- _ closure: @escaping (A0, A1, A2, A3, A4, A5, A6, A7) -> R
155
- ) -> AnyFunction {
156
- return ConcreteFunction(
157
- name,
158
- argTypes: [ArgumentType(A0.self), ArgumentType(A1.self), ArgumentType(A2.self), ArgumentType(A3.self), ArgumentType(A4.self), ArgumentType(A5.self), ArgumentType(A6.self), ArgumentType(A7.self)],
159
- closure
160
- )
161
- }
162
-
163
20
  // MARK: - Module's lifecycle
164
21
 
165
22
  /**
166
23
  Creates module's lifecycle listener that is called right after module initialization.
167
24
  */
25
+ @available(*, deprecated, renamed: "OnCreate")
168
26
  public func onCreate(_ closure: @escaping () -> Void) -> AnyDefinition {
169
27
  return EventListener(.moduleCreate, closure)
170
28
  }
@@ -172,6 +30,7 @@ extension AnyModule {
172
30
  /**
173
31
  Creates module's lifecycle listener that is called when the module is about to be deallocated.
174
32
  */
33
+ @available(*, deprecated, renamed: "OnDestroy")
175
34
  public func onDestroy(_ closure: @escaping () -> Void) -> AnyDefinition {
176
35
  return EventListener(.moduleDestroy, closure)
177
36
  }
@@ -179,6 +38,7 @@ extension AnyModule {
179
38
  /**
180
39
  Creates module's lifecycle listener that is called when the app context owning the module is about to be deallocated.
181
40
  */
41
+ @available(*, deprecated, renamed: "OnAppContextDestroys")
182
42
  public func onAppContextDestroys(_ closure: @escaping () -> Void) -> AnyDefinition {
183
43
  return EventListener(.appContextDestroys, closure)
184
44
  }
@@ -186,6 +46,7 @@ extension AnyModule {
186
46
  /**
187
47
  Creates a listener that is called when the app is about to enter the foreground mode.
188
48
  */
49
+ @available(*, deprecated, renamed: "OnAppEntersBackground")
189
50
  public func onAppEntersForeground(_ closure: @escaping () -> Void) -> AnyDefinition {
190
51
  return EventListener(.appEntersForeground, closure)
191
52
  }
@@ -193,6 +54,7 @@ extension AnyModule {
193
54
  /**
194
55
  Creates a listener that is called when the app becomes active again.
195
56
  */
57
+ @available(*, deprecated, renamed: "OnAppBecomesActive")
196
58
  public func onAppBecomesActive(_ closure: @escaping () -> Void) -> AnyDefinition {
197
59
  return EventListener(.appBecomesActive, closure)
198
60
  }
@@ -200,6 +62,7 @@ extension AnyModule {
200
62
  /**
201
63
  Creates a listener that is called when the app enters the background mode.
202
64
  */
65
+ @available(*, deprecated, renamed: "OnAppEntersBackground")
203
66
  public func onAppEntersBackground(_ closure: @escaping () -> Void) -> AnyDefinition {
204
67
  return EventListener(.appEntersBackground, closure)
205
68
  }
@@ -209,99 +72,70 @@ extension AnyModule {
209
72
  /**
210
73
  Creates the view manager definition that scopes other view-related definitions.
211
74
  */
75
+ @available(*, deprecated, renamed: "ViewManager")
212
76
  public func viewManager(@ViewManagerDefinitionBuilder _ closure: @escaping () -> ViewManagerDefinition) -> AnyDefinition {
213
77
  return closure()
214
78
  }
79
+ }
215
80
 
216
- // MARK: - Events
81
+ // MARK: - Module name
217
82
 
218
- /**
219
- Defines event names that this module can send to JavaScript.
220
- */
221
- public func events(_ names: String...) -> AnyDefinition {
222
- return EventsDefinition(names: names)
223
- }
83
+ /**
84
+ Sets the name of the module that is exported to the JavaScript world.
85
+ */
86
+ public func Name(_ name: String) -> AnyDefinition {
87
+ return ModuleNameDefinition(name: name)
88
+ }
224
89
 
225
- /**
226
- Function that is invoked when the first event listener is added.
227
- */
228
- public func onStartObserving(_ body: @escaping () -> ()) -> AnyFunction {
229
- return ConcreteFunction("startObserving", argTypes: [], body)
230
- }
90
+ // MARK: - Module's lifecycle
231
91
 
232
- /**
233
- Function that is invoked when all event listeners are removed.
234
- */
235
- public func onStopObserving(_ body: @escaping () -> ()) -> AnyFunction {
236
- return ConcreteFunction("stopObserving", argTypes: [], body)
237
- }
92
+ /**
93
+ Creates module's lifecycle listener that is called right after module initialization.
94
+ */
95
+ public func OnCreate(_ closure: @escaping () -> Void) -> AnyDefinition {
96
+ return EventListener(.moduleCreate, closure)
238
97
  }
239
98
 
240
99
  /**
241
- Defines the factory creating a native view when the module is used as a view.
100
+ Creates module's lifecycle listener that is called when the module is about to be deallocated.
242
101
  */
243
- public func view(_ closure: @escaping () -> UIView) -> AnyDefinition {
244
- return ViewFactory(closure)
102
+ public func OnDestroy(_ closure: @escaping () -> Void) -> AnyDefinition {
103
+ return EventListener(.moduleDestroy, closure)
245
104
  }
246
105
 
247
106
  /**
248
- Creates a view prop that defines its name and setter.
107
+ Creates module's lifecycle listener that is called when the app context owning the module is about to be deallocated.
249
108
  */
250
- public func prop<ViewType: UIView, PropType: AnyArgument>(
251
- _ name: String,
252
- _ setter: @escaping (ViewType, PropType) -> Void
253
- ) -> AnyDefinition {
254
- return ConcreteViewProp(
255
- name: name,
256
- propType: ArgumentType(PropType.self),
257
- setter: setter
258
- )
109
+ public func OnAppContextDestroys(_ closure: @escaping () -> Void) -> AnyDefinition {
110
+ return EventListener(.appContextDestroys, closure)
259
111
  }
260
112
 
261
- // TODO: - Remove deprecated `method` component once SDK44 is out.
262
- public extension AnyModule {
263
- /**
264
- Function without arguments.
265
- */
266
- @available(*, deprecated, renamed: "function")
267
- func method<R>(
268
- _ name: String,
269
- _ closure: @escaping () -> R
270
- ) -> AnyFunction {
271
- return ConcreteFunction(
272
- name,
273
- argTypes: [],
274
- closure
275
- )
276
- }
113
+ /**
114
+ Creates a listener that is called when the app is about to enter the foreground mode.
115
+ */
116
+ public func OnAppEntersForeground(_ closure: @escaping () -> Void) -> AnyDefinition {
117
+ return EventListener(.appEntersForeground, closure)
118
+ }
277
119
 
278
- /**
279
- Function with one argument.
280
- */
281
- @available(*, deprecated, renamed: "function")
282
- func method<R, A0: AnyArgument>(
283
- _ name: String,
284
- _ closure: @escaping (A0) -> R
285
- ) -> AnyFunction {
286
- return ConcreteFunction(
287
- name,
288
- argTypes: [ArgumentType(A0.self)],
289
- closure
290
- )
291
- }
120
+ /**
121
+ Creates a listener that is called when the app becomes active again.
122
+ */
123
+ public func OnAppBecomesActive(_ closure: @escaping () -> Void) -> AnyDefinition {
124
+ return EventListener(.appBecomesActive, closure)
125
+ }
292
126
 
293
- /**
294
- Function with two arguments.
295
- */
296
- @available(*, deprecated, renamed: "function")
297
- func method<R, A0: AnyArgument, A1: AnyArgument>(
298
- _ name: String,
299
- _ closure: @escaping (A0, A1) -> R
300
- ) -> AnyFunction {
301
- return ConcreteFunction(
302
- name,
303
- argTypes: [ArgumentType(A0.self), ArgumentType(A1.self)],
304
- closure
305
- )
306
- }
127
+ /**
128
+ Creates a listener that is called when the app enters the background mode.
129
+ */
130
+ public func OnAppEntersBackground(_ closure: @escaping () -> Void) -> AnyDefinition {
131
+ return EventListener(.appEntersBackground, closure)
132
+ }
133
+
134
+ // MARK: - View Manager
135
+
136
+ /**
137
+ Creates the view manager definition that scopes other view-related definitions.
138
+ */
139
+ public func ViewManager(@ViewManagerDefinitionBuilder _ closure: @escaping () -> ViewManagerDefinition) -> AnyDefinition {
140
+ return closure()
307
141
  }