expo-modules-core 0.9.2 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -5
- package/android/CMakeLists.txt +154 -0
- package/android/build.gradle +293 -5
- package/android/src/main/cpp/Exceptions.cpp +22 -0
- package/android/src/main/cpp/Exceptions.h +38 -0
- package/android/src/main/cpp/ExpoModulesHostObject.cpp +47 -0
- package/android/src/main/cpp/ExpoModulesHostObject.h +32 -0
- package/android/src/main/cpp/JNIFunctionBody.cpp +29 -0
- package/android/src/main/cpp/JNIFunctionBody.h +50 -0
- package/android/src/main/cpp/JNIInjector.cpp +19 -0
- package/android/src/main/cpp/JSIInteropModuleRegistry.cpp +122 -0
- package/android/src/main/cpp/JSIInteropModuleRegistry.h +96 -0
- package/android/src/main/cpp/JSIObjectWrapper.h +33 -0
- package/android/src/main/cpp/JSITypeConverter.h +84 -0
- package/android/src/main/cpp/JavaScriptModuleObject.cpp +138 -0
- package/android/src/main/cpp/JavaScriptModuleObject.h +122 -0
- package/android/src/main/cpp/JavaScriptObject.cpp +125 -0
- package/android/src/main/cpp/JavaScriptObject.h +131 -0
- package/android/src/main/cpp/JavaScriptRuntime.cpp +127 -0
- package/android/src/main/cpp/JavaScriptRuntime.h +87 -0
- package/android/src/main/cpp/JavaScriptValue.cpp +172 -0
- package/android/src/main/cpp/JavaScriptValue.h +78 -0
- package/android/src/main/cpp/MethodMetadata.cpp +230 -0
- package/android/src/main/cpp/MethodMetadata.h +92 -0
- package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +2 -0
- package/android/src/main/java/expo/modules/core/errors/ContextDestroyedException.kt +7 -0
- package/android/src/main/java/expo/modules/interfaces/permissions/Permissions.java +30 -0
- package/android/src/main/java/expo/modules/kotlin/AppContext.kt +49 -1
- package/android/src/main/java/expo/modules/kotlin/ConcatIterator.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +15 -12
- package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +39 -3
- package/android/src/main/java/expo/modules/kotlin/defaultmodules/ErrorManagerModule.kt +2 -2
- package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +13 -0
- package/android/src/main/java/expo/modules/kotlin/exception/ExceptionDecorator.kt +2 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AnyFunction.kt +19 -14
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +29 -7
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +13 -13
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionComponent.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromiseComponent.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/functions/SuspendFunctionComponent.kt +56 -0
- package/android/src/main/java/expo/modules/kotlin/functions/SyncFunctionComponent.kt +28 -0
- package/android/src/main/java/expo/modules/kotlin/jni/CppType.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JNIFunctionBody.kt +39 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JSIInteropModuleRegistry.kt +89 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptModuleObject.kt +44 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptObject.kt +113 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptValue.kt +35 -0
- package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +15 -5
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +65 -111
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +35 -2
- package/android/src/main/java/expo/modules/kotlin/providers/AppContextProvider.kt +14 -0
- package/android/src/main/java/expo/modules/kotlin/providers/CurrentActivityProvider.kt +22 -0
- package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +19 -2
- package/android/src/main/java/expo/modules/kotlin/types/AnyType.kt +3 -2
- package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +7 -2
- package/android/src/main/java/expo/modules/kotlin/types/BasicTypeConverters.kt +68 -20
- package/android/src/main/java/expo/modules/kotlin/types/EnumTypeConverter.kt +50 -22
- package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +18 -2
- package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +18 -2
- package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +17 -2
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +43 -3
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +5 -0
- package/build/NativeModulesProxy.native.d.ts.map +1 -1
- package/build/NativeModulesProxy.native.js +9 -3
- package/build/NativeModulesProxy.native.js.map +1 -1
- package/ios/AppDelegates/EXAppDelegatesLoader.m +1 -2
- package/ios/ExpoModulesCore.podspec +1 -1
- package/ios/JSI/EXJSIConversions.mm +6 -0
- package/ios/JSI/EXJSIInstaller.h +15 -21
- package/ios/JSI/EXJSIInstaller.mm +39 -3
- package/ios/JSI/EXJSIUtils.h +47 -3
- package/ios/JSI/EXJSIUtils.mm +88 -4
- package/ios/JSI/EXJavaScriptObject.h +11 -18
- package/ios/JSI/EXJavaScriptObject.mm +37 -18
- package/ios/JSI/EXJavaScriptRuntime.h +43 -9
- package/ios/JSI/EXJavaScriptRuntime.mm +70 -27
- package/ios/JSI/EXJavaScriptTypedArray.h +30 -0
- package/ios/JSI/EXJavaScriptTypedArray.mm +29 -0
- package/ios/JSI/EXJavaScriptValue.h +3 -2
- package/ios/JSI/EXJavaScriptValue.mm +17 -20
- package/ios/JSI/EXJavaScriptWeakObject.h +23 -0
- package/ios/JSI/EXJavaScriptWeakObject.mm +53 -0
- package/ios/JSI/EXObjectDeallocator.h +27 -0
- package/ios/JSI/ExpoModulesHostObject.h +3 -3
- package/ios/JSI/ExpoModulesHostObject.mm +4 -4
- package/ios/JSI/JavaScriptRuntime.swift +38 -1
- package/ios/JSI/JavaScriptValue.swift +7 -0
- package/ios/JSI/TypedArray.cpp +67 -0
- package/ios/JSI/TypedArray.h +46 -0
- package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +0 -11
- package/ios/NativeModulesProxy/EXNativeModulesProxy.h +17 -10
- package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +85 -77
- package/ios/NativeModulesProxy/NativeModulesProxyModule.swift +17 -0
- package/ios/Services/EXReactNativeEventEmitter.h +2 -2
- package/ios/Services/EXReactNativeEventEmitter.m +11 -6
- package/ios/Swift/AppContext.swift +208 -28
- package/ios/Swift/Arguments/AnyArgument.swift +18 -0
- package/ios/Swift/Arguments/{Types/EnumArgumentType.swift → EnumArgument.swift} +2 -17
- package/ios/Swift/Classes/ClassComponent.swift +95 -0
- package/ios/Swift/Classes/ClassComponentElement.swift +33 -0
- package/ios/Swift/Classes/ClassComponentElementsBuilder.swift +34 -0
- package/ios/Swift/Classes/ClassComponentFactories.swift +96 -0
- package/ios/Swift/DynamicTypes/AnyDynamicType.swift +44 -0
- package/ios/Swift/DynamicTypes/DynamicArrayType.swift +56 -0
- package/ios/Swift/DynamicTypes/DynamicConvertibleType.swift +27 -0
- package/ios/Swift/DynamicTypes/DynamicEnumType.swift +27 -0
- package/ios/Swift/DynamicTypes/DynamicOptionalType.swift +63 -0
- package/ios/Swift/DynamicTypes/DynamicRawType.swift +33 -0
- package/ios/Swift/DynamicTypes/DynamicSharedObjectType.swift +37 -0
- package/ios/Swift/DynamicTypes/DynamicType.swift +39 -0
- package/ios/Swift/DynamicTypes/DynamicTypedArrayType.swift +46 -0
- package/ios/Swift/Exceptions/CodedError.swift +1 -1
- package/ios/Swift/Exceptions/Exception.swift +8 -6
- package/ios/Swift/Exceptions/UnexpectedException.swift +2 -1
- package/ios/Swift/ExpoBridgeModule.m +5 -0
- package/ios/Swift/ExpoBridgeModule.swift +65 -0
- package/ios/Swift/Functions/AnyFunction.swift +33 -31
- package/ios/Swift/Functions/AsyncFunctionComponent.swift +196 -59
- package/ios/Swift/Functions/SyncFunctionComponent.swift +142 -58
- package/ios/Swift/JavaScriptUtils.swift +32 -57
- package/ios/Swift/Logging/LogHandlers.swift +39 -0
- package/ios/Swift/Logging/LogType.swift +62 -0
- package/ios/Swift/Logging/Logger.swift +198 -0
- package/ios/Swift/ModuleHolder.swift +19 -54
- package/ios/Swift/ModuleRegistry.swift +7 -1
- package/ios/Swift/Modules/AnyModule.swift +3 -3
- package/ios/Swift/ModulesProvider.swift +2 -0
- package/ios/Swift/Objects/JavaScriptObjectBuilder.swift +37 -0
- package/ios/Swift/Objects/ObjectDefinition.swift +74 -1
- package/ios/Swift/Objects/ObjectDefinitionComponents.swift +77 -68
- package/ios/Swift/Objects/PropertyComponent.swift +147 -0
- package/ios/Swift/Promise.swift +12 -3
- package/ios/Swift/Records/Field.swift +2 -2
- package/ios/Swift/SharedObjects/SharedObject.swift +20 -0
- package/ios/Swift/SharedObjects/SharedObjectRegistry.swift +129 -0
- package/ios/Swift/TypedArrays/AnyTypedArray.swift +11 -0
- package/ios/Swift/TypedArrays/ConcreteTypedArrays.swift +56 -0
- package/ios/Swift/TypedArrays/GenericTypedArray.swift +49 -0
- package/ios/Swift/TypedArrays/TypedArray.swift +80 -0
- package/ios/Swift/Utilities.swift +28 -0
- package/ios/Swift/Views/ConcreteViewProp.swift +3 -3
- package/ios/Swift/Views/ViewManagerDefinitionComponents.swift +2 -2
- package/ios/Tests/ClassComponentSpec.swift +210 -0
- package/ios/Tests/DynamicTypeSpec.swift +336 -0
- package/ios/Tests/EnumArgumentSpec.swift +48 -0
- package/ios/Tests/ExpoModulesSpec.swift +17 -3
- package/ios/Tests/FunctionSpec.swift +167 -118
- package/ios/Tests/Mocks/ModuleMocks.swift +1 -1
- package/ios/Tests/PropertyComponentSpec.swift +95 -0
- package/ios/Tests/SharedObjectRegistrySpec.swift +109 -0
- package/ios/Tests/TypedArraysSpec.swift +136 -0
- package/package.json +2 -2
- package/src/NativeModulesProxy.native.ts +13 -3
- package/src/ts-declarations/ExpoModules.d.ts +7 -0
- package/tsconfig.json +1 -1
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromise.kt +0 -15
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncSuspendFunction.kt +0 -36
- package/ios/Swift/Arguments/AnyArgumentType.swift +0 -13
- package/ios/Swift/Arguments/ArgumentType.swift +0 -28
- package/ios/Swift/Arguments/Types/ArrayArgumentType.swift +0 -42
- package/ios/Swift/Arguments/Types/ConvertibleArgumentType.swift +0 -16
- package/ios/Swift/Arguments/Types/OptionalArgumentType.swift +0 -49
- package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +0 -15
- package/ios/Swift/Arguments/Types/RawArgumentType.swift +0 -25
- package/ios/Swift/Functions/ConcreteFunction.swift +0 -103
- package/ios/Swift/SwiftInteropBridge.swift +0 -155
- package/ios/Tests/ArgumentTypeSpec.swift +0 -143
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import ExpoModulesTestCore
|
|
4
|
+
|
|
5
|
+
@testable import ExpoModulesCore
|
|
6
|
+
|
|
7
|
+
final class TypedArraysSpec: ExpoSpec {
|
|
8
|
+
override func spec() {
|
|
9
|
+
describe("module") {
|
|
10
|
+
let appContext = AppContext.create()
|
|
11
|
+
let runtime = appContext.runtime!
|
|
12
|
+
|
|
13
|
+
beforeSuite {
|
|
14
|
+
appContext.moduleRegistry.register(moduleType: TypedArraysModule.self)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Gets the value at index 3 from the array
|
|
18
|
+
it("reads from Int8Array") {
|
|
19
|
+
let intValue = try runtime
|
|
20
|
+
.eval([
|
|
21
|
+
"typedArray = new Int8Array([2, 1, 3, 7])",
|
|
22
|
+
"ExpoModules.TypedArrays.int8_subscript_get(typedArray, 3)",
|
|
23
|
+
])
|
|
24
|
+
.asInt()
|
|
25
|
+
|
|
26
|
+
expect(intValue) == 7
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Sets the value at index 1 to the random int
|
|
30
|
+
it("writes to Int8Array") {
|
|
31
|
+
let randomInt = Int.random(in: -128...127)
|
|
32
|
+
let array = try runtime
|
|
33
|
+
.eval([
|
|
34
|
+
"typedArray = new Int8Array(3)",
|
|
35
|
+
"ExpoModules.TypedArrays.int8_subscript_set(typedArray, 1, \(randomInt))",
|
|
36
|
+
"Array.from(typedArray)",
|
|
37
|
+
])
|
|
38
|
+
.asArray()
|
|
39
|
+
|
|
40
|
+
expect(array[0]?.getInt()) == 0 // Remains unset
|
|
41
|
+
expect(array[1]?.getInt()) == randomInt
|
|
42
|
+
expect(array[2]?.getInt()) == 0 // Remains unset
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Gets a slice from the array from index 1 to 3
|
|
46
|
+
it("reads from UInt16Array slice") {
|
|
47
|
+
let values = try runtime
|
|
48
|
+
.eval([
|
|
49
|
+
"typedArray = new Uint16Array([0, 8, 4, 1])",
|
|
50
|
+
"ExpoModules.TypedArrays.uint16_subscript_range_get(typedArray, 1, 3)"
|
|
51
|
+
])
|
|
52
|
+
.asArray()
|
|
53
|
+
.map({ try $0?.asInt() })
|
|
54
|
+
|
|
55
|
+
expect(values.count) == 3
|
|
56
|
+
expect(values[0]) == 8
|
|
57
|
+
expect(values[1]) == 4
|
|
58
|
+
expect(values[2]) == 1
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Sets a slice of the array from index x to y
|
|
62
|
+
it("writes to UInt16Array slice") {
|
|
63
|
+
let random1 = Int.random(in: 0...65535)
|
|
64
|
+
let random2 = Int.random(in: 0...65535)
|
|
65
|
+
let values = try runtime
|
|
66
|
+
.eval([
|
|
67
|
+
"typedArray = new Uint16Array(4)",
|
|
68
|
+
"ExpoModules.TypedArrays.uint16_subscript_range_set(typedArray, 1, 2, [\(random1), \(random2)])",
|
|
69
|
+
"Array.from(typedArray)",
|
|
70
|
+
])
|
|
71
|
+
.asArray()
|
|
72
|
+
|
|
73
|
+
expect(values[0]?.getInt()) == 0 // Remains unset
|
|
74
|
+
expect(values[1]?.getInt()) == random1
|
|
75
|
+
expect(values[2]?.getInt()) == random2
|
|
76
|
+
expect(values[3]?.getInt()) == 0 // Remains unset
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
it("returns itself") {
|
|
80
|
+
let input = try runtime.eval("typedArray = new Float32Array([1.2, 3.4]); typedArray").asTypedArray()
|
|
81
|
+
let output = try runtime.eval("ExpoModules.TypedArrays.return(typedArray)").asTypedArray()
|
|
82
|
+
|
|
83
|
+
expect(input.getProperty("0").getDouble()) == output.getProperty("0").getDouble()
|
|
84
|
+
expect(input.getProperty("1").getDouble()) == output.getProperty("1").getDouble()
|
|
85
|
+
expect(input.getUnsafeMutableRawPointer()) == output.getUnsafeMutableRawPointer()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
it("writes to unsafe raw pointer") {
|
|
89
|
+
let count = 6
|
|
90
|
+
let values = try runtime
|
|
91
|
+
.eval([
|
|
92
|
+
"typedArray = new Uint8Array(\(count))",
|
|
93
|
+
"Array.from(ExpoModules.TypedArrays.writeToUnsafeRawPointer(typedArray))",
|
|
94
|
+
])
|
|
95
|
+
.asArray()
|
|
96
|
+
.map({ $0?.getInt() ?? 0 })
|
|
97
|
+
|
|
98
|
+
// Assume that at least one element should have changed
|
|
99
|
+
expect(values.filter({ $0 != 0 }).count) >= 1
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// TODO: Test throwing NotTypedArrayException and ArrayTypeMismatchException
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
fileprivate final class TypedArraysModule: Module {
|
|
108
|
+
func definition() -> ModuleDefinition {
|
|
109
|
+
Name("TypedArrays")
|
|
110
|
+
|
|
111
|
+
Function("int8_subscript_get") { (array: Int8Array, index: Int) in
|
|
112
|
+
return array[index]
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
Function("int8_subscript_set") { (array: Int8Array, index: Int, value: Int8) in
|
|
116
|
+
array[index] = value
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
Function("uint16_subscript_range_get") { (array: Uint16Array, start: Int, end: Int) in
|
|
120
|
+
return array[start...end]
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
Function("uint16_subscript_range_set") { (array: Uint16Array, start: Int, end: Int, values: [UInt16]) in
|
|
124
|
+
array[start...end] = values
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
Function("return") { (array: TypedArray) -> JavaScriptTypedArray in
|
|
128
|
+
return array.jsTypedArray
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
Function("writeToUnsafeRawPointer") { (array: TypedArray) -> JavaScriptTypedArray in
|
|
132
|
+
let _ = SecRandomCopyBytes(kSecRandomDefault, array.byteLength, array.rawPointer)
|
|
133
|
+
return array.jsTypedArray
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-modules-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "The core of Expo Modules architecture",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"@testing-library/react-hooks": "^7.0.1",
|
|
43
43
|
"expo-module-scripts": "^2.0.0"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "72253d4b18b62d329bbc6785d996e227f185d533"
|
|
46
46
|
}
|
|
@@ -2,15 +2,23 @@ import { NativeModules } from 'react-native';
|
|
|
2
2
|
|
|
3
3
|
import { ProxyNativeModule } from './NativeModulesProxy.types';
|
|
4
4
|
|
|
5
|
-
const
|
|
5
|
+
const ExpoNativeProxy = global.ExpoModules?.NativeModulesProxy;
|
|
6
|
+
const LegacyNativeProxy = NativeModules.NativeUnimoduleProxy;
|
|
7
|
+
|
|
6
8
|
const modulesConstantsKey = 'modulesConstants';
|
|
7
9
|
const exportedMethodsKey = 'exportedMethods';
|
|
8
10
|
|
|
9
11
|
const NativeModulesProxy: { [moduleName: string]: ProxyNativeModule } = {};
|
|
10
12
|
|
|
11
|
-
if (
|
|
13
|
+
if (LegacyNativeProxy) {
|
|
14
|
+
// use JSI proxy if available, fallback to legacy RN proxy
|
|
15
|
+
const NativeProxy = ExpoNativeProxy ?? LegacyNativeProxy;
|
|
16
|
+
|
|
12
17
|
Object.keys(NativeProxy[exportedMethodsKey]).forEach((moduleName) => {
|
|
18
|
+
// copy constants
|
|
13
19
|
NativeModulesProxy[moduleName] = NativeProxy[modulesConstantsKey][moduleName] || {};
|
|
20
|
+
|
|
21
|
+
// copy methods
|
|
14
22
|
NativeProxy[exportedMethodsKey][moduleName].forEach((methodInfo) => {
|
|
15
23
|
NativeModulesProxy[moduleName][methodInfo.name] = (...args: unknown[]): Promise<any> => {
|
|
16
24
|
const { key, argumentsCount } = methodInfo;
|
|
@@ -23,7 +31,9 @@ if (NativeProxy) {
|
|
|
23
31
|
)
|
|
24
32
|
);
|
|
25
33
|
}
|
|
26
|
-
|
|
34
|
+
|
|
35
|
+
// We still want to call methods using the legacy proxy in SDK 46
|
|
36
|
+
return LegacyNativeProxy.callMethod(moduleName, key, args);
|
|
27
37
|
};
|
|
28
38
|
});
|
|
29
39
|
|
package/tsconfig.json
CHANGED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
package expo.modules.kotlin.functions
|
|
2
|
-
|
|
3
|
-
import expo.modules.kotlin.ModuleHolder
|
|
4
|
-
import expo.modules.kotlin.Promise
|
|
5
|
-
import expo.modules.kotlin.types.AnyType
|
|
6
|
-
|
|
7
|
-
class AsyncFunctionWithPromise(
|
|
8
|
-
name: String,
|
|
9
|
-
argsType: Array<AnyType>,
|
|
10
|
-
private val body: (args: Array<out Any?>, promise: Promise) -> Unit
|
|
11
|
-
) : AnyFunction(name, argsType) {
|
|
12
|
-
override fun callImplementation(holder: ModuleHolder, args: Array<out Any?>, promise: Promise) {
|
|
13
|
-
body(args, promise)
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
package expo.modules.kotlin.functions
|
|
2
|
-
|
|
3
|
-
import expo.modules.kotlin.ModuleHolder
|
|
4
|
-
import expo.modules.kotlin.Promise
|
|
5
|
-
import expo.modules.kotlin.exception.CodedException
|
|
6
|
-
import expo.modules.kotlin.exception.FunctionCallException
|
|
7
|
-
import expo.modules.kotlin.exception.UnexpectedException
|
|
8
|
-
import expo.modules.kotlin.exception.exceptionDecorator
|
|
9
|
-
import expo.modules.kotlin.types.AnyType
|
|
10
|
-
import kotlinx.coroutines.CoroutineScope
|
|
11
|
-
import kotlinx.coroutines.isActive
|
|
12
|
-
import kotlinx.coroutines.launch
|
|
13
|
-
|
|
14
|
-
class AsyncSuspendFunction(
|
|
15
|
-
name: String,
|
|
16
|
-
argsType: Array<AnyType>,
|
|
17
|
-
private val body: suspend CoroutineScope.(args: Array<out Any?>) -> Any?
|
|
18
|
-
) : AnyFunction(name, argsType) {
|
|
19
|
-
override fun callImplementation(holder: ModuleHolder, args: Array<out Any?>, promise: Promise) {
|
|
20
|
-
val scope = holder.module.coroutineScopeDelegate.value
|
|
21
|
-
scope.launch {
|
|
22
|
-
try {
|
|
23
|
-
val result = exceptionDecorator({ cause -> FunctionCallException(name, holder.name, cause) }) {
|
|
24
|
-
body.invoke(scope, args)
|
|
25
|
-
}
|
|
26
|
-
if (isActive) {
|
|
27
|
-
promise.resolve(result)
|
|
28
|
-
}
|
|
29
|
-
} catch (e: CodedException) {
|
|
30
|
-
promise.reject(e)
|
|
31
|
-
} catch (e: Throwable) {
|
|
32
|
-
promise.reject(UnexpectedException(e))
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
A protocol whose intention is to wrap function's argument type
|
|
5
|
-
to keep its real signature and not type-erase it by the compiler.
|
|
6
|
-
*/
|
|
7
|
-
public protocol AnyArgumentType: CustomStringConvertible {
|
|
8
|
-
/**
|
|
9
|
-
Casts given any value to the wrapped type and returns as `Any`.
|
|
10
|
-
NOTE: It may not be just simple type-casting (e.g. when the wrapped type conforms to `ConvertibleArgument`).
|
|
11
|
-
*/
|
|
12
|
-
func cast<ArgType>(_ value: ArgType) throws -> Any
|
|
13
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
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
|
-
|
|
7
|
-
/**
|
|
8
|
-
Factory creating an instance of the argument type wrapper conforming to `AnyArgumentType`.
|
|
9
|
-
Depending on the given type, it may return one of `ArrayArgumentType`, `OptionalArgumentType`, `ConvertibleArgumentType`, etc.
|
|
10
|
-
*/
|
|
11
|
-
internal func ArgumentType<T>(_ type: T.Type) -> AnyArgumentType {
|
|
12
|
-
if let ArrayType = T.self as? AnyArrayArgument.Type {
|
|
13
|
-
return ArrayArgumentType(elementType: ArrayType.getElementArgumentType())
|
|
14
|
-
}
|
|
15
|
-
if let OptionalType = T.self as? AnyOptionalArgument.Type {
|
|
16
|
-
return OptionalArgumentType(wrappedType: OptionalType.getWrappedArgumentType())
|
|
17
|
-
}
|
|
18
|
-
if let ConvertibleType = T.self as? ConvertibleArgument.Type {
|
|
19
|
-
return ConvertibleArgumentType(innerType: ConvertibleType)
|
|
20
|
-
}
|
|
21
|
-
if let EnumType = T.self as? EnumArgument.Type {
|
|
22
|
-
return EnumArgumentType(innerType: EnumType)
|
|
23
|
-
}
|
|
24
|
-
if T.self is Promise.Type {
|
|
25
|
-
return PromiseArgumentType()
|
|
26
|
-
}
|
|
27
|
-
return RawArgumentType(innerType: T.self)
|
|
28
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
An argument type representing array types. Requires the argument type for
|
|
5
|
-
array's element type as it delegates casting to that type for each element in the array.
|
|
6
|
-
*/
|
|
7
|
-
internal struct ArrayArgumentType: AnyArgumentType {
|
|
8
|
-
let elementType: AnyArgumentType
|
|
9
|
-
|
|
10
|
-
func cast<ArgType>(_ value: ArgType) throws -> Any {
|
|
11
|
-
if let value = value as? [Any] {
|
|
12
|
-
return try value.map { try elementType.cast($0) }
|
|
13
|
-
}
|
|
14
|
-
// We should probably throw an error if we get here. On the other side, the array type
|
|
15
|
-
// requirement can be more loosen so we can try to arrayize values that are not arrays.
|
|
16
|
-
return [try elementType.cast(value)]
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
var description: String {
|
|
20
|
-
"[\(elementType.description)]"
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
A type-erased protocol used to recognize arrays with elements of argument-compatible type.
|
|
26
|
-
`Array` is a generic type, so it's impossible to check the inheritance directly.
|
|
27
|
-
*/
|
|
28
|
-
internal protocol AnyArrayArgument: AnyArgument {
|
|
29
|
-
/**
|
|
30
|
-
Exposes the `Element` generic type wrapped by the argument type to preserve its metadata.
|
|
31
|
-
*/
|
|
32
|
-
static func getElementArgumentType() -> AnyArgumentType
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
Extends the `Array` type to expose its generic `Element` as an argument type.
|
|
37
|
-
*/
|
|
38
|
-
extension Array: AnyArrayArgument where Element: AnyArgument {
|
|
39
|
-
static func getElementArgumentType() -> AnyArgumentType {
|
|
40
|
-
return ArgumentType(Element.self)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
An argument type that wraps any type conforming to `ConvertibleArgument` protocol.
|
|
5
|
-
*/
|
|
6
|
-
internal struct ConvertibleArgumentType: AnyArgumentType {
|
|
7
|
-
let innerType: ConvertibleArgument.Type
|
|
8
|
-
|
|
9
|
-
func cast<ArgType>(_ value: ArgType) throws -> Any {
|
|
10
|
-
return try innerType.convert(from: value)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
var description: String {
|
|
14
|
-
String(describing: innerType.self)
|
|
15
|
-
}
|
|
16
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
An argument type that represents an optional type, which allows `nil` to be passed when casting.
|
|
5
|
-
Requires the argument type for optional's unwrapped type as it delegates casting to that type for non-nil values.
|
|
6
|
-
*/
|
|
7
|
-
internal struct OptionalArgumentType: AnyArgumentType {
|
|
8
|
-
let wrappedType: AnyArgumentType
|
|
9
|
-
|
|
10
|
-
func cast<ArgType>(_ value: ArgType) throws -> Any {
|
|
11
|
-
if Optional.isNil(value) {
|
|
12
|
-
return Optional<Any>.none as Any
|
|
13
|
-
}
|
|
14
|
-
return try wrappedType.cast(value)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
var description: String {
|
|
18
|
-
"\(wrappedType)?"
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
A type-erased protocol used to recognize if the generic type is an optional type.
|
|
24
|
-
`Optional` is a generic enum, so it's impossible to check the inheritance directly.
|
|
25
|
-
*/
|
|
26
|
-
internal protocol AnyOptionalArgument: AnyArgument {
|
|
27
|
-
/**
|
|
28
|
-
Exposes the `Wrapped` generic type wrapped by the argument type to preserve its metadata.`
|
|
29
|
-
*/
|
|
30
|
-
static func getWrappedArgumentType() -> AnyArgumentType
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
Make generic `Optional` implement non-generic `AnyOptional` and add handy check against type-erased `nil`.
|
|
35
|
-
*/
|
|
36
|
-
extension Optional: AnyOptionalArgument {
|
|
37
|
-
static func getWrappedArgumentType() -> AnyArgumentType {
|
|
38
|
-
return ArgumentType(Wrapped.self)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
static func isNil(_ object: Wrapped) -> Bool {
|
|
42
|
-
switch object as Any {
|
|
43
|
-
case Optional<Any>.none:
|
|
44
|
-
return true
|
|
45
|
-
default:
|
|
46
|
-
return false
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
An argument type that represents the `Promise` argument.
|
|
5
|
-
*/
|
|
6
|
-
internal struct PromiseArgumentType: AnyArgumentType {
|
|
7
|
-
func cast<ArgType>(_ value: ArgType) throws -> Any {
|
|
8
|
-
if let value = value as? Promise {
|
|
9
|
-
return value
|
|
10
|
-
}
|
|
11
|
-
throw Conversions.CastingException<Promise>(value)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
var description: String = "Promise"
|
|
15
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
An argument type that can wrap any type, but it casts only type-compatible values using `as?` keyword.
|
|
5
|
-
The innermost type of other argument types like `ArrayArgumentType` and `OptionalArgumentType`.
|
|
6
|
-
*/
|
|
7
|
-
internal struct RawArgumentType<InnerType>: AnyArgumentType {
|
|
8
|
-
let innerType: InnerType.Type
|
|
9
|
-
|
|
10
|
-
func cast<ArgType>(_ value: ArgType) throws -> Any {
|
|
11
|
-
if let value = value as? InnerType {
|
|
12
|
-
return value
|
|
13
|
-
}
|
|
14
|
-
// Raw arguments are always non-optional, but they may receive `nil` values.
|
|
15
|
-
// Let's throw more specific error in this case.
|
|
16
|
-
if Optional.isNil(value) {
|
|
17
|
-
throw Conversions.NullCastException<InnerType>()
|
|
18
|
-
}
|
|
19
|
-
throw Conversions.CastingException<InnerType>(value)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
var description: String {
|
|
23
|
-
String(describing: innerType.self)
|
|
24
|
-
}
|
|
25
|
-
}
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import Dispatch
|
|
2
|
-
|
|
3
|
-
public class ConcreteFunction<Args, ReturnType>: AnyFunction {
|
|
4
|
-
public typealias ClosureType = (Args) throws -> ReturnType
|
|
5
|
-
|
|
6
|
-
public let name: String
|
|
7
|
-
|
|
8
|
-
public var takesPromise: Bool
|
|
9
|
-
|
|
10
|
-
public var argumentsCount: Int {
|
|
11
|
-
return argumentTypes.count
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
public var queue: DispatchQueue?
|
|
15
|
-
|
|
16
|
-
public var isAsync: Bool = true
|
|
17
|
-
|
|
18
|
-
let closure: ClosureType
|
|
19
|
-
|
|
20
|
-
public let argumentTypes: [AnyArgumentType]
|
|
21
|
-
|
|
22
|
-
init(
|
|
23
|
-
_ name: String,
|
|
24
|
-
argTypes: [AnyArgumentType],
|
|
25
|
-
_ closure: @escaping ClosureType
|
|
26
|
-
) {
|
|
27
|
-
self.name = name
|
|
28
|
-
self.takesPromise = argTypes.last is PromiseArgumentType
|
|
29
|
-
self.closure = closure
|
|
30
|
-
|
|
31
|
-
// Drop the last argument type if it's the `Promise`.
|
|
32
|
-
self.argumentTypes = takesPromise ? argTypes.dropLast(1) : argTypes
|
|
33
|
-
|
|
34
|
-
// This is temporary solution to keep backwards compatibility for existing functions — they all end with "Async".
|
|
35
|
-
// `function` component that we've used so far was async by default, but we decided to replace it with `asyncFunction`
|
|
36
|
-
// and make `function`s synchronous. Introduced in SDK45, can be removed in SDK46 after migrating all modules.
|
|
37
|
-
self.isAsync = name.hasSuffix("Async")
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
Calls the function with given arguments.
|
|
42
|
-
- Parameters:
|
|
43
|
-
- args: An array of arguments to pass to the function. The arguments must be of the same type as in the underlying ``closure``.
|
|
44
|
-
- promise: A promise to resolve or reject by the async ``closure`` when it finishes execution.
|
|
45
|
-
- ToDo: Make it internal.
|
|
46
|
-
*/
|
|
47
|
-
public func call(args: [Any], promise: Promise) {
|
|
48
|
-
// Add promise to the array of arguments if necessary.
|
|
49
|
-
let arguments = takesPromise ? args + [promise] : args
|
|
50
|
-
let returnedValue: ReturnType?
|
|
51
|
-
|
|
52
|
-
do {
|
|
53
|
-
let argumentsTuple = try Conversions.toTuple(arguments) as! Args
|
|
54
|
-
returnedValue = try closure(argumentsTuple)
|
|
55
|
-
} catch let error as CodedError {
|
|
56
|
-
promise.reject(FunctionCallException(name).causedBy(error))
|
|
57
|
-
return
|
|
58
|
-
} catch {
|
|
59
|
-
promise.reject(UnexpectedException(error))
|
|
60
|
-
return
|
|
61
|
-
}
|
|
62
|
-
if !takesPromise {
|
|
63
|
-
promise.resolve(returnedValue)
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
Calls the function synchronously with given arguments.
|
|
69
|
-
- Parameters:
|
|
70
|
-
- args: An array of arguments to pass to the function. The arguments must be of the same type as in the underlying ``closure``.
|
|
71
|
-
- Returns: A value returned by the called function when succeeded or an error when it failed.
|
|
72
|
-
- ToDo: Make it internal.
|
|
73
|
-
*/
|
|
74
|
-
public func callSync(args: [Any]) -> Any {
|
|
75
|
-
if takesPromise {
|
|
76
|
-
// Using `Promise` in the synchronous function is prohibited. Probably should throw an exception here,
|
|
77
|
-
// but for now let's return nil until we split async and sync functions.
|
|
78
|
-
return Optional<Any>.none as Any
|
|
79
|
-
}
|
|
80
|
-
do {
|
|
81
|
-
let argumentsTuple = try Conversions.toTuple(args) as! Args
|
|
82
|
-
return try closure(argumentsTuple)
|
|
83
|
-
} catch let error {
|
|
84
|
-
return error
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
public func runOnQueue(_ queue: DispatchQueue?) -> Self {
|
|
89
|
-
self.queue = queue
|
|
90
|
-
return self
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
public func runSynchronously() -> Self {
|
|
94
|
-
self.isAsync = false
|
|
95
|
-
return self
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
internal class FunctionCallException: GenericException<String> {
|
|
100
|
-
override var reason: String {
|
|
101
|
-
"Call to function '\(param)' has been rejected"
|
|
102
|
-
}
|
|
103
|
-
}
|