expo-modules-core 0.9.2 → 0.10.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 +18 -5
- package/android/CMakeLists.txt +154 -0
- package/android/build.gradle +293 -5
- package/android/src/main/cpp/Exceptions.cpp +22 -0
- package/android/src/main/cpp/Exceptions.h +38 -0
- package/android/src/main/cpp/ExpoModulesHostObject.cpp +47 -0
- package/android/src/main/cpp/ExpoModulesHostObject.h +32 -0
- package/android/src/main/cpp/JNIFunctionBody.cpp +29 -0
- package/android/src/main/cpp/JNIFunctionBody.h +50 -0
- package/android/src/main/cpp/JNIInjector.cpp +19 -0
- package/android/src/main/cpp/JSIInteropModuleRegistry.cpp +122 -0
- package/android/src/main/cpp/JSIInteropModuleRegistry.h +96 -0
- package/android/src/main/cpp/JSIObjectWrapper.h +33 -0
- package/android/src/main/cpp/JSITypeConverter.h +84 -0
- package/android/src/main/cpp/JavaScriptModuleObject.cpp +138 -0
- package/android/src/main/cpp/JavaScriptModuleObject.h +122 -0
- package/android/src/main/cpp/JavaScriptObject.cpp +125 -0
- package/android/src/main/cpp/JavaScriptObject.h +131 -0
- package/android/src/main/cpp/JavaScriptRuntime.cpp +127 -0
- package/android/src/main/cpp/JavaScriptRuntime.h +87 -0
- package/android/src/main/cpp/JavaScriptValue.cpp +172 -0
- package/android/src/main/cpp/JavaScriptValue.h +78 -0
- package/android/src/main/cpp/MethodMetadata.cpp +230 -0
- package/android/src/main/cpp/MethodMetadata.h +92 -0
- package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +2 -0
- package/android/src/main/java/expo/modules/core/errors/ContextDestroyedException.kt +7 -0
- package/android/src/main/java/expo/modules/interfaces/permissions/Permissions.java +30 -0
- package/android/src/main/java/expo/modules/kotlin/AppContext.kt +49 -1
- package/android/src/main/java/expo/modules/kotlin/ConcatIterator.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +15 -12
- package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +39 -3
- package/android/src/main/java/expo/modules/kotlin/defaultmodules/ErrorManagerModule.kt +2 -2
- package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +13 -0
- package/android/src/main/java/expo/modules/kotlin/exception/ExceptionDecorator.kt +2 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AnyFunction.kt +19 -14
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +29 -7
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +13 -13
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionComponent.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromiseComponent.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/functions/SuspendFunctionComponent.kt +56 -0
- package/android/src/main/java/expo/modules/kotlin/functions/SyncFunctionComponent.kt +28 -0
- package/android/src/main/java/expo/modules/kotlin/jni/CppType.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JNIFunctionBody.kt +39 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JSIInteropModuleRegistry.kt +89 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptModuleObject.kt +44 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptObject.kt +113 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptValue.kt +35 -0
- package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +15 -5
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +65 -111
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +35 -2
- package/android/src/main/java/expo/modules/kotlin/providers/AppContextProvider.kt +14 -0
- package/android/src/main/java/expo/modules/kotlin/providers/CurrentActivityProvider.kt +22 -0
- package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +19 -2
- package/android/src/main/java/expo/modules/kotlin/types/AnyType.kt +3 -2
- package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +7 -2
- package/android/src/main/java/expo/modules/kotlin/types/BasicTypeConverters.kt +68 -20
- package/android/src/main/java/expo/modules/kotlin/types/EnumTypeConverter.kt +50 -22
- package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +18 -2
- package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +18 -2
- package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +17 -2
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +43 -3
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +5 -0
- package/build/NativeModulesProxy.native.d.ts.map +1 -1
- package/build/NativeModulesProxy.native.js +9 -3
- package/build/NativeModulesProxy.native.js.map +1 -1
- package/ios/AppDelegates/EXAppDelegatesLoader.m +1 -2
- package/ios/ExpoModulesCore.podspec +1 -1
- package/ios/JSI/EXJSIConversions.mm +6 -0
- package/ios/JSI/EXJSIInstaller.h +15 -21
- package/ios/JSI/EXJSIInstaller.mm +39 -3
- package/ios/JSI/EXJSIUtils.h +47 -3
- package/ios/JSI/EXJSIUtils.mm +88 -4
- package/ios/JSI/EXJavaScriptObject.h +11 -18
- package/ios/JSI/EXJavaScriptObject.mm +37 -18
- package/ios/JSI/EXJavaScriptRuntime.h +43 -9
- package/ios/JSI/EXJavaScriptRuntime.mm +70 -27
- package/ios/JSI/EXJavaScriptTypedArray.h +30 -0
- package/ios/JSI/EXJavaScriptTypedArray.mm +29 -0
- package/ios/JSI/EXJavaScriptValue.h +3 -2
- package/ios/JSI/EXJavaScriptValue.mm +17 -20
- package/ios/JSI/EXJavaScriptWeakObject.h +23 -0
- package/ios/JSI/EXJavaScriptWeakObject.mm +53 -0
- package/ios/JSI/EXObjectDeallocator.h +27 -0
- package/ios/JSI/ExpoModulesHostObject.h +3 -3
- package/ios/JSI/ExpoModulesHostObject.mm +4 -4
- package/ios/JSI/JavaScriptRuntime.swift +38 -1
- package/ios/JSI/JavaScriptValue.swift +7 -0
- package/ios/JSI/TypedArray.cpp +67 -0
- package/ios/JSI/TypedArray.h +46 -0
- package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +0 -11
- package/ios/NativeModulesProxy/EXNativeModulesProxy.h +17 -10
- package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +85 -77
- package/ios/NativeModulesProxy/NativeModulesProxyModule.swift +17 -0
- package/ios/Services/EXReactNativeEventEmitter.h +2 -2
- package/ios/Services/EXReactNativeEventEmitter.m +11 -6
- package/ios/Swift/AppContext.swift +208 -28
- package/ios/Swift/Arguments/AnyArgument.swift +18 -0
- package/ios/Swift/Arguments/{Types/EnumArgumentType.swift → EnumArgument.swift} +2 -17
- package/ios/Swift/Classes/ClassComponent.swift +95 -0
- package/ios/Swift/Classes/ClassComponentElement.swift +33 -0
- package/ios/Swift/Classes/ClassComponentElementsBuilder.swift +34 -0
- package/ios/Swift/Classes/ClassComponentFactories.swift +96 -0
- package/ios/Swift/DynamicTypes/AnyDynamicType.swift +44 -0
- package/ios/Swift/DynamicTypes/DynamicArrayType.swift +56 -0
- package/ios/Swift/DynamicTypes/DynamicConvertibleType.swift +27 -0
- package/ios/Swift/DynamicTypes/DynamicEnumType.swift +27 -0
- package/ios/Swift/DynamicTypes/DynamicOptionalType.swift +63 -0
- package/ios/Swift/DynamicTypes/DynamicRawType.swift +33 -0
- package/ios/Swift/DynamicTypes/DynamicSharedObjectType.swift +37 -0
- package/ios/Swift/DynamicTypes/DynamicType.swift +39 -0
- package/ios/Swift/DynamicTypes/DynamicTypedArrayType.swift +46 -0
- package/ios/Swift/Exceptions/CodedError.swift +1 -1
- package/ios/Swift/Exceptions/Exception.swift +8 -6
- package/ios/Swift/Exceptions/UnexpectedException.swift +2 -1
- package/ios/Swift/ExpoBridgeModule.m +5 -0
- package/ios/Swift/ExpoBridgeModule.swift +65 -0
- package/ios/Swift/Functions/AnyFunction.swift +33 -31
- package/ios/Swift/Functions/AsyncFunctionComponent.swift +196 -59
- package/ios/Swift/Functions/SyncFunctionComponent.swift +142 -58
- package/ios/Swift/JavaScriptUtils.swift +32 -57
- package/ios/Swift/Logging/LogHandlers.swift +39 -0
- package/ios/Swift/Logging/LogType.swift +62 -0
- package/ios/Swift/Logging/Logger.swift +198 -0
- package/ios/Swift/ModuleHolder.swift +19 -54
- package/ios/Swift/ModuleRegistry.swift +7 -1
- package/ios/Swift/Modules/AnyModule.swift +3 -3
- package/ios/Swift/ModulesProvider.swift +2 -0
- package/ios/Swift/Objects/JavaScriptObjectBuilder.swift +37 -0
- package/ios/Swift/Objects/ObjectDefinition.swift +74 -1
- package/ios/Swift/Objects/ObjectDefinitionComponents.swift +77 -68
- package/ios/Swift/Objects/PropertyComponent.swift +147 -0
- package/ios/Swift/Promise.swift +12 -3
- package/ios/Swift/Records/Field.swift +2 -2
- package/ios/Swift/SharedObjects/SharedObject.swift +20 -0
- package/ios/Swift/SharedObjects/SharedObjectRegistry.swift +129 -0
- package/ios/Swift/TypedArrays/AnyTypedArray.swift +11 -0
- package/ios/Swift/TypedArrays/ConcreteTypedArrays.swift +56 -0
- package/ios/Swift/TypedArrays/GenericTypedArray.swift +49 -0
- package/ios/Swift/TypedArrays/TypedArray.swift +80 -0
- package/ios/Swift/Utilities.swift +28 -0
- package/ios/Swift/Views/ConcreteViewProp.swift +3 -3
- package/ios/Swift/Views/ViewManagerDefinitionComponents.swift +2 -2
- package/ios/Tests/ClassComponentSpec.swift +210 -0
- package/ios/Tests/DynamicTypeSpec.swift +336 -0
- package/ios/Tests/EnumArgumentSpec.swift +48 -0
- package/ios/Tests/ExpoModulesSpec.swift +17 -3
- package/ios/Tests/FunctionSpec.swift +167 -118
- package/ios/Tests/Mocks/ModuleMocks.swift +1 -1
- package/ios/Tests/PropertyComponentSpec.swift +95 -0
- package/ios/Tests/SharedObjectRegistrySpec.swift +109 -0
- package/ios/Tests/TypedArraysSpec.swift +136 -0
- package/package.json +2 -2
- package/src/NativeModulesProxy.native.ts +13 -3
- package/src/ts-declarations/ExpoModules.d.ts +7 -0
- package/tsconfig.json +1 -1
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromise.kt +0 -15
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncSuspendFunction.kt +0 -36
- package/ios/Swift/Arguments/AnyArgumentType.swift +0 -13
- package/ios/Swift/Arguments/ArgumentType.swift +0 -28
- package/ios/Swift/Arguments/Types/ArrayArgumentType.swift +0 -42
- package/ios/Swift/Arguments/Types/ConvertibleArgumentType.swift +0 -16
- package/ios/Swift/Arguments/Types/OptionalArgumentType.swift +0 -49
- package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +0 -15
- package/ios/Swift/Arguments/Types/RawArgumentType.swift +0 -25
- package/ios/Swift/Functions/ConcreteFunction.swift +0 -103
- package/ios/Swift/SwiftInteropBridge.swift +0 -155
- package/ios/Tests/ArgumentTypeSpec.swift +0 -143
|
@@ -1,19 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
An argument type representing an enum that conforms to `EnumArgument`.
|
|
5
|
-
*/
|
|
6
|
-
internal struct EnumArgumentType: AnyArgumentType {
|
|
7
|
-
let innerType: EnumArgument.Type
|
|
8
|
-
|
|
9
|
-
func cast<ArgType>(_ value: ArgType) throws -> Any {
|
|
10
|
-
return try innerType.create(fromRawValue: value)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
var description: String {
|
|
14
|
-
"Enum<\(innerType)>"
|
|
15
|
-
}
|
|
16
|
-
}
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
17
2
|
|
|
18
3
|
/**
|
|
19
4
|
A protocol that allows converting raw values to enum cases.
|
|
@@ -23,7 +8,7 @@ public protocol EnumArgument: AnyArgument {
|
|
|
23
8
|
Tries to create an enum case using given raw value.
|
|
24
9
|
May throw errors, e.g. when the raw value doesn't match any case.
|
|
25
10
|
*/
|
|
26
|
-
static func create<
|
|
11
|
+
static func create<RawValueType>(fromRawValue rawValue: RawValueType) throws -> Self
|
|
27
12
|
|
|
28
13
|
/**
|
|
29
14
|
Returns an array of all raw values available in the enum.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
Represents a JavaScript class.
|
|
5
|
+
*/
|
|
6
|
+
public final class ClassComponent: ObjectDefinition {
|
|
7
|
+
/**
|
|
8
|
+
Name of the class.
|
|
9
|
+
*/
|
|
10
|
+
let name: String
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
A synchronous function that gets called when the object of this class is initializing.
|
|
14
|
+
*/
|
|
15
|
+
let constructor: AnySyncFunctionComponent?
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
A dynamic type for the associated object class.
|
|
19
|
+
*/
|
|
20
|
+
let associatedType: AnyDynamicType?
|
|
21
|
+
|
|
22
|
+
init<AssociatedObject: ClassAssociatedObject>(
|
|
23
|
+
name: String,
|
|
24
|
+
associatedType: AssociatedObject.Type,
|
|
25
|
+
elements: [AnyClassComponentElement] = []
|
|
26
|
+
) {
|
|
27
|
+
self.name = name
|
|
28
|
+
self.constructor = elements.first(where: isConstructor) as? AnySyncFunctionComponent
|
|
29
|
+
self.associatedType = ~AssociatedObject.self
|
|
30
|
+
|
|
31
|
+
// Constructors can't be passed down to the object component
|
|
32
|
+
// as we shouldn't override the default `<Class>.prototype.constructor`.
|
|
33
|
+
let elementsWithoutConstructors = elements.filter({ !isConstructor($0) })
|
|
34
|
+
|
|
35
|
+
super.init(definitions: elementsWithoutConstructors)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// MARK: - JavaScriptObjectBuilder
|
|
39
|
+
|
|
40
|
+
public override func build(inRuntime runtime: JavaScriptRuntime) -> JavaScriptObject {
|
|
41
|
+
let klass = runtime.createClass(name) { [weak self, weak runtime] this, arguments in
|
|
42
|
+
guard let self = self, let runtime = runtime else {
|
|
43
|
+
// TODO: Throw an exception? (@tsapeta)
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
// The properties can't go into the prototype as they would be shared across all instances.
|
|
47
|
+
// Instead, we decorate the instance object on initialization.
|
|
48
|
+
self.decorateWithProperties(runtime: runtime, object: this)
|
|
49
|
+
|
|
50
|
+
// Call the native constructor when defined.
|
|
51
|
+
let result = try? self.constructor?.call(by: this, withArguments: arguments)
|
|
52
|
+
|
|
53
|
+
// Register the shared object if returned by the constructor.
|
|
54
|
+
if let result = result as? SharedObject {
|
|
55
|
+
SharedObjectRegistry.add(native: result, javaScript: this)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
decorate(object: klass, inRuntime: runtime)
|
|
59
|
+
return klass
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public override func decorate(object: JavaScriptObject, inRuntime runtime: JavaScriptRuntime) {
|
|
63
|
+
// Here we actually don't decorate the input object (constructor) but its prototype.
|
|
64
|
+
// Properties are intentionally skipped here — they have to decorate an instance instead of the prototype.
|
|
65
|
+
let prototype = object.getProperty("prototype").getObject()
|
|
66
|
+
decorateWithConstants(runtime: runtime, object: prototype)
|
|
67
|
+
decorateWithFunctions(runtime: runtime, object: prototype)
|
|
68
|
+
decorateWithClasses(runtime: runtime, object: prototype)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// MARK: - ClassAssociatedObject
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
A protocol for types that can be used an associated type of the `ClassComponent`.
|
|
76
|
+
*/
|
|
77
|
+
internal protocol ClassAssociatedObject {}
|
|
78
|
+
|
|
79
|
+
// Basically we only need these two
|
|
80
|
+
extension JavaScriptObject: ClassAssociatedObject {}
|
|
81
|
+
extension SharedObject: ClassAssociatedObject {}
|
|
82
|
+
|
|
83
|
+
// MARK: - Privates
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
Checks whether the definition item is a constructor — a synchronous function whose name is "constructor".
|
|
87
|
+
|
|
88
|
+
We do it that way for the following two reasons:
|
|
89
|
+
- It's easier to reuse existing `SyncFunctionComponent`.
|
|
90
|
+
- Redefining prototype's `constructor` is a bad idea so a function with this name
|
|
91
|
+
needs to be filtered out when decorating the prototype.
|
|
92
|
+
*/
|
|
93
|
+
fileprivate func isConstructor(_ item: AnyDefinition) -> Bool {
|
|
94
|
+
return (item as? AnySyncFunctionComponent)?.name == "constructor"
|
|
95
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
A type-erased protocol that must be implemented by the components passed as ``ClassComponent`` elements.
|
|
5
|
+
*/
|
|
6
|
+
public protocol AnyClassComponentElement: AnyDefinition {}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
Class component element with an associated owner type. The `OwnerType` should refer to
|
|
10
|
+
the type that the parent `Class` component is associated with (e.g. the shared object type).
|
|
11
|
+
*/
|
|
12
|
+
public protocol ClassComponentElement: AnyClassComponentElement {
|
|
13
|
+
associatedtype OwnerType
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// MARK: - Conformance
|
|
17
|
+
// Allow some other components to be used as the class component elements.
|
|
18
|
+
|
|
19
|
+
extension SyncFunctionComponent: ClassComponentElement {
|
|
20
|
+
public typealias OwnerType = FirstArgType
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
extension AsyncFunctionComponent: ClassComponentElement {
|
|
24
|
+
public typealias OwnerType = FirstArgType
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
extension PropertyComponent: ClassComponentElement {
|
|
28
|
+
public typealias OwnerType = Void
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
extension ConstantsDefinition: ClassComponentElement {
|
|
32
|
+
public typealias OwnerType = Void
|
|
33
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
A result builder that captures the ``ClassComponent`` elements such as functions, constants and properties.
|
|
5
|
+
*/
|
|
6
|
+
@resultBuilder
|
|
7
|
+
public struct ClassComponentElementsBuilder<OwnerType> {
|
|
8
|
+
public static func buildBlock(_ elements: AnyClassComponentElement...) -> [AnyClassComponentElement] {
|
|
9
|
+
return elements
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
Default implementation without any constraints that just returns type-erased element.
|
|
14
|
+
*/
|
|
15
|
+
static func buildExpression<ElementType: ClassComponentElement>(
|
|
16
|
+
_ element: ElementType
|
|
17
|
+
) -> AnyClassComponentElement {
|
|
18
|
+
return element
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
In case the element's owner type matches builder's generic type,
|
|
23
|
+
we need to instruct the function to pass `this` to the closure
|
|
24
|
+
as the first argument and deduct it from `argumentsCount`.
|
|
25
|
+
*/
|
|
26
|
+
static func buildExpression<ElementType: ClassComponentElement>(
|
|
27
|
+
_ element: ElementType
|
|
28
|
+
) -> AnyClassComponentElement where ElementType.OwnerType == OwnerType {
|
|
29
|
+
if var function = element as? AnyFunction {
|
|
30
|
+
function.takesOwner = true
|
|
31
|
+
}
|
|
32
|
+
return element
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
Class constructor without arguments.
|
|
5
|
+
*/
|
|
6
|
+
public func Constructor<R>(
|
|
7
|
+
_ body: @escaping () throws -> R
|
|
8
|
+
) -> SyncFunctionComponent<(), Void, R> {
|
|
9
|
+
return Function("constructor", body)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
Class constructor with one argument.
|
|
14
|
+
*/
|
|
15
|
+
public func Constructor<R, A0: AnyArgument>(
|
|
16
|
+
_ body: @escaping (A0) throws -> R
|
|
17
|
+
) -> SyncFunctionComponent<(A0), A0, R> {
|
|
18
|
+
return Function("constructor", body)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
Class constructor with two arguments.
|
|
23
|
+
*/
|
|
24
|
+
public func Constructor<R, A0: AnyArgument, A1: AnyArgument>(
|
|
25
|
+
_ body: @escaping (A0, A1) throws -> R
|
|
26
|
+
) -> SyncFunctionComponent<(A0, A1), A0, R> {
|
|
27
|
+
return Function("constructor", body)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
Class constructor with three arguments.
|
|
32
|
+
*/
|
|
33
|
+
public func Constructor<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument>(
|
|
34
|
+
_ body: @escaping (A0, A1, A2) throws -> R
|
|
35
|
+
) -> SyncFunctionComponent<(A0, A1, A2), A0, R> {
|
|
36
|
+
return Function("constructor", body)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
Class constructor with four arguments.
|
|
41
|
+
*/
|
|
42
|
+
public func Constructor<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument>(
|
|
43
|
+
_ body: @escaping (A0, A1, A2, A3) throws -> R
|
|
44
|
+
) -> SyncFunctionComponent<(A0, A1, A2, A3), A0, R> {
|
|
45
|
+
return Function("constructor", body)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
Class constructor with five arguments.
|
|
50
|
+
*/
|
|
51
|
+
public func Constructor<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument>(
|
|
52
|
+
_ body: @escaping (A0, A1, A2, A3, A4) throws -> R
|
|
53
|
+
) -> SyncFunctionComponent<(A0, A1, A2, A3, A4), A0, R> {
|
|
54
|
+
return Function("constructor", body)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
Class constructor with six arguments.
|
|
59
|
+
*/
|
|
60
|
+
public func Constructor<R, A0: AnyArgument, A1: AnyArgument, A2: AnyArgument, A3: AnyArgument, A4: AnyArgument, A5: AnyArgument>(
|
|
61
|
+
_ body: @escaping (A0, A1, A2, A3, A4, A5) throws -> R
|
|
62
|
+
) -> SyncFunctionComponent<(A0, A1, A2, A3, A4, A5), A0, R> {
|
|
63
|
+
return Function("constructor", body)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
Creates the component describing a JavaScript class.
|
|
68
|
+
*/
|
|
69
|
+
public func Class(
|
|
70
|
+
_ name: String,
|
|
71
|
+
@ClassComponentElementsBuilder<JavaScriptObject> _ elements: () -> [AnyClassComponentElement]
|
|
72
|
+
) -> ClassComponent {
|
|
73
|
+
return ClassComponent(name: name, associatedType: JavaScriptObject.self, elements: elements())
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
Creates the component describing a JavaScript class with an associated native shared object class.
|
|
78
|
+
*/
|
|
79
|
+
public func Class<SharedObjectType: SharedObject>(
|
|
80
|
+
_ name: String = String(describing: SharedObjectType.self),
|
|
81
|
+
_ sharedObjectType: SharedObjectType.Type,
|
|
82
|
+
@ClassComponentElementsBuilder<SharedObjectType> _ elements: () -> [AnyClassComponentElement]
|
|
83
|
+
) -> ClassComponent {
|
|
84
|
+
return ClassComponent(name: name, associatedType: SharedObjectType.self, elements: elements())
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
Creates the component describing a JavaScript class with an associated native shared object class
|
|
89
|
+
and with the name that is inferred from the shared object type.
|
|
90
|
+
*/
|
|
91
|
+
public func Class<SharedObjectType: SharedObject>(
|
|
92
|
+
_ sharedObjectType: SharedObjectType.Type,
|
|
93
|
+
@ClassComponentElementsBuilder<SharedObjectType> _ elements: () -> [AnyClassComponentElement]
|
|
94
|
+
) -> ClassComponent {
|
|
95
|
+
return ClassComponent(name: String(describing: SharedObjectType.self), associatedType: SharedObjectType.self, elements: elements())
|
|
96
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
A protocol whose intention is to wrap any type
|
|
5
|
+
to keep its real signature and not type-erase it by the compiler.
|
|
6
|
+
*/
|
|
7
|
+
public protocol AnyDynamicType: CustomStringConvertible {
|
|
8
|
+
/**
|
|
9
|
+
Checks whether the inner type is the same as the given type.
|
|
10
|
+
*/
|
|
11
|
+
func wraps<InnerType>(_ type: InnerType.Type) -> Bool
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
Checks whether the dynamic type is equal to another,
|
|
15
|
+
that is when the type of the dynamic types are equal and their inner types are equal.
|
|
16
|
+
*/
|
|
17
|
+
func equals(_ type: AnyDynamicType) -> Bool
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
Casts given any value to the wrapped type and returns as `Any`.
|
|
21
|
+
NOTE: It may not be just simple type-casting (e.g. when the wrapped type conforms to `ConvertibleArgument`).
|
|
22
|
+
*/
|
|
23
|
+
func cast<ValueType>(_ value: ValueType) throws -> Any
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// MARK: - Operators
|
|
27
|
+
|
|
28
|
+
infix operator ~>
|
|
29
|
+
public func ~> <T>(lhs: AnyDynamicType, rhs: T.Type) -> Bool {
|
|
30
|
+
return lhs.wraps(rhs)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
infix operator !~>
|
|
34
|
+
public func !~> <T>(lhs: AnyDynamicType, rhs: T.Type) -> Bool {
|
|
35
|
+
return !lhs.wraps(rhs)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public func == (lhs: AnyDynamicType, rhs: AnyDynamicType) -> Bool {
|
|
39
|
+
return lhs.equals(rhs)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public func != (lhs: AnyDynamicType, rhs: AnyDynamicType) -> Bool {
|
|
43
|
+
return !lhs.equals(rhs)
|
|
44
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
A dynamic type representing array types. Requires the array's element type
|
|
5
|
+
for the initialization as it delegates casting to that type for each element in the array.
|
|
6
|
+
*/
|
|
7
|
+
internal struct DynamicArrayType: AnyDynamicType {
|
|
8
|
+
let elementType: AnyDynamicType
|
|
9
|
+
|
|
10
|
+
func wraps<InnerType>(_ type: InnerType.Type) -> Bool {
|
|
11
|
+
if let ArrayType = InnerType.self as? AnyArray.Type {
|
|
12
|
+
return elementType.equals(ArrayType.getElementDynamicType())
|
|
13
|
+
}
|
|
14
|
+
return false
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
func equals(_ type: AnyDynamicType) -> Bool {
|
|
18
|
+
if let arrayType = type as? Self {
|
|
19
|
+
return arrayType.elementType.equals(elementType)
|
|
20
|
+
}
|
|
21
|
+
return false
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
func cast<ValueType>(_ value: ValueType) throws -> Any {
|
|
25
|
+
if let value = value as? [Any] {
|
|
26
|
+
return try value.map { try elementType.cast($0) }
|
|
27
|
+
}
|
|
28
|
+
// We should probably throw an error if we get here. On the other side, the array type
|
|
29
|
+
// requirement can be more loosen so we can try to arrayize values that are not arrays.
|
|
30
|
+
return [try elementType.cast(value)]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
var description: String {
|
|
34
|
+
"[\(elementType.description)]"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
A type-erased protocol used to recognize if the generic type is an array type.
|
|
40
|
+
`Array` is a generic type, so it's impossible to check the inheritance directly.
|
|
41
|
+
*/
|
|
42
|
+
internal protocol AnyArray {
|
|
43
|
+
/**
|
|
44
|
+
Exposes the `Element` generic type wrapped by the dynamic type to preserve its metadata.
|
|
45
|
+
*/
|
|
46
|
+
static func getElementDynamicType() -> AnyDynamicType
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
Extends the `Array` type to expose its generic `Element` as a dynamic type.
|
|
51
|
+
*/
|
|
52
|
+
extension Array: AnyArray {
|
|
53
|
+
static func getElementDynamicType() -> AnyDynamicType {
|
|
54
|
+
return DynamicType(Element.self)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
A dynamic type that wraps any type conforming to `ConvertibleArgument` protocol.
|
|
5
|
+
*/
|
|
6
|
+
internal struct DynamicConvertibleType: AnyDynamicType {
|
|
7
|
+
let innerType: ConvertibleArgument.Type
|
|
8
|
+
|
|
9
|
+
func wraps<InnerType>(_ type: InnerType.Type) -> Bool {
|
|
10
|
+
return innerType == InnerType.self
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
func equals(_ type: AnyDynamicType) -> Bool {
|
|
14
|
+
if let convertibleType = type as? Self {
|
|
15
|
+
return convertibleType.innerType == innerType
|
|
16
|
+
}
|
|
17
|
+
return false
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
func cast<ValueType>(_ value: ValueType) throws -> Any {
|
|
21
|
+
return try innerType.convert(from: value)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var description: String {
|
|
25
|
+
String(describing: innerType.self)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
A dynamic type representing an enum that conforms to `EnumArgument`.
|
|
5
|
+
*/
|
|
6
|
+
internal struct DynamicEnumType: AnyDynamicType {
|
|
7
|
+
let innerType: EnumArgument.Type
|
|
8
|
+
|
|
9
|
+
func wraps<InnerType>(_ type: InnerType.Type) -> Bool {
|
|
10
|
+
return innerType == InnerType.self
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
func equals(_ type: AnyDynamicType) -> Bool {
|
|
14
|
+
if let enumType = type as? Self {
|
|
15
|
+
return enumType.innerType == innerType
|
|
16
|
+
}
|
|
17
|
+
return false
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
func cast<ValueType>(_ value: ValueType) throws -> Any {
|
|
21
|
+
return try innerType.create(fromRawValue: value)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var description: String {
|
|
25
|
+
"Enum<\(innerType)>"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
A dynamic type that represents an optional type, which allows `nil` to be passed when casting.
|
|
5
|
+
Requires the optional's wrapped type as it delegates casting to that type for non-nil values.
|
|
6
|
+
*/
|
|
7
|
+
internal struct DynamicOptionalType: AnyDynamicType {
|
|
8
|
+
let wrappedType: AnyDynamicType
|
|
9
|
+
|
|
10
|
+
func wraps<InnerType>(_ type: InnerType.Type) -> Bool {
|
|
11
|
+
if let OptionalType = InnerType.self as? AnyOptional.Type {
|
|
12
|
+
return wrappedType.equals(OptionalType.getWrappedDynamicType())
|
|
13
|
+
}
|
|
14
|
+
return false
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
func equals(_ type: AnyDynamicType) -> Bool {
|
|
18
|
+
if let optionalType = type as? Self {
|
|
19
|
+
return optionalType.wrappedType.equals(wrappedType)
|
|
20
|
+
}
|
|
21
|
+
return false
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
func cast<ValueType>(_ value: ValueType) throws -> Any {
|
|
25
|
+
if Optional.isNil(value) || value is NSNull {
|
|
26
|
+
return Optional<Any>.none as Any
|
|
27
|
+
}
|
|
28
|
+
return try wrappedType.cast(value)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
var description: String {
|
|
32
|
+
"\(wrappedType)?"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
A type-erased protocol used to recognize if the generic type is an optional type.
|
|
38
|
+
`Optional` is a generic enum, so it's impossible to check the inheritance directly.
|
|
39
|
+
*/
|
|
40
|
+
internal protocol AnyOptional {
|
|
41
|
+
/**
|
|
42
|
+
Exposes the `Wrapped` generic type wrapped by the dynamic type to preserve its metadata.`
|
|
43
|
+
*/
|
|
44
|
+
static func getWrappedDynamicType() -> AnyDynamicType
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
Make generic `Optional` implement non-generic `AnyOptional` and add handy check against type-erased `nil`.
|
|
49
|
+
*/
|
|
50
|
+
extension Optional: AnyOptional {
|
|
51
|
+
static func getWrappedDynamicType() -> AnyDynamicType {
|
|
52
|
+
return DynamicType(Wrapped.self)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static func isNil(_ object: Wrapped) -> Bool {
|
|
56
|
+
switch object as Any {
|
|
57
|
+
case Optional<Any>.none:
|
|
58
|
+
return true
|
|
59
|
+
default:
|
|
60
|
+
return false
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
A dynamic type that can wrap any type, but it casts only type-compatible values using `as?` keyword.
|
|
5
|
+
The innermost type of the other dynamic types like `ArrayArgumentType` and `OptionalArgumentType`.
|
|
6
|
+
*/
|
|
7
|
+
internal struct DynamicRawType<InnerType>: AnyDynamicType {
|
|
8
|
+
let innerType: InnerType.Type
|
|
9
|
+
|
|
10
|
+
func wraps<InnerType>(_ type: InnerType.Type) -> Bool {
|
|
11
|
+
return type == innerType
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
func equals(_ type: AnyDynamicType) -> Bool {
|
|
15
|
+
return type is Self
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
func cast<ValueType>(_ value: ValueType) throws -> Any {
|
|
19
|
+
if let value = value as? InnerType {
|
|
20
|
+
return value
|
|
21
|
+
}
|
|
22
|
+
// Raw types are always non-optional, but they may receive `nil` values.
|
|
23
|
+
// Let's throw more specific error in this case.
|
|
24
|
+
if Optional.isNil(value) {
|
|
25
|
+
throw Conversions.NullCastException<InnerType>()
|
|
26
|
+
}
|
|
27
|
+
throw Conversions.CastingException<InnerType>(value)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
var description: String {
|
|
31
|
+
String(describing: innerType.self)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
A dynamic type representing the `SharedObject` type and its subclasses.
|
|
5
|
+
*/
|
|
6
|
+
internal struct DynamicSharedObjectType: AnyDynamicType {
|
|
7
|
+
let innerType: SharedObject.Type
|
|
8
|
+
|
|
9
|
+
func wraps<InnerType>(_ type: InnerType.Type) -> Bool {
|
|
10
|
+
return innerType == InnerType.self
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
func equals(_ type: AnyDynamicType) -> Bool {
|
|
14
|
+
if let sharedObjectType = type as? Self {
|
|
15
|
+
return sharedObjectType.innerType == innerType
|
|
16
|
+
}
|
|
17
|
+
return false
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
func cast<ValueType>(_ value: ValueType) throws -> Any {
|
|
21
|
+
if let jsObject = try (value as? JavaScriptValue)?.asObject(),
|
|
22
|
+
let nativeSharedObject = SharedObjectRegistry.toNativeObject(jsObject) {
|
|
23
|
+
return nativeSharedObject
|
|
24
|
+
}
|
|
25
|
+
throw NativeSharedObjectNotFoundException()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
var description: String {
|
|
29
|
+
return "SharedObject<\(innerType)>"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
internal final class NativeSharedObjectNotFoundException: Exception {
|
|
34
|
+
override var reason: String {
|
|
35
|
+
"Unable to find the native shared object associated with given JavaScript object"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
// Function names should start with a lowercase character, but in this one case
|
|
4
|
+
// we want it to be uppercase as we treat it more like a generic class.
|
|
5
|
+
// swiftlint:disable identifier_name
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
Factory creating an instance of the dynamic type wrapper conforming to `AnyDynamicType`.
|
|
9
|
+
Depending on the given type, it may return one of `DynamicArrayType`, `DynamicOptionalType`, `DynamicConvertibleType`, etc.
|
|
10
|
+
*/
|
|
11
|
+
internal func DynamicType<T>(_ type: T.Type) -> AnyDynamicType {
|
|
12
|
+
if let ArrayType = T.self as? AnyArray.Type {
|
|
13
|
+
return DynamicArrayType(elementType: ArrayType.getElementDynamicType())
|
|
14
|
+
}
|
|
15
|
+
if let OptionalType = T.self as? AnyOptional.Type {
|
|
16
|
+
return DynamicOptionalType(wrappedType: OptionalType.getWrappedDynamicType())
|
|
17
|
+
}
|
|
18
|
+
if let ConvertibleType = T.self as? ConvertibleArgument.Type {
|
|
19
|
+
return DynamicConvertibleType(innerType: ConvertibleType)
|
|
20
|
+
}
|
|
21
|
+
if let EnumType = T.self as? EnumArgument.Type {
|
|
22
|
+
return DynamicEnumType(innerType: EnumType)
|
|
23
|
+
}
|
|
24
|
+
if let SharedObjectType = T.self as? SharedObject.Type {
|
|
25
|
+
return DynamicSharedObjectType(innerType: SharedObjectType)
|
|
26
|
+
}
|
|
27
|
+
if let TypedArrayType = T.self as? AnyTypedArray.Type {
|
|
28
|
+
return DynamicTypedArrayType(innerType: TypedArrayType)
|
|
29
|
+
}
|
|
30
|
+
return DynamicRawType(innerType: T.self)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
Handy prefix operator that makes the dynamic type from the static type.
|
|
35
|
+
*/
|
|
36
|
+
prefix operator ~
|
|
37
|
+
public prefix func ~ <T>(type: T.Type) -> AnyDynamicType {
|
|
38
|
+
return DynamicType(type)
|
|
39
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
internal struct DynamicTypedArrayType: AnyDynamicType {
|
|
4
|
+
let innerType: AnyTypedArray.Type
|
|
5
|
+
|
|
6
|
+
func wraps<InnerType>(_ type: InnerType.Type) -> Bool {
|
|
7
|
+
return innerType == InnerType.self
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
func equals(_ type: AnyDynamicType) -> Bool {
|
|
11
|
+
if let typedArrayType = type as? Self {
|
|
12
|
+
return typedArrayType.innerType == innerType
|
|
13
|
+
}
|
|
14
|
+
return false
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
func cast<ValueType>(_ value: ValueType) throws -> Any {
|
|
18
|
+
// It must be a JavaScript typed array.
|
|
19
|
+
guard let value = value as? JavaScriptValue, let jsTypedArray = value.getTypedArray() else {
|
|
20
|
+
throw NotTypedArrayException(innerType)
|
|
21
|
+
}
|
|
22
|
+
let typedArray = TypedArray.create(from: jsTypedArray)
|
|
23
|
+
|
|
24
|
+
// Concrete typed arrays must be the same as the inner type.
|
|
25
|
+
guard innerType == TypedArray.self || type(of: typedArray) == innerType else {
|
|
26
|
+
throw ArrayTypeMismatchException((received: type(of: typedArray), expected: innerType))
|
|
27
|
+
}
|
|
28
|
+
return typedArray
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
var description: String {
|
|
32
|
+
return String(describing: innerType)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
internal final class ArrayTypeMismatchException: GenericException<(received: Any.Type, expected: Any.Type)> {
|
|
37
|
+
override var reason: String {
|
|
38
|
+
"Received a typed array of type \(param.received), expected \(param.expected)"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
internal final class NotTypedArrayException: GenericException<AnyTypedArray.Type> {
|
|
43
|
+
override var reason: String {
|
|
44
|
+
"Given argument is not an instance of \(param)"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -3,7 +3,7 @@ import Foundation
|
|
|
3
3
|
/**
|
|
4
4
|
A protocol for errors specyfing its `code` and providing the `description`.
|
|
5
5
|
*/
|
|
6
|
-
public protocol CodedError: Error {
|
|
6
|
+
public protocol CodedError: Error, CustomStringConvertible {
|
|
7
7
|
var code: String { get }
|
|
8
8
|
var description: String { get }
|
|
9
9
|
}
|