Noop when removing views from empty parent

Summary:
In some cases (BottomSheet?) the parent/ViewManager removes all children of the View before Fabric gets a chance to remove the children.

Apparently prior to D23368229 (https://github.com/facebook/react-native/commit/d344fb4e29a827d1e7d233672a3efe3b2b981a8a) (landed just today!) this sequence of operations happened and just noop'ed. Since we've been doing that happily as long as Fabric
has existed, we'll keep doing that for now.

I suspect that on *some* versions of Android this crashes and others it doesn't, based on logviews and my inability to repro certain crashes.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D23387044

fbshipit-source-id: 88a46191adef4f6816bd7babd9103d103ddcef33
This commit is contained in:
Joshua Gross
2020-08-27 19:37:06 -07:00
committed by Facebook GitHub Bot
parent 9a5ab9e366
commit e3711407a1
@@ -369,13 +369,35 @@ public class MountingManager {
int actualTag = (view != null ? view.getId() : -1);
if (actualTag != tag) {
int tagActualIndex = -1;
for (int i = 0; i < parentView.getChildCount(); i++) {
int parentChildrenCount = parentView.getChildCount();
for (int i = 0; i < parentChildrenCount; i++) {
if (parentView.getChildAt(i).getId() == tag) {
tagActualIndex = i;
break;
}
}
// TODO T74425739: previously, we did not do this check and `removeViewAt` would be executed
// below, sometimes crashing there. *However*, interestingly enough, `removeViewAt` would not
// complain if you removed views from an already-empty parent. This seems necessary currently
// for certain ViewManagers that remove their own children - like BottomSheet?
// This workaround seems not-great, but for now, we just return here for
// backwards-compatibility. Essentially, if a view has already been removed from the
// hierarchy, we treat it as a noop.
if (tagActualIndex == -1) {
FLog.e(
TAG,
"removeViewAt: ["
+ tag
+ "] -> ["
+ parentTag
+ "] @"
+ index
+ ": view already removed from parent! Children in parent: "
+ parentChildrenCount);
return;
}
throw new IllegalStateException(
"Tried to delete view ["
+ tag