expo-modules-core 0.6.4 → 0.7.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 (159) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +1 -1
  3. package/android/build.gradle +5 -5
  4. package/android/src/main/java/expo/modules/kotlin/AppContext.kt +11 -1
  5. package/android/src/main/java/expo/modules/kotlin/DynamicExtenstions.kt +5 -3
  6. package/android/src/main/java/expo/modules/kotlin/KPromiseWrapper.kt +8 -2
  7. package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +13 -4
  8. package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +7 -6
  9. package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +6 -1
  10. package/android/src/main/java/expo/modules/kotlin/Promise.kt +1 -1
  11. package/android/src/main/java/expo/modules/kotlin/callbacks/Callback.kt +5 -0
  12. package/android/src/main/java/expo/modules/kotlin/callbacks/ViewCallback.kt +28 -0
  13. package/android/src/main/java/expo/modules/kotlin/callbacks/ViewCallbackDelegate.kt +27 -0
  14. package/android/src/main/java/expo/modules/kotlin/defaultmodules/ErrorManagerModule.kt +25 -0
  15. package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +68 -8
  16. package/android/src/main/java/expo/modules/kotlin/exception/ExceptionDecorator.kt +11 -0
  17. package/android/src/main/java/expo/modules/kotlin/methods/AnyMethod.kt +13 -14
  18. package/android/src/main/java/expo/modules/kotlin/modules/DefinitionMarker.kt +4 -0
  19. package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +3 -2
  20. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +44 -4
  21. package/android/src/main/java/expo/modules/kotlin/records/Record.kt +39 -0
  22. package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +14 -7
  23. package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +11 -5
  24. package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +10 -4
  25. package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +12 -6
  26. package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +29 -13
  27. package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +2 -1
  28. package/android/src/main/java/expo/modules/kotlin/views/CallbacksDefinition.kt +3 -0
  29. package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +22 -0
  30. package/android/src/main/java/expo/modules/kotlin/views/SimpleViewManagerWrapper.kt +22 -0
  31. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +27 -2
  32. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +29 -1
  33. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +59 -2
  34. package/build/EventEmitter.d.ts +1 -0
  35. package/build/EventEmitter.d.ts.map +1 -0
  36. package/build/NativeModulesProxy.d.ts +1 -0
  37. package/build/NativeModulesProxy.d.ts.map +1 -0
  38. package/build/NativeModulesProxy.native.d.ts +1 -0
  39. package/build/NativeModulesProxy.native.d.ts.map +1 -0
  40. package/build/NativeModulesProxy.types.d.ts +1 -0
  41. package/build/NativeModulesProxy.types.d.ts.map +1 -0
  42. package/build/NativeViewManagerAdapter.d.ts +1 -0
  43. package/build/NativeViewManagerAdapter.d.ts.map +1 -0
  44. package/build/NativeViewManagerAdapter.native.d.ts +1 -0
  45. package/build/NativeViewManagerAdapter.native.d.ts.map +1 -0
  46. package/build/PermissionsHook.d.ts +1 -0
  47. package/build/PermissionsHook.d.ts.map +1 -0
  48. package/build/PermissionsInterface.d.ts +1 -0
  49. package/build/PermissionsInterface.d.ts.map +1 -0
  50. package/build/Platform.d.ts +1 -0
  51. package/build/Platform.d.ts.map +1 -0
  52. package/build/SyntheticPlatformEmitter.d.ts +1 -0
  53. package/build/SyntheticPlatformEmitter.d.ts.map +1 -0
  54. package/build/SyntheticPlatformEmitter.web.d.ts +1 -0
  55. package/build/SyntheticPlatformEmitter.web.d.ts.map +1 -0
  56. package/build/deprecate.d.ts +1 -0
  57. package/build/deprecate.d.ts.map +1 -0
  58. package/build/environment/browser.d.ts +1 -0
  59. package/build/environment/browser.d.ts.map +1 -0
  60. package/build/environment/browser.web.d.ts +1 -0
  61. package/build/environment/browser.web.d.ts.map +1 -0
  62. package/build/errors/CodedError.d.ts +1 -0
  63. package/build/errors/CodedError.d.ts.map +1 -0
  64. package/build/errors/UnavailabilityError.d.ts +1 -0
  65. package/build/errors/UnavailabilityError.d.ts.map +1 -0
  66. package/build/index.d.ts +3 -0
  67. package/build/index.d.ts.map +1 -0
  68. package/build/index.js +2 -0
  69. package/build/index.js.map +1 -1
  70. package/build/requireNativeModule.d.ts +16 -0
  71. package/build/requireNativeModule.d.ts.map +1 -0
  72. package/build/requireNativeModule.js +18 -0
  73. package/build/requireNativeModule.js.map +1 -0
  74. package/build/sweet/NativeErrorManager.d.ts +3 -0
  75. package/build/sweet/NativeErrorManager.d.ts.map +1 -0
  76. package/build/sweet/NativeErrorManager.js +3 -0
  77. package/build/sweet/NativeErrorManager.js.map +1 -0
  78. package/build/sweet/setUpErrorManager.fx.d.ts +2 -0
  79. package/build/sweet/setUpErrorManager.fx.d.ts.map +1 -0
  80. package/build/sweet/setUpErrorManager.fx.js +11 -0
  81. package/build/sweet/setUpErrorManager.fx.js.map +1 -0
  82. package/ios/AppDelegates/ExpoAppDelegate.swift +18 -10
  83. package/ios/JSI/ExpoModulesHostObject.h +33 -0
  84. package/ios/JSI/ExpoModulesHostObject.mm +40 -0
  85. package/ios/JSI/ExpoModulesProxySpec.h +4 -0
  86. package/ios/JSI/ExpoModulesProxySpec.mm +1 -3
  87. package/ios/JSI/JSIConversions.h +2 -0
  88. package/ios/JSI/JSIConversions.mm +9 -0
  89. package/ios/JSI/JSIInstaller.h +10 -0
  90. package/ios/JSI/JSIInstaller.mm +14 -2
  91. package/ios/JSI/JavaScriptObject.h +60 -0
  92. package/ios/JSI/JavaScriptObject.mm +93 -0
  93. package/ios/JSI/JavaScriptRuntime.h +54 -0
  94. package/ios/JSI/JavaScriptRuntime.mm +102 -0
  95. package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +2 -12
  96. package/ios/NativeModulesProxy/EXComponentDataCompatibleWrapper.h +16 -0
  97. package/ios/NativeModulesProxy/EXComponentDataCompatibleWrapper.m +28 -0
  98. package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +90 -66
  99. package/ios/RCTComponentData+Privates.h +12 -0
  100. package/ios/ReactDelegates/ExpoReactDelegate.swift +2 -2
  101. package/ios/ReactDelegates/ExpoReactDelegateHandler.swift +3 -3
  102. package/ios/ReactDelegates/ModulePriorities.swift +1 -1
  103. package/ios/Swift/AppContext.swift +38 -4
  104. package/ios/Swift/Arguments/ArgumentType.swift +4 -0
  105. package/ios/Swift/Arguments/Convertibles.swift +13 -13
  106. package/ios/Swift/Arguments/Types/EnumArgumentType.swift +11 -17
  107. package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +1 -1
  108. package/ios/Swift/Arguments/Types/RawArgumentType.swift +2 -2
  109. package/ios/Swift/Conversions.swift +51 -56
  110. package/ios/Swift/EventListener.swift +8 -10
  111. package/ios/Swift/Events/Callback.swift +66 -0
  112. package/ios/Swift/Events/Event.swift +43 -0
  113. package/ios/Swift/Exceptions/ChainableException.swift +51 -0
  114. package/ios/Swift/{CodedError.swift → Exceptions/CodedError.swift} +1 -12
  115. package/ios/Swift/Exceptions/Exception.swift +62 -0
  116. package/ios/Swift/Exceptions/ExceptionOrigin.swift +28 -0
  117. package/ios/Swift/Exceptions/GenericException.swift +20 -0
  118. package/ios/Swift/Exceptions/UnexpectedException.swift +16 -0
  119. package/ios/Swift/Functions/AnyFunction.swift +11 -1
  120. package/ios/Swift/Functions/ConcreteFunction.swift +37 -16
  121. package/ios/Swift/JavaScriptUtils.swift +43 -0
  122. package/ios/Swift/ModuleHolder.swift +53 -14
  123. package/ios/Swift/ModuleRegistry.swift +4 -1
  124. package/ios/Swift/Modules/AnyModule.swift +0 -1
  125. package/ios/Swift/Modules/ModuleDefinition.swift +4 -13
  126. package/ios/Swift/Modules/ModuleDefinitionBuilder.swift +0 -1
  127. package/ios/Swift/Modules/ModuleDefinitionComponents.swift +0 -188
  128. package/ios/Swift/ModulesProvider.swift +0 -1
  129. package/ios/Swift/Objects/ObjectDefinition.swift +30 -0
  130. package/ios/Swift/Objects/ObjectDefinitionComponents.swift +208 -0
  131. package/ios/Swift/Promise.swift +8 -3
  132. package/ios/Swift/Records/AnyField.swift +7 -0
  133. package/ios/Swift/Records/Field.swift +24 -19
  134. package/ios/Swift/Records/FieldOption.swift +1 -1
  135. package/ios/Swift/Records/Record.swift +12 -4
  136. package/ios/Swift/SwiftInteropBridge.swift +39 -10
  137. package/ios/Swift/Views/AnyViewProp.swift +1 -1
  138. package/ios/Swift/Views/ComponentData.swift +95 -0
  139. package/ios/Swift/Views/ConcreteViewProp.swift +6 -8
  140. package/ios/Swift/Views/ViewFactory.swift +1 -1
  141. package/ios/Swift/Views/ViewManagerDefinition.swift +23 -2
  142. package/ios/Swift/Views/ViewManagerDefinitionBuilder.swift +0 -1
  143. package/ios/Swift/Views/ViewManagerDefinitionComponents.swift +26 -0
  144. package/ios/Swift/Views/ViewModuleWrapper.swift +5 -2
  145. package/ios/Tests/ArgumentTypeSpec.swift +3 -4
  146. package/ios/Tests/ConstantsSpec.swift +4 -4
  147. package/ios/Tests/ConvertiblesSpec.swift +33 -33
  148. package/ios/Tests/ExceptionsSpec.swift +112 -0
  149. package/ios/Tests/FunctionSpec.swift +20 -22
  150. package/ios/Tests/FunctionWithConvertiblesSpec.swift +2 -2
  151. package/ios/Tests/Mocks/ModuleMocks.swift +1 -1
  152. package/ios/Tests/Mocks/ModulesProviderMock.swift +0 -1
  153. package/ios/Tests/ModuleEventListenersSpec.swift +1 -1
  154. package/ios/Tests/RecordSpec.swift +7 -17
  155. package/package.json +3 -3
  156. package/src/index.ts +4 -0
  157. package/src/requireNativeModule.ts +29 -0
  158. package/src/sweet/NativeErrorManager.ts +2 -0
  159. package/src/sweet/setUpErrorManager.fx.ts +12 -0
