expo-modules-core 1.2.6 → 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 +33 -4
  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 +18 -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 +34 -21
  42. package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +13 -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 -4
  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 +7 -8
  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
@@ -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
  }
@@ -7,7 +7,7 @@ import ExpoModulesTestCore
7
7
  final class SharedObjectRegistrySpec: 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
 
12
12
  describe("pullNextId") {
13
13
  it("returns nextId") {
@@ -29,28 +29,28 @@ final class SharedObjectRegistrySpec: ExpoSpec {
29
29
  describe("add") {
30
30
  it("adds using nextId") {
31
31
  let nextId = SharedObjectRegistry.nextId
32
- let id = SharedObjectRegistry.add(native: TestSharedObject(), javaScript: runtime!.createObject())
32
+ let id = SharedObjectRegistry.add(native: TestSharedObject(), javaScript: runtime.createObject())
33
33
  expect(nextId) == id
34
34
  }
35
35
  it("is increasing size") {
36
36
  let size = SharedObjectRegistry.size
37
- SharedObjectRegistry.add(native: TestSharedObject(), javaScript: runtime!.createObject())
37
+ SharedObjectRegistry.add(native: TestSharedObject(), javaScript: runtime.createObject())
38
38
  expect(SharedObjectRegistry.size) == size + 1
39
39
  }
40
40
  it("assigns id on native object") {
41
41
  let nativeObject = TestSharedObject()
42
- let id = SharedObjectRegistry.add(native: nativeObject, javaScript: runtime!.createObject())
42
+ let id = SharedObjectRegistry.add(native: nativeObject, javaScript: runtime.createObject())
43
43
  expect(nativeObject.sharedObjectId) == id
44
44
  }
45
45
  it("assigns id on JS object") {
46
- let jsObject = runtime!.createObject()
46
+ let jsObject = runtime.createObject()
47
47
  let id = SharedObjectRegistry.add(native: TestSharedObject(), javaScript: jsObject)
48
48
  expect(jsObject.hasProperty(sharedObjectIdPropertyName)) == true
49
49
  expect(try! jsObject.getProperty(sharedObjectIdPropertyName).asInt()) == id
50
50
  }
51
51
  it("saves objects pair") {
52
52
  let nativeObject = TestSharedObject()
53
- let jsObject = runtime!.createObject()
53
+ let jsObject = runtime.createObject()
54
54
  let id = SharedObjectRegistry.add(native: nativeObject, javaScript: jsObject)
55
55
  let pair = SharedObjectRegistry.get(id)
56
56
  expect(pair?.native) === nativeObject
@@ -60,18 +60,18 @@ final class SharedObjectRegistrySpec: ExpoSpec {
60
60
 
61
61
  describe("delete") {
62
62
  it("deletes objects pair") {
63
- let id = SharedObjectRegistry.add(native: TestSharedObject(), javaScript: runtime!.createObject())
63
+ let id = SharedObjectRegistry.add(native: TestSharedObject(), javaScript: runtime.createObject())
64
64
  SharedObjectRegistry.delete(id)
65
65
  expect(SharedObjectRegistry.get(id)).to(beNil())
66
66
  }
67
67
  it("resets id on native object") {
68
68
  let nativeObject = TestSharedObject()
69
- let id = SharedObjectRegistry.add(native: nativeObject, javaScript: runtime!.createObject())
69
+ let id = SharedObjectRegistry.add(native: nativeObject, javaScript: runtime.createObject())
70
70
  SharedObjectRegistry.delete(id)
71
71
  expect(nativeObject.sharedObjectId) == 0
72
72
  }
73
73
  it("resets id on JS object") {
74
- let jsObject = runtime!.createObject()
74
+ let jsObject = runtime.createObject()
75
75
  let id = SharedObjectRegistry.add(native: TestSharedObject(), javaScript: jsObject)
76
76
  SharedObjectRegistry.delete(id)
77
77
  expect(try! jsObject.getProperty(sharedObjectIdPropertyName).asInt()) == 0
@@ -81,12 +81,12 @@ final class SharedObjectRegistrySpec: ExpoSpec {
81
81
  describe("toNativeObject") {
82
82
  it("returns native object") {
83
83
  let nativeObject = TestSharedObject()
84
- let jsObject = runtime!.createObject()
84
+ let jsObject = runtime.createObject()
85
85
  SharedObjectRegistry.add(native: nativeObject, javaScript: jsObject)
86
86
  expect(SharedObjectRegistry.toNativeObject(jsObject)) === nativeObject
87
87
  }
88
88
  it("returns nil") {
89
- let jsObject = runtime!.createObject()
89
+ let jsObject = runtime.createObject()
90
90
  expect(SharedObjectRegistry.toNativeObject(jsObject)).to(beNil())
91
91
  }
92
92
  }
@@ -94,7 +94,7 @@ final class SharedObjectRegistrySpec: ExpoSpec {
94
94
  describe("toJavaScriptObject") {
95
95
  it("returns JS object") {
96
96
  let nativeObject = TestSharedObject()
97
- let jsObject = runtime!.createObject()
97
+ let jsObject = runtime.createObject()
98
98
  SharedObjectRegistry.add(native: nativeObject, javaScript: jsObject)
99
99
  expect(SharedObjectRegistry.toJavaScriptObject(nativeObject)) == jsObject
100
100
  }
@@ -8,7 +8,7 @@ final class TypedArraysSpec: ExpoSpec {
8
8
  override func spec() {
9
9
  describe("module") {
10
10
  let appContext = AppContext.create()
11
- let runtime = appContext.runtime!
11
+ let runtime = try! appContext.runtime
12
12
 
13
13
  beforeSuite {
14
14
  appContext.moduleRegistry.register(moduleType: TypedArraysModule.self)
@@ -15,6 +15,8 @@ final class ViewDefinitionSpec: ExpoSpec {
15
15
  }
16
16
 
17
17
  describe("Prop") {
18
+ let appContext = AppContext.create()
19
+
18
20
  it("sets the prop") {
19
21
  let textView = UITextView()
20
22
  let content = "hello"
@@ -23,7 +25,7 @@ final class ViewDefinitionSpec: ExpoSpec {
23
25
  view.text = value
24
26
  }
25
27
  }
26
- try definition.propsDict()["content"]?.set(value: content, onView: textView)
28
+ try definition.propsDict()["content"]?.set(value: content, onView: textView, appContext: appContext)
27
29
  expect(textView.text) == content
28
30
  }
29
31
 
@@ -36,7 +38,7 @@ final class ViewDefinitionSpec: ExpoSpec {
36
38
  expect(view).to(beAKindOf(UITextView.self))
37
39
  }
38
40
  }
39
- try definition.propsDict()["content"]?.set(value: content, onView: textView)
41
+ try definition.propsDict()["content"]?.set(value: content, onView: textView, appContext: appContext)
40
42
  }
41
43
  }
42
44
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-modules-core",
3
- "version": "1.2.6",
3
+ "version": "1.3.0",
4
4
  "description": "The core of Expo Modules architecture",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -42,5 +42,5 @@
42
42
  "@testing-library/react-hooks": "^7.0.1",
43
43
  "expo-module-scripts": "^3.0.0"
44
44
  },
45
- "gitHead": "eaf0d87f56e17cb7162ccbd4f9ee29fb64dab810"
45
+ "gitHead": "4ba50c428c8369bb6b3a51a860d4898ad4ccbe78"
46
46
  }
@@ -1,5 +1,7 @@
1
1
  import React from 'react';
2
- import { NativeModules, requireNativeComponent, HostComponent } from 'react-native';
2
+ import { findNodeHandle, NativeModules, requireNativeComponent, HostComponent } from 'react-native';
3
+
4
+ import { requireNativeModule } from './requireNativeModule';
3
5
 
4
6
  // To make the transition from React Native's `requireNativeComponent` to Expo's
5
7
  // `requireNativeViewManager` as easy as possible, `requireNativeViewManager` is a drop-in
@@ -10,10 +12,6 @@ import { NativeModules, requireNativeComponent, HostComponent } from 'react-nati
10
12
  // passed to React Native's View (ex: style, testID) and custom view props, which are passed to the
11
13
  // adapter view component in a prop called `proxiedProperties`.
12
14
 
13
- type NativeExpoComponentProps = {
14
- proxiedProperties: object;
15
- };
16
-
17
15
  /**
18
16
  * A map that caches registered native components.
19
17
  */
@@ -52,33 +50,39 @@ export function requireNativeViewManager<P>(viewName: string): React.ComponentTy
52
50
  // Set up the React Native native component, which is an adapter to the universal module's view
53
51
  // manager
54
52
  const reactNativeViewName = `ViewManagerAdapter_${viewName}`;
55
- const ReactNativeComponent =
56
- requireCachedNativeComponent<NativeExpoComponentProps>(reactNativeViewName);
57
- const proxiedPropsNames = viewManagerConfig?.propsNames ?? [];
53
+ const ReactNativeComponent = requireCachedNativeComponent(reactNativeViewName);
58
54
 
59
- // Define a component for universal-module authors to access their native view manager
60
- const NativeComponentAdapter = React.forwardRef<any>((props, ref) => {
61
- const nativeProps = omit(props, proxiedPropsNames);
62
- const proxiedProps = pick(props, proxiedPropsNames);
63
- return <ReactNativeComponent {...nativeProps} proxiedProperties={proxiedProps} ref={ref} />;
64
- }) as React.ComponentType<P>;
65
- NativeComponentAdapter.displayName = `Adapter<${viewName}>`;
66
- return NativeComponentAdapter;
67
- }
55
+ class NativeComponent extends React.PureComponent<P> {
56
+ static displayName = viewName;
57
+
58
+ // This will be accessed from native when the prototype functions are called,
59
+ // in order to find the associated native view.
60
+ nativeTag: number | null = null;
61
+
62
+ componentDidMount(): void {
63
+ this.nativeTag = findNodeHandle(this);
64
+ }
68
65
 
69
- function omit(props: Record<string, any>, propNames: string[]) {
70
- const copied = { ...props };
71
- for (const propName of propNames) {
72
- delete copied[propName];
66
+ render(): React.ReactNode {
67
+ return <ReactNativeComponent {...this.props} />;
68
+ }
73
69
  }
74
- return copied;
75
- }
76
70
 
77
- function pick(props: Record<string, any>, propNames: string[]) {
78
- return propNames.reduce((prev, curr) => {
79
- if (curr in props) {
80
- prev[curr] = props[curr];
71
+ try {
72
+ const nativeModule = requireNativeModule(viewName);
73
+ const nativeViewPrototype = nativeModule.ViewPrototype;
74
+
75
+ if (nativeViewPrototype) {
76
+ // Assign native view functions to the component prototype so they can be accessed from the ref.
77
+ Object.assign(NativeComponent.prototype, nativeViewPrototype);
81
78
  }
82
- return prev;
83
- }, {});
79
+ } catch {
80
+ // `requireNativeModule` may throw an error when the native module cannot be found.
81
+ // In some tests we don't mock the entire modules, but we do want to mock native views. For now,
82
+ // until we still have to support the legacy modules proxy and don't have better ways to mock,
83
+ // let's just gracefully skip assigning the prototype functions.
84
+ // See: https://github.com/expo/expo/blob/main/packages/expo-modules-core/src/__tests__/NativeViewManagerAdapter-test.native.tsx
85
+ }
86
+
87
+ return NativeComponent;
84
88
  }
@@ -34,8 +34,8 @@ declare global {
34
34
  */
35
35
  export function requireNativeModule<ModuleType = any>(moduleName: string): ModuleType {
36
36
  const nativeModule: ModuleType =
37
- global.expo?.modules?.[moduleName] ??
38
- global.ExpoModules?.[moduleName] ??
37
+ globalThis.expo?.modules?.[moduleName] ??
38
+ globalThis.ExpoModules?.[moduleName] ??
39
39
  NativeModulesProxy[moduleName];
40
40
 
41
41
  if (!nativeModule) {