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.
Files changed (167) hide show
  1. package/CHANGELOG.md +18 -5
  2. package/android/CMakeLists.txt +154 -0
  3. package/android/build.gradle +293 -5
  4. package/android/src/main/cpp/Exceptions.cpp +22 -0
  5. package/android/src/main/cpp/Exceptions.h +38 -0
  6. package/android/src/main/cpp/ExpoModulesHostObject.cpp +47 -0
  7. package/android/src/main/cpp/ExpoModulesHostObject.h +32 -0
  8. package/android/src/main/cpp/JNIFunctionBody.cpp +29 -0
  9. package/android/src/main/cpp/JNIFunctionBody.h +50 -0
  10. package/android/src/main/cpp/JNIInjector.cpp +19 -0
  11. package/android/src/main/cpp/JSIInteropModuleRegistry.cpp +122 -0
  12. package/android/src/main/cpp/JSIInteropModuleRegistry.h +96 -0
  13. package/android/src/main/cpp/JSIObjectWrapper.h +33 -0
  14. package/android/src/main/cpp/JSITypeConverter.h +84 -0
  15. package/android/src/main/cpp/JavaScriptModuleObject.cpp +138 -0
  16. package/android/src/main/cpp/JavaScriptModuleObject.h +122 -0
  17. package/android/src/main/cpp/JavaScriptObject.cpp +125 -0
  18. package/android/src/main/cpp/JavaScriptObject.h +131 -0
  19. package/android/src/main/cpp/JavaScriptRuntime.cpp +127 -0
  20. package/android/src/main/cpp/JavaScriptRuntime.h +87 -0
  21. package/android/src/main/cpp/JavaScriptValue.cpp +172 -0
  22. package/android/src/main/cpp/JavaScriptValue.h +78 -0
  23. package/android/src/main/cpp/MethodMetadata.cpp +230 -0
  24. package/android/src/main/cpp/MethodMetadata.h +92 -0
  25. package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +2 -0
  26. package/android/src/main/java/expo/modules/core/errors/ContextDestroyedException.kt +7 -0
  27. package/android/src/main/java/expo/modules/interfaces/permissions/Permissions.java +30 -0
  28. package/android/src/main/java/expo/modules/kotlin/AppContext.kt +49 -1
  29. package/android/src/main/java/expo/modules/kotlin/ConcatIterator.kt +18 -0
  30. package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +15 -12
  31. package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +39 -3
  32. package/android/src/main/java/expo/modules/kotlin/defaultmodules/ErrorManagerModule.kt +2 -2
  33. package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +13 -0
  34. package/android/src/main/java/expo/modules/kotlin/exception/ExceptionDecorator.kt +2 -0
  35. package/android/src/main/java/expo/modules/kotlin/functions/AnyFunction.kt +19 -14
  36. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +29 -7
  37. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +13 -13
  38. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionComponent.kt +18 -0
  39. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromiseComponent.kt +18 -0
  40. package/android/src/main/java/expo/modules/kotlin/functions/SuspendFunctionComponent.kt +56 -0
  41. package/android/src/main/java/expo/modules/kotlin/functions/SyncFunctionComponent.kt +28 -0
  42. package/android/src/main/java/expo/modules/kotlin/jni/CppType.kt +18 -0
  43. package/android/src/main/java/expo/modules/kotlin/jni/JNIFunctionBody.kt +39 -0
  44. package/android/src/main/java/expo/modules/kotlin/jni/JSIInteropModuleRegistry.kt +89 -0
  45. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptModuleObject.kt +44 -0
  46. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptObject.kt +113 -0
  47. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptValue.kt +35 -0
  48. package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +15 -5
  49. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +65 -111
  50. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +35 -2
  51. package/android/src/main/java/expo/modules/kotlin/providers/AppContextProvider.kt +14 -0
  52. package/android/src/main/java/expo/modules/kotlin/providers/CurrentActivityProvider.kt +22 -0
  53. package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +19 -2
  54. package/android/src/main/java/expo/modules/kotlin/types/AnyType.kt +3 -2
  55. package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +7 -2
  56. package/android/src/main/java/expo/modules/kotlin/types/BasicTypeConverters.kt +68 -20
  57. package/android/src/main/java/expo/modules/kotlin/types/EnumTypeConverter.kt +50 -22
  58. package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +18 -2
  59. package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +18 -2
  60. package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +17 -2
  61. package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +43 -3
  62. package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +5 -0
  63. package/build/NativeModulesProxy.native.d.ts.map +1 -1
  64. package/build/NativeModulesProxy.native.js +9 -3
  65. package/build/NativeModulesProxy.native.js.map +1 -1
  66. package/ios/AppDelegates/EXAppDelegatesLoader.m +1 -2
  67. package/ios/ExpoModulesCore.podspec +1 -1
  68. package/ios/JSI/EXJSIConversions.mm +6 -0
  69. package/ios/JSI/EXJSIInstaller.h +15 -21
  70. package/ios/JSI/EXJSIInstaller.mm +39 -3
  71. package/ios/JSI/EXJSIUtils.h +47 -3
  72. package/ios/JSI/EXJSIUtils.mm +88 -4
  73. package/ios/JSI/EXJavaScriptObject.h +11 -18
  74. package/ios/JSI/EXJavaScriptObject.mm +37 -18
  75. package/ios/JSI/EXJavaScriptRuntime.h +43 -9
  76. package/ios/JSI/EXJavaScriptRuntime.mm +70 -27
  77. package/ios/JSI/EXJavaScriptTypedArray.h +30 -0
  78. package/ios/JSI/EXJavaScriptTypedArray.mm +29 -0
  79. package/ios/JSI/EXJavaScriptValue.h +3 -2
  80. package/ios/JSI/EXJavaScriptValue.mm +17 -20
  81. package/ios/JSI/EXJavaScriptWeakObject.h +23 -0
  82. package/ios/JSI/EXJavaScriptWeakObject.mm +53 -0
  83. package/ios/JSI/EXObjectDeallocator.h +27 -0
  84. package/ios/JSI/ExpoModulesHostObject.h +3 -3
  85. package/ios/JSI/ExpoModulesHostObject.mm +4 -4
  86. package/ios/JSI/JavaScriptRuntime.swift +38 -1
  87. package/ios/JSI/JavaScriptValue.swift +7 -0
  88. package/ios/JSI/TypedArray.cpp +67 -0
  89. package/ios/JSI/TypedArray.h +46 -0
  90. package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +0 -11
  91. package/ios/NativeModulesProxy/EXNativeModulesProxy.h +17 -10
  92. package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +85 -77
  93. package/ios/NativeModulesProxy/NativeModulesProxyModule.swift +17 -0
  94. package/ios/Services/EXReactNativeEventEmitter.h +2 -2
  95. package/ios/Services/EXReactNativeEventEmitter.m +11 -6
  96. package/ios/Swift/AppContext.swift +208 -28
  97. package/ios/Swift/Arguments/AnyArgument.swift +18 -0
  98. package/ios/Swift/Arguments/{Types/EnumArgumentType.swift → EnumArgument.swift} +2 -17
  99. package/ios/Swift/Classes/ClassComponent.swift +95 -0
  100. package/ios/Swift/Classes/ClassComponentElement.swift +33 -0
  101. package/ios/Swift/Classes/ClassComponentElementsBuilder.swift +34 -0
  102. package/ios/Swift/Classes/ClassComponentFactories.swift +96 -0
  103. package/ios/Swift/DynamicTypes/AnyDynamicType.swift +44 -0
  104. package/ios/Swift/DynamicTypes/DynamicArrayType.swift +56 -0
  105. package/ios/Swift/DynamicTypes/DynamicConvertibleType.swift +27 -0
  106. package/ios/Swift/DynamicTypes/DynamicEnumType.swift +27 -0
  107. package/ios/Swift/DynamicTypes/DynamicOptionalType.swift +63 -0
  108. package/ios/Swift/DynamicTypes/DynamicRawType.swift +33 -0
  109. package/ios/Swift/DynamicTypes/DynamicSharedObjectType.swift +37 -0
  110. package/ios/Swift/DynamicTypes/DynamicType.swift +39 -0
  111. package/ios/Swift/DynamicTypes/DynamicTypedArrayType.swift +46 -0
  112. package/ios/Swift/Exceptions/CodedError.swift +1 -1
  113. package/ios/Swift/Exceptions/Exception.swift +8 -6
  114. package/ios/Swift/Exceptions/UnexpectedException.swift +2 -1
  115. package/ios/Swift/ExpoBridgeModule.m +5 -0
  116. package/ios/Swift/ExpoBridgeModule.swift +65 -0
  117. package/ios/Swift/Functions/AnyFunction.swift +33 -31
  118. package/ios/Swift/Functions/AsyncFunctionComponent.swift +196 -59
  119. package/ios/Swift/Functions/SyncFunctionComponent.swift +142 -58
  120. package/ios/Swift/JavaScriptUtils.swift +32 -57
  121. package/ios/Swift/Logging/LogHandlers.swift +39 -0
  122. package/ios/Swift/Logging/LogType.swift +62 -0
  123. package/ios/Swift/Logging/Logger.swift +198 -0
  124. package/ios/Swift/ModuleHolder.swift +19 -54
  125. package/ios/Swift/ModuleRegistry.swift +7 -1
  126. package/ios/Swift/Modules/AnyModule.swift +3 -3
  127. package/ios/Swift/ModulesProvider.swift +2 -0
  128. package/ios/Swift/Objects/JavaScriptObjectBuilder.swift +37 -0
  129. package/ios/Swift/Objects/ObjectDefinition.swift +74 -1
  130. package/ios/Swift/Objects/ObjectDefinitionComponents.swift +77 -68
  131. package/ios/Swift/Objects/PropertyComponent.swift +147 -0
  132. package/ios/Swift/Promise.swift +12 -3
  133. package/ios/Swift/Records/Field.swift +2 -2
  134. package/ios/Swift/SharedObjects/SharedObject.swift +20 -0
  135. package/ios/Swift/SharedObjects/SharedObjectRegistry.swift +129 -0
  136. package/ios/Swift/TypedArrays/AnyTypedArray.swift +11 -0
  137. package/ios/Swift/TypedArrays/ConcreteTypedArrays.swift +56 -0
  138. package/ios/Swift/TypedArrays/GenericTypedArray.swift +49 -0
  139. package/ios/Swift/TypedArrays/TypedArray.swift +80 -0
  140. package/ios/Swift/Utilities.swift +28 -0
  141. package/ios/Swift/Views/ConcreteViewProp.swift +3 -3
  142. package/ios/Swift/Views/ViewManagerDefinitionComponents.swift +2 -2
  143. package/ios/Tests/ClassComponentSpec.swift +210 -0
  144. package/ios/Tests/DynamicTypeSpec.swift +336 -0
  145. package/ios/Tests/EnumArgumentSpec.swift +48 -0
  146. package/ios/Tests/ExpoModulesSpec.swift +17 -3
  147. package/ios/Tests/FunctionSpec.swift +167 -118
  148. package/ios/Tests/Mocks/ModuleMocks.swift +1 -1
  149. package/ios/Tests/PropertyComponentSpec.swift +95 -0
  150. package/ios/Tests/SharedObjectRegistrySpec.swift +109 -0
  151. package/ios/Tests/TypedArraysSpec.swift +136 -0
  152. package/package.json +2 -2
  153. package/src/NativeModulesProxy.native.ts +13 -3
  154. package/src/ts-declarations/ExpoModules.d.ts +7 -0
  155. package/tsconfig.json +1 -1
  156. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromise.kt +0 -15
  157. package/android/src/main/java/expo/modules/kotlin/functions/AsyncSuspendFunction.kt +0 -36
  158. package/ios/Swift/Arguments/AnyArgumentType.swift +0 -13
  159. package/ios/Swift/Arguments/ArgumentType.swift +0 -28
  160. package/ios/Swift/Arguments/Types/ArrayArgumentType.swift +0 -42
  161. package/ios/Swift/Arguments/Types/ConvertibleArgumentType.swift +0 -16
  162. package/ios/Swift/Arguments/Types/OptionalArgumentType.swift +0 -49
  163. package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +0 -15
  164. package/ios/Swift/Arguments/Types/RawArgumentType.swift +0 -25
  165. package/ios/Swift/Functions/ConcreteFunction.swift +0 -103
  166. package/ios/Swift/SwiftInteropBridge.swift +0 -155
  167. package/ios/Tests/ArgumentTypeSpec.swift +0 -143
