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
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import CoreGraphics
|
|
4
|
+
import ExpoModulesTestCore
|
|
5
|
+
|
|
6
|
+
@testable import ExpoModulesCore
|
|
7
|
+
|
|
8
|
+
final class DynamicTypeSpec: ExpoSpec {
|
|
9
|
+
override func spec() {
|
|
10
|
+
// MARK: - DynamicRawType
|
|
11
|
+
|
|
12
|
+
describe("DynamicRawType") {
|
|
13
|
+
it("is created") {
|
|
14
|
+
expect(~String.self).to(beAKindOf(DynamicRawType<String>.self))
|
|
15
|
+
expect(~Bool.self).to(beAKindOf(DynamicRawType<Bool>.self))
|
|
16
|
+
expect(~ExpoSpec.self).to(beAKindOf(DynamicRawType<ExpoSpec>.self))
|
|
17
|
+
}
|
|
18
|
+
describe("casts") {
|
|
19
|
+
it("succeeds") {
|
|
20
|
+
expect(try (~String.self).cast("expo") as? String) == "expo"
|
|
21
|
+
expect(try (~Double.self).cast(2.1) as? Double) == 2.1
|
|
22
|
+
expect(try (~Bool.self).cast(false) as? Bool) == false
|
|
23
|
+
}
|
|
24
|
+
it("throws NullCastException") {
|
|
25
|
+
let value: Double? = nil
|
|
26
|
+
let anyValue = value as Any
|
|
27
|
+
|
|
28
|
+
expect { try (~Double.self).cast(anyValue) }.to(
|
|
29
|
+
throwError(errorType: Conversions.NullCastException<Double>.self)
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
it("throws CastingException") {
|
|
33
|
+
expect { try (~String.self).cast(true) }.to(
|
|
34
|
+
throwError(errorType: Conversions.CastingException<String>.self)
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
describe("wraps") {
|
|
39
|
+
it("is true") {
|
|
40
|
+
expect(~Double.self ~> Double.self) == true
|
|
41
|
+
expect(~Bool.self ~> Bool.self) == true
|
|
42
|
+
expect(~DynamicTypeSpec.self ~> DynamicTypeSpec.self) == true
|
|
43
|
+
}
|
|
44
|
+
it("is false") {
|
|
45
|
+
expect(~Double.self !~> Bool.self) == true
|
|
46
|
+
expect(~Bool.self !~> Double.self) == true
|
|
47
|
+
expect(~DynamicTypeSpec.self !~> ExpoSpec.self) == true
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
describe("equals") {
|
|
51
|
+
it("is true") {
|
|
52
|
+
expect(~Int.self == ~Int.self) == true
|
|
53
|
+
expect(~Double.self == ~Double.self) == true
|
|
54
|
+
expect(~Bool.self == ~Bool.self) == true
|
|
55
|
+
expect(~ExpoSpec.self == ~ExpoSpec.self) == true
|
|
56
|
+
}
|
|
57
|
+
it("is false") {
|
|
58
|
+
expect(~Int.self != ~String.self) == true
|
|
59
|
+
expect(~String.self != ~CGSize.self) == true
|
|
60
|
+
expect(~Bool.self != ~Promise.self) == true
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// MARK: - DynamicArrayType
|
|
66
|
+
|
|
67
|
+
describe("DynamicArrayType") {
|
|
68
|
+
it("is created") {
|
|
69
|
+
expect(~[Double].self).to(beAKindOf(DynamicArrayType.self))
|
|
70
|
+
expect(~[String?].self).to(beAKindOf(DynamicArrayType.self))
|
|
71
|
+
expect(~[[Int]].self).to(beAKindOf(DynamicArrayType.self))
|
|
72
|
+
}
|
|
73
|
+
describe("casts") {
|
|
74
|
+
it("succeeds") {
|
|
75
|
+
expect(try (~[Double].self).cast([1.2, 3.4]) as? [Double]) == [1.2, 3.4]
|
|
76
|
+
expect(try (~[[String]].self).cast([["hello", "expo"]]) as? [[String]]) == [["hello", "expo"]]
|
|
77
|
+
}
|
|
78
|
+
it("casts arrays") {
|
|
79
|
+
let value = 9.9
|
|
80
|
+
let anyValue = [value] as [Any]
|
|
81
|
+
let result = try (~[Double].self).cast(anyValue) as! [Any]
|
|
82
|
+
|
|
83
|
+
expect(result).to(beAKindOf([Double].self))
|
|
84
|
+
expect(result as? [Double]) == [value]
|
|
85
|
+
}
|
|
86
|
+
it("arrayizes single element") {
|
|
87
|
+
// The dynamic array type can arrayize the single element
|
|
88
|
+
// if only the array element's dynamic type can cast it.
|
|
89
|
+
expect(try (~[Int].self).cast(50) as? [Int]) == [50]
|
|
90
|
+
expect(try (~[String].self).cast("not an array") as? [String]) == ["not an array"]
|
|
91
|
+
}
|
|
92
|
+
it("throws CastingException") {
|
|
93
|
+
expect { try (~[String].self).cast(84) }.to(
|
|
94
|
+
throwError(errorType: Conversions.CastingException<String>.self)
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
describe("wraps") {
|
|
99
|
+
it("is true") {
|
|
100
|
+
expect(~[Double].self ~> [Double].self) == true
|
|
101
|
+
expect(~[[String]].self ~> [[String]].self) == true
|
|
102
|
+
expect(~[CGPoint].self ~> [CGPoint].self) == true
|
|
103
|
+
}
|
|
104
|
+
it("is false") {
|
|
105
|
+
expect(~[String].self !~> [Int].self) == true
|
|
106
|
+
expect(~[Promise].self !~> Promise.self) == true
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
describe("equals") {
|
|
110
|
+
it("is true") {
|
|
111
|
+
expect(~[String].self == ~[String].self) == true
|
|
112
|
+
expect(~[CGSize].self == ~[CGSize].self) == true
|
|
113
|
+
expect(~[[[Double]]].self == ~[[[Double]]].self) == true
|
|
114
|
+
}
|
|
115
|
+
it("is false") {
|
|
116
|
+
expect(~[Int].self != ~[Double].self) == true
|
|
117
|
+
expect(~[[String]].self != ~[String].self) == true
|
|
118
|
+
expect(~[URL].self != ~[String].self) == true
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// MARK: - DynamicConvertibleType
|
|
124
|
+
|
|
125
|
+
describe("DynamicConvertibleType") {
|
|
126
|
+
it("is created") {
|
|
127
|
+
expect(~CGPoint.self).to(beAKindOf(DynamicConvertibleType.self))
|
|
128
|
+
expect(~CGRect.self).to(beAKindOf(DynamicConvertibleType.self))
|
|
129
|
+
expect(~CGColor.self).to(beAKindOf(DynamicConvertibleType.self))
|
|
130
|
+
expect(~URL.self).to(beAKindOf(DynamicConvertibleType.self))
|
|
131
|
+
}
|
|
132
|
+
describe("casts") {
|
|
133
|
+
it("succeeds") {
|
|
134
|
+
expect(try (~CGPoint.self).cast([2.1, 3.7]) as? CGPoint) == CGPoint(x: 2.1, y: 3.7)
|
|
135
|
+
expect(try (~CGVector.self).cast(["dx": 0.8, "dy": 4.1]) as? CGVector) == CGVector(dx: 0.8, dy: 4.1)
|
|
136
|
+
expect(try (~URL.self).cast("/test/path") as? URL) == URL(fileURLWithPath: "/test/path")
|
|
137
|
+
}
|
|
138
|
+
it("throws ConvertingException") {
|
|
139
|
+
expect { try (~CGRect.self).cast("not a rect") as? CGRect }.to(
|
|
140
|
+
throwError(errorType: Conversions.ConvertingException<CGRect>.self)
|
|
141
|
+
)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
describe("wraps") {
|
|
145
|
+
it("is true") {
|
|
146
|
+
expect(~CGRect.self ~> CGRect.self) == true
|
|
147
|
+
expect(~CGColor.self ~> CGColor.self) == true
|
|
148
|
+
expect(~URL.self ~> URL.self) == true
|
|
149
|
+
}
|
|
150
|
+
it("is false") {
|
|
151
|
+
expect(~CGRect.self !~> Double.self) == true
|
|
152
|
+
expect(~CGColor.self !~> CGRect.self) == true
|
|
153
|
+
expect(~URL.self !~> String.self) == true
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
describe("equals") {
|
|
157
|
+
it("is true") {
|
|
158
|
+
expect(~CGSize.self == ~CGSize.self) == true
|
|
159
|
+
expect(~URL.self == ~URL.self) == true
|
|
160
|
+
expect(~UIColor.self == ~UIColor.self) == true
|
|
161
|
+
}
|
|
162
|
+
it("is false") {
|
|
163
|
+
expect(~CGSize.self != ~CGRect.self) == true
|
|
164
|
+
expect(~CGPoint.self != ~CGVector.self) == true
|
|
165
|
+
expect(~URL.self != ~String.self) == true
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// MARK: - DynamicEnumType
|
|
171
|
+
|
|
172
|
+
describe("DynamicEnumType") {
|
|
173
|
+
enum StringTestEnum: String, EnumArgument {
|
|
174
|
+
case hello
|
|
175
|
+
case expo
|
|
176
|
+
}
|
|
177
|
+
enum IntTestEnum: Int, EnumArgument {
|
|
178
|
+
case negative = -1
|
|
179
|
+
case positive = 1
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
it("is created") {
|
|
183
|
+
expect(~StringTestEnum.self).to(beAKindOf(DynamicEnumType.self))
|
|
184
|
+
expect(~IntTestEnum.self).to(beAKindOf(DynamicEnumType.self))
|
|
185
|
+
}
|
|
186
|
+
describe("casts") {
|
|
187
|
+
it("succeeds") {
|
|
188
|
+
expect(try (~StringTestEnum.self).cast("expo") as? StringTestEnum) == .expo
|
|
189
|
+
expect(try (~IntTestEnum.self).cast(1) as? IntTestEnum) == .positive
|
|
190
|
+
}
|
|
191
|
+
it("throws EnumNoSuchValueException") {
|
|
192
|
+
expect { try (~StringTestEnum.self).cast("react native") as? StringTestEnum }.to(
|
|
193
|
+
throwError(errorType: EnumNoSuchValueException.self)
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
it("throws EnumCastingException") {
|
|
197
|
+
expect { try (~IntTestEnum.self).cast(true) as? StringTestEnum }.to(
|
|
198
|
+
throwError(errorType: EnumCastingException.self)
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
describe("wraps") {
|
|
203
|
+
it("is true") {
|
|
204
|
+
expect(~StringTestEnum.self ~> StringTestEnum.self) == true
|
|
205
|
+
expect(~IntTestEnum.self ~> IntTestEnum.self) == true
|
|
206
|
+
}
|
|
207
|
+
it("is false") {
|
|
208
|
+
expect(~StringTestEnum.self !~> IntTestEnum.self) == true
|
|
209
|
+
expect(~IntTestEnum.self !~> StringTestEnum.self) == true
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
describe("equals") {
|
|
214
|
+
it("is true") {
|
|
215
|
+
expect(~StringTestEnum.self == ~StringTestEnum.self) == true
|
|
216
|
+
expect(~IntTestEnum.self == ~IntTestEnum.self) == true
|
|
217
|
+
}
|
|
218
|
+
it("is false") {
|
|
219
|
+
expect(~StringTestEnum.self != ~IntTestEnum.self) == true
|
|
220
|
+
expect(~IntTestEnum.self != ~StringTestEnum.self) == true
|
|
221
|
+
expect(~StringTestEnum.self != ~Double.self) == true
|
|
222
|
+
expect(~IntTestEnum.self != ~Int.self) == true
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// MARK: - DynamicOptionalType
|
|
228
|
+
|
|
229
|
+
describe("DynamicOptionalType") {
|
|
230
|
+
it("is created") {
|
|
231
|
+
expect(~String?.self).to(beAKindOf(DynamicOptionalType.self))
|
|
232
|
+
expect(~[Double]?.self).to(beAKindOf(DynamicOptionalType.self))
|
|
233
|
+
expect(~[Int?]?.self).to(beAKindOf(DynamicOptionalType.self))
|
|
234
|
+
}
|
|
235
|
+
describe("casts") {
|
|
236
|
+
it("succeeds") {
|
|
237
|
+
expect(try (~String?.self).cast("expo") as? String) == "expo"
|
|
238
|
+
expect(try (~Bool?.self).cast(false) as? Bool) == false
|
|
239
|
+
}
|
|
240
|
+
it("succeeds with nil") {
|
|
241
|
+
let value: Double? = nil
|
|
242
|
+
let result = try (~Double?.self).cast(value as Any)
|
|
243
|
+
|
|
244
|
+
expect(result).to(beAKindOf(Double?.self))
|
|
245
|
+
|
|
246
|
+
// Since this `nil` is in fact of non-optional `Any` type, under the hood it's described as `Optional` enum.
|
|
247
|
+
// Simply checking `result == nil` does NOT work here, see `Optional.isNil` extension implementation.
|
|
248
|
+
expect(Optional.isNil(result)) == true
|
|
249
|
+
}
|
|
250
|
+
it("succeeds with NSNull") {
|
|
251
|
+
let value = NSNull()
|
|
252
|
+
let result = try (~Double?.self).cast(value as Any)
|
|
253
|
+
expect(result).to(beAKindOf(Double?.self))
|
|
254
|
+
expect(Optional.isNil(result)) == true
|
|
255
|
+
}
|
|
256
|
+
it("throws CastingException") {
|
|
257
|
+
expect { try (~Double?.self).cast("a string") as? Double }.to(
|
|
258
|
+
throwError(errorType: Conversions.CastingException<Double>.self)
|
|
259
|
+
)
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
describe("wraps") {
|
|
263
|
+
it("is true") {
|
|
264
|
+
expect(~Double?.self ~> Double?.self) == true
|
|
265
|
+
expect(~String?.self ~> String?.self) == true
|
|
266
|
+
expect(~URL?.self ~> URL?.self) == true
|
|
267
|
+
}
|
|
268
|
+
it("is false") {
|
|
269
|
+
expect(~Double?.self !~> Double.self) == true
|
|
270
|
+
expect(~[URL]?.self !~> URL.self) == true
|
|
271
|
+
expect(~[String]?.self !~> [String?].self) == true
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
describe("equals") {
|
|
275
|
+
it("is true") {
|
|
276
|
+
expect(~Int?.self == ~Int?.self) == true
|
|
277
|
+
expect(~ExpoSpec.self == ~ExpoSpec.self) == true
|
|
278
|
+
}
|
|
279
|
+
it("is false") {
|
|
280
|
+
expect(~Double?.self != ~Double.self) == true
|
|
281
|
+
expect(~Int?.self != ~Double?.self) == true
|
|
282
|
+
expect(~[Bool]?.self != ~[Bool].self) == true
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// MARK: - DynamicSharedObjectType
|
|
288
|
+
|
|
289
|
+
describe("DynamicSharedObjectType") {
|
|
290
|
+
class TestSharedObject: SharedObject {}
|
|
291
|
+
|
|
292
|
+
it("is created") {
|
|
293
|
+
expect(~TestSharedObject.self).to(beAKindOf(DynamicSharedObjectType.self))
|
|
294
|
+
}
|
|
295
|
+
describe("casts") {
|
|
296
|
+
it("succeeds") {
|
|
297
|
+
let appContext = AppContext.create()
|
|
298
|
+
let nativeObject = TestSharedObject()
|
|
299
|
+
let jsObjectValue = try appContext.runtime!.eval("({})")
|
|
300
|
+
|
|
301
|
+
SharedObjectRegistry.add(native: nativeObject, javaScript: try jsObjectValue.asObject())
|
|
302
|
+
|
|
303
|
+
// `DynamicSharedObjectType` only supports casting
|
|
304
|
+
// from `JavaScriptValue`, but not from `JavaScriptObject`.
|
|
305
|
+
expect(try (~TestSharedObject.self).cast(jsObjectValue) as? TestSharedObject) === nativeObject
|
|
306
|
+
}
|
|
307
|
+
it("throws NativeSharedObjectNotFoundException") {
|
|
308
|
+
expect { try (~TestSharedObject.self).cast("a string") as? TestSharedObject }.to(
|
|
309
|
+
throwError(errorType: NativeSharedObjectNotFoundException.self)
|
|
310
|
+
)
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
describe("wraps") {
|
|
314
|
+
it("is true") {
|
|
315
|
+
expect(~TestSharedObject.self ~> TestSharedObject.self) == true
|
|
316
|
+
}
|
|
317
|
+
it("is false") {
|
|
318
|
+
expect(~TestSharedObject.self !~> SharedObject.self) == true
|
|
319
|
+
expect(~TestSharedObject.self !~> String?.self) == true
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
describe("equals") {
|
|
323
|
+
it("is true") {
|
|
324
|
+
expect(~TestSharedObject.self == ~TestSharedObject.self) == true
|
|
325
|
+
expect(~TestSharedObject?.self == ~TestSharedObject?.self) == true
|
|
326
|
+
expect(~[TestSharedObject].self == ~[TestSharedObject].self) == true
|
|
327
|
+
}
|
|
328
|
+
it("is false") {
|
|
329
|
+
expect(~TestSharedObject.self != ~TestSharedObject?.self) == true
|
|
330
|
+
expect(~TestSharedObject.self != ~[String: Any].self) == true
|
|
331
|
+
expect(~TestSharedObject.self != ~[TestSharedObject].self) == true
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import ExpoModulesTestCore
|
|
4
|
+
|
|
5
|
+
@testable import ExpoModulesCore
|
|
6
|
+
|
|
7
|
+
final class EnumArgumentSpec: ExpoSpec {
|
|
8
|
+
override func spec() {
|
|
9
|
+
describe("static createFromRawValue") {
|
|
10
|
+
it("succeeds") {
|
|
11
|
+
expect(try Position.create(fromRawValue: "top")) == .top
|
|
12
|
+
expect(try Position.create(fromRawValue: "right")) == .right
|
|
13
|
+
}
|
|
14
|
+
it("throws EnumNoSuchValueException") {
|
|
15
|
+
expect { try Position.create(fromRawValue: "top-right") }.to(
|
|
16
|
+
throwError(errorType: EnumNoSuchValueException.self)
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
it("throws EnumCastingException") {
|
|
20
|
+
expect { try Position.create(fromRawValue: 4729) }.to(
|
|
21
|
+
throwError(errorType: EnumCastingException.self)
|
|
22
|
+
)
|
|
23
|
+
expect { try Position.create(fromRawValue: ["left"]) }.to(
|
|
24
|
+
throwError(errorType: EnumCastingException.self)
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
describe("anyRawValue") {
|
|
30
|
+
it("returns type-erased raw value") {
|
|
31
|
+
expect(Position.left.anyRawValue as? String) == Position.left.rawValue
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
describe("allRawValues") {
|
|
36
|
+
it("returns all raw values") {
|
|
37
|
+
expect(Position.allRawValues as? [String]) == ["top", "right", "bottom", "left"]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
fileprivate enum Position: String, EnumArgument {
|
|
44
|
+
case top
|
|
45
|
+
case right
|
|
46
|
+
case bottom
|
|
47
|
+
case left
|
|
48
|
+
}
|
|
@@ -7,24 +7,27 @@ import ExpoModulesTestCore
|
|
|
7
7
|
class ExpoModulesSpec: ExpoSpec {
|
|
8
8
|
override func spec() {
|
|
9
9
|
let appContext = AppContext.create()
|
|
10
|
-
let interopBridge = SwiftInteropBridge(appContext: appContext)
|
|
11
10
|
let runtime = appContext.runtime
|
|
12
11
|
let testModuleName = "TestModule"
|
|
13
12
|
let testFunctionName = "testFunction"
|
|
13
|
+
let throwingFunctionName = "throwingFunction"
|
|
14
|
+
let exceptionToThrow = Exception(name: "Some exception", description: "Exception description")
|
|
14
15
|
let constantsDict: [String: Any] = [
|
|
15
16
|
"expo": "is cool",
|
|
16
17
|
"sdk": 45,
|
|
17
18
|
]
|
|
18
19
|
|
|
19
20
|
beforeSuite {
|
|
20
|
-
try! appContext.installExpoModulesHostObject(interopBridge)
|
|
21
|
-
|
|
22
21
|
appContext.moduleRegistry.register(holder: mockModuleHolder(appContext) {
|
|
23
22
|
Name(testModuleName)
|
|
24
23
|
|
|
25
24
|
Constants(constantsDict)
|
|
26
25
|
|
|
27
26
|
Function(testFunctionName) { Double.pi }
|
|
27
|
+
|
|
28
|
+
Function(throwingFunctionName) {
|
|
29
|
+
throw exceptionToThrow
|
|
30
|
+
}
|
|
28
31
|
})
|
|
29
32
|
}
|
|
30
33
|
|
|
@@ -70,6 +73,17 @@ class ExpoModulesSpec: ExpoSpec {
|
|
|
70
73
|
it("calls function") {
|
|
71
74
|
expect(try! runtime?.eval("ExpoModules.TestModule.\(testFunctionName)()").asDouble()) == Double.pi
|
|
72
75
|
}
|
|
76
|
+
|
|
77
|
+
it("throws from sync function") {
|
|
78
|
+
// Invoke the throwing function and return the error (eval shouldn't rethrow here)
|
|
79
|
+
let error = try! runtime!.eval("try { ExpoModules.TestModule.\(throwingFunctionName)() } catch (error) { error }").asObject()
|
|
80
|
+
|
|
81
|
+
// We just check if it contains the description — they won't be equal for the following reasons:
|
|
82
|
+
// - the `exceptionToThrow` is just the root cause, in fact it returns `FunctionCallException`
|
|
83
|
+
// - the debug description contains the file and line number, so it's hard to mock the `FunctionCallException`
|
|
84
|
+
// Ideally if we have a better way (error codes/names) to identify them w/o relying on the description that may change over time.
|
|
85
|
+
expect(error.getProperty("message").getString()).to(contain(exceptionToThrow.debugDescription))
|
|
86
|
+
}
|
|
73
87
|
}
|
|
74
88
|
}
|
|
75
89
|
}
|