mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
b640b6faf7
Summary: Kotlin is getting traction and more developers write RN native modules in it. This PR adds nullable annotations to help with Kotlin null inference and improve developer experience. Also it'll help checking code quality using lint. I skimmed through JavaOnlyMap.java, JavaOnlyArray.java, ReadableNativeArray.java, ReadableNativeMap.java, WritableNativeArray.java and WritableNativeMap.java to infer nullability. This is breaking change to Kotlin code. [Android] [Changed] - Add nullable annotations to ReadableMap, WritableMap, ReadableArray, Writable. Pull Request resolved: https://github.com/facebook/react-native/pull/23329 Differential Revision: D14002571 Pulled By: cpojer fbshipit-source-id: 899d8b3b0a5dad43e8300e6c4ea4208cca0f01a9
206 lines
5.7 KiB
Java
206 lines
5.7 KiB
Java
/**
|
|
* Copyright (c) Facebook, Inc. and its 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.infer.annotation.Assertions;
|
|
import com.facebook.jni.HybridData;
|
|
import com.facebook.proguard.annotations.DoNotStrip;
|
|
import com.facebook.react.config.ReactFeatureFlags;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
|
|
import javax.annotation.Nonnull;
|
|
import javax.annotation.Nullable;
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
@DoNotStrip
|
|
public class ReadableNativeArray extends NativeArray implements ReadableArray {
|
|
static {
|
|
ReactBridge.staticInit();
|
|
}
|
|
|
|
protected ReadableNativeArray(HybridData hybridData) {
|
|
super(hybridData);
|
|
}
|
|
|
|
//WriteOnce but not in the constructor fields
|
|
private @Nullable Object[] mLocalArray;
|
|
private @Nullable ReadableType[] mLocalTypeArray;
|
|
|
|
private static int jniPassCounter = 0;
|
|
public static void setUseNativeAccessor(boolean useNativeAccessor) {
|
|
ReactFeatureFlags.useArrayNativeAccessor = useNativeAccessor;
|
|
}
|
|
public static int getJNIPassCounter() {
|
|
return jniPassCounter;
|
|
}
|
|
|
|
private Object[] getLocalArray() {
|
|
// Fast, non blocking check for the common case
|
|
if (mLocalArray != null) {
|
|
return mLocalArray;
|
|
}
|
|
synchronized (this) {
|
|
// Make sure no concurrent call already updated
|
|
if (mLocalArray == null) {
|
|
jniPassCounter++;
|
|
mLocalArray = Assertions.assertNotNull(importArray());
|
|
}
|
|
}
|
|
return mLocalArray;
|
|
}
|
|
private native Object[] importArray();
|
|
|
|
private ReadableType[] getLocalTypeArray() {
|
|
// Fast, non-blocking check for the common case
|
|
if (mLocalTypeArray != null) {
|
|
return mLocalTypeArray;
|
|
}
|
|
synchronized (this) {
|
|
// Make sure no concurrent call already updated
|
|
if (mLocalTypeArray == null) {
|
|
jniPassCounter++;
|
|
Object[] tempArray = Assertions.assertNotNull(importTypeArray());
|
|
mLocalTypeArray = Arrays.copyOf(tempArray, tempArray.length, ReadableType[].class);
|
|
}
|
|
}
|
|
return mLocalTypeArray;
|
|
}
|
|
private native Object[] importTypeArray();
|
|
|
|
@Override
|
|
public int size() {
|
|
if (ReactFeatureFlags.useArrayNativeAccessor) {
|
|
jniPassCounter++;
|
|
return sizeNative();
|
|
}
|
|
return getLocalArray().length;
|
|
}
|
|
private native int sizeNative();
|
|
|
|
@Override
|
|
public boolean isNull(int index) {
|
|
if (ReactFeatureFlags.useArrayNativeAccessor) {
|
|
jniPassCounter++;
|
|
return isNullNative(index);
|
|
}
|
|
return getLocalArray()[index] == null;
|
|
}
|
|
private native boolean isNullNative(int index);
|
|
|
|
@Override
|
|
public boolean getBoolean(int index) {
|
|
if (ReactFeatureFlags.useArrayNativeAccessor) {
|
|
jniPassCounter++;
|
|
return getBooleanNative(index);
|
|
}
|
|
return ((Boolean) getLocalArray()[index]).booleanValue();
|
|
}
|
|
private native boolean getBooleanNative(int index);
|
|
|
|
@Override
|
|
public double getDouble(int index) {
|
|
if (ReactFeatureFlags.useArrayNativeAccessor) {
|
|
jniPassCounter++;
|
|
return getDoubleNative(index);
|
|
}
|
|
return ((Double) getLocalArray()[index]).doubleValue();
|
|
}
|
|
private native double getDoubleNative(int index);
|
|
|
|
@Override
|
|
public int getInt(int index) {
|
|
if (ReactFeatureFlags.useArrayNativeAccessor) {
|
|
jniPassCounter++;
|
|
return getIntNative(index);
|
|
}
|
|
return ((Double) getLocalArray()[index]).intValue();
|
|
}
|
|
private native int getIntNative(int index);
|
|
|
|
@Override
|
|
public @Nullable String getString(int index) {
|
|
if (ReactFeatureFlags.useArrayNativeAccessor) {
|
|
jniPassCounter++;
|
|
return getStringNative(index);
|
|
}
|
|
return (String) getLocalArray()[index];
|
|
}
|
|
private native String getStringNative(int index);
|
|
|
|
@Override
|
|
public @Nullable ReadableNativeArray getArray(int index) {
|
|
if (ReactFeatureFlags.useArrayNativeAccessor) {
|
|
jniPassCounter++;
|
|
return getArrayNative(index);
|
|
}
|
|
return (ReadableNativeArray) getLocalArray()[index];
|
|
}
|
|
private native ReadableNativeArray getArrayNative(int index);
|
|
|
|
@Override
|
|
public @Nullable ReadableNativeMap getMap(int index) {
|
|
if (ReactFeatureFlags.useArrayNativeAccessor) {
|
|
jniPassCounter++;
|
|
return getMapNative(index);
|
|
}
|
|
return (ReadableNativeMap) getLocalArray()[index];
|
|
}
|
|
private native ReadableNativeMap getMapNative(int index);
|
|
|
|
@Override
|
|
public @Nonnull ReadableType getType(int index) {
|
|
if (ReactFeatureFlags.useArrayNativeAccessor) {
|
|
jniPassCounter++;
|
|
return getTypeNative(index);
|
|
}
|
|
return getLocalTypeArray()[index];
|
|
}
|
|
|
|
private native ReadableType getTypeNative(int index);
|
|
|
|
@Override
|
|
public @Nonnull Dynamic getDynamic(int index) {
|
|
return DynamicFromArray.create(this, index);
|
|
}
|
|
|
|
@Override
|
|
public @Nonnull ArrayList<Object> toArrayList() {
|
|
ArrayList<Object> arrayList = new ArrayList<>();
|
|
|
|
for (int i = 0; i < this.size(); i++) {
|
|
switch (getType(i)) {
|
|
case Null:
|
|
arrayList.add(null);
|
|
break;
|
|
case Boolean:
|
|
arrayList.add(getBoolean(i));
|
|
break;
|
|
case Number:
|
|
arrayList.add(getDouble(i));
|
|
break;
|
|
case String:
|
|
arrayList.add(getString(i));
|
|
break;
|
|
case Map:
|
|
arrayList.add(getMap(i).toHashMap());
|
|
break;
|
|
case Array:
|
|
arrayList.add(getArray(i).toArrayList());
|
|
break;
|
|
default:
|
|
throw new IllegalArgumentException("Could not convert object at index: " + i + ".");
|
|
}
|
|
}
|
|
return arrayList;
|
|
}
|
|
}
|