Fabric: Preventing an obsolete state to be committed

Summary:
It's okay in Fabric model to commit some subtrees which are kinda obsolete (that's strange but technically it's not against the model), but it's not okay to commit some states that were already committed before.
This diff prevents that.

Reviewed By: JoshuaGross

Differential Revision: D17053428

fbshipit-source-id: fb3536312163b7b57011647b4ba7b931c2179d89
This commit is contained in:
Valentin Shergin 2019-08-28 21:08:27 -07:00 коммит произвёл Facebook Github Bot
Родитель f8e5093823
Коммит 876a2789db
2 изменённых файлов: 28 добавлений и 0 удалений

Просмотреть файл

@ -49,6 +49,14 @@ class State {
* Must be used by `ShadowNode` *only*.
*/
State::Shared getCommitedState() const;
/*
* Indicates that the state was committed once and then was replaced by a
* newer one.
* To be used by `StateCoordinator` only.
* Protected by mutex inside `StateCoordinator`.
*/
mutable bool isObsolete_{false};
};
} // namespace react

Просмотреть файл

@ -24,6 +24,26 @@ const StateTarget &StateCoordinator::getTarget() const {
void StateCoordinator::setTarget(StateTarget &&target) const {
std::unique_lock<better::shared_mutex> lock(mutex_);
assert(target && "`StateTarget` must not be empty.");
if (target_) {
auto &previousState = target_.getShadowNode().getState();
auto &nextState = target.getShadowNode().getState();
/*
* Checking and setting `isObsolete_` prevents old states to be recommitted
* on top of fresher states. It's okay to commit a tree with "older" Shadow
* Nodes (the evolution of nodes is not linear), however, we never back out
* states (they progress linearly).
*/
if (nextState->isObsolete_) {
return;
}
previousState->isObsolete_ = true;
}
target_ = std::move(target);
}