expo-modules-core 1.3.2 → 1.4.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 (64) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/ExpoModulesCore.podspec +26 -5
  3. package/android/ExpoModulesCorePlugin.gradle +4 -0
  4. package/android/build.gradle +13 -14
  5. package/android/src/main/AndroidManifest.xml +1 -2
  6. package/android/src/main/cpp/ExpoModulesHostObject.cpp +3 -0
  7. package/android/src/main/cpp/JNIDeallocator.cpp +17 -0
  8. package/android/src/main/cpp/JNIDeallocator.h +25 -0
  9. package/android/src/main/cpp/JSIInteropModuleRegistry.cpp +8 -1
  10. package/android/src/main/cpp/JSIInteropModuleRegistry.h +6 -1
  11. package/android/src/main/cpp/JavaCallback.cpp +9 -0
  12. package/android/src/main/cpp/JavaCallback.h +12 -2
  13. package/android/src/main/cpp/JavaScriptFunction.cpp +13 -0
  14. package/android/src/main/cpp/JavaScriptFunction.h +7 -1
  15. package/android/src/main/cpp/JavaScriptModuleObject.cpp +2 -1
  16. package/android/src/main/cpp/JavaScriptObject.cpp +17 -2
  17. package/android/src/main/cpp/JavaScriptObject.h +10 -3
  18. package/android/src/main/cpp/JavaScriptRuntime.cpp +5 -4
  19. package/android/src/main/cpp/JavaScriptRuntime.h +5 -3
  20. package/android/src/main/cpp/JavaScriptTypedArray.cpp +14 -0
  21. package/android/src/main/cpp/JavaScriptTypedArray.h +6 -0
  22. package/android/src/main/cpp/JavaScriptValue.cpp +32 -4
  23. package/android/src/main/cpp/JavaScriptValue.h +10 -3
  24. package/android/src/main/cpp/MethodMetadata.cpp +1 -1
  25. package/android/src/main/cpp/types/FrontendConverter.cpp +8 -4
  26. package/android/src/main/java/expo/modules/core/interfaces/ReactActivityHandler.java +14 -0
  27. package/android/src/main/java/expo/modules/kotlin/AppContext.kt +4 -1
  28. package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +7 -3
  29. package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +19 -12
  30. package/android/src/main/java/expo/modules/kotlin/devtools/ExpoNetworkInspectOkHttpInterceptors.kt +70 -0
  31. package/android/src/main/java/expo/modules/kotlin/devtools/ExpoRequestCdpInterceptor.kt +72 -0
  32. package/android/src/main/java/expo/modules/kotlin/devtools/OkHttpHeadersExtension.kt +18 -0
  33. package/android/src/main/java/expo/modules/kotlin/devtools/cdp/CdpNetworkTypes.kt +257 -0
  34. package/android/src/main/java/expo/modules/kotlin/jni/JNIDeallocator.kt +24 -15
  35. package/android/src/main/java/expo/modules/kotlin/jni/JSIInteropModuleRegistry.kt +8 -1
  36. package/android/src/main/java/expo/modules/kotlin/jni/JavaCallback.kt +0 -4
  37. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptFunction.kt +0 -4
  38. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptModuleObject.kt +5 -2
  39. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptObject.kt +0 -5
  40. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptValue.kt +0 -4
  41. package/android/src/main/java/expo/modules/kotlin/objects/ObjectDefinitionBuilder.kt +1 -1
  42. package/android/src/main/java/expo/modules/kotlin/types/ColorTypeConverter.kt +3 -0
  43. package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +1 -2
  44. package/android-annotation/build.gradle +2 -2
  45. package/android-annotation-processor/build.gradle +2 -2
  46. package/ios/JSI/EXJSIInstaller.h +2 -2
  47. package/ios/JSI/EXJSIInstaller.mm +6 -6
  48. package/ios/JSI/EXJavaScriptRuntime.h +0 -6
  49. package/ios/JSI/EXJavaScriptRuntime.mm +0 -23
  50. package/ios/RCTComponentData+Privates.h +17 -0
  51. package/ios/RCTComponentData+Privates.m +15 -0
  52. package/ios/Swift/AppContext.swift +20 -11
  53. package/ios/Swift/DevTools/CdpNetworkTypes.swift +163 -0
  54. package/ios/Swift/DevTools/ExpoRequestCdpInterceptor.swift +71 -0
  55. package/ios/Swift/DevTools/ExpoRequestInterceptorProtocol.swift +183 -0
  56. package/ios/Swift/DevTools/URLRequest+httpBodyData.swift +43 -0
  57. package/ios/Swift/ExpoRuntime.swift +28 -0
  58. package/ios/Swift/Modules/CoreModule.swift +7 -0
  59. package/ios/Swift/SharedObjects/SharedRef.swift +12 -0
  60. package/ios/Swift/Views/ComponentData.swift +1 -1
  61. package/ios/Tests/CoreModuleSpec.swift +27 -0
  62. package/ios/Tests/ExpoRequestCdpInterceptorSpec.swift +165 -0
  63. package/ios/Tests/SharedRefSpec.swift +60 -0
  64. package/package.json +2 -2
