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,198 @@
|
|
|
1
|
+
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import Dispatch
|
|
4
|
+
|
|
5
|
+
public let log = Logger(category: "expo")
|
|
6
|
+
|
|
7
|
+
public class Logger {
|
|
8
|
+
#if DEBUG || EXPO_CONFIGURATION_DEBUG
|
|
9
|
+
private var minLevel: LogType = .trace
|
|
10
|
+
#else
|
|
11
|
+
private var minLevel: LogType = .info
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
private let category: String
|
|
15
|
+
|
|
16
|
+
private var handlers: [LogHandler] = []
|
|
17
|
+
|
|
18
|
+
init(category: String = "main") {
|
|
19
|
+
self.category = category
|
|
20
|
+
|
|
21
|
+
if #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) {
|
|
22
|
+
addHandler(withType: OSLogHandler.self)
|
|
23
|
+
} else {
|
|
24
|
+
addHandler(withType: PrintLogHandler.self)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
internal func addHandler<LogHandlerType: LogHandler>(_ handler: LogHandlerType) {
|
|
29
|
+
handlers.append(handler)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
internal func addHandler<LogHandlerType: LogHandler>(withType: LogHandlerType.Type) {
|
|
33
|
+
addHandler(LogHandlerType(category: category))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// MARK: - Public logging functions
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
The most verbose log level that captures all the details about the behavior of the implementation.
|
|
40
|
+
It is mostly diagnostic and is more granular and finer than `debug` log level.
|
|
41
|
+
These logs should not be committed to the repository and are ignored in the release builds.
|
|
42
|
+
*/
|
|
43
|
+
public func trace(_ items: Any...) {
|
|
44
|
+
log(type: .trace, items)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
Used to log diagnostically helpful information. As opposed to `trace`,
|
|
49
|
+
it is acceptable to commit these logs to the repository. Ignored in the release builds.
|
|
50
|
+
*/
|
|
51
|
+
public func debug(_ items: Any...) {
|
|
52
|
+
log(type: .debug, items)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
For information that should be logged under normal conditions such as successful initialization
|
|
57
|
+
and notable events that are not considered an error but might be useful for debugging purposes in the release builds.
|
|
58
|
+
*/
|
|
59
|
+
public func info(_ items: Any...) {
|
|
60
|
+
log(type: .info, items)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
Used to log an unwanted state that has not much impact on the process so it can be continued, but could potentially become an error.
|
|
65
|
+
*/
|
|
66
|
+
public func warn(_ items: Any...) {
|
|
67
|
+
log(type: .warn, items)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
Logs unwanted state that has an impact on the currently running process, but the entire app can continue to run.
|
|
72
|
+
*/
|
|
73
|
+
public func error(_ items: Any...) {
|
|
74
|
+
log(type: .error, items)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
Logs critical error due to which the entire app cannot continue to run.
|
|
79
|
+
*/
|
|
80
|
+
public func fatal(_ items: Any...) {
|
|
81
|
+
log(type: .fatal, items)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
Logs the stack of symbols on the current thread.
|
|
86
|
+
*/
|
|
87
|
+
public func stacktrace(type: LogType = .stacktrace, file: String = #fileID, line: UInt = #line) {
|
|
88
|
+
guard type.rawValue >= minLevel.rawValue else {
|
|
89
|
+
return
|
|
90
|
+
}
|
|
91
|
+
let queueName = OperationQueue.current?.underlyingQueue?.label ?? "<unknown>"
|
|
92
|
+
|
|
93
|
+
// Get the call stack symbols without the first symbol as it points right here.
|
|
94
|
+
let symbols = Thread.callStackSymbols.dropFirst()
|
|
95
|
+
|
|
96
|
+
log(type: type, "The stacktrace from '\(file):\(line)' on queue '\(queueName)':")
|
|
97
|
+
|
|
98
|
+
symbols.forEach { symbol in
|
|
99
|
+
let formattedSymbol = reformatStackSymbol(symbol)
|
|
100
|
+
log(type: type, "≫ \(formattedSymbol)")
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
Allows the logger instance to be called as a function. The same as `logger.debug(...)`.
|
|
106
|
+
*/
|
|
107
|
+
public func callAsFunction(_ items: Any...) {
|
|
108
|
+
log(type: .debug, items)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// MARK: - Timers
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
Stores the timers created by `timeStart` function.
|
|
115
|
+
*/
|
|
116
|
+
private var timers: [String: DispatchTime] = [:]
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
Starts the timer to measure how much time the following operations take.
|
|
120
|
+
*/
|
|
121
|
+
public func timeStart(_ id: String) {
|
|
122
|
+
guard LogType.timer.rawValue >= minLevel.rawValue else {
|
|
123
|
+
return
|
|
124
|
+
}
|
|
125
|
+
log(type: .timer, "Starting timer '\(id)'")
|
|
126
|
+
timers[id] = DispatchTime.now()
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
Stops the timer and logs how much time elapsed since it started.
|
|
131
|
+
*/
|
|
132
|
+
public func timeEnd(_ id: String) {
|
|
133
|
+
guard LogType.timer.rawValue >= minLevel.rawValue else {
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
guard let startTime = timers[id] else {
|
|
137
|
+
log(type: .timer, "Timer '\(id)' has not been started!")
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
let endTime = DispatchTime.now()
|
|
141
|
+
let diff = Double(endTime.uptimeNanoseconds - startTime.uptimeNanoseconds) / 1_000_000
|
|
142
|
+
log(type: .timer, "Timer '\(id)' has finished in: \(diff) seconds")
|
|
143
|
+
timers.removeValue(forKey: id)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
Measures how much time it takes to run given closure. Returns the same value as the closure returned.
|
|
148
|
+
*/
|
|
149
|
+
public func time<ReturnType>(_ id: String, _ closure: () -> ReturnType) -> ReturnType {
|
|
150
|
+
timeStart(id)
|
|
151
|
+
let result = closure()
|
|
152
|
+
timeEnd(id)
|
|
153
|
+
return result
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// MARK: - Changing the category
|
|
157
|
+
|
|
158
|
+
public func category(_ category: String) -> Logger {
|
|
159
|
+
return Logger(category: category)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// MARK: - Private logging functions
|
|
163
|
+
|
|
164
|
+
private func log(type: LogType = .trace, _ items: [Any]) {
|
|
165
|
+
guard type.rawValue >= minLevel.rawValue else {
|
|
166
|
+
return
|
|
167
|
+
}
|
|
168
|
+
let messages = items
|
|
169
|
+
.map { describe(value: $0) }
|
|
170
|
+
.joined(separator: " ")
|
|
171
|
+
.split(whereSeparator: \.isNewline)
|
|
172
|
+
.map { "\(type.prefix) \($0)" }
|
|
173
|
+
|
|
174
|
+
handlers.forEach { handler in
|
|
175
|
+
messages.forEach { message in
|
|
176
|
+
handler.log(type: type, message)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private func log(type: LogType = .trace, _ items: Any...) {
|
|
182
|
+
log(type: type, items)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
fileprivate func reformatStackSymbol(_ symbol: String) -> String {
|
|
187
|
+
return symbol.replacingOccurrences(of: #"^\d+\s+"#, with: "", options: .regularExpression)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
fileprivate func describe(value: Any) -> String {
|
|
191
|
+
if let value = value as? CustomDebugStringConvertible {
|
|
192
|
+
return value.debugDescription
|
|
193
|
+
}
|
|
194
|
+
if let value = value as? CustomStringConvertible {
|
|
195
|
+
return value.description
|
|
196
|
+
}
|
|
197
|
+
return String(describing: value)
|
|
198
|
+
}
|
|
@@ -56,54 +56,33 @@ public final class ModuleHolder {
|
|
|
56
56
|
Merges all `constants` definitions into one dictionary.
|
|
57
57
|
*/
|
|
58
58
|
func getConstants() -> [String: Any?] {
|
|
59
|
-
return definition.
|
|
60
|
-
dict.merge(definition.body()) { $1 }
|
|
61
|
-
}
|
|
59
|
+
return definition.getConstants()
|
|
62
60
|
}
|
|
63
61
|
|
|
64
62
|
// MARK: Calling functions
|
|
65
63
|
|
|
66
|
-
func call(function functionName: String, args: [Any],
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
let queue = function.queue ?? DispatchQueue.global(qos: .default)
|
|
72
|
-
|
|
73
|
-
// Given arguments can be:
|
|
74
|
-
// - Swift primitives when invoked through the bridge and in unit tests
|
|
75
|
-
// - `JavaScriptValue`s when the function is called through the JSI
|
|
76
|
-
// The latter need to be unpacked to Swift primitives on the JS thread,
|
|
77
|
-
// so we do the casting before the function call is scheduled on the queue.
|
|
78
|
-
let arguments = try castArguments(args, toTypes: function.argumentTypes)
|
|
79
|
-
|
|
80
|
-
queue.async {
|
|
81
|
-
function.call(args: arguments, promise: promise)
|
|
82
|
-
}
|
|
83
|
-
} catch let error as CodedError {
|
|
84
|
-
promise.reject(error)
|
|
85
|
-
} catch {
|
|
86
|
-
promise.reject(UnexpectedException(error))
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
func call(function functionName: String, args: [Any], _ callback: @escaping (Any?, CodedError?) -> Void = { _, _ in }) {
|
|
91
|
-
let promise = Promise {
|
|
92
|
-
callback($0, nil)
|
|
93
|
-
} rejecter: {
|
|
94
|
-
callback(nil, $0)
|
|
64
|
+
func call(function functionName: String, args: [Any], _ callback: @escaping (FunctionCallResult) -> () = { _ in }) {
|
|
65
|
+
guard let function = definition.functions[functionName] else {
|
|
66
|
+
callback(.failure(FunctionNotFoundException((functionName: functionName, moduleName: self.name))))
|
|
67
|
+
return
|
|
95
68
|
}
|
|
96
|
-
call(
|
|
69
|
+
function.call(by: self, withArguments: args, callback: callback)
|
|
97
70
|
}
|
|
98
71
|
|
|
99
72
|
@discardableResult
|
|
100
73
|
func callSync(function functionName: String, args: [Any]) -> Any? {
|
|
101
|
-
guard let function = definition.functions[functionName] else {
|
|
74
|
+
guard let function = definition.functions[functionName] as? AnySyncFunctionComponent else {
|
|
102
75
|
return nil
|
|
103
76
|
}
|
|
104
77
|
do {
|
|
105
|
-
let arguments = try
|
|
106
|
-
|
|
78
|
+
let arguments = try cast(arguments: args, forFunction: function)
|
|
79
|
+
let result = try function.call(by: self, withArguments: arguments)
|
|
80
|
+
|
|
81
|
+
if let result = result as? SharedObject {
|
|
82
|
+
let jsObject = SharedObjectRegistry.ensureSharedJavaScriptObject(runtime: appContext!.runtime!, nativeObject: result)
|
|
83
|
+
return jsObject
|
|
84
|
+
}
|
|
85
|
+
return result
|
|
107
86
|
} catch {
|
|
108
87
|
return error
|
|
109
88
|
}
|
|
@@ -119,24 +98,10 @@ public final class ModuleHolder {
|
|
|
119
98
|
*/
|
|
120
99
|
private func createJavaScriptModuleObject() -> JavaScriptObject? {
|
|
121
100
|
// It might be impossible to create any object at the moment (e.g. remote debugging, app context destroyed)
|
|
122
|
-
guard let
|
|
101
|
+
guard let runtime = appContext?.runtime else {
|
|
123
102
|
return nil
|
|
124
103
|
}
|
|
125
|
-
|
|
126
|
-
// Fill in with constants
|
|
127
|
-
for (key, value) in getConstants() {
|
|
128
|
-
object.setProperty(key, value: value)
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Fill in with functions
|
|
132
|
-
for (_, fn) in definition.functions {
|
|
133
|
-
if fn.isAsync {
|
|
134
|
-
object.setAsyncFunction(fn.name, argsCount: fn.argumentsCount, block: createAsyncFunctionBlock(holder: self, name: fn.name))
|
|
135
|
-
} else {
|
|
136
|
-
object.setSyncFunction(fn.name, argsCount: fn.argumentsCount, block: createSyncFunctionBlock(holder: self, name: fn.name))
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
return object
|
|
104
|
+
return definition.build(inRuntime: runtime)
|
|
140
105
|
}
|
|
141
106
|
|
|
142
107
|
// MARK: Listening to native events
|
|
@@ -166,9 +131,9 @@ public final class ModuleHolder {
|
|
|
166
131
|
*/
|
|
167
132
|
func modifyListenersCount(_ count: Int) {
|
|
168
133
|
if count > 0 && listenersCount == 0 {
|
|
169
|
-
|
|
134
|
+
definition.functions["startObserving"]?.call(withArguments: [])
|
|
170
135
|
} else if count < 0 && listenersCount + count <= 0 {
|
|
171
|
-
|
|
136
|
+
definition.functions["stopObserving"]?.call(withArguments: [])
|
|
172
137
|
}
|
|
173
138
|
listenersCount = max(0, listenersCount + count)
|
|
174
139
|
}
|
|
@@ -13,6 +13,7 @@ public final class ModuleRegistry: Sequence {
|
|
|
13
13
|
Registers an instance of module holder.
|
|
14
14
|
*/
|
|
15
15
|
internal func register(holder: ModuleHolder) {
|
|
16
|
+
log.info("Registering module '\(holder.name)'")
|
|
16
17
|
registry[holder.name] = holder
|
|
17
18
|
}
|
|
18
19
|
|
|
@@ -47,7 +48,10 @@ public final class ModuleRegistry: Sequence {
|
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
public func unregister(moduleName: String) {
|
|
50
|
-
registry[moduleName]
|
|
51
|
+
if registry[moduleName] != nil {
|
|
52
|
+
log.info("Unregistering module '\(moduleName)'")
|
|
53
|
+
registry[moduleName] = nil
|
|
54
|
+
}
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
public func has(moduleWithName moduleName: String) -> Bool {
|
|
@@ -71,12 +75,14 @@ public final class ModuleRegistry: Sequence {
|
|
|
71
75
|
}
|
|
72
76
|
|
|
73
77
|
internal func post(event: EventName) {
|
|
78
|
+
log.info("Posting '\(event)' event to registered modules")
|
|
74
79
|
forEach { holder in
|
|
75
80
|
holder.post(event: event)
|
|
76
81
|
}
|
|
77
82
|
}
|
|
78
83
|
|
|
79
84
|
internal func post<PayloadType>(event: EventName, payload: PayloadType? = nil) {
|
|
85
|
+
log.info("Posting '\(event)' event to registered modules")
|
|
80
86
|
forEach { holder in
|
|
81
87
|
holder.post(event: event, payload: payload)
|
|
82
88
|
}
|
|
@@ -16,8 +16,8 @@ public protocol AnyModule: AnyObject, AnyArgument {
|
|
|
16
16
|
|
|
17
17
|
```
|
|
18
18
|
public func definition() -> ModuleDefinition {
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
Name("MyModule")
|
|
20
|
+
AsyncFunction("myFunction") { (a: String, b: String) in
|
|
21
21
|
"\(a) \(b)"
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -37,7 +37,7 @@ public protocol AnyModule: AnyObject, AnyArgument {
|
|
|
37
37
|
just specify an argument of type `Promise` as the last one and use its `resolve` or `reject` functions.
|
|
38
38
|
|
|
39
39
|
```
|
|
40
|
-
|
|
40
|
+
AsyncFunction("myFunction") { (promise: Promise) in
|
|
41
41
|
DispatchQueue.main.async {
|
|
42
42
|
promise.resolve("return value obtained in async callback")
|
|
43
43
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
A type that can decorate a `JavaScriptObject` with some properties.
|
|
5
|
+
*/
|
|
6
|
+
internal protocol JavaScriptObjectDecorator {
|
|
7
|
+
/**
|
|
8
|
+
Decorates an existing `JavaScriptObject`.
|
|
9
|
+
*/
|
|
10
|
+
func decorate(object: JavaScriptObject, inRuntime runtime: JavaScriptRuntime)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
A type that can build and decorate a `JavaScriptObject` based on its attributes.
|
|
15
|
+
*/
|
|
16
|
+
internal protocol JavaScriptObjectBuilder: JavaScriptObjectDecorator {
|
|
17
|
+
/**
|
|
18
|
+
Creates a decorated `JavaScriptObject` in the given runtime.
|
|
19
|
+
*/
|
|
20
|
+
func build(inRuntime runtime: JavaScriptRuntime) -> JavaScriptObject
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
Provides the default behavior of `JavaScriptObjectBuilder`.
|
|
25
|
+
The `build(inRuntime:)` creates a plain object and uses `decorate(object:)` for decoration.
|
|
26
|
+
*/
|
|
27
|
+
extension JavaScriptObjectBuilder {
|
|
28
|
+
func build(inRuntime runtime: JavaScriptRuntime) -> JavaScriptObject {
|
|
29
|
+
let object = runtime.createObject()
|
|
30
|
+
decorate(object: object, inRuntime: runtime)
|
|
31
|
+
return object
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
func decorate(object: JavaScriptObject, inRuntime runtime: JavaScriptRuntime) {
|
|
35
|
+
// no-op by default
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/**
|
|
4
4
|
Base class for other definitions representing an object, such as `ModuleDefinition`.
|
|
5
5
|
*/
|
|
6
|
-
public class ObjectDefinition: AnyDefinition {
|
|
6
|
+
public class ObjectDefinition: AnyDefinition, JavaScriptObjectBuilder {
|
|
7
7
|
/**
|
|
8
8
|
A dictionary of functions defined by the object.
|
|
9
9
|
*/
|
|
@@ -14,6 +14,16 @@ public class ObjectDefinition: AnyDefinition {
|
|
|
14
14
|
*/
|
|
15
15
|
let constants: [ConstantsDefinition]
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
A map of dynamic properties defined by the object.
|
|
19
|
+
*/
|
|
20
|
+
let properties: [String: PropertyComponent]
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
A map of classes defined within the object.
|
|
24
|
+
*/
|
|
25
|
+
let classes: [String: ClassComponent]
|
|
26
|
+
|
|
17
27
|
/**
|
|
18
28
|
Default initializer receiving children definitions from the result builder.
|
|
19
29
|
*/
|
|
@@ -26,5 +36,68 @@ public class ObjectDefinition: AnyDefinition {
|
|
|
26
36
|
|
|
27
37
|
self.constants = definitions
|
|
28
38
|
.compactMap { $0 as? ConstantsDefinition }
|
|
39
|
+
|
|
40
|
+
self.properties = definitions
|
|
41
|
+
.compactMap { $0 as? PropertyComponent }
|
|
42
|
+
.reduce(into: [String: PropertyComponent]()) { dict, property in
|
|
43
|
+
dict[property.name] = property
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
self.classes = definitions
|
|
47
|
+
.compactMap { $0 as? ClassComponent }
|
|
48
|
+
.reduce(into: [String: ClassComponent]()) { dict, klass in
|
|
49
|
+
dict[klass.name] = klass
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
Merges all `constants` definitions into one dictionary.
|
|
55
|
+
*/
|
|
56
|
+
func getConstants() -> [String: Any?] {
|
|
57
|
+
return constants.reduce(into: [String: Any?]()) { dict, definition in
|
|
58
|
+
dict.merge(definition.body()) { $1 }
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// MARK: - JavaScriptObjectBuilder
|
|
63
|
+
|
|
64
|
+
public func build(inRuntime runtime: JavaScriptRuntime) -> JavaScriptObject {
|
|
65
|
+
let object = runtime.createObject()
|
|
66
|
+
decorate(object: object, inRuntime: runtime)
|
|
67
|
+
return object
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public func decorate(object: JavaScriptObject, inRuntime runtime: JavaScriptRuntime) {
|
|
71
|
+
decorateWithConstants(runtime: runtime, object: object)
|
|
72
|
+
decorateWithFunctions(runtime: runtime, object: object)
|
|
73
|
+
decorateWithProperties(runtime: runtime, object: object)
|
|
74
|
+
decorateWithClasses(runtime: runtime, object: object)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// MARK: - Internals
|
|
78
|
+
|
|
79
|
+
internal func decorateWithConstants(runtime: JavaScriptRuntime, object: JavaScriptObject) {
|
|
80
|
+
for (key, value) in getConstants() {
|
|
81
|
+
object.setProperty(key, value: value)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
internal func decorateWithFunctions(runtime: JavaScriptRuntime, object: JavaScriptObject) {
|
|
86
|
+
for fn in functions.values {
|
|
87
|
+
object.setProperty(fn.name, value: fn.build(inRuntime: runtime))
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
internal func decorateWithProperties(runtime: JavaScriptRuntime, object: JavaScriptObject) {
|
|
92
|
+
for property in properties.values {
|
|
93
|
+
let descriptor = property.buildDescriptor(inRuntime: runtime, withCaller: object)
|
|
94
|
+
object.defineProperty(property.name, descriptor: descriptor)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
internal func decorateWithClasses(runtime: JavaScriptRuntime, object: JavaScriptObject) {
|
|
99
|
+
for klass in classes.values {
|
|
100
|
+
object.setProperty(klass.name, value: klass.build(inRuntime: runtime))
|
|
101
|
+
}
|
|
29
102
|
}
|
|
30
103
|
}
|