expo-modules-core 1.2.7 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/CHANGELOG.md +28 -5
  2. package/ExpoModulesCore.podspec +1 -0
  3. package/README.md +1 -1
  4. package/android/ExpoModulesCorePlugin.gradle +16 -0
  5. package/android/build.gradle +3 -2
  6. package/android/src/main/cpp/Exceptions.cpp +8 -0
  7. package/android/src/main/cpp/Exceptions.h +11 -0
  8. package/android/src/main/cpp/ExpoModulesHostObject.cpp +22 -5
  9. package/android/src/main/cpp/ExpoModulesHostObject.h +5 -0
  10. package/android/src/main/cpp/JNIInjector.cpp +2 -0
  11. package/android/src/main/cpp/JSIInteropModuleRegistry.cpp +25 -1
  12. package/android/src/main/cpp/JSIInteropModuleRegistry.h +14 -0
  13. package/android/src/main/cpp/JSIObjectWrapper.h +15 -4
  14. package/android/src/main/cpp/JSITypeConverter.h +3 -2
  15. package/android/src/main/cpp/JavaReferencesCache.cpp +2 -0
  16. package/android/src/main/cpp/JavaScriptFunction.cpp +56 -0
  17. package/android/src/main/cpp/JavaScriptFunction.h +54 -0
  18. package/android/src/main/cpp/JavaScriptModuleObject.cpp +225 -105
  19. package/android/src/main/cpp/JavaScriptModuleObject.h +67 -34
  20. package/android/src/main/cpp/JavaScriptObject.cpp +55 -1
  21. package/android/src/main/cpp/JavaScriptObject.h +17 -13
  22. package/android/src/main/cpp/JavaScriptRuntime.cpp +12 -3
  23. package/android/src/main/cpp/JavaScriptRuntime.h +9 -1
  24. package/android/src/main/cpp/JavaScriptValue.cpp +9 -0
  25. package/android/src/main/cpp/JavaScriptValue.h +4 -0
  26. package/android/src/main/cpp/MethodMetadata.cpp +66 -87
  27. package/android/src/main/cpp/MethodMetadata.h +18 -16
  28. package/android/src/main/cpp/ObjectDeallocator.h +25 -0
  29. package/android/src/main/cpp/WeakRuntimeHolder.cpp +7 -0
  30. package/android/src/main/cpp/WeakRuntimeHolder.h +4 -0
  31. package/android/src/main/cpp/types/CppType.h +4 -1
  32. package/android/src/main/cpp/types/FrontendConverter.cpp +58 -0
  33. package/android/src/main/cpp/types/FrontendConverter.h +45 -0
  34. package/android/src/main/cpp/types/FrontendConverterProvider.cpp +3 -0
  35. package/android/src/main/cpp/types/JNIToJSIConverter.cpp +88 -0
  36. package/android/src/main/cpp/types/JNIToJSIConverter.h +22 -0
  37. package/android/src/main/java/com/facebook/react/uimanager/ReactStylesDiffMapHelper.kt +10 -0
  38. package/android/src/main/java/expo/modules/kotlin/AppContext.kt +8 -25
  39. package/android/src/main/java/expo/modules/kotlin/FilteredIterator.kt +37 -0
  40. package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +1 -1
  41. package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +30 -23
  42. package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +0 -3
  43. package/android/src/main/java/expo/modules/kotlin/Utils.kt +21 -0
  44. package/android/src/main/java/expo/modules/kotlin/activityresult/AppContextActivityResultCaller.kt +21 -1
  45. package/android/src/main/java/expo/modules/kotlin/classcomponent/ClassComponentBuilder.kt +112 -0
  46. package/android/src/main/java/expo/modules/kotlin/classcomponent/ClassDefinitionData.kt +10 -0
  47. package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +21 -0
  48. package/android/src/main/java/expo/modules/kotlin/exception/CommonExceptions.kt +15 -0
  49. package/android/src/main/java/expo/modules/kotlin/functions/AnyFunction.kt +17 -3
  50. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +38 -8
  51. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionComponent.kt +3 -2
  52. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromiseComponent.kt +3 -2
  53. package/android/src/main/java/expo/modules/kotlin/functions/SuspendFunctionComponent.kt +1 -0
  54. package/android/src/main/java/expo/modules/kotlin/functions/SyncFunctionComponent.kt +18 -11
  55. package/android/src/main/java/expo/modules/kotlin/jni/CppType.kt +4 -1
  56. package/android/src/main/java/expo/modules/kotlin/jni/JNIDeallocator.kt +73 -0
  57. package/android/src/main/java/expo/modules/kotlin/jni/JSIInteropModuleRegistry.kt +28 -2
  58. package/android/src/main/java/expo/modules/kotlin/jni/JavaCallback.kt +8 -1
  59. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptFunction.kt +48 -0
  60. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptModuleObject.kt +40 -3
  61. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptObject.kt +23 -3
  62. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptValue.kt +26 -1
  63. package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +0 -11
  64. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +26 -16
  65. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +3 -1
  66. package/android/src/main/java/expo/modules/kotlin/sharedobjects/SharedObject.kt +12 -0
  67. package/android/src/main/java/expo/modules/kotlin/sharedobjects/SharedObjectRegistry.kt +62 -0
  68. package/android/src/main/java/expo/modules/kotlin/sharedobjects/SharedObjectTypeConverter.kt +27 -0
  69. package/android/src/main/java/expo/modules/kotlin/types/AnyType.kt +2 -1
  70. package/android/src/main/java/expo/modules/kotlin/types/EitherTypeConverter.kt +7 -6
  71. package/android/src/main/java/expo/modules/kotlin/types/JavaScriptFunctionTypeConverter.kt +22 -0
  72. package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +30 -24
  73. package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +45 -1
  74. package/android/src/main/java/expo/modules/kotlin/types/TypedArrayTypeConverter.kt +3 -2
  75. package/android/src/main/java/expo/modules/kotlin/views/AnyViewProp.kt +3 -1
  76. package/android/src/main/java/expo/modules/kotlin/views/ConcreteViewProp.kt +3 -3
  77. package/android/src/main/java/expo/modules/kotlin/views/FilteredReadableMap.kt +53 -0
  78. package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +25 -5
  79. package/android/src/main/java/expo/modules/kotlin/views/SimpleViewManagerWrapper.kt +25 -5
  80. package/android/src/main/java/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +161 -10
  81. package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinitionBuilder.kt +0 -67
  82. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +6 -7
  83. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +40 -3
  84. package/android/src/main/java/expo/modules/kotlin/views/ViewTypeConverter.kt +44 -0
  85. package/android-annotation/build.gradle +45 -0
  86. package/android-annotation/src/main/java/expo/modules/annotation/Config.kt +7 -0
  87. package/android-annotation/src/main/java/expo/modules/annotation/ConverterBinder.kt +7 -0
  88. package/android-annotation-processor/build.gradle +51 -0
  89. package/android-annotation-processor/src/main/java/expo/modules/annotationprocessor/ExpoSymbolProcessor.kt +175 -0
  90. package/android-annotation-processor/src/main/java/expo/modules/annotationprocessor/ExpoSymbolProcessorProvider.kt +10 -0
  91. package/android-annotation-processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider +1 -0
  92. package/build/NativeViewManagerAdapter.native.d.ts.map +1 -1
  93. package/build/NativeViewManagerAdapter.native.js +36 -23
  94. package/build/NativeViewManagerAdapter.native.js.map +1 -1
  95. package/build/requireNativeModule.js +2 -2
  96. package/build/requireNativeModule.js.map +1 -1
  97. package/common/cpp/fabric/ExpoViewProps.cpp +18 -3
  98. package/common/cpp/fabric/ExpoViewProps.h +4 -1
  99. package/ios/Fabric/ExpoFabricView.swift +10 -10
  100. package/ios/Fabric/ExpoFabricViewObjC.h +2 -0
  101. package/ios/Fabric/ExpoFabricViewObjC.mm +17 -2
  102. package/ios/JSI/EXJSIInstaller.mm +1 -1
  103. package/ios/JSI/EXJSIUtils.h +5 -0
  104. package/ios/JSI/EXJSIUtils.mm +17 -0
  105. package/ios/JSI/EXJavaScriptRuntime.h +5 -0
  106. package/ios/JSI/EXJavaScriptRuntime.mm +6 -0
  107. package/ios/JSI/EXJavaScriptValue.h +2 -0
  108. package/ios/JSI/EXJavaScriptValue.mm +8 -0
  109. package/ios/JSI/EXJavaScriptWeakObject.mm +29 -8
  110. package/ios/JSI/EXRawJavaScriptFunction.h +24 -0
  111. package/ios/JSI/EXRawJavaScriptFunction.mm +52 -0
  112. package/ios/JSI/ExpoModulesHostObject.mm +1 -1
  113. package/ios/JSI/JavaScriptValue.swift +28 -1
  114. package/ios/ModuleRegistry/EXModuleRegistry.h +0 -4
  115. package/ios/ModuleRegistry/EXModuleRegistry.m +0 -23
  116. package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +0 -16
  117. package/ios/ModuleRegistryProvider/EXModuleRegistryProvider.m +0 -6
  118. package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +1 -31
  119. package/ios/Swift/AppContext.swift +46 -6
  120. package/ios/Swift/Arguments/Convertible.swift +3 -3
  121. package/ios/Swift/Arguments/Convertibles.swift +5 -5
  122. package/ios/Swift/Classes/ClassComponent.swift +18 -12
  123. package/ios/Swift/Classes/ClassRegistry.swift +31 -0
  124. package/ios/Swift/Conversions.swift +19 -3
  125. package/ios/Swift/Convertibles/Convertibles+Color.swift +3 -3
  126. package/ios/Swift/Convertibles/Either.swift +6 -4
  127. package/ios/Swift/DynamicTypes/AnyDynamicType.swift +18 -2
  128. package/ios/Swift/DynamicTypes/DynamicArrayType.swift +3 -3
  129. package/ios/Swift/DynamicTypes/DynamicConvertibleType.swift +2 -2
  130. package/ios/Swift/DynamicTypes/DynamicEnumType.swift +1 -1
  131. package/ios/Swift/DynamicTypes/DynamicJavaScriptType.swift +27 -0
  132. package/ios/Swift/DynamicTypes/DynamicOptionalType.swift +9 -2
  133. package/ios/Swift/DynamicTypes/DynamicRawType.swift +1 -1
  134. package/ios/Swift/DynamicTypes/DynamicSharedObjectType.swift +16 -2
  135. package/ios/Swift/DynamicTypes/DynamicType.swift +6 -0
  136. package/ios/Swift/DynamicTypes/DynamicTypedArrayType.swift +15 -4
  137. package/ios/Swift/DynamicTypes/DynamicViewType.swift +68 -0
  138. package/ios/Swift/ExpoBridgeModule.swift +1 -1
  139. package/ios/Swift/Functions/AnyFunction.swift +5 -4
  140. package/ios/Swift/Functions/AsyncFunctionComponent.swift +22 -19
  141. package/ios/Swift/Functions/ConcurrentFunctionDefinition.swift +29 -13
  142. package/ios/Swift/Functions/SyncFunctionComponent.swift +26 -15
  143. package/ios/Swift/JavaScriptFunction.swift +68 -0
  144. package/ios/Swift/JavaScriptUtils.swift +57 -18
  145. package/ios/Swift/ModuleHolder.swift +22 -10
  146. package/ios/Swift/Modules/ModuleDefinition.swift +8 -2
  147. package/ios/Swift/Objects/JavaScriptObjectBuilder.swift +8 -8
  148. package/ios/Swift/Objects/ObjectDefinition.swift +17 -15
  149. package/ios/Swift/Objects/PropertyComponent.swift +23 -17
  150. package/ios/Swift/Records/AnyField.swift +1 -1
  151. package/ios/Swift/Records/Field.swift +2 -2
  152. package/ios/Swift/Records/Record.swift +5 -5
  153. package/ios/Swift/SharedObjects/SharedObjectRegistry.swift +4 -0
  154. package/ios/Swift/Views/AnyViewProp.swift +1 -1
  155. package/ios/Swift/Views/ComponentData.swift +37 -2
  156. package/ios/Swift/Views/ConcreteViewProp.swift +2 -2
  157. package/ios/Swift/Views/ViewDefinition.swift +39 -0
  158. package/ios/Swift/Views/ViewModuleWrapper.swift +0 -29
  159. package/ios/Tests/ClassComponentSpec.swift +39 -27
  160. package/ios/Tests/ConvertiblesSpec.swift +75 -49
  161. package/ios/Tests/DynamicTypeSpec.swift +29 -27
  162. package/ios/Tests/EitherSpec.swift +9 -7
  163. package/ios/Tests/ExpoModulesSpec.swift +13 -13
  164. package/ios/Tests/FunctionSpec.swift +38 -22
  165. package/ios/Tests/JavaScriptRuntimeSpec.swift +4 -0
  166. package/ios/Tests/PropertyComponentSpec.swift +33 -30
  167. package/ios/Tests/RecordSpec.swift +7 -5
  168. package/ios/Tests/SharedObjectRegistrySpec.swift +12 -12
  169. package/ios/Tests/TypedArraysSpec.swift +1 -1
  170. package/ios/Tests/ViewDefinitionSpec.swift +4 -2
  171. package/package.json +2 -2
  172. package/src/NativeViewManagerAdapter.native.tsx +33 -29
  173. package/src/requireNativeModule.ts +2 -2
  174. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +0 -132
  175. package/ios/EXViewManager.h +0 -21
  176. package/ios/EXViewManager.m +0 -128
  177. package/ios/ModuleRegistryAdapter/EXViewManagerAdapterClassesRegistry.h +0 -17
  178. package/ios/ModuleRegistryAdapter/EXViewManagerAdapterClassesRegistry.m +0 -67
  179. package/ios/ViewManagerAdapter/EXViewManagerAdapter.h +0 -17
  180. package/ios/ViewManagerAdapter/EXViewManagerAdapter.m +0 -45