@@ -0,0 +1,257 @@
1
+ // Copyright 2015-present 650 Industries. All rights reserved.
2
+
3
+ package expo.modules.kotlin.devtools.cdp
4
+
5
+ import expo.modules.kotlin.devtools.ExpoNetworkInspectOkHttpNetworkInterceptor
6
+ import expo.modules.kotlin.devtools.toSingleMap
7
+ import okio.Buffer
8
+ import org.json.JSONObject
9
+ import java.math.BigDecimal
10
+
11
+ //region Types
12
+
13
+ typealias Headers = Map<String, String>
14
+ typealias MonotonicTime = BigDecimal
15
+ typealias RequestId = String
16
+ typealias TimeSinceEpoch = BigDecimal
17
+
18
+ enum class ResourceType(val value: String) {
19
+ IMAGE("Image"),
20
+ MEDIA("Media"),
21
+ FONT("Font"),
22
+ SCRIPT("Script"),
23
+ FETCH("Fetch"),
24
+ OTHER("Other")
25
+ }
26
+
27
+ interface JsonSerializable {
28
+ fun toJSONObject(): JSONObject
29
+ }
30
+
31
+ data class ConnectTiming(val requestTime: MonotonicTime) : JsonSerializable {
32
+ override fun toJSONObject(): JSONObject {
33
+ return JSONObject().apply {
34
+ put("requestTime", requestTime)
35
+ }
36
+ }
37
+ }
38
+
39
+ data class Request(
40
+ val url: String,
41
+ val method: String,
42
+ val headers: Headers,
43
+ val postData: String?
44
+ ) : JsonSerializable {
45
+ constructor(request: okhttp3.Request) : this(
46
+ url = request.url.toString(),
47
+ method = request.method,
48
+ headers = request.headers.toSingleMap(),
49
+ postData = request.body?.let {
50
+ if (it.contentLength() < ExpoNetworkInspectOkHttpNetworkInterceptor.MAX_BODY_SIZE) {
51
+ val buffer = Buffer()
52
+ it.writeTo(buffer)
53
+ return@let buffer.readUtf8(buffer.size.coerceAtMost(ExpoNetworkInspectOkHttpNetworkInterceptor.MAX_BODY_SIZE))
54
+ } else return@let null
55
+ }
56
+ )
57
+
58
+ override fun toJSONObject(): JSONObject {
59
+ return JSONObject().apply {
60
+ put("url", url)
61
+ put("method", method)
62
+ put("headers", JSONObject(headers))
63
+ postData?.let {
64
+ put("postData", postData)
65
+ }
66
+ }
67
+ }
68
+ }
69
+
70
+ data class Response(
71
+ val url: String,
72
+ val status: Int,
73
+ val statusText: String,
74
+ val headers: Headers,
75
+ val mimeType: String,
76
+ val encodedDataLength: Long
77
+ ) : JsonSerializable {
78
+ constructor(response: okhttp3.Response) : this(
79
+ url = response.request.url.toString(),
80
+ status = response.code,
81
+ statusText = response.message,
82
+ headers = response.headers.toSingleMap(),
83
+ mimeType = response.header("Content-Type", "") ?: "",
84
+ encodedDataLength = response.body?.contentLength() ?: 0,
85
+ )
86
+
87
+ override fun toJSONObject(): JSONObject {
88
+ return JSONObject().apply {
89
+ put("url", url)
90
+ put("status", status)
91
+ put("statusText", statusText)
92
+ put("headers", JSONObject(headers))
93
+ put("mimeType", mimeType)
94
+ put("encodedDataLength", encodedDataLength)
95
+ }
96
+ }
97
+ }
98
+
99
+ //endregion Types
100
+
101
+ //region Events
102
+
103
+ data class RequestWillBeSentParams(
104
+ val requestId: RequestId,
105
+ val loaderId: String = "",
106
+ val documentURL: String = "mobile",
107
+ val request: Request,
108
+ val timestamp: MonotonicTime,
109
+ val wallTime: TimeSinceEpoch,
110
+ val initiator: Map<String, String> = mapOf("type" to "script"),
111
+ val redirectHasExtraInfo: Boolean,
112
+ val redirectResponse: Response?,
113
+ val referrerPolicy: String = "no-referrer",
114
+ val type: ResourceType,
115
+ ) : JsonSerializable {
116
+ constructor(now: BigDecimal, requestId: RequestId, request: okhttp3.Request, redirectResponse: okhttp3.Response?) : this(
117
+ requestId = requestId,
118
+ request = Request(request),
119
+ timestamp = now,
120
+ wallTime = now,
121
+ redirectHasExtraInfo = redirectResponse != null,
122
+ redirectResponse = redirectResponse?.let { Response(it) },
123
+ type = ResourceType.FETCH,
124
+ )
125
+
126
+ override fun toJSONObject(): JSONObject {
127
+ return JSONObject().apply {
128
+ put("requestId", requestId)
129
+ put("loaderId", loaderId)
130
+ put("documentURL", documentURL)
131
+ put("request", request.toJSONObject())
132
+ put("timestamp", timestamp)
133
+ put("wallTime", wallTime)
134
+ put("initiator", JSONObject(initiator))
135
+ put("redirectHasExtraInfo", redirectHasExtraInfo)
136
+ redirectResponse?.let {
137
+ put("redirectResponse", it.toJSONObject())
138
+ }
139
+ put("referrerPolicy", referrerPolicy)
140
+ put("type", type.value)
141
+ }
142
+ }
143
+ }
144
+
145
+ data class RequestWillBeSentExtraInfoParams(
146
+ val requestId: RequestId,
147
+ val associatedCookies: Map<String, String> = emptyMap(),
148
+ val headers: Headers,
149
+ val connectTiming: ConnectTiming,
150
+ ) : JsonSerializable {
151
+ constructor(now: BigDecimal, requestId: RequestId, request: okhttp3.Request) : this(
152
+ requestId = requestId,
153
+ headers = request.headers.toSingleMap(),
154
+ connectTiming = ConnectTiming(now),
155
+ )
156
+
157
+ override fun toJSONObject(): JSONObject {
158
+ return JSONObject().apply {
159
+ put("requestId", requestId)
160
+ put("associatedCookies", JSONObject(associatedCookies))
161
+ put("headers", JSONObject(headers))
162
+ put("connectTiming", connectTiming.toJSONObject())
163
+ }
164
+ }
165
+ }
166
+
167
+ data class ResponseReceivedParams(
168
+ val requestId: RequestId,
169
+ val loaderId: String = "",
170
+ val timestamp: MonotonicTime,
171
+ val type: ResourceType,
172
+ val response: Response,
173
+ val hasExtraInfo: Boolean = false,
174
+ ) : JsonSerializable {
175
+ constructor(now: BigDecimal, requestId: RequestId, request: okhttp3.Request, repsonse: okhttp3.Response) : this(
176
+ requestId = requestId,
177
+ timestamp = now,
178
+ type = ResourceType.FETCH,
179
+ response = Response(repsonse),
180
+ )
181
+
182
+ override fun toJSONObject(): JSONObject {
183
+ return JSONObject().apply {
184
+ put("requestId", requestId)
185
+ put("loaderId", loaderId)
186
+ put("timestamp", timestamp)
187
+ put("type", type.value)
188
+ put("response", response.toJSONObject())
189
+ put("hasExtraInfo", hasExtraInfo)
190
+ }
191
+ }
192
+ }
193
+
194
+ data class LoadingFinishedParams(
195
+ val requestId: RequestId,
196
+ val timestamp: MonotonicTime,
197
+ val encodedDataLength: Long,
198
+ ) : JsonSerializable {
199
+ constructor(now: BigDecimal, requestId: RequestId, request: okhttp3.Request, repsonse: okhttp3.Response) : this(
200
+ requestId = requestId,
201
+ timestamp = now,
202
+ encodedDataLength = repsonse.body?.contentLength() ?: 0,
203
+ )
204
+
205
+ override fun toJSONObject(): JSONObject {
206
+ return JSONObject().apply {
207
+ put("requestId", requestId)
208
+ put("timestamp", timestamp)
209
+ put("encodedDataLength", encodedDataLength)
210
+ }
211
+ }
212
+ }
213
+
214
+ data class ExpoReceivedResponseBodyParams(
215
+ val requestId: RequestId,
216
+ var body: String,
217
+ var base64Encoded: Boolean,
218
+ ) : JsonSerializable {
219
+ constructor(now: BigDecimal, requestId: RequestId, request: okhttp3.Request, response: okhttp3.Response) : this(
220
+ requestId = requestId,
221
+ body = "",
222
+ base64Encoded = false,
223
+ ) {
224
+ val contentLength = response.body?.contentLength() ?: 0
225
+ check(contentLength >= 0 && contentLength <= ExpoNetworkInspectOkHttpNetworkInterceptor.MAX_BODY_SIZE)
226
+ val rawBody = response.peekBody(ExpoNetworkInspectOkHttpNetworkInterceptor.MAX_BODY_SIZE)
227
+ val contentType = rawBody.contentType()
228
+ val isText = contentType?.type == "text" || (contentType?.type == "application" && contentType.subtype == "json")
229
+ val bodyString = if (isText) rawBody.string() else rawBody.source().readByteString().base64()
230
+
231
+ this.body = bodyString
232
+ this.base64Encoded = !isText
233
+ }
234
+ override fun toJSONObject(): JSONObject {
235
+ return JSONObject().apply {
236
+ put("requestId", requestId)
237
+ put("body", body)
238
+ put("base64Encoded", base64Encoded)
239
+ }
240
+ }
241
+ }
242
+
243
+ //endregion Events
244
+
245
+ typealias EventParams = JsonSerializable
246
+
247
+ data class Event(
248
+ val method: String,
249
+ val params: EventParams
250
+ ) {
251
+ fun toJson(): String {
252
+ return JSONObject().apply {
253
+ put("method", method)
254
+ put("params", params.toJSONObject())
255
+ }.toString()
256
+ }
257
+ }
@@ -1,14 +1,17 @@
1
1
  package expo.modules.kotlin.jni