@@ -0,0 +1,28 @@
1
+ // Copyright 2022-present 650 Industries. All rights reserved.
2
+
3
+ /**
4
+ Represents the place in code where the exception was created.
5
+ */
6
+ public struct ExceptionOrigin: CustomStringConvertible {
7
+ /**
8
+ The path to the file in which the exception was created.
9
+ */
10
+ let file: String
11
+
12
+ /**
13
+ The line number on which the exception was created.
14
+ */
15
+ let line: UInt
16
+
17
+ /**
18
+ The name (selector) of the declaration in which the exception was created.
19
+ */
20
+ let function: String
21
+
22
+ /**
23
+ Stringified representation of the exception origin.
24
+ */
25
+ public var description: String {
26
+ "at \(file):\(line) in \(function)"
27
+ }
28
+ }
@@ -0,0 +1,20 @@
1
+ // Copyright 2022-present 650 Industries. All rights reserved.
2
+
3
+ /**
4
+ The exception that needs some additional parameters to be best described.
5
+ */
6
+ open class GenericException<ParamType>: Exception {
7
+ /**
8
+ The additional parameter passed to the initializer.
9
+ */
10
+ public let param: ParamType
11
+
12
+ /**
13
+ The default initializer that takes a param and captures the place in the code where the exception was created.
14
+ - Warning: Call it only with one argument! If you need to pass more parameters, use a tuple instead.
15
+ */
16
+ public init(_ param: ParamType, file: String = #fileID, line: UInt = #line, function: String = #function) {
17
+ self.param = param
18
+ super.init(file: file, line: line, function: function)
19
+ }
20
+ }
@@ -0,0 +1,16 @@
1
+ // Copyright 2022-present 650 Industries. All rights reserved.
2
+
3
+ /**
4
+ Exception wrapper used to handle unexpected internal native errors.
5
+ */
6
+ public class UnexpectedException: Exception {
7
+ private let errorDescription: String
8
+
9
+ public init(_ error: Error) {
10
+ self.errorDescription = error.localizedDescription
11
+ }
12
+
13
+ public override var reason: String {
14
+ return errorDescription
15
+ }
16
+ }
@@ -24,10 +24,15 @@ public protocol AnyFunction: AnyDefinition {
24
24
  */
25
25
  var queue: DispatchQueue? { get }
26
26
 
27
+ /**
28
+ Whether the function needs to be called asynchronously from JavaScript.
29
+ */
30
+ var isAsync: Bool { get }
31
+
27
32
  /**
28
33
  Calls the function on given module with arguments and a promise.
29
34
  */
30
- func call(args: [Any], promise: Promise) -> Void
35
+ func call(args: [Any], promise: Promise)
31
36
 
32
37
  /**
33
38
  Synchronously calls the function with given arguments. If the function takes a promise,
@@ -39,4 +44,9 @@ public protocol AnyFunction: AnyDefinition {
39
44
  Specifies on which queue the function should run.
40
45
  */
41
46
  func runOnQueue(_ queue: DispatchQueue?) -> Self
47
+
48
+ /**
49
+ Makes the JavaScript function synchronous.
50
+ */
51
+ func runSynchronously() -> Self
42
52
  }
