expo-modules-core 1.2.7 → 1.3.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 +28 -5
- package/ExpoModulesCore.podspec +1 -0
- package/README.md +1 -1
- package/android/ExpoModulesCorePlugin.gradle +16 -0
- package/android/build.gradle +3 -2
- package/android/src/main/cpp/Exceptions.cpp +8 -0
- package/android/src/main/cpp/Exceptions.h +11 -0
- package/android/src/main/cpp/ExpoModulesHostObject.cpp +22 -5
- package/android/src/main/cpp/ExpoModulesHostObject.h +5 -0
- package/android/src/main/cpp/JNIInjector.cpp +2 -0
- package/android/src/main/cpp/JSIInteropModuleRegistry.cpp +25 -1
- package/android/src/main/cpp/JSIInteropModuleRegistry.h +14 -0
- package/android/src/main/cpp/JSIObjectWrapper.h +15 -4
- package/android/src/main/cpp/JSITypeConverter.h +3 -2
- package/android/src/main/cpp/JavaReferencesCache.cpp +2 -0
- package/android/src/main/cpp/JavaScriptFunction.cpp +56 -0
- package/android/src/main/cpp/JavaScriptFunction.h +54 -0
- package/android/src/main/cpp/JavaScriptModuleObject.cpp +225 -105
- package/android/src/main/cpp/JavaScriptModuleObject.h +67 -34
- package/android/src/main/cpp/JavaScriptObject.cpp +55 -1
- package/android/src/main/cpp/JavaScriptObject.h +17 -13
- package/android/src/main/cpp/JavaScriptRuntime.cpp +12 -3
- package/android/src/main/cpp/JavaScriptRuntime.h +9 -1
- package/android/src/main/cpp/JavaScriptValue.cpp +9 -0
- package/android/src/main/cpp/JavaScriptValue.h +4 -0
- package/android/src/main/cpp/MethodMetadata.cpp +66 -87
- package/android/src/main/cpp/MethodMetadata.h +18 -16
- package/android/src/main/cpp/ObjectDeallocator.h +25 -0
- package/android/src/main/cpp/WeakRuntimeHolder.cpp +7 -0
- package/android/src/main/cpp/WeakRuntimeHolder.h +4 -0
- package/android/src/main/cpp/types/CppType.h +4 -1
- package/android/src/main/cpp/types/FrontendConverter.cpp +58 -0
- package/android/src/main/cpp/types/FrontendConverter.h +45 -0
- package/android/src/main/cpp/types/FrontendConverterProvider.cpp +3 -0
- package/android/src/main/cpp/types/JNIToJSIConverter.cpp +88 -0
- package/android/src/main/cpp/types/JNIToJSIConverter.h +22 -0
- package/android/src/main/java/com/facebook/react/uimanager/ReactStylesDiffMapHelper.kt +10 -0
- package/android/src/main/java/expo/modules/kotlin/AppContext.kt +8 -25
- package/android/src/main/java/expo/modules/kotlin/FilteredIterator.kt +37 -0
- package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +1 -1
- package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +30 -23
- package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +0 -3
- package/android/src/main/java/expo/modules/kotlin/Utils.kt +21 -0
- package/android/src/main/java/expo/modules/kotlin/activityresult/AppContextActivityResultCaller.kt +21 -1
- package/android/src/main/java/expo/modules/kotlin/classcomponent/ClassComponentBuilder.kt +112 -0
- package/android/src/main/java/expo/modules/kotlin/classcomponent/ClassDefinitionData.kt +10 -0
- package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +21 -0
- package/android/src/main/java/expo/modules/kotlin/exception/CommonExceptions.kt +15 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AnyFunction.kt +17 -3
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +38 -8
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionComponent.kt +3 -2
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromiseComponent.kt +3 -2
- package/android/src/main/java/expo/modules/kotlin/functions/SuspendFunctionComponent.kt +1 -0
- package/android/src/main/java/expo/modules/kotlin/functions/SyncFunctionComponent.kt +18 -11
- package/android/src/main/java/expo/modules/kotlin/jni/CppType.kt +4 -1
- package/android/src/main/java/expo/modules/kotlin/jni/JNIDeallocator.kt +73 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JSIInteropModuleRegistry.kt +28 -2
- package/android/src/main/java/expo/modules/kotlin/jni/JavaCallback.kt +8 -1
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptFunction.kt +48 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptModuleObject.kt +40 -3
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptObject.kt +23 -3
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptValue.kt +26 -1
- package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +0 -11
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +26 -16
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +3 -1
- package/android/src/main/java/expo/modules/kotlin/sharedobjects/SharedObject.kt +12 -0
- package/android/src/main/java/expo/modules/kotlin/sharedobjects/SharedObjectRegistry.kt +62 -0
- package/android/src/main/java/expo/modules/kotlin/sharedobjects/SharedObjectTypeConverter.kt +27 -0
- package/android/src/main/java/expo/modules/kotlin/types/AnyType.kt +2 -1
- package/android/src/main/java/expo/modules/kotlin/types/EitherTypeConverter.kt +7 -6
- package/android/src/main/java/expo/modules/kotlin/types/JavaScriptFunctionTypeConverter.kt +22 -0
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +30 -24
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +45 -1
- package/android/src/main/java/expo/modules/kotlin/types/TypedArrayTypeConverter.kt +3 -2
- package/android/src/main/java/expo/modules/kotlin/views/AnyViewProp.kt +3 -1
- package/android/src/main/java/expo/modules/kotlin/views/ConcreteViewProp.kt +3 -3
- package/android/src/main/java/expo/modules/kotlin/views/FilteredReadableMap.kt +53 -0
- package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +25 -5
- package/android/src/main/java/expo/modules/kotlin/views/SimpleViewManagerWrapper.kt +25 -5
- package/android/src/main/java/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +161 -10
- package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinitionBuilder.kt +0 -67
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +6 -7
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +40 -3
- package/android/src/main/java/expo/modules/kotlin/views/ViewTypeConverter.kt +44 -0
- package/android-annotation/build.gradle +45 -0
- package/android-annotation/src/main/java/expo/modules/annotation/Config.kt +7 -0
- package/android-annotation/src/main/java/expo/modules/annotation/ConverterBinder.kt +7 -0
- package/android-annotation-processor/build.gradle +51 -0
- package/android-annotation-processor/src/main/java/expo/modules/annotationprocessor/ExpoSymbolProcessor.kt +175 -0
- package/android-annotation-processor/src/main/java/expo/modules/annotationprocessor/ExpoSymbolProcessorProvider.kt +10 -0
- package/android-annotation-processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider +1 -0
- package/build/NativeViewManagerAdapter.native.d.ts.map +1 -1
- package/build/NativeViewManagerAdapter.native.js +36 -23
- package/build/NativeViewManagerAdapter.native.js.map +1 -1
- package/build/requireNativeModule.js +2 -2
- package/build/requireNativeModule.js.map +1 -1
- package/common/cpp/fabric/ExpoViewProps.cpp +18 -3
- package/common/cpp/fabric/ExpoViewProps.h +4 -1
- package/ios/Fabric/ExpoFabricView.swift +10 -10
- package/ios/Fabric/ExpoFabricViewObjC.h +2 -0
- package/ios/Fabric/ExpoFabricViewObjC.mm +17 -2
- package/ios/JSI/EXJSIInstaller.mm +1 -1
- package/ios/JSI/EXJSIUtils.h +5 -0
- package/ios/JSI/EXJSIUtils.mm +17 -0
- package/ios/JSI/EXJavaScriptRuntime.h +5 -0
- package/ios/JSI/EXJavaScriptRuntime.mm +6 -0
- package/ios/JSI/EXJavaScriptValue.h +2 -0
- package/ios/JSI/EXJavaScriptValue.mm +8 -0
- package/ios/JSI/EXJavaScriptWeakObject.mm +29 -8
- package/ios/JSI/EXRawJavaScriptFunction.h +24 -0
- package/ios/JSI/EXRawJavaScriptFunction.mm +52 -0
- package/ios/JSI/ExpoModulesHostObject.mm +1 -1
- package/ios/JSI/JavaScriptValue.swift +28 -1
- package/ios/ModuleRegistry/EXModuleRegistry.h +0 -4
- package/ios/ModuleRegistry/EXModuleRegistry.m +0 -23
- package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +0 -16
- package/ios/ModuleRegistryProvider/EXModuleRegistryProvider.m +0 -6
- package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +1 -31
- package/ios/Swift/AppContext.swift +46 -6
- package/ios/Swift/Arguments/Convertible.swift +3 -3
- package/ios/Swift/Arguments/Convertibles.swift +5 -5
- package/ios/Swift/Classes/ClassComponent.swift +18 -12
- package/ios/Swift/Classes/ClassRegistry.swift +31 -0
- package/ios/Swift/Conversions.swift +19 -3
- package/ios/Swift/Convertibles/Convertibles+Color.swift +3 -3
- package/ios/Swift/Convertibles/Either.swift +6 -4
- package/ios/Swift/DynamicTypes/AnyDynamicType.swift +18 -2
- package/ios/Swift/DynamicTypes/DynamicArrayType.swift +3 -3
- package/ios/Swift/DynamicTypes/DynamicConvertibleType.swift +2 -2
- package/ios/Swift/DynamicTypes/DynamicEnumType.swift +1 -1
- package/ios/Swift/DynamicTypes/DynamicJavaScriptType.swift +27 -0
- package/ios/Swift/DynamicTypes/DynamicOptionalType.swift +9 -2
- package/ios/Swift/DynamicTypes/DynamicRawType.swift +1 -1
- package/ios/Swift/DynamicTypes/DynamicSharedObjectType.swift +16 -2
- package/ios/Swift/DynamicTypes/DynamicType.swift +6 -0
- package/ios/Swift/DynamicTypes/DynamicTypedArrayType.swift +15 -4
- package/ios/Swift/DynamicTypes/DynamicViewType.swift +68 -0
- package/ios/Swift/ExpoBridgeModule.swift +1 -1
- package/ios/Swift/Functions/AnyFunction.swift +5 -4
- package/ios/Swift/Functions/AsyncFunctionComponent.swift +22 -19
- package/ios/Swift/Functions/ConcurrentFunctionDefinition.swift +29 -13
- package/ios/Swift/Functions/SyncFunctionComponent.swift +26 -15
- package/ios/Swift/JavaScriptFunction.swift +68 -0
- package/ios/Swift/JavaScriptUtils.swift +57 -18
- package/ios/Swift/ModuleHolder.swift +22 -10
- package/ios/Swift/Modules/ModuleDefinition.swift +8 -2
- package/ios/Swift/Objects/JavaScriptObjectBuilder.swift +8 -8
- package/ios/Swift/Objects/ObjectDefinition.swift +17 -15
- package/ios/Swift/Objects/PropertyComponent.swift +23 -17
- package/ios/Swift/Records/AnyField.swift +1 -1
- package/ios/Swift/Records/Field.swift +2 -2
- package/ios/Swift/Records/Record.swift +5 -5
- package/ios/Swift/SharedObjects/SharedObjectRegistry.swift +4 -0
- package/ios/Swift/Views/AnyViewProp.swift +1 -1
- package/ios/Swift/Views/ComponentData.swift +37 -2
- package/ios/Swift/Views/ConcreteViewProp.swift +2 -2
- package/ios/Swift/Views/ViewDefinition.swift +39 -0
- package/ios/Swift/Views/ViewModuleWrapper.swift +0 -29
- package/ios/Tests/ClassComponentSpec.swift +39 -27
- package/ios/Tests/ConvertiblesSpec.swift +75 -49
- package/ios/Tests/DynamicTypeSpec.swift +29 -27
- package/ios/Tests/EitherSpec.swift +9 -7
- package/ios/Tests/ExpoModulesSpec.swift +13 -13
- package/ios/Tests/FunctionSpec.swift +38 -22
- package/ios/Tests/JavaScriptRuntimeSpec.swift +4 -0
- package/ios/Tests/PropertyComponentSpec.swift +33 -30
- package/ios/Tests/RecordSpec.swift +7 -5
- package/ios/Tests/SharedObjectRegistrySpec.swift +12 -12
- package/ios/Tests/TypedArraysSpec.swift +1 -1
- package/ios/Tests/ViewDefinitionSpec.swift +4 -2
- package/package.json +2 -2
- package/src/NativeViewManagerAdapter.native.tsx +33 -29
- package/src/requireNativeModule.ts +2 -2
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +0 -132
- package/ios/EXViewManager.h +0 -21
- package/ios/EXViewManager.m +0 -128
- package/ios/ModuleRegistryAdapter/EXViewManagerAdapterClassesRegistry.h +0 -17
- package/ios/ModuleRegistryAdapter/EXViewManagerAdapterClassesRegistry.m +0 -67
- package/ios/ViewManagerAdapter/EXViewManagerAdapter.h +0 -17
- package/ios/ViewManagerAdapter/EXViewManagerAdapter.m +0 -45
|
@@ -151,15 +151,31 @@ internal final class Conversions {
|
|
|
151
151
|
/**
|
|
152
152
|
Converts the function result to the type compatible with JavaScript.
|
|
153
153
|
*/
|
|
154
|
-
static func convertFunctionResult<ValueType>(
|
|
154
|
+
static func convertFunctionResult<ValueType>(
|
|
155
|
+
_ value: ValueType?,
|
|
156
|
+
appContext: AppContext? = nil,
|
|
157
|
+
dynamicType: AnyDynamicType? = nil
|
|
158
|
+
) -> Any {
|
|
155
159
|
if let value = value as? Record {
|
|
156
160
|
return value.toDictionary()
|
|
157
161
|
}
|
|
158
162
|
if let value = value as? [Record] {
|
|
159
163
|
return value.map { $0.toDictionary() }
|
|
160
164
|
}
|
|
161
|
-
if let
|
|
162
|
-
|
|
165
|
+
if let appContext {
|
|
166
|
+
if let value = value as? JavaScriptObjectBuilder {
|
|
167
|
+
return try? value.build(appContext: appContext)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// If the returned value is a native shared object, create its JS representation and add the pair to the registry of shared objects.
|
|
171
|
+
if let value = value as? SharedObject, let dynamicType = dynamicType as? DynamicSharedObjectType {
|
|
172
|
+
guard let object = try? appContext.newObject(nativeClassId: dynamicType.typeIdentifier) else {
|
|
173
|
+
log.warn("Unable to create a JS object for \(dynamicType.description)")
|
|
174
|
+
return Optional<Any>.none
|
|
175
|
+
}
|
|
176
|
+
SharedObjectRegistry.add(native: value, javaScript: object)
|
|
177
|
+
return object
|
|
178
|
+
}
|
|
163
179
|
}
|
|
164
180
|
return value as Any
|
|
165
181
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
2
|
|
|
3
3
|
extension UIColor: Convertible {
|
|
4
|
-
public static func convert(from value: Any
|
|
4
|
+
public static func convert(from value: Any?, appContext: AppContext) throws -> Self {
|
|
5
5
|
// swiftlint:disable force_cast
|
|
6
6
|
if let value = value as? String {
|
|
7
7
|
if let namedColorComponents = namedColors[value] {
|
|
@@ -21,10 +21,10 @@ extension UIColor: Convertible {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
extension CGColor: Convertible {
|
|
24
|
-
public static func convert(from value: Any
|
|
24
|
+
public static func convert(from value: Any?, appContext: AppContext) throws -> Self {
|
|
25
25
|
// swiftlint:disable force_cast
|
|
26
26
|
do {
|
|
27
|
-
return try UIColor.convert(from: value).cgColor as! Self
|
|
27
|
+
return try UIColor.convert(from: value, appContext: appContext).cgColor as! Self
|
|
28
28
|
} catch _ as Conversions.ConvertingException<UIColor> {
|
|
29
29
|
// Rethrow `ConvertingError` with proper type
|
|
30
30
|
throw Conversions.ConvertingException<CGColor>(value)
|
|
@@ -50,14 +50,16 @@ open class Either<FirstType, SecondType>: Convertible {
|
|
|
50
50
|
|
|
51
51
|
// MARK: - Convertible
|
|
52
52
|
|
|
53
|
-
public class func convert(from value: Any
|
|
54
|
-
|
|
53
|
+
public class func convert(from value: Any?, appContext: AppContext) throws -> Self {
|
|
54
|
+
let dynamicTypes = dynamicTypes()
|
|
55
|
+
|
|
56
|
+
for type in dynamicTypes {
|
|
55
57
|
// Initialize the "either" when the current type can cast given value.
|
|
56
|
-
if let value = try? type.cast(value) {
|
|
58
|
+
if let value = try? type.cast(value, appContext: appContext) {
|
|
57
59
|
return Self(value)
|
|
58
60
|
}
|
|
59
61
|
}
|
|
60
|
-
throw NeitherTypeException(
|
|
62
|
+
throw NeitherTypeException(dynamicTypes)
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
65
|
|
|
@@ -17,10 +17,26 @@ public protocol AnyDynamicType: CustomStringConvertible {
|
|
|
17
17
|
func equals(_ type: AnyDynamicType) -> Bool
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
|
|
20
|
+
Preliminarily casts the given JavaScriptValue to a non-JS value that the other `cast` function can handle.
|
|
21
|
+
It **must** be run on the thread used by the JavaScript runtime.
|
|
22
|
+
*/
|
|
23
|
+
func cast(jsValue: JavaScriptValue, appContext: AppContext) throws -> Any
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
Casts the given value to the wrapped type and returns it as `Any`.
|
|
21
27
|
NOTE: It may not be just simple type-casting (e.g. when the wrapped type conforms to `Convertible`).
|
|
22
28
|
*/
|
|
23
|
-
func cast<ValueType>(_ value: ValueType) throws -> Any
|
|
29
|
+
func cast<ValueType>(_ value: ValueType, appContext: AppContext) throws -> Any
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
extension AnyDynamicType {
|
|
33
|
+
func cast(jsValue: JavaScriptValue, appContext: AppContext) throws -> Any {
|
|
34
|
+
return jsValue.getRaw()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
func cast<ValueType>(_ value: ValueType, appContext: AppContext) throws -> Any {
|
|
38
|
+
return value
|
|
39
|
+
}
|
|
24
40
|
}
|
|
25
41
|
|
|
26
42
|
// MARK: - Operators
|
|
@@ -21,13 +21,13 @@ internal struct DynamicArrayType: AnyDynamicType {
|
|
|
21
21
|
return false
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
func cast<ValueType>(_ value: ValueType) throws -> Any {
|
|
24
|
+
func cast<ValueType>(_ value: ValueType, appContext: AppContext) throws -> Any {
|
|
25
25
|
if let value = value as? [Any] {
|
|
26
|
-
return try value.map { try elementType.cast($0) }
|
|
26
|
+
return try value.map { try elementType.cast($0, appContext: appContext) }
|
|
27
27
|
}
|
|
28
28
|
// We should probably throw an error if we get here. On the other side, the array type
|
|
29
29
|
// requirement can be more loosen so we can try to arrayize values that are not arrays.
|
|
30
|
-
return [try elementType.cast(value)]
|
|
30
|
+
return [try elementType.cast(value, appContext: appContext)]
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
var description: String {
|
|
@@ -17,8 +17,8 @@ internal struct DynamicConvertibleType: AnyDynamicType {
|
|
|
17
17
|
return false
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
func cast<ValueType>(_ value: ValueType) throws -> Any {
|
|
21
|
-
return try innerType.convert(from: value)
|
|
20
|
+
func cast<ValueType>(_ value: ValueType, appContext: AppContext) throws -> Any {
|
|
21
|
+
return try innerType.convert(from: value, appContext: appContext)
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
var description: String {
|
|
@@ -17,7 +17,7 @@ internal struct DynamicEnumType: AnyDynamicType {
|
|
|
17
17
|
return false
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
func cast<ValueType>(_ value: ValueType) throws -> Any {
|
|
20
|
+
func cast<ValueType>(_ value: ValueType, appContext: AppContext) throws -> Any {
|
|
21
21
|
return try innerType.create(fromRawValue: value)
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
A dynamic type representing various types of JavaScript values.
|
|
5
|
+
*/
|
|
6
|
+
internal struct DynamicJavaScriptType: AnyDynamicType {
|
|
7
|
+
let innerType: AnyJavaScriptValue.Type
|
|
8
|
+
|
|
9
|
+
func wraps<InnerType>(_ type: InnerType.Type) -> Bool {
|
|
10
|
+
return innerType == InnerType.self
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
func equals(_ type: AnyDynamicType) -> Bool {
|
|
14
|
+
if let providedType = type as? Self {
|
|
15
|
+
return providedType.innerType == innerType
|
|
16
|
+
}
|
|
17
|
+
return false
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
func cast(jsValue: JavaScriptValue, appContext: AppContext) throws -> Any {
|
|
21
|
+
return try innerType.convert(from: jsValue, appContext: appContext)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var description: String {
|
|
25
|
+
return String(describing: innerType.self)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -21,11 +21,18 @@ internal struct DynamicOptionalType: AnyDynamicType {
|
|
|
21
21
|
return false
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
func cast
|
|
24
|
+
func cast(jsValue: JavaScriptValue, appContext: AppContext) throws -> Any {
|
|
25
|
+
if jsValue.isUndefined() || jsValue.isNull() {
|
|
26
|
+
return Optional<Any>.none as Any
|
|
27
|
+
}
|
|
28
|
+
return try wrappedType.cast(jsValue: jsValue, appContext: appContext)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
func cast<ValueType>(_ value: ValueType, appContext: AppContext) throws -> Any {
|
|
25
32
|
if Optional.isNil(value) || value is NSNull {
|
|
26
33
|
return Optional<Any>.none as Any
|
|
27
34
|
}
|
|
28
|
-
return try wrappedType.cast(value)
|
|
35
|
+
return try wrappedType.cast(value, appContext: appContext)
|
|
29
36
|
}
|
|
30
37
|
|
|
31
38
|
var description: String {
|
|
@@ -15,7 +15,7 @@ internal struct DynamicRawType<InnerType>: AnyDynamicType {
|
|
|
15
15
|
return type is Self
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
func cast<ValueType>(_ value: ValueType) throws -> Any {
|
|
18
|
+
func cast<ValueType>(_ value: ValueType, appContext: AppContext) throws -> Any {
|
|
19
19
|
if let value = value as? InnerType {
|
|
20
20
|
return value
|
|
21
21
|
}
|
|
@@ -6,6 +6,16 @@
|
|
|
6
6
|
internal struct DynamicSharedObjectType: AnyDynamicType {
|
|
7
7
|
let innerType: SharedObject.Type
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
A unique identifier of the wrapped type.
|
|
11
|
+
*/
|
|
12
|
+
let typeIdentifier: ObjectIdentifier
|
|
13
|
+
|
|
14
|
+
init<SharedObjectType: SharedObject>(innerType: SharedObjectType.Type) {
|
|
15
|
+
self.innerType = innerType
|
|
16
|
+
self.typeIdentifier = ObjectIdentifier(SharedObjectType.self)
|
|
17
|
+
}
|
|
18
|
+
|
|
9
19
|
func wraps<InnerType>(_ type: InnerType.Type) -> Bool {
|
|
10
20
|
return innerType == InnerType.self
|
|
11
21
|
}
|
|
@@ -17,12 +27,16 @@ internal struct DynamicSharedObjectType: AnyDynamicType {
|
|
|
17
27
|
return false
|
|
18
28
|
}
|
|
19
29
|
|
|
20
|
-
func cast<ValueType>(_ value: ValueType) throws -> Any {
|
|
30
|
+
func cast<ValueType>(_ value: ValueType, appContext: AppContext) throws -> Any {
|
|
21
31
|
if let value = value as? SharedObject, type(of: value) == innerType {
|
|
22
32
|
// Given value is a shared object already
|
|
23
33
|
return value
|
|
24
34
|
}
|
|
25
|
-
|
|
35
|
+
throw NativeSharedObjectNotFoundException()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
func cast(jsValue: JavaScriptValue, appContext: AppContext) throws -> Any {
|
|
39
|
+
if let jsObject = try? jsValue.asObject(),
|
|
26
40
|
let nativeSharedObject = SharedObjectRegistry.toNativeObject(jsObject) {
|
|
27
41
|
return nativeSharedObject
|
|
28
42
|
}
|
|
@@ -21,12 +21,18 @@ internal func DynamicType<T>(_ type: T.Type) -> AnyDynamicType {
|
|
|
21
21
|
if let EnumType = T.self as? any Enumerable.Type {
|
|
22
22
|
return DynamicEnumType(innerType: EnumType)
|
|
23
23
|
}
|
|
24
|
+
if let ViewType = T.self as? UIView.Type {
|
|
25
|
+
return DynamicViewType(innerType: ViewType)
|
|
26
|
+
}
|
|
24
27
|
if let SharedObjectType = T.self as? SharedObject.Type {
|
|
25
28
|
return DynamicSharedObjectType(innerType: SharedObjectType)
|
|
26
29
|
}
|
|
27
30
|
if let TypedArrayType = T.self as? AnyTypedArray.Type {
|
|
28
31
|
return DynamicTypedArrayType(innerType: TypedArrayType)
|
|
29
32
|
}
|
|
33
|
+
if let JavaScriptValueType = T.self as? any AnyJavaScriptValue.Type {
|
|
34
|
+
return DynamicJavaScriptType(innerType: JavaScriptValueType)
|
|
35
|
+
}
|
|
30
36
|
return DynamicRawType(innerType: T.self)
|
|
31
37
|
}
|
|
32
38
|
|
|
@@ -14,13 +14,24 @@ internal struct DynamicTypedArrayType: AnyDynamicType {
|
|
|
14
14
|
return false
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
/**
|
|
18
|
+
Converts JS typed array to its native representation.
|
|
19
|
+
*/
|
|
20
|
+
func cast(jsValue: JavaScriptValue, appContext: AppContext) throws -> Any {
|
|
21
|
+
guard let jsTypedArray = jsValue.getTypedArray() else {
|
|
20
22
|
throw NotTypedArrayException(innerType)
|
|
21
23
|
}
|
|
22
|
-
|
|
24
|
+
return TypedArray.create(from: jsTypedArray)
|
|
25
|
+
}
|
|
23
26
|
|
|
27
|
+
/**
|
|
28
|
+
Converts the given native `TypedArray` to a concrete typed array class wrapped by the dynamic type.
|
|
29
|
+
Throws `ArrayTypeMismatchException` otherwise.
|
|
30
|
+
*/
|
|
31
|
+
func cast<ValueType>(_ value: ValueType, appContext: AppContext) throws -> Any {
|
|
32
|
+
guard let typedArray = value as? TypedArray else {
|
|
33
|
+
throw NotTypedArrayException(innerType)
|
|
34
|
+
}
|
|
24
35
|
// Concrete typed arrays must be the same as the inner type.
|
|
25
36
|
guard innerType == TypedArray.self || type(of: typedArray) == innerType else {
|
|
26
37
|
throw ArrayTypeMismatchException((received: type(of: typedArray), expected: innerType))
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Copyright 2023-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
internal struct DynamicViewType: AnyDynamicType {
|
|
4
|
+
let innerType: UIView.Type
|
|
5
|
+
|
|
6
|
+
func wraps<InnerType>(_ type: InnerType.Type) -> Bool {
|
|
7
|
+
return innerType == InnerType.self
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
func equals(_ type: AnyDynamicType) -> Bool {
|
|
11
|
+
if let viewType = type as? Self {
|
|
12
|
+
return viewType.innerType == innerType
|
|
13
|
+
}
|
|
14
|
+
return false
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
Casts from the React component instance to the view tag (`Int`).
|
|
19
|
+
*/
|
|
20
|
+
func cast(jsValue: JavaScriptValue, appContext: AppContext) throws -> Any {
|
|
21
|
+
guard let viewTag = findViewTag(jsValue) else {
|
|
22
|
+
throw InvalidViewTagException()
|
|
23
|
+
}
|
|
24
|
+
return viewTag
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
Converts a value of type `Int` to a native view with that tag in the given app context.
|
|
29
|
+
*/
|
|
30
|
+
func cast<ValueType>(_ value: ValueType, appContext: AppContext) throws -> Any {
|
|
31
|
+
guard let viewTag = value as? Int else {
|
|
32
|
+
throw InvalidViewTagException()
|
|
33
|
+
}
|
|
34
|
+
guard Thread.isMainThread else {
|
|
35
|
+
throw NonMainThreadException()
|
|
36
|
+
}
|
|
37
|
+
guard let view = appContext.findView(withTag: viewTag, ofType: innerType.self) else {
|
|
38
|
+
throw Exceptions.ViewNotFound((tag: viewTag, type: innerType.self))
|
|
39
|
+
}
|
|
40
|
+
return view
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
var description: String {
|
|
44
|
+
return "View<\(innerType)>"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private func findViewTag(_ value: JavaScriptValue) -> Int? {
|
|
49
|
+
if let viewTag = value as? Int {
|
|
50
|
+
return viewTag
|
|
51
|
+
}
|
|
52
|
+
if let value = value as? JavaScriptValue, value.isObject() {
|
|
53
|
+
return value.getObject().getProperty("nativeTag").getInt()
|
|
54
|
+
}
|
|
55
|
+
return nil
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
internal final class InvalidViewTagException: Exception {
|
|
59
|
+
override var reason: String {
|
|
60
|
+
"The view tag must be a number"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
internal final class NonMainThreadException: Exception {
|
|
65
|
+
override var reason: String {
|
|
66
|
+
"All operations on the views must run from the main UI thread"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -46,7 +46,7 @@ public final class ExpoBridgeModule: NSObject, RCTBridgeModule {
|
|
|
46
46
|
guard let self = self, let bridge = self.appContext.reactBridge else {
|
|
47
47
|
return
|
|
48
48
|
}
|
|
49
|
-
self.appContext.
|
|
49
|
+
self.appContext._runtime = EXJavaScriptRuntimeManager.runtime(fromBridge: bridge)
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
if bridge.responds(to: Selector(("runtime"))) {
|
|
@@ -41,9 +41,10 @@ internal protocol AnyFunction: AnyDefinition, JavaScriptObjectBuilder {
|
|
|
41
41
|
- args: An array of arguments to pass to the function. They could be Swift primitives
|
|
42
42
|
when invoked through the bridge and in unit tests or `JavaScriptValue`s
|
|
43
43
|
when the function is called through the JSI.
|
|
44
|
+
- appContext: An app context where the function is being executed.
|
|
44
45
|
- callback: A callback that receives a result of the function execution.
|
|
45
46
|
*/
|
|
46
|
-
func call(by owner: AnyObject?, withArguments args: [Any], callback: @escaping (FunctionCallResult) -> ())
|
|
47
|
+
func call(by owner: AnyObject?, withArguments args: [Any], appContext: AppContext, callback: @escaping (FunctionCallResult) -> ())
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
extension AnyFunction {
|
|
@@ -65,12 +66,12 @@ extension AnyFunction {
|
|
|
65
66
|
}
|
|
66
67
|
|
|
67
68
|
/**
|
|
68
|
-
Calls the function just like `call(by:withArguments:callback:)`, but without an owner
|
|
69
|
+
Calls the function just like `call(by:withArguments:appContext:callback:)`, but without an owner
|
|
69
70
|
and with an empty callback. Might be useful when you only want to call the function,
|
|
70
71
|
but don't care about the result.
|
|
71
72
|
*/
|
|
72
|
-
func call(withArguments args: [Any]) {
|
|
73
|
-
call(by: nil, withArguments: args, callback: { _ in })
|
|
73
|
+
func call(withArguments args: [Any], appContext: AppContext) {
|
|
74
|
+
call(by: nil, withArguments: args, appContext: appContext, callback: { _ in })
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
|
|
@@ -46,10 +46,8 @@ public final class AsyncFunctionComponent<Args, FirstArgType, ReturnType>: AnyAs
|
|
|
46
46
|
) {
|
|
47
47
|
self.name = name
|
|
48
48
|
self.takesPromise = dynamicArgumentTypes.last?.wraps(Promise.self) ?? false
|
|
49
|
+
self.dynamicArgumentTypes = dynamicArgumentTypes
|
|
49
50
|
self.body = body
|
|
50
|
-
|
|
51
|
-
// Drop the last argument type if it's the `Promise`.
|
|
52
|
-
self.dynamicArgumentTypes = takesPromise ? dynamicArgumentTypes.dropLast(1) : dynamicArgumentTypes
|
|
53
51
|
}
|
|
54
52
|
|
|
55
53
|
// MARK: - AnyFunction
|
|
@@ -59,25 +57,30 @@ public final class AsyncFunctionComponent<Args, FirstArgType, ReturnType>: AnyAs
|
|
|
59
57
|
let dynamicArgumentTypes: [AnyDynamicType]
|
|
60
58
|
|
|
61
59
|
var argumentsCount: Int {
|
|
62
|
-
return dynamicArgumentTypes.count - (takesOwner ? 1 : 0)
|
|
60
|
+
return dynamicArgumentTypes.count - (takesOwner ? 1 : 0) - (takesPromise ? 1 : 0)
|
|
63
61
|
}
|
|
64
62
|
|
|
65
63
|
var takesOwner: Bool = false
|
|
66
64
|
|
|
67
|
-
func call(by owner: AnyObject?, withArguments args: [Any], callback: @escaping (FunctionCallResult) -> ()) {
|
|
65
|
+
func call(by owner: AnyObject?, withArguments args: [Any], appContext: AppContext, callback: @escaping (FunctionCallResult) -> ()) {
|
|
68
66
|
let promise = Promise { value in
|
|
69
67
|
callback(.success(Conversions.convertFunctionResult(value)))
|
|
70
68
|
} rejecter: { exception in
|
|
71
69
|
callback(.failure(exception))
|
|
72
70
|
}
|
|
73
|
-
var arguments: [Any] =
|
|
71
|
+
var arguments: [Any] = concat(
|
|
72
|
+
arguments: args,
|
|
73
|
+
withOwner: owner,
|
|
74
|
+
withPromise: takesPromise ? promise : nil,
|
|
75
|
+
forFunction: self,
|
|
76
|
+
appContext: appContext
|
|
77
|
+
)
|
|
74
78
|
|
|
75
79
|
do {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
)
|
|
80
|
+
try validateArgumentsNumber(function: self, received: args.count)
|
|
81
|
+
|
|
82
|
+
// All `JavaScriptValue` args must be preliminarly converted on the JS thread, so before we jump to the function's queue.
|
|
83
|
+
arguments = try cast(jsValues: arguments, forFunction: self, appContext: appContext)
|
|
81
84
|
} catch let error as Exception {
|
|
82
85
|
callback(.failure(error))
|
|
83
86
|
return
|
|
@@ -86,18 +89,18 @@ public final class AsyncFunctionComponent<Args, FirstArgType, ReturnType>: AnyAs
|
|
|
86
89
|
return
|
|
87
90
|
}
|
|
88
91
|
|
|
89
|
-
// Add promise to the array of arguments if necessary.
|
|
90
|
-
if takesPromise {
|
|
91
|
-
arguments.append(promise)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
92
|
let queue = queue ?? defaultQueue
|
|
95
93
|
|
|
96
94
|
queue.async { [body, name] in
|
|
97
95
|
let returnedValue: ReturnType?
|
|
98
96
|
|
|
99
97
|
do {
|
|
98
|
+
// Convert arguments to the types desired by the function.
|
|
99
|
+
arguments = try cast(arguments: arguments, forFunction: self, appContext: appContext)
|
|
100
|
+
|
|
101
|
+
// swiftlint:disable:next force_cast
|
|
100
102
|
let argumentsTuple = try Conversions.toTuple(arguments) as! Args
|
|
103
|
+
|
|
101
104
|
returnedValue = try body(argumentsTuple)
|
|
102
105
|
} catch let error as Exception {
|
|
103
106
|
promise.reject(FunctionCallException(name).causedBy(error))
|
|
@@ -114,13 +117,13 @@ public final class AsyncFunctionComponent<Args, FirstArgType, ReturnType>: AnyAs
|
|
|
114
117
|
|
|
115
118
|
// MARK: - JavaScriptObjectBuilder
|
|
116
119
|
|
|
117
|
-
func build(
|
|
118
|
-
return runtime.createAsyncFunction(name, argsCount: argumentsCount) { [weak self, name] this, args, resolve, reject in
|
|
120
|
+
func build(appContext: AppContext) throws -> JavaScriptObject {
|
|
121
|
+
return try appContext.runtime.createAsyncFunction(name, argsCount: argumentsCount) { [weak self, name] this, args, resolve, reject in
|
|
119
122
|
guard let self = self else {
|
|
120
123
|
let exception = NativeFunctionUnavailableException(name)
|
|
121
124
|
return reject(exception.code, exception.description, nil)
|
|
122
125
|
}
|
|
123
|
-
self.call(by: this, withArguments: args) { result in
|
|
126
|
+
self.call(by: this, withArguments: args, appContext: appContext) { result in
|
|
124
127
|
switch result {
|
|
125
128
|
case .failure(let error):
|
|
126
129
|
reject(error.code, error.description, nil)
|
|
@@ -28,15 +28,22 @@ public final class ConcurrentFunctionDefinition<Args, FirstArgType, ReturnType>:
|
|
|
28
28
|
|
|
29
29
|
var takesOwner: Bool = false
|
|
30
30
|
|
|
31
|
-
func call(by owner: AnyObject?, withArguments args: [Any], callback: @escaping (FunctionCallResult) -> Void) {
|
|
32
|
-
|
|
31
|
+
func call(by owner: AnyObject?, withArguments args: [Any], appContext: AppContext, callback: @escaping (FunctionCallResult) -> Void) {
|
|
32
|
+
var arguments: [Any]
|
|
33
33
|
|
|
34
34
|
do {
|
|
35
|
+
try validateArgumentsNumber(function: self, received: args.count)
|
|
36
|
+
|
|
35
37
|
arguments = concat(
|
|
36
|
-
arguments:
|
|
38
|
+
arguments: args,
|
|
37
39
|
withOwner: owner,
|
|
38
|
-
|
|
40
|
+
withPromise: nil,
|
|
41
|
+
forFunction: self,
|
|
42
|
+
appContext: appContext
|
|
39
43
|
)
|
|
44
|
+
|
|
45
|
+
// All `JavaScriptValue` args must be preliminarly converted on the JS thread, before we jump to the function's queue.
|
|
46
|
+
arguments = try cast(jsValues: args, forFunction: self, appContext: appContext)
|
|
40
47
|
} catch let error as Exception {
|
|
41
48
|
callback(.failure(error))
|
|
42
49
|
return
|
|
@@ -50,9 +57,12 @@ public final class ConcurrentFunctionDefinition<Args, FirstArgType, ReturnType>:
|
|
|
50
57
|
let result: Result<Any, Exception>
|
|
51
58
|
|
|
52
59
|
do {
|
|
60
|
+
// Convert arguments to the types desired by the function.
|
|
61
|
+
let finalArguments = try cast(arguments: arguments, forFunction: self, appContext: appContext)
|
|
62
|
+
|
|
53
63
|
// TODO: Right now we force cast the tuple in all types of functions, but we should throw another exception here.
|
|
54
64
|
// swiftlint:disable force_cast
|
|
55
|
-
let argumentsTuple = try Conversions.toTuple(
|
|
65
|
+
let argumentsTuple = try Conversions.toTuple(finalArguments) as! Args
|
|
56
66
|
let returnValue = try await body(argumentsTuple)
|
|
57
67
|
|
|
58
68
|
result = .success(returnValue)
|
|
@@ -68,18 +78,24 @@ public final class ConcurrentFunctionDefinition<Args, FirstArgType, ReturnType>:
|
|
|
68
78
|
|
|
69
79
|
// MARK: - JavaScriptObjectBuilder
|
|
70
80
|
|
|
71
|
-
func build(
|
|
72
|
-
return runtime.createAsyncFunction(name, argsCount: argumentsCount) {
|
|
73
|
-
|
|
81
|
+
func build(appContext: AppContext) throws -> JavaScriptObject {
|
|
82
|
+
return try appContext.runtime.createAsyncFunction(name, argsCount: argumentsCount) {
|
|
83
|
+
[weak appContext, weak self, name] this, args, resolve, reject in
|
|
84
|
+
|
|
85
|
+
guard let appContext else {
|
|
86
|
+
let exception = Exceptions.AppContextLost()
|
|
87
|
+
return reject(exception.code, exception.description, nil)
|
|
88
|
+
}
|
|
89
|
+
guard let self else {
|
|
74
90
|
let exception = NativeFunctionUnavailableException(name)
|
|
75
91
|
return reject(exception.code, exception.description, nil)
|
|
76
92
|
}
|
|
77
|
-
self.call(by: this, withArguments: args) { result in
|
|
93
|
+
self.call(by: this, withArguments: args, appContext: appContext) { result in
|
|
78
94
|
switch result {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
95
|
+
case .failure(let error):
|
|
96
|
+
reject(error.code, error.description, nil)
|
|
97
|
+
case .success(let value):
|
|
98
|
+
resolve(value)
|
|
83
99
|
}
|
|
84
100
|
}
|
|
85
101
|
}
|
|
@@ -10,9 +10,10 @@ internal protocol AnySyncFunctionComponent: AnyFunction {
|
|
|
10
10
|
- owner: An object that calls this function. If the `takesOwner` property is true
|
|
11
11
|
and type of the first argument matches the owner type, it's being passed as the argument.
|
|
12
12
|
- args: An array of arguments to pass to the function. The arguments must be of the same type as in the underlying closure.
|
|
13
|
+
- appContext: An app context where the function is executed.
|
|
13
14
|
- Returns: A value returned by the called function when succeeded or an error when it failed.
|
|
14
15
|
*/
|
|
15
|
-
func call(by owner: AnyObject?, withArguments args: [Any]) throws -> Any
|
|
16
|
+
func call(by owner: AnyObject?, withArguments args: [Any], appContext: AppContext) throws -> Any
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -49,9 +50,9 @@ public final class SyncFunctionComponent<Args, FirstArgType, ReturnType>: AnySyn
|
|
|
49
50
|
|
|
50
51
|
var takesOwner: Bool = false
|
|
51
52
|
|
|
52
|
-
func call(by owner: AnyObject?, withArguments args: [Any], callback: @escaping (FunctionCallResult) -> ()) {
|
|
53
|
+
func call(by owner: AnyObject?, withArguments args: [Any], appContext: AppContext, callback: @escaping (FunctionCallResult) -> ()) {
|
|
53
54
|
do {
|
|
54
|
-
let result = try call(by: owner, withArguments: args)
|
|
55
|
+
let result = try call(by: owner, withArguments: args, appContext: appContext)
|
|
55
56
|
callback(.success(Conversions.convertFunctionResult(result)))
|
|
56
57
|
} catch let error as Exception {
|
|
57
58
|
callback(.failure(error))
|
|
@@ -62,16 +63,26 @@ public final class SyncFunctionComponent<Args, FirstArgType, ReturnType>: AnySyn
|
|
|
62
63
|
|
|
63
64
|
// MARK: - AnySyncFunctionComponent
|
|
64
65
|
|
|
65
|
-
func call(by owner: AnyObject?, withArguments args: [Any]) throws -> Any {
|
|
66
|
+
func call(by owner: AnyObject?, withArguments args: [Any], appContext: AppContext) throws -> Any {
|
|
66
67
|
do {
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
try validateArgumentsNumber(function: self, received: args.count)
|
|
69
|
+
|
|
70
|
+
var arguments = concat(
|
|
71
|
+
arguments: args,
|
|
69
72
|
withOwner: owner,
|
|
70
|
-
|
|
73
|
+
withPromise: nil,
|
|
74
|
+
forFunction: self,
|
|
75
|
+
appContext: appContext
|
|
71
76
|
)
|
|
77
|
+
|
|
78
|
+
// Convert JS values to non-JS native types.
|
|
79
|
+
arguments = try cast(jsValues: arguments, forFunction: self, appContext: appContext)
|
|
80
|
+
|
|
81
|
+
// Convert arguments to the types desired by the function.
|
|
82
|
+
arguments = try cast(arguments: arguments, forFunction: self, appContext: appContext)
|
|
83
|
+
|
|
72
84
|
let argumentsTuple = try Conversions.toTuple(arguments) as! Args
|
|
73
|
-
|
|
74
|
-
return Conversions.convertFunctionResult(result)
|
|
85
|
+
return try body(argumentsTuple)
|
|
75
86
|
} catch let error as Exception {
|
|
76
87
|
throw FunctionCallException(name).causedBy(error)
|
|
77
88
|
} catch {
|
|
@@ -81,17 +92,17 @@ public final class SyncFunctionComponent<Args, FirstArgType, ReturnType>: AnySyn
|
|
|
81
92
|
|
|
82
93
|
// MARK: - JavaScriptObjectBuilder
|
|
83
94
|
|
|
84
|
-
func build(
|
|
95
|
+
func build(appContext: AppContext) throws -> JavaScriptObject {
|
|
85
96
|
// We intentionally capture a strong reference to `self`, otherwise the "detached" objects would
|
|
86
97
|
// immediately lose the reference to the definition and thus the underlying native function.
|
|
87
98
|
// It may potentially cause memory leaks, but at the time of writing this comment,
|
|
88
99
|
// the native definition instance deallocates correctly when the JS VM triggers the garbage collector.
|
|
89
|
-
return runtime.createSyncFunction(name, argsCount: argumentsCount) { [weak
|
|
90
|
-
guard let
|
|
91
|
-
throw Exceptions.
|
|
100
|
+
return try appContext.runtime.createSyncFunction(name, argsCount: argumentsCount) { [weak appContext, self] this, args in
|
|
101
|
+
guard let appContext else {
|
|
102
|
+
throw Exceptions.AppContextLost()
|
|
92
103
|
}
|
|
93
|
-
let result = try self.call(by: this, withArguments: args)
|
|
94
|
-
return Conversions.convertFunctionResult(result,
|
|
104
|
+
let result = try self.call(by: this, withArguments: args, appContext: appContext)
|
|
105
|
+
return Conversions.convertFunctionResult(result, appContext: appContext, dynamicType: ~ReturnType.self)
|
|
95
106
|
}
|
|
96
107
|
}
|
|
97
108
|
}
|