expo-modules-core 0.6.4 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/README.md +1 -1
- package/android/build.gradle +5 -5
- package/android/src/main/java/expo/modules/kotlin/AppContext.kt +11 -1
- package/android/src/main/java/expo/modules/kotlin/DynamicExtenstions.kt +5 -3
- package/android/src/main/java/expo/modules/kotlin/KPromiseWrapper.kt +8 -2
- package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +13 -4
- package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +7 -6
- package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +6 -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 +28 -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/exception/CodedException.kt +68 -8
- package/android/src/main/java/expo/modules/kotlin/exception/ExceptionDecorator.kt +11 -0
- package/android/src/main/java/expo/modules/kotlin/methods/AnyMethod.kt +13 -14
- package/android/src/main/java/expo/modules/kotlin/modules/DefinitionMarker.kt +4 -0
- package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +3 -2
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +44 -4
- package/android/src/main/java/expo/modules/kotlin/records/Record.kt +39 -0
- package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +14 -7
- package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +11 -5
- 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/views/CallbacksDefinition.kt +3 -0
- package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +22 -0
- package/android/src/main/java/expo/modules/kotlin/views/SimpleViewManagerWrapper.kt +22 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +27 -2
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +29 -1
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +59 -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 -0
- package/build/NativeModulesProxy.native.d.ts.map +1 -0
- package/build/NativeModulesProxy.types.d.ts +1 -0
- package/build/NativeModulesProxy.types.d.ts.map +1 -0
- 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/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/ExpoAppDelegate.swift +18 -10
- package/ios/JSI/ExpoModulesHostObject.h +33 -0
- package/ios/JSI/ExpoModulesHostObject.mm +40 -0
- package/ios/JSI/ExpoModulesProxySpec.h +4 -0
- package/ios/JSI/ExpoModulesProxySpec.mm +1 -3
- package/ios/JSI/JSIConversions.h +2 -0
- package/ios/JSI/JSIConversions.mm +9 -0
- package/ios/JSI/JSIInstaller.h +10 -0
- package/ios/JSI/JSIInstaller.mm +14 -2
- package/ios/JSI/JavaScriptObject.h +60 -0
- package/ios/JSI/JavaScriptObject.mm +93 -0
- package/ios/JSI/JavaScriptRuntime.h +54 -0
- package/ios/JSI/JavaScriptRuntime.mm +102 -0
- package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +2 -12
- package/ios/NativeModulesProxy/EXComponentDataCompatibleWrapper.h +16 -0
- package/ios/NativeModulesProxy/EXComponentDataCompatibleWrapper.m +28 -0
- package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +90 -66
- package/ios/RCTComponentData+Privates.h +12 -0
- package/ios/ReactDelegates/ExpoReactDelegate.swift +2 -2
- package/ios/ReactDelegates/ExpoReactDelegateHandler.swift +3 -3
- package/ios/ReactDelegates/ModulePriorities.swift +1 -1
- package/ios/Swift/AppContext.swift +38 -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/ConcreteFunction.swift +37 -16
- package/ios/Swift/JavaScriptUtils.swift +43 -0
- package/ios/Swift/ModuleHolder.swift +53 -14
- 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 +0 -1
- package/ios/Swift/Objects/ObjectDefinition.swift +30 -0
- package/ios/Swift/Objects/ObjectDefinitionComponents.swift +208 -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 +39 -10
- package/ios/Swift/Views/AnyViewProp.swift +1 -1
- package/ios/Swift/Views/ComponentData.swift +95 -0
- package/ios/Swift/Views/ConcreteViewProp.swift +6 -8
- 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/Tests/ArgumentTypeSpec.swift +3 -4
- package/ios/Tests/ConstantsSpec.swift +4 -4
- package/ios/Tests/ConvertiblesSpec.swift +33 -33
- package/ios/Tests/ExceptionsSpec.swift +112 -0
- package/ios/Tests/FunctionSpec.swift +20 -22
- package/ios/Tests/FunctionWithConvertiblesSpec.swift +2 -2
- package/ios/Tests/Mocks/ModuleMocks.swift +1 -1
- package/ios/Tests/Mocks/ModulesProviderMock.swift +0 -1
- package/ios/Tests/ModuleEventListenersSpec.swift +1 -1
- package/ios/Tests/RecordSpec.swift +7 -17
- package/package.json +3 -3
- 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
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/// Here we implement the components exclusive for view managers.
|
|
2
|
+
|
|
3
|
+
// MARK: View factory
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
Defines the factory creating a native view when the module is used as a view.
|
|
7
|
+
*/
|
|
8
|
+
public func view(_ closure: @escaping () -> UIView) -> ViewManagerDefinitionComponent {
|
|
9
|
+
return ViewFactory(closure)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// MARK: Props
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
Creates a view prop that defines its name and setter.
|
|
16
|
+
*/
|
|
17
|
+
public func prop<ViewType: UIView, PropType: AnyArgument>(
|
|
18
|
+
_ name: String,
|
|
19
|
+
_ setter: @escaping (ViewType, PropType) -> Void
|
|
20
|
+
) -> ViewManagerDefinitionComponent {
|
|
21
|
+
return ConcreteViewProp(
|
|
22
|
+
name: name,
|
|
23
|
+
propType: ArgumentType(PropType.self),
|
|
24
|
+
setter: setter
|
|
25
|
+
)
|
|
26
|
+
}
|
|
@@ -93,7 +93,7 @@ public final class ViewModuleWrapper: RCTViewManager, DynamicModuleWrapperProtoc
|
|
|
93
93
|
*/
|
|
94
94
|
@objc
|
|
95
95
|
public class func propConfig_proxiedProperties() -> [String] {
|
|
96
|
-
return ["NSDictionary", "__custom__"]
|
|
96
|
+
return ["NSDictionary", "__custom__"]
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
/**
|
|
@@ -126,7 +126,7 @@ public final class ViewModuleWrapper: RCTViewManager, DynamicModuleWrapperProtoc
|
|
|
126
126
|
let prefixedViewName = "ViewManagerAdapter_\(module.name())"
|
|
127
127
|
|
|
128
128
|
return prefixedViewName.withCString { viewNamePtr in
|
|
129
|
-
// Create a new
|
|
129
|
+
// Create a new class that inherits from `ViewModuleWrapper`. The class name passed here, doesn't work for Swift classes,
|
|
130
130
|
// so we also have to override `moduleName` class method.
|
|
131
131
|
let wrapperClass: AnyClass? = objc_allocateClassPair(ViewModuleWrapper.self, viewNamePtr, 0)
|
|
132
132
|
|
|
@@ -141,3 +141,6 @@ public final class ViewModuleWrapper: RCTViewManager, DynamicModuleWrapperProtoc
|
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
|
+
|
|
145
|
+
// The direct event implementation can be cached and lazy-loaded (global and static variables are lazy by default in Swift).
|
|
146
|
+
let directEventBlockImplementation = imp_implementationWithBlock({ ["RCTDirectEventBlock"] } as @convention(block) () -> [String])
|
|
@@ -7,7 +7,6 @@ import Nimble
|
|
|
7
7
|
|
|
8
8
|
class ArgumentTypeSpec: QuickSpec {
|
|
9
9
|
override func spec() {
|
|
10
|
-
|
|
11
10
|
it("casts primitives") {
|
|
12
11
|
let type = ArgumentType(Int.self)
|
|
13
12
|
let value = 123
|
|
@@ -34,7 +33,7 @@ class ArgumentTypeSpec: QuickSpec {
|
|
|
34
33
|
let value: Double? = nil
|
|
35
34
|
let anyValue = value as Any
|
|
36
35
|
|
|
37
|
-
expect { try type.cast(anyValue) }.to(throwError(errorType: Conversions.
|
|
36
|
+
expect { try type.cast(anyValue) }.to(throwError(errorType: Conversions.NullCastException<Double>.self))
|
|
38
37
|
}
|
|
39
38
|
|
|
40
39
|
it("casts arrays") {
|
|
@@ -104,7 +103,7 @@ class ArgumentTypeSpec: QuickSpec {
|
|
|
104
103
|
|
|
105
104
|
// "841" is not a raw value of any `IntTestEnum` case
|
|
106
105
|
expect { try type.cast("string instead of int") }.to(throwError {
|
|
107
|
-
expect($0).to(beAKindOf(
|
|
106
|
+
expect($0).to(beAKindOf(EnumCastingException.self))
|
|
108
107
|
})
|
|
109
108
|
}
|
|
110
109
|
|
|
@@ -113,7 +112,7 @@ class ArgumentTypeSpec: QuickSpec {
|
|
|
113
112
|
|
|
114
113
|
// "841" is not a raw value of any `IntTestEnum` case
|
|
115
114
|
expect { try type.cast(841) }.to(throwError {
|
|
116
|
-
expect($0).to(beAKindOf(
|
|
115
|
+
expect($0).to(beAKindOf(EnumNoSuchValueException.self))
|
|
117
116
|
})
|
|
118
117
|
}
|
|
119
118
|
|
|
@@ -9,7 +9,7 @@ class ConstantsSpec: QuickSpec {
|
|
|
9
9
|
|
|
10
10
|
it("takes closure resolving to dictionary") {
|
|
11
11
|
let holder = mockModuleHolder(appContext) {
|
|
12
|
-
|
|
12
|
+
constants {
|
|
13
13
|
return ["test": 123]
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -18,15 +18,15 @@ class ConstantsSpec: QuickSpec {
|
|
|
18
18
|
|
|
19
19
|
it("takes the dictionary") {
|
|
20
20
|
let holder = mockModuleHolder(appContext) {
|
|
21
|
-
|
|
21
|
+
constants(["test": 123])
|
|
22
22
|
}
|
|
23
23
|
expect(holder.getConstants()["test"] as? Int) == 123
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
it("merges multiple constants definitions") {
|
|
27
27
|
let holder = mockModuleHolder(appContext) {
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
constants(["test": 456, "test2": 789])
|
|
29
|
+
constants(["test": 123])
|
|
30
30
|
}
|
|
31
31
|
let consts = holder.getConstants()
|
|
32
32
|
expect(consts["test"] as? Int) == 123
|
|
@@ -37,7 +37,7 @@ class ConvertiblesSpec: QuickSpec {
|
|
|
37
37
|
|
|
38
38
|
it("throws when no string") {
|
|
39
39
|
expect { try URL.convert(from: 29.5) }.to(
|
|
40
|
-
throwError(errorType: Conversions.
|
|
40
|
+
throwError(errorType: Conversions.ConvertingException<URL>.self)
|
|
41
41
|
)
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -61,22 +61,22 @@ class ConvertiblesSpec: QuickSpec {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
it("throws when array size is unexpected") { // different than two
|
|
64
|
-
expect { try CGPoint.convert(from: []) }.to(throwError(errorType: Conversions.
|
|
65
|
-
expect { try CGPoint.convert(from: [x]) }.to(throwError(errorType: Conversions.
|
|
66
|
-
expect { try CGPoint.convert(from: [x, y, x]) }.to(throwError(errorType: Conversions.
|
|
64
|
+
expect { try CGPoint.convert(from: []) }.to(throwError(errorType: Conversions.ConvertingException<CGPoint>.self))
|
|
65
|
+
expect { try CGPoint.convert(from: [x]) }.to(throwError(errorType: Conversions.ConvertingException<CGPoint>.self))
|
|
66
|
+
expect { try CGPoint.convert(from: [x, y, x]) }.to(throwError(errorType: Conversions.ConvertingException<CGPoint>.self))
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
it("throws when dict is missing some keys") {
|
|
70
70
|
expect { try CGPoint.convert(from: ["test": x]) }.to(throwError {
|
|
71
|
-
expect($0).to(beAKindOf(Conversions.
|
|
72
|
-
expect(($0 as! CodedError).description) == Conversions.
|
|
71
|
+
expect($0).to(beAKindOf(Conversions.MissingKeysException<Double>.self))
|
|
72
|
+
expect(($0 as! CodedError).description) == Conversions.MissingKeysException<Double>(["x", "y"]).description
|
|
73
73
|
})
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
it("throws when dict has uncastable keys") {
|
|
77
77
|
expect { try CGPoint.convert(from: ["x": x, "y": "string"]) }.to(throwError {
|
|
78
|
-
expect($0).to(beAKindOf(Conversions.
|
|
79
|
-
expect(($0 as! CodedError).description) == Conversions.
|
|
78
|
+
expect($0).to(beAKindOf(Conversions.CastingValuesException<Double>.self))
|
|
79
|
+
expect(($0 as! CodedError).description) == Conversions.CastingValuesException<Double>(["y"]).description
|
|
80
80
|
})
|
|
81
81
|
}
|
|
82
82
|
}
|
|
@@ -100,22 +100,22 @@ class ConvertiblesSpec: QuickSpec {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
it("throws when array size is unexpected") { // different than two
|
|
103
|
-
expect { try CGSize.convert(from: []) }.to(throwError(errorType: Conversions.
|
|
104
|
-
expect { try CGSize.convert(from: [width]) }.to(throwError(errorType: Conversions.
|
|
105
|
-
expect { try CGSize.convert(from: [width, height, width]) }.to(throwError(errorType: Conversions.
|
|
103
|
+
expect { try CGSize.convert(from: []) }.to(throwError(errorType: Conversions.ConvertingException<CGSize>.self))
|
|
104
|
+
expect { try CGSize.convert(from: [width]) }.to(throwError(errorType: Conversions.ConvertingException<CGSize>.self))
|
|
105
|
+
expect { try CGSize.convert(from: [width, height, width]) }.to(throwError(errorType: Conversions.ConvertingException<CGSize>.self))
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
it("throws when dict is missing some keys") {
|
|
109
109
|
expect { try CGSize.convert(from: ["width": width]) }.to(throwError {
|
|
110
|
-
expect($0).to(beAKindOf(Conversions.
|
|
111
|
-
expect(($0 as! CodedError).description) == Conversions.
|
|
110
|
+
expect($0).to(beAKindOf(Conversions.MissingKeysException<Double>.self))
|
|
111
|
+
expect(($0 as! CodedError).description) == Conversions.MissingKeysException<Double>(["height"]).description
|
|
112
112
|
})
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
it("throws when dict has uncastable keys") {
|
|
116
116
|
expect { try CGSize.convert(from: ["width": "test", "height": height]) }.to(throwError {
|
|
117
|
-
expect($0).to(beAKindOf(Conversions.
|
|
118
|
-
expect(($0 as! CodedError).description) == Conversions.
|
|
117
|
+
expect($0).to(beAKindOf(Conversions.CastingValuesException<Double>.self))
|
|
118
|
+
expect(($0 as! CodedError).description) == Conversions.CastingValuesException<Double>(["width"]).description
|
|
119
119
|
})
|
|
120
120
|
}
|
|
121
121
|
}
|
|
@@ -139,22 +139,22 @@ class ConvertiblesSpec: QuickSpec {
|
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
it("throws when array size is unexpected") { // different than two
|
|
142
|
-
expect { try CGVector.convert(from: []) }.to(throwError(errorType: Conversions.
|
|
143
|
-
expect { try CGVector.convert(from: [dx]) }.to(throwError(errorType: Conversions.
|
|
144
|
-
expect { try CGVector.convert(from: [dx, dy, dx]) }.to(throwError(errorType: Conversions.
|
|
142
|
+
expect { try CGVector.convert(from: []) }.to(throwError(errorType: Conversions.ConvertingException<CGVector>.self))
|
|
143
|
+
expect { try CGVector.convert(from: [dx]) }.to(throwError(errorType: Conversions.ConvertingException<CGVector>.self))
|
|
144
|
+
expect { try CGVector.convert(from: [dx, dy, dx]) }.to(throwError(errorType: Conversions.ConvertingException<CGVector>.self))
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
it("throws when dict is missing some keys") {
|
|
148
148
|
expect { try CGVector.convert(from: ["dx": dx]) }.to(throwError {
|
|
149
|
-
expect($0).to(beAKindOf(Conversions.
|
|
150
|
-
expect(($0 as! CodedError).description) == Conversions.
|
|
149
|
+
expect($0).to(beAKindOf(Conversions.MissingKeysException<Double>.self))
|
|
150
|
+
expect(($0 as! CodedError).description) == Conversions.MissingKeysException<Double>(["dy"]).description
|
|
151
151
|
})
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
it("throws when dict has uncastable keys") {
|
|
155
155
|
expect { try CGVector.convert(from: ["dx": "dx", "dy": dy]) }.to(throwError {
|
|
156
|
-
expect($0).to(beAKindOf(Conversions.
|
|
157
|
-
expect(($0 as! CodedError).description) == Conversions.
|
|
156
|
+
expect($0).to(beAKindOf(Conversions.CastingValuesException<Double>.self))
|
|
157
|
+
expect(($0 as! CodedError).description) == Conversions.CastingValuesException<Double>(["dx"]).description
|
|
158
158
|
})
|
|
159
159
|
}
|
|
160
160
|
}
|
|
@@ -184,22 +184,22 @@ class ConvertiblesSpec: QuickSpec {
|
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
it("throws when array size is unexpected") { // different than four
|
|
187
|
-
expect { try CGRect.convert(from: [x]) }.to(throwError(errorType: Conversions.
|
|
188
|
-
expect { try CGRect.convert(from: [x, y]) }.to(throwError(errorType: Conversions.
|
|
189
|
-
expect { try CGRect.convert(from: [x, y, width, height, y]) }.to(throwError(errorType: Conversions.
|
|
187
|
+
expect { try CGRect.convert(from: [x]) }.to(throwError(errorType: Conversions.ConvertingException<CGRect>.self))
|
|
188
|
+
expect { try CGRect.convert(from: [x, y]) }.to(throwError(errorType: Conversions.ConvertingException<CGRect>.self))
|
|
189
|
+
expect { try CGRect.convert(from: [x, y, width, height, y]) }.to(throwError(errorType: Conversions.ConvertingException<CGRect>.self))
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
it("throws when dict is missing some keys") {
|
|
193
193
|
expect { try CGRect.convert(from: ["x": x]) }.to(throwError {
|
|
194
|
-
expect($0).to(beAKindOf(Conversions.
|
|
195
|
-
expect(($0 as! CodedError).description) == Conversions.
|
|
194
|
+
expect($0).to(beAKindOf(Conversions.MissingKeysException<Double>.self))
|
|
195
|
+
expect(($0 as! CodedError).description) == Conversions.MissingKeysException<Double>(["y", "width", "height"]).description
|
|
196
196
|
})
|
|
197
197
|
}
|
|
198
198
|
|
|
199
199
|
it("throws when dict has uncastable keys") {
|
|
200
200
|
expect { try CGRect.convert(from: ["x": x, "y": nil, "width": width, "height": "\(height)"]) }.to(throwError {
|
|
201
|
-
expect($0).to(beAKindOf(Conversions.
|
|
202
|
-
expect(($0 as! CodedError).description) == Conversions.
|
|
201
|
+
expect($0).to(beAKindOf(Conversions.CastingValuesException<Double>.self))
|
|
202
|
+
expect(($0 as! CodedError).description) == Conversions.CastingValuesException<Double>(["y", "height"]).description
|
|
203
203
|
})
|
|
204
204
|
}
|
|
205
205
|
}
|
|
@@ -213,8 +213,8 @@ class ConvertiblesSpec: QuickSpec {
|
|
|
213
213
|
}
|
|
214
214
|
func testInvalidHexColor(_ hex: String) {
|
|
215
215
|
expect { try CGColor.convert(from: hex) }.to(throwError {
|
|
216
|
-
expect($0).to(beAKindOf(Conversions.
|
|
217
|
-
expect(($0 as! CodedError).description) == Conversions.
|
|
216
|
+
expect($0).to(beAKindOf(Conversions.InvalidHexColorException.self))
|
|
217
|
+
expect(($0 as! CodedError).description) == Conversions.InvalidHexColorException(hex).description
|
|
218
218
|
})
|
|
219
219
|
}
|
|
220
220
|
|
|
@@ -256,8 +256,8 @@ class ConvertiblesSpec: QuickSpec {
|
|
|
256
256
|
it("throws when int overflows") {
|
|
257
257
|
let hex = 0xBBAA88FF2
|
|
258
258
|
expect { try CGColor.convert(from: hex) }.to(throwError {
|
|
259
|
-
expect($0).to(beAKindOf(Conversions.
|
|
260
|
-
expect(($0 as! CodedError).description) == Conversions.
|
|
259
|
+
expect($0).to(beAKindOf(Conversions.HexColorOverflowException.self))
|
|
260
|
+
expect(($0 as! CodedError).description) == Conversions.HexColorOverflowException(UInt64(hex)).description
|
|
261
261
|
})
|
|
262
262
|
}
|
|
263
263
|
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import Quick
|
|
4
|
+
import Nimble
|
|
5
|
+
|
|
6
|
+
@testable import ExpoModulesCore
|
|
7
|
+
|
|
8
|
+
final class ExceptionsSpec: QuickSpec {
|
|
9
|
+
override func spec() {
|
|
10
|
+
it("has name") {
|
|
11
|
+
let error = TestException()
|
|
12
|
+
expect(error.name) == "TestException"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
it("has code") {
|
|
16
|
+
let error = TestException()
|
|
17
|
+
expect(error.code) == "ERR_TEST"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
it("has reason") {
|
|
21
|
+
let error = TestException()
|
|
22
|
+
expect(error.reason) == "This is the test exception"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
it("can be chained once") {
|
|
26
|
+
func throwable() throws {
|
|
27
|
+
do {
|
|
28
|
+
throw TestExceptionCause()
|
|
29
|
+
} catch {
|
|
30
|
+
throw TestException().causedBy(error)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
expect { try throwable() }.to(throwError { error in
|
|
34
|
+
testChainedExceptionTypes(error: error, types: [TestException.self, TestExceptionCause.self])
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
it("can be chained twice") {
|
|
39
|
+
func throwable() throws {
|
|
40
|
+
do {
|
|
41
|
+
do {
|
|
42
|
+
throw TestExceptionCause()
|
|
43
|
+
} catch {
|
|
44
|
+
throw TestExceptionCause().causedBy(error)
|
|
45
|
+
}
|
|
46
|
+
} catch {
|
|
47
|
+
throw TestException().causedBy(error)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
expect { try throwable() }.to(throwError { error in
|
|
51
|
+
testChainedExceptionTypes(error: error, types: [TestException.self, TestExceptionCause.self, TestExceptionCause.self])
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
it("includes cause description") {
|
|
56
|
+
func throwable() throws {
|
|
57
|
+
do {
|
|
58
|
+
throw TestExceptionCause()
|
|
59
|
+
} catch {
|
|
60
|
+
throw TestException().causedBy(error)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
expect { try throwable() }.to(throwError { error in
|
|
64
|
+
if let error = error as? TestException, let cause = error.cause as? TestExceptionCause {
|
|
65
|
+
expect(error.description).to(contain(cause.description))
|
|
66
|
+
} else {
|
|
67
|
+
fail("Error and its cause are not of expected types.")
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
it("has root cause") {
|
|
73
|
+
let a = TestException()
|
|
74
|
+
let b = TestException().causedBy(a)
|
|
75
|
+
let c = TestException().causedBy(b)
|
|
76
|
+
|
|
77
|
+
expect(c.rootCause) === a
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
class TestException: Exception {
|
|
83
|
+
override var reason: String {
|
|
84
|
+
"This is the test exception"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
class TestExceptionCause: Exception {
|
|
89
|
+
override var reason: String {
|
|
90
|
+
"This is the cause of the test exception"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
Tests whether the exception chain matches given types and their order.
|
|
96
|
+
*/
|
|
97
|
+
private func testChainedExceptionTypes(error: Error, types: [Error.Type]) {
|
|
98
|
+
var next: Error? = error
|
|
99
|
+
|
|
100
|
+
for errorType in types {
|
|
101
|
+
let expectedErrorTypeName = String(describing: errorType)
|
|
102
|
+
let currentErrorTypeName = String(describing: type(of: next!))
|
|
103
|
+
|
|
104
|
+
expect(currentErrorTypeName).to(equal(expectedErrorTypeName), description: "The cause is not of type \(expectedErrorTypeName)")
|
|
105
|
+
|
|
106
|
+
if let chainableException = next as? ChainableException {
|
|
107
|
+
next = chainableException.cause
|
|
108
|
+
} else {
|
|
109
|
+
next = nil
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -11,11 +11,11 @@ class FunctionSpec: QuickSpec {
|
|
|
11
11
|
func testFunctionReturning<T: Equatable>(value returnValue: T) {
|
|
12
12
|
waitUntil { done in
|
|
13
13
|
mockModuleHolder(appContext) {
|
|
14
|
-
|
|
14
|
+
function(functionName) {
|
|
15
15
|
return returnValue
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
-
.call(function: functionName, args: []) { value,
|
|
18
|
+
.call(function: functionName, args: []) { value, _ in
|
|
19
19
|
expect(value).notTo(beNil())
|
|
20
20
|
expect(value).to(beAKindOf(T.self))
|
|
21
21
|
expect(value as? T).to(equal(returnValue))
|
|
@@ -27,7 +27,7 @@ class FunctionSpec: QuickSpec {
|
|
|
27
27
|
it("is called") {
|
|
28
28
|
waitUntil { done in
|
|
29
29
|
mockModuleHolder(appContext) {
|
|
30
|
-
|
|
30
|
+
function(functionName) {
|
|
31
31
|
done()
|
|
32
32
|
}
|
|
33
33
|
}
|
|
@@ -42,7 +42,7 @@ class FunctionSpec: QuickSpec {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
it("returns int values") {
|
|
45
|
-
testFunctionReturning(value:
|
|
45
|
+
testFunctionReturning(value: 1_234)
|
|
46
46
|
testFunctionReturning(value: [2, 1, 3, 7])
|
|
47
47
|
}
|
|
48
48
|
|
|
@@ -60,7 +60,7 @@ class FunctionSpec: QuickSpec {
|
|
|
60
60
|
let str: String? = nil
|
|
61
61
|
|
|
62
62
|
mockModuleHolder(appContext) {
|
|
63
|
-
|
|
63
|
+
function(functionName) { (a: String?) in
|
|
64
64
|
expect(a == nil) == true
|
|
65
65
|
}
|
|
66
66
|
}
|
|
@@ -71,7 +71,7 @@ class FunctionSpec: QuickSpec {
|
|
|
71
71
|
let array: [[String]] = [["expo"]]
|
|
72
72
|
|
|
73
73
|
mockModuleHolder(appContext) {
|
|
74
|
-
|
|
74
|
+
function(functionName) { (a: [[String]]) in
|
|
75
75
|
expect(a.first!.first) == array.first!.first
|
|
76
76
|
}
|
|
77
77
|
}
|
|
@@ -81,7 +81,7 @@ class FunctionSpec: QuickSpec {
|
|
|
81
81
|
describe("converting dicts to records") {
|
|
82
82
|
struct TestRecord: Record {
|
|
83
83
|
@Field var property: String = "expo"
|
|
84
|
-
@Field var optionalProperty: Int?
|
|
84
|
+
@Field var optionalProperty: Int?
|
|
85
85
|
@Field("propertyWithCustomKey") var customKeyProperty: String = "expo"
|
|
86
86
|
}
|
|
87
87
|
let dict = [
|
|
@@ -92,11 +92,11 @@ class FunctionSpec: QuickSpec {
|
|
|
92
92
|
it("converts to simple record when passed as an argument") {
|
|
93
93
|
waitUntil { done in
|
|
94
94
|
mockModuleHolder(appContext) {
|
|
95
|
-
|
|
95
|
+
function(functionName) { (a: TestRecord) in
|
|
96
96
|
return a.property
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
|
-
.call(function: functionName, args: [dict]) { value,
|
|
99
|
+
.call(function: functionName, args: [dict]) { value, _ in
|
|
100
100
|
expect(value).notTo(beNil())
|
|
101
101
|
expect(value).to(beAKindOf(String.self))
|
|
102
102
|
expect(value).to(be(dict["property"]))
|
|
@@ -108,11 +108,11 @@ class FunctionSpec: QuickSpec {
|
|
|
108
108
|
it("converts to record with custom key") {
|
|
109
109
|
waitUntil { done in
|
|
110
110
|
mockModuleHolder(appContext) {
|
|
111
|
-
|
|
111
|
+
function(functionName) { (a: TestRecord) in
|
|
112
112
|
return a.customKeyProperty
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
-
.call(function: functionName, args: [dict]) { value,
|
|
115
|
+
.call(function: functionName, args: [dict]) { value, _ in
|
|
116
116
|
expect(value).notTo(beNil())
|
|
117
117
|
expect(value).to(beAKindOf(String.self))
|
|
118
118
|
expect(value).to(be(dict["propertyWithCustomKey"]))
|
|
@@ -124,11 +124,11 @@ class FunctionSpec: QuickSpec {
|
|
|
124
124
|
it("returns the record back") {
|
|
125
125
|
waitUntil { done in
|
|
126
126
|
mockModuleHolder(appContext) {
|
|
127
|
-
|
|
127
|
+
function(functionName) { (a: TestRecord) in
|
|
128
128
|
return a.toDictionary()
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
|
-
.call(function: functionName, args: [dict]) { value,
|
|
131
|
+
.call(function: functionName, args: [dict]) { value, _ in
|
|
132
132
|
expect(value).notTo(beNil())
|
|
133
133
|
expect(value).to(beAKindOf(Record.Dict.self))
|
|
134
134
|
|
|
@@ -145,16 +145,15 @@ class FunctionSpec: QuickSpec {
|
|
|
145
145
|
it("throws when called with more arguments than expected") {
|
|
146
146
|
waitUntil { done in
|
|
147
147
|
mockModuleHolder(appContext) {
|
|
148
|
-
|
|
148
|
+
function(functionName) { (_: Int) in
|
|
149
149
|
return "something"
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
152
|
// Function expects one argument, let's give it more.
|
|
153
|
-
.call(function: functionName, args: [1, 2]) {
|
|
153
|
+
.call(function: functionName, args: [1, 2]) { _, error in
|
|
154
154
|
expect(error).notTo(beNil())
|
|
155
|
-
expect(error).to(beAKindOf(
|
|
156
|
-
expect(error
|
|
157
|
-
expect(error?.description).to(equal(InvalidArgsNumberError(received: 2, expected: 1).description))
|
|
155
|
+
expect(error).to(beAKindOf(FunctionCallException.self))
|
|
156
|
+
expect((error as! Exception).isCausedBy(InvalidArgsNumberException.self)) == true
|
|
158
157
|
done()
|
|
159
158
|
}
|
|
160
159
|
}
|
|
@@ -163,16 +162,15 @@ class FunctionSpec: QuickSpec {
|
|
|
163
162
|
it("throws when called with arguments of incompatible types") {
|
|
164
163
|
waitUntil { done in
|
|
165
164
|
mockModuleHolder(appContext) {
|
|
166
|
-
|
|
165
|
+
function(functionName) { (_: String) in
|
|
167
166
|
return "something"
|
|
168
167
|
}
|
|
169
168
|
}
|
|
170
169
|
// Function expects a string, let's give it a number.
|
|
171
170
|
.call(function: functionName, args: [1]) { value, error in
|
|
172
171
|
expect(error).notTo(beNil())
|
|
173
|
-
expect(error).to(beAKindOf(
|
|
174
|
-
expect(error
|
|
175
|
-
expect(error?.description).to(equal(Conversions.CastingError<String>(value: 1).description))
|
|
172
|
+
expect(error).to(beAKindOf(FunctionCallException.self))
|
|
173
|
+
expect((error as! Exception).isCausedBy(Conversions.CastingException<String>.self)) == true
|
|
176
174
|
done()
|
|
177
175
|
}
|
|
178
176
|
}
|
|
@@ -18,7 +18,7 @@ class FunctionWithConvertiblesSpec: QuickSpec {
|
|
|
18
18
|
let height = 592.1
|
|
19
19
|
|
|
20
20
|
mockModuleHolder(appContext) {
|
|
21
|
-
|
|
21
|
+
function(functionName) { (point: CGPoint, size: CGSize, vector: CGVector, rect: CGRect) in
|
|
22
22
|
expect(point.x) == x
|
|
23
23
|
expect(point.y) == y
|
|
24
24
|
expect(size.width) == width
|
|
@@ -48,7 +48,7 @@ class FunctionWithConvertiblesSpec: QuickSpec {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
mockModuleHolder(appContext) {
|
|
51
|
-
|
|
51
|
+
function(functionName) { (color1: CGColor, color2: CGColor, color3: CGColor, color4: CGColor) in
|
|
52
52
|
testColorComponents(color1, 0x2A, 0x4B, 0x5D, 0xFF)
|
|
53
53
|
testColorComponents(color2, 0x11, 0xFF, 0x00, 0xDD)
|
|
54
54
|
testColorComponents(color3, 0x66, 0x00, 0xCC, 0xAA)
|
|
@@ -32,7 +32,7 @@ class CustomModule: Module {
|
|
|
32
32
|
typealias MockedDefinitionFunc = (CustomModule) -> ModuleDefinition
|
|
33
33
|
|
|
34
34
|
func mockModuleHolder(_ appContext: AppContext, @ModuleDefinitionBuilder _ definitionBody: @escaping () -> ModuleDefinition) -> ModuleHolder {
|
|
35
|
-
return ModuleHolder(appContext: appContext, module: CustomModule(appContext: appContext, {
|
|
35
|
+
return ModuleHolder(appContext: appContext, module: CustomModule(appContext: appContext, { _ in definitionBody() }))
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
func mockModuleHolder(_ appContext: AppContext, @ModuleDefinitionBuilder _ definitionBody: @escaping (CustomModule) -> ModuleDefinition) -> ModuleHolder {
|
|
@@ -7,7 +7,7 @@ class RecordSpec: QuickSpec {
|
|
|
7
7
|
override func spec() {
|
|
8
8
|
it("initializes with empty dictionary") {
|
|
9
9
|
struct TestRecord: Record { }
|
|
10
|
-
|
|
10
|
+
_ = try TestRecord(from: [:])
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
it("works back and forth with a field") {
|
|
@@ -37,14 +37,9 @@ class RecordSpec: QuickSpec {
|
|
|
37
37
|
@Field(.required) var a: Int
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
} catch let error as CodedError {
|
|
44
|
-
expect(error).to(beAKindOf(FieldRequiredError.self))
|
|
45
|
-
expect(error.code).to(equal("ERR_FIELD_REQUIRED"))
|
|
46
|
-
expect(error.description).to(equal(FieldRequiredError(fieldKey: "a").description))
|
|
47
|
-
}
|
|
40
|
+
expect { try TestRecord(from: [:]) }.to(throwError { error in
|
|
41
|
+
expect(error).to(beAKindOf(FieldRequiredException.self))
|
|
42
|
+
})
|
|
48
43
|
}
|
|
49
44
|
|
|
50
45
|
it("throws when casting is not possible") {
|
|
@@ -53,14 +48,9 @@ class RecordSpec: QuickSpec {
|
|
|
53
48
|
}
|
|
54
49
|
let dict = ["a": "try with String instead of Int"]
|
|
55
50
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
} catch let error as CodedError {
|
|
60
|
-
expect(error).to(beAKindOf(FieldInvalidTypeError.self))
|
|
61
|
-
expect(error.code).to(equal("ERR_FIELD_INVALID_TYPE"))
|
|
62
|
-
expect(error.description).to(equal(FieldInvalidTypeError(fieldKey: "a", value: dict["a"], desiredType: Int.self).description))
|
|
63
|
-
}
|
|
51
|
+
expect { try TestRecord(from: dict) }.to(throwError { error in
|
|
52
|
+
expect(error).to(beAKindOf(FieldInvalidTypeException.self))
|
|
53
|
+
})
|
|
64
54
|
}
|
|
65
55
|
}
|
|
66
56
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-modules-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "The core of Expo Modules architecture",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"author": "650 Industries, Inc.",
|
|
32
32
|
"license": "MIT",
|
|
33
|
-
"homepage": "https://github.com/expo/expo/tree/
|
|
33
|
+
"homepage": "https://github.com/expo/expo/tree/main/packages/expo-modules-core",
|
|
34
34
|
"jest": {
|
|
35
35
|
"preset": "expo-module-scripts"
|
|
36
36
|
},
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"@testing-library/react-hooks": "^7.0.1",
|
|
43
43
|
"expo-module-scripts": "^2.0.0"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "e1ff1a3d6bc62f374e6947a5e81428a1bb7cfa34"
|
|
46
46
|
}
|
package/src/index.ts
CHANGED
|
@@ -9,6 +9,8 @@ import SyntheticPlatformEmitter from './SyntheticPlatformEmitter';
|
|
|
9
9
|
import { CodedError } from './errors/CodedError';
|
|
10
10
|
import { UnavailabilityError } from './errors/UnavailabilityError';
|
|
11
11
|
|
|
12
|
+
import './sweet/setUpErrorManager.fx';
|
|
13
|
+
|
|
12
14
|
export { default as deprecate } from './deprecate';
|
|
13
15
|
|
|
14
16
|
export {
|
|
@@ -25,6 +27,8 @@ export {
|
|
|
25
27
|
UnavailabilityError,
|
|
26
28
|
};
|
|
27
29
|
|
|
30
|
+
export * from './requireNativeModule';
|
|
31
|
+
|
|
28
32
|
/**
|
|
29
33
|
* @deprecated renamed to `DeviceEventEmitter`
|
|
30
34
|
*/
|