From 183b1c13c46df9c44ca4f832fae8669119dc95bc Mon Sep 17 00:00:00 2001 From: Joshua Gross Date: Thu, 23 Jan 2020 15:18:54 -0800 Subject: [PATCH] Always create new State object from latest Summary: Since we're using `tryCommit`, there could be races between two updates to state attached to the same node, especially if a ComponentDescriptor's `createState` implementation uses previous state data to create the new state object. By creating the State object from the "old" node within the tryCommit lambda, we prevent races. Changelog: [Internal] Reviewed By: shergin Differential Revision: D19542908 fbshipit-source-id: 787e4aefc573adf1fa308a6fa859123976a823e7 --- ReactCommon/fabric/uimanager/UIManager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ReactCommon/fabric/uimanager/UIManager.cpp b/ReactCommon/fabric/uimanager/UIManager.cpp index ba322cbe42f..88f57b32785 100644 --- a/ReactCommon/fabric/uimanager/UIManager.cpp +++ b/ReactCommon/fabric/uimanager/UIManager.cpp @@ -195,16 +195,16 @@ LayoutMetrics UIManager::getRelativeLayoutMetrics( void UIManager::updateState( ShadowNode const &shadowNode, StateData::Shared const &rawStateData) const { - auto &componentDescriptor = shadowNode.getComponentDescriptor(); - auto state = - componentDescriptor.createState(shadowNode.getState(), rawStateData); - shadowTreeRegistry_.visit( shadowNode.getSurfaceId(), [&](ShadowTree const &shadowTree) { shadowTree.tryCommit([&](RootShadowNode::Shared const &oldRootShadowNode) { return oldRootShadowNode->clone( shadowNode, [&](ShadowNode const &oldShadowNode) { + auto &componentDescriptor = + oldShadowNode.getComponentDescriptor(); + auto state = componentDescriptor.createState( + oldShadowNode.getState(), rawStateData); return oldShadowNode.clone({ /* .props = */ ShadowNodeFragment::propsPlaceholder(), /* .children = */ ShadowNodeFragment::childrenPlaceholder(),