Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
import com.facebook.react.fabric.mounting.mountitems.MountItem;
import com.facebook.react.fabric.mounting.mountitems.MountItemFactory;
import com.facebook.react.fabric.mounting.mountitems.PrefetchResourcesMountItem;
import com.facebook.react.fabric.mounting.mountitems.SynchronousMountItem;
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags;
import com.facebook.react.internal.featureflags.ReactNativeNewArchitectureFeatureFlags;
import com.facebook.react.internal.interop.InteropEventEmitter;
Expand Down Expand Up @@ -178,7 +179,7 @@ public class FabricUIManager

private final BatchEventDispatchedListener mBatchEventDispatchedListener;

private final CopyOnWriteArrayList<UIManagerListener> mListeners = new CopyOnWriteArrayList<>();
private final List<UIManagerListener> mListeners = new CopyOnWriteArrayList<>();

private boolean mMountNotificationScheduled = false;
private List<Integer> mSurfaceIdsWithPendingMountNotification = new ArrayList<>();
Expand Down Expand Up @@ -791,35 +792,7 @@ public void synchronouslyUpdateViewOnUIThread(final int reactTag, final Readable
// android.view.View.updateDisplayListIfDirty(View.java:20466)
// 3. A view is deleted while its parent is being drawn, causing a crash.

MountItem synchronousMountItem =
new MountItem() {
@Override
public void execute(MountingManager mountingManager) {
try {
mountingManager.storeSynchronousMountPropsOverride(reactTag, props);
mountingManager.updatePropsSynchronously(reactTag, props);
} catch (Exception ex) {
// TODO T42943890: Fix animations in Fabric and remove this try/catch?
// There might always be race conditions between surface teardown and
// animations/other operations, so it may not be feasible to remove this.
// Practically 100% of reported errors from this point are because the
// surface has stopped by this point, but the MountItem was queued before
// the surface was stopped. It's likely not feasible to prevent all such races.
}
}

@Override
public int getSurfaceId() {
return View.NO_ID;
}

@Override
public String toString() {
String propsString =
IS_DEVELOPMENT_ENVIRONMENT ? props.toHashMap().toString() : "<hidden>";
return String.format("SYNC UPDATE PROPS [%d]: %s", reactTag, propsString);
}
};
MountItem synchronousMountItem = new SynchronousMountItem(reactTag, props);

// If the reactTag exists, we assume that it might at the end of the next
// batch of MountItems. Otherwise, we try to execute immediately.
Expand Down Expand Up @@ -1399,24 +1372,21 @@ public void didMountItems(@Nullable List<? extends MountItem> mountItems) {
// delay paint.
UiThreadUtil.getUiThreadHandler()
.postAtFrontOfQueue(
new Runnable() {
@Override
public void run() {
mMountNotificationScheduled = false;

// Create a copy in case mount hooks trigger more mutations
final List<Integer> surfaceIdsToReportMount =
mSurfaceIdsWithPendingMountNotification;
mSurfaceIdsWithPendingMountNotification = new ArrayList<>();

final @Nullable FabricUIManagerBinding binding = mBinding;
if (binding == null || mDestroyed) {
return;
}

for (int surfaceId : surfaceIdsToReportMount) {
binding.reportMount(surfaceId);
}
() -> {
mMountNotificationScheduled = false;

// Create a copy in case mount hooks trigger more mutations
final List<Integer> surfaceIdsToReportMount =
mSurfaceIdsWithPendingMountNotification;
mSurfaceIdsWithPendingMountNotification = new ArrayList<>();

final @Nullable FabricUIManagerBinding binding = mBinding;
if (binding == null || mDestroyed) {
return;
}

for (int surfaceId : surfaceIdsToReportMount) {
binding.reportMount(surfaceId);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ internal class MountingManager(
private val rootViewManager = RootViewManager()

internal fun interface MountItemExecutor {
@UiThread @ThreadConfined(ThreadConfined.UI) fun executeItems(items: Queue<MountItem?>?)
@UiThread @ThreadConfined(ThreadConfined.UI) fun executeItems(items: Queue<MountItem>)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import com.facebook.react.fabric.mounting.MountingManager
* for views that were preallcated but never mounted on the screen.
*/
internal class DestroyUnmountedViewMountItem(
private val _surfaceId: Int,
private val surfaceId: Int,
private val reactTag: Int,
) : MountItem {

override fun execute(mountingManager: MountingManager) {
val surfaceMountingManager = mountingManager.getSurfaceManager(_surfaceId) ?: return
val surfaceMountingManager = mountingManager.getSurfaceManager(surfaceId) ?: return
surfaceMountingManager.deleteView(reactTag)
}

override fun getSurfaceId(): Int = _surfaceId
override fun getSurfaceId(): Int = surfaceId
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
package com.facebook.react.fabric.mounting.mountitems

import com.facebook.common.logging.FLog
import com.facebook.proguard.annotations.DoNotStripAny
import com.facebook.react.bridge.ReactMarker
import com.facebook.react.bridge.ReactMarkerConstants
import com.facebook.react.bridge.ReadableMap
Expand All @@ -31,7 +30,8 @@ import java.util.Locale
* The purpose of encapsulating the array of MountItems this way, is to reduce the amount of
* allocations in C++ and JNI round-trips.
*/
@DoNotStripAny
private const val TAG = "IntBufferBatchMountItem"

internal class IntBufferBatchMountItem(
private val surfaceId: Int,
private val intBuffer: IntArray,
Expand Down Expand Up @@ -341,8 +341,6 @@ internal class IntBufferBatchMountItem(
}

companion object {
val TAG: String = IntBufferBatchMountItem::class.java.simpleName

const val INSTRUCTION_FLAG_MULTIPLE: Int = 1

const val INSTRUCTION_CREATE: Int = 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ import com.facebook.react.bridge.ReactSoftExceptionLogger
import com.facebook.react.bridge.RetryableMountingLayerException
import com.facebook.react.fabric.mounting.MountingManager

private const val TAG = "SendAccessibilityEventMountItem"

internal class SendAccessibilityEventMountItem(
private val _surfaceId: Int,
private val surfaceId: Int,
private val reactTag: Int,
private val eventType: Int,
) : MountItem {

private val TAG = "Fabric.SendAccessibilityEvent"

override fun execute(mountingManager: MountingManager) {
try {
mountingManager.sendAccessibilityEvent(_surfaceId, reactTag, eventType)
mountingManager.sendAccessibilityEvent(surfaceId, reactTag, eventType)
} catch (e: RetryableMountingLayerException) {
// Accessibility events are similar to commands in that they're imperative
// calls from JS, disconnected from the commit lifecycle, and therefore
Expand All @@ -35,7 +35,7 @@ internal class SendAccessibilityEventMountItem(
}
}

override fun getSurfaceId(): Int = _surfaceId
override fun getSurfaceId(): Int = surfaceId

override fun toString(): String = "SendAccessibilityEventMountItem [$reactTag] $eventType"
override fun toString(): String = "$TAG [$reactTag] $eventType"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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.fabric.mounting.mountitems

import android.view.View
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.fabric.FabricUIManager.IS_DEVELOPMENT_ENVIRONMENT
import com.facebook.react.fabric.mounting.MountingManager

internal class SynchronousMountItem(private val reactTag: Int, private val props: ReadableMap) :
MountItem {

override fun execute(mountingManager: MountingManager) {
try {
mountingManager.storeSynchronousMountPropsOverride(reactTag, props)
mountingManager.updatePropsSynchronously(reactTag, props)
} catch (ex: Exception) {
// TODO T42943890: Fix animations in Fabric and remove this try/catch?
// There might always be race conditions between surface teardown and
// animations/other operations, so it may not be feasible to remove this.
// Practically 100% of reported errors from this point are because the
// surface has stopped by this point, but the MountItem was queued before
// the surface was stopped. It's likely not feasible to prevent all such races.
}
}

override fun toString(): String {
val propsString = if (IS_DEVELOPMENT_ENVIRONMENT) props.toHashMap().toString() else "<hidden>"
return "SYNC UPDATE PROPS [$reactTag]: $propsString"
}

override fun getSurfaceId(): Int = View.NO_ID
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ public open class ReactViewManager : ReactClippingViewManager<ReactViewGroup>()
}

init {
if (ReactNativeFeatureFlags.enableViewRecyclingForView()) {
if (
ReactNativeFeatureFlags.enableViewRecyclingForView() &&
this.javaClass == ReactViewManager::class.java
) {
setupViewRecycling()
}
}
Expand Down
Loading