diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java index ae471c2a8c4..d6693e1d87d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java @@ -12,6 +12,7 @@ import androidx.annotation.Nullable; 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.HashMap; import java.util.Iterator; import java.util.Map; @@ -88,6 +89,64 @@ public class ReadableNativeMap extends NativeMap implements ReadableMap { return mLocalTypeMap; } + private Iterator> createExperimentalIterator() { + if (mKeys == null) { + mKeys = Assertions.assertNotNull(importKeys()); + } + final String[] iteratorKeys = mKeys; + final Object[] iteratorValues = Assertions.assertNotNull(importValues()); + return new Iterator>() { + int currentIndex = 0; + + @Override + public boolean hasNext() { + return currentIndex < iteratorKeys.length; + } + + @Override + public Map.Entry next() { + final int index = currentIndex++; + return new Map.Entry() { + @Override + public String getKey() { + return iteratorKeys[index]; + } + + @Override + public Object getValue() { + return iteratorValues[index]; + } + + @Override + public Object setValue(Object value) { + throw new UnsupportedOperationException( + "Can't set a value while iterating over a ReadableNativeMap"); + } + }; + } + }; + } + + private ReadableMapKeySetIterator createExperimentalKeySetIterator() { + if (mKeys == null) { + mKeys = Assertions.assertNotNull(importKeys()); + } + final String[] iteratorKeys = mKeys; + return new ReadableMapKeySetIterator() { + int currentIndex = 0; + + @Override + public boolean hasNextKey() { + return currentIndex < iteratorKeys.length; + } + + @Override + public String nextKey() { + return iteratorKeys[currentIndex++]; + } + }; + } + private native Object[] importTypes(); @Override @@ -187,12 +246,16 @@ public class ReadableNativeMap extends NativeMap implements ReadableMap { @Override public @NonNull Iterator> getEntryIterator() { - return getLocalMap().entrySet().iterator(); + return ReactFeatureFlags.enableExperimentalReadableNativeMapIterator + ? createExperimentalIterator() + : getLocalMap().entrySet().iterator(); } @Override public @NonNull ReadableMapKeySetIterator keySetIterator() { - return new ReadableNativeMapKeySetIterator(this); + return ReactFeatureFlags.enableExperimentalReadableNativeMapIterator + ? createExperimentalKeySetIterator() + : new ReadableNativeMapKeySetIterator(this); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java b/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java index 260d366e290..c6de0646a2b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +++ b/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java @@ -97,4 +97,7 @@ public class ReactFeatureFlags { * we verify the fix is correct in production */ public static boolean enableStartSurfaceRaceConditionFix = false; + + /** Enables the usage of an experimental optimized iterator for ReadableNativeMaps. */ + public static boolean enableExperimentalReadableNativeMapIterator = false; }