@@ -4,173 +4,222 @@ import ExpoModulesTestCore
4
4
 
5
5
  class FunctionSpec: ExpoSpec {
6
6
  override func spec() {
7
- let appContext = AppContext()
7
+ let appContext = AppContext.create()
8
8
  let functionName = "test function name"
9
9
 
10
- func testFunctionReturning<T: Equatable>(value returnValue: T) {
11
- waitUntil { done in
12
- mockModuleHolder(appContext) {
13
- AsyncFunction(functionName) {
14
- return returnValue
10
+ context("native") {
11
+ func testFunctionReturning<T: Equatable>(value returnValue: T) {
12
+ waitUntil { done in
13
+ mockModuleHolder(appContext) {
14
+ AsyncFunction(functionName) {
15
+ return returnValue
16
+ }
17
+ }
18
+ .call(function: functionName, args: []) { result in
19
+ let value = try! result.get()
20
+
21
+ expect(value).notTo(beNil())
22
+ expect(value).to(beAKindOf(T.self))
23
+ expect(value as? T).to(equal(returnValue))
24
+ done()
15
25
  }
16
- }
17
- .call(function: functionName, args: []) { value, _ in
18
- expect(value).notTo(beNil())
19
- expect(value).to(beAKindOf(T.self))
20
- expect(value as? T).to(equal(returnValue))
21
- done()
22
26
  }
23
27
  }
24
- }
25
28
 
26
- it("is called") {
27
- waitUntil { done in
28
- mockModuleHolder(appContext) {
29
- AsyncFunction(functionName) {
30
- done()
29
+ it("is called") {
30
+ waitUntil { done in
31
+ mockModuleHolder(appContext) {
32
+ AsyncFunction(functionName) {
33
+ done()
34
+ }
31
35
  }
36
+ .call(function: functionName, args: [])
32
37
  }
33
- .call(function: functionName, args: [])
34
38
  }
35
- }
36
39
 
37
- it("returns bool values") {
38
- testFunctionReturning(value: true)
39
- testFunctionReturning(value: false)
40
- testFunctionReturning(value: [true, false])
41
- }
40
+ it("returns bool values") {
41
+ testFunctionReturning(value: true)
42
+ testFunctionReturning(value: false)
43
+ testFunctionReturning(value: [true, false])
44
+ }
42
45
 
43
- it("returns int values") {
44
- testFunctionReturning(value: 1_234)
45
- testFunctionReturning(value: [2, 1, 3, 7])
46
- }
46
+ it("returns int values") {
47
+ testFunctionReturning(value: 1_234)
48
+ testFunctionReturning(value: [2, 1, 3, 7])
49
+ }
47
50
 
48
- it("returns double values") {
49
- testFunctionReturning(value: 3.14)
50
- testFunctionReturning(value: [0, 1.1, 2.2])
51
- }
51
+ it("returns double values") {
52
+ testFunctionReturning(value: 3.14)
53
+ testFunctionReturning(value: [0, 1.1, 2.2])
54
+ }
52
55
 
53
- it("returns string values") {
54
- testFunctionReturning(value: "a string")
55
- testFunctionReturning(value: ["expo", "modules", "core"])
56
- }
56
+ it("returns string values") {
57
+ testFunctionReturning(value: "a string")
58
+ testFunctionReturning(value: ["expo", "modules", "core"])
59
+ }
57
60
 
58
- it("is called with nil value") {
59
- let str: String? = nil
61
+ it("is called with nil value") {
62
+ let str: String? = nil
60
63
 
61
- mockModuleHolder(appContext) {
62
- AsyncFunction(functionName) { (a: String?) in
63
- expect(a == nil) == true
64
+ mockModuleHolder(appContext) {
65
+ AsyncFunction(functionName) { (a: String?) in
66
+ expect(a == nil) == true
67
+ }
64
68
  }
69
+ .callSync(function: functionName, args: [str as Any])
65
70
  }
66
- .callSync(function: functionName, args: [str as Any])
67
- }
68
71
 
69
- it("is called with an array of arrays") {
70
- let array: [[String]] = [["expo"]]
72
+ it("is called with an array of arrays") {
73
+ let array: [[String]] = [["expo"]]
71
74
 
72
- mockModuleHolder(appContext) {
73
- AsyncFunction(functionName) { (a: [[String]]) in
74
- expect(a.first!.first) == array.first!.first
75
+ mockModuleHolder(appContext) {
76
+ AsyncFunction(functionName) { (a: [[String]]) in
77
+ expect(a.first!.first) == array.first!.first
78
+ }
75
79
  }
80
+ .callSync(function: functionName, args: [array])
76
81
  }
77
- .callSync(function: functionName, args: [array])
78
- }
79
82
 
80
- describe("converting dicts to records") {
81
- struct TestRecord: Record {
82
- @Field var property: String = "expo"
83
- @Field var optionalProperty: Int?
84
- @Field("propertyWithCustomKey") var customKeyProperty: String = "expo"
85
- }
86
- let dict = [
87
- "property": "Hello",
88
- "propertyWithCustomKey": "Expo!"
89
- ]
83
+ describe("converting dicts to records") {
84
+ struct TestRecord: Record {
85
+ @Field var property: String = "expo"
86
+ @Field var optionalProperty: Int?
87
+ @Field("propertyWithCustomKey") var customKeyProperty: String = "expo"
88
+ }
89
+ let dict = [
90
+ "property": "Hello",
91
+ "propertyWithCustomKey": "Expo!"
92
+ ]
93
+
94
+ it("converts to simple record when passed as an argument") {
95
+ waitUntil { done in
96
+ mockModuleHolder(appContext) {
97
+ AsyncFunction(functionName) { (a: TestRecord) in
98
+ return a.property
99
+ }
100
+ }
101
+ .call(function: functionName, args: [dict]) { result in
102
+ let value = try! result.get()
90
103
 
91
- it("converts to simple record when passed as an argument") {
92
- waitUntil { done in
93
- mockModuleHolder(appContext) {
94
- AsyncFunction(functionName) { (a: TestRecord) in
95
- return a.property
104
+ expect(value).notTo(beNil())
105
+ expect(value).to(beAKindOf(String.self))
106
+ expect(value).to(be(dict["property"]))
107
+ done()
96
108
  }
97
109
  }
98
- .call(function: functionName, args: [dict]) { value, _ in
99
- expect(value).notTo(beNil())
100
- expect(value).to(beAKindOf(String.self))
101
- expect(value).to(be(dict["property"]))
102
- done()
110
+ }
111
+
112
+ it("converts to record with custom key") {
113
+ waitUntil { done in
114
+ mockModuleHolder(appContext) {
115
+ AsyncFunction(functionName) { (a: TestRecord) in
116
+ return a.customKeyProperty
117
+ }
118
+ }
119
+ .call(function: functionName, args: [dict]) { result in
120
+ let value = try! result.get()
121
+ expect(value).notTo(beNil())
122
+ expect(value).to(beAKindOf(String.self))
123
+ expect(value).to(be(dict["propertyWithCustomKey"]))
124
+ done()
125
+ }
126
+ }
127
+ }
128
+
129
+ it("returns the record back") {
130
+ waitUntil { done in
131
+ mockModuleHolder(appContext) {
132
+ AsyncFunction(functionName) { (a: TestRecord) in
133
+ return a.toDictionary()
134
+ }
135
+ }
136
+ .call(function: functionName, args: [dict]) { result in
137
+ let value = try! result.get()
138
+
139
+ expect(value).notTo(beNil())
140
+ expect(value).to(beAKindOf(Record.Dict.self))
141
+
142
+ let valueAsDict = value as! Record.Dict
143
+
144
+ expect(valueAsDict["property"] as? String).to(equal(dict["property"]))
145
+ expect(valueAsDict["propertyWithCustomKey"] as? String).to(equal(dict["propertyWithCustomKey"]))
146
+ done()
147
+ }
103
148
  }
104
149
  }
105
150
  }
106
151
 
107
- it("converts to record with custom key") {
152
+ it("throws when called with more arguments than expected") {
108
153
  waitUntil { done in
109
154
  mockModuleHolder(appContext) {
110
- AsyncFunction(functionName) { (a: TestRecord) in
111
- return a.customKeyProperty
155
+ AsyncFunction(functionName) { (_: Int) in
156
+ return "something"
112
157
  }
113
158
  }
114
- .call(function: functionName, args: [dict]) { value, _ in
115
- expect(value).notTo(beNil())
116
- expect(value).to(beAKindOf(String.self))
117
- expect(value).to(be(dict["propertyWithCustomKey"]))
159
+ // Function expects one argument, let's give it more.
160
+ .call(function: functionName, args: [1, 2]) { result in
161
+ switch result {
162
+ case .failure(let error):
163
+ expect(error).notTo(beNil())
164
+ expect(error).to(beAKindOf(InvalidArgsNumberException.self))
165
+ case .success(_):
166
+ fail()
167
+ }
118
168
  done()
119
169
  }
120
170
  }
121
171
  }
122
172
 
123
- it("returns the record back") {
173
+ it("throws when called with arguments of incompatible types") {
124
174
  waitUntil { done in
125
175
  mockModuleHolder(appContext) {
126
- AsyncFunction(functionName) { (a: TestRecord) in
127
- return a.toDictionary()
176
+ AsyncFunction(functionName) { (_: String) in
177
+ return "something"
128
178
  }
129
179
  }
130
- .call(function: functionName, args: [dict]) { value, _ in
131
- expect(value).notTo(beNil())
132
- expect(value).to(beAKindOf(Record.Dict.self))
133
-
134
- let valueAsDict = value as! Record.Dict
135
-
136
- expect(valueAsDict["property"] as? String).to(equal(dict["property"]))
137
- expect(valueAsDict["propertyWithCustomKey"] as? String).to(equal(dict["propertyWithCustomKey"]))
180
+ // Function expects a string, let's give it a number.
181
+ .call(function: functionName, args: [1]) { result in
182
+ switch result {
183
+ case .failure(let error):
184
+ expect(error).notTo(beNil())
185
+ expect(error).to(beAKindOf(ArgumentCastException.self))
186
+ expect(error.isCausedBy(Conversions.CastingException<String>.self)) == true
187
+ case .success(_):
188
+ fail()
189
+ }
138
190
  done()
139
191
  }
140
192
  }
141
193
  }
142
194
  }
143
-
144
- it("throws when called with more arguments than expected") {
145
- waitUntil { done in
146
- mockModuleHolder(appContext) {
147
- AsyncFunction(functionName) { (_: Int) in
148
- return "something"
195
+
196
+ context("JavaScript") {
197
+ let runtime = appContext.runtime
198
+
199
+ beforeSuite {
200
+ appContext.moduleRegistry.register(holder: mockModuleHolder(appContext) {
201
+ Name("TestModule")
202
+
203
+ Function("returnPi") { Double.pi }
204
+
205
+ Function("returnNull") { () -> Double? in
206
+ return nil
149
207
  }
150
- }
151
- // Function expects one argument, let's give it more.
152
- .call(function: functionName, args: [1, 2]) { _, error in
153
- expect(error).notTo(beNil())
154
- expect(error).to(beAKindOf(InvalidArgsNumberException.self))
155
- done()
156
- }
157
- }
158
- }
159
-
160
- it("throws when called with arguments of incompatible types") {
161
- waitUntil { done in
162
- mockModuleHolder(appContext) {
163
- AsyncFunction(functionName) { (_: String) in
164
- return "something"
208
+
209
+ Function("isArgNull") { (arg: Double?) -> Bool in
210
+ return arg == nil
165
211
  }
166
- }
167
- // Function expects a string, let's give it a number.
168
- .call(function: functionName, args: [1]) { value, error in
169
- expect(error).notTo(beNil())
170
- expect(error).to(beAKindOf(ArgumentCastException.self))
171
- expect((error as! Exception).isCausedBy(Conversions.CastingException<String>.self)) == true
172
- done()
173
- }
212
+ })
213
+ }
214
+
215
+ it("returns values") {
216
+ expect(try runtime?.eval("ExpoModules.TestModule.returnPi()").asDouble()) == Double.pi
217
+ expect(try runtime?.eval("ExpoModules.TestModule.returnNull()").isNull()) == true
218
+ }
219
+
220
+ it("accepts optional arguments") {
221
+ expect(try runtime?.eval("ExpoModules.TestModule.isArgNull(3.14)").asBool()) == false
222
+ expect(try runtime?.eval("ExpoModules.TestModule.isArgNull(null)").asBool()) == true
174
223
  }
175
224
  }
176
225
  }
@@ -8,7 +8,7 @@ class NamedModule: Module {
8
8
  static let namedModuleName = "MyModule"
9
9
 
10
10
  func definition() -> ModuleDefinition {
11
- name(Self.namedModuleName)
11
+ Name(Self.namedModuleName)
12
12
  }
13
13
  }
14
14
 
@@ -0,0 +1,95 @@
1
+ import ExpoModulesTestCore
2
+
3
+ @testable import ExpoModulesCore
4
+
5
+ class PropertyComponentSpec: ExpoSpec {
6
+ override func spec() {
7
+ describe("property") {
8
+ it("gets the value") {
9
+ let property = Property("test") { return "expo" }
10
+ expect(property.getValue()) == "expo"
11
+ }
12
+
13
+ it("sets the value") {
14
+ var value = Int.random(in: 0..<100)
15
+ let property = Property("test")
16
+ .get { value }
17
+ .set { (newValue: Int) in
18
+ value = newValue
19
+ }
20
+
21
+ let newValue = Int.random(in: 0..<100)
22
+ property.setValue(newValue)
23
+
24
+ expect(property.getValue()) == value
25
+ expect(value) == newValue
26
+ }
27
+ }
28
+
29
+ describe("module property") {
30
+ let appContext = AppContext.create()
31
+ let runtime = appContext.runtime
32
+
33
+ beforeSuite {
34
+ class PropertyTestModule: Module {
35
+ func definition() -> ModuleDefinition {
36
+ Name("PropertyTest")
37
+
38
+ Property("readOnly") {
39
+ return "foo"
40
+ }
41
+
42
+ var writablePropertyValue = 444
43
+ Property("writable")
44
+ .get {
45
+ return writablePropertyValue
46
+ }
47
+ .set { value in
48
+ writablePropertyValue = value
49
+ }
50
+
51
+ Property("withCaller") { (caller: JavaScriptObject) -> String in
52
+ // Here, the caller is a JS object of the module.
53
+ // Return another property of itself.
54
+ return caller.getProperty("readOnly").getString()
55
+ }
56
+
57
+ Property("undefined")
58
+ }
59
+ }
60
+ appContext.moduleRegistry.register(moduleType: PropertyTestModule.self)
61
+ }
62
+
63
+ it("gets read-only property") {
64
+ let value = try runtime?.eval("ExpoModules.PropertyTest.readOnly")
65
+ expect(value?.getString()) == "foo"
66
+ }
67
+
68
+ it("gets writable property") {
69
+ let value = try runtime?.eval("ExpoModules.PropertyTest.writable")
70
+ expect(value?.getInt()) == 444
71
+ }
72
+
73
+ it("sets writable property") {
74
+ try runtime?.eval("ExpoModules.PropertyTest.writable = 777")
75
+ let value = try runtime?.eval("ExpoModules.PropertyTest.writable")
76
+ expect(value?.getInt()) == 777
77
+ }
78
+
79
+ it("is enumerable") {
80
+ let keys = try runtime?.eval("Object.keys(ExpoModules.PropertyTest)").getArray().map { $0.getString() } ?? []
81
+ expect(keys).to(contain("readOnly", "writable", "withCaller", "undefined"))
82
+ }
83
+
84
+ it("is called with the caller") {
85
+ let value = try runtime?.eval("ExpoModules.PropertyTest.withCaller")
86
+ expect(value?.getString()) == "foo"
87
+ }
88
+
89
+ it("returns undefined when getter is not specified") {
90
+ let value = try runtime?.eval("ExpoModules.PropertyTest.undefined")
91
+ expect(value?.isUndefined()) == true
92
+ }
93
+ }
94
+ }
95
+ }
@@ -0,0 +1,109 @@
1
+ // Copyright 2022-present 650 Industries. All rights reserved.
2
+
3
+ import ExpoModulesTestCore
4
+
5
+ @testable import ExpoModulesCore
6
+
7
+ final class SharedObjectRegistrySpec: ExpoSpec {
8
+ override func spec() {
9
+ let appContext = AppContext.create()
10
+ let runtime = appContext.runtime
11
+
12
+ describe("pullNextId") {
13
+ it("returns nextId") {
14
+ let id = SharedObjectRegistry.nextId
15
+ expect(SharedObjectRegistry.pullNextId()) == id
16
+ }
17
+ it("increments nextId") {
18
+ let id = SharedObjectRegistry.nextId
19
+ SharedObjectRegistry.pullNextId()
20
+ expect(SharedObjectRegistry.nextId) == id + 1
21
+ }
22
+ it("is not increasing size") {
23
+ let size = SharedObjectRegistry.size
24
+ SharedObjectRegistry.pullNextId()
25
+ expect(SharedObjectRegistry.size) == size
26
+ }
27
+ }
28
+
29
+ describe("add") {
30
+ it("adds using nextId") {
31
+ let nextId = SharedObjectRegistry.nextId
32
+ let id = SharedObjectRegistry.add(native: TestSharedObject(), javaScript: runtime!.createObject())
33
+ expect(nextId) == id
34
+ }
35
+ it("is increasing size") {
36
+ let size = SharedObjectRegistry.size
37
+ SharedObjectRegistry.add(native: TestSharedObject(), javaScript: runtime!.createObject())
38
+ expect(SharedObjectRegistry.size) == size + 1
39
+ }
40
+ it("assigns id on native object") {
41
+ let nativeObject = TestSharedObject()
42
+ let id = SharedObjectRegistry.add(native: nativeObject, javaScript: runtime!.createObject())
43
+ expect(nativeObject.sharedObjectId) == id
44
+ }
45
+ it("assigns id on JS object") {
46
+ let jsObject = runtime!.createObject()
47
+ let id = SharedObjectRegistry.add(native: TestSharedObject(), javaScript: jsObject)
48
+ expect(jsObject.hasProperty(sharedObjectIdPropertyName)) == true
49
+ expect(try! jsObject.getProperty(sharedObjectIdPropertyName).asInt()) == id
50
+ }
51
+ it("saves objects pair") {
52
+ let nativeObject = TestSharedObject()
53
+ let jsObject = runtime!.createObject()
54
+ let id = SharedObjectRegistry.add(native: nativeObject, javaScript: jsObject)
55
+ let pair = SharedObjectRegistry.get(id)
56
+ expect(pair?.native) === nativeObject
57
+ expect(pair?.javaScript.lock()) == jsObject
58
+ }
59
+ }
60
+
61
+ describe("delete") {
62
+ it("deletes objects pair") {
63
+ let id = SharedObjectRegistry.add(native: TestSharedObject(), javaScript: runtime!.createObject())
64
+ SharedObjectRegistry.delete(id)
65
+ expect(SharedObjectRegistry.get(id)).to(beNil())
66
+ }
67
+ it("resets id on native object") {
68
+ let nativeObject = TestSharedObject()
69
+ let id = SharedObjectRegistry.add(native: nativeObject, javaScript: runtime!.createObject())
70
+ SharedObjectRegistry.delete(id)
71
+ expect(nativeObject.sharedObjectId) == 0
72
+ }
73
+ it("resets id on JS object") {
74
+ let jsObject = runtime!.createObject()
75
+ let id = SharedObjectRegistry.add(native: TestSharedObject(), javaScript: jsObject)
76
+ SharedObjectRegistry.delete(id)
77
+ expect(try! jsObject.getProperty(sharedObjectIdPropertyName).asInt()) == 0
78
+ }
79
+ }
80
+
81
+ describe("toNativeObject") {
82
+ it("returns native object") {
83
+ let nativeObject = TestSharedObject()
84
+ let jsObject = runtime!.createObject()
85
+ SharedObjectRegistry.add(native: nativeObject, javaScript: jsObject)
86
+ expect(SharedObjectRegistry.toNativeObject(jsObject)) === nativeObject
87
+ }
88
+ it("returns nil") {
89
+ let jsObject = runtime!.createObject()
90
+ expect(SharedObjectRegistry.toNativeObject(jsObject)).to(beNil())
91
+ }
92
+ }
93
+
94
+ describe("toJavaScriptObject") {
95
+ it("returns JS object") {
96
+ let nativeObject = TestSharedObject()
97
+ let jsObject = runtime!.createObject()
98
+ SharedObjectRegistry.add(native: nativeObject, javaScript: jsObject)
99
+ expect(SharedObjectRegistry.toJavaScriptObject(nativeObject)) == jsObject
100
+ }
101
+ it("returns nil") {
102
+ let nativeObject = TestSharedObject()
103
+ expect(SharedObjectRegistry.toJavaScriptObject(nativeObject)).to(beNil())
104
+ }
105
+ }
106
+ }
107
+ }
108
+
109
+ fileprivate final class TestSharedObject: SharedObject {}