Skip to content

Commit

Permalink
Migrate NativeArray classes to Kotlin (facebook#44569)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: facebook#44569

# Changelog:
[Internal] -

This converts the vertical of NativeArray/ReadableNativeArray/WritableNativeArray classes to Kotlin.

NOTE: the `getArray`, `getMap` and `getString` being annotated as `NonNull` in the Java code is a scam - there is no guarantee that native side will send non-null to the Java side, and in practice, indeed, in certain cases it doesn't. So I opted to make it nullable instead - this way it's at least explicit and is not a ticking bomb hidden to explode behind the false sense of security.

Reviewed By: javache

Differential Revision: D57327835
  • Loading branch information
rshest authored and facebook-github-bot committed Aug 2, 2024
1 parent 51278d3 commit 998e654
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 278 deletions.
2 changes: 1 addition & 1 deletion packages/react-native/ReactAndroid/api/ReactAndroid.api
Original file line number Diff line number Diff line change
Expand Up @@ -1489,7 +1489,7 @@ public class com/facebook/react/bridge/ReadableNativeArray : com/facebook/react/
public fun getDouble (I)D
public fun getDynamic (I)Lcom/facebook/react/bridge/Dynamic;
public fun getInt (I)I
public static fun getJNIPassCounter ()I
public static final fun getJNIPassCounter ()I
public fun getLong (I)J
public synthetic fun getMap (I)Lcom/facebook/react/bridge/ReadableMap;
public fun getMap (I)Lcom/facebook/react/bridge/ReadableNativeMap;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

package com.facebook.react.bridge

import com.facebook.jni.HybridData
import com.facebook.proguard.annotations.DoNotStrip

/** Base class for an array whose members are stored in native code (C++). */
@DoNotStrip
public abstract class NativeArray
protected constructor(@field:DoNotStrip private val mHybridData: HybridData?) :
NativeArrayInterface {
external override fun toString(): String

private companion object {
init {
ReactBridge.staticInit()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,5 @@ public interface ReadableArray {

public fun size(): Int

public fun toArrayList(): ArrayList<Any>
public fun toArrayList(): ArrayList<Any?>
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

package com.facebook.react.bridge

import com.facebook.jni.HybridData
import com.facebook.proguard.annotations.DoNotStripAny
import java.util.Arrays

/**
* Implementation of a NativeArray that allows read-only access to its members. This will generally
* be constructed and filled in native code so you shouldn't construct one yourself.
*/
@DoNotStripAny
public open class ReadableNativeArray protected constructor(hybridData: HybridData?) :
NativeArray(hybridData), ReadableArray {

private val localArray: Array<Any?> by
lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
jniPassCounter++
importArray()
}

private external fun importArray(): Array<Any?>

private val localTypeArray: Array<ReadableType> by
lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
jniPassCounter++
importTypeArray()
}

private external fun importTypeArray(): Array<ReadableType>

override fun size(): Int = localArray.size

override fun isNull(index: Int): Boolean = localArray[index] == null

override fun getBoolean(index: Int): Boolean = localArray[index] as Boolean

override fun getDouble(index: Int): Double = localArray[index] as Double

override fun getInt(index: Int): Int = getDouble(index).toInt()

override fun getLong(index: Int): Long = localArray[index] as Long

override fun getString(index: Int): String = localArray[index] as String

override fun getArray(index: Int): ReadableNativeArray = localArray[index] as ReadableNativeArray

override fun getMap(index: Int): ReadableNativeMap = localArray[index] as ReadableNativeMap

override fun getType(index: Int): ReadableType = localTypeArray[index]

override fun getDynamic(index: Int): Dynamic = DynamicFromArray.create(this, index)

override fun hashCode(): Int = localArray.hashCode()

override fun equals(other: Any?): Boolean =
if (other !is ReadableNativeArray) false else Arrays.deepEquals(localArray, other.localArray)

override fun toArrayList(): ArrayList<Any?> {
val arrayList = ArrayList<Any?>()
for (i in 0 until size()) {
when (getType(i)) {
ReadableType.Null -> arrayList.add(null)
ReadableType.Boolean -> arrayList.add(getBoolean(i))
ReadableType.Number -> arrayList.add(getDouble(i))
ReadableType.String -> arrayList.add(getString(i))
ReadableType.Map -> arrayList.add(getMap(i).toHashMap())
ReadableType.Array -> arrayList.add(getArray(i).toArrayList())
else -> throw IllegalArgumentException("Could not convert object at index: $i.")
}
}
return arrayList
}

private companion object {
init {
ReactBridge.staticInit()
}

private var jniPassCounter: Int = 0

@JvmStatic public fun getJNIPassCounter(): Int = jniPassCounter
}
}
Loading

0 comments on commit 998e654

Please sign in to comment.