expo-modules-core 0.6.4 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +53 -0
- package/README.md +1 -1
- package/android/ExpoModulesCorePlugin.gradle +15 -0
- package/android/build.gradle +46 -32
- package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +5 -5
- package/android/src/main/java/expo/modules/adapters/react/services/UIManagerModuleWrapper.java +13 -0
- package/android/src/main/java/expo/modules/core/ViewManager.java +9 -0
- package/android/src/main/java/expo/modules/core/interfaces/JavaScriptContextProvider.java +4 -0
- package/android/src/main/java/expo/modules/core/interfaces/ReactActivityHandler.java +37 -1
- package/android/src/main/java/expo/modules/core/interfaces/ReactNativeHostHandler.java +19 -0
- package/android/src/main/java/expo/modules/core/interfaces/services/UIManager.java +2 -0
- package/android/src/main/java/expo/modules/kotlin/AppContext.kt +23 -5
- package/android/src/main/java/expo/modules/kotlin/DynamicExtenstions.kt +5 -3
- package/android/src/main/java/expo/modules/kotlin/KPromiseWrapper.kt +3 -8
- package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +24 -9
- package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +12 -7
- package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +23 -1
- package/android/src/main/java/expo/modules/kotlin/Promise.kt +1 -1
- package/android/src/main/java/expo/modules/kotlin/callbacks/Callback.kt +5 -0
- package/android/src/main/java/expo/modules/kotlin/callbacks/ViewCallback.kt +39 -0
- package/android/src/main/java/expo/modules/kotlin/callbacks/ViewCallbackDelegate.kt +27 -0
- package/android/src/main/java/expo/modules/kotlin/defaultmodules/ErrorManagerModule.kt +25 -0
- package/android/src/main/java/expo/modules/kotlin/events/EventEmitter.kt +13 -0
- package/android/src/main/java/expo/modules/kotlin/events/KModuleEventEmitterWrapper.kt +102 -0
- package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +93 -9
- package/android/src/main/java/expo/modules/kotlin/exception/ExceptionDecorator.kt +11 -0
- package/android/src/main/java/expo/modules/kotlin/{methods/AnyMethod.kt → functions/AnyFunction.kt} +18 -18
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +15 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +61 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromise.kt +15 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncSuspendFunction.kt +36 -0
- package/android/src/main/java/expo/modules/kotlin/modules/DefinitionMarker.kt +4 -0
- package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +17 -2
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +219 -30
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +2 -2
- package/android/src/main/java/expo/modules/kotlin/records/FieldValidator.kt +139 -0
- package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +71 -15
- package/android/src/main/java/expo/modules/kotlin/records/Required.kt +5 -0
- package/android/src/main/java/expo/modules/kotlin/records/ValidationBinder.kt +110 -0
- package/android/src/main/java/expo/modules/kotlin/records/Validators.kt +61 -0
- package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +11 -5
- package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverter.kt +35 -0
- package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverterHelper.kt +148 -0
- package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +10 -4
- package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +12 -6
- package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +29 -13
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +2 -1
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +9 -1
- package/android/src/main/java/expo/modules/kotlin/views/CallbacksDefinition.kt +3 -0
- package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +71 -0
- package/android/src/main/java/expo/modules/kotlin/views/SimpleViewManagerWrapper.kt +22 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinition.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinitionBuilder.kt +64 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +30 -2
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +42 -1
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +62 -2
- package/build/EventEmitter.d.ts +1 -0
- package/build/EventEmitter.d.ts.map +1 -0
- package/build/NativeModulesProxy.d.ts +1 -0
- package/build/NativeModulesProxy.d.ts.map +1 -0
- package/build/NativeModulesProxy.native.d.ts +1 -4
- package/build/NativeModulesProxy.native.d.ts.map +1 -0
- package/build/NativeModulesProxy.native.js +1 -14
- package/build/NativeModulesProxy.native.js.map +1 -1
- package/build/NativeModulesProxy.types.d.ts +1 -3
- package/build/NativeModulesProxy.types.d.ts.map +1 -0
- package/build/NativeModulesProxy.types.js.map +1 -1
- package/build/NativeViewManagerAdapter.d.ts +1 -0
- package/build/NativeViewManagerAdapter.d.ts.map +1 -0
- package/build/NativeViewManagerAdapter.native.d.ts +1 -0
- package/build/NativeViewManagerAdapter.native.d.ts.map +1 -0
- package/build/NativeViewManagerAdapter.native.js +9 -33
- package/build/NativeViewManagerAdapter.native.js.map +1 -1
- package/build/PermissionsHook.d.ts +1 -0
- package/build/PermissionsHook.d.ts.map +1 -0
- package/build/PermissionsInterface.d.ts +1 -0
- package/build/PermissionsInterface.d.ts.map +1 -0
- package/build/Platform.d.ts +1 -0
- package/build/Platform.d.ts.map +1 -0
- package/build/SyntheticPlatformEmitter.d.ts +1 -0
- package/build/SyntheticPlatformEmitter.d.ts.map +1 -0
- package/build/SyntheticPlatformEmitter.web.d.ts +1 -0
- package/build/SyntheticPlatformEmitter.web.d.ts.map +1 -0
- package/build/deprecate.d.ts +1 -0
- package/build/deprecate.d.ts.map +1 -0
- package/build/environment/browser.d.ts +1 -0
- package/build/environment/browser.d.ts.map +1 -0
- package/build/environment/browser.web.d.ts +1 -0
- package/build/environment/browser.web.d.ts.map +1 -0
- package/build/errors/CodedError.d.ts +1 -0
- package/build/errors/CodedError.d.ts.map +1 -0
- package/build/errors/UnavailabilityError.d.ts +1 -0
- package/build/errors/UnavailabilityError.d.ts.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +2 -0
- package/build/index.js.map +1 -1
- package/build/requireNativeModule.d.ts +16 -0
- package/build/requireNativeModule.d.ts.map +1 -0
- package/build/requireNativeModule.js +18 -0
- package/build/requireNativeModule.js.map +1 -0
- package/build/sweet/NativeErrorManager.d.ts +3 -0
- package/build/sweet/NativeErrorManager.d.ts.map +1 -0
- package/build/sweet/NativeErrorManager.js +3 -0
- package/build/sweet/NativeErrorManager.js.map +1 -0
- package/build/sweet/setUpErrorManager.fx.d.ts +2 -0
- package/build/sweet/setUpErrorManager.fx.d.ts.map +1 -0
- package/build/sweet/setUpErrorManager.fx.js +11 -0
- package/build/sweet/setUpErrorManager.fx.js.map +1 -0
- package/ios/AppDelegates/EXAppDelegatesLoader.m +4 -8
- package/ios/AppDelegates/ExpoAppDelegate.swift +22 -20
- package/ios/EXAppDefines.h +1 -0
- package/ios/EXAppDefines.m +6 -0
- package/ios/EXUtilities.h +2 -0
- package/ios/EXUtilities.m +12 -0
- package/ios/ExpoModulesCore.h +4 -0
- package/ios/ExpoModulesCore.podspec +4 -2
- package/ios/Interfaces/FileSystem/EXFileSystemInterface.h +1 -1
- package/ios/Interfaces/TaskManager/EXTaskServiceInterface.h +1 -0
- package/ios/JSI/{JSIConversions.h → EXJSIConversions.h} +5 -0
- package/ios/JSI/{JSIConversions.mm → EXJSIConversions.mm} +21 -1
- package/ios/JSI/{JSIInstaller.h → EXJSIInstaller.h} +10 -0
- package/ios/JSI/EXJSIInstaller.mm +17 -0
- package/ios/JSI/EXJSIUtils.h +19 -0
- package/ios/JSI/EXJSIUtils.mm +89 -0
- package/ios/JSI/EXJavaScriptObject.h +97 -0
- package/ios/JSI/EXJavaScriptObject.mm +121 -0
- package/ios/JSI/EXJavaScriptRuntime.h +73 -0
- package/ios/JSI/EXJavaScriptRuntime.mm +153 -0
- package/ios/JSI/EXJavaScriptValue.h +57 -0
- package/ios/JSI/EXJavaScriptValue.mm +166 -0
- package/ios/JSI/ExpoModulesHostObject.h +33 -0
- package/ios/JSI/ExpoModulesHostObject.mm +41 -0
- package/ios/JSI/JavaScriptRuntime.swift +32 -0
- package/ios/JSI/JavaScriptValue.swift +94 -0
- package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +3 -23
- package/ios/NativeModulesProxy/EXNativeModulesProxy.h +2 -2
- package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +101 -75
- package/ios/RCTComponentData+Privates.h +12 -0
- package/ios/ReactDelegates/EXReactCompatibleHelpers.h +18 -0
- package/ios/ReactDelegates/EXReactCompatibleHelpers.m +19 -0
- package/ios/ReactDelegates/ExpoReactDelegate.swift +3 -3
- package/ios/ReactDelegates/ExpoReactDelegateHandler.swift +4 -4
- package/ios/ReactDelegates/ModulePriorities.swift +1 -1
- package/ios/Swift/AppContext.swift +64 -4
- package/ios/Swift/Arguments/ArgumentType.swift +4 -0
- package/ios/Swift/Arguments/Convertibles.swift +13 -13
- package/ios/Swift/Arguments/Types/EnumArgumentType.swift +11 -17
- package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +1 -1
- package/ios/Swift/Arguments/Types/RawArgumentType.swift +2 -2
- package/ios/Swift/Conversions.swift +51 -56
- package/ios/Swift/EventListener.swift +8 -10
- package/ios/Swift/Events/Callback.swift +66 -0
- package/ios/Swift/Events/Event.swift +43 -0
- package/ios/Swift/Exceptions/ChainableException.swift +51 -0
- package/ios/Swift/{CodedError.swift → Exceptions/CodedError.swift} +1 -12
- package/ios/Swift/Exceptions/Exception.swift +62 -0
- package/ios/Swift/Exceptions/ExceptionOrigin.swift +28 -0
- package/ios/Swift/Exceptions/GenericException.swift +20 -0
- package/ios/Swift/Exceptions/UnexpectedException.swift +16 -0
- package/ios/Swift/Functions/AnyFunction.swift +11 -1
- package/ios/Swift/Functions/AsyncFunction.swift +17 -0
- package/ios/Swift/Functions/ConcreteFunction.swift +43 -17
- package/ios/Swift/JavaScriptUtils.swift +54 -0
- package/ios/Swift/ModuleHolder.swift +66 -16
- package/ios/Swift/ModuleRegistry.swift +4 -1
- package/ios/Swift/Modules/AnyModule.swift +0 -1
- package/ios/Swift/Modules/ModuleDefinition.swift +4 -13
- package/ios/Swift/Modules/ModuleDefinitionBuilder.swift +0 -1
- package/ios/Swift/Modules/ModuleDefinitionComponents.swift +0 -188
- package/ios/Swift/ModulesProvider.swift +3 -11
- package/ios/Swift/Objects/ObjectDefinition.swift +30 -0
- package/ios/Swift/Objects/ObjectDefinitionComponents.swift +384 -0
- package/ios/Swift/Promise.swift +8 -3
- package/ios/Swift/Records/AnyField.swift +7 -0
- package/ios/Swift/Records/Field.swift +24 -19
- package/ios/Swift/Records/FieldOption.swift +1 -1
- package/ios/Swift/Records/Record.swift +12 -4
- package/ios/Swift/SwiftInteropBridge.swift +53 -15
- package/ios/Swift/Views/AnyViewProp.swift +1 -1
- package/ios/Swift/Views/ComponentData.swift +96 -0
- package/ios/Swift/Views/ConcreteViewProp.swift +6 -8
- package/ios/Swift/Views/ExpoView.swift +8 -0
- package/ios/Swift/Views/ViewFactory.swift +1 -1
- package/ios/Swift/Views/ViewManagerDefinition.swift +23 -2
- package/ios/Swift/Views/ViewManagerDefinitionBuilder.swift +0 -1
- package/ios/Swift/Views/ViewManagerDefinitionComponents.swift +26 -0
- package/ios/Swift/Views/ViewModuleWrapper.swift +5 -2
- package/ios/Swift.h +5 -0
- package/ios/Tests/ArgumentTypeSpec.swift +5 -7
- package/ios/Tests/ConstantsSpec.swift +6 -7
- package/ios/Tests/ConvertiblesSpec.swift +35 -36
- package/ios/Tests/ExceptionsSpec.swift +111 -0
- package/ios/Tests/ExpoModulesSpec.swift +76 -0
- package/ios/Tests/FunctionSpec.swift +22 -25
- package/ios/Tests/FunctionWithConvertiblesSpec.swift +4 -5
- package/ios/Tests/JavaScriptObjectSpec.swift +97 -0
- package/ios/Tests/JavaScriptRuntimeSpec.swift +94 -0
- package/ios/Tests/Mocks/ModuleMocks.swift +1 -1
- package/ios/Tests/Mocks/ModulesProviderMock.swift +0 -1
- package/ios/Tests/ModuleEventListenersSpec.swift +3 -4
- package/ios/Tests/ModuleRegistrySpec.swift +2 -3
- package/ios/Tests/RecordSpec.swift +9 -20
- package/package.json +3 -3
- package/src/NativeModulesProxy.native.ts +2 -22
- package/src/NativeModulesProxy.types.ts +0 -8
- package/src/NativeViewManagerAdapter.native.tsx +12 -28
- package/src/index.ts +4 -0
- package/src/requireNativeModule.ts +29 -0
- package/src/sweet/NativeErrorManager.ts +2 -0
- package/src/sweet/setUpErrorManager.fx.ts +12 -0
- package/android/src/main/java/expo/modules/kotlin/events/KEventEmitterWrapper.kt +0 -26
- package/android/src/main/java/expo/modules/kotlin/methods/Method.kt +0 -14
- package/android/src/main/java/expo/modules/kotlin/methods/PromiseMethod.kt +0 -15
- package/ios/JSI/ExpoModulesProxySpec.h +0 -24
- package/ios/JSI/ExpoModulesProxySpec.mm +0 -135
- package/ios/JSI/JSIInstaller.mm +0 -22
|
@@ -17,11 +17,11 @@
|
|
|
17
17
|
#import <ExpoModulesCore/EXViewManagerAdapterClassesRegistry.h>
|
|
18
18
|
#import <ExpoModulesCore/EXModuleRegistryProvider.h>
|
|
19
19
|
#import <ExpoModulesCore/EXReactNativeEventEmitter.h>
|
|
20
|
-
#import <ExpoModulesCore/
|
|
20
|
+
#import <ExpoModulesCore/EXJSIInstaller.h>
|
|
21
21
|
#import <ExpoModulesCore/Swift.h>
|
|
22
22
|
|
|
23
23
|
static const NSString *exportedMethodsNamesKeyPath = @"exportedMethods";
|
|
24
|
-
static const NSString *
|
|
24
|
+
static const NSString *viewManagersMetadataKeyPath = @"viewManagersMetadata";
|
|
25
25
|
static const NSString *exportedConstantsKeyPath = @"modulesConstants";
|
|
26
26
|
|
|
27
27
|
static const NSString *methodInfoKeyKey = @"key";
|
|
@@ -41,13 +41,6 @@ static const NSString *methodInfoArgumentsCountKey = @"argumentsCount";
|
|
|
41
41
|
|
|
42
42
|
@end
|
|
43
43
|
|
|
44
|
-
@interface RCTComponentData (EXNativeModulesProxy)
|
|
45
|
-
|
|
46
|
-
- (instancetype)initWithManagerClass:(Class)managerClass bridge:(RCTBridge *)bridge eventDispatcher:(id<RCTEventDispatcherProtocol>) eventDispatcher; // available in RN 0.65+
|
|
47
|
-
- (instancetype)initWithManagerClass:(Class)managerClass bridge:(RCTBridge *)bridge;
|
|
48
|
-
|
|
49
|
-
@end
|
|
50
|
-
|
|
51
44
|
@interface EXNativeModulesProxy ()
|
|
52
45
|
|
|
53
46
|
@property (nonatomic, strong) NSRegularExpression *regexp;
|
|
@@ -97,8 +90,9 @@ RCT_EXPORT_MODULE(NativeUnimoduleProxy)
|
|
|
97
90
|
|
|
98
91
|
- (NSDictionary *)constantsToExport
|
|
99
92
|
{
|
|
100
|
-
// Install the
|
|
101
|
-
|
|
93
|
+
// Install ExpoModules host object in the runtime. It's probably not the right place,
|
|
94
|
+
// but it's the earliest moment in bridge's lifecycle when we have access to the runtime.
|
|
95
|
+
[self installExpoModulesHostObject];
|
|
102
96
|
|
|
103
97
|
NSMutableDictionary <NSString *, id> *exportedModulesConstants = [NSMutableDictionary dictionary];
|
|
104
98
|
// Grab all the constants exported by modules
|
|
@@ -130,17 +124,21 @@ RCT_EXPORT_MODULE(NativeUnimoduleProxy)
|
|
|
130
124
|
// Add entries from Swift modules
|
|
131
125
|
[exportedMethodsNamesAccumulator addEntriesFromDictionary:[_swiftInteropBridge exportedFunctionNames]];
|
|
132
126
|
|
|
133
|
-
// Also, add `
|
|
127
|
+
// Also, add `viewManagersMetadata` for sanity check and testing purposes -- with names we know what managers to mock on UIManager
|
|
134
128
|
NSArray<EXViewManager *> *viewManagers = [_exModuleRegistry getAllViewManagers];
|
|
135
|
-
|
|
129
|
+
NSMutableDictionary<NSString *, NSDictionary *> *viewManagersMetadata = [[NSMutableDictionary alloc] initWithCapacity:[viewManagers count]];
|
|
130
|
+
|
|
136
131
|
for (EXViewManager *viewManager in viewManagers) {
|
|
137
|
-
[
|
|
132
|
+
viewManagersMetadata[viewManager.viewName] = @{
|
|
133
|
+
@"propsNames": [[viewManager getPropsNames] allKeys]
|
|
134
|
+
};
|
|
138
135
|
}
|
|
139
136
|
|
|
140
|
-
|
|
137
|
+
// Add entries from Swift view managers
|
|
138
|
+
[viewManagersMetadata addEntriesFromDictionary:[_swiftInteropBridge viewManagersMetadata]];
|
|
141
139
|
|
|
142
140
|
NSMutableDictionary <NSString *, id> *constantsAccumulator = [NSMutableDictionary dictionary];
|
|
143
|
-
constantsAccumulator[
|
|
141
|
+
constantsAccumulator[viewManagersMetadataKeyPath] = viewManagersMetadata;
|
|
144
142
|
constantsAccumulator[exportedConstantsKeyPath] = exportedModulesConstants;
|
|
145
143
|
constantsAccumulator[exportedMethodsNamesKeyPath] = exportedMethodsNamesAccumulator;
|
|
146
144
|
|
|
@@ -150,8 +148,18 @@ RCT_EXPORT_MODULE(NativeUnimoduleProxy)
|
|
|
150
148
|
- (void)setBridge:(RCTBridge *)bridge
|
|
151
149
|
{
|
|
152
150
|
if (!_bridge) {
|
|
153
|
-
|
|
151
|
+
// The `setBridge` can be called during module setup or after. Registering more modules
|
|
152
|
+
// during setup causes a crash due to mutating `_moduleDataByID` while it's being enumerated.
|
|
153
|
+
// In that case we register them asynchronously.
|
|
154
|
+
if ([[bridge valueForKey:@"_moduleSetupComplete"] boolValue]) {
|
|
155
|
+
[self registerExpoModulesInBridge:bridge];
|
|
156
|
+
} else {
|
|
157
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
158
|
+
[self registerExpoModulesInBridge:bridge];
|
|
159
|
+
});
|
|
160
|
+
}
|
|
154
161
|
}
|
|
162
|
+
[_swiftInteropBridge setReactBridge:bridge];
|
|
155
163
|
_bridge = bridge;
|
|
156
164
|
}
|
|
157
165
|
|
|
@@ -203,7 +211,7 @@ RCT_EXPORT_METHOD(callMethod:(NSString *)moduleName methodNameOrKey:(id)methodNa
|
|
|
203
211
|
|
|
204
212
|
#pragma mark - Statics
|
|
205
213
|
|
|
206
|
-
+ (
|
|
214
|
+
+ (ModulesProvider *)getExpoModulesProvider
|
|
207
215
|
{
|
|
208
216
|
// Dynamically gets the modules provider class.
|
|
209
217
|
// NOTE: This needs to be versioned in Expo Go.
|
|
@@ -233,45 +241,49 @@ RCT_EXPORT_METHOD(callMethod:(NSString *)moduleName methodNameOrKey:(id)methodNa
|
|
|
233
241
|
|
|
234
242
|
- (void)registerExpoModulesInBridge:(RCTBridge *)bridge
|
|
235
243
|
{
|
|
236
|
-
// Registering expo modules in bridge is needed only when the proxy module owns
|
|
237
|
-
// (was autoinitialized by React Native). Otherwise they're registered by the registry adapter.
|
|
238
|
-
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
244
|
+
// Registering expo modules (excluding Swifty view managers!) in bridge is needed only when the proxy module owns
|
|
245
|
+
// the registry (was autoinitialized by React Native). Otherwise they're registered by the registry adapter.
|
|
246
|
+
BOOL ownsModuleRegistry = _ownsModuleRegistry && ![bridge moduleIsInitialized:[EXReactNativeEventEmitter class]];
|
|
241
247
|
|
|
242
248
|
// An array of `RCTBridgeModule` classes to register.
|
|
243
249
|
NSMutableArray<Class<RCTBridgeModule>> *additionalModuleClasses = [NSMutableArray new];
|
|
244
250
|
NSMutableSet *visitedSweetModules = [NSMutableSet new];
|
|
245
251
|
|
|
246
|
-
// Event emitter is a bridge module, however it's also needed by expo modules,
|
|
247
|
-
// so later we'll register an instance created by React Native as expo module.
|
|
248
|
-
[additionalModuleClasses addObject:[EXReactNativeEventEmitter class]];
|
|
249
|
-
|
|
250
252
|
// Add dynamic wrappers for view modules written in Sweet API.
|
|
251
253
|
for (ViewModuleWrapper *swiftViewModule in [_swiftInteropBridge getViewManagers]) {
|
|
252
|
-
Class wrappedViewModuleClass = [
|
|
254
|
+
Class wrappedViewModuleClass = [self registerComponentData:swiftViewModule inBridge:bridge];
|
|
253
255
|
[additionalModuleClasses addObject:wrappedViewModuleClass];
|
|
254
256
|
[visitedSweetModules addObject:swiftViewModule.name];
|
|
255
257
|
}
|
|
256
258
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
259
|
+
[additionalModuleClasses addObject:[ViewModuleWrapper class]];
|
|
260
|
+
[self registerLegacyComponentData:[ViewModuleWrapper class] inBridge:bridge];
|
|
261
|
+
|
|
262
|
+
// Add modules from legacy module registry only when the NativeModulesProxy owns the registry.
|
|
263
|
+
if (ownsModuleRegistry) {
|
|
264
|
+
// Event emitter is a bridge module, however it's also needed by expo modules,
|
|
265
|
+
// so later we'll register an instance created by React Native as expo module.
|
|
266
|
+
[additionalModuleClasses addObject:[EXReactNativeEventEmitter class]];
|
|
267
|
+
|
|
268
|
+
// Add dynamic wrappers for the classic view managers.
|
|
269
|
+
for (EXViewManager *viewManager in [_exModuleRegistry getAllViewManagers]) {
|
|
270
|
+
if (![visitedSweetModules containsObject:viewManager.viewName]) {
|
|
271
|
+
Class viewManagerWrapperClass = [EXViewManagerAdapterClassesRegistry createViewManagerAdapterClassForViewManager:viewManager];
|
|
272
|
+
[additionalModuleClasses addObject:viewManagerWrapperClass];
|
|
273
|
+
[self registerLegacyComponentData:viewManagerWrapperClass inBridge:bridge];
|
|
274
|
+
}
|
|
262
275
|
}
|
|
263
|
-
}
|
|
264
276
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
[additionalModuleClasses addObject:[ViewModuleWrapper class]];
|
|
277
|
+
// View manager wrappers don't have their own prop configs, so we must register
|
|
278
|
+
// their base view managers that provides common props such as `proxiedProperties`.
|
|
279
|
+
// Otherwise, React Native may treat these props as invalid in subclassing views.
|
|
280
|
+
[additionalModuleClasses addObject:[EXViewManagerAdapter class]];
|
|
270
281
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
282
|
+
// Some modules might need access to the bridge.
|
|
283
|
+
for (id module in [_exModuleRegistry getAllInternalModules]) {
|
|
284
|
+
if ([module conformsToProtocol:@protocol(RCTBridgeModule)]) {
|
|
285
|
+
[module setValue:bridge forKey:@"bridge"];
|
|
286
|
+
}
|
|
275
287
|
}
|
|
276
288
|
}
|
|
277
289
|
|
|
@@ -283,19 +295,19 @@ RCT_EXPORT_METHOD(callMethod:(NSString *)moduleName methodNameOrKey:(id)methodNa
|
|
|
283
295
|
// Register the view managers as additional modules.
|
|
284
296
|
[self registerAdditionalModuleClasses:additionalModuleClasses inBridge:bridge];
|
|
285
297
|
|
|
286
|
-
//
|
|
287
|
-
// components in UIManager — we need to register them on our own.
|
|
288
|
-
[self registerComponentDataForModuleClasses:additionalModuleClasses inBridge:bridge];
|
|
289
|
-
|
|
290
|
-
// Get the newly created instance of `EXReactEventEmitter` bridge module,
|
|
291
|
-
// pass event names supported by Swift modules and register it in legacy modules registry.
|
|
298
|
+
// Get the instance of `EXReactEventEmitter` bridge module and give it access to the interop bridge.
|
|
292
299
|
EXReactNativeEventEmitter *eventEmitter = [bridge moduleForClass:[EXReactNativeEventEmitter class]];
|
|
293
300
|
[eventEmitter setSwiftInteropBridge:_swiftInteropBridge];
|
|
294
|
-
[_exModuleRegistry registerInternalModule:eventEmitter];
|
|
295
301
|
|
|
296
|
-
//
|
|
297
|
-
//
|
|
298
|
-
|
|
302
|
+
// As the last step, when the registry is owned,
|
|
303
|
+
// register the event emitter and initialize the registry.
|
|
304
|
+
if (ownsModuleRegistry) {
|
|
305
|
+
[_exModuleRegistry registerInternalModule:eventEmitter];
|
|
306
|
+
|
|
307
|
+
// Let the modules consume the registry :)
|
|
308
|
+
// It calls `setModuleRegistry:` on all `EXModuleRegistryConsumer`s.
|
|
309
|
+
[_exModuleRegistry initialize];
|
|
310
|
+
}
|
|
299
311
|
}
|
|
300
312
|
|
|
301
313
|
- (void)registerAdditionalModuleClasses:(NSArray<Class> *)moduleClasses inBridge:(RCTBridge *)bridge
|
|
@@ -324,27 +336,38 @@ RCT_EXPORT_METHOD(callMethod:(NSString *)moduleName methodNameOrKey:(id)methodNa
|
|
|
324
336
|
[bridge registerAdditionalModuleClasses:moduleClasses];
|
|
325
337
|
}
|
|
326
338
|
|
|
327
|
-
- (
|
|
339
|
+
- (Class)registerComponentData:(ViewModuleWrapper *)viewModule inBridge:(RCTBridge *)bridge
|
|
328
340
|
{
|
|
329
341
|
// Hacky way to get a dictionary with `RCTComponentData` from UIManager.
|
|
330
342
|
NSMutableDictionary<NSString *, RCTComponentData *> *componentDataByName = [bridge.uiManager valueForKey:@"_componentDataByName"];
|
|
343
|
+
Class wrappedViewModuleClass = [ViewModuleWrapper createViewModuleWrapperClassWithModule:viewModule];
|
|
344
|
+
NSString *className = NSStringFromClass(wrappedViewModuleClass);
|
|
331
345
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
346
|
+
if (componentDataByName[className]) {
|
|
347
|
+
// Just in case the component was already registered, let's leave a log that we're overriding it.
|
|
348
|
+
NSLog(@"Overriding ComponentData for view %@", className);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
EXComponentData *componentData = [[EXComponentData alloc] initWithViewModule:viewModule
|
|
352
|
+
managerClass:wrappedViewModuleClass
|
|
353
|
+
bridge:bridge];
|
|
354
|
+
componentDataByName[className] = componentData;
|
|
355
|
+
return wrappedViewModuleClass;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
Bridge's `registerAdditionalModuleClasses:` method doesn't register
|
|
360
|
+
components in UIManager — we need to register them on our own.
|
|
361
|
+
*/
|
|
362
|
+
- (void)registerLegacyComponentData:(Class)moduleClass inBridge:(RCTBridge *)bridge
|
|
363
|
+
{
|
|
364
|
+
// Hacky way to get a dictionary with `RCTComponentData` from UIManager.
|
|
365
|
+
NSMutableDictionary<NSString *, RCTComponentData *> *componentDataByName = [bridge.uiManager valueForKey:@"_componentDataByName"];
|
|
366
|
+
NSString *className = NSStringFromClass(moduleClass);
|
|
367
|
+
|
|
368
|
+
if ([moduleClass isSubclassOfClass:[RCTViewManager class]] && !componentDataByName[className]) {
|
|
369
|
+
RCTComponentData *componentData = [[RCTComponentData alloc] initWithManagerClass:moduleClass bridge:bridge eventDispatcher:bridge.eventDispatcher];
|
|
370
|
+
componentDataByName[className] = componentData;
|
|
348
371
|
}
|
|
349
372
|
}
|
|
350
373
|
|
|
@@ -380,14 +403,17 @@ RCT_EXPORT_METHOD(callMethod:(NSString *)moduleName methodNameOrKey:(id)methodNa
|
|
|
380
403
|
}
|
|
381
404
|
|
|
382
405
|
/**
|
|
383
|
-
Installs
|
|
406
|
+
Installs ExpoModules host object in the runtime that the current bridge operates on.
|
|
384
407
|
*/
|
|
385
|
-
- (void)
|
|
408
|
+
- (void)installExpoModulesHostObject
|
|
386
409
|
{
|
|
387
|
-
facebook::jsi::Runtime *
|
|
410
|
+
facebook::jsi::Runtime *jsiRuntime = [_bridge respondsToSelector:@selector(runtime)] ? reinterpret_cast<facebook::jsi::Runtime *>(_bridge.runtime) : nullptr;
|
|
411
|
+
|
|
412
|
+
if (jsiRuntime) {
|
|
413
|
+
EXJavaScriptRuntime *runtime = [[EXJavaScriptRuntime alloc] initWithRuntime:jsiRuntime callInvoker:_bridge.jsCallInvoker];
|
|
388
414
|
|
|
389
|
-
|
|
390
|
-
|
|
415
|
+
[EXJavaScriptRuntimeManager installExpoModulesToRuntime:runtime withSwiftInterop:_swiftInteropBridge];
|
|
416
|
+
[_swiftInteropBridge setRuntime:runtime];
|
|
391
417
|
}
|
|
392
418
|
}
|
|
393
419
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
#import <React/RCTComponent.h>
|
|
4
|
+
#import <React/RCTComponentData.h>
|
|
5
|
+
|
|
6
|
+
typedef void (^RCTPropBlockAlias)(id<RCTComponent> _Nonnull view, id _Nullable json);
|
|
7
|
+
|
|
8
|
+
@interface RCTComponentData (Privates)
|
|
9
|
+
|
|
10
|
+
- (nonnull RCTPropBlockAlias)createPropBlock:(nonnull NSString *)name isShadowView:(BOOL)isShadowView;
|
|
11
|
+
|
|
12
|
+
@end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Copyright 2018-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
#import <UIKit/UIKit.h>
|
|
4
|
+
|
|
5
|
+
#import <ExpoModulesCore/EXDefines.h>
|
|
6
|
+
#import <React/RCTBridge.h>
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
EX_EXTERN_C_BEGIN
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Backward compatible version of `RCTAppSetupDefaultRootView`.
|
|
13
|
+
*
|
|
14
|
+
* `RCTAppSetupDefaultRootView` is introduced in react-native 0.68. To make `expo-modules-core` compatible with older react-native, introduces this compatible helper.
|
|
15
|
+
*/
|
|
16
|
+
UIView *EXAppSetupDefaultRootView(RCTBridge *bridge, NSString *moduleName, NSDictionary *initialProperties);
|
|
17
|
+
|
|
18
|
+
EX_EXTERN_C_END
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Copyright 2018-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
#import <ExpoModulesCore/EXReactCompatibleHelpers.h>
|
|
4
|
+
|
|
5
|
+
#import <React/RCTRootView.h>
|
|
6
|
+
|
|
7
|
+
#if __has_include(<React/RCTAppSetupUtils.h>)
|
|
8
|
+
#import <React/RCTAppSetupUtils.h>
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
UIView *EXAppSetupDefaultRootView(RCTBridge *bridge, NSString *moduleName, NSDictionary *initialProperties)
|
|
12
|
+
{
|
|
13
|
+
#if __has_include(<React/RCTAppSetupUtils.h>)
|
|
14
|
+
return RCTAppSetupDefaultRootView(bridge, moduleName, initialProperties);
|
|
15
|
+
#else
|
|
16
|
+
return [[RCTRootView alloc] initWithBridge:bridge moduleName:moduleName initialProperties:initialProperties];
|
|
17
|
+
#endif
|
|
18
|
+
}
|
|
19
|
+
|
|
@@ -12,7 +12,7 @@ public class ExpoReactDelegate: NSObject {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
@objc
|
|
15
|
-
public func createBridge(delegate: RCTBridgeDelegate, launchOptions: [AnyHashable
|
|
15
|
+
public func createBridge(delegate: RCTBridgeDelegate, launchOptions: [AnyHashable: Any]?) -> RCTBridge {
|
|
16
16
|
self.handlers.forEach { $0.bridgeWillCreate() }
|
|
17
17
|
let result = self.handlers.lazy
|
|
18
18
|
.compactMap { $0.createBridge(reactDelegate: self, bridgeDelegate: delegate, launchOptions: launchOptions) }
|
|
@@ -22,10 +22,10 @@ public class ExpoReactDelegate: NSObject {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
@objc
|
|
25
|
-
public func createRootView(bridge: RCTBridge, moduleName: String, initialProperties: [AnyHashable
|
|
25
|
+
public func createRootView(bridge: RCTBridge, moduleName: String, initialProperties: [AnyHashable: Any]?) -> UIView {
|
|
26
26
|
return self.handlers.lazy
|
|
27
27
|
.compactMap { $0.createRootView(reactDelegate: self, bridge: bridge, moduleName: moduleName, initialProperties: initialProperties) }
|
|
28
|
-
.first(where: { _ in true }) ??
|
|
28
|
+
.first(where: { _ in true }) ?? EXAppSetupDefaultRootView(bridge, moduleName, initialProperties)
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
@objc
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Copyright 2018-present 650 Industries. All rights reserved.
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import React
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
The handler for `ExpoReactDelegate`. A module can implement a handler to process react instance creation.
|
|
@@ -14,7 +14,7 @@ open class ExpoReactDelegateHandler: NSObject {
|
|
|
14
14
|
Otherwise return nil.
|
|
15
15
|
*/
|
|
16
16
|
@objc
|
|
17
|
-
open func createBridge(reactDelegate: ExpoReactDelegate, bridgeDelegate: RCTBridgeDelegate, launchOptions: [AnyHashable
|
|
17
|
+
open func createBridge(reactDelegate: ExpoReactDelegate, bridgeDelegate: RCTBridgeDelegate, launchOptions: [AnyHashable: Any]?) -> RCTBridge? {
|
|
18
18
|
return nil
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -23,7 +23,7 @@ open class ExpoReactDelegateHandler: NSObject {
|
|
|
23
23
|
Otherwise return nil.
|
|
24
24
|
*/
|
|
25
25
|
@objc
|
|
26
|
-
open func createRootView(reactDelegate: ExpoReactDelegate, bridge: RCTBridge, moduleName: String, initialProperties: [AnyHashable
|
|
26
|
+
open func createRootView(reactDelegate: ExpoReactDelegate, bridge: RCTBridge, moduleName: String, initialProperties: [AnyHashable: Any]?) -> RCTRootView? {
|
|
27
27
|
return nil
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -36,7 +36,7 @@ open class ExpoReactDelegateHandler: NSObject {
|
|
|
36
36
|
return nil
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
// MARK - event callbacks
|
|
39
|
+
// MARK: - event callbacks
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
Callback before bridge creation
|
|
@@ -11,7 +11,7 @@ internal struct ModulePriorities {
|
|
|
11
11
|
// key: node package name
|
|
12
12
|
// value: priority value, the higher value takes precedence
|
|
13
13
|
"expo-screen-orientation": 10,
|
|
14
|
-
"expo-updates": 5
|
|
14
|
+
"expo-updates": 5
|
|
15
15
|
]
|
|
16
16
|
|
|
17
17
|
static func get(_ packageName: String) -> Int {
|
|
@@ -3,6 +3,13 @@ import UIKit
|
|
|
3
3
|
The app context is an interface to a single Expo app.
|
|
4
4
|
*/
|
|
5
5
|
public final class AppContext {
|
|
6
|
+
internal static func create() -> AppContext {
|
|
7
|
+
let appContext = AppContext()
|
|
8
|
+
|
|
9
|
+
appContext.runtime = JavaScriptRuntime()
|
|
10
|
+
return appContext
|
|
11
|
+
}
|
|
12
|
+
|
|
6
13
|
/**
|
|
7
14
|
The module registry for the app context.
|
|
8
15
|
*/
|
|
@@ -13,6 +20,25 @@ public final class AppContext {
|
|
|
13
20
|
*/
|
|
14
21
|
public private(set) var legacyModuleRegistry: EXModuleRegistry?
|
|
15
22
|
|
|
23
|
+
/**
|
|
24
|
+
React bridge of the context's app.
|
|
25
|
+
*/
|
|
26
|
+
public internal(set) weak var reactBridge: RCTBridge?
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
JSI runtime of the running app.
|
|
30
|
+
*/
|
|
31
|
+
public internal(set) var runtime: JavaScriptRuntime? {
|
|
32
|
+
didSet {
|
|
33
|
+
// When the runtime is unpinned from the context (e.g. deallocated),
|
|
34
|
+
// we should make sure to release all JS objects from the memory.
|
|
35
|
+
// Otherwise the JSCRuntime asserts may fail on deallocation.
|
|
36
|
+
if runtime == nil {
|
|
37
|
+
releaseRuntimeObjects()
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
16
42
|
/**
|
|
17
43
|
Designated initializer without modules provider.
|
|
18
44
|
*/
|
|
@@ -78,6 +104,13 @@ public final class AppContext {
|
|
|
78
104
|
return legacyModule(implementing: EXEventEmitterService.self)
|
|
79
105
|
}
|
|
80
106
|
|
|
107
|
+
/**
|
|
108
|
+
Provides access to the logger from legacy module registry.
|
|
109
|
+
*/
|
|
110
|
+
public var logger: EXLogManager? {
|
|
111
|
+
return legacyModuleRegistry?.getSingletonModule(forName: EXLogManager.name()) as? EXLogManager
|
|
112
|
+
}
|
|
113
|
+
|
|
81
114
|
/**
|
|
82
115
|
Starts listening to `UIApplication` notifications.
|
|
83
116
|
*/
|
|
@@ -85,7 +118,7 @@ public final class AppContext {
|
|
|
85
118
|
[
|
|
86
119
|
UIApplication.willEnterForegroundNotification,
|
|
87
120
|
UIApplication.didBecomeActiveNotification,
|
|
88
|
-
UIApplication.didEnterBackgroundNotification
|
|
121
|
+
UIApplication.didEnterBackgroundNotification
|
|
89
122
|
].forEach { name in
|
|
90
123
|
NotificationCenter.default.addObserver(self, selector: #selector(handleClientAppNotification(_:)), name: name, object: nil)
|
|
91
124
|
}
|
|
@@ -108,6 +141,25 @@ public final class AppContext {
|
|
|
108
141
|
}
|
|
109
142
|
}
|
|
110
143
|
|
|
144
|
+
// MARK: - Runtime
|
|
145
|
+
|
|
146
|
+
internal func installExpoModulesHostObject(_ interopBridge: SwiftInteropBridge) throws {
|
|
147
|
+
guard let runtime = runtime else {
|
|
148
|
+
throw UndefinedRuntimeException()
|
|
149
|
+
}
|
|
150
|
+
EXJavaScriptRuntimeManager.installExpoModules(to: runtime, withSwiftInterop: interopBridge)
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
Unsets runtime objects that we hold for each module.
|
|
154
|
+
*/
|
|
155
|
+
private func releaseRuntimeObjects() {
|
|
156
|
+
for module in moduleRegistry {
|
|
157
|
+
module.javaScriptObject = nil
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// MARK: - Deallocation
|
|
162
|
+
|
|
111
163
|
/**
|
|
112
164
|
Cleans things up before deallocation.
|
|
113
165
|
*/
|
|
@@ -116,9 +168,17 @@ public final class AppContext {
|
|
|
116
168
|
moduleRegistry.post(event: .appContextDestroys)
|
|
117
169
|
}
|
|
118
170
|
|
|
119
|
-
// MARK:
|
|
171
|
+
// MARK: - Exceptions
|
|
120
172
|
|
|
121
|
-
|
|
122
|
-
var
|
|
173
|
+
class DeallocatedAppContextException: Exception {
|
|
174
|
+
override var reason: String {
|
|
175
|
+
"The AppContext has been deallocated"
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
class UndefinedRuntimeException: Exception {
|
|
180
|
+
override var reason: String {
|
|
181
|
+
"The AppContext has undefined runtime"
|
|
182
|
+
}
|
|
123
183
|
}
|
|
124
184
|
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
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
|
+
|
|
3
7
|
/**
|
|
4
8
|
Factory creating an instance of the argument type wrapper conforming to `AnyArgumentType`.
|
|
5
9
|
Depending on the given type, it may return one of `ArrayArgumentType`, `OptionalArgumentType`, `ConvertibleArgumentType`, etc.
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
import UIKit
|
|
4
4
|
import CoreGraphics
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
// Here we extend some common iOS types to implement `ConvertibleArgument` protocol and
|
|
7
|
+
// describe how they can be converted from primitive types received from JavaScript runtime.
|
|
8
|
+
// This allows these types to be used as argument types of functions callable from JavaScript.
|
|
9
|
+
// As an example, when the `CGPoint` type is used as an argument type, its instance can be
|
|
10
|
+
// created from an array of two doubles or an object with `x` and `y` fields.
|
|
11
11
|
|
|
12
12
|
// MARK: - Foundation
|
|
13
13
|
|
|
@@ -19,7 +19,7 @@ extension URL: ConvertibleArgument {
|
|
|
19
19
|
// If it has no scheme, we assume it was the file path.
|
|
20
20
|
return url.scheme != nil ? url : URL(fileURLWithPath: uri)
|
|
21
21
|
}
|
|
22
|
-
throw Conversions.
|
|
22
|
+
throw Conversions.ConvertingException<URL>(value)
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -37,7 +37,7 @@ extension UIColor: ConvertibleArgument {
|
|
|
37
37
|
if let value = value as? Int {
|
|
38
38
|
return try Conversions.toColor(argb: UInt64(value)) as! Self
|
|
39
39
|
}
|
|
40
|
-
throw Conversions.
|
|
40
|
+
throw Conversions.ConvertingException<UIColor>(value)
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -52,7 +52,7 @@ extension CGPoint: ConvertibleArgument {
|
|
|
52
52
|
let args = try Conversions.pickValues(from: value, byKeys: ["x", "y"], as: Double.self)
|
|
53
53
|
return CGPoint(x: args[0], y: args[1])
|
|
54
54
|
}
|
|
55
|
-
throw Conversions.
|
|
55
|
+
throw Conversions.ConvertingException<CGPoint>(value)
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
@@ -65,7 +65,7 @@ extension CGSize: ConvertibleArgument {
|
|
|
65
65
|
let args = try Conversions.pickValues(from: value, byKeys: ["width", "height"], as: Double.self)
|
|
66
66
|
return CGSize(width: args[0], height: args[1])
|
|
67
67
|
}
|
|
68
|
-
throw Conversions.
|
|
68
|
+
throw Conversions.ConvertingException<CGSize>(value)
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -78,7 +78,7 @@ extension CGVector: ConvertibleArgument {
|
|
|
78
78
|
let args = try Conversions.pickValues(from: value, byKeys: ["dx", "dy"], as: Double.self)
|
|
79
79
|
return CGVector(dx: args[0], dy: args[1])
|
|
80
80
|
}
|
|
81
|
-
throw Conversions.
|
|
81
|
+
throw Conversions.ConvertingException<CGVector>(value)
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -91,7 +91,7 @@ extension CGRect: ConvertibleArgument {
|
|
|
91
91
|
let args = try Conversions.pickValues(from: value, byKeys: ["x", "y", "width", "height"], as: Double.self)
|
|
92
92
|
return CGRect(x: args[0], y: args[1], width: args[2], height: args[3])
|
|
93
93
|
}
|
|
94
|
-
throw Conversions.
|
|
94
|
+
throw Conversions.ConvertingException<CGRect>(value)
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
|
|
@@ -99,9 +99,9 @@ extension CGColor: ConvertibleArgument {
|
|
|
99
99
|
public static func convert(from value: Any?) throws -> Self {
|
|
100
100
|
do {
|
|
101
101
|
return try UIColor.convert(from: value).cgColor as! Self
|
|
102
|
-
} catch _ as Conversions.
|
|
102
|
+
} catch _ as Conversions.ConvertingException<UIColor> {
|
|
103
103
|
// Rethrow `ConvertingError` with proper type
|
|
104
|
-
throw Conversions.
|
|
104
|
+
throw Conversions.ConvertingException<CGColor>(value)
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
}
|
|
@@ -43,10 +43,10 @@ public protocol EnumArgument: AnyArgument {
|
|
|
43
43
|
public extension EnumArgument where Self: RawRepresentable, Self: Hashable {
|
|
44
44
|
static func create<ArgType>(fromRawValue rawValue: ArgType) throws -> Self {
|
|
45
45
|
guard let rawValue = rawValue as? RawValue else {
|
|
46
|
-
throw
|
|
46
|
+
throw EnumCastingException((type: RawValue.self, value: rawValue))
|
|
47
47
|
}
|
|
48
48
|
guard let enumCase = Self.init(rawValue: rawValue) else {
|
|
49
|
-
throw
|
|
49
|
+
throw EnumNoSuchValueException((type: Self.self, value: rawValue))
|
|
50
50
|
}
|
|
51
51
|
return enumCase
|
|
52
52
|
}
|
|
@@ -75,31 +75,25 @@ public extension EnumArgument where Self: RawRepresentable, Self: Hashable {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
/**
|
|
78
|
-
An error that is thrown when the value cannot be
|
|
78
|
+
An error that is thrown when the value cannot be cast to associated `RawValue`.
|
|
79
79
|
*/
|
|
80
|
-
internal
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
var description: String {
|
|
85
|
-
"Cannot cast value `\(value)` to expected type `\(type)`"
|
|
80
|
+
internal class EnumCastingException: GenericException<(type: Any.Type, value: Any)> {
|
|
81
|
+
override var reason: String {
|
|
82
|
+
"Unable to cast '\(param.value)' to expected type \(param.type)"
|
|
86
83
|
}
|
|
87
84
|
}
|
|
88
85
|
|
|
89
86
|
/**
|
|
90
87
|
An error that is thrown when the value doesn't match any available case.
|
|
91
88
|
*/
|
|
92
|
-
internal
|
|
93
|
-
let type: EnumArgument.Type
|
|
94
|
-
let value: Any
|
|
95
|
-
|
|
89
|
+
internal class EnumNoSuchValueException: GenericException<(type: EnumArgument.Type, value: Any)> {
|
|
96
90
|
var allRawValuesFormatted: String {
|
|
97
|
-
return type.allRawValues
|
|
98
|
-
.map { "
|
|
91
|
+
return param.type.allRawValues
|
|
92
|
+
.map { "'\($0)'" }
|
|
99
93
|
.joined(separator: ", ")
|
|
100
94
|
}
|
|
101
95
|
|
|
102
|
-
var
|
|
103
|
-
"
|
|
96
|
+
override var reason: String {
|
|
97
|
+
"'\(param.value)' is not present in \(param.type) enum, it must be one of: \(allRawValuesFormatted)"
|
|
104
98
|
}
|
|
105
99
|
}
|