@@ -7,6 +7,8 @@ import ExpoModulesTestCore
7
7
 
8
8
  final class DynamicTypeSpec: ExpoSpec {
9
9
  override func spec() {
10
+ let appContext = AppContext.create()
11
+
10
12
  // MARK: - DynamicRawType
11
13
 
12
14
  describe("DynamicRawType") {
@@ -17,20 +19,20 @@ final class DynamicTypeSpec: ExpoSpec {
17
19
  }
18
20
  describe("casts") {
19
21
  it("succeeds") {
20
- expect(try (~String.self).cast("expo") as? String) == "expo"
21
- expect(try (~Double.self).cast(2.1) as? Double) == 2.1
22
- expect(try (~Bool.self).cast(false) as? Bool) == false
22
+ expect(try (~String.self).cast("expo", appContext: appContext) as? String) == "expo"
23
+ expect(try (~Double.self).cast(2.1, appContext: appContext) as? Double) == 2.1
24
+ expect(try (~Bool.self).cast(false, appContext: appContext) as? Bool) == false
23
25
  }
24
26
  it("throws NullCastException") {
25
27
  let value: Double? = nil
26
28
  let anyValue = value as Any
27
29
 
28
- expect { try (~Double.self).cast(anyValue) }.to(
30
+ expect { try (~Double.self).cast(anyValue, appContext: appContext) }.to(
29
31
  throwError(errorType: Conversions.NullCastException<Double>.self)
30
32
  )
31
33
  }
32
34
  it("throws CastingException") {
33
- expect { try (~String.self).cast(true) }.to(
35
+ expect { try (~String.self).cast(true, appContext: appContext) }.to(
34
36
  throwError(errorType: Conversions.CastingException<String>.self)
35
37
  )
36
38
  }
@@ -72,13 +74,13 @@ final class DynamicTypeSpec: ExpoSpec {
72
74
  }
73
75
  describe("casts") {
74
76
  it("succeeds") {
75
- expect(try (~[Double].self).cast([1.2, 3.4]) as? [Double]) == [1.2, 3.4]
76
- expect(try (~[[String]].self).cast([["hello", "expo"]]) as? [[String]]) == [["hello", "expo"]]
77
+ expect(try (~[Double].self).cast([1.2, 3.4], appContext: appContext) as? [Double]) == [1.2, 3.4]
78
+ expect(try (~[[String]].self).cast([["hello", "expo"]], appContext: appContext) as? [[String]]) == [["hello", "expo"]]
77
79
  }
78
80
  it("casts arrays") {
79
81
  let value = 9.9
80
82
  let anyValue = [value] as [Any]
81
- let result = try (~[Double].self).cast(anyValue) as! [Any]
83
+ let result = try (~[Double].self).cast(anyValue, appContext: appContext) as! [Any]
82
84
 
83
85
  expect(result).to(beAKindOf([Double].self))
84
86
  expect(result as? [Double]) == [value]
@@ -86,11 +88,11 @@ final class DynamicTypeSpec: ExpoSpec {
86
88
  it("arrayizes single element") {
87
89
  // The dynamic array type can arrayize the single element
88
90
  // if only the array element's dynamic type can cast it.
89
- expect(try (~[Int].self).cast(50) as? [Int]) == [50]
90
- expect(try (~[String].self).cast("not an array") as? [String]) == ["not an array"]
91
+ expect(try (~[Int].self).cast(50, appContext: appContext) as? [Int]) == [50]
92
+ expect(try (~[String].self).cast("not an array", appContext: appContext) as? [String]) == ["not an array"]
91
93
  }
92
94
  it("throws CastingException") {
93
- expect { try (~[String].self).cast(84) }.to(
95
+ expect { try (~[String].self).cast(84, appContext: appContext) }.to(
94
96
  throwError(errorType: Conversions.CastingException<String>.self)
95
97
  )
96
98
  }
@@ -131,12 +133,12 @@ final class DynamicTypeSpec: ExpoSpec {
131
133
  }
132
134
  describe("casts") {
133
135
  it("succeeds") {
134
- expect(try (~CGPoint.self).cast([2.1, 3.7]) as? CGPoint) == CGPoint(x: 2.1, y: 3.7)
135
- expect(try (~CGVector.self).cast(["dx": 0.8, "dy": 4.1]) as? CGVector) == CGVector(dx: 0.8, dy: 4.1)
136
- expect(try (~URL.self).cast("/test/path") as? URL) == URL(fileURLWithPath: "/test/path")
136
+ expect(try (~CGPoint.self).cast([2.1, 3.7], appContext: appContext) as? CGPoint) == CGPoint(x: 2.1, y: 3.7)
137
+ expect(try (~CGVector.self).cast(["dx": 0.8, "dy": 4.1], appContext: appContext) as? CGVector) == CGVector(dx: 0.8, dy: 4.1)
138
+ expect(try (~URL.self).cast("/test/path", appContext: appContext) as? URL) == URL(fileURLWithPath: "/test/path")
137
139
  }
138
140
  it("throws ConvertingException") {
139
- expect { try (~CGRect.self).cast("not a rect") as? CGRect }.to(
141
+ expect { try (~CGRect.self).cast("not a rect", appContext: appContext) as? CGRect }.to(
140
142
  throwError(errorType: Conversions.ConvertingException<CGRect>.self)
141
143
  )
142
144
  }
@@ -185,16 +187,16 @@ final class DynamicTypeSpec: ExpoSpec {
185
187
  }
186
188
  describe("casts") {
187
189
  it("succeeds") {
188
- expect(try (~StringTestEnum.self).cast("expo") as? StringTestEnum) == .expo
189
- expect(try (~IntTestEnum.self).cast(1) as? IntTestEnum) == .positive
190
+ expect(try (~StringTestEnum.self).cast("expo", appContext: appContext) as? StringTestEnum) == .expo
191
+ expect(try (~IntTestEnum.self).cast(1, appContext: appContext) as? IntTestEnum) == .positive
190
192
  }
191
193
  it("throws EnumNoSuchValueException") {
192
- expect { try (~StringTestEnum.self).cast("react native") as? StringTestEnum }.to(
194
+ expect { try (~StringTestEnum.self).cast("react native", appContext: appContext) as? StringTestEnum }.to(
193
195
  throwError(errorType: EnumNoSuchValueException.self)
194
196
  )
195
197
  }
196
198
  it("throws EnumCastingException") {
197
- expect { try (~IntTestEnum.self).cast(true) as? StringTestEnum }.to(
199
+ expect { try (~IntTestEnum.self).cast(true, appContext: appContext) as? StringTestEnum }.to(
198
200
  throwError(errorType: EnumCastingException.self)
199
201
  )
200
202
  }
@@ -234,12 +236,12 @@ final class DynamicTypeSpec: ExpoSpec {
234
236
  }
235
237
  describe("casts") {
236
238
  it("succeeds") {
237
- expect(try (~String?.self).cast("expo") as? String) == "expo"
238
- expect(try (~Bool?.self).cast(false) as? Bool) == false
239
+ expect(try (~String?.self).cast("expo", appContext: appContext) as? String) == "expo"
240
+ expect(try (~Bool?.self).cast(false, appContext: appContext) as? Bool) == false
239
241
  }
240
242
  it("succeeds with nil") {
241
243
  let value: Double? = nil
242
- let result = try (~Double?.self).cast(value as Any)
244
+ let result = try (~Double?.self).cast(value as Any, appContext: appContext)
243
245
 
244
246
  expect(result).to(beAKindOf(Double?.self))
245
247
 
@@ -249,12 +251,12 @@ final class DynamicTypeSpec: ExpoSpec {
249
251
  }
250
252
  it("succeeds with NSNull") {
251
253
  let value = NSNull()
252
- let result = try (~Double?.self).cast(value as Any)
254
+ let result = try (~Double?.self).cast(value as Any, appContext: appContext)
253
255
  expect(result).to(beAKindOf(Double?.self))
254
256
  expect(Optional.isNil(result)) == true
255
257
  }
256
258
  it("throws CastingException") {
257
- expect { try (~Double?.self).cast("a string") as? Double }.to(
259
+ expect { try (~Double?.self).cast("a string", appContext: appContext) as? Double }.to(
258
260
  throwError(errorType: Conversions.CastingException<Double>.self)
259
261
  )
260
262
  }
@@ -296,16 +298,16 @@ final class DynamicTypeSpec: ExpoSpec {
296
298
  it("succeeds") {
297
299
  let appContext = AppContext.create()
298
300
  let nativeObject = TestSharedObject()
299
- let jsObjectValue = try appContext.runtime!.eval("({})")
301
+ let jsObjectValue = try appContext.runtime.eval("({})")
300
302
 
301
303
  SharedObjectRegistry.add(native: nativeObject, javaScript: try jsObjectValue.asObject())
302
304
 
303
305
  // `DynamicSharedObjectType` only supports casting
304
306
  // from `JavaScriptValue`, but not from `JavaScriptObject`.
305
- expect(try (~TestSharedObject.self).cast(jsObjectValue) as? TestSharedObject) === nativeObject
307
+ expect(try (~TestSharedObject.self).cast(jsValue: jsObjectValue, appContext: appContext) as? TestSharedObject) === nativeObject
306
308
  }
307
309
  it("throws NativeSharedObjectNotFoundException") {
308
- expect { try (~TestSharedObject.self).cast("a string") as? TestSharedObject }.to(
310
+ expect { try (~TestSharedObject.self).cast("a string", appContext: appContext) as? TestSharedObject }.to(
309
311
  throwError(errorType: NativeSharedObjectNotFoundException.self)
310
312
  )
311
313
  }
@@ -6,6 +6,8 @@ import ExpoModulesTestCore
6
6
 
7
7
  final class EitherSpec: ExpoSpec {
8
8
  override func spec() {
9
+ let appContext = AppContext.create()
10
+
9
11
  describe("Either") {
10
12
  it("is the first type") {
11
13
  let either = Either<String, Int>("string")
@@ -33,16 +35,16 @@ final class EitherSpec: ExpoSpec {
33
35
  expect(value).notTo(beNil())
34
36
  }
35
37
  it("converts as convertible") {
36
- let either = try Either<String, Int>.convert(from: 123)
38
+ let either = try Either<String, Int>.convert(from: 123, appContext: appContext)
37
39
  expect(either.is(String.self)) == false
38
40
  expect(either.is(Int.self)) == true
39
41
  }
40
42
  it("throws when converting from neither type") {
41
- expect({ try Either<String, Int>.convert(from: true) }).to(throwError(errorType: NeitherTypeException.self))
43
+ expect({ try Either<String, Int>.convert(from: true, appContext: appContext) }).to(throwError(errorType: NeitherTypeException.self))
42
44
  }
43
45
 
44
46
  it("supports arrays") {
45
- let either = try Either<String, [String]>.convert(from: ["foo"])
47
+ let either = try Either<String, [String]>.convert(from: ["foo"], appContext: appContext)
46
48
  let value: [String]? = either.get()
47
49
 
48
50
  expect(either.is([String].self)) == true
@@ -50,7 +52,7 @@ final class EitherSpec: ExpoSpec {
50
52
  }
51
53
 
52
54
  it("supports convertibles (UIColor)") {
53
- let either = try Either<Int, UIColor>.convert(from: "blue")
55
+ let either = try Either<Int, UIColor>.convert(from: "blue", appContext: appContext)
54
56
  let color: UIColor? = either.get()
55
57
 
56
58
  expect(either.is(UIColor.self)) == true
@@ -62,7 +64,7 @@ final class EitherSpec: ExpoSpec {
62
64
  @Field
63
65
  var foo: String
64
66
  }
65
- let either = try Either<String, TestRecord>.convert(from: ["foo": "bar"])
67
+ let either = try Either<String, TestRecord>.convert(from: ["foo": "bar"], appContext: appContext)
66
68
  let record: TestRecord? = either.get()
67
69
 
68
70
  expect(either.is(TestRecord.self)) == true
@@ -88,7 +90,7 @@ final class EitherSpec: ExpoSpec {
88
90
  expect(value).notTo(beNil())
89
91
  }
90
92
  it("throws when converting from neither type") {
91
- expect({ try EitherOfThree<String, Int, Double>.convert(from: false) }).to(throwError(errorType: NeitherTypeException.self))
93
+ expect({ try EitherOfThree<String, Int, Double>.convert(from: false, appContext: appContext) }).to(throwError(errorType: NeitherTypeException.self))
92
94
  }
93
95
  }
94
96
  describe("EitherOfFour") {
@@ -112,7 +114,7 @@ final class EitherSpec: ExpoSpec {
112
114
  expect(value).notTo(beNil())
113
115
  }
114
116
  it("throws when converting from neither type") {
115
- expect({ try EitherOfFour<String, Int, Double, Bool>.convert(from: [1, 2]) }).to(throwError(errorType: NeitherTypeException.self))
117
+ expect({ try EitherOfFour<String, Int, Double, Bool>.convert(from: [1, 2], appContext: appContext) }).to(throwError(errorType: NeitherTypeException.self))
116
118
  }
117
119
  }
118
120
  }
@@ -7,7 +7,7 @@ import ExpoModulesTestCore
7
7
  class ExpoModulesSpec: ExpoSpec {
8
8
  override func spec() {
9
9
  let appContext = AppContext.create()
10
- let runtime = appContext.runtime
10
+ let runtime = try! appContext.runtime
11
11
  let testModuleName = "TestModule"
12
12
  let testFunctionName = "testFunction"
13
13
  let throwingFunctionName = "throwingFunction"
@@ -33,23 +33,23 @@ class ExpoModulesSpec: ExpoSpec {
33
33
 
34
34
  describe("host object") {
35
35
  it("is defined") {
36
- expect(try! runtime?.eval("'ExpoModules' in this").asBool()) === true
36
+ expect(try! runtime.eval("'ExpoModules' in this").asBool()) === true
37
37
  }
38
38
 
39
39
  it("has native module defined") {
40
- expect(try! runtime?.eval("'\(testModuleName)' in ExpoModules").asBool()) === true
40
+ expect(try! runtime.eval("'\(testModuleName)' in ExpoModules").asBool()) === true
41
41
  }
42
42
 
43
43
  it("can access native module") {
44
- let nativeModule = try! runtime?.eval("expo.modules.\(testModuleName)")
45
- expect(nativeModule?.isUndefined()) == false
46
- expect(nativeModule?.isObject()) == true
47
- expect(nativeModule?.getRaw()).notTo(beNil())
44
+ let nativeModule = try runtime.eval("expo.modules.\(testModuleName)")
45
+ expect(nativeModule.isUndefined()) == false
46
+ expect(nativeModule.isObject()) == true
47
+ expect(nativeModule.getRaw()).notTo(beNil())
48
48
  }
49
49
 
50
50
  it("has keys for registered modules") {
51
51
  let registeredModuleNames = appContext.moduleRegistry.getModuleNames()
52
- let keys = try! runtime?.eval("Object.keys(ExpoModules)").asArray().compactMap {
52
+ let keys = try runtime.eval("Object.keys(ExpoModules)").asArray().compactMap {
53
53
  return try! $0?.asString()
54
54
  }
55
55
  expect(keys).to(contain(registeredModuleNames))
@@ -58,7 +58,7 @@ class ExpoModulesSpec: ExpoSpec {
58
58
 
59
59
  describe("module") {
60
60
  it("exposes constants") {
61
- let dict = try! runtime!.eval("expo.modules.TestModule").asDict()
61
+ let dict = try runtime.eval("expo.modules.TestModule").asDict()
62
62
 
63
63
  dict.forEach { (key: String, value: Any) in
64
64
  expect(value) === dict[key]!
@@ -66,17 +66,17 @@ class ExpoModulesSpec: ExpoSpec {
66
66
  }
67
67
 
68
68
  it("has function") {
69
- expect(try! runtime?.eval("typeof expo.modules.TestModule.\(testFunctionName)").asString()) == "function"
70
- expect(try! runtime?.eval("expo.modules.TestModule.\(testFunctionName)").isFunction()) == true
69
+ expect(try runtime.eval("typeof expo.modules.TestModule.\(testFunctionName)").asString()) == "function"
70
+ expect(try runtime.eval("expo.modules.TestModule.\(testFunctionName)").isFunction()) == true
71
71
  }
72
72
 
73
73
  it("calls function") {
74
- expect(try! runtime?.eval("expo.modules.TestModule.\(testFunctionName)()").asDouble()) == Double.pi
74
+ expect(try runtime.eval("expo.modules.TestModule.\(testFunctionName)()").asDouble()) == Double.pi
75
75
  }
76
76
 
77
77
  it("throws from sync function") {
78
78
  // Invoke the throwing function and return the error (eval shouldn't rethrow here)
79
- let error = try! runtime!.eval("try { expo.modules.TestModule.\(throwingFunctionName)() } catch (error) { error }").asObject()
79
+ let error = try runtime.eval("try { expo.modules.TestModule.\(throwingFunctionName)() } catch (error) { error }").asObject()
80
80
 
81
81
  // We just check if it contains the description — they won't be equal for the following reasons:
82
82
  // - the `exceptionToThrow` is just the root cause, in fact it returns `FunctionCallException`
@@ -128,11 +128,15 @@ class FunctionSpec: ExpoSpec {
128
128
 
129
129
  it("returns the record back (sync)") {
130
130
  let result = try Function(functionName) { (record: TestRecord) in record }
131
- .call(by: nil, withArguments: [dict]) as? TestRecord.Dict
131
+ .call(by: nil, withArguments: [dict], appContext: appContext) as? TestRecord
132
+
133
+ guard let result = Conversions.convertFunctionResult(result, appContext: appContext) as? TestRecord.Dict else {
134
+ return fail()
135
+ }
132
136
 
133
137
  expect(result).notTo(beNil())
134
- expect(result?["property"] as? String).to(equal(dict["property"]))
135
- expect(result?["propertyWithCustomKey"] as? String).to(equal(dict["propertyWithCustomKey"]))
138
+ expect(result["property"] as? String).to(equal(dict["property"]))
139
+ expect(result["propertyWithCustomKey"] as? String).to(equal(dict["propertyWithCustomKey"]))
136
140
  }
137
141
 
138
142
  it("returns the record back (async)") {
@@ -186,11 +190,11 @@ class FunctionSpec: ExpoSpec {
186
190
  return returnedValue
187
191
  }
188
192
 
189
- expect({ try fn.call(by: nil, withArguments: ["test"]) })
193
+ expect({ try fn.call(by: nil, withArguments: ["test"], appContext: appContext) })
190
194
  .notTo(throwError())
191
195
  .to(be(returnedValue))
192
196
 
193
- expect({ try fn.call(by: nil, withArguments: ["test", 3]) })
197
+ expect({ try fn.call(by: nil, withArguments: ["test", 3], appContext: appContext) })
194
198
  .notTo(throwError())
195
199
  .to(be(returnedValue))
196
200
  }
@@ -200,7 +204,7 @@ class FunctionSpec: ExpoSpec {
200
204
  return "something"
201
205
  }
202
206
 
203
- expect({ try fn.call(by: nil, withArguments: []) })
207
+ expect({ try fn.call(by: nil, withArguments: [], appContext: appContext) })
204
208
  .to(throwError(errorType: FunctionCallException.self) { error in
205
209
  expect(error.rootCause).to(beAKindOf(InvalidArgsNumberException.self))
206
210
  let exception = error.rootCause as! InvalidArgsNumberException
@@ -222,7 +226,8 @@ class FunctionSpec: ExpoSpec {
222
226
  switch result {
223
227
  case .failure(let error):
224
228
  expect(error).notTo(beNil())
225
- expect(error).to(beAKindOf(ArgumentCastException.self))
229
+ expect(error).to(beAKindOf(FunctionCallException.self))
230
+ expect(error.isCausedBy(ArgumentCastException.self)) == true
226
231
  expect(error.isCausedBy(Conversions.CastingException<String>.self)) == true
227
232
  case .success(_):
228
233
  fail()
@@ -232,20 +237,20 @@ class FunctionSpec: ExpoSpec {
232
237
  }
233
238
  }
234
239
  }
235
-
240
+
236
241
  context("JavaScript") {
237
- let runtime = appContext.runtime
238
-
242
+ let runtime = try! appContext.runtime
243
+
239
244
  beforeSuite {
240
245
  appContext.moduleRegistry.register(holder: mockModuleHolder(appContext) {
241
246
  Name("TestModule")
242
247
 
243
248
  Function("returnPi") { Double.pi }
244
-
249
+
245
250
  Function("returnNull") { () -> Double? in
246
251
  return nil
247
252
  }
248
-
253
+
249
254
  Function("isArgNull") { (arg: Double?) -> Bool in
250
255
  return arg == nil
251
256
  }
@@ -260,30 +265,41 @@ class FunctionSpec: ExpoSpec {
260
265
  }
261
266
  }
262
267
  }
268
+
269
+ Function("withFunction") { (fn: JavaScriptFunction<String>) -> String in
270
+ return try fn.call("foo", "bar")
271
+ }
263
272
  })
264
273
  }
265
274
 
266
275
  it("returns values") {
267
- expect(try runtime?.eval("expo.modules.TestModule.returnPi()").asDouble()) == Double.pi
268
- expect(try runtime?.eval("expo.modules.TestModule.returnNull()").isNull()) == true
276
+ expect(try runtime.eval("expo.modules.TestModule.returnPi()").asDouble()) == Double.pi
277
+ expect(try runtime.eval("expo.modules.TestModule.returnNull()").isNull()) == true
269
278
  }
270
279
 
271
280
  it("accepts optional arguments") {
272
- expect(try runtime?.eval("expo.modules.TestModule.isArgNull(3.14)").asBool()) == false
273
- expect(try runtime?.eval("expo.modules.TestModule.isArgNull(null)").asBool()) == true
281
+ expect(try runtime.eval("expo.modules.TestModule.isArgNull(3.14)").asBool()) == false
282
+ expect(try runtime.eval("expo.modules.TestModule.isArgNull(null)").asBool()) == true
274
283
  }
275
284
 
276
285
  it("returns object made from definition") {
277
286
  let initialValue = Int.random(in: 1..<100)
278
- let object = try runtime?.eval("object = expo.modules.TestModule.returnObjectDefinition(\(initialValue))")
287
+ let object = try runtime.eval("object = expo.modules.TestModule.returnObjectDefinition(\(initialValue))")
288
+
289
+ expect(object.kind) == .object
290
+ expect(object.getObject().hasProperty("increment")) == true
279
291
 
280
- expect(object?.kind) == .object
281
- expect(object?.getObject().hasProperty("increment")) == true
292
+ let result = try runtime.eval("object.increment()")
293
+
294
+ expect(result.kind) == .number
295
+ expect(result.getInt()) == initialValue + 1
296
+ }
282
297
 
283
- let result = try runtime?.eval("object.increment()")
298
+ it("takes JavaScriptFunction argument") {
299
+ let value = try runtime.eval("expo.modules.TestModule.withFunction((a, b) => a + b)")
284
300
 
285
- expect(result?.kind) == .number
286
- expect(result?.getInt()) == initialValue + 1
301
+ expect(value.kind) == .string
302
+ expect(value.getString()) == "foobar"
287
303
  }
288
304
  }
289
305
  }
@@ -86,7 +86,11 @@ class JavaScriptRuntimeSpec: ExpoSpec {
86
86
  it("throws evaluation exception") {
87
87
  expect({ try runtime.eval("foo") }).to(throwError { error in
88
88
  expect(error).to(beAKindOf(JavaScriptEvalException.self))
89
+ #if canImport(reacthermes)
90
+ expect((error as! JavaScriptEvalException).reason).to(contain("Property 'foo' doesn't exist"))
91
+ #else
89
92
  expect((error as! JavaScriptEvalException).reason).to(contain("Can't find variable: foo"))
93
+ #endif
90
94
  })
91
95
  }
92
96
  }
@@ -5,9 +5,12 @@ import ExpoModulesTestCore
5
5
  class PropertyComponentSpec: ExpoSpec {
6
6
  override func spec() {
7
7
  describe("property") {
8
+ let appContext = AppContext.create()
9
+ let runtime = try! appContext.runtime
10
+
8
11
  it("gets the value") {
9
12
  let property = Property("test") { return "expo" }
10
- expect(try property.getValue()) == "expo"
13
+ expect(try property.getValue(appContext: appContext)) == "expo"
11
14
  }
12
15
 
13
16
  it("sets the value") {
@@ -19,39 +22,39 @@ class PropertyComponentSpec: ExpoSpec {
19
22
  }
20
23
 
21
24
  let newValue = Int.random(in: 0..<100)
22
- property.setValue(newValue)
25
+ property.setValue(newValue, appContext: appContext)
23
26
 
24
- expect(try property.getValue()) == value
27
+ expect(try property.getValue(appContext: appContext)) == value
25
28
  expect(value) == newValue
26
29
  }
27
30
  }
28
31
 
29
32
  describe("module property") {
30
33
  let appContext = AppContext.create()
31
- let runtime = appContext.runtime
34
+ let runtime = try! appContext.runtime
32
35
 
33
36
  beforeSuite {
34
37
  appContext.moduleRegistry.register(moduleType: PropertyTestModule.self)
35
38
  }
36
39
 
37
40
  it("gets read-only property") {
38
- let value = try runtime?.eval("expo.modules.PropertyTest.readOnly")
39
- expect(value?.getString()) == "foo"
41
+ let value = try runtime.eval("expo.modules.PropertyTest.readOnly")
42
+ expect(value.getString()) == "foo"
40
43
  }
41
44
 
42
45
  it("gets writable property") {
43
- let value = try runtime?.eval("expo.modules.PropertyTest.writable")
44
- expect(value?.getInt()) == 444
46
+ let value = try runtime.eval("expo.modules.PropertyTest.writable")
47
+ expect(value.getInt()) == 444
45
48
  }
46
49
 
47
50
  it("sets writable property") {
48
- try runtime?.eval("expo.modules.PropertyTest.writable = 777")
49
- let value = try runtime?.eval("expo.modules.PropertyTest.writable")
50
- expect(value?.getInt()) == 777
51
+ try runtime.eval("expo.modules.PropertyTest.writable = 777")
52
+ let value = try runtime.eval("expo.modules.PropertyTest.writable")
53
+ expect(value.getInt()) == 777
51
54
  }
52
55
 
53
56
  it("is enumerable") {
54
- let keys = try runtime?.eval("Object.keys(expo.modules.PropertyTest)").getArray().map { $0.getString() } ?? []
57
+ let keys = try runtime.eval("Object.keys(expo.modules.PropertyTest)").getArray().map { $0.getString() } ?? []
55
58
  expect(keys).to(contain("readOnly", "writable", "undefined"))
56
59
  }
57
60
 
@@ -62,73 +65,73 @@ class PropertyComponentSpec: ExpoSpec {
62
65
  // }
63
66
 
64
67
  it("returns undefined when getter is not specified") {
65
- let value = try runtime?.eval("expo.modules.PropertyTest.undefined")
66
- expect(value?.isUndefined()) == true
68
+ let value = try runtime.eval("expo.modules.PropertyTest.undefined")
69
+ expect(value.isUndefined()) == true
67
70
  }
68
71
  }
69
72
 
70
73
  describe("class property") {
71
74
  let appContext = AppContext.create()
72
- let runtime = appContext.runtime
75
+ let runtime = try! appContext.runtime
73
76
 
74
77
  beforeSuite {
75
78
  appContext.moduleRegistry.register(moduleType: PropertyTestModule.self)
76
79
  }
77
80
 
78
81
  it("gets the value") {
79
- let value = try runtime?.eval("new expo.modules.PropertyTest.TestClass().someValue")
82
+ let value = try runtime.eval("new expo.modules.PropertyTest.TestClass().someValue")
80
83
 
81
- expect(value?.kind) == .number
82
- expect(value?.getInt()) == TestClass.constantValue
84
+ expect(value.kind) == .number
85
+ expect(value.getInt()) == TestClass.constantValue
83
86
  }
84
87
 
85
88
  it("sets the value") {
86
89
  let newValue = Int.random(in: 1..<100)
87
- let value = try runtime?.eval([
90
+ let value = try runtime.eval([
88
91
  "object = new expo.modules.PropertyTest.TestClass()",
89
92
  "object.someValue = \(newValue)",
90
93
  "object.someValue"
91
94
  ])
92
95
 
93
- expect(value?.kind) == .number
94
- expect(value?.getInt()) == newValue
96
+ expect(value.kind) == .number
97
+ expect(value.getInt()) == newValue
95
98
  }
96
99
 
97
100
  // Tests for accessing shared object properties through KeyPath and ReferenceWritableKeyPath
98
101
  describe("key path") {
99
102
  it("gets immutable property") {
100
- let value = try runtime?.eval([
103
+ let value = try runtime.eval([
101
104
  "object = new expo.modules.PropertyTest.TestClass()",
102
105
  "object.immutableKeyPathProperty"
103
106
  ])
104
107
 
105
- expect(value?.kind) == .number
106
- expect(value?.getInt()) == TestClass.constantValue
108
+ expect(value.kind) == .number
109
+ expect(value.getInt()) == TestClass.constantValue
107
110
  }
108
111
 
109
112
  it("cannot set immutable property") {
110
113
  let newValue = Int.random(in: 100..<200)
111
- let value = try runtime?.eval([
114
+ let value = try runtime.eval([
112
115
  "object = new expo.modules.PropertyTest.TestClass()",
113
116
  "object.immutableKeyPathProperty = \(newValue)",
114
117
  "object.immutableKeyPathProperty"
115
118
  ])
116
119
 
117
120
  // Returned value didn't change, it doesn't equal to `newValue`
118
- expect(value?.kind) == .number
119
- expect(value?.getInt()) == TestClass.constantValue
121
+ expect(value.kind) == .number
122
+ expect(value.getInt()) == TestClass.constantValue
120
123
  }
121
124
 
122
125
  it("sets mutable property") {
123
126
  let newValue = Int.random(in: 100..<200)
124
- let value = try runtime?.eval([
127
+ let value = try runtime.eval([
125
128
  "object = new expo.modules.PropertyTest.TestClass()",
126
129
  "object.mutableKeyPathProperty = \(newValue)",
127
130
  "object.mutableKeyPathProperty"
128
131
  ])
129
132
 
130
- expect(value?.kind) == .number
131
- expect(value?.getInt()) == newValue
133
+ expect(value.kind) == .number
134
+ expect(value.getInt()) == newValue
132
135
  }
133
136
  }
134
137
  }
@@ -4,9 +4,11 @@ import ExpoModulesTestCore
4
4
 
5
5
  class RecordSpec: ExpoSpec {
6
6
  override func spec() {
7
+ let appContext = AppContext.create()
8
+
7
9
  it("initializes with empty dictionary") {
8
10
  struct TestRecord: Record { }
9
- _ = try TestRecord(from: [:])
11
+ _ = try TestRecord(from: [:], appContext: appContext)
10
12
  }
11
13
 
12
14
  it("works back and forth with a field") {
@@ -14,7 +16,7 @@ class RecordSpec: ExpoSpec {
14
16
  @Field var a: String?
15
17
  }
16
18
  let dict = ["a": "b"]
17
- let record = try TestRecord(from: dict)
19
+ let record = try TestRecord(from: dict, appContext: appContext)
18
20
 
19
21
  expect(record.a).to(be(dict["a"]))
20
22
  expect(record.toDictionary()["a"]).to(be(dict["a"]))
@@ -25,7 +27,7 @@ class RecordSpec: ExpoSpec {
25
27
  @Field("key") var a: String?
26
28
  }
27
29
  let dict = ["key": "b"]
28
- let record = try TestRecord(from: dict)
30
+ let record = try TestRecord(from: dict, appContext: appContext)
29
31
 
30
32
  expect(record.a).to(be(dict["key"]))
31
33
  expect(record.toDictionary()["key"]).to(be(dict["key"]))
@@ -36,7 +38,7 @@ class RecordSpec: ExpoSpec {
36
38
  @Field(.required) var a: Int
37
39
  }
38
40
 
39
- expect { try TestRecord(from: [:]) }.to(throwError { error in
41
+ expect { try TestRecord(from: [:], appContext: appContext) }.to(throwError { error in
40
42
  expect(error).to(beAKindOf(FieldRequiredException.self))
41
43
  })
42
44
  }
@@ -47,7 +49,7 @@ class RecordSpec: ExpoSpec {
47
49
  }
48
50
  let dict = ["a": "try with String instead of Int"]
49
51
 
50
- expect { try TestRecord(from: dict) }.to(throwError { error in
52
+ expect { try TestRecord(from: dict, appContext: appContext) }.to(throwError { error in
51
53
  expect(error).to(beAKindOf(FieldInvalidTypeException.self))
52
54
  })
53
55
  }