Refactor ReactAndroid to use buildReadableMap, buildReadableArray DSL (#51145)

Summary:
This PR refactors the entire ReactAndroid package to replace manual `Arguments.createMap()…` and `Arguments.createArray()…` calls with the new Kotlin DSL helpers `buildReadableMap { … }` and `buildReadableArray { … }`. All eligible call sites have been migrated to the DSL, except in functions whose signatures explicitly declare or return WritableMap or WritableArray.

No runtime behavior changes are introduced; existing functionality and tests continue to pass unchanged.

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[ANDROID] [CHANGED] Apply Collections DSL on ReactAndroid package

Pull Request resolved: https://github.com/facebook/react-native/pull/51145

Test Plan:
```
yarn android
yarn test-android
```

Reviewed By: rshest

Differential Revision: D74401357

Pulled By: cortinico

fbshipit-source-id: 0f7b7dfbb7b495675bc4730bdf018666e9041884
This commit is contained in:
HyunWoo Lee
2025-05-12 16:35:07 -07:00
committed by Facebook GitHub Bot
parent d362e496eb
commit b2ffd34a39
19 changed files with 289 additions and 235 deletions
@@ -1353,6 +1353,8 @@ public final class com/facebook/react/bridge/ReadableArrayBuilder {
public final fun add (D)V
public final fun add (I)V
public final fun add (J)V
public final fun add (Lcom/facebook/react/bridge/ReadableArray;)V
public final fun add (Lcom/facebook/react/bridge/ReadableMap;)V
public final fun add (Ljava/lang/String;)V
public final fun add (Z)V
public final fun addArray (Lkotlin/jvm/functions/Function1;)V
@@ -1386,6 +1388,8 @@ public final class com/facebook/react/bridge/ReadableMapBuilder {
public final fun put (Ljava/lang/String;D)V
public final fun put (Ljava/lang/String;I)V
public final fun put (Ljava/lang/String;J)V
public final fun put (Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;)V
public final fun put (Ljava/lang/String;Lcom/facebook/react/bridge/ReadableMap;)V
public final fun put (Ljava/lang/String;Ljava/lang/String;)V
public final fun put (Ljava/lang/String;Z)V
public final fun putArray (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
@@ -11,7 +11,6 @@ import androidx.annotation.AnyThread
import androidx.annotation.UiThread
import com.facebook.common.logging.FLog
import com.facebook.fbreact.specs.NativeAnimatedModuleSpec
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.Callback
import com.facebook.react.bridge.LifecycleEventListener
import com.facebook.react.bridge.ReactApplicationContext
@@ -20,6 +19,7 @@ import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.UIManager
import com.facebook.react.bridge.UIManagerListener
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.common.annotations.VisibleForTesting
import com.facebook.react.common.build.ReactBuildConfig
@@ -230,14 +230,8 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext?) :
return
}
val tagsArray = Arguments.createArray()
for (tag in tags) {
tagsArray.pushInt(tag)
}
// emit the event to JS to resync the trees
val onAnimationEndedData = Arguments.createMap()
onAnimationEndedData.putArray("tags", tagsArray)
val onAnimationEndedData = buildReadableMap { putArray("tags") { tags.forEach { add(it) } } }
val reactApplicationContext = reactApplicationContextIfActiveOrWarn
reactApplicationContext?.emitDeviceEvent("onUserDrivenAnimationEnded", onAnimationEndedData)
@@ -543,10 +537,11 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext?) :
}
val listener = AnimatedNodeValueListener { value, offset ->
val onAnimatedValueData = Arguments.createMap()
onAnimatedValueData.putInt("tag", tag)
onAnimatedValueData.putDouble("value", value)
onAnimatedValueData.putDouble("offset", offset)
val onAnimatedValueData = buildReadableMap {
put("tag", tag)
put("value", value)
put("offset", offset)
}
val reactApplicationContext = reactApplicationContextIfActiveOrWarn
reactApplicationContext?.emitDeviceEvent("onAnimatedValueUpdate", onAnimatedValueData)
@@ -978,10 +973,11 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext?) :
BatchExecutionOpCodes.OP_START_LISTENING_TO_ANIMATED_NODE_VALUE -> {
val tag = opsAndArgs.getInt(i++)
val listener = AnimatedNodeValueListener { value, offset ->
val onAnimatedValueData = Arguments.createMap()
onAnimatedValueData.putInt("tag", tag)
onAnimatedValueData.putDouble("value", value)
onAnimatedValueData.putDouble("offset", offset)
val onAnimatedValueData = buildReadableMap {
put("tag", tag)
put("value", value)
put("offset", offset)
}
val reactApplicationContext = reactApplicationContextIfActiveOrWarn
reactApplicationContext?.emitDeviceEvent(
@@ -20,6 +20,7 @@ import com.facebook.react.bridge.ReactSoftExceptionLogger
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.bridge.WritableArray
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.uimanager.UIManagerHelper
import com.facebook.react.uimanager.common.UIManagerType
import com.facebook.react.uimanager.events.Event
@@ -269,20 +270,22 @@ public class NativeAnimatedNodesManager(
val animatedValueNonnull = checkNotNull(animation.animatedValue)
if (animation.endCallback != null) {
// Invoke animation end callback with {finished: false}
val endCallbackResponse = Arguments.createMap()
endCallbackResponse.putBoolean("finished", false)
endCallbackResponse.putDouble("value", animatedValueNonnull.nodeValue)
endCallbackResponse.putDouble("offset", animatedValueNonnull.offset)
val endCallbackResponse = buildReadableMap {
put("finished", false)
put("value", animatedValueNonnull.nodeValue)
put("offset", animatedValueNonnull.offset)
}
animation.endCallback?.invoke(endCallbackResponse)
} else if (reactApplicationContext != null) {
// If no callback is passed in, this /may/ be an animation set up by the single-op
// instruction from JS, meaning that no jsi::functions are passed into native and
// we communicate via RCTDeviceEventEmitter instead of callbacks.
val params = Arguments.createMap()
params.putInt("animationId", animation.id)
params.putBoolean("finished", false)
params.putDouble("value", animatedValueNonnull.nodeValue)
params.putDouble("offset", animatedValueNonnull.offset)
val params = buildReadableMap {
put("animationId", animation.id)
put("finished", false)
put("value", animatedValueNonnull.nodeValue)
put("offset", animatedValueNonnull.offset)
}
events = events ?: Arguments.createArray()
events.pushMap(params)
}
@@ -308,20 +311,22 @@ public class NativeAnimatedNodesManager(
if (animation.id == animationId) {
if (animation.endCallback != null) {
// Invoke animation end callback with {finished: false}
val endCallbackResponse = Arguments.createMap()
endCallbackResponse.putBoolean("finished", false)
endCallbackResponse.putDouble("value", checkNotNull(animation.animatedValue).nodeValue)
endCallbackResponse.putDouble("offset", checkNotNull(animation.animatedValue).offset)
val endCallbackResponse = buildReadableMap {
put("finished", false)
put("value", checkNotNull(animation.animatedValue).nodeValue)
put("offset", checkNotNull(animation.animatedValue).offset)
}
checkNotNull(animation.endCallback).invoke(endCallbackResponse)
} else if (reactApplicationContext != null) {
// If no callback is passed in, this /may/ be an animation set up by the single-op
// instruction from JS, meaning that no jsi::functions are passed into native and
// we communicate via RCTDeviceEventEmitter instead of callbacks.
val params = Arguments.createMap()
params.putInt("animationId", animation.id)
params.putBoolean("finished", false)
params.putDouble("value", checkNotNull(animation.animatedValue).nodeValue)
params.putDouble("offset", checkNotNull(animation.animatedValue).offset)
val params = buildReadableMap {
put("animationId", animation.id)
put("finished", false)
put("value", checkNotNull(animation.animatedValue).nodeValue)
put("offset", checkNotNull(animation.animatedValue).offset)
}
events = events ?: Arguments.createArray()
events.pushMap(params)
}
@@ -425,9 +430,10 @@ public class NativeAnimatedNodesManager(
if (reactApplicationContext == null) {
return
}
val params = Arguments.createMap()
params.putInt("tag", tag)
params.putDouble("value", value)
val params = buildReadableMap {
put("tag", tag)
put("value", value)
}
reactApplicationContext.emitDeviceEvent("onNativeAnimatedModuleGetValue", params)
}
@@ -579,20 +585,22 @@ public class NativeAnimatedNodesManager(
if (animation.hasFinished) {
val animatedValueNonnull = checkNotNull(animation.animatedValue)
if (animation.endCallback != null) {
val endCallbackResponse = Arguments.createMap()
endCallbackResponse.putBoolean("finished", true)
endCallbackResponse.putDouble("value", animatedValueNonnull.nodeValue)
endCallbackResponse.putDouble("offset", animatedValueNonnull.offset)
val endCallbackResponse = buildReadableMap {
put("finished", true)
put("value", animatedValueNonnull.nodeValue)
put("offset", animatedValueNonnull.offset)
}
animation.endCallback?.invoke(endCallbackResponse)
} else if (reactApplicationContext != null) {
// If no callback is passed in, this /may/ be an animation set up by the single-op
// instruction from JS, meaning that no jsi::functions are passed into native and
// we communicate via RCTDeviceEventEmitter instead of callbacks.
val params = Arguments.createMap()
params.putInt("animationId", animation.id)
params.putBoolean("finished", true)
params.putDouble("value", animatedValueNonnull.nodeValue)
params.putDouble("offset", animatedValueNonnull.offset)
val params = buildReadableMap {
put("animationId", animation.id)
put("finished", true)
put("value", animatedValueNonnull.nodeValue)
put("offset", animatedValueNonnull.offset)
}
events = events ?: Arguments.createArray()
events.pushMap(params)
}
@@ -31,27 +31,28 @@ public object JSONArguments {
@JvmStatic
@Throws(JSONException::class)
public fun fromJSONObject(obj: JSONObject): ReadableMap {
val result: WritableMap = Arguments.createMap()
val keys = obj.keys()
while (keys.hasNext()) {
val key = keys.next()
val value = obj.get(key)
val result = buildReadableMap {
while (keys.hasNext()) {
val key = keys.next()
val value = obj.get(key)
when (value) {
is JSONObject -> result.putMap(key, fromJSONObject(value))
is JSONArray -> result.putArray(key, fromJSONArray(value))
is String -> result.putString(key, value)
is Boolean -> result.putBoolean(key, value)
is Int -> result.putInt(key, value)
is Double -> result.putDouble(key, value)
is Long -> result.putInt(key, value.toInt())
else ->
if (obj.isNull(key)) {
result.putNull(key)
} else {
throw JSONException("Unexpected value when parsing JSON object. key: $key")
}
when (value) {
is JSONObject -> put(key, fromJSONObject(value))
is JSONArray -> put(key, fromJSONArray(value))
is String -> put(key, value)
is Boolean -> put(key, value)
is Int -> put(key, value)
is Double -> put(key, value)
is Long -> put(key, value.toInt())
else ->
if (obj.isNull(key)) {
putNull(key)
} else {
throw JSONException("Unexpected value when parsing JSON object. key: $key")
}
}
}
}
@@ -79,25 +80,25 @@ public object JSONArguments {
@JvmStatic
@Throws(JSONException::class)
public fun fromJSONArray(arr: JSONArray): ReadableArray {
val result: WritableArray = Arguments.createArray()
val result = buildReadableArray {
repeat(arr.length()) {
val value = arr.get(it)
for (i in 0 until arr.length()) {
val value = arr.get(i)
when (value) {
is JSONObject -> result.pushMap(fromJSONObject(value))
is JSONArray -> result.pushArray(fromJSONArray(value))
is String -> result.pushString(value)
is Boolean -> result.pushBoolean(value)
is Int -> result.pushInt(value)
is Double -> result.pushDouble(value)
is Long -> result.pushInt(value.toInt())
else ->
if (arr.isNull(i)) {
result.pushNull()
} else {
throw JSONException("Unexpected value when parsing JSON array. index: $i")
}
when (value) {
is JSONObject -> add(fromJSONObject(value))
is JSONArray -> add(fromJSONArray(value))
is String -> add(value)
is Boolean -> add(value)
is Int -> add(value)
is Double -> add(value)
is Long -> add(value.toInt())
else ->
if (arr.isNull(it)) {
addNull()
} else {
throw JSONException("Unexpected value when parsing JSON array. index: $it")
}
}
}
}
@@ -47,6 +47,14 @@ public class ReadableArrayBuilder(private val array: WritableArray) {
array.pushDouble(value.toDouble())
}
public fun add(value: ReadableMap) {
array.pushMap(value)
}
public fun add(value: ReadableArray) {
array.pushArray(value)
}
public fun addNull() {
array.pushNull()
}
@@ -11,13 +11,19 @@ package com.facebook.react.bridge
* Convenience class for building a [ReadableMap] in a Kotlin idiomatic way. You can use it as
* follows:
* ```
* val array: ReadableArray = buildReadableArray {
* add("one")
* add(2)
* add(true)
* addNull()
* addMap { put("nestedKey", "nestedValue") }
* }
* val map: ReadableMap = buildReadableMap {
* put("first", "one")
* put("second", 2)
* put("third", true)
* putNull("fourth")
* putMap("fifth") {
* put("nestedKey", "nestedValue")
* }
* putArray("sixth") {
* add(1)
* add("2")
* }
* }
* ```
*/
public inline fun buildReadableMap(builder: ReadableMapBuilder.() -> Unit): ReadableMap {
@@ -51,6 +57,14 @@ public class ReadableMapBuilder(private val map: WritableMap) {
map.putNull(key)
}
public fun put(key: String, value: ReadableMap) {
map.putMap(key, value)
}
public fun put(key: String, value: ReadableArray) {
map.putArray(key, value)
}
public fun putMap(key: String, builder: ReadableMapBuilder.() -> Unit) {
map.putMap(key, buildReadableMap(builder))
}
@@ -11,9 +11,9 @@ import android.content.Context
import android.content.res.Configuration
import androidx.appcompat.app.AppCompatDelegate
import com.facebook.fbreact.specs.NativeAppearanceSpec
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.module.annotations.ReactModule
/** Module that exposes the user's preferred color scheme. */
@@ -89,8 +89,7 @@ constructor(
/** Sends an event to the JS instance that the preferred color scheme has changed. */
public fun emitAppearanceChanged(colorScheme: String) {
val appearancePreferences = Arguments.createMap()
appearancePreferences.putString("colorScheme", colorScheme)
val appearancePreferences = buildReadableMap { put("colorScheme", colorScheme) }
val reactApplicationContext = getReactApplicationContextIfActiveOrWarn()
reactApplicationContext?.emitDeviceEvent(APPEARANCE_CHANGED_EVENT_NAME, appearancePreferences)
}
@@ -19,6 +19,7 @@ import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.modules.network.NetworkingModule
import com.facebook.react.modules.websocket.WebSocketModule
@@ -52,10 +53,11 @@ public class BlobModule(reactContext: ReactApplicationContext) :
override fun onMessage(byteString: ByteString, params: WritableMap) {
val data = byteString.toByteArray()
val blob = Arguments.createMap()
blob.putString("blobId", store(data))
blob.putInt("offset", 0)
blob.putInt("size", data.size)
val blob = buildReadableMap {
put("blobId", store(data))
put("offset", 0)
put("size", data.size)
}
params.putMap("data", blob)
params.putString("type", "blob")
@@ -10,10 +10,10 @@ package com.facebook.react.modules.core
import android.net.Uri
import com.facebook.fbreact.specs.NativeDeviceEventManagerSpec
import com.facebook.proguard.annotations.DoNotStripAny
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.JavaScriptModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.module.annotations.ReactModule
/** Native module that handles device hardware events like hardware back presses. */
@@ -43,8 +43,7 @@ public open class DeviceEventManagerModule(
public open fun emitNewIntentReceived(uri: Uri) {
val reactApplicationContext: ReactApplicationContext? =
getReactApplicationContextIfActiveOrWarn()
val map = Arguments.createMap()
map.putString("url", uri.toString())
val map = buildReadableMap { put("url", uri.toString()) }
reactApplicationContext?.emitDeviceEvent("url", map)
}
@@ -8,9 +8,9 @@
package com.facebook.react.modules.debug
import com.facebook.fbreact.specs.NativeDevSettingsSpec
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.devsupport.interfaces.DevSupportManager
import com.facebook.react.module.annotations.ReactModule
@@ -50,8 +50,7 @@ public class DevSettingsModule(
override fun addMenuItem(title: String) {
devSupportManager.addCustomDevOption(title) {
val data = Arguments.createMap()
data.putString("title", title)
val data = buildReadableMap { put("title", title) }
val reactApplicationContext = reactApplicationContextIfActiveOrWarn
reactApplicationContext?.emitDeviceEvent("didPressMenuItem", data)
}
@@ -20,7 +20,6 @@ import com.facebook.imagepipeline.core.ImagePipeline
import com.facebook.imagepipeline.image.CloseableImage
import com.facebook.imagepipeline.request.ImageRequest
import com.facebook.imagepipeline.request.ImageRequestBuilder
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.GuardedAsyncTask
import com.facebook.react.bridge.LifecycleEventListener
import com.facebook.react.bridge.Promise
@@ -28,7 +27,7 @@ import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.modules.fresco.ReactNetworkImageRequest
import com.facebook.react.views.image.ReactCallerContextFactory
@@ -96,9 +95,10 @@ internal class ImageLoaderModule : NativeImageLoaderAndroidSpec, LifecycleEventL
if (ref != null) {
try {
val image: CloseableImage = ref.get()
val sizes: WritableMap = Arguments.createMap()
sizes.putInt("width", image.width)
sizes.putInt("height", image.height)
val sizes = buildReadableMap {
put("width", image.width)
put("height", image.height)
}
promise.resolve(sizes)
} catch (e: Exception) {
promise.reject(ERROR_GET_SIZE_FAILURE, e)
@@ -131,7 +131,7 @@ internal class ImageLoaderModule : NativeImageLoaderAndroidSpec, LifecycleEventL
promise.reject(ERROR_INVALID_URI, "Cannot get the size of an image for an empty URI")
return
}
val source = ImageSource(getReactApplicationContext(), uriString)
val source = ImageSource(reactApplicationContext, uriString)
val imageRequestBuilder: ImageRequestBuilder =
ImageRequestBuilder.newBuilderWithSource(source.uri)
val request: ImageRequest =
@@ -148,9 +148,10 @@ internal class ImageLoaderModule : NativeImageLoaderAndroidSpec, LifecycleEventL
if (ref != null) {
try {
val image: CloseableImage = ref.get()
val sizes: WritableMap = Arguments.createMap()
sizes.putInt("width", image.width)
sizes.putInt("height", image.height)
val sizes = buildReadableMap {
put("width", image.width)
put("height", image.height)
}
promise.resolve(sizes)
} catch (e: Exception) {
promise.reject(ERROR_GET_SIZE_FAILURE, e)
@@ -227,16 +228,17 @@ internal class ImageLoaderModule : NativeImageLoaderAndroidSpec, LifecycleEventL
@Suppress("DEPRECATION", "StaticFieldLeak")
object : GuardedAsyncTask<Void, Void>(getReactApplicationContext()) {
override fun doInBackgroundGuarded(vararg params: Void) {
val result: WritableMap = Arguments.createMap()
val imagePipeline: ImagePipeline = this@ImageLoaderModule.imagePipeline
for (i in 0 until uris.size()) {
val uriString = uris.getString(i)
if (!uriString.isNullOrEmpty()) {
val uri = Uri.parse(uriString)
if (imagePipeline.isInBitmapMemoryCache(uri)) {
result.putString(uriString, "memory")
} else if (imagePipeline.isInDiskCacheSync(uri)) {
result.putString(uriString, "disk")
val result = buildReadableMap {
val imagePipeline: ImagePipeline = this@ImageLoaderModule.imagePipeline
repeat(uris.size()) {
val uriString = uris.getString(it)
if (!uriString.isNullOrEmpty()) {
val uri = Uri.parse(uriString)
if (imagePipeline.isInBitmapMemoryCache(uri)) {
put(uriString, "memory")
} else if (imagePipeline.isInDiskCacheSync(uri)) {
put(uriString, "disk")
}
}
}
}
@@ -10,6 +10,7 @@ package com.facebook.react.modules.network
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.buildReadableArray
import java.net.SocketTimeoutException
/** Util methods to send network responses to JS. */
@@ -23,10 +24,10 @@ internal object ResponseUtil {
) {
reactContext?.emitDeviceEvent(
"didSendNetworkData",
Arguments.createArray().apply {
pushInt(requestId)
pushInt(progress.toInt())
pushInt(total.toInt())
buildReadableArray {
add(requestId)
add(progress.toInt())
add(total.toInt())
})
}
@@ -40,11 +41,11 @@ internal object ResponseUtil {
) {
reactContext?.emitDeviceEvent(
"didReceiveNetworkIncrementalData",
Arguments.createArray().apply {
pushInt(requestId)
pushString(data)
pushInt(progress.toInt())
pushInt(total.toInt())
buildReadableArray {
add(requestId)
add(data)
add(progress.toInt())
add(total.toInt())
})
}
@@ -57,10 +58,10 @@ internal object ResponseUtil {
) {
reactContext?.emitDeviceEvent(
"didReceiveNetworkDataProgress",
Arguments.createArray().apply {
pushInt(requestId)
pushInt(progress.toInt())
pushInt(total.toInt())
buildReadableArray {
add(requestId)
add(progress.toInt())
add(total.toInt())
})
}
@@ -68,9 +69,9 @@ internal object ResponseUtil {
fun onDataReceived(reactContext: ReactApplicationContext?, requestId: Int, data: String?) {
reactContext?.emitDeviceEvent(
"didReceiveNetworkData",
Arguments.createArray().apply {
pushInt(requestId)
pushString(data)
buildReadableArray {
add(requestId)
add(data)
})
}
@@ -93,11 +94,11 @@ internal object ResponseUtil {
) {
reactContext?.emitDeviceEvent(
"didCompleteNetworkResponse",
Arguments.createArray().apply {
pushInt(requestId)
pushString(error)
buildReadableArray {
add(requestId)
add(error)
if (e?.javaClass == SocketTimeoutException::class.java) {
pushBoolean(true) // last argument is a time out boolean
add(true) // last argument is a time out boolean
}
})
}
@@ -106,9 +107,9 @@ internal object ResponseUtil {
fun onRequestSuccess(reactContext: ReactApplicationContext?, requestId: Int) {
reactContext?.emitDeviceEvent(
"didCompleteNetworkResponse",
Arguments.createArray().apply {
pushInt(requestId)
pushNull()
buildReadableArray {
add(requestId)
addNull()
})
}
@@ -9,10 +9,10 @@ package com.facebook.react.modules.share
import android.content.Intent
import com.facebook.fbreact.specs.NativeShareModuleSpec
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.Promise
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.module.annotations.ReactModule
/** Intent module. Launch other activities or open URLs. */
@@ -48,10 +48,9 @@ internal class ShareModule(reactContext: ReactApplicationContext) :
if (currentActivity != null) {
currentActivity.startActivity(chooser)
} else {
getReactApplicationContext().startActivity(chooser)
reactApplicationContext.startActivity(chooser)
}
val result = Arguments.createMap()
result.putString("action", ACTION_SHARED)
val result = buildReadableMap { put("action", ACTION_SHARED) }
promise.resolve(result)
} catch (e: Exception) {
promise.reject(ERROR_UNABLE_TO_OPEN_DIALOG, "Failed to open share dialog")
@@ -17,6 +17,7 @@ import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.ReadableType
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.common.ReactConstants
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.modules.network.CustomClientBuilder
@@ -56,7 +57,7 @@ public class WebSocketModule(context: ReactApplicationContext) :
contentHandlers.clear()
}
private fun sendEvent(eventName: String, params: WritableMap) {
private fun sendEvent(eventName: String, params: ReadableMap) {
val reactAppContext = reactApplicationContext
if (reactAppContext.hasActiveReactInstance()) {
reactAppContext.emitDeviceEvent(eventName, params)
@@ -141,9 +142,10 @@ public class WebSocketModule(context: ReactApplicationContext) :
object : WebSocketListener() {
override fun onOpen(webSocket: WebSocket, response: Response) {
webSocketConnections[id] = webSocket
val params = Arguments.createMap()
params.putInt("id", id)
params.putString("protocol", response.header("Sec-WebSocket-Protocol", ""))
val params = buildReadableMap {
put("id", id)
put("protocol", response.header("Sec-WebSocket-Protocol", ""))
}
sendEvent("websocketOpen", params)
}
@@ -152,10 +154,11 @@ public class WebSocketModule(context: ReactApplicationContext) :
}
override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
val params = Arguments.createMap()
params.putInt("id", id)
params.putInt("code", code)
params.putString("reason", reason)
val params = buildReadableMap {
put("id", id)
put("code", code)
put("reason", reason)
}
sendEvent("websocketClosed", params)
}
@@ -221,14 +224,16 @@ public class WebSocketModule(context: ReactApplicationContext) :
val client = webSocketConnections[id]
if (client == null) {
// This is a programmer error -- display development warning
var params: WritableMap = Arguments.createMap()
params.putInt("id", id)
params.putString("message", "client is null")
var params = buildReadableMap {
put("id", id)
put("message", "client is null")
}
sendEvent("websocketFailed", params)
params = Arguments.createMap()
params.putInt("id", id)
params.putInt("code", 0)
params.putString("reason", "client is null")
params = buildReadableMap {
put("id", id)
put("code", 0)
put("reason", "client is null")
}
sendEvent("websocketClosed", params)
webSocketConnections.remove(id)
contentHandlers.remove(id)
@@ -246,14 +251,16 @@ public class WebSocketModule(context: ReactApplicationContext) :
val client = webSocketConnections[id]
if (client == null) {
// This is a programmer error -- display development warning
var params: WritableMap = Arguments.createMap()
params.putInt("id", id)
params.putString("message", "client is null")
var params = buildReadableMap {
put("id", id)
put("message", "client is null")
}
sendEvent("websocketFailed", params)
params = Arguments.createMap()
params.putInt("id", id)
params.putInt("code", 0)
params.putString("reason", "client is null")
params = buildReadableMap {
put("id", id)
put("code", 0)
put("reason", "client is null")
}
sendEvent("websocketClosed", params)
webSocketConnections.remove(id)
contentHandlers.remove(id)
@@ -271,14 +278,16 @@ public class WebSocketModule(context: ReactApplicationContext) :
val client = webSocketConnections[id]
if (client == null) {
// This is a programmer error -- display development warning
var params: WritableMap = Arguments.createMap()
params.putInt("id", id)
params.putString("message", "client is null")
var params = buildReadableMap {
put("id", id)
put("message", "client is null")
}
sendEvent("websocketFailed", params)
params = Arguments.createMap()
params.putInt("id", id)
params.putInt("code", 0)
params.putString("reason", "client is null")
params = buildReadableMap {
put("id", id)
put("code", 0)
put("reason", "client is null")
}
sendEvent("websocketClosed", params)
webSocketConnections.remove(id)
contentHandlers.remove(id)
@@ -296,14 +305,16 @@ public class WebSocketModule(context: ReactApplicationContext) :
val client = webSocketConnections[id]
if (client == null) {
// This is a programmer error -- display development warning
var params: WritableMap = Arguments.createMap()
params.putInt("id", id)
params.putString("message", "client is null")
var params = buildReadableMap {
put("id", id)
put("message", "client is null")
}
sendEvent("websocketFailed", params)
params = Arguments.createMap()
params.putInt("id", id)
params.putInt("code", 0)
params.putString("reason", "client is null")
params = buildReadableMap {
put("id", id)
put("code", 0)
put("reason", "client is null")
}
sendEvent("websocketClosed", params)
webSocketConnections.remove(id)
contentHandlers.remove(id)
@@ -317,9 +328,10 @@ public class WebSocketModule(context: ReactApplicationContext) :
}
private fun notifyWebSocketFailed(id: Int, message: String?) {
val params = Arguments.createMap()
params.putInt("id", id)
params.putString("message", message)
val params = buildReadableMap {
put("id", id)
put("message", message)
}
sendEvent("websocketFailed", params)
}
@@ -10,6 +10,7 @@ package com.facebook.react.uimanager
import androidx.core.util.Pools.SynchronizedPool
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.common.annotations.VisibleForTesting
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
@@ -40,13 +41,12 @@ public class OnLayoutEvent private constructor() : Event<OnLayoutEvent>() {
override fun getEventName(): String = "topLayout"
override fun getEventData(): WritableMap {
val layout =
Arguments.createMap().apply {
putDouble("x", toDIPFromPixel(x.toFloat()).toDouble())
putDouble("y", toDIPFromPixel(y.toFloat()).toDouble())
putDouble("width", toDIPFromPixel(width.toFloat()).toDouble())
putDouble("height", toDIPFromPixel(height.toFloat()).toDouble())
}
val layout = buildReadableMap {
put("x", toDIPFromPixel(x.toFloat()).toDouble())
put("y", toDIPFromPixel(y.toFloat()).toDouble())
put("width", toDIPFromPixel(width.toFloat()).toDouble())
put("height", toDIPFromPixel(height.toFloat()).toDouble())
}
val event =
Arguments.createMap().apply {
@@ -13,6 +13,7 @@ import com.facebook.infer.annotation.Assertions
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReactSoftExceptionLogger
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.uimanager.PixelUtil.toDIPFromPixel
import com.facebook.react.uimanager.common.ViewUtil
import com.facebook.react.uimanager.events.Event
@@ -74,23 +75,33 @@ public class ScrollEvent private constructor() : Event<ScrollEvent>() {
override fun canCoalesce(): Boolean = scrollEventType == ScrollEventType.SCROLL
override fun getEventData(): WritableMap {
val contentInset = Arguments.createMap()
contentInset.putDouble("top", 0.0)
contentInset.putDouble("bottom", 0.0)
contentInset.putDouble("left", 0.0)
contentInset.putDouble("right", 0.0)
val contentOffset = Arguments.createMap()
contentOffset.putDouble("x", toDIPFromPixel(scrollX).toDouble())
contentOffset.putDouble("y", toDIPFromPixel(scrollY).toDouble())
val contentSize = Arguments.createMap()
contentSize.putDouble("width", toDIPFromPixel(contentWidth.toFloat()).toDouble())
contentSize.putDouble("height", toDIPFromPixel(contentHeight.toFloat()).toDouble())
val layoutMeasurement = Arguments.createMap()
layoutMeasurement.putDouble("width", toDIPFromPixel(scrollViewWidth.toFloat()).toDouble())
layoutMeasurement.putDouble("height", toDIPFromPixel(scrollViewHeight.toFloat()).toDouble())
val velocity = Arguments.createMap()
velocity.putDouble("x", xVelocity.toDouble())
velocity.putDouble("y", yVelocity.toDouble())
val contentInset = buildReadableMap {
put("top", 0.0)
put("bottom", 0.0)
put("left", 0.0)
put("right", 0.0)
}
val contentOffset = buildReadableMap {
put("x", toDIPFromPixel(scrollX).toDouble())
put("y", toDIPFromPixel(scrollY).toDouble())
}
val contentSize = buildReadableMap {
put("width", toDIPFromPixel(contentWidth.toFloat()).toDouble())
put("height", toDIPFromPixel(contentHeight.toFloat()).toDouble())
}
val layoutMeasurement = buildReadableMap {
put("width", toDIPFromPixel(scrollViewWidth.toFloat()).toDouble())
put("height", toDIPFromPixel(scrollViewHeight.toFloat()).toDouble())
}
val velocity = buildReadableMap {
put("x", toDIPFromPixel(xVelocity).toDouble())
put("y", toDIPFromPixel(yVelocity).toDouble())
}
val event = Arguments.createMap()
event.putMap("contentInset", contentInset)
event.putMap("contentOffset", contentOffset)
@@ -13,6 +13,7 @@ import android.text.Layout
import android.text.TextPaint
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableArray
import com.facebook.react.bridge.buildReadableMap
internal object FontMetricsUtil {
@@ -51,20 +52,18 @@ internal object FontMetricsUtil {
val lineWidth = if (endsWithNewLine) layout.getLineMax(i) else layout.getLineWidth(i)
val bounds = Rect()
layout.getLineBounds(i, bounds)
val line =
Arguments.createMap().apply {
putDouble("x", (layout.getLineLeft(i) / dm.density).toDouble())
putDouble("y", (bounds.top / dm.density).toDouble())
putDouble("width", (lineWidth / dm.density).toDouble())
putDouble("height", (bounds.height() / dm.density).toDouble())
putDouble("descender", (layout.getLineDescent(i) / dm.density).toDouble())
putDouble("ascender", (-layout.getLineAscent(i) / dm.density).toDouble())
putDouble("baseline", (layout.getLineBaseline(i) / dm.density).toDouble())
putDouble("capHeight", capHeight.toDouble())
putDouble("xHeight", xHeight.toDouble())
putString(
"text", text.subSequence(layout.getLineStart(i), layout.getLineEnd(i)).toString())
}
val line = buildReadableMap {
put("x", (layout.getLineLeft(i) / dm.density).toDouble())
put("y", (bounds.top / dm.density).toDouble())
put("width", (lineWidth / dm.density).toDouble())
put("height", (bounds.height() / dm.density).toDouble())
put("descender", (layout.getLineDescent(i) / dm.density).toDouble())
put("ascender", (-layout.getLineAscent(i) / dm.density).toDouble())
put("baseline", (layout.getLineBaseline(i) / dm.density).toDouble())
put("capHeight", capHeight.toDouble())
put("xHeight", xHeight.toDouble())
put("text", text.subSequence(layout.getLineStart(i), layout.getLineEnd(i)).toString())
}
lines.pushMap(line)
}
return lines
@@ -9,6 +9,7 @@ package com.facebook.react.views.textinput
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.uimanager.common.ViewUtil
import com.facebook.react.uimanager.events.Event
@@ -32,11 +33,10 @@ internal class ReactContentSizeChangedEvent(
override fun getEventName(): String = EVENT_NAME
override fun getEventData(): WritableMap {
val contentSize =
Arguments.createMap().apply {
putDouble("width", contentWidth.toDouble())
putDouble("height", contentHeight.toDouble())
}
val contentSize = buildReadableMap {
put("width", contentWidth.toDouble())
put("height", contentHeight.toDouble())
}
return Arguments.createMap().apply {
putMap("contentSize", contentSize)
@@ -9,6 +9,7 @@ package com.facebook.react.views.textinput
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.uimanager.common.ViewUtil
import com.facebook.react.uimanager.events.Event
@@ -31,11 +32,10 @@ internal class ReactTextInputSelectionEvent(
override fun getEventName(): String = EVENT_NAME
override fun getEventData(): WritableMap {
val selectionData =
Arguments.createMap().apply {
putInt("end", selectionEnd)
putInt("start", selectionStart)
}
val selectionData = buildReadableMap {
put("start", selectionStart)
put("end", selectionEnd)
}
return Arguments.createMap().apply { putMap("selection", selectionData) }
}