diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index a5a719cc1..05ce4025e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -451,7 +451,7 @@ public class FabricUIManager implements UIManager, JSHandler { } int tag = node.getReactTag(); - if (mRootShadowNodeRegistry.getNode(tag) == null) { + if (getRootNode(tag) == null) { boolean frameDidChange = node.dispatchUpdates(absoluteX, absoluteY, mUIViewOperationQueue, null); // Notify JS about layout event if requested @@ -511,13 +511,16 @@ public class FabricUIManager implements UIManager, JSHandler { @Override @DoNotStrip - public void updateRootLayoutSpecs(int rootViewTag, int widthMeasureSpec, int heightMeasureSpec) { - ReactShadowNode rootNode = mRootShadowNodeRegistry.getNode(rootViewTag); + public synchronized void updateRootLayoutSpecs(int rootViewTag, int widthMeasureSpec, int heightMeasureSpec) { + ReactShadowNode rootNode = getRootNode(rootViewTag); if (rootNode == null) { FLog.w(ReactConstants.TAG, "Tried to update non-existent root tag: " + rootViewTag); return; } - updateRootView(rootNode, widthMeasureSpec, heightMeasureSpec); + + ReactShadowNode newRootNode = rootNode.mutableCopy(rootNode.getInstanceHandle()); + updateRootView(newRootNode, widthMeasureSpec, heightMeasureSpec); + mRootShadowNodeRegistry.replaceNode(newRootNode); } /** @@ -526,18 +529,20 @@ public class FabricUIManager implements UIManager, JSHandler { * //TODO: change synchronization to integrate with new #render loop. */ private synchronized void updateRootSize(int rootTag, int newWidth, int newHeight) { - ReactShadowNode rootNode = mRootShadowNodeRegistry.getNode(rootTag); + ReactShadowNode rootNode = getRootNode(rootTag); if (rootNode == null) { FLog.w( ReactConstants.TAG, "Tried to update size of non-existent tag: " + rootTag); return; } + + ReactShadowNode newRootNode = rootNode.mutableCopy(rootNode.getInstanceHandle()); int newWidthSpec = View.MeasureSpec.makeMeasureSpec(newWidth, View.MeasureSpec.EXACTLY); int newHeightSpec = View.MeasureSpec.makeMeasureSpec(newHeight, View.MeasureSpec.EXACTLY); - updateRootView(rootNode, newWidthSpec, newHeightSpec); + updateRootView(newRootNode, newWidthSpec, newHeightSpec); - completeRoot(rootTag, rootNode.getChildrenList()); + completeRoot(rootTag, newRootNode.getChildrenList()); } public void removeRootView(int rootTag) { 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 dffd37266..d6075b7db 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java @@ -299,6 +299,7 @@ public class ReactShadowNodeImpl implements ReactShadowNode @Override public final void markUpdateSeen() { + assertNotSealed(); mNodeUpdated = false; if (hasNewLayout()) { markLayoutSeen(); @@ -324,6 +325,7 @@ public class ReactShadowNodeImpl implements ReactShadowNode @Override public void dirty() { + assertNotSealed(); if (!isVirtual()) { mYogaNode.dirty(); } @@ -336,6 +338,7 @@ public class ReactShadowNodeImpl implements ReactShadowNode @Override public void addChildAt(ReactShadowNodeImpl child, int i) { + assertNotSealed(); if (mChildren == null) { mChildren = new ArrayList<>(4); } @@ -367,6 +370,7 @@ public class ReactShadowNodeImpl implements ReactShadowNode @Override public ReactShadowNodeImpl removeChildAt(int i) { + assertNotSealed(); if (mChildren == null) { throw new ArrayIndexOutOfBoundsException( "Index " + i + " out of bounds: node has no children"); @@ -539,6 +543,7 @@ public class ReactShadowNodeImpl implements ReactShadowNode @Override public void setReactTag(int reactTag) { + assertNotSealed(); mReactTag = reactTag; } @@ -550,11 +555,13 @@ public class ReactShadowNodeImpl implements ReactShadowNode @Override public final void setRootTag(int rootTag) { + assertNotSealed(); mRootTag = rootTag; } @Override public final void setViewClassName(String viewClassName) { + assertNotSealed(); mViewClassName = viewClassName; } @@ -596,6 +603,7 @@ public class ReactShadowNodeImpl implements ReactShadowNode @Override public final void markLayoutSeen() { + assertNotSealed(); if (mYogaNode != null) { mYogaNode.markLayoutSeen(); } @@ -607,6 +615,7 @@ public class ReactShadowNodeImpl implements ReactShadowNode */ @Override public final void addNativeChildAt(ReactShadowNodeImpl child, int nativeIndex) { + assertNotSealed(); Assertions.assertCondition(!mIsLayoutOnly); Assertions.assertCondition(!child.mIsLayoutOnly); @@ -658,6 +667,7 @@ public class ReactShadowNodeImpl implements ReactShadowNode */ @Override public final void setIsLayoutOnly(boolean isLayoutOnly) { + assertNotSealed(); Assertions.assertCondition(getParent() == null, "Must remove from no opt parent first"); Assertions.assertCondition(mNativeParent == null, "Must remove from native parent first"); Assertions.assertCondition(getNativeChildCount() == 0, "Must remove all native children first"); @@ -806,6 +816,7 @@ public class ReactShadowNodeImpl implements ReactShadowNode @Override public void setLayoutDirection(YogaDirection direction) { + assertNotSealed(); mYogaNode.setDirection(direction); } @@ -816,36 +827,43 @@ public class ReactShadowNodeImpl implements ReactShadowNode @Override public void setStyleWidth(float widthPx) { + assertNotSealed(); mYogaNode.setWidth(widthPx); } @Override public void setStyleWidthPercent(float percent) { + assertNotSealed(); mYogaNode.setWidthPercent(percent); } @Override public void setStyleWidthAuto() { + assertNotSealed(); mYogaNode.setWidthAuto(); } @Override public void setStyleMinWidth(float widthPx) { + assertNotSealed(); mYogaNode.setMinWidth(widthPx); } @Override public void setStyleMinWidthPercent(float percent) { + assertNotSealed(); mYogaNode.setMinWidthPercent(percent); } @Override public void setStyleMaxWidth(float widthPx) { + assertNotSealed(); mYogaNode.setMaxWidth(widthPx); } @Override public void setStyleMaxWidthPercent(float percent) { + assertNotSealed(); mYogaNode.setMaxWidthPercent(percent); } @@ -856,126 +874,151 @@ public class ReactShadowNodeImpl implements ReactShadowNode @Override public void setStyleHeight(float heightPx) { + assertNotSealed(); mYogaNode.setHeight(heightPx); } @Override public void setStyleHeightPercent(float percent) { + assertNotSealed(); mYogaNode.setHeightPercent(percent); } @Override public void setStyleHeightAuto() { + assertNotSealed(); mYogaNode.setHeightAuto(); } @Override public void setStyleMinHeight(float widthPx) { + assertNotSealed(); mYogaNode.setMinHeight(widthPx); } @Override public void setStyleMinHeightPercent(float percent) { + assertNotSealed(); mYogaNode.setMinHeightPercent(percent); } @Override public void setStyleMaxHeight(float widthPx) { + assertNotSealed(); mYogaNode.setMaxHeight(widthPx); } @Override public void setStyleMaxHeightPercent(float percent) { + assertNotSealed(); mYogaNode.setMaxHeightPercent(percent); } @Override public void setFlex(float flex) { + assertNotSealed(); mYogaNode.setFlex(flex); } @Override public void setFlexGrow(float flexGrow) { + assertNotSealed(); mYogaNode.setFlexGrow(flexGrow); } @Override public void setFlexShrink(float flexShrink) { + assertNotSealed(); mYogaNode.setFlexShrink(flexShrink); } @Override public void setFlexBasis(float flexBasis) { + assertNotSealed(); mYogaNode.setFlexBasis(flexBasis); } @Override public void setFlexBasisAuto() { + assertNotSealed(); mYogaNode.setFlexBasisAuto(); } @Override public void setFlexBasisPercent(float percent) { + assertNotSealed(); mYogaNode.setFlexBasisPercent(percent); } @Override public void setStyleAspectRatio(float aspectRatio) { + assertNotSealed(); mYogaNode.setAspectRatio(aspectRatio); } @Override public void setFlexDirection(YogaFlexDirection flexDirection) { + assertNotSealed(); mYogaNode.setFlexDirection(flexDirection); } @Override public void setFlexWrap(YogaWrap wrap) { + assertNotSealed(); mYogaNode.setWrap(wrap); } @Override public void setAlignSelf(YogaAlign alignSelf) { + assertNotSealed(); mYogaNode.setAlignSelf(alignSelf); } @Override public void setAlignItems(YogaAlign alignItems) { + assertNotSealed(); mYogaNode.setAlignItems(alignItems); } @Override public void setAlignContent(YogaAlign alignContent) { + assertNotSealed(); mYogaNode.setAlignContent(alignContent); } @Override public void setJustifyContent(YogaJustify justifyContent) { + assertNotSealed(); mYogaNode.setJustifyContent(justifyContent); } @Override public void setOverflow(YogaOverflow overflow) { + assertNotSealed(); mYogaNode.setOverflow(overflow); } @Override public void setDisplay(YogaDisplay display) { + assertNotSealed(); mYogaNode.setDisplay(display); } @Override public void setMargin(int spacingType, float margin) { + assertNotSealed(); mYogaNode.setMargin(YogaEdge.fromInt(spacingType), margin); } @Override public void setMarginPercent(int spacingType, float percent) { + assertNotSealed(); mYogaNode.setMarginPercent(YogaEdge.fromInt(spacingType), percent); } @Override public void setMarginAuto(int spacingType) { + assertNotSealed(); mYogaNode.setMarginAuto(YogaEdge.fromInt(spacingType)); } @@ -991,12 +1034,14 @@ public class ReactShadowNodeImpl implements ReactShadowNode @Override public void setDefaultPadding(int spacingType, float padding) { + assertNotSealed(); mDefaultPadding.set(spacingType, padding); updatePadding(); } @Override public void setPadding(int spacingType, float padding) { + assertNotSealed(); mPadding[spacingType] = padding; mPaddingIsPercent[spacingType] = false; updatePadding(); @@ -1004,12 +1049,14 @@ public class ReactShadowNodeImpl implements ReactShadowNode @Override public void setPaddingPercent(int spacingType, float percent) { + assertNotSealed(); mPadding[spacingType] = percent; mPaddingIsPercent[spacingType] = !YogaConstants.isUndefined(percent); updatePadding(); } private void updatePadding() { + assertNotSealed(); for (int spacingType = Spacing.LEFT; spacingType <= Spacing.ALL; spacingType++) { if (spacingType == Spacing.LEFT || spacingType == Spacing.RIGHT @@ -1045,36 +1092,43 @@ public class ReactShadowNodeImpl implements ReactShadowNode @Override public void setBorder(int spacingType, float borderWidth) { + assertNotSealed(); mYogaNode.setBorder(YogaEdge.fromInt(spacingType), borderWidth); } @Override public void setPosition(int spacingType, float position) { + assertNotSealed(); mYogaNode.setPosition(YogaEdge.fromInt(spacingType), position); } @Override public void setPositionPercent(int spacingType, float percent) { + assertNotSealed(); mYogaNode.setPositionPercent(YogaEdge.fromInt(spacingType), percent); } @Override public void setPositionType(YogaPositionType positionType) { + assertNotSealed(); mYogaNode.setPositionType(positionType); } @Override public void setShouldNotifyOnLayout(boolean shouldNotifyOnLayout) { + assertNotSealed(); mShouldNotifyOnLayout = shouldNotifyOnLayout; } @Override public void setBaselineFunction(YogaBaselineFunction baselineFunction) { + assertNotSealed(); mYogaNode.setBaselineFunction(baselineFunction); } @Override public void setMeasureFunction(YogaMeasureFunction measureFunction) { + assertNotSealed(); mYogaNode.setMeasureFunction(measureFunction); } @@ -1147,6 +1201,7 @@ public class ReactShadowNodeImpl implements ReactShadowNode @Override public void setInstanceHandle(long instanceHandle) { + assertNotSealed(); mInstanceHandle = instanceHandle; } @@ -1159,4 +1214,10 @@ public class ReactShadowNodeImpl implements ReactShadowNode public boolean isSealed() { return mIsSealed; } + + private void assertNotSealed() { + if (mIsSealed) { + throw new IllegalStateException("Can not modify sealed node " + toString()); + } + } }