2
2
 
3
+ import expo.modules.core.interfaces.DoNotStrip
3
4
  import java.lang.ref.PhantomReference
4
5
  import java.lang.ref.ReferenceQueue
5
6
  import java.lang.ref.WeakReference
6
7
 
8
+ @DoNotStrip
7
9
  interface Destructible {
8
10
  fun deallocate()
9
11
  }
10
12
 
11
- object JNIDeallocator {
13
+ @DoNotStrip
14
+ class JNIDeallocator(private val shouldCreateDestructorThread: Boolean = true) {
12
15
  /**
13
16
  * A [PhantomReference] queue managed by JVM
14
17
  */
@@ -23,23 +26,27 @@ object JNIDeallocator {
23
26
  * A thread that clears your registry when an object has been garbage collected
24
27
  * to not store invalid references to every created object.
25
28
  */
26
- private val destructorThread = object : Thread("Expo JNI deallocator") {
27
- override fun run() {
28
- while (true) {
29
- try {
30
- // Referent of PhantomReference were garbage collected so we can remove it from our registry.
31
- // Note that we don't have to call `deallocate` method - it was called [com.facebook.jni.HybridData].
32
- val current = referenceQueue.remove()
33
- synchronized(this) {
34
- destructorMap.remove(current)
29
+ private val destructorThread = if (shouldCreateDestructorThread) {
30
+ object : Thread("Expo JNI deallocator") {
31
+ override fun run() {
32
+ while (!isInterrupted) {
33
+ try {
34
+ // Referent of PhantomReference were garbage collected so we can remove it from our registry.
35
+ // Note that we don't have to call `deallocate` method - it was called [com.facebook.jni.HybridData].
36
+ val current = referenceQueue.remove()
37
+ synchronized(this) {
38
+ destructorMap.remove(current)
39
+ }
40
+ } catch (e: InterruptedException) {
41
+ return
35
42
  }
36
- } catch (e: InterruptedException) {
37
- // Continue. This thread should never be terminated.
38
43
  }
39
44
  }
45
+ }.also {
46
+ it.start()
40
47
  }
41
- }.also {
42
- it.start()
48
+ } else {
49
+ null
43
50
  }
44
51
 
45
52
  /**
@@ -47,7 +54,8 @@ object JNIDeallocator {
47
54
  * That reference will be deallocated when [JNIDeallocator.deallocate] is called or
48
55
  * when the reference won't be reachable by the GC.
49
56
  */
50
- internal fun addReference(destructible: Destructible) = synchronized(this) {
57
+ @DoNotStrip
58
+ fun addReference(destructible: Destructible): Unit = synchronized(this) {
51
59
  val weakRef = WeakReference(destructible)
52
60
  val phantomRef = PhantomReference(destructible, referenceQueue)
53
61
  destructorMap[phantomRef] = weakRef
@@ -61,6 +69,7 @@ object JNIDeallocator {
61
69
  it.get()?.deallocate()
62
70
  }
63
71
  destructorMap.clear()
72
+ destructorThread?.interrupt()
64
73
  }
65
74
 
66
75
  /**
@@ -31,6 +31,7 @@ class JSIInteropModuleRegistry(appContext: AppContext) : Destructible {
31
31
  */
32
32
  external fun installJSI(
33
33
  jsRuntimePointer: Long,
34
+ jniDeallocator: JNIDeallocator,
34
35
  jsInvokerHolder: CallInvokerHolderImpl,
35
36
  nativeInvokerHolder: CallInvokerHolderImpl
36
37
  )
@@ -38,7 +39,13 @@ class JSIInteropModuleRegistry(appContext: AppContext) : Destructible {
38
39
  /**
39
40
  * Initializes the test runtime. Shouldn't be used in the production.
40
41
  */
41
- external fun installJSIForTests()
42
+ external fun installJSIForTests(
43
+ jniDeallocator: JNIDeallocator,
44
+ )
45
+
46
+ fun installJSIForTests() = installJSIForTests(
47
+ JNIDeallocator(shouldCreateDestructorThread = false)
48
+ )
42
49
 
43
50
  /**
44
51
  * Evaluates given JavaScript source code.
@@ -9,10 +9,6 @@ import expo.modules.kotlin.exception.UnexpectedException
9
9
  @Suppress("KotlinJniMissingFunction")
10
10
  @DoNotStrip
11
11
  class JavaCallback @DoNotStrip internal constructor(@DoNotStrip private val mHybridData: HybridData) : Destructible {
12
- init {
13
- JNIDeallocator.addReference(this)
14
- }
15
-
16
12
  operator fun invoke(result: Any?) {
17
13
  if (result == null) {
18
14
  invoke()
@@ -11,10 +11,6 @@ import kotlin.reflect.typeOf
11
11
  @Suppress("KotlinJniMissingFunction")
12
12
  @DoNotStrip
13
13
  class JavaScriptFunction<ReturnType : Any?> @DoNotStrip private constructor(@DoNotStrip private val mHybridData: HybridData) : Destructible {
14
- init {
15
- JNIDeallocator.addReference(this)
16
- }
17
-
18
14
  @PublishedApi
19
15
  internal var returnType: KType? = null
20
16
 
@@ -16,7 +16,10 @@ import expo.modules.kotlin.objects.ObjectDefinitionData
16
16
  */
17
17
  @Suppress("KotlinJniMissingFunction")
18
18
  @DoNotStrip
19
- class JavaScriptModuleObject(val name: String) : Destructible {
19
+ class JavaScriptModuleObject(
20
+ jniDeallocator: JNIDeallocator,
21
+ val name: String
22
+ ) : Destructible {
20
23
  // Has to be called "mHybridData" - fbjni uses it via reflection
21
24
  @DoNotStrip
22
25
  private val mHybridData = initHybrid()
@@ -24,7 +27,7 @@ class JavaScriptModuleObject(val name: String) : Destructible {
24
27
  private external fun initHybrid(): HybridData
25
28
 
26
29
  init {
27
- JNIDeallocator.addReference(this)
30
+ jniDeallocator.addReference(this)
28
31
  }
29
32
 
30
33
  fun initUsingObjectDefinition(appContext: AppContext, definition: ObjectDefinitionData) = apply {
@@ -10,11 +10,6 @@ import expo.modules.core.interfaces.DoNotStrip
10
10
  @Suppress("KotlinJniMissingFunction")
11
11
  @DoNotStrip
12
12
  open class JavaScriptObject @DoNotStrip internal constructor(@DoNotStrip private val mHybridData: HybridData) : Destructible {
13
- init {
14
- @Suppress("LeakingThis")
15
- JNIDeallocator.addReference(this)
16
- }
17
-
18
13
  /**
19
14
  * The property descriptor options for the property being defined or modified.
20
15
  */
@@ -11,10 +11,6 @@ import kotlin.reflect.typeOf
11
11
  @Suppress("KotlinJniMissingFunction")
12
12
  @DoNotStrip
13
13
  class JavaScriptValue @DoNotStrip private constructor(@DoNotStrip private val mHybridData: HybridData) : Destructible {
14
- init {
15
- JNIDeallocator.addReference(this)
16
- }
17
-
18
14
  fun isValid() = mHybridData.isValid
19
15
  external fun kind(): String
20
16
 
@@ -361,7 +361,7 @@ inline fun ModuleDefinitionBuilder.Object(block: ObjectDefinitionBuilder.() -> U
361
361
 
362
362
  inline fun Module.Object(block: ObjectDefinitionBuilder.() -> Unit): JavaScriptModuleObject {
363
363
  val objectData = ObjectDefinitionBuilder().also(block).buildObject()
364
- return JavaScriptModuleObject("[Anonymous Object]")
364
+ return JavaScriptModuleObject(appContext.jniDeallocator, "[Anonymous Object]")
365
365
  .apply {
366
366
  val constants = objectData.constantsProvider()
367
367
  val convertedConstants = Arguments.makeNativeMap(constants)
@@ -1,6 +1,8 @@
1
1
  package expo.modules.kotlin.types
2
2
 
3
3
  import android.graphics.Color
4
+ import android.os.Build
5
+ import androidx.annotation.RequiresApi
4
6
  import com.facebook.react.bridge.Dynamic
5
7
  import com.facebook.react.bridge.ReadableType
6
8
  import expo.modules.kotlin.exception.UnexpectedException
@@ -166,6 +168,7 @@ private val namedColors = mapOf(
166
168
  value.map { it.toFloat() / 255f }
167
169
  }
168
170
 
171
+ @RequiresApi(Build.VERSION_CODES.O)
169
172
  class ColorTypeConverter(
170
173
  isOptional: Boolean
171
174
  ) : DynamicAwareTypeConverters<Color>(isOptional) {
@@ -272,8 +272,6 @@ object TypeConverterProviderImpl : TypeConverterProvider {
272
272
  BigUint64Array::class.createType(nullable = isOptional) to BigUint64ArrayTypeConverter(isOptional),
273
273
  TypedArray::class.createType(nullable = isOptional) to TypedArrayTypeConverter(isOptional),
274
274
 
275
- Color::class.createType(nullable = isOptional) to ColorTypeConverter(isOptional),
276
-
277
275
  URL::class.createType(nullable = isOptional) to URLTypConverter(isOptional),
278
276
  Uri::class.createType(nullable = isOptional) to UriTypeConverter(isOptional),
279
277
  URI::class.createType(nullable = isOptional) to JavaURITypeConverter(isOptional),
@@ -286,6 +284,7 @@ object TypeConverterProviderImpl : TypeConverterProvider {
286
284
  if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
287
285
  return converters + mapOf(
288
286
  Path::class.createType(nullable = isOptional) to PathTypeConverter(isOptional),
287
+ Color::class.createType(nullable = isOptional) to ColorTypeConverter(isOptional),
289
288
  )
290
289
  }
291
290
 
@@ -36,8 +36,8 @@ buildscript {
36
36
  }
37
37
 
38
38
  java {
39
- sourceCompatibility = JavaVersion.VERSION_1_8
40
- targetCompatibility = JavaVersion.VERSION_1_8
39
+ sourceCompatibility = JavaVersion.VERSION_11
40
+ targetCompatibility = JavaVersion.VERSION_11
41
41
  }
42
42
 
43
43
  dependencies {
@@ -36,8 +36,8 @@ buildscript {
36
36
  }
37
37
 
38
38
  java {
39
- sourceCompatibility = JavaVersion.VERSION_1_8
40
- targetCompatibility = JavaVersion.VERSION_1_8
39
+ sourceCompatibility = JavaVersion.VERSION_11
40
+ targetCompatibility = JavaVersion.VERSION_11
41
41
  }
42
42
 
43
43
  dependencies {
@@ -4,7 +4,7 @@
4
4
 
5
5
  // Swift classes need forward-declaration in the headers.
6
6
  @class EXAppContext;
7
- @class EXJavaScriptRuntime;
7
+ @class ExpoRuntime;
8
8
 
9
9
  @interface EXJavaScriptRuntimeManager : NSObject
10
10
 
@@ -12,7 +12,7 @@
12
12
  Gets the JS runtime from the given bridge. May return `nil` when
13
13
  the runtime is not available yet or the remote debugging is enabled.
14
14
  */
15
- + (nullable EXJavaScriptRuntime *)runtimeFromBridge:(nonnull RCTBridge *)bridge NS_SWIFT_NAME(runtime(fromBridge:));
15
+ + (nullable ExpoRuntime *)runtimeFromBridge:(nonnull RCTBridge *)bridge NS_SWIFT_NAME(runtime(fromBridge:));
16
16
 
17
17
  /**
18
18
  Installs ExpoModules host object in the runtime of the given app context.
@@ -27,15 +27,15 @@ static NSString *modulesHostObjectLegacyPropertyName = @"ExpoModules";
27
27
 
28
28
  @implementation EXJavaScriptRuntimeManager
29
29
 
30
- + (nullable EXJavaScriptRuntime *)runtimeFromBridge:(nonnull RCTBridge *)bridge
30
+ + (nullable ExpoRuntime *)runtimeFromBridge:(nonnull RCTBridge *)bridge
31
31
  {
32
32
  jsi::Runtime *jsiRuntime = [bridge respondsToSelector:@selector(runtime)] ? reinterpret_cast<jsi::Runtime *>(bridge.runtime) : nullptr;
33
- return jsiRuntime ? [[EXJavaScriptRuntime alloc] initWithRuntime:jsiRuntime callInvoker:bridge.jsCallInvoker] : nil;
33
+ return jsiRuntime ? [[ExpoRuntime alloc] initWithRuntime:jsiRuntime callInvoker:bridge.jsCallInvoker] : nil;
34
34
  }
35
35
 
36
36
  + (BOOL)installExpoModulesHostObject:(nonnull EXAppContext *)appContext
37
37
  {
38
- EXJavaScriptRuntime *runtime = [appContext _runtime];
38
+ ExpoRuntime *runtime = [appContext _runtime];
39
39
 
40
40
  // The runtime may be unavailable, e.g. remote debugger is enabled or it hasn't been set yet.
41
41
  if (!runtime) {
@@ -43,9 +43,9 @@ static NSString *modulesHostObjectLegacyPropertyName = @"ExpoModules";
43
43
  }
44
44
 
45
45
  EXJavaScriptObject *global = [runtime global];
46
- EXJavaScriptObject *mainObject = [runtime mainObject];
46
+ EXJavaScriptObject *coreObject = [runtime coreObject];
47
47
 
48
- if ([mainObject hasProperty:modulesHostObjectPropertyName]) {
48
+ if ([coreObject hasProperty:modulesHostObjectPropertyName]) {
49
49
  return false;
50
50
  }
51
51
 
@@ -53,7 +53,7 @@ static NSString *modulesHostObjectLegacyPropertyName = @"ExpoModules";
53
53
  EXJavaScriptObject *modulesHostObject = [runtime createHostObject:modulesHostObjectPtr];
54
54
 
55
55
  // Define the `global.expo.modules` object as a non-configurable, read-only and enumerable property.
56
- [mainObject defineProperty:modulesHostObjectPropertyName
56
+ [coreObject defineProperty:modulesHostObjectPropertyName
57
57
  value:modulesHostObject
58
58
  options:EXJavaScriptObjectPropertyDescriptorEnumerable];
59
59
 
@@ -66,12 +66,6 @@ NS_SWIFT_NAME(JavaScriptRuntime)
66
66
  */
67
67
  - (nonnull EXJavaScriptObject *)global;
68
68
 
69
- /**
70
- The main object of the Expo runtime that is used to scope native Expo-specific functionalities.
71
- It gets installed into the runtime as the `global.expo` object.
72
- */
73
- - (nonnull EXJavaScriptObject *)mainObject;
74
-
75
69
  /**
76
70
  Creates a new object for use in Swift.
77
71
  */
@@ -20,16 +20,9 @@
20
20
  #import <ExpoModulesCore/EXJSIConversions.h>
21
21
  #import <ExpoModulesCore/Swift.h>
22
22
 
23
-
24
- /**
25
- Property name of the main object in the Expo JS runtime.
26
- */
27
- static NSString *mainObjectPropertyName = @"expo";
28
-
29
23
  @implementation EXJavaScriptRuntime {
30
24
  std::shared_ptr<jsi::Runtime> _runtime;
31
25
  std::shared_ptr<react::CallInvoker> _jsCallInvoker;
32
- EXJavaScriptObject *_mainObject;
33
26
  }
34
27
 
35
28
  /**
@@ -46,7 +39,6 @@ static NSString *mainObjectPropertyName = @"expo";
46
39
  _runtime = jsc::makeJSCRuntime();
47
40
  #endif
48
41
  _jsCallInvoker = nil;
49
- [self initializeMainObject];
50
42
  }
51
43
  return self;
52
44
  }
@@ -60,7 +52,6 @@ static NSString *mainObjectPropertyName = @"expo";
60
52
  // See explanation for constructor (8): https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr
61
53
  _runtime = std::shared_ptr<jsi::Runtime>(std::shared_ptr<jsi::Runtime>(), runtime);
62
54
  _jsCallInvoker = callInvoker;
63
- [self initializeMainObject];
64
55
  }
65
56
  return self;
66
57
  }
@@ -93,11 +84,6 @@ static NSString *mainObjectPropertyName = @"expo";
93
84
  return [[EXJavaScriptObject alloc] initWith:jsGlobalPtr runtime:self];
94
85
  }
95
86
 
96
- - (nonnull EXJavaScriptObject *)mainObject
97
- {
98
- return _mainObject;
99
- }
100
-
101
87
  - (nonnull EXJavaScriptObject *)createSyncFunction:(nonnull NSString *)name
102
88
  argsCount:(NSInteger)argsCount
103
89
  block:(nonnull JSSyncFunctionBlock)block
@@ -195,15 +181,6 @@ static NSString *mainObjectPropertyName = @"expo";
195
181
 
196
182
  #pragma mark - Private
197
183
 
198
- - (void)initializeMainObject
199
- {
200
- if (!_mainObject) {
201
- // Add the main object to the runtime (`global.expo`).
202
- _mainObject = [self createObject];
203
- [[self global] defineProperty:mainObjectPropertyName value:_mainObject options:EXJavaScriptObjectPropertyDescriptorEnumerable];
204
- }
205
- }
206
-
207
184
  - (nonnull EXJavaScriptObject *)createHostFunction:(nonnull NSString *)name
208
185
  argsCount:(NSInteger)argsCount
209
186
  block:(nonnull JSHostFunctionBlock)block
@@ -10,3 +10,20 @@ typedef void (^RCTPropBlockAlias)(id<RCTComponent> _Nonnull view, id _Nullable j
10
10
  - (nonnull RCTPropBlockAlias)createPropBlock:(nonnull NSString *)name isShadowView:(BOOL)isShadowView;
11
11
 
12
12
  @end
13
+
14
+ /**
15
+ This is a compatible adapter for Swift `ComponentData` to access react-native's `RCTComponentData`.
16
+ When running in react-native new architecture mode, the `eventDispatcher` is actually null.
17
+ however the`RCTComponentData` still expects it's nonnull because of the `NS_ASSUME_NONNULL_BEGIN`
18
+ https://github.com/facebook/react-native/blob/ea4724b37c9f78bd33daab547d6cc4f8b7f7dd81/packages/react-native/React/Views/RCTComponentData.h#L19-L35.
19
+ Swift will have a runtime exception from the implicitly unwrapping.
20
+ This compatible adapter basically allows the `eventDispatcher` to be nullable.
21
+ TODO: We should propose the fix to upstream and remove this adapter when dropping SDK 49.
22
+ */
23
+ @interface RCTComponentDataSwiftAdapter : RCTComponentData
24
+
25
+ - (nonnull instancetype)initWithManagerClass:(nonnull Class)managerClass
26
+ bridge:(nonnull RCTBridge *)bridge
27
+ eventDispatcher:(nullable id<RCTEventDispatcherProtocol>)eventDispatcher;
28
+
29
+ @end
@@ -0,0 +1,15 @@
1
+ // Copyright 2021-present 650 Industries. All rights reserved.
2
+
3
+ #import <ExpoModulesCore/RCTComponentData+Privates.h>
4
+ #import <React/RCTComponentData.h>
5
+
6
+ @implementation RCTComponentDataSwiftAdapter
7
+
8
+ - (nonnull instancetype)initWithManagerClass:(nonnull Class)managerClass
9
+ bridge:(nonnull RCTBridge *)bridge
10
+ eventDispatcher:(nullable id<RCTEventDispatcherProtocol>)eventDispatcher
11
+ {
12
+ return [super initWithManagerClass:managerClass bridge:bridge eventDispatcher:nil];
13
+ }
14
+
15
+ @end