diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerModule.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerModule.java index dbed0e09d66..c920f3d3742 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerModule.java @@ -2,6 +2,7 @@ package com.facebook.react.fabric; +import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReadableNativeMap; import com.facebook.react.modules.i18nmanager.I18nUtil; @@ -48,7 +49,7 @@ public class FabricUIManagerModule implements UIModule { ReactShadowNode node = viewManager.createShadowNodeInstance(mReactApplicationContext); node.setRootNode(getRootNode(rootTag)); node.setReactTag(reactTag); - ReactStylesDiffMap styles = updateProps(props, node); + ReactStylesDiffMap styles = updateProps(node, props); return node; } @@ -57,7 +58,7 @@ public class FabricUIManagerModule implements UIModule { return mRootShadowNodeRegistry.getNode(rootTag); } - private ReactStylesDiffMap updateProps(ReadableNativeMap props, ReactShadowNode node) { + private ReactStylesDiffMap updateProps(ReactShadowNode node, @Nullable ReadableNativeMap props) { ReactStylesDiffMap styles = null; if (props != null) { styles = new ReactStylesDiffMap(props); @@ -73,7 +74,9 @@ public class FabricUIManagerModule implements UIModule { */ @Nullable public ReactShadowNode cloneNode(ReactShadowNode node) { - return node.mutableCopy(); + ReactShadowNode clone = node.mutableCopy(); + assertReactShadowNodeCopy(node, clone); + return clone; } /** @@ -83,8 +86,8 @@ public class FabricUIManagerModule implements UIModule { */ @Nullable public ReactShadowNode cloneNodeWithNewChildren(ReactShadowNode node) { - ReactShadowNode clone = cloneNode(node); - clone.removeAllChildren(); + ReactShadowNode clone = node.mutableCopyWithNewChildren(); + assertReactShadowNodeCopy(node, clone); return clone; } @@ -94,9 +97,12 @@ public class FabricUIManagerModule implements UIModule { * props will be overridden with the {@link ReadableMap} received by parameter. */ @Nullable - public ReactShadowNode cloneNodeWithNewProps(ReactShadowNode node, ReadableNativeMap newProps) { - ReactShadowNode clone = cloneNode(node); - updateProps(newProps, clone); + public ReactShadowNode cloneNodeWithNewProps( + ReactShadowNode node, + @Nullable ReadableNativeMap newProps) { + ReactShadowNode clone = node.mutableCopy(); + updateProps(clone, newProps); + assertReactShadowNodeCopy(node, clone); return clone; } @@ -110,11 +116,18 @@ public class FabricUIManagerModule implements UIModule { public ReactShadowNode cloneNodeWithNewChildrenAndProps( ReactShadowNode node, ReadableNativeMap newProps) { - ReactShadowNode clone = cloneNodeWithNewChildren(node); - updateProps(newProps, clone); + ReactShadowNode clone = node.mutableCopyWithNewChildren(); + updateProps(clone, newProps); + assertReactShadowNodeCopy(node, clone); return clone; } + private void assertReactShadowNodeCopy(ReactShadowNode source, ReactShadowNode target) { + Assertions.assertCondition(source.getClass().equals(target.getClass()), + "Found " + target.getClass() + " class when expecting: " + source.getClass() + + ". Check that " + source.getClass() + " implements the mutableCopy() method correctly."); + } + /** * Appends the child {@link ReactShadowNode} to the children set of the parent * {@link ReactShadowNode}. diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNode.java index 69c130aa80b..af0841a487c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNode.java @@ -72,6 +72,8 @@ public interface ReactShadowNode { */ T mutableCopy(); + T mutableCopyWithNewChildren(); + String getViewClass(); boolean hasUpdates(); @@ -164,8 +166,6 @@ public interface ReactShadowNode { T removeNativeChildAt(int i); - void removeAllChildren(); - void removeAllNativeChildren(); int getNativeChildCount(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java index 59ab9b69ec3..92a4d57fe19 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java @@ -9,6 +9,7 @@ package com.facebook.react.uimanager; import static java.lang.System.arraycopy; import com.facebook.infer.annotation.Assertions; +import com.facebook.react.bridge.ReadableMap; import com.facebook.react.uimanager.annotations.ReactPropertyHolder; import com.facebook.yoga.YogaAlign; import com.facebook.yoga.YogaBaselineFunction; @@ -128,6 +129,14 @@ public class ReactShadowNodeImpl implements ReactShadowNode return new ReactShadowNodeImpl(this); } + @Override + public ReactShadowNodeImpl mutableCopyWithNewChildren() { + ReactShadowNodeImpl copy = mutableCopy(); + copy.mNativeChildren = null; + copy.mChildren = null; + return copy; + } + /** * Nodes that return {@code true} will be treated as "virtual" nodes. That is, nodes that are not * mapped into native views (e.g. nested text node). By default this method returns {@code false}. @@ -484,14 +493,6 @@ public class ReactShadowNodeImpl implements ReactShadowNode return removed; } - @Override - public final void removeAllChildren() { - removeAllNativeChildren(); - if (mChildren != null) { - mChildren.clear(); - } - } - @Override public final void removeAllNativeChildren() { if (mNativeChildren != null) {