expo-modules-core 0.6.4 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +53 -0
- package/README.md +1 -1
- package/android/ExpoModulesCorePlugin.gradle +15 -0
- package/android/build.gradle +46 -32
- package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +5 -5
- package/android/src/main/java/expo/modules/adapters/react/services/UIManagerModuleWrapper.java +13 -0
- package/android/src/main/java/expo/modules/core/ViewManager.java +9 -0
- package/android/src/main/java/expo/modules/core/interfaces/JavaScriptContextProvider.java +4 -0
- package/android/src/main/java/expo/modules/core/interfaces/ReactActivityHandler.java +37 -1
- package/android/src/main/java/expo/modules/core/interfaces/ReactNativeHostHandler.java +19 -0
- package/android/src/main/java/expo/modules/core/interfaces/services/UIManager.java +2 -0
- package/android/src/main/java/expo/modules/kotlin/AppContext.kt +23 -5
- package/android/src/main/java/expo/modules/kotlin/DynamicExtenstions.kt +5 -3
- package/android/src/main/java/expo/modules/kotlin/KPromiseWrapper.kt +3 -8
- package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +24 -9
- package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +12 -7
- package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +23 -1
- package/android/src/main/java/expo/modules/kotlin/Promise.kt +1 -1
- package/android/src/main/java/expo/modules/kotlin/callbacks/Callback.kt +5 -0
- package/android/src/main/java/expo/modules/kotlin/callbacks/ViewCallback.kt +39 -0
- package/android/src/main/java/expo/modules/kotlin/callbacks/ViewCallbackDelegate.kt +27 -0
- package/android/src/main/java/expo/modules/kotlin/defaultmodules/ErrorManagerModule.kt +25 -0
- package/android/src/main/java/expo/modules/kotlin/events/EventEmitter.kt +13 -0
- package/android/src/main/java/expo/modules/kotlin/events/KModuleEventEmitterWrapper.kt +102 -0
- package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +93 -9
- package/android/src/main/java/expo/modules/kotlin/exception/ExceptionDecorator.kt +11 -0
- package/android/src/main/java/expo/modules/kotlin/{methods/AnyMethod.kt → functions/AnyFunction.kt} +18 -18
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +15 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +61 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromise.kt +15 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncSuspendFunction.kt +36 -0
- package/android/src/main/java/expo/modules/kotlin/modules/DefinitionMarker.kt +4 -0
- package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +17 -2
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +219 -30
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +2 -2
- package/android/src/main/java/expo/modules/kotlin/records/FieldValidator.kt +139 -0
- package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +71 -15
- package/android/src/main/java/expo/modules/kotlin/records/Required.kt +5 -0
- package/android/src/main/java/expo/modules/kotlin/records/ValidationBinder.kt +110 -0
- package/android/src/main/java/expo/modules/kotlin/records/Validators.kt +61 -0
- package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +11 -5
- package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverter.kt +35 -0
- package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverterHelper.kt +148 -0
- package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +10 -4
- package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +12 -6
- package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +29 -13
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +2 -1
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +9 -1
- package/android/src/main/java/expo/modules/kotlin/views/CallbacksDefinition.kt +3 -0
- package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +71 -0
- package/android/src/main/java/expo/modules/kotlin/views/SimpleViewManagerWrapper.kt +22 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinition.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinitionBuilder.kt +64 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +30 -2
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +42 -1
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +62 -2
- package/build/EventEmitter.d.ts +1 -0
- package/build/EventEmitter.d.ts.map +1 -0
- package/build/NativeModulesProxy.d.ts +1 -0
- package/build/NativeModulesProxy.d.ts.map +1 -0
- package/build/NativeModulesProxy.native.d.ts +1 -4
- package/build/NativeModulesProxy.native.d.ts.map +1 -0
- package/build/NativeModulesProxy.native.js +1 -14
- package/build/NativeModulesProxy.native.js.map +1 -1
- package/build/NativeModulesProxy.types.d.ts +1 -3
- package/build/NativeModulesProxy.types.d.ts.map +1 -0
- package/build/NativeModulesProxy.types.js.map +1 -1
- package/build/NativeViewManagerAdapter.d.ts +1 -0
- package/build/NativeViewManagerAdapter.d.ts.map +1 -0
- package/build/NativeViewManagerAdapter.native.d.ts +1 -0
- package/build/NativeViewManagerAdapter.native.d.ts.map +1 -0
- package/build/NativeViewManagerAdapter.native.js +9 -33
- package/build/NativeViewManagerAdapter.native.js.map +1 -1
- package/build/PermissionsHook.d.ts +1 -0
- package/build/PermissionsHook.d.ts.map +1 -0
- package/build/PermissionsInterface.d.ts +1 -0
- package/build/PermissionsInterface.d.ts.map +1 -0
- package/build/Platform.d.ts +1 -0
- package/build/Platform.d.ts.map +1 -0
- package/build/SyntheticPlatformEmitter.d.ts +1 -0
- package/build/SyntheticPlatformEmitter.d.ts.map +1 -0
- package/build/SyntheticPlatformEmitter.web.d.ts +1 -0
- package/build/SyntheticPlatformEmitter.web.d.ts.map +1 -0
- package/build/deprecate.d.ts +1 -0
- package/build/deprecate.d.ts.map +1 -0
- package/build/environment/browser.d.ts +1 -0
- package/build/environment/browser.d.ts.map +1 -0
- package/build/environment/browser.web.d.ts +1 -0
- package/build/environment/browser.web.d.ts.map +1 -0
- package/build/errors/CodedError.d.ts +1 -0
- package/build/errors/CodedError.d.ts.map +1 -0
- package/build/errors/UnavailabilityError.d.ts +1 -0
- package/build/errors/UnavailabilityError.d.ts.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +2 -0
- package/build/index.js.map +1 -1
- package/build/requireNativeModule.d.ts +16 -0
- package/build/requireNativeModule.d.ts.map +1 -0
- package/build/requireNativeModule.js +18 -0
- package/build/requireNativeModule.js.map +1 -0
- package/build/sweet/NativeErrorManager.d.ts +3 -0
- package/build/sweet/NativeErrorManager.d.ts.map +1 -0
- package/build/sweet/NativeErrorManager.js +3 -0
- package/build/sweet/NativeErrorManager.js.map +1 -0
- package/build/sweet/setUpErrorManager.fx.d.ts +2 -0
- package/build/sweet/setUpErrorManager.fx.d.ts.map +1 -0
- package/build/sweet/setUpErrorManager.fx.js +11 -0
- package/build/sweet/setUpErrorManager.fx.js.map +1 -0
- package/ios/AppDelegates/EXAppDelegatesLoader.m +4 -8
- package/ios/AppDelegates/ExpoAppDelegate.swift +22 -20
- package/ios/EXAppDefines.h +1 -0
- package/ios/EXAppDefines.m +6 -0
- package/ios/EXUtilities.h +2 -0
- package/ios/EXUtilities.m +12 -0
- package/ios/ExpoModulesCore.h +4 -0
- package/ios/ExpoModulesCore.podspec +4 -2
- package/ios/Interfaces/FileSystem/EXFileSystemInterface.h +1 -1
- package/ios/Interfaces/TaskManager/EXTaskServiceInterface.h +1 -0
- package/ios/JSI/{JSIConversions.h → EXJSIConversions.h} +5 -0
- package/ios/JSI/{JSIConversions.mm → EXJSIConversions.mm} +21 -1
- package/ios/JSI/{JSIInstaller.h → EXJSIInstaller.h} +10 -0
- package/ios/JSI/EXJSIInstaller.mm +17 -0
- package/ios/JSI/EXJSIUtils.h +19 -0
- package/ios/JSI/EXJSIUtils.mm +89 -0
- package/ios/JSI/EXJavaScriptObject.h +97 -0
- package/ios/JSI/EXJavaScriptObject.mm +121 -0
- package/ios/JSI/EXJavaScriptRuntime.h +73 -0
- package/ios/JSI/EXJavaScriptRuntime.mm +153 -0
- package/ios/JSI/EXJavaScriptValue.h +57 -0
- package/ios/JSI/EXJavaScriptValue.mm +166 -0
- package/ios/JSI/ExpoModulesHostObject.h +33 -0
- package/ios/JSI/ExpoModulesHostObject.mm +41 -0
- package/ios/JSI/JavaScriptRuntime.swift +32 -0
- package/ios/JSI/JavaScriptValue.swift +94 -0
- package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +3 -23
- package/ios/NativeModulesProxy/EXNativeModulesProxy.h +2 -2
- package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +101 -75
- package/ios/RCTComponentData+Privates.h +12 -0
- package/ios/ReactDelegates/EXReactCompatibleHelpers.h +18 -0
- package/ios/ReactDelegates/EXReactCompatibleHelpers.m +19 -0
- package/ios/ReactDelegates/ExpoReactDelegate.swift +3 -3
- package/ios/ReactDelegates/ExpoReactDelegateHandler.swift +4 -4
- package/ios/ReactDelegates/ModulePriorities.swift +1 -1
- package/ios/Swift/AppContext.swift +64 -4
- package/ios/Swift/Arguments/ArgumentType.swift +4 -0
- package/ios/Swift/Arguments/Convertibles.swift +13 -13
- package/ios/Swift/Arguments/Types/EnumArgumentType.swift +11 -17
- package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +1 -1
- package/ios/Swift/Arguments/Types/RawArgumentType.swift +2 -2
- package/ios/Swift/Conversions.swift +51 -56
- package/ios/Swift/EventListener.swift +8 -10
- package/ios/Swift/Events/Callback.swift +66 -0
- package/ios/Swift/Events/Event.swift +43 -0
- package/ios/Swift/Exceptions/ChainableException.swift +51 -0
- package/ios/Swift/{CodedError.swift → Exceptions/CodedError.swift} +1 -12
- package/ios/Swift/Exceptions/Exception.swift +62 -0
- package/ios/Swift/Exceptions/ExceptionOrigin.swift +28 -0
- package/ios/Swift/Exceptions/GenericException.swift +20 -0
- package/ios/Swift/Exceptions/UnexpectedException.swift +16 -0
- package/ios/Swift/Functions/AnyFunction.swift +11 -1
- package/ios/Swift/Functions/AsyncFunction.swift +17 -0
- package/ios/Swift/Functions/ConcreteFunction.swift +43 -17
- package/ios/Swift/JavaScriptUtils.swift +54 -0
- package/ios/Swift/ModuleHolder.swift +66 -16
- package/ios/Swift/ModuleRegistry.swift +4 -1
- package/ios/Swift/Modules/AnyModule.swift +0 -1
- package/ios/Swift/Modules/ModuleDefinition.swift +4 -13
- package/ios/Swift/Modules/ModuleDefinitionBuilder.swift +0 -1
- package/ios/Swift/Modules/ModuleDefinitionComponents.swift +0 -188
- package/ios/Swift/ModulesProvider.swift +3 -11
- package/ios/Swift/Objects/ObjectDefinition.swift +30 -0
- package/ios/Swift/Objects/ObjectDefinitionComponents.swift +384 -0
- package/ios/Swift/Promise.swift +8 -3
- package/ios/Swift/Records/AnyField.swift +7 -0
- package/ios/Swift/Records/Field.swift +24 -19
- package/ios/Swift/Records/FieldOption.swift +1 -1
- package/ios/Swift/Records/Record.swift +12 -4
- package/ios/Swift/SwiftInteropBridge.swift +53 -15
- package/ios/Swift/Views/AnyViewProp.swift +1 -1
- package/ios/Swift/Views/ComponentData.swift +96 -0
- package/ios/Swift/Views/ConcreteViewProp.swift +6 -8
- package/ios/Swift/Views/ExpoView.swift +8 -0
- package/ios/Swift/Views/ViewFactory.swift +1 -1
- package/ios/Swift/Views/ViewManagerDefinition.swift +23 -2
- package/ios/Swift/Views/ViewManagerDefinitionBuilder.swift +0 -1
- package/ios/Swift/Views/ViewManagerDefinitionComponents.swift +26 -0
- package/ios/Swift/Views/ViewModuleWrapper.swift +5 -2
- package/ios/Swift.h +5 -0
- package/ios/Tests/ArgumentTypeSpec.swift +5 -7
- package/ios/Tests/ConstantsSpec.swift +6 -7
- package/ios/Tests/ConvertiblesSpec.swift +35 -36
- package/ios/Tests/ExceptionsSpec.swift +111 -0
- package/ios/Tests/ExpoModulesSpec.swift +76 -0
- package/ios/Tests/FunctionSpec.swift +22 -25
- package/ios/Tests/FunctionWithConvertiblesSpec.swift +4 -5
- package/ios/Tests/JavaScriptObjectSpec.swift +97 -0
- package/ios/Tests/JavaScriptRuntimeSpec.swift +94 -0
- package/ios/Tests/Mocks/ModuleMocks.swift +1 -1
- package/ios/Tests/Mocks/ModulesProviderMock.swift +0 -1
- package/ios/Tests/ModuleEventListenersSpec.swift +3 -4
- package/ios/Tests/ModuleRegistrySpec.swift +2 -3
- package/ios/Tests/RecordSpec.swift +9 -20
- package/package.json +3 -3
- package/src/NativeModulesProxy.native.ts +2 -22
- package/src/NativeModulesProxy.types.ts +0 -8
- package/src/NativeViewManagerAdapter.native.tsx +12 -28
- package/src/index.ts +4 -0
- package/src/requireNativeModule.ts +29 -0
- package/src/sweet/NativeErrorManager.ts +2 -0
- package/src/sweet/setUpErrorManager.fx.ts +12 -0
- package/android/src/main/java/expo/modules/kotlin/events/KEventEmitterWrapper.kt +0 -26
- package/android/src/main/java/expo/modules/kotlin/methods/Method.kt +0 -14
- package/android/src/main/java/expo/modules/kotlin/methods/PromiseMethod.kt +0 -15
- package/ios/JSI/ExpoModulesProxySpec.h +0 -24
- package/ios/JSI/ExpoModulesProxySpec.mm +0 -135
- package/ios/JSI/JSIInstaller.mm +0 -22
|
@@ -8,7 +8,7 @@ internal struct PromiseArgumentType: AnyArgumentType {
|
|
|
8
8
|
if let value = value as? Promise {
|
|
9
9
|
return value
|
|
10
10
|
}
|
|
11
|
-
throw Conversions.
|
|
11
|
+
throw Conversions.CastingException<Promise>(value)
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
var description: String = "Promise"
|
|
@@ -14,9 +14,9 @@ internal struct RawArgumentType<InnerType>: AnyArgumentType {
|
|
|
14
14
|
// Raw arguments are always non-optional, but they may receive `nil` values.
|
|
15
15
|
// Let's throw more specific error in this case.
|
|
16
16
|
if Optional.isNil(value) {
|
|
17
|
-
throw Conversions.
|
|
17
|
+
throw Conversions.NullCastException<InnerType>()
|
|
18
18
|
}
|
|
19
|
-
throw Conversions.
|
|
19
|
+
throw Conversions.CastingException<InnerType>(value)
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
var description: String {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
|
|
2
1
|
internal final class Conversions {
|
|
3
2
|
/**
|
|
4
3
|
Converts an array to tuple. Because of tuples nature, it's not possible to convert an array of any size, so we can support only up to some fixed size.
|
|
5
4
|
*/
|
|
6
5
|
static func toTuple(_ array: [Any?]) throws -> Any? {
|
|
7
|
-
switch
|
|
6
|
+
switch array.count {
|
|
8
7
|
case 0:
|
|
9
8
|
return ()
|
|
10
9
|
case 1:
|
|
@@ -28,7 +27,7 @@ internal final class Conversions {
|
|
|
28
27
|
case 10:
|
|
29
28
|
return (array[0], array[1], array[2], array[3], array[4], array[5], array[6], array[7], array[8], array[9])
|
|
30
29
|
default:
|
|
31
|
-
throw
|
|
30
|
+
throw TooManyArgumentsException((count: array.count, limit: 10))
|
|
32
31
|
}
|
|
33
32
|
}
|
|
34
33
|
|
|
@@ -47,9 +46,9 @@ internal final class Conversions {
|
|
|
47
46
|
}
|
|
48
47
|
|
|
49
48
|
/**
|
|
50
|
-
Picks values under given keys from the dictionary,
|
|
51
|
-
- The dictionary is missing some of the given keys (`
|
|
52
|
-
- Some of the values cannot be
|
|
49
|
+
Picks values under given keys from the dictionary, cast to a specific type. Can throw exceptions when
|
|
50
|
+
- The dictionary is missing some of the given keys (`MissingKeysException`)
|
|
51
|
+
- Some of the values cannot be cast to specified type (`CastingValuesException`)
|
|
53
52
|
*/
|
|
54
53
|
static func pickValues<ValueType>(from dict: [String: Any], byKeys keys: [String], as type: ValueType.Type) throws -> [ValueType] {
|
|
55
54
|
var result = (
|
|
@@ -68,17 +67,17 @@ internal final class Conversions {
|
|
|
68
67
|
result.invalidKeys.append(key)
|
|
69
68
|
}
|
|
70
69
|
}
|
|
71
|
-
if result.missingKeys.
|
|
72
|
-
throw
|
|
70
|
+
if !result.missingKeys.isEmpty {
|
|
71
|
+
throw MissingKeysException<ValueType>(result.missingKeys)
|
|
73
72
|
}
|
|
74
|
-
if result.invalidKeys.
|
|
75
|
-
throw
|
|
73
|
+
if !result.invalidKeys.isEmpty {
|
|
74
|
+
throw CastingValuesException<ValueType>(result.invalidKeys)
|
|
76
75
|
}
|
|
77
76
|
return result.values
|
|
78
77
|
}
|
|
79
78
|
|
|
80
79
|
/**
|
|
81
|
-
Converts hex string to `UIColor` or throws an
|
|
80
|
+
Converts hex string to `UIColor` or throws an exception if the string is corrupted.
|
|
82
81
|
*/
|
|
83
82
|
static func toColor(hexString hex: String) throws -> UIColor {
|
|
84
83
|
var hexStr = hex
|
|
@@ -104,7 +103,7 @@ internal final class Conversions {
|
|
|
104
103
|
|
|
105
104
|
guard hexStr.range(of: #"^[0-9a-fA-F]{8}$"#, options: .regularExpression) != nil,
|
|
106
105
|
Scanner(string: hexStr).scanHexInt64(&rgba) else {
|
|
107
|
-
throw
|
|
106
|
+
throw InvalidHexColorException(hex)
|
|
108
107
|
}
|
|
109
108
|
return try toColor(rgba: rgba)
|
|
110
109
|
}
|
|
@@ -115,7 +114,7 @@ internal final class Conversions {
|
|
|
115
114
|
*/
|
|
116
115
|
static func toColor(argb: UInt64) throws -> UIColor {
|
|
117
116
|
guard argb <= UInt32.max else {
|
|
118
|
-
throw
|
|
117
|
+
throw HexColorOverflowException(argb)
|
|
119
118
|
}
|
|
120
119
|
let alpha = CGFloat((argb >> 24) & 0xff) / 255.0
|
|
121
120
|
let red = CGFloat((argb >> 16) & 0xff) / 255.0
|
|
@@ -129,7 +128,7 @@ internal final class Conversions {
|
|
|
129
128
|
*/
|
|
130
129
|
static func toColor(rgba: UInt64) throws -> UIColor {
|
|
131
130
|
guard rgba <= UInt32.max else {
|
|
132
|
-
throw
|
|
131
|
+
throw HexColorOverflowException(rgba)
|
|
133
132
|
}
|
|
134
133
|
let red = CGFloat((rgba >> 24) & 0xff) / 255.0
|
|
135
134
|
let green = CGFloat((rgba >> 16) & 0xff) / 255.0
|
|
@@ -145,90 +144,86 @@ internal final class Conversions {
|
|
|
145
144
|
return keys.map { "`\($0)`" }.joined(separator: ", ")
|
|
146
145
|
}
|
|
147
146
|
|
|
148
|
-
|
|
147
|
+
static func formatPlural(_ number: Int, _ singular: String, _ plural: String? = nil) -> String {
|
|
148
|
+
return String(number) + (number == 1 ? singular : (plural ?? singular + "s"))
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// MARK: - Exceptions
|
|
149
152
|
|
|
150
153
|
/**
|
|
151
|
-
An
|
|
154
|
+
An exception meaning that the number of arguments exceeds the limit.
|
|
152
155
|
*/
|
|
153
|
-
internal
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
var description: String {
|
|
157
|
-
"A number of arguments `\(count)` exceeds the limit of `\(limit)`"
|
|
156
|
+
internal class TooManyArgumentsException: GenericException<(count: Int, limit: Int)> {
|
|
157
|
+
override var reason: String {
|
|
158
|
+
"Native function expects \(formatPlural(param.limit, "argument")), but received \(param.count)"
|
|
158
159
|
}
|
|
159
160
|
}
|
|
160
161
|
|
|
161
162
|
/**
|
|
162
|
-
An
|
|
163
|
+
An exception that can be thrown by convertible types, when given value cannot be converted.
|
|
163
164
|
*/
|
|
164
|
-
internal
|
|
165
|
-
let value: Any?
|
|
165
|
+
internal class ConvertingException<TargetType>: GenericException<Any?> {
|
|
166
166
|
var code: String = "ERR_CONVERTING_FAILED"
|
|
167
|
-
var
|
|
168
|
-
"Cannot convert
|
|
167
|
+
override var reason: String {
|
|
168
|
+
"Cannot convert '\(String(describing: param))' to \(TargetType.self)"
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
/**
|
|
173
|
-
An
|
|
173
|
+
An exception that is thrown when given value cannot be cast.
|
|
174
174
|
*/
|
|
175
|
-
internal
|
|
176
|
-
let value: Any
|
|
175
|
+
internal class CastingException<TargetType>: GenericException<Any> {
|
|
177
176
|
var code: String = "ERR_CASTING_FAILED"
|
|
178
|
-
var
|
|
179
|
-
"Cannot cast
|
|
177
|
+
override var reason: String {
|
|
178
|
+
"Cannot cast '\(String(describing: param))' to \(TargetType.self)"
|
|
180
179
|
}
|
|
181
180
|
}
|
|
182
181
|
|
|
183
182
|
/**
|
|
184
|
-
An
|
|
185
|
-
when the values in given dictionary cannot be
|
|
183
|
+
An exception that can be thrown by convertible types,
|
|
184
|
+
when the values in given dictionary cannot be cast to specific type.
|
|
186
185
|
*/
|
|
187
|
-
internal
|
|
188
|
-
let keys: [String]
|
|
186
|
+
internal class CastingValuesException<ValueType>: GenericException<[String]> {
|
|
189
187
|
var code: String = "ERR_CASTING_VALUES_FAILED"
|
|
190
|
-
var
|
|
191
|
-
"Cannot cast keys \(formatKeys(
|
|
188
|
+
override var reason: String {
|
|
189
|
+
"Cannot cast keys \(formatKeys(param)) to \(ValueType.self)"
|
|
192
190
|
}
|
|
193
191
|
}
|
|
194
192
|
|
|
195
193
|
/**
|
|
196
|
-
An
|
|
194
|
+
An exception that can be thrown by convertible types,
|
|
197
195
|
when given dictionary is missing some required keys.
|
|
198
196
|
*/
|
|
199
|
-
internal
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
"Missing keys \(formatKeys(keys)) of type `\(ValueType.self)`"
|
|
197
|
+
internal class MissingKeysException<ValueType>: GenericException<[String]> {
|
|
198
|
+
override var reason: String {
|
|
199
|
+
"Missing keys \(formatKeys(param)) to create \(ValueType.self) record"
|
|
203
200
|
}
|
|
204
201
|
}
|
|
205
202
|
|
|
206
203
|
/**
|
|
207
|
-
An
|
|
204
|
+
An exception that is thrown when null value is tried to be cast to non-optional type.
|
|
208
205
|
*/
|
|
209
|
-
internal
|
|
210
|
-
var
|
|
211
|
-
"Cannot cast null
|
|
206
|
+
internal class NullCastException<TargetType>: Exception {
|
|
207
|
+
override var reason: String {
|
|
208
|
+
"Cannot cast null to non-optional '\(TargetType.self)'"
|
|
212
209
|
}
|
|
213
210
|
}
|
|
214
211
|
|
|
215
212
|
/**
|
|
216
|
-
An
|
|
213
|
+
An exception used when the hex color string is invalid (e.g. contains non-hex characters).
|
|
217
214
|
*/
|
|
218
|
-
internal
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
"Provided hex color `\(hex)` is invalid"
|
|
215
|
+
internal class InvalidHexColorException: GenericException<String> {
|
|
216
|
+
override var reason: String {
|
|
217
|
+
"Provided hex color '\(param)' is invalid"
|
|
222
218
|
}
|
|
223
219
|
}
|
|
224
220
|
|
|
225
221
|
/**
|
|
226
|
-
An
|
|
222
|
+
An exception used when the integer value of the color would result in an overflow of `UInt32`.
|
|
227
223
|
*/
|
|
228
|
-
internal
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
"Provided hex color `\(hex)` would result in an overflow"
|
|
224
|
+
internal class HexColorOverflowException: GenericException<UInt64> {
|
|
225
|
+
override var reason: String {
|
|
226
|
+
"Provided hex color '\(param)' would result in an overflow"
|
|
232
227
|
}
|
|
233
228
|
}
|
|
234
229
|
}
|
|
@@ -10,7 +10,7 @@ internal struct EventListener: AnyDefinition {
|
|
|
10
10
|
*/
|
|
11
11
|
init(_ name: EventName, _ listener: @escaping () -> Void) {
|
|
12
12
|
self.name = name
|
|
13
|
-
self.call = {
|
|
13
|
+
self.call = { _, _ in listener() }
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -18,9 +18,9 @@ internal struct EventListener: AnyDefinition {
|
|
|
18
18
|
*/
|
|
19
19
|
init<Sender>(_ name: EventName, _ listener: @escaping (Sender) -> Void) {
|
|
20
20
|
self.name = name
|
|
21
|
-
self.call = {
|
|
21
|
+
self.call = { sender, _ in
|
|
22
22
|
guard let sender = sender as? Sender else {
|
|
23
|
-
throw
|
|
23
|
+
throw InvalidSenderTypeException((eventName: name, senderType: Sender.self))
|
|
24
24
|
}
|
|
25
25
|
listener(sender)
|
|
26
26
|
}
|
|
@@ -31,20 +31,18 @@ internal struct EventListener: AnyDefinition {
|
|
|
31
31
|
*/
|
|
32
32
|
init<Sender, PayloadType>(_ name: EventName, _ listener: @escaping (Sender, PayloadType?) -> Void) {
|
|
33
33
|
self.name = name
|
|
34
|
-
self.call = {
|
|
34
|
+
self.call = { sender, payload in
|
|
35
35
|
guard let sender = sender as? Sender else {
|
|
36
|
-
throw
|
|
36
|
+
throw InvalidSenderTypeException((eventName: name, senderType: Sender.self))
|
|
37
37
|
}
|
|
38
38
|
listener(sender, payload as? PayloadType)
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
var
|
|
45
|
-
|
|
46
|
-
var description: String {
|
|
47
|
-
"Sender for event `\(eventName)` must be of type `\(senderType)`."
|
|
43
|
+
class InvalidSenderTypeException: GenericException<(eventName: EventName, senderType: Any.Type)> {
|
|
44
|
+
override var reason: String {
|
|
45
|
+
"Sender for event '\(param.eventName)' must be of type \(param.senderType)"
|
|
48
46
|
}
|
|
49
47
|
}
|
|
50
48
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
An alias for type-erased callback handler.
|
|
5
|
+
*/
|
|
6
|
+
typealias AnyCallbackHandlerType = (Any) -> Void
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
Public type-erased protocol that `Callback` object conforms to.
|
|
10
|
+
*/
|
|
11
|
+
public protocol AnyCallback {
|
|
12
|
+
/**
|
|
13
|
+
Initializes an empty callback (no-op).
|
|
14
|
+
*/
|
|
15
|
+
init()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
Internal type-erased protocol for `Callback` object.
|
|
20
|
+
*/
|
|
21
|
+
internal protocol AnyCallbackInternal: AnyCallback {
|
|
22
|
+
/**
|
|
23
|
+
Sets the callback handler. By default the callback
|
|
24
|
+
is not settled which means it has no handler, thus is no-op.
|
|
25
|
+
*/
|
|
26
|
+
func settle(_ handler: @escaping AnyCallbackHandlerType)
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
Invalidates the callback, making its handler no-op.
|
|
30
|
+
*/
|
|
31
|
+
func invalidate()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
Callable object that represents a JavaScript function.
|
|
36
|
+
*/
|
|
37
|
+
public class Callback<ArgType>: AnyCallback, AnyCallbackInternal {
|
|
38
|
+
/**
|
|
39
|
+
The underlying closure to invoke when the callback is called.
|
|
40
|
+
*/
|
|
41
|
+
private var handler: AnyCallbackHandlerType?
|
|
42
|
+
|
|
43
|
+
// MARK: AnyCallback
|
|
44
|
+
|
|
45
|
+
public required init() {}
|
|
46
|
+
|
|
47
|
+
// MARK: AnyCallbackInternal
|
|
48
|
+
|
|
49
|
+
internal func settle(_ handler: @escaping AnyCallbackHandlerType) {
|
|
50
|
+
self.handler = handler
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
internal func invalidate() {
|
|
54
|
+
self.handler = nil
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// MARK: Calling as function
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
Allows the callback instance to be called as a function.
|
|
61
|
+
*/
|
|
62
|
+
public func callAsFunction(_ arg: ArgType) {
|
|
63
|
+
// TODO: Convert records to dictionaries (@tsapeta)
|
|
64
|
+
handler?(arg as Any)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
Internal type-erased protocol for the instances of the `Event` property wrapper.
|
|
5
|
+
*/
|
|
6
|
+
internal protocol AnyEventInternal {
|
|
7
|
+
/**
|
|
8
|
+
Sets the handler on the wrapped callback.
|
|
9
|
+
*/
|
|
10
|
+
func settle(_ handler: @escaping AnyCallbackHandlerType)
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
Invalidates the callback.
|
|
14
|
+
*/
|
|
15
|
+
func invalidate()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
The class used as a property wrapper on view's or object's callbacks.
|
|
20
|
+
*/
|
|
21
|
+
@propertyWrapper
|
|
22
|
+
public final class Event<CallbackType: AnyCallback>: AnyEventInternal {
|
|
23
|
+
public var wrappedValue: CallbackType
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
The property wrapper initializer. The wrapped value falls back to the empty callback.
|
|
27
|
+
*/
|
|
28
|
+
public init(wrappedValue: CallbackType = CallbackType()) {
|
|
29
|
+
self.wrappedValue = wrappedValue
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
internal func settle(_ handler: @escaping AnyCallbackHandlerType) {
|
|
33
|
+
if let callback = wrappedValue as? AnyCallbackInternal {
|
|
34
|
+
callback.settle(handler)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
internal func invalidate() {
|
|
39
|
+
if let callback = wrappedValue as? AnyCallbackInternal {
|
|
40
|
+
callback.invalidate()
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
An exception that may have been caused by another error.
|
|
5
|
+
*/
|
|
6
|
+
public protocol ChainableException: Error, AnyObject {
|
|
7
|
+
/**
|
|
8
|
+
The direct cause of the exception.
|
|
9
|
+
*/
|
|
10
|
+
var cause: Error? { get set }
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
The first error that started the chain of exceptions.
|
|
14
|
+
*/
|
|
15
|
+
var rootCause: Error? { get }
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
Sets the direct cause of the exception and returns itself.
|
|
19
|
+
*/
|
|
20
|
+
func causedBy(_ error: Error) -> Self
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
Tells whether any of the cause in chain is of given type.
|
|
24
|
+
*/
|
|
25
|
+
func isCausedBy<ErrorType: Error>(_ errorType: ErrorType.Type) -> Bool
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public extension ChainableException {
|
|
29
|
+
var rootCause: Error? {
|
|
30
|
+
if let cause = cause as? ChainableException {
|
|
31
|
+
return cause.rootCause ?? cause
|
|
32
|
+
}
|
|
33
|
+
return cause
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@discardableResult
|
|
37
|
+
func causedBy(_ error: Error) -> Self {
|
|
38
|
+
cause = error
|
|
39
|
+
return self
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
func isCausedBy<ErrorType: Error>(_ errorType: ErrorType.Type) -> Bool {
|
|
43
|
+
if cause is ErrorType {
|
|
44
|
+
return true
|
|
45
|
+
}
|
|
46
|
+
if let cause = cause as? ChainableException {
|
|
47
|
+
return cause.isCausedBy(errorType)
|
|
48
|
+
}
|
|
49
|
+
return false
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -18,7 +18,7 @@ public extension CodedError {
|
|
|
18
18
|
*/
|
|
19
19
|
var code: String {
|
|
20
20
|
let className = String(describing: type(of: self))
|
|
21
|
-
.replacingOccurrences(of: #"(Error)?(<.*>)?$"#, with: "", options: .regularExpression)
|
|
21
|
+
.replacingOccurrences(of: #"(Error|Exception)?(<.*>)?$"#, with: "", options: .regularExpression)
|
|
22
22
|
let regex = try! NSRegularExpression(pattern: "(.)([A-Z])", options: [])
|
|
23
23
|
let range = NSRange(location: 0, length: className.count)
|
|
24
24
|
|
|
@@ -48,14 +48,3 @@ public struct SimpleCodedError: CodedError {
|
|
|
48
48
|
self.description = description
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
Coded wrapper for uncoded errors. Intended to be used to handle unexpected native errors.
|
|
54
|
-
*/
|
|
55
|
-
public struct UnexpectedError: CodedError {
|
|
56
|
-
public let description: String
|
|
57
|
-
|
|
58
|
-
init(_ error: Error) {
|
|
59
|
-
self.description = error.localizedDescription
|
|
60
|
-
}
|
|
61
|
-
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
open class Exception: CodedError, ChainableException, CustomStringConvertible, CustomDebugStringConvertible {
|
|
4
|
+
open var name: String {
|
|
5
|
+
return String(describing: Self.self)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
String describing the reason of the exception.
|
|
10
|
+
*/
|
|
11
|
+
open var reason: String {
|
|
12
|
+
"undefined reason"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
The origin in code where the exception was created.
|
|
17
|
+
*/
|
|
18
|
+
open var origin: ExceptionOrigin
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
The default initializer that captures the place in the code where the exception was created.
|
|
22
|
+
- Warning: Call it only without arguments!
|
|
23
|
+
*/
|
|
24
|
+
public init(file: String = #fileID, line: UInt = #line, function: String = #function) {
|
|
25
|
+
self.origin = ExceptionOrigin(file: file, line: line, function: function)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// MARK: ChainableException
|
|
29
|
+
|
|
30
|
+
open var cause: Error?
|
|
31
|
+
|
|
32
|
+
// MARK: CustomStringConvertible
|
|
33
|
+
|
|
34
|
+
open var description: String {
|
|
35
|
+
return concatDescription(reason, withCause: cause, debug: false)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// MARK: CustomDebugStringConvertible
|
|
39
|
+
|
|
40
|
+
open var debugDescription: String {
|
|
41
|
+
let debugDescription = "\(name): \(reason) (at \(origin.file):\(origin.line))"
|
|
42
|
+
return concatDescription(debugDescription, withCause: cause, debug: true)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
Concatenates the exception description with its cause description.
|
|
48
|
+
*/
|
|
49
|
+
private func concatDescription(_ description: String, withCause cause: Error?, debug: Bool = false) -> String {
|
|
50
|
+
let causeSeparator = "\n→ Caused by: "
|
|
51
|
+
switch cause {
|
|
52
|
+
case let cause as Exception:
|
|
53
|
+
return description + causeSeparator + (debug ? cause.debugDescription : cause.description)
|
|
54
|
+
case let cause as CodedError:
|
|
55
|
+
// `CodedError` is deprecated but we need to provide backwards compatibility as some modules already used it.
|
|
56
|
+
return description + causeSeparator + cause.description
|
|
57
|
+
case let cause?:
|
|
58
|
+
return description + causeSeparator + cause.localizedDescription
|
|
59
|
+
default:
|
|
60
|
+
return description
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -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)
|
|
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
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
Represents a function that can only be called asynchronously, thus its JavaScript equivalent returns a Promise.
|
|
5
|
+
|
|
6
|
+
- ToDo: Move some asynchronous logic from `ConcreteFunction` (like `call(args:promise:)`) to this class and drop the `isAsync` property.
|
|
7
|
+
*/
|
|
8
|
+
public final class AsyncFunction<Args, ReturnType>: ConcreteFunction<Args, ReturnType> {
|
|
9
|
+
override init(
|
|
10
|
+
_ name: String,
|
|
11
|
+
argTypes: [AnyArgumentType],
|
|
12
|
+
_ closure: @escaping ConcreteFunction<Args, ReturnType>.ClosureType
|
|
13
|
+
) {
|
|
14
|
+
super.init(name, argTypes: argTypes, closure)
|
|
15
|
+
self.isAsync = true
|
|
16
|
+
}
|
|
17
|
+
}
|