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
This commit is contained in:
Joshua Gross
2020-01-23 15:21:09 -08:00
committed by Facebook Github Bot
parent d72e078df4
commit 183b1c13c4
+4 -4
View File
@@ -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(),