mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Migrate Arguments to Kotlin (#52457)
Summary: Migrate com.facebook.react.bridge.Arguments to Kotlin. ## Changelog: [Android][Changed] - Migrated com.facebook.react.bridge.Arguments to Kotlin. Pull Request resolved: https://github.com/facebook/react-native/pull/52457 Test Plan: ```bash yarn test-android yarn android ``` Reviewed By: javache Differential Revision: D78353290 Pulled By: cortinico fbshipit-source-id: 3d42b44c00a60d34264cb1093991315f5e3c444e
This commit is contained in:
committed by
Facebook GitHub Bot
parent
ff85e2f6dd
commit
2534aeaddb
@@ -531,20 +531,21 @@ public abstract interface class com/facebook/react/bridge/ActivityEventListener
|
||||
public fun onUserLeaveHint (Landroid/app/Activity;)V
|
||||
}
|
||||
|
||||
public class com/facebook/react/bridge/Arguments {
|
||||
public fun <init> ()V
|
||||
public static fun createArray ()Lcom/facebook/react/bridge/WritableArray;
|
||||
public static fun createMap ()Lcom/facebook/react/bridge/WritableMap;
|
||||
public static fun fromArray (Ljava/lang/Object;)Lcom/facebook/react/bridge/WritableArray;
|
||||
public static fun fromBundle (Landroid/os/Bundle;)Lcom/facebook/react/bridge/WritableMap;
|
||||
public static fun fromJavaArgs ([Ljava/lang/Object;)Lcom/facebook/react/bridge/WritableNativeArray;
|
||||
public static fun fromList (Ljava/util/List;)Lcom/facebook/react/bridge/WritableArray;
|
||||
public static fun makeNativeArray (Ljava/lang/Object;)Lcom/facebook/react/bridge/WritableNativeArray;
|
||||
public static fun makeNativeArray (Ljava/util/List;)Lcom/facebook/react/bridge/WritableNativeArray;
|
||||
public static fun makeNativeMap (Landroid/os/Bundle;)Lcom/facebook/react/bridge/WritableNativeMap;
|
||||
public static fun makeNativeMap (Ljava/util/Map;)Lcom/facebook/react/bridge/WritableNativeMap;
|
||||
public static fun toBundle (Lcom/facebook/react/bridge/ReadableMap;)Landroid/os/Bundle;
|
||||
public static fun toList (Lcom/facebook/react/bridge/ReadableArray;)Ljava/util/ArrayList;
|
||||
public final class com/facebook/react/bridge/Arguments {
|
||||
public static final field INSTANCE Lcom/facebook/react/bridge/Arguments;
|
||||
public static final fun createArray ()Lcom/facebook/react/bridge/WritableArray;
|
||||
public static final fun createMap ()Lcom/facebook/react/bridge/WritableMap;
|
||||
public static final fun fromArray (Ljava/lang/Object;)Lcom/facebook/react/bridge/WritableArray;
|
||||
public static final fun fromBundle (Landroid/os/Bundle;)Lcom/facebook/react/bridge/WritableMap;
|
||||
public static final fun fromJavaArgs (Ljava/lang/Object;)Lcom/facebook/react/bridge/WritableNativeArray;
|
||||
public static final fun fromJavaArgs ([Ljava/lang/Object;)Lcom/facebook/react/bridge/WritableNativeArray;
|
||||
public static final fun fromList (Ljava/util/List;)Lcom/facebook/react/bridge/WritableArray;
|
||||
public static final fun makeNativeArray (Ljava/lang/Object;)Lcom/facebook/react/bridge/WritableNativeArray;
|
||||
public static final fun makeNativeArray (Ljava/util/List;)Lcom/facebook/react/bridge/WritableNativeArray;
|
||||
public static final fun makeNativeMap (Landroid/os/Bundle;)Lcom/facebook/react/bridge/WritableNativeMap;
|
||||
public static final fun makeNativeMap (Ljava/util/Map;)Lcom/facebook/react/bridge/WritableNativeMap;
|
||||
public static final fun toBundle (Lcom/facebook/react/bridge/ReadableMap;)Landroid/os/Bundle;
|
||||
public static final fun toList (Lcom/facebook/react/bridge/ReadableArray;)Ljava/util/ArrayList;
|
||||
}
|
||||
|
||||
public final class com/facebook/react/bridge/AssertionException : java/lang/RuntimeException {
|
||||
|
||||
-423
@@ -1,423 +0,0 @@
|
||||
/*
|
||||
* 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 android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.infer.annotation.Nullsafe;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Nullsafe(Nullsafe.Mode.LOCAL)
|
||||
@DoNotStrip
|
||||
public class Arguments {
|
||||
private static @Nullable Object makeNativeObject(@Nullable Object object) {
|
||||
if (object == null) {
|
||||
return null;
|
||||
} else if (object instanceof Float
|
||||
|| object instanceof Long
|
||||
|| object instanceof Byte
|
||||
|| object instanceof Short) {
|
||||
return ((Number) object).doubleValue();
|
||||
} else if (object.getClass().isArray()) {
|
||||
return makeNativeArray(object);
|
||||
} else if (object instanceof List) {
|
||||
return makeNativeArray((List) object);
|
||||
} else if (object instanceof Map) {
|
||||
return makeNativeMap((Map<String, Object>) object);
|
||||
} else if (object instanceof Bundle) {
|
||||
return makeNativeMap((Bundle) object);
|
||||
} else if (object instanceof JavaOnlyMap) {
|
||||
return makeNativeMap(((JavaOnlyMap) object).toHashMap());
|
||||
} else if (object instanceof JavaOnlyArray) {
|
||||
return makeNativeArray(((JavaOnlyArray) object).toArrayList());
|
||||
} else {
|
||||
// Boolean, Integer, Double, String, WritableNativeArray, WritableNativeMap
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method converts a List into a NativeArray. The data types supported are boolean, int,
|
||||
* float, double, and String. List, Map, and Bundle objects, as well as arrays, containing values
|
||||
* of the above types and/or null, or any recursive arrangement of these, are also supported. The
|
||||
* best way to think of this is a way to generate a Java representation of a json list, from Java
|
||||
* types which have a natural representation in json.
|
||||
*/
|
||||
public static WritableNativeArray makeNativeArray(@Nullable List objects) {
|
||||
WritableNativeArray nativeArray = new WritableNativeArray();
|
||||
if (objects == null) {
|
||||
return nativeArray;
|
||||
}
|
||||
for (Object elem : objects) {
|
||||
elem = makeNativeObject(elem);
|
||||
if (elem == null) {
|
||||
nativeArray.pushNull();
|
||||
} else if (elem instanceof Boolean) {
|
||||
nativeArray.pushBoolean((Boolean) elem);
|
||||
} else if (elem instanceof Integer) {
|
||||
nativeArray.pushInt((Integer) elem);
|
||||
} else if (elem instanceof Double) {
|
||||
nativeArray.pushDouble((Double) elem);
|
||||
} else if (elem instanceof String) {
|
||||
nativeArray.pushString((String) elem);
|
||||
} else if (elem instanceof WritableNativeArray) {
|
||||
nativeArray.pushArray((WritableNativeArray) elem);
|
||||
} else if (elem instanceof WritableNativeMap) {
|
||||
nativeArray.pushMap((WritableNativeMap) elem);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Could not convert " + elem.getClass());
|
||||
}
|
||||
}
|
||||
return nativeArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* This overload is like the above, but uses reflection to operate on any primitive or object
|
||||
* type.
|
||||
*/
|
||||
public static <T> WritableNativeArray makeNativeArray(final @Nullable Object objects) {
|
||||
if (objects == null) {
|
||||
return new WritableNativeArray();
|
||||
}
|
||||
// No explicit check for objects's type here. If it's not an array, the
|
||||
// Array methods will throw IllegalArgumentException.
|
||||
return makeNativeArray(
|
||||
new AbstractList() {
|
||||
public int size() {
|
||||
return Array.getLength(objects);
|
||||
}
|
||||
|
||||
public @Nullable Object get(int index) {
|
||||
return Array.get(objects, index);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void addEntry(WritableNativeMap nativeMap, String key, @Nullable Object value) {
|
||||
value = makeNativeObject(value);
|
||||
if (value == null) {
|
||||
nativeMap.putNull(key);
|
||||
} else if (value instanceof Boolean) {
|
||||
nativeMap.putBoolean(key, (Boolean) value);
|
||||
} else if (value instanceof Integer) {
|
||||
nativeMap.putInt(key, (Integer) value);
|
||||
} else if (value instanceof Number) {
|
||||
nativeMap.putDouble(key, ((Number) value).doubleValue());
|
||||
} else if (value instanceof String) {
|
||||
nativeMap.putString(key, (String) value);
|
||||
} else if (value instanceof WritableNativeArray) {
|
||||
nativeMap.putArray(key, (WritableNativeArray) value);
|
||||
} else if (value instanceof WritableNativeMap) {
|
||||
nativeMap.putMap(key, (WritableNativeMap) value);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Could not convert " + value.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method converts a Map into a NativeMap. Value types are supported as with makeNativeArray.
|
||||
* The best way to think of this is a way to generate a Java representation of a json object, from
|
||||
* Java types which have a natural representation in json.
|
||||
*/
|
||||
@DoNotStrip
|
||||
public static WritableNativeMap makeNativeMap(@Nullable Map<String, Object> objects) {
|
||||
WritableNativeMap nativeMap = new WritableNativeMap();
|
||||
if (objects == null) {
|
||||
return nativeMap;
|
||||
}
|
||||
for (Map.Entry<String, Object> entry : objects.entrySet()) {
|
||||
addEntry(nativeMap, entry.getKey(), entry.getValue());
|
||||
}
|
||||
return nativeMap;
|
||||
}
|
||||
|
||||
/** Like the above, but takes a Bundle instead of a Map. */
|
||||
@DoNotStrip
|
||||
public static WritableNativeMap makeNativeMap(@Nullable Bundle bundle) {
|
||||
WritableNativeMap nativeMap = new WritableNativeMap();
|
||||
if (bundle == null) {
|
||||
return nativeMap;
|
||||
}
|
||||
for (String key : bundle.keySet()) {
|
||||
addEntry(nativeMap, key, bundle.get(key));
|
||||
}
|
||||
return nativeMap;
|
||||
}
|
||||
|
||||
/** This method should be used when you need to stub out creating NativeArrays in unit tests. */
|
||||
public static WritableArray createArray() {
|
||||
return new WritableNativeArray();
|
||||
}
|
||||
|
||||
/** This method should be used when you need to stub out creating NativeMaps in unit tests. */
|
||||
public static WritableMap createMap() {
|
||||
return new WritableNativeMap();
|
||||
}
|
||||
|
||||
public static WritableNativeArray fromJavaArgs(Object[] args) {
|
||||
WritableNativeArray arguments = new WritableNativeArray();
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
Object argument = args[i];
|
||||
if (argument == null) {
|
||||
arguments.pushNull();
|
||||
continue;
|
||||
}
|
||||
|
||||
Class argumentClass = argument.getClass();
|
||||
if (argumentClass == Boolean.class) {
|
||||
arguments.pushBoolean(((Boolean) argument).booleanValue());
|
||||
} else if (argumentClass == Integer.class) {
|
||||
arguments.pushDouble(((Integer) argument).doubleValue());
|
||||
} else if (argumentClass == Double.class) {
|
||||
arguments.pushDouble(((Double) argument).doubleValue());
|
||||
} else if (argumentClass == Float.class) {
|
||||
arguments.pushDouble(((Float) argument).doubleValue());
|
||||
} else if (argumentClass == String.class) {
|
||||
arguments.pushString(argument.toString());
|
||||
} else if (argumentClass == WritableNativeMap.class) {
|
||||
arguments.pushMap((WritableNativeMap) argument);
|
||||
} else if (argumentClass == WritableNativeArray.class) {
|
||||
arguments.pushArray((WritableNativeArray) argument);
|
||||
} else {
|
||||
throw new RuntimeException("Cannot convert argument of type " + argumentClass);
|
||||
}
|
||||
}
|
||||
return arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an array to a {@link WritableArray}.
|
||||
*
|
||||
* @param array the array to convert. Supported types are: {@code String[]}, {@code Bundle[]},
|
||||
* {@code int[]}, {@code float[]}, {@code double[]}, {@code boolean[]}.
|
||||
* @return the converted {@link WritableArray}
|
||||
* @throws IllegalArgumentException if the passed object is none of the above types
|
||||
*/
|
||||
public static WritableArray fromArray(Object array) {
|
||||
WritableArray catalystArray = createArray();
|
||||
if (array instanceof String[]) {
|
||||
for (String v : (String[]) array) {
|
||||
catalystArray.pushString(v);
|
||||
}
|
||||
} else if (array instanceof Bundle[]) {
|
||||
for (Bundle v : (Bundle[]) array) {
|
||||
catalystArray.pushMap(fromBundle(v));
|
||||
}
|
||||
} else if (array instanceof int[]) {
|
||||
for (int v : (int[]) array) {
|
||||
catalystArray.pushInt(v);
|
||||
}
|
||||
} else if (array instanceof float[]) {
|
||||
for (float v : (float[]) array) {
|
||||
catalystArray.pushDouble(v);
|
||||
}
|
||||
} else if (array instanceof double[]) {
|
||||
for (double v : (double[]) array) {
|
||||
catalystArray.pushDouble(v);
|
||||
}
|
||||
} else if (array instanceof boolean[]) {
|
||||
for (boolean v : (boolean[]) array) {
|
||||
catalystArray.pushBoolean(v);
|
||||
}
|
||||
} else if (array instanceof Parcelable[]) {
|
||||
for (Parcelable v : (Parcelable[]) array) {
|
||||
if (v instanceof Bundle) {
|
||||
catalystArray.pushMap(fromBundle((Bundle) v));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unexpected array member type " + v.getClass());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown array type " + array.getClass());
|
||||
}
|
||||
return catalystArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a {@link List} to a {@link WritableArray}.
|
||||
*
|
||||
* @param list the list to convert. Supported value types are: {@code null}, {@code String},
|
||||
* {@code Bundle}, {@code List}, {@code Number}, {@code Boolean}, and all array types
|
||||
* supported in {@link #fromArray(Object)}.
|
||||
* @return the converted {@link WritableArray}
|
||||
* @throws IllegalArgumentException if one of the values from the passed list is none of the above
|
||||
* types
|
||||
*/
|
||||
public static WritableArray fromList(List list) {
|
||||
WritableArray catalystArray = createArray();
|
||||
for (Object obj : list) {
|
||||
if (obj == null) {
|
||||
catalystArray.pushNull();
|
||||
} else if (obj.getClass().isArray()) {
|
||||
catalystArray.pushArray(fromArray(obj));
|
||||
} else if (obj instanceof Bundle) {
|
||||
catalystArray.pushMap(fromBundle((Bundle) obj));
|
||||
} else if (obj instanceof List) {
|
||||
catalystArray.pushArray(fromList((List) obj));
|
||||
} else if (obj instanceof String) {
|
||||
catalystArray.pushString((String) obj);
|
||||
} else if (obj instanceof Integer) {
|
||||
catalystArray.pushInt((Integer) obj);
|
||||
} else if (obj instanceof Number) {
|
||||
catalystArray.pushDouble(((Number) obj).doubleValue());
|
||||
} else if (obj instanceof Boolean) {
|
||||
catalystArray.pushBoolean((Boolean) obj);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown value type " + obj.getClass());
|
||||
}
|
||||
}
|
||||
return catalystArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a {@link Bundle} to a {@link WritableMap}. Supported key types in the bundle are:
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>primitive types: int, float, double, boolean
|
||||
* <li>arrays supported by {@link #fromArray(Object)}
|
||||
* <li>lists supported by {@link #fromList(List)}
|
||||
* <li>{@link Bundle} objects that are recursively converted to maps
|
||||
* </ul>
|
||||
*
|
||||
* @param bundle the {@link Bundle} to convert
|
||||
* @return the converted {@link WritableMap}
|
||||
* @throws IllegalArgumentException if there are keys of unsupported types
|
||||
*/
|
||||
public static WritableMap fromBundle(Bundle bundle) {
|
||||
WritableMap map = createMap();
|
||||
for (String key : bundle.keySet()) {
|
||||
Object value = bundle.get(key);
|
||||
if (value == null) {
|
||||
map.putNull(key);
|
||||
} else if (value.getClass().isArray()) {
|
||||
map.putArray(key, fromArray(value));
|
||||
} else if (value instanceof String) {
|
||||
map.putString(key, (String) value);
|
||||
} else if (value instanceof Number) {
|
||||
if (value instanceof Integer) {
|
||||
map.putInt(key, (Integer) value);
|
||||
} else {
|
||||
map.putDouble(key, ((Number) value).doubleValue());
|
||||
}
|
||||
} else if (value instanceof Boolean) {
|
||||
map.putBoolean(key, (Boolean) value);
|
||||
} else if (value instanceof Bundle) {
|
||||
map.putMap(key, fromBundle((Bundle) value));
|
||||
} else if (value instanceof List) {
|
||||
map.putArray(key, fromList((List) value));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Could not convert " + value.getClass());
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a {@link WritableArray} to a {@link ArrayList}.
|
||||
*
|
||||
* @param readableArray the {@link WritableArray} to convert.
|
||||
* @return the converted {@link ArrayList}.
|
||||
*/
|
||||
@Nullable
|
||||
public static ArrayList toList(@Nullable ReadableArray readableArray) {
|
||||
if (readableArray == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ArrayList list = new ArrayList();
|
||||
|
||||
for (int i = 0; i < readableArray.size(); i++) {
|
||||
switch (readableArray.getType(i)) {
|
||||
case Null:
|
||||
list.add(null);
|
||||
break;
|
||||
case Boolean:
|
||||
list.add(readableArray.getBoolean(i));
|
||||
break;
|
||||
case Number:
|
||||
double number = readableArray.getDouble(i);
|
||||
if (number == Math.rint(number)) {
|
||||
// Add as an integer
|
||||
list.add((int) number);
|
||||
} else {
|
||||
// Add as a double
|
||||
list.add(number);
|
||||
}
|
||||
break;
|
||||
case String:
|
||||
list.add(readableArray.getString(i));
|
||||
break;
|
||||
case Map:
|
||||
list.add(toBundle(readableArray.getMap(i)));
|
||||
break;
|
||||
case Array:
|
||||
list.add(toList(readableArray.getArray(i)));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Could not convert object in array.");
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a {@link WritableMap} to a {@link Bundle}. Note: Each array is converted to an {@link
|
||||
* ArrayList}.
|
||||
*
|
||||
* @param readableMap the {@link WritableMap} to convert.
|
||||
* @return the converted {@link Bundle}.
|
||||
*/
|
||||
@Nullable
|
||||
public static Bundle toBundle(@Nullable ReadableMap readableMap) {
|
||||
if (readableMap == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
while (iterator.hasNextKey()) {
|
||||
String key = iterator.nextKey();
|
||||
ReadableType readableType = readableMap.getType(key);
|
||||
switch (readableType) {
|
||||
case Null:
|
||||
bundle.putString(key, null);
|
||||
break;
|
||||
case Boolean:
|
||||
bundle.putBoolean(key, readableMap.getBoolean(key));
|
||||
break;
|
||||
case Number:
|
||||
// Can be int or double.
|
||||
bundle.putDouble(key, readableMap.getDouble(key));
|
||||
break;
|
||||
case String:
|
||||
bundle.putString(key, readableMap.getString(key));
|
||||
break;
|
||||
case Map:
|
||||
bundle.putBundle(key, toBundle(readableMap.getMap(key)));
|
||||
break;
|
||||
case Array:
|
||||
bundle.putSerializable(key, toList(readableMap.getArray(key)));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Could not convert object with key: " + key + ".");
|
||||
}
|
||||
}
|
||||
|
||||
return bundle;
|
||||
}
|
||||
}
|
||||
+356
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
* 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 android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import com.facebook.proguard.annotations.DoNotStrip
|
||||
import java.util.AbstractList
|
||||
import kotlin.math.round
|
||||
|
||||
@DoNotStrip
|
||||
public object Arguments {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun makeNativeObject(value: Any?): Any? =
|
||||
when {
|
||||
value == null -> null
|
||||
value is Float || value is Long || value is Byte || value is Short ->
|
||||
(value as Number).toDouble()
|
||||
value.javaClass.isArray -> makeNativeArray<Any>(value)
|
||||
value is List<*> -> makeNativeArray(value)
|
||||
value is Map<*, *> -> makeNativeMap(value as Map<String, Any?>)
|
||||
value is Bundle -> makeNativeMap(value)
|
||||
value is JavaOnlyMap -> makeNativeMap(value.toHashMap())
|
||||
value is JavaOnlyArray -> makeNativeArray(value.toArrayList())
|
||||
else -> value // Boolean, Integer, Double, String, WritableNativeArray, WritableNativeMap
|
||||
}
|
||||
|
||||
/**
|
||||
* This method converts a List into a NativeArray. The data types supported are boolean, int,
|
||||
* float, double, and String. List, Map, and Bundle objects, as well as arrays, containing values
|
||||
* of the above types and/or null, or any recursive arrangement of these, are also supported. The
|
||||
* best way to think of this is a way to generate a Java representation of a json list, from Java
|
||||
* types which have a natural representation in json.
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun makeNativeArray(objects: List<*>?): WritableNativeArray {
|
||||
val nativeArray = WritableNativeArray()
|
||||
if (objects == null) {
|
||||
return nativeArray
|
||||
}
|
||||
for (elem in objects) {
|
||||
when (val value = makeNativeObject(elem)) {
|
||||
null -> nativeArray.pushNull()
|
||||
is Boolean -> nativeArray.pushBoolean(value)
|
||||
is Int -> nativeArray.pushInt(value)
|
||||
is Double -> nativeArray.pushDouble(value)
|
||||
is String -> nativeArray.pushString(value)
|
||||
is WritableNativeArray -> nativeArray.pushArray(value)
|
||||
is WritableNativeMap -> nativeArray.pushMap(value)
|
||||
else -> throw IllegalArgumentException("Could not convert ${value.javaClass}")
|
||||
}
|
||||
}
|
||||
return nativeArray
|
||||
}
|
||||
|
||||
/**
|
||||
* This overload is like the above, but uses reflection to operate on any primitive or object
|
||||
* type.
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun <T> makeNativeArray(objects: Any?): WritableNativeArray {
|
||||
if (objects == null) {
|
||||
return WritableNativeArray()
|
||||
}
|
||||
// No explicit check for objects's type here. If it's not an array, the
|
||||
// Array methods will throw IllegalArgumentException.
|
||||
return makeNativeArray(
|
||||
object : AbstractList<Any?>() {
|
||||
override val size: Int
|
||||
get() = java.lang.reflect.Array.getLength(objects)
|
||||
|
||||
override fun get(index: Int): Any? = java.lang.reflect.Array.get(objects, index)
|
||||
})
|
||||
}
|
||||
|
||||
private fun addEntry(nativeMap: WritableNativeMap, key: String, value: Any?) {
|
||||
when (val nativeObjectValue = makeNativeObject(value)) {
|
||||
null -> nativeMap.putNull(key)
|
||||
is Boolean -> nativeMap.putBoolean(key, nativeObjectValue)
|
||||
is Int -> nativeMap.putInt(key, nativeObjectValue)
|
||||
is Number -> nativeMap.putDouble(key, nativeObjectValue.toDouble())
|
||||
is String -> nativeMap.putString(key, nativeObjectValue)
|
||||
is WritableNativeArray -> nativeMap.putArray(key, nativeObjectValue)
|
||||
is WritableNativeMap -> nativeMap.putMap(key, nativeObjectValue)
|
||||
else -> throw IllegalArgumentException("Could not convert ${nativeObjectValue.javaClass}")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method converts a Map into a NativeMap. Value types are supported as with makeNativeArray.
|
||||
* The best way to think of this is a way to generate a Java representation of a json object, from
|
||||
* Java types which have a natural representation in json.
|
||||
*/
|
||||
@DoNotStrip
|
||||
@JvmStatic
|
||||
public fun makeNativeMap(objects: Map<String, Any?>?): WritableNativeMap {
|
||||
val nativeMap = WritableNativeMap()
|
||||
if (objects == null) {
|
||||
return nativeMap
|
||||
}
|
||||
for ((key, value) in objects) {
|
||||
addEntry(nativeMap, key, value)
|
||||
}
|
||||
return nativeMap
|
||||
}
|
||||
|
||||
/** Like the above, but takes a Bundle instead of a Map. */
|
||||
@DoNotStrip
|
||||
@JvmStatic
|
||||
@Suppress("DEPRECATION")
|
||||
public fun makeNativeMap(bundle: Bundle?): WritableNativeMap {
|
||||
val nativeMap = WritableNativeMap()
|
||||
if (bundle == null) {
|
||||
return nativeMap
|
||||
}
|
||||
for (key in bundle.keySet()) {
|
||||
addEntry(nativeMap, key, bundle[key])
|
||||
}
|
||||
return nativeMap
|
||||
}
|
||||
|
||||
/** This method should be used when you need to stub out creating NativeArrays in unit tests. */
|
||||
@JvmStatic public fun createArray(): WritableArray = WritableNativeArray()
|
||||
|
||||
/** This method should be used when you need to stub out creating NativeMaps in unit tests. */
|
||||
@JvmStatic public fun createMap(): WritableMap = WritableNativeMap()
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@JvmStatic
|
||||
@Deprecated(
|
||||
"Use fromJavaArgs(Array<Any?>) instead. This method is added only to retain compatibility with Java consumers.")
|
||||
public fun fromJavaArgs(args: Any?): WritableNativeArray = fromJavaArgs(args as Array<Any?>)
|
||||
|
||||
@JvmStatic
|
||||
public fun fromJavaArgs(args: Array<Any?>): WritableNativeArray {
|
||||
val arguments = WritableNativeArray()
|
||||
for (i in args.indices) {
|
||||
val argument = args[i]
|
||||
when (val argumentClass = argument?.javaClass) {
|
||||
null -> arguments.pushNull()
|
||||
Boolean::class.java,
|
||||
java.lang.Boolean::class.java -> arguments.pushBoolean(argument as Boolean)
|
||||
Int::class.java,
|
||||
java.lang.Integer::class.java -> arguments.pushDouble((argument as Number).toDouble())
|
||||
Double::class.java,
|
||||
java.lang.Double::class.java -> arguments.pushDouble((argument as Double))
|
||||
Float::class.java -> arguments.pushDouble((argument as Float).toDouble())
|
||||
java.lang.Float::class.java -> arguments.pushDouble((argument as Float).toDouble())
|
||||
String::class.java -> arguments.pushString(argument.toString())
|
||||
WritableNativeMap::class.java -> arguments.pushMap(argument as WritableNativeMap)
|
||||
WritableNativeArray::class.java -> arguments.pushArray(argument as WritableNativeArray)
|
||||
else -> throw RuntimeException("Cannot convert argument of type $argumentClass")
|
||||
}
|
||||
}
|
||||
return arguments
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an array to a [WritableArray].
|
||||
*
|
||||
* @param array the array to convert. Supported types are: `String[]`, `Bundle[]`, `int[]`,
|
||||
* `float[]`, `double[]`, `boolean[]`.
|
||||
* @return the converted [WritableArray]
|
||||
* @throws IllegalArgumentException if the passed object is none of the above types
|
||||
*/
|
||||
@JvmStatic
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public fun fromArray(array: Any): WritableArray {
|
||||
val catalystArray = createArray()
|
||||
when {
|
||||
array is Array<*> && array.isArrayOf<String>() -> {
|
||||
for (v in array as Array<String?>) {
|
||||
catalystArray.pushString(v)
|
||||
}
|
||||
}
|
||||
array is Array<*> && array.isArrayOf<Bundle>() -> {
|
||||
for (v in array as Array<Bundle>) {
|
||||
catalystArray.pushMap(fromBundle(v))
|
||||
}
|
||||
}
|
||||
array is IntArray -> {
|
||||
for (v in array) {
|
||||
catalystArray.pushInt(v)
|
||||
}
|
||||
}
|
||||
array is FloatArray -> {
|
||||
for (v in array) {
|
||||
catalystArray.pushDouble(v.toDouble())
|
||||
}
|
||||
}
|
||||
array is DoubleArray -> {
|
||||
for (v in array) {
|
||||
catalystArray.pushDouble(v)
|
||||
}
|
||||
}
|
||||
array is BooleanArray -> {
|
||||
for (v in array) {
|
||||
catalystArray.pushBoolean(v)
|
||||
}
|
||||
}
|
||||
array is Array<*> && array.isArrayOf<Parcelable>() -> {
|
||||
for (v in array as Array<Parcelable>) {
|
||||
if (v is Bundle) {
|
||||
catalystArray.pushMap(fromBundle(v))
|
||||
} else {
|
||||
throw IllegalArgumentException("Unexpected array member type ${v.javaClass}")
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> throw IllegalArgumentException("Unknown array type ${array.javaClass}")
|
||||
}
|
||||
return catalystArray
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a [List] to a [WritableArray].
|
||||
*
|
||||
* @param list the list to convert. Supported value types are: `null`, `String`, `Bundle`, `List`,
|
||||
* `Number`, `Boolean`, and all array types supported in [.fromArray].
|
||||
* @return the converted [WritableArray]
|
||||
* @throws IllegalArgumentException if one of the values from the passed list is none of the above
|
||||
* types
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun fromList(list: List<*>): WritableArray {
|
||||
val catalystArray = createArray()
|
||||
for (obj in list) {
|
||||
when {
|
||||
obj == null -> catalystArray.pushNull()
|
||||
obj.javaClass.isArray -> catalystArray.pushArray(fromArray(obj))
|
||||
obj is Bundle -> catalystArray.pushMap(fromBundle(obj))
|
||||
obj is List<*> -> catalystArray.pushArray(fromList(obj))
|
||||
obj is String -> catalystArray.pushString(obj)
|
||||
obj is Int -> catalystArray.pushInt(obj)
|
||||
obj is Number -> catalystArray.pushDouble(obj.toDouble())
|
||||
obj is Boolean -> catalystArray.pushBoolean(obj)
|
||||
else -> throw IllegalArgumentException("Unknown value type ${obj.javaClass}")
|
||||
}
|
||||
}
|
||||
return catalystArray
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a [Bundle] to a [WritableMap]. Supported key types in the bundle are:
|
||||
* * primitive types: int, float, double, boolean
|
||||
* * arrays supported by [.fromArray]
|
||||
* * lists supported by [.fromList]
|
||||
* * [Bundle] objects that are recursively converted to maps
|
||||
*
|
||||
* @param bundle the [Bundle] to convert
|
||||
* @return the converted [WritableMap]
|
||||
* @throws IllegalArgumentException if there are keys of unsupported types
|
||||
*/
|
||||
@JvmStatic
|
||||
@Suppress("DEPRECATION")
|
||||
public fun fromBundle(bundle: Bundle): WritableMap {
|
||||
val map = createMap()
|
||||
for (key in bundle.keySet()) {
|
||||
val value = bundle[key]
|
||||
when {
|
||||
value == null -> map.putNull(key)
|
||||
value.javaClass.isArray -> map.putArray(key, fromArray(value))
|
||||
value is String -> map.putString(key, value)
|
||||
value is Number -> {
|
||||
if (value is Int) {
|
||||
map.putInt(key, value)
|
||||
} else {
|
||||
map.putDouble(key, value.toDouble())
|
||||
}
|
||||
}
|
||||
value is Boolean -> map.putBoolean(key, value)
|
||||
value is Bundle -> map.putMap(key, fromBundle(value))
|
||||
value is List<*> -> map.putArray(key, fromList(value))
|
||||
else -> throw IllegalArgumentException("Could not convert ${value.javaClass}")
|
||||
}
|
||||
}
|
||||
return map
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a [WritableArray] to a [ArrayList].
|
||||
*
|
||||
* @param readableArray the [WritableArray] to convert.
|
||||
* @return the converted [ArrayList].
|
||||
*/
|
||||
@JvmStatic
|
||||
@Suppress("REDUNDANT_ELSE_IN_WHEN")
|
||||
public fun toList(readableArray: ReadableArray?): ArrayList<Any?>? {
|
||||
if (readableArray == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
val list: ArrayList<Any?> = ArrayList()
|
||||
|
||||
for (i in 0..<readableArray.size()) {
|
||||
when (readableArray.getType(i)) {
|
||||
ReadableType.Null -> list.add(null)
|
||||
ReadableType.Boolean -> list.add(readableArray.getBoolean(i))
|
||||
ReadableType.Number -> {
|
||||
val number = readableArray.getDouble(i)
|
||||
if (number == round(number)) {
|
||||
// Add as an integer
|
||||
list.add(number.toInt())
|
||||
} else {
|
||||
// Add as a double
|
||||
list.add(number)
|
||||
}
|
||||
}
|
||||
ReadableType.String -> list.add(readableArray.getString(i))
|
||||
ReadableType.Map -> list.add(toBundle(readableArray.getMap(i)))
|
||||
ReadableType.Array -> list.add(toList(readableArray.getArray(i)))
|
||||
else -> throw IllegalArgumentException("Could not convert object in array.")
|
||||
}
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a [WritableMap] to a [Bundle]. Note: Each array is converted to an [ArrayList].
|
||||
*
|
||||
* @param readableMap the [WritableMap] to convert.
|
||||
* @return the converted [Bundle].
|
||||
*/
|
||||
@JvmStatic
|
||||
@Suppress("REDUNDANT_ELSE_IN_WHEN")
|
||||
public fun toBundle(readableMap: ReadableMap?): Bundle? {
|
||||
if (readableMap == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
val iterator = readableMap.keySetIterator()
|
||||
val bundle = Bundle()
|
||||
|
||||
while (iterator.hasNextKey()) {
|
||||
val key = iterator.nextKey()
|
||||
when (readableMap.getType(key)) {
|
||||
ReadableType.Null -> bundle.putString(key, null)
|
||||
ReadableType.Boolean -> bundle.putBoolean(key, readableMap.getBoolean(key))
|
||||
ReadableType.Number ->
|
||||
bundle.putDouble(key, readableMap.getDouble(key)) // Can be int or double.
|
||||
ReadableType.String -> bundle.putString(key, readableMap.getString(key))
|
||||
ReadableType.Map -> bundle.putBundle(key, toBundle(readableMap.getMap(key)))
|
||||
ReadableType.Array -> bundle.putSerializable(key, toList(readableMap.getArray(key)))
|
||||
else -> throw IllegalArgumentException("Could not convert object with key: $key.")
|
||||
}
|
||||
}
|
||||
|
||||
return bundle
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -22,7 +22,8 @@ internal class CallbackImpl(private val jsInstance: JSInstance, private val call
|
||||
throw RuntimeException(
|
||||
"Illegal callback invocation from native module. This callback type only permits a single invocation from native code.")
|
||||
}
|
||||
jsInstance.invokeCallback(callbackId, Arguments.fromJavaArgs(args))
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
jsInstance.invokeCallback(callbackId, Arguments.fromJavaArgs(args as Array<Any?>))
|
||||
invoked = true
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import com.facebook.proguard.annotations.DoNotStrip
|
||||
public class CxxCallbackImpl @DoNotStrip private constructor() : HybridClassBase(), Callback {
|
||||
|
||||
override fun invoke(vararg args: Any?) {
|
||||
nativeInvoke(Arguments.fromJavaArgs(args))
|
||||
@Suppress("UNCHECKED_CAST") nativeInvoke(Arguments.fromJavaArgs(args as Array<Any?>))
|
||||
}
|
||||
|
||||
private external fun nativeInvoke(arguments: NativeArray)
|
||||
|
||||
+2
-4
@@ -21,7 +21,6 @@ import com.facebook.react.bridge.NativeArray
|
||||
import com.facebook.react.bridge.NativeModule
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
import com.facebook.react.bridge.UIManager
|
||||
import com.facebook.react.bridge.WritableNativeArray
|
||||
import com.facebook.react.common.annotations.FrameworkAPI
|
||||
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
||||
import com.facebook.react.common.build.ReactBuildConfig
|
||||
@@ -105,9 +104,8 @@ internal class BridgelessReactContext(context: Context, private val reactHost: R
|
||||
private val reactHost: ReactHostImpl,
|
||||
private val jsModuleInterface: Class<out JavaScriptModule>
|
||||
) : InvocationHandler {
|
||||
override fun invoke(proxy: Any, method: Method, args: Array<Any>?): Any? {
|
||||
val jsArgs: NativeArray =
|
||||
if (args != null) Arguments.fromJavaArgs(args) else WritableNativeArray()
|
||||
override fun invoke(proxy: Any, method: Method, args: Array<Any?>): Any? {
|
||||
val jsArgs: NativeArray = Arguments.fromJavaArgs(args)
|
||||
reactHost.callFunctionOnModule(
|
||||
JavaScriptModuleRegistry.getJSModuleName(jsModuleInterface), method.name, jsArgs)
|
||||
return null
|
||||
|
||||
+3
-6
@@ -11,9 +11,6 @@ import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.graphics.Rect
|
||||
import android.util.DisplayMetrics
|
||||
import com.facebook.react.bridge.Arguments
|
||||
import com.facebook.react.bridge.JavaOnlyMap
|
||||
import com.facebook.react.bridge.WritableMap
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlagsForTests
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder
|
||||
import com.facebook.react.uimanager.events.Event
|
||||
@@ -21,6 +18,7 @@ import com.facebook.react.uimanager.events.EventDispatcher
|
||||
import com.facebook.react.views.scroll.ReactScrollView
|
||||
import com.facebook.react.views.virtual.VirtualViewMode
|
||||
import com.facebook.react.views.virtual.VirtualViewModeChangeEvent
|
||||
import com.facebook.testutils.shadows.ShadowArguments
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
@@ -32,8 +30,10 @@ import org.mockito.kotlin.times
|
||||
import org.mockito.kotlin.verify
|
||||
import org.robolectric.Robolectric
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
/** Tests [ReactVirtualView] */
|
||||
@Config(shadows = [ShadowArguments::class])
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class ReactVirtualViewTest {
|
||||
|
||||
@@ -45,9 +45,6 @@ class ReactVirtualViewTest {
|
||||
|
||||
context = Robolectric.buildActivity(Activity::class.java).create().get()
|
||||
|
||||
val arguments = mockStatic(Arguments::class.java)
|
||||
arguments.`when`<WritableMap> { Arguments.createMap() }.thenAnswer { JavaOnlyMap() }
|
||||
|
||||
val displayMetricsHolder = mockStatic(DisplayMetricsHolder::class.java)
|
||||
displayMetricsHolder
|
||||
.`when`<DisplayMetrics> { DisplayMetricsHolder.getWindowDisplayMetrics() }
|
||||
|
||||
+12
-9
@@ -18,15 +18,18 @@ import org.robolectric.annotation.Implements
|
||||
import org.robolectric.shadow.api.Shadow
|
||||
|
||||
@Implements(Arguments::class)
|
||||
object ShadowArguments {
|
||||
@JvmStatic @Implementation fun createArray(): WritableArray = JavaOnlyArray()
|
||||
class ShadowArguments {
|
||||
|
||||
@JvmStatic @Implementation fun createMap(): WritableMap = JavaOnlyMap()
|
||||
companion object {
|
||||
@JvmStatic @Implementation fun createArray(): WritableArray = JavaOnlyArray()
|
||||
|
||||
@JvmStatic
|
||||
@Implementation
|
||||
fun fromJavaArgs(args: Array<Any?>): WritableNativeArray =
|
||||
WritableNativeArray().apply {
|
||||
(Shadow.extract(this) as ShadowNativeArray).backingArray = JavaOnlyArray.of(*args)
|
||||
}
|
||||
@JvmStatic @Implementation fun createMap(): WritableMap = JavaOnlyMap()
|
||||
|
||||
@JvmStatic
|
||||
@Implementation
|
||||
fun fromJavaArgs(args: Array<Any?>): WritableNativeArray =
|
||||
WritableNativeArray().apply {
|
||||
(Shadow.extract(this) as ShadowNativeArray).backingArray = JavaOnlyArray.of(*args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user