expo-modules-core 0.7.0 → 0.9.1
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 +49 -0
- package/README.md +1 -1
- package/android/ExpoModulesCorePlugin.gradle +15 -0
- package/android/build.gradle +46 -32
- package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +5 -5
- package/android/src/main/java/expo/modules/adapters/react/services/UIManagerModuleWrapper.java +13 -0
- package/android/src/main/java/expo/modules/core/ViewManager.java +9 -0
- package/android/src/main/java/expo/modules/core/interfaces/JavaScriptContextProvider.java +4 -0
- package/android/src/main/java/expo/modules/core/interfaces/ReactActivityHandler.java +37 -1
- package/android/src/main/java/expo/modules/core/interfaces/ReactNativeHostHandler.java +30 -0
- package/android/src/main/java/expo/modules/core/interfaces/services/UIManager.java +2 -0
- package/android/src/main/java/expo/modules/kotlin/AppContext.kt +13 -5
- package/android/src/main/java/expo/modules/kotlin/KPromiseWrapper.kt +2 -13
- package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +11 -5
- package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +5 -1
- package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +17 -0
- package/android/src/main/java/expo/modules/kotlin/callbacks/ViewCallback.kt +14 -3
- package/android/src/main/java/expo/modules/kotlin/events/EventEmitter.kt +13 -0
- package/android/src/main/java/expo/modules/kotlin/events/KModuleEventEmitterWrapper.kt +102 -0
- package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +25 -1
- package/android/src/main/java/expo/modules/kotlin/{methods/AnyMethod.kt → functions/AnyFunction.kt} +6 -5
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +15 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +170 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromise.kt +15 -0
- package/android/src/main/java/expo/modules/kotlin/functions/AsyncSuspendFunction.kt +36 -0
- package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +14 -0
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +374 -41
- package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +2 -2
- package/android/src/main/java/expo/modules/kotlin/records/FieldValidator.kt +139 -0
- package/android/src/main/java/expo/modules/kotlin/records/Record.kt +0 -39
- package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +59 -10
- package/android/src/main/java/expo/modules/kotlin/records/Required.kt +5 -0
- package/android/src/main/java/expo/modules/kotlin/records/ValidationBinder.kt +110 -0
- package/android/src/main/java/expo/modules/kotlin/records/Validators.kt +61 -0
- package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverter.kt +35 -0
- package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverterHelper.kt +148 -0
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +9 -1
- package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +49 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinition.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinitionBuilder.kt +114 -0
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +4 -1
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +56 -5
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +3 -0
- package/build/NativeModulesProxy.native.d.ts +0 -4
- package/build/NativeModulesProxy.native.d.ts.map +1 -1
- package/build/NativeModulesProxy.native.js +1 -14
- package/build/NativeModulesProxy.native.js.map +1 -1
- package/build/NativeModulesProxy.types.d.ts +0 -3
- package/build/NativeModulesProxy.types.d.ts.map +1 -1
- package/build/NativeModulesProxy.types.js.map +1 -1
- package/build/NativeViewManagerAdapter.native.d.ts.map +1 -1
- package/build/NativeViewManagerAdapter.native.js +9 -33
- package/build/NativeViewManagerAdapter.native.js.map +1 -1
- package/build/sweet/NativeErrorManager.js +1 -1
- package/build/sweet/NativeErrorManager.js.map +1 -1
- package/ios/AppDelegates/EXAppDelegatesLoader.m +4 -8
- package/ios/AppDelegates/ExpoAppDelegate.swift +4 -10
- package/ios/EXAppDefines.h +1 -0
- package/ios/EXAppDefines.m +6 -0
- package/ios/EXUtilities.h +2 -0
- package/ios/EXUtilities.m +12 -0
- package/ios/ExpoModulesCore.h +4 -0
- package/ios/ExpoModulesCore.podspec +4 -2
- package/ios/Interfaces/FileSystem/EXFileSystemInterface.h +1 -1
- package/ios/Interfaces/TaskManager/EXTaskServiceInterface.h +1 -0
- package/ios/JSI/{JSIConversions.h → EXJSIConversions.h} +4 -1
- package/ios/JSI/{JSIConversions.mm → EXJSIConversions.mm} +16 -5
- package/ios/JSI/{JSIInstaller.h → EXJSIInstaller.h} +3 -3
- package/ios/JSI/EXJSIInstaller.mm +17 -0
- package/ios/JSI/{ExpoModulesProxySpec.h → EXJSIUtils.h} +0 -9
- package/ios/JSI/{ExpoModulesProxySpec.mm → EXJSIUtils.mm} +4 -48
- package/ios/JSI/EXJavaScriptObject.h +97 -0
- package/ios/JSI/EXJavaScriptObject.mm +121 -0
- package/ios/JSI/{JavaScriptRuntime.h → EXJavaScriptRuntime.h} +27 -8
- package/ios/JSI/EXJavaScriptRuntime.mm +153 -0
- package/ios/JSI/EXJavaScriptValue.h +57 -0
- package/ios/JSI/EXJavaScriptValue.mm +166 -0
- package/ios/JSI/ExpoModulesHostObject.mm +2 -1
- package/ios/JSI/JavaScriptRuntime.swift +32 -0
- package/ios/JSI/JavaScriptValue.swift +94 -0
- package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +1 -11
- package/ios/NativeModulesProxy/EXNativeModulesProxy.h +2 -2
- package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +24 -22
- package/ios/ReactDelegates/EXReactCompatibleHelpers.h +18 -0
- package/ios/ReactDelegates/EXReactCompatibleHelpers.m +19 -0
- package/ios/ReactDelegates/ExpoReactDelegate.swift +2 -2
- package/ios/ReactDelegates/ExpoReactDelegateHandler.swift +1 -1
- package/ios/Swift/AppContext.swift +21 -2
- package/ios/Swift/Arguments/AnyArgumentType.swift +1 -1
- package/ios/Swift/Functions/AnyFunction.swift +5 -0
- package/ios/Swift/Functions/AsyncFunctionComponent.swift +182 -0
- package/ios/Swift/Functions/ConcreteFunction.swift +40 -68
- package/ios/Swift/Functions/SyncFunctionComponent.swift +181 -0
- package/ios/Swift/JavaScriptUtils.swift +56 -0
- package/ios/Swift/ModuleHolder.swift +17 -5
- package/ios/Swift/Modules/ModuleDefinitionComponents.swift +66 -44
- package/ios/Swift/ModulesProvider.swift +3 -10
- package/ios/Swift/Objects/ObjectDefinitionComponents.swift +49 -0
- package/ios/Swift/SwiftInteropBridge.swift +14 -5
- package/ios/Swift/Views/ComponentData.swift +2 -1
- package/ios/Swift/Views/ExpoView.swift +8 -0
- package/ios/Swift/Views/ViewManagerDefinitionComponents.swift +23 -0
- package/ios/Swift.h +5 -0
- package/ios/Tests/ArgumentTypeSpec.swift +2 -3
- package/ios/Tests/ConstantsSpec.swift +6 -7
- package/ios/Tests/ConvertiblesSpec.swift +2 -3
- package/ios/Tests/ExceptionsSpec.swift +2 -3
- package/ios/Tests/ExpoModulesSpec.swift +75 -0
- package/ios/Tests/FunctionSpec.swift +13 -15
- package/ios/Tests/FunctionWithConvertiblesSpec.swift +4 -5
- package/ios/Tests/JavaScriptObjectSpec.swift +97 -0
- package/ios/Tests/JavaScriptRuntimeSpec.swift +94 -0
- package/ios/Tests/ModuleEventListenersSpec.swift +15 -16
- package/ios/Tests/ModuleRegistrySpec.swift +2 -3
- package/ios/Tests/RecordSpec.swift +2 -3
- package/package.json +2 -2
- package/src/NativeModulesProxy.native.ts +2 -22
- package/src/NativeModulesProxy.types.ts +0 -8
- package/src/NativeViewManagerAdapter.native.tsx +12 -28
- package/src/sweet/NativeErrorManager.ts +1 -1
- package/android/src/main/java/expo/modules/kotlin/events/KEventEmitterWrapper.kt +0 -26
- package/android/src/main/java/expo/modules/kotlin/methods/Method.kt +0 -14
- package/android/src/main/java/expo/modules/kotlin/methods/PromiseMethod.kt +0 -15
- package/ios/JSI/JSIInstaller.mm +0 -34
- package/ios/JSI/JavaScriptObject.h +0 -60
- package/ios/JSI/JavaScriptObject.mm +0 -93
- package/ios/JSI/JavaScriptRuntime.mm +0 -102
- package/ios/NativeModulesProxy/EXComponentDataCompatibleWrapper.h +0 -16
- package/ios/NativeModulesProxy/EXComponentDataCompatibleWrapper.m +0 -28
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import Nimble
|
|
1
|
+
import ExpoModulesTestCore
|
|
3
2
|
|
|
4
3
|
@testable import ExpoModulesCore
|
|
5
4
|
|
|
6
|
-
class FunctionSpec:
|
|
5
|
+
class FunctionSpec: ExpoSpec {
|
|
7
6
|
override func spec() {
|
|
8
7
|
let appContext = AppContext()
|
|
9
8
|
let functionName = "test function name"
|
|
@@ -11,7 +10,7 @@ class FunctionSpec: QuickSpec {
|
|
|
11
10
|
func testFunctionReturning<T: Equatable>(value returnValue: T) {
|
|
12
11
|
waitUntil { done in
|
|
13
12
|
mockModuleHolder(appContext) {
|
|
14
|
-
|
|
13
|
+
AsyncFunction(functionName) {
|
|
15
14
|
return returnValue
|
|
16
15
|
}
|
|
17
16
|
}
|
|
@@ -27,7 +26,7 @@ class FunctionSpec: QuickSpec {
|
|
|
27
26
|
it("is called") {
|
|
28
27
|
waitUntil { done in
|
|
29
28
|
mockModuleHolder(appContext) {
|
|
30
|
-
|
|
29
|
+
AsyncFunction(functionName) {
|
|
31
30
|
done()
|
|
32
31
|
}
|
|
33
32
|
}
|
|
@@ -60,7 +59,7 @@ class FunctionSpec: QuickSpec {
|
|
|
60
59
|
let str: String? = nil
|
|
61
60
|
|
|
62
61
|
mockModuleHolder(appContext) {
|
|
63
|
-
|
|
62
|
+
AsyncFunction(functionName) { (a: String?) in
|
|
64
63
|
expect(a == nil) == true
|
|
65
64
|
}
|
|
66
65
|
}
|
|
@@ -71,7 +70,7 @@ class FunctionSpec: QuickSpec {
|
|
|
71
70
|
let array: [[String]] = [["expo"]]
|
|
72
71
|
|
|
73
72
|
mockModuleHolder(appContext) {
|
|
74
|
-
|
|
73
|
+
AsyncFunction(functionName) { (a: [[String]]) in
|
|
75
74
|
expect(a.first!.first) == array.first!.first
|
|
76
75
|
}
|
|
77
76
|
}
|
|
@@ -92,7 +91,7 @@ class FunctionSpec: QuickSpec {
|
|
|
92
91
|
it("converts to simple record when passed as an argument") {
|
|
93
92
|
waitUntil { done in
|
|
94
93
|
mockModuleHolder(appContext) {
|
|
95
|
-
|
|
94
|
+
AsyncFunction(functionName) { (a: TestRecord) in
|
|
96
95
|
return a.property
|
|
97
96
|
}
|
|
98
97
|
}
|
|
@@ -108,7 +107,7 @@ class FunctionSpec: QuickSpec {
|
|
|
108
107
|
it("converts to record with custom key") {
|
|
109
108
|
waitUntil { done in
|
|
110
109
|
mockModuleHolder(appContext) {
|
|
111
|
-
|
|
110
|
+
AsyncFunction(functionName) { (a: TestRecord) in
|
|
112
111
|
return a.customKeyProperty
|
|
113
112
|
}
|
|
114
113
|
}
|
|
@@ -124,7 +123,7 @@ class FunctionSpec: QuickSpec {
|
|
|
124
123
|
it("returns the record back") {
|
|
125
124
|
waitUntil { done in
|
|
126
125
|
mockModuleHolder(appContext) {
|
|
127
|
-
|
|
126
|
+
AsyncFunction(functionName) { (a: TestRecord) in
|
|
128
127
|
return a.toDictionary()
|
|
129
128
|
}
|
|
130
129
|
}
|
|
@@ -145,15 +144,14 @@ class FunctionSpec: QuickSpec {
|
|
|
145
144
|
it("throws when called with more arguments than expected") {
|
|
146
145
|
waitUntil { done in
|
|
147
146
|
mockModuleHolder(appContext) {
|
|
148
|
-
|
|
147
|
+
AsyncFunction(functionName) { (_: Int) in
|
|
149
148
|
return "something"
|
|
150
149
|
}
|
|
151
150
|
}
|
|
152
151
|
// Function expects one argument, let's give it more.
|
|
153
152
|
.call(function: functionName, args: [1, 2]) { _, error in
|
|
154
153
|
expect(error).notTo(beNil())
|
|
155
|
-
expect(error).to(beAKindOf(
|
|
156
|
-
expect((error as! Exception).isCausedBy(InvalidArgsNumberException.self)) == true
|
|
154
|
+
expect(error).to(beAKindOf(InvalidArgsNumberException.self))
|
|
157
155
|
done()
|
|
158
156
|
}
|
|
159
157
|
}
|
|
@@ -162,14 +160,14 @@ class FunctionSpec: QuickSpec {
|
|
|
162
160
|
it("throws when called with arguments of incompatible types") {
|
|
163
161
|
waitUntil { done in
|
|
164
162
|
mockModuleHolder(appContext) {
|
|
165
|
-
|
|
163
|
+
AsyncFunction(functionName) { (_: String) in
|
|
166
164
|
return "something"
|
|
167
165
|
}
|
|
168
166
|
}
|
|
169
167
|
// Function expects a string, let's give it a number.
|
|
170
168
|
.call(function: functionName, args: [1]) { value, error in
|
|
171
169
|
expect(error).notTo(beNil())
|
|
172
|
-
expect(error).to(beAKindOf(
|
|
170
|
+
expect(error).to(beAKindOf(ArgumentCastException.self))
|
|
173
171
|
expect((error as! Exception).isCausedBy(Conversions.CastingException<String>.self)) == true
|
|
174
172
|
done()
|
|
175
173
|
}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
// Copyright 2018-present 650 Industries. All rights reserved.
|
|
2
2
|
|
|
3
3
|
import CoreGraphics
|
|
4
|
-
import
|
|
5
|
-
import Nimble
|
|
4
|
+
import ExpoModulesTestCore
|
|
6
5
|
|
|
7
6
|
@testable import ExpoModulesCore
|
|
8
7
|
|
|
9
|
-
class FunctionWithConvertiblesSpec:
|
|
8
|
+
class FunctionWithConvertiblesSpec: ExpoSpec {
|
|
10
9
|
override func spec() {
|
|
11
10
|
let appContext = AppContext()
|
|
12
11
|
let functionName = "function"
|
|
@@ -18,7 +17,7 @@ class FunctionWithConvertiblesSpec: QuickSpec {
|
|
|
18
17
|
let height = 592.1
|
|
19
18
|
|
|
20
19
|
mockModuleHolder(appContext) {
|
|
21
|
-
|
|
20
|
+
AsyncFunction(functionName) { (point: CGPoint, size: CGSize, vector: CGVector, rect: CGRect) in
|
|
22
21
|
expect(point.x) == x
|
|
23
22
|
expect(point.y) == y
|
|
24
23
|
expect(size.width) == width
|
|
@@ -48,7 +47,7 @@ class FunctionWithConvertiblesSpec: QuickSpec {
|
|
|
48
47
|
}
|
|
49
48
|
|
|
50
49
|
mockModuleHolder(appContext) {
|
|
51
|
-
|
|
50
|
+
AsyncFunction(functionName) { (color1: CGColor, color2: CGColor, color3: CGColor, color4: CGColor) in
|
|
52
51
|
testColorComponents(color1, 0x2A, 0x4B, 0x5D, 0xFF)
|
|
53
52
|
testColorComponents(color2, 0x11, 0xFF, 0x00, 0xDD)
|
|
54
53
|
testColorComponents(color3, 0x66, 0x00, 0xCC, 0xAA)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import ExpoModulesTestCore
|
|
4
|
+
|
|
5
|
+
@testable import ExpoModulesCore
|
|
6
|
+
|
|
7
|
+
final class JavaScriptObjectSpec: ExpoSpec {
|
|
8
|
+
override func spec() {
|
|
9
|
+
let runtime = JavaScriptRuntime()
|
|
10
|
+
var object: JavaScriptObject?
|
|
11
|
+
|
|
12
|
+
let key = "expo"
|
|
13
|
+
let value1 = "💙"
|
|
14
|
+
let value2 = "💛"
|
|
15
|
+
|
|
16
|
+
beforeEach {
|
|
17
|
+
object = runtime.createObject()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
describe("hasProperty") {
|
|
21
|
+
it("returns false when the property is missing") {
|
|
22
|
+
expect(object?.hasProperty(key)) == false
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
it("returns true when the property exists") {
|
|
26
|
+
object?.setProperty(key, value: value1)
|
|
27
|
+
expect(object?.hasProperty(key)) == true
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
it("returns true when the property is explicitly set to undefined") {
|
|
31
|
+
object?.setProperty(key, value: nil)
|
|
32
|
+
expect(object?.hasProperty(key)) == true
|
|
33
|
+
expect(object?.getProperty(key).isUndefined()) == true
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
describe("getProperty") {
|
|
38
|
+
it("returns correct value") {
|
|
39
|
+
object?.setProperty(key, value: value1)
|
|
40
|
+
expect(try! object?.getProperty(key).asString()) == value1
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
it("returns undefined") {
|
|
44
|
+
expect(object?.getProperty("bar").isUndefined()) == true
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
describe("setProperty") {
|
|
49
|
+
it("sets") {
|
|
50
|
+
object?.setProperty(key, value: value1)
|
|
51
|
+
expect(try! object?.getProperty(key).asString()) == value1
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
it("overrides") {
|
|
55
|
+
object?.setProperty(key, value: value1)
|
|
56
|
+
object?.setProperty(key, value: value2)
|
|
57
|
+
expect(try! object?.getProperty(key).asString()) == value2
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
it("unsets") {
|
|
61
|
+
object?.setProperty(key, value: nil)
|
|
62
|
+
expect(object?.getProperty(key).isUndefined()) == true
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
describe("defineProperty") {
|
|
67
|
+
it("defines non-enumerable property") {
|
|
68
|
+
object?.defineProperty(key, value: value1, options: [])
|
|
69
|
+
expect(try! object?.getProperty(key).asString()) == value1
|
|
70
|
+
expect(object?.getPropertyNames()).notTo(contain(key))
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
it("defines enumerable property") {
|
|
74
|
+
// When the property is enumerable, it is listed in the property names
|
|
75
|
+
object?.defineProperty(key, value: value1, options: .enumerable)
|
|
76
|
+
expect(try! object?.getProperty(key).asString()) == value1
|
|
77
|
+
expect(object?.getPropertyNames()).to(contain(key))
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
it("defines configurable property") {
|
|
81
|
+
// Configurable allows to redefine the property
|
|
82
|
+
object?.defineProperty(key, value: value1, options: .configurable)
|
|
83
|
+
expect(try! object?.getProperty(key).asString()) == value1
|
|
84
|
+
object?.defineProperty(key, value: value2, options: [])
|
|
85
|
+
expect(try! object?.getProperty(key).asString()) == value2
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
it("defines writable property") {
|
|
89
|
+
// Writable allows changing the property
|
|
90
|
+
object?.defineProperty(key, value: value1, options: .writable)
|
|
91
|
+
expect(try! object?.getProperty(key).asString()) == value1
|
|
92
|
+
object?.setProperty(key, value: value2)
|
|
93
|
+
expect(try! object?.getProperty(key).asString()) == value2
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import ExpoModulesTestCore
|
|
2
|
+
|
|
3
|
+
@testable import ExpoModulesCore
|
|
4
|
+
|
|
5
|
+
class JavaScriptRuntimeSpec: ExpoSpec {
|
|
6
|
+
override func spec() {
|
|
7
|
+
let runtime = JavaScriptRuntime()
|
|
8
|
+
|
|
9
|
+
it("has global object accessible") {
|
|
10
|
+
expect(runtime.global) !== nil
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
describe("eval") {
|
|
14
|
+
it("returns undefined") {
|
|
15
|
+
let undefined = try! runtime.eval("undefined")
|
|
16
|
+
expect(undefined.isUndefined()) == true
|
|
17
|
+
expect(undefined.kind) == .undefined
|
|
18
|
+
expect(undefined.isNull()) == false
|
|
19
|
+
expect(undefined.getRaw()).to(beNil())
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
it("returns null") {
|
|
23
|
+
let null = try! runtime.eval("null")
|
|
24
|
+
expect(null.isNull()) == true
|
|
25
|
+
expect(null.kind) == .null
|
|
26
|
+
expect(null.getRaw()).to(beNil())
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
it("returns bool") {
|
|
30
|
+
let boolTrue = try! runtime.eval("true")
|
|
31
|
+
let boolFalse = try! runtime.eval("false")
|
|
32
|
+
expect(boolTrue.isBool()) == true
|
|
33
|
+
expect(boolFalse.isBool()) == true
|
|
34
|
+
expect(boolTrue.kind) == .bool
|
|
35
|
+
expect(boolFalse.kind) == .bool
|
|
36
|
+
expect(try! boolTrue.asBool()) == true
|
|
37
|
+
expect(try! boolFalse.asBool()) == false
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
it("returns number") {
|
|
41
|
+
let number = try! runtime.eval("1.23")
|
|
42
|
+
expect(number.isNumber()) == true
|
|
43
|
+
expect(number.kind) == .number
|
|
44
|
+
expect(try! number.asInt()) == 1
|
|
45
|
+
expect(try! number.asDouble()) == 1.23
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
it("returns string") {
|
|
49
|
+
let string = try! runtime.eval("'foobar'")
|
|
50
|
+
expect(string.isString()) == true
|
|
51
|
+
expect(string.kind) == .string
|
|
52
|
+
expect(try! string.asString()) == "foobar"
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
it("returns array") {
|
|
56
|
+
let array = try! runtime.eval("(['foo', 'bar'])")
|
|
57
|
+
expect(array.isObject()) == true
|
|
58
|
+
expect(array.kind) == .object
|
|
59
|
+
expect(try! array.asArray().map { try $0?.asString() }) == ["foo", "bar"]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
it("returns dict") {
|
|
63
|
+
let dict1 = try! runtime.eval("({ 'foo': 123 })")
|
|
64
|
+
let dict2 = try! runtime.eval("({ 'foo': 'bar' })")
|
|
65
|
+
expect(dict1.isObject()) == true
|
|
66
|
+
expect(dict2.isObject()) == true
|
|
67
|
+
expect(dict1.kind) == .object
|
|
68
|
+
expect(dict2.kind) == .object
|
|
69
|
+
expect(try! dict1.asDict() as? [String: Int]) == ["foo": 123]
|
|
70
|
+
expect(try! dict2.asDict() as? [String: String]) == ["foo": "bar"]
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
it("returns function") {
|
|
74
|
+
let function = try! runtime.eval("(function() {})")
|
|
75
|
+
expect(function.isObject()) == true
|
|
76
|
+
expect(function.isFunction()) == true
|
|
77
|
+
expect(function.kind) == .function
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
it("returns symbol") {
|
|
81
|
+
let symbol = try! runtime.eval("Symbol('foo')")
|
|
82
|
+
expect(symbol.isSymbol()) == true
|
|
83
|
+
expect(symbol.kind) == .symbol
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
it("throws evaluation exception") {
|
|
87
|
+
expect({ try runtime.eval("foo") }).to(throwError { error in
|
|
88
|
+
expect(error).to(beAKindOf(JavaScriptEvalException.self))
|
|
89
|
+
expect((error as! JavaScriptEvalException).reason).to(contain("Can't find variable: foo"))
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import Nimble
|
|
1
|
+
import ExpoModulesTestCore
|
|
3
2
|
|
|
4
3
|
@testable import ExpoModulesCore
|
|
5
4
|
|
|
@@ -11,7 +10,7 @@ import Nimble
|
|
|
11
10
|
|
|
12
11
|
NOTE: Each test registers the module because only registered modules can capture events.
|
|
13
12
|
*/
|
|
14
|
-
class ModuleEventListenersSpec:
|
|
13
|
+
class ModuleEventListenersSpec: ExpoSpec {
|
|
15
14
|
override func spec() {
|
|
16
15
|
var appContext: AppContext!
|
|
17
16
|
|
|
@@ -19,22 +18,22 @@ class ModuleEventListenersSpec: QuickSpec {
|
|
|
19
18
|
appContext = AppContext()
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
it("calls
|
|
21
|
+
it("calls OnCreate once the module instance is created") {
|
|
23
22
|
waitUntil { done in
|
|
24
23
|
_ = mockModuleHolder(appContext) {
|
|
25
|
-
|
|
24
|
+
OnCreate {
|
|
26
25
|
done()
|
|
27
26
|
}
|
|
28
27
|
}
|
|
29
28
|
}
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
it("calls
|
|
31
|
+
it("calls OnDestroy once the module is about to be deallocated") {
|
|
33
32
|
waitUntil { done in
|
|
34
33
|
let moduleName = "mockedModule"
|
|
35
34
|
let holder = mockModuleHolder(appContext) {
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
Name(moduleName)
|
|
36
|
+
OnDestroy {
|
|
38
37
|
done()
|
|
39
38
|
}
|
|
40
39
|
}
|
|
@@ -45,10 +44,10 @@ class ModuleEventListenersSpec: QuickSpec {
|
|
|
45
44
|
}
|
|
46
45
|
}
|
|
47
46
|
|
|
48
|
-
it("calls
|
|
47
|
+
it("calls OnAppContextDestroys once the context destroys") {
|
|
49
48
|
waitUntil { done in
|
|
50
49
|
let holder = mockModuleHolder(appContext) {
|
|
51
|
-
|
|
50
|
+
OnAppContextDestroys {
|
|
52
51
|
done()
|
|
53
52
|
}
|
|
54
53
|
}
|
|
@@ -70,10 +69,10 @@ class ModuleEventListenersSpec: QuickSpec {
|
|
|
70
69
|
}
|
|
71
70
|
}
|
|
72
71
|
|
|
73
|
-
it("calls
|
|
72
|
+
it("calls OnAppEntersForeground when system's willEnterForegroundNotification is sent") {
|
|
74
73
|
waitUntil { done in
|
|
75
74
|
let holder = mockModuleHolder(appContext) {
|
|
76
|
-
|
|
75
|
+
OnAppEntersForeground {
|
|
77
76
|
done()
|
|
78
77
|
}
|
|
79
78
|
}
|
|
@@ -82,10 +81,10 @@ class ModuleEventListenersSpec: QuickSpec {
|
|
|
82
81
|
}
|
|
83
82
|
}
|
|
84
83
|
|
|
85
|
-
it("calls
|
|
84
|
+
it("calls OnAppBecomesActive when system's didBecomeActiveNotification is sent") {
|
|
86
85
|
waitUntil { done in
|
|
87
86
|
let holder = mockModuleHolder(appContext) {
|
|
88
|
-
|
|
87
|
+
OnAppBecomesActive {
|
|
89
88
|
done()
|
|
90
89
|
}
|
|
91
90
|
}
|
|
@@ -94,10 +93,10 @@ class ModuleEventListenersSpec: QuickSpec {
|
|
|
94
93
|
}
|
|
95
94
|
}
|
|
96
95
|
|
|
97
|
-
it("calls
|
|
96
|
+
it("calls OnAppEntersBackground when system's didEnterBackgroundNotification is sent") {
|
|
98
97
|
waitUntil { done in
|
|
99
98
|
let holder = mockModuleHolder(appContext) {
|
|
100
|
-
|
|
99
|
+
OnAppEntersBackground {
|
|
101
100
|
done()
|
|
102
101
|
}
|
|
103
102
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import Nimble
|
|
1
|
+
import ExpoModulesTestCore
|
|
3
2
|
|
|
4
3
|
@testable import ExpoModulesCore
|
|
5
4
|
|
|
6
|
-
class RecordSpec:
|
|
5
|
+
class RecordSpec: ExpoSpec {
|
|
7
6
|
override func spec() {
|
|
8
7
|
it("initializes with empty dictionary") {
|
|
9
8
|
struct TestRecord: Record { }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-modules-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
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": "b9d655c1bed682ad8919e071dd923968773f05b5"
|
|
46
46
|
}
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { NativeModules } from 'react-native';
|
|
2
2
|
|
|
3
|
-
import { ProxyNativeModule
|
|
4
|
-
|
|
5
|
-
// `ExpoModulesProxy` is not declared in TypeScript yet. It's installed via JSI.
|
|
6
|
-
declare namespace global {
|
|
7
|
-
const ExpoModulesProxy: TurboNativeModuleProxy;
|
|
8
|
-
}
|
|
3
|
+
import { ProxyNativeModule } from './NativeModulesProxy.types';
|
|
9
4
|
|
|
10
5
|
const NativeProxy = NativeModules.NativeUnimoduleProxy;
|
|
11
6
|
const modulesConstantsKey = 'modulesConstants';
|
|
@@ -13,16 +8,6 @@ const exportedMethodsKey = 'exportedMethods';
|
|
|
13
8
|
|
|
14
9
|
const NativeModulesProxy: { [moduleName: string]: ProxyNativeModule } = {};
|
|
15
10
|
|
|
16
|
-
// Keep it opt-in for now. It's too risky without proper and thorough testing.
|
|
17
|
-
let canUseExpoTurboModules = false;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Sets whether to use a TurboModule version of the proxy.
|
|
21
|
-
*/
|
|
22
|
-
export function useExpoTurboModules(state: boolean = true) {
|
|
23
|
-
canUseExpoTurboModules = state;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
11
|
if (NativeProxy) {
|
|
27
12
|
Object.keys(NativeProxy[exportedMethodsKey]).forEach((moduleName) => {
|
|
28
13
|
NativeModulesProxy[moduleName] = NativeProxy[modulesConstantsKey][moduleName] || {};
|
|
@@ -38,12 +23,7 @@ if (NativeProxy) {
|
|
|
38
23
|
)
|
|
39
24
|
);
|
|
40
25
|
}
|
|
41
|
-
|
|
42
|
-
if (canUseExpoTurboModules && global.ExpoModulesProxy) {
|
|
43
|
-
return global.ExpoModulesProxy.callMethodAsync(moduleName, methodInfo.name, args);
|
|
44
|
-
} else {
|
|
45
|
-
return NativeProxy.callMethod(moduleName, key, args);
|
|
46
|
-
}
|
|
26
|
+
return NativeProxy.callMethod(moduleName, key, args);
|
|
47
27
|
};
|
|
48
28
|
});
|
|
49
29
|
|
|
@@ -3,11 +3,3 @@ export type ProxyNativeModule = {
|
|
|
3
3
|
addListener: (eventName: string) => void;
|
|
4
4
|
removeListeners: (count: number) => void;
|
|
5
5
|
};
|
|
6
|
-
|
|
7
|
-
export type TurboNativeModuleProxy = {
|
|
8
|
-
callMethodAsync: <ReturnType>(
|
|
9
|
-
moduleName: string,
|
|
10
|
-
methodName: string,
|
|
11
|
-
args: any[]
|
|
12
|
-
) => Promise<ReturnType>;
|
|
13
|
-
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { NativeModules,
|
|
2
|
+
import { NativeModules, requireNativeComponent } from 'react-native';
|
|
3
3
|
|
|
4
4
|
// To make the transition from React Native's `requireNativeComponent` to Expo's
|
|
5
5
|
// `requireNativeViewManager` as easy as possible, `requireNativeViewManager` is a drop-in
|
|
@@ -10,11 +10,6 @@ import { NativeModules, UIManager, ViewPropTypes, requireNativeComponent } from
|
|
|
10
10
|
// passed to React Native's View (ex: style, testID) and custom view props, which are passed to the
|
|
11
11
|
// adapter view component in a prop called `proxiedProperties`.
|
|
12
12
|
|
|
13
|
-
// NOTE: React Native is moving away from runtime PropTypes and may remove ViewPropTypes, in which
|
|
14
|
-
// case we will need another way to separate standard React Native view props from other props,
|
|
15
|
-
// which we proxy through the adapter
|
|
16
|
-
const ViewPropTypesKeys = Object.keys(ViewPropTypes);
|
|
17
|
-
|
|
18
13
|
type NativeExpoComponentProps = {
|
|
19
14
|
proxiedProperties: object;
|
|
20
15
|
};
|
|
@@ -23,14 +18,14 @@ type NativeExpoComponentProps = {
|
|
|
23
18
|
* A drop-in replacement for `requireNativeComponent`.
|
|
24
19
|
*/
|
|
25
20
|
export function requireNativeViewManager<P = any>(viewName: string): React.ComponentType<P> {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
)
|
|
33
|
-
|
|
21
|
+
const { viewManagersMetadata } = NativeModules.NativeUnimoduleProxy;
|
|
22
|
+
const viewManagerConfig = viewManagersMetadata?.[viewName];
|
|
23
|
+
|
|
24
|
+
if (__DEV__ && !viewManagerConfig) {
|
|
25
|
+
const exportedViewManagerNames = Object.keys(viewManagersMetadata).join(', ');
|
|
26
|
+
console.warn(
|
|
27
|
+
`The native view manager required by name (${viewName}) from NativeViewManagerAdapter isn't exported by expo-modules-core. Views of this type may not render correctly. Exported view managers: [${exportedViewManagerNames}].`
|
|
28
|
+
);
|
|
34
29
|
}
|
|
35
30
|
|
|
36
31
|
// Set up the React Native native component, which is an adapter to the universal module's view
|
|
@@ -38,23 +33,12 @@ export function requireNativeViewManager<P = any>(viewName: string): React.Compo
|
|
|
38
33
|
const reactNativeViewName = `ViewManagerAdapter_${viewName}`;
|
|
39
34
|
const ReactNativeComponent =
|
|
40
35
|
requireNativeComponent<NativeExpoComponentProps>(reactNativeViewName);
|
|
41
|
-
const
|
|
42
|
-
? UIManager.getViewManagerConfig(reactNativeViewName)
|
|
43
|
-
: UIManager[reactNativeViewName]) || {
|
|
44
|
-
NativeProps: {},
|
|
45
|
-
directEventTypes: {},
|
|
46
|
-
};
|
|
47
|
-
const reactNativeComponentPropNames = [
|
|
48
|
-
'children',
|
|
49
|
-
...ViewPropTypesKeys,
|
|
50
|
-
...Object.keys(reactNativeUIConfiguration.NativeProps),
|
|
51
|
-
...Object.keys(reactNativeUIConfiguration.directEventTypes),
|
|
52
|
-
];
|
|
36
|
+
const proxiedPropsNames = viewManagerConfig?.propsNames ?? [];
|
|
53
37
|
|
|
54
38
|
// Define a component for universal-module authors to access their native view manager
|
|
55
39
|
function NativeComponentAdapter(props, ref) {
|
|
56
|
-
const nativeProps =
|
|
57
|
-
const proxiedProps =
|
|
40
|
+
const nativeProps = omit(props, proxiedPropsNames);
|
|
41
|
+
const proxiedProps = pick(props, proxiedPropsNames);
|
|
58
42
|
return <ReactNativeComponent {...nativeProps} proxiedProperties={proxiedProps} ref={ref} />;
|
|
59
43
|
}
|
|
60
44
|
NativeComponentAdapter.displayName = `Adapter<${viewName}>`;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import NativeModulesProxy from '../NativeModulesProxy';
|
|
2
2
|
export default NativeModulesProxy.ExpoModulesCoreErrorManager;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
package expo.modules.kotlin.events
|
|
2
|
-
|
|
3
|
-
import android.os.Bundle
|
|
4
|
-
import expo.modules.core.interfaces.services.EventEmitter
|
|
5
|
-
import expo.modules.kotlin.ModuleHolder
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* In Swift, we check if the event is supported. Otherwise, we can't send such event through the bridge.
|
|
9
|
-
* However, in Kotlin this is unnecessary, but to make our API consistent, we added similar check.
|
|
10
|
-
* But because of that, we had to create a wrapper for EventEmitter.
|
|
11
|
-
*/
|
|
12
|
-
class KEventEmitterWrapper(
|
|
13
|
-
private val moduleHolder: ModuleHolder,
|
|
14
|
-
private val legacyEventEmitter: EventEmitter
|
|
15
|
-
) : EventEmitter by legacyEventEmitter {
|
|
16
|
-
override fun emit(eventName: String, eventBody: Bundle?) {
|
|
17
|
-
require(
|
|
18
|
-
moduleHolder
|
|
19
|
-
.definition
|
|
20
|
-
.eventsDefinition
|
|
21
|
-
?.names
|
|
22
|
-
?.contains(eventName) == true
|
|
23
|
-
) { "Unsupported event: $eventName." }
|
|
24
|
-
legacyEventEmitter.emit(eventName, eventBody)
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
package expo.modules.kotlin.methods
|
|
2
|
-
|
|
3
|
-
import expo.modules.kotlin.Promise
|
|
4
|
-
import expo.modules.kotlin.types.AnyType
|
|
5
|
-
|
|
6
|
-
class Method(
|
|
7
|
-
name: String,
|
|
8
|
-
argsType: Array<AnyType>,
|
|
9
|
-
private val body: (args: Array<out Any?>) -> Any?
|
|
10
|
-
) : AnyMethod(name, argsType) {
|
|
11
|
-
override fun callImplementation(args: Array<out Any?>, promise: Promise) {
|
|
12
|
-
promise.resolve(body(args))
|
|
13
|
-
}
|
|
14
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
package expo.modules.kotlin.methods
|
|
2
|
-
|
|
3
|
-
import expo.modules.kotlin.Promise
|
|
4
|
-
import expo.modules.kotlin.types.AnyType
|
|
5
|
-
|
|
6
|
-
class PromiseMethod(
|
|
7
|
-
name: String,
|
|
8
|
-
argsType: Array<AnyType>,
|
|
9
|
-
private val body: (args: Array<out Any?>, promise: Promise) -> Unit
|
|
10
|
-
) : AnyMethod(name, argsType) {
|
|
11
|
-
|
|
12
|
-
override fun callImplementation(args: Array<out Any?>, promise: Promise) {
|
|
13
|
-
body(args, promise)
|
|
14
|
-
}
|
|
15
|
-
}
|