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
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Copyright 2023-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
Represents a JavaScript function that can be called by the native code and that must return the given generic `ReturnType`.
|
|
5
|
+
*/
|
|
6
|
+
public final class JavaScriptFunction<ReturnType>: AnyArgument, AnyJavaScriptValue {
|
|
7
|
+
/**
|
|
8
|
+
Raw representation of the JavaScript function that doesn't impose any restrictions on the returned type.
|
|
9
|
+
*/
|
|
10
|
+
private let rawFunction: RawJavaScriptFunction
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
Weak reference to the app context that is necessary to convert some arguments associated with the context (e.g. shared objects).
|
|
14
|
+
*/
|
|
15
|
+
private weak var appContext: AppContext?
|
|
16
|
+
|
|
17
|
+
init(rawFunction: RawJavaScriptFunction, appContext: AppContext) {
|
|
18
|
+
self.rawFunction = rawFunction
|
|
19
|
+
self.appContext = appContext
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// MARK: - Calling
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
Calls the function with the given `this` object and arguments.
|
|
26
|
+
*/
|
|
27
|
+
public func call(_ arguments: Any..., usingThis this: JavaScriptObject? = nil) throws -> ReturnType {
|
|
28
|
+
return try call(withArguments: arguments, asConstructor: false, usingThis: this)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
Calls the function as a constructor with the given arguments. It's like calling a function with the `new` keyword.
|
|
33
|
+
*/
|
|
34
|
+
public func callAsConstructor(_ arguments: Any...) throws -> ReturnType {
|
|
35
|
+
return try call(withArguments: arguments, asConstructor: true, usingThis: nil)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
Universal function that calls the function with given arguments, this object and whether to call it as a constructor.
|
|
40
|
+
*/
|
|
41
|
+
private func call(withArguments arguments: [Any] = [], asConstructor: Bool = false, usingThis this: JavaScriptObject? = nil) throws -> ReturnType {
|
|
42
|
+
guard let appContext else {
|
|
43
|
+
throw AppContextLostException()
|
|
44
|
+
}
|
|
45
|
+
let value = rawFunction.call(withArguments: arguments, thisObject: this, asConstructor: false)
|
|
46
|
+
let dynamicType = ~ReturnType.self
|
|
47
|
+
|
|
48
|
+
guard let result = try dynamicType.cast(jsValue: value, appContext: appContext) as? ReturnType else {
|
|
49
|
+
throw UnexpectedReturnType(dynamicType.description)
|
|
50
|
+
}
|
|
51
|
+
return result
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// MARK: - AnyJavaScriptValue
|
|
55
|
+
|
|
56
|
+
internal static func convert(from value: JavaScriptValue, appContext: AppContext) throws -> Self {
|
|
57
|
+
guard value.kind == .function else {
|
|
58
|
+
throw Conversions.ConvertingException<JavaScriptFunction<ReturnType>>(value)
|
|
59
|
+
}
|
|
60
|
+
return Self(rawFunction: value.getFunction(), appContext: appContext)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private final class UnexpectedReturnType: GenericException<String> {
|
|
65
|
+
override var reason: String {
|
|
66
|
+
return "The function returned a value that cannot be converted to \(param)"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
- Returns: A new value converted according to the dynamic type.
|
|
11
11
|
- Throws: Rethrows various exceptions that could be thrown by the dynamic types.
|
|
12
12
|
*/
|
|
13
|
-
internal func cast(_ value: Any, toType type: AnyDynamicType) throws -> Any {
|
|
13
|
+
internal func cast(_ value: Any, toType type: AnyDynamicType, appContext: AppContext) throws -> Any {
|
|
14
14
|
// TODO: Accept JavaScriptValue and JavaScriptObject as argument types.
|
|
15
15
|
if !(type is DynamicTypedArrayType), let value = value as? JavaScriptValue {
|
|
16
|
-
return try type.cast(value.getRaw())
|
|
16
|
+
return try type.cast(value.getRaw(), appContext: appContext)
|
|
17
17
|
}
|
|
18
|
-
return try type.cast(value)
|
|
18
|
+
return try type.cast(value, appContext: appContext)
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -23,46 +23,85 @@ internal func cast(_ value: Any, toType type: AnyDynamicType) throws -> Any {
|
|
|
23
23
|
- Parameters:
|
|
24
24
|
- arguments: An array of arguments to be cast.
|
|
25
25
|
- function: A function for which to cast the arguments.
|
|
26
|
+
- appContext: A context of the app.
|
|
26
27
|
- Returns: An array of arguments after casting. Its size is the same as the input arrays.
|
|
27
28
|
- Throws: `InvalidArgsNumberException` when the number of arguments is not equal to the actual number
|
|
28
29
|
of function's arguments (without an owner and promise). Rethrows exceptions thrown by `cast(_:toType:)`.
|
|
29
30
|
*/
|
|
30
|
-
internal func cast(arguments: [Any], forFunction function: AnyFunction) throws -> [Any] {
|
|
31
|
-
let requiredArgumentsCount = function.requiredArgumentsCount
|
|
32
|
-
let argumentTypeOffset = function.takesOwner ? 1 : 0
|
|
33
|
-
|
|
34
|
-
if arguments.count < requiredArgumentsCount || arguments.count > function.argumentsCount {
|
|
35
|
-
throw InvalidArgsNumberException((
|
|
36
|
-
received: arguments.count,
|
|
37
|
-
expected: function.argumentsCount,
|
|
38
|
-
required: requiredArgumentsCount
|
|
39
|
-
))
|
|
40
|
-
}
|
|
31
|
+
internal func cast(arguments: [Any], forFunction function: AnyFunction, appContext: AppContext) throws -> [Any] {
|
|
41
32
|
return try arguments.enumerated().map { index, argument in
|
|
42
|
-
let argumentType = function.dynamicArgumentTypes[index
|
|
33
|
+
let argumentType = function.dynamicArgumentTypes[index]
|
|
43
34
|
|
|
44
35
|
do {
|
|
45
|
-
return try cast(argument, toType: argumentType)
|
|
36
|
+
return try cast(argument, toType: argumentType, appContext: appContext)
|
|
46
37
|
} catch {
|
|
47
38
|
throw ArgumentCastException((index: index, type: argumentType)).causedBy(error)
|
|
48
39
|
}
|
|
49
40
|
}
|
|
50
41
|
}
|
|
51
42
|
|
|
43
|
+
/**
|
|
44
|
+
Casts an array of JavaScript values to non-JavaScript types.
|
|
45
|
+
*/
|
|
46
|
+
internal func cast(jsValues: [Any], forFunction function: AnyFunction, appContext: AppContext) throws -> [Any] {
|
|
47
|
+
// TODO: Replace `[Any]` with `[JavaScriptValue]` once we make sure only JS values are passed here
|
|
48
|
+
return try jsValues.enumerated().map { index, jsValue in
|
|
49
|
+
let type = function.dynamicArgumentTypes[index]
|
|
50
|
+
|
|
51
|
+
do {
|
|
52
|
+
// Temporarily some values might already be cast to primitive types, so make sure we cast only `JavaScriptValue` and leave the others as they are.
|
|
53
|
+
if let jsValue = jsValue as? JavaScriptValue {
|
|
54
|
+
return try type.cast(jsValue: jsValue, appContext: appContext)
|
|
55
|
+
} else {
|
|
56
|
+
return jsValue
|
|
57
|
+
}
|
|
58
|
+
} catch {
|
|
59
|
+
throw ArgumentCastException((index: index, type: type)).causedBy(error)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
Validates whether the number of received arguments is enough to call the given function.
|
|
66
|
+
Throws `InvalidArgsNumberException` otherwise.
|
|
67
|
+
*/
|
|
68
|
+
internal func validateArgumentsNumber(function: AnyFunction, received: Int) throws {
|
|
69
|
+
let argumentsCount = function.argumentsCount
|
|
70
|
+
let requiredArgumentsCount = function.requiredArgumentsCount
|
|
71
|
+
|
|
72
|
+
if received < requiredArgumentsCount || received > argumentsCount {
|
|
73
|
+
throw InvalidArgsNumberException((
|
|
74
|
+
received: received,
|
|
75
|
+
expected: argumentsCount,
|
|
76
|
+
required: requiredArgumentsCount
|
|
77
|
+
))
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
52
81
|
/**
|
|
53
82
|
Ensures the provided array of arguments matches the number of arguments expected by the function.
|
|
54
83
|
- If the function takes the owner, it's added to the beginning.
|
|
55
84
|
- If the array is still too small, missing arguments are very likely to be optional so it puts `nil` in their place.
|
|
56
85
|
*/
|
|
57
|
-
internal func concat(
|
|
86
|
+
internal func concat(
|
|
87
|
+
arguments: [Any],
|
|
88
|
+
withOwner owner: AnyObject?,
|
|
89
|
+
withPromise promise: Promise?,
|
|
90
|
+
forFunction function: AnyFunction,
|
|
91
|
+
appContext: AppContext
|
|
92
|
+
) -> [Any] {
|
|
58
93
|
var result = arguments
|
|
59
94
|
|
|
60
|
-
if function.takesOwner
|
|
95
|
+
if function.takesOwner {
|
|
61
96
|
result = [owner] + arguments
|
|
62
97
|
}
|
|
63
98
|
if arguments.count < function.argumentsCount {
|
|
64
99
|
result += Array(repeating: Any?.none as Any, count: function.argumentsCount - arguments.count)
|
|
65
100
|
}
|
|
101
|
+
// Add promise to the array of arguments if necessary.
|
|
102
|
+
if let promise {
|
|
103
|
+
result += [promise]
|
|
104
|
+
}
|
|
66
105
|
return result
|
|
67
106
|
}
|
|
68
107
|
|
|
@@ -62,24 +62,28 @@ public final class ModuleHolder {
|
|
|
62
62
|
// MARK: Calling functions
|
|
63
63
|
|
|
64
64
|
func call(function functionName: String, args: [Any], _ callback: @escaping (FunctionCallResult) -> () = { _ in }) {
|
|
65
|
+
guard let appContext else {
|
|
66
|
+
callback(.failure(Exceptions.AppContextLost()))
|
|
67
|
+
return
|
|
68
|
+
}
|
|
65
69
|
guard let function = definition.functions[functionName] else {
|
|
66
70
|
callback(.failure(FunctionNotFoundException((functionName: functionName, moduleName: self.name))))
|
|
67
71
|
return
|
|
68
72
|
}
|
|
69
|
-
function.call(by: self, withArguments: args, callback: callback)
|
|
73
|
+
function.call(by: self, withArguments: args, appContext: appContext, callback: callback)
|
|
70
74
|
}
|
|
71
75
|
|
|
72
76
|
@discardableResult
|
|
73
77
|
func callSync(function functionName: String, args: [Any]) -> Any? {
|
|
74
|
-
guard let function = definition.functions[functionName] as? AnySyncFunctionComponent else {
|
|
78
|
+
guard let appContext, let function = definition.functions[functionName] as? AnySyncFunctionComponent else {
|
|
75
79
|
return nil
|
|
76
80
|
}
|
|
77
81
|
do {
|
|
78
|
-
let arguments = try cast(arguments: args, forFunction: function)
|
|
79
|
-
let result = try function.call(by: self, withArguments: arguments)
|
|
82
|
+
let arguments = try cast(arguments: args, forFunction: function, appContext: appContext)
|
|
83
|
+
let result = try function.call(by: self, withArguments: arguments, appContext: appContext)
|
|
80
84
|
|
|
81
85
|
if let result = result as? SharedObject {
|
|
82
|
-
let jsObject = SharedObjectRegistry.ensureSharedJavaScriptObject(runtime: appContext
|
|
86
|
+
let jsObject = SharedObjectRegistry.ensureSharedJavaScriptObject(runtime: try appContext.runtime, nativeObject: result)
|
|
83
87
|
return jsObject
|
|
84
88
|
}
|
|
85
89
|
return result
|
|
@@ -98,11 +102,16 @@ public final class ModuleHolder {
|
|
|
98
102
|
*/
|
|
99
103
|
private func createJavaScriptModuleObject() -> JavaScriptObject? {
|
|
100
104
|
// It might be impossible to create any object at the moment (e.g. remote debugging, app context destroyed)
|
|
101
|
-
guard let
|
|
105
|
+
guard let appContext else {
|
|
106
|
+
return nil
|
|
107
|
+
}
|
|
108
|
+
do {
|
|
109
|
+
log.info("Creating JS object for module '\(name)'")
|
|
110
|
+
return try definition.build(appContext: appContext)
|
|
111
|
+
} catch {
|
|
112
|
+
log.error("Building the module object failed: \(error)")
|
|
102
113
|
return nil
|
|
103
114
|
}
|
|
104
|
-
log.info("Creating JS object for module '\(name)'")
|
|
105
|
-
return definition.build(inRuntime: runtime)
|
|
106
115
|
}
|
|
107
116
|
|
|
108
117
|
// MARK: Listening to native events
|
|
@@ -131,10 +140,13 @@ public final class ModuleHolder {
|
|
|
131
140
|
Modifies module's listeners count and calls `onStartObserving` or `onStopObserving` accordingly.
|
|
132
141
|
*/
|
|
133
142
|
func modifyListenersCount(_ count: Int) {
|
|
143
|
+
guard let appContext else {
|
|
144
|
+
return
|
|
145
|
+
}
|
|
134
146
|
if count > 0 && listenersCount == 0 {
|
|
135
|
-
definition.functions["startObserving"]?.call(withArguments: [])
|
|
147
|
+
definition.functions["startObserving"]?.call(withArguments: [], appContext: appContext)
|
|
136
148
|
} else if count < 0 && listenersCount + count <= 0 {
|
|
137
|
-
definition.functions["stopObserving"]?.call(withArguments: [])
|
|
149
|
+
definition.functions["stopObserving"]?.call(withArguments: [], appContext: appContext)
|
|
138
150
|
}
|
|
139
151
|
listenersCount = max(0, listenersCount + count)
|
|
140
152
|
}
|
|
@@ -65,8 +65,14 @@ public final class ModuleDefinition: ObjectDefinition {
|
|
|
65
65
|
return self
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
public override func build(
|
|
69
|
-
let object = super.build(
|
|
68
|
+
public override func build(appContext: AppContext) throws -> JavaScriptObject {
|
|
69
|
+
let object = try super.build(appContext: appContext)
|
|
70
|
+
|
|
71
|
+
if let viewManager {
|
|
72
|
+
let reactComponentPrototype = try appContext.runtime.createObject()
|
|
73
|
+
try viewManager.decorateWithFunctions(object: reactComponentPrototype, appContext: appContext)
|
|
74
|
+
object.setProperty("ViewPrototype", value: reactComponentPrototype)
|
|
75
|
+
}
|
|
70
76
|
|
|
71
77
|
// Give the module object a name. It's used for compatibility reasons, see `EventEmitter.ts`.
|
|
72
78
|
object.defineProperty("__expo_module_name__", value: name, options: [])
|
|
@@ -7,7 +7,7 @@ internal protocol JavaScriptObjectDecorator {
|
|
|
7
7
|
/**
|
|
8
8
|
Decorates an existing `JavaScriptObject`.
|
|
9
9
|
*/
|
|
10
|
-
func decorate(object: JavaScriptObject,
|
|
10
|
+
func decorate(object: JavaScriptObject, appContext: AppContext) throws
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -15,23 +15,23 @@ internal protocol JavaScriptObjectDecorator {
|
|
|
15
15
|
*/
|
|
16
16
|
internal protocol JavaScriptObjectBuilder: JavaScriptObjectDecorator {
|
|
17
17
|
/**
|
|
18
|
-
Creates a decorated `JavaScriptObject` in the given
|
|
18
|
+
Creates a decorated `JavaScriptObject` in the given app context.
|
|
19
19
|
*/
|
|
20
|
-
func build(
|
|
20
|
+
func build(appContext: AppContext) throws -> JavaScriptObject
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
Provides the default behavior of `JavaScriptObjectBuilder`.
|
|
25
|
-
The `build(
|
|
25
|
+
The `build(appContext:)` creates a plain object and uses `decorate(object:appContext:)` for decoration.
|
|
26
26
|
*/
|
|
27
27
|
extension JavaScriptObjectBuilder {
|
|
28
|
-
func build(
|
|
29
|
-
let object = runtime.createObject()
|
|
30
|
-
decorate(object: object,
|
|
28
|
+
func build(appContext: AppContext) throws -> JavaScriptObject {
|
|
29
|
+
let object = try appContext.runtime.createObject()
|
|
30
|
+
try decorate(object: object, appContext: appContext)
|
|
31
31
|
return object
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
func decorate(object: JavaScriptObject,
|
|
34
|
+
func decorate(object: JavaScriptObject, appContext: AppContext) throws {
|
|
35
35
|
// no-op by default
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -61,43 +61,45 @@ public class ObjectDefinition: AnyDefinition, JavaScriptObjectBuilder {
|
|
|
61
61
|
|
|
62
62
|
// MARK: - JavaScriptObjectBuilder
|
|
63
63
|
|
|
64
|
-
public func build(
|
|
65
|
-
let object = runtime.createObject()
|
|
66
|
-
decorate(object: object,
|
|
64
|
+
public func build(appContext: AppContext) throws -> JavaScriptObject {
|
|
65
|
+
let object = try appContext.runtime.createObject()
|
|
66
|
+
try decorate(object: object, appContext: appContext)
|
|
67
67
|
return object
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
public func decorate(object: JavaScriptObject,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
70
|
+
public func decorate(object: JavaScriptObject, appContext: AppContext) throws {
|
|
71
|
+
let runtime = try appContext.runtime
|
|
72
|
+
|
|
73
|
+
decorateWithConstants(object: object)
|
|
74
|
+
try decorateWithFunctions(object: object, appContext: appContext)
|
|
75
|
+
try decorateWithProperties(object: object, appContext: appContext)
|
|
76
|
+
try decorateWithClasses(object: object, appContext: appContext)
|
|
75
77
|
}
|
|
76
78
|
|
|
77
79
|
// MARK: - Internals
|
|
78
80
|
|
|
79
|
-
internal func decorateWithConstants(
|
|
81
|
+
internal func decorateWithConstants(object: JavaScriptObject) {
|
|
80
82
|
for (key, value) in getConstants() {
|
|
81
83
|
object.setProperty(key, value: value)
|
|
82
84
|
}
|
|
83
85
|
}
|
|
84
86
|
|
|
85
|
-
internal func decorateWithFunctions(
|
|
87
|
+
internal func decorateWithFunctions(object: JavaScriptObject, appContext: AppContext) throws {
|
|
86
88
|
for fn in functions.values {
|
|
87
|
-
object.setProperty(fn.name, value: fn.build(
|
|
89
|
+
object.setProperty(fn.name, value: try fn.build(appContext: appContext))
|
|
88
90
|
}
|
|
89
91
|
}
|
|
90
92
|
|
|
91
|
-
internal func decorateWithProperties(
|
|
93
|
+
internal func decorateWithProperties(object: JavaScriptObject, appContext: AppContext) throws {
|
|
92
94
|
for property in properties.values {
|
|
93
|
-
let descriptor = property.buildDescriptor(
|
|
95
|
+
let descriptor = try property.buildDescriptor(appContext: appContext)
|
|
94
96
|
object.defineProperty(property.name, descriptor: descriptor)
|
|
95
97
|
}
|
|
96
98
|
}
|
|
97
99
|
|
|
98
|
-
internal func decorateWithClasses(
|
|
100
|
+
internal func decorateWithClasses(object: JavaScriptObject, appContext: AppContext) throws {
|
|
99
101
|
for klass in classes.values {
|
|
100
|
-
object.setProperty(klass.name, value: klass.build(
|
|
102
|
+
object.setProperty(klass.name, value: try klass.build(appContext: appContext))
|
|
101
103
|
}
|
|
102
104
|
}
|
|
103
105
|
}
|
|
@@ -9,7 +9,7 @@ protocol AnyPropertyComponent {
|
|
|
9
9
|
/**
|
|
10
10
|
Creates the JavaScript object representing the property descriptor.
|
|
11
11
|
*/
|
|
12
|
-
func buildDescriptor(
|
|
12
|
+
func buildDescriptor(appContext: AppContext) throws -> JavaScriptObject
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
public final class PropertyComponent<OwnerType>: AnyDefinition, AnyPropertyComponent {
|
|
@@ -119,60 +119,66 @@ public final class PropertyComponent<OwnerType>: AnyDefinition, AnyPropertyCompo
|
|
|
119
119
|
|
|
120
120
|
// MARK: - Internals
|
|
121
121
|
|
|
122
|
-
internal func getValue<ValueType>(owner: OwnerType? = nil) throws -> ValueType? {
|
|
122
|
+
internal func getValue<ValueType>(owner: OwnerType? = nil, appContext: AppContext) throws -> ValueType? {
|
|
123
123
|
let owner = owner as? AnyObject
|
|
124
|
-
let value = try getter?.call(by: owner, withArguments: [])
|
|
124
|
+
let value = try getter?.call(by: owner, withArguments: [], appContext: appContext)
|
|
125
125
|
return value as? ValueType
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
internal func setValue(_ value: Any, owner: OwnerType? = nil) {
|
|
128
|
+
internal func setValue(_ value: Any, owner: OwnerType? = nil, appContext: AppContext) {
|
|
129
129
|
let owner = owner as? AnyObject
|
|
130
|
-
_ = try? setter?.call(by: owner, withArguments: [value])
|
|
130
|
+
_ = try? setter?.call(by: owner, withArguments: [value], appContext: appContext)
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
/**
|
|
134
134
|
Creates the JavaScript function that will be used as a getter of the property.
|
|
135
135
|
*/
|
|
136
|
-
internal func buildGetter(
|
|
137
|
-
return runtime.createSyncFunction(name, argsCount: 0) { [weak self, name] this, args in
|
|
138
|
-
guard let
|
|
136
|
+
internal func buildGetter(appContext: AppContext) throws -> JavaScriptObject {
|
|
137
|
+
return try appContext.runtime.createSyncFunction(name, argsCount: 0) { [weak appContext, weak self, name] this, args in
|
|
138
|
+
guard let appContext else {
|
|
139
|
+
throw Exceptions.AppContextLost()
|
|
140
|
+
}
|
|
141
|
+
guard let self else {
|
|
139
142
|
throw NativePropertyUnavailableException(name)
|
|
140
143
|
}
|
|
141
144
|
guard let getter = self.getter else {
|
|
142
145
|
return
|
|
143
146
|
}
|
|
144
|
-
return try getter.call(by: this, withArguments: args)
|
|
147
|
+
return try getter.call(by: this, withArguments: args, appContext: appContext)
|
|
145
148
|
}
|
|
146
149
|
}
|
|
147
150
|
|
|
148
151
|
/**
|
|
149
152
|
Creates the JavaScript function that will be used as a setter of the property.
|
|
150
153
|
*/
|
|
151
|
-
internal func buildSetter(
|
|
152
|
-
return runtime.createSyncFunction(name, argsCount: 1) { [weak self, name] this, args in
|
|
153
|
-
guard let
|
|
154
|
+
internal func buildSetter(appContext: AppContext) throws -> JavaScriptObject {
|
|
155
|
+
return try appContext.runtime.createSyncFunction(name, argsCount: 1) { [weak appContext, weak self, name] this, args in
|
|
156
|
+
guard let appContext else {
|
|
157
|
+
throw Exceptions.AppContextLost()
|
|
158
|
+
}
|
|
159
|
+
guard let self else {
|
|
154
160
|
throw NativePropertyUnavailableException(name)
|
|
155
161
|
}
|
|
156
162
|
guard let setter = self.setter else {
|
|
157
163
|
return
|
|
158
164
|
}
|
|
159
|
-
return try setter.call(by: this, withArguments: args)
|
|
165
|
+
return try setter.call(by: this, withArguments: args, appContext: appContext)
|
|
160
166
|
}
|
|
161
167
|
}
|
|
162
168
|
|
|
163
169
|
/**
|
|
164
170
|
Creates the JavaScript object representing the property descriptor.
|
|
165
171
|
*/
|
|
166
|
-
internal func buildDescriptor(
|
|
167
|
-
let descriptor = runtime.createObject()
|
|
172
|
+
internal func buildDescriptor(appContext: AppContext) throws -> JavaScriptObject {
|
|
173
|
+
let descriptor = try appContext.runtime.createObject()
|
|
168
174
|
|
|
169
175
|
descriptor.setProperty("enumerable", value: true)
|
|
170
176
|
|
|
171
177
|
if getter != nil {
|
|
172
|
-
descriptor.setProperty("get", value: buildGetter(
|
|
178
|
+
descriptor.setProperty("get", value: try buildGetter(appContext: appContext))
|
|
173
179
|
}
|
|
174
180
|
if setter != nil {
|
|
175
|
-
descriptor.setProperty("set", value: buildSetter(
|
|
181
|
+
descriptor.setProperty("set", value: try buildSetter(appContext: appContext))
|
|
176
182
|
}
|
|
177
183
|
return descriptor
|
|
178
184
|
}
|
|
@@ -74,12 +74,12 @@ public final class Field<Type>: AnyFieldInternal {
|
|
|
74
74
|
/**
|
|
75
75
|
Sets the wrapped value with a value of `Any` type.
|
|
76
76
|
*/
|
|
77
|
-
internal func set(_ newValue: Any
|
|
77
|
+
internal func set(_ newValue: Any?, appContext: AppContext) throws {
|
|
78
78
|
if newValue == nil && (!isOptional || isRequired) {
|
|
79
79
|
throw FieldRequiredException(key!)
|
|
80
80
|
}
|
|
81
81
|
do {
|
|
82
|
-
if let value = try fieldType.cast(newValue) as? Type {
|
|
82
|
+
if let value = try fieldType.cast(newValue, appContext: appContext) as? Type {
|
|
83
83
|
wrappedValue = value
|
|
84
84
|
}
|
|
85
85
|
} catch {
|
|
@@ -15,7 +15,7 @@ public protocol Record: Convertible {
|
|
|
15
15
|
/**
|
|
16
16
|
Initializes a record from given dictionary. Only members wrapped by `@Field` will be set in the object.
|
|
17
17
|
*/
|
|
18
|
-
init(from: Dict) throws
|
|
18
|
+
init(from: Dict, appContext: AppContext) throws
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
Converts the record back to the dictionary. Only members wrapped by `@Field` will be set in the dictionary.
|
|
@@ -27,14 +27,14 @@ public protocol Record: Convertible {
|
|
|
27
27
|
Provides the default implementation of `Record` protocol.
|
|
28
28
|
*/
|
|
29
29
|
public extension Record {
|
|
30
|
-
static func convert(from value: Any
|
|
30
|
+
static func convert(from value: Any?, appContext: AppContext) throws -> Self {
|
|
31
31
|
if let value = value as? Dict {
|
|
32
|
-
return try Self(from: value)
|
|
32
|
+
return try Self(from: value, appContext: appContext)
|
|
33
33
|
}
|
|
34
34
|
throw Conversions.ConvertingException<Self>(value)
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
init(from dict: Dict) throws {
|
|
37
|
+
init(from dict: Dict, appContext: AppContext) throws {
|
|
38
38
|
self.init()
|
|
39
39
|
|
|
40
40
|
let dictKeys = dict.keys
|
|
@@ -45,7 +45,7 @@ public extension Record {
|
|
|
45
45
|
return
|
|
46
46
|
}
|
|
47
47
|
if dictKeys.contains(key) || field.isRequired {
|
|
48
|
-
try field.set(dict[key])
|
|
48
|
+
try field.set(dict[key], appContext: appContext)
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
}
|
|
@@ -43,6 +43,37 @@ public final class ComponentData: RCTComponentData {
|
|
|
43
43
|
return super.createPropBlock(propName, isShadowView: isShadowView)
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
public override func setProps(_ props: [String: Any], forView view: RCTComponent) {
|
|
47
|
+
guard let view = view as? UIView else {
|
|
48
|
+
log.warn("Given view is not an UIView")
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
guard let viewManager = moduleHolder?.viewManager else {
|
|
52
|
+
log.warn("View manager '\(self.name)' not found")
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
guard let appContext = moduleHolder?.appContext else {
|
|
56
|
+
log.warn("App context has been lost")
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
let propsDict = viewManager.propsDict()
|
|
60
|
+
var remainingProps = props
|
|
61
|
+
|
|
62
|
+
for (key, prop) in propsDict {
|
|
63
|
+
let newValue = props[key] as Any
|
|
64
|
+
|
|
65
|
+
// TODO: @tsapeta: Figure out better way to rethrow errors from here.
|
|
66
|
+
try? prop.set(value: Conversions.fromNSObject(newValue), onView: view, appContext: appContext)
|
|
67
|
+
|
|
68
|
+
remainingProps.removeValue(forKey: key)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Let the base class `RCTComponentData` handle all remaining props.
|
|
72
|
+
super.setProps(remainingProps, forView: view)
|
|
73
|
+
|
|
74
|
+
viewManager.callLifecycleMethods(withType: .didUpdateProps, forView: view)
|
|
75
|
+
}
|
|
76
|
+
|
|
46
77
|
/**
|
|
47
78
|
The base `RCTComponentData` class does some Objective-C dynamic calls in this function, but we don't
|
|
48
79
|
need to do these slow operations since the Sweet API gives us necessary details without reflections.
|
|
@@ -52,8 +83,12 @@ public final class ComponentData: RCTComponentData {
|
|
|
52
83
|
var directEvents: [String] = []
|
|
53
84
|
let superClass: AnyClass? = managerClass.superclass()
|
|
54
85
|
|
|
55
|
-
if let
|
|
56
|
-
for
|
|
86
|
+
if let viewManager = moduleHolder?.viewManager {
|
|
87
|
+
for prop in viewManager.props {
|
|
88
|
+
// `id` allows every type to be passed in
|
|
89
|
+
propTypes[prop.name] = "id"
|
|
90
|
+
}
|
|
91
|
+
for eventName in viewManager.eventNames {
|
|
57
92
|
directEvents.append(RCTNormalizeInputEventName(eventName))
|
|
58
93
|
propTypes[eventName] = "BOOL"
|
|
59
94
|
}
|
|
@@ -32,13 +32,13 @@ public final class ConcreteViewProp<ViewType: UIView, PropType: AnyArgument>: An
|
|
|
32
32
|
/**
|
|
33
33
|
Function that sets the underlying prop value for given view.
|
|
34
34
|
*/
|
|
35
|
-
public func set(value: Any, onView view: UIView) throws {
|
|
35
|
+
public func set(value: Any, onView view: UIView, appContext: AppContext) throws {
|
|
36
36
|
// Method's signature must be type-erased to conform to `AnyViewProp` protocol.
|
|
37
37
|
// Given view must be castable to the generic `ViewType` type.
|
|
38
38
|
guard let view = view as? ViewType else {
|
|
39
39
|
throw IncompatibleViewException((propName: name, viewType: ViewType.self))
|
|
40
40
|
}
|
|
41
|
-
guard let value = try propType.cast(value) as? PropType else {
|
|
41
|
+
guard let value = try propType.cast(value, appContext: appContext) as? PropType else {
|
|
42
42
|
throw Conversions.CastingException<PropType>(value)
|
|
43
43
|
}
|
|
44
44
|
setter(view, value)
|