@@ -1,7 +1,7 @@
1
1
  import Dispatch
2
2
 
3
3
  public final class ConcreteFunction<Args, ReturnType>: AnyFunction {
4
- public typealias ClosureType = (Args) -> ReturnType
4
+ public typealias ClosureType = (Args) throws -> ReturnType
5
5
 
6
6
  public let name: String
7
7
 
@@ -15,6 +15,8 @@ public final class ConcreteFunction<Args, ReturnType>: AnyFunction {
15
15
 
16
16
  public var queue: DispatchQueue?
17
17
 
18
+ public var isAsync: Bool = true
19
+
18
20
  let closure: ClosureType
19
21
 
20
22
  let argTypes: [AnyArgumentType]
@@ -41,12 +43,12 @@ public final class ConcreteFunction<Args, ReturnType>: AnyFunction {
41
43
  }
42
44
 
43
45
  let tuple = try Conversions.toTuple(finalArgs) as! Args
44
- returnedValue = closure(tuple)
46
+ returnedValue = try closure(tuple)
45
47
  } catch let error as CodedError {
46
- promise.reject(error)
48
+ promise.reject(FunctionCallException(name).causedBy(error))
47
49
  return
48
- } catch let error {
49
- promise.reject(UnexpectedError(error))
50
+ } catch {
51
+ promise.reject(UnexpectedException(error))
50
52
  return
51
53
  }
52
54
  if !takesPromise {
@@ -62,7 +64,7 @@ public final class ConcreteFunction<Args, ReturnType>: AnyFunction {
62
64
  let promise = Promise {
63
65
  result = $0
64
66
  semaphore.signal()
65
- } rejecter: { error in
67
+ } rejecter: { _ in
66
68
  semaphore.signal()
67
69
  }
68
70
  call(args: args, promise: promise)
@@ -72,7 +74,7 @@ public final class ConcreteFunction<Args, ReturnType>: AnyFunction {
72
74
  do {
73
75
  let finalArgs = try castArguments(args)
74
76
  let tuple = try Conversions.toTuple(finalArgs) as! Args
75
- return closure(tuple)
77
+ return try closure(tuple)
76
78
  } catch let error {
77
79
  return error
78
80
  }
@@ -84,27 +86,46 @@ public final class ConcreteFunction<Args, ReturnType>: AnyFunction {
84
86
  return self
85
87
  }
86
88
 
89
+ public func runSynchronously() -> Self {
90
+ self.isAsync = false
91
+ return self
92
+ }
93
+
87
94
  private func argumentType(atIndex index: Int) -> AnyArgumentType? {
88
95
  return (0..<argTypes.count).contains(index) ? argTypes[index] : nil
89
96
  }
90
97
 
91
98
  private func castArguments(_ args: [Any]) throws -> [Any] {
92
99
  if args.count != argumentsCount {
93
- throw InvalidArgsNumberError(received: args.count, expected: argumentsCount)
100
+ throw InvalidArgsNumberException((received: args.count, expected: argumentsCount))
94
101
  }
95
- return try args.enumerated().map { (index, arg) in
102
+ return try args.enumerated().map { index, arg in
96
103
  let expectedType = argumentType(atIndex: index)
97
104
 
98
- // It's safe to unwrap since the arguments count matches.
99
- return try expectedType!.cast(arg)
105
+ do {
106
+ // It's safe to unwrap since the arguments count matches.
107
+ return try expectedType!.cast(arg)
108
+ } catch {
109
+ throw ArgumentCastException((index: index, type: expectedType!)).causedBy(error)
110
+ }
100
111
  }
101
112
  }
102
113
  }
103
114
 
104
- internal struct InvalidArgsNumberError: CodedError {
105
- let received: Int
106
- let expected: Int
107
- var description: String {
108
- "Received \(received) arguments, but \(expected) was expected."
115
+ internal class InvalidArgsNumberException: GenericException<(received: Int, expected: Int)> {
116
+ override var reason: String {
117
+ "Received \(param.received) arguments, but \(param.expected) was expected"
118
+ }
119
+ }
120
+
121
+ internal class ArgumentCastException: GenericException<(index: Int, type: AnyArgumentType)> {
122
+ override var reason: String {
123
+ "Argument at index '\(param.index)' couldn't be cast to type \(param.type.description)"
124
+ }
125
+ }
126
+
127
+ internal class FunctionCallException: GenericException<String> {
128
+ override var reason: String {
129
+ "Call to function '\(param)' has been rejected"
109
130
  }
110
131
  }
@@ -0,0 +1,43 @@
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
+ private class ModuleUnavailableException: GenericException<String> {
40
+ override var reason: String {
41
+ "Module '\(param)' is no longer available"
42
+ }
43
+ }
@@ -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,7 +66,7 @@ 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
 
@@ -64,7 +76,7 @@ public final class ModuleHolder {
64
76
  } catch let error as CodedError {
65
77
  promise.reject(error)
66
78
  } catch {
67
- promise.reject(UnexpectedError(error))
79
+ promise.reject(UnexpectedException(error))
68
80
  }
69
81
  }
70
82
 
@@ -85,6 +97,36 @@ public final class ModuleHolder {
85
97
  return nil
86
98
  }
87
99
 
100
+ // MARK: JavaScript Module Object
101
+
102
+ /**
103
+ Creates the JavaScript object that will be used to communicate with the native module.
104
+ The object is prefilled with module's constants and functions.
105
+ JavaScript can access it through `global.ExpoModules[moduleName]`.
106
+ - Note: The object will be `nil` when the runtime is unavailable (e.g. remote debugger is enabled).
107
+ */
108
+ private func createJavaScriptModuleObject() -> JavaScriptObject? {
109
+ // It might be impossible to create any object at the moment (e.g. remote debugging, app context destroyed)
110
+ guard let object = appContext?.runtime?.createObject() else {
111
+ return nil
112
+ }
113
+
114
+ // Fill in with constants
115
+ for (key, value) in getConstants() {
116
+ object[key] = value
117
+ }
118
+
119
+ // Fill in with functions
120
+ for (_, fn) in definition.functions {
121
+ if fn.isAsync {
122
+ object.setAsyncFunction(fn.name, argsCount: fn.argumentsCount, block: createAsyncFunctionBlock(holder: self, name: fn.name))
123
+ } else {
124
+ object.setSyncFunction(fn.name, argsCount: fn.argumentsCount, block: createSyncFunctionBlock(holder: self, name: fn.name))
125
+ }
126
+ }
127
+ return object
128
+ }
129
+
88
130
  // MARK: Listening to native events
89
131
 
90
132
  func listeners(forEvent event: EventName) -> [EventListener] {
@@ -112,9 +154,9 @@ public final class ModuleHolder {
112
154
  */
113
155
  func modifyListenersCount(_ count: Int) {
114
156
  if count > 0 && listenersCount == 0 {
115
- let _ = definition.functions["startObserving"]?.callSync(args: [])
157
+ _ = definition.functions["startObserving"]?.callSync(args: [])
116
158
  } else if count < 0 && listenersCount + count <= 0 {
117
- let _ = definition.functions["stopObserving"]?.callSync(args: [])
159
+ _ = definition.functions["stopObserving"]?.callSync(args: [])
118
160
  }
119
161
  listenersCount = max(0, listenersCount + count)
120
162
  }
@@ -125,20 +167,17 @@ public final class ModuleHolder {
125
167
  post(event: .moduleDestroy)
126
168
  }
127
169
 
128
- // MARK: Errors
170
+ // MARK: - Exceptions
129
171
 
130
- struct ModuleNotFoundError: CodedError {
131
- let moduleName: String
132
- var description: String {
133
- "Cannot find module `\(moduleName)`"
172
+ internal class ModuleNotFoundException: GenericException<String> {
173
+ override var reason: String {
174
+ "Module '\(param)' not found"
134
175
  }
135
176
  }
136
177
 
137
- struct FunctionNotFoundError: CodedError {
138
- let functionName: String
139
- let moduleName: String
140
- var description: String {
141
- "Cannot find function `\(functionName)` in module `\(moduleName)`"
178
+ internal class FunctionNotFoundException: GenericException<(functionName: String, moduleName: String)> {
179
+ override var reason: String {
180
+ "Function '\(param.functionName)' not found in module '\(param.moduleName)'"
142
181
  }
143
182
  }
144
183
  }
@@ -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,
@@ -16,150 +16,6 @@ extension AnyModule {
16
16
  return ModuleNameDefinition(name: name)
17
17
  }
18
18
 
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
19
  // MARK: - Module's lifecycle
164
20
 
165
21
  /**
@@ -212,50 +68,6 @@ extension AnyModule {
212
68
  public func viewManager(@ViewManagerDefinitionBuilder _ closure: @escaping () -> ViewManagerDefinition) -> AnyDefinition {
213
69
  return closure()
214
70
  }
215
-
216
- // MARK: - Events
217
-
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
- }
224
-
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
- }
231
-
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
- }
238
- }
239
-
240
- /**
241
- Defines the factory creating a native view when the module is used as a view.
242
- */
243
- public func view(_ closure: @escaping () -> UIView) -> AnyDefinition {
244
- return ViewFactory(closure)
245
- }
246
-
247
- /**
248
- Creates a view prop that defines its name and setter.
249
- */
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
- )
259
71
  }
260
72
 
261
73
  // TODO: - Remove deprecated `method` component once SDK44 is out.
@@ -1,4 +1,3 @@
1
-
2
1
  import Foundation
3
2
 
4
3
  /**
@@ -0,0 +1,30 @@
1
+ // Copyright 2021-present 650 Industries. All rights reserved.
2
+
3
+ /**
4
+ Base class for other definitions representing an object, such as `ModuleDefinition`.
5
+ */
6
+ public class ObjectDefinition: AnyDefinition {
7
+ /**
8
+ A dictionary of functions defined by the object.
9
+ */
10
+ let functions: [String: AnyFunction]
11
+
12
+ /**
13
+ An array of constants definitions.
14
+ */
15
+ let constants: [ConstantsDefinition]
16
+
17
+ /**
18
+ Default initializer receiving children definitions from the result builder.
19
+ */
20
+ init(definitions: [AnyDefinition]) {
21
+ self.functions = definitions
22
+ .compactMap { $0 as? AnyFunction }
23
+ .reduce(into: [String: AnyFunction]()) { dict, function in
24
+ dict[function.name] = function
25
+ }
26
+
27
+ self.constants = definitions
28
+ .compactMap { $0 as? ConstantsDefinition }
29
+ }
30
+ }