LayoutAnimations: attempt to work around potential crashes when animation is racing with setup or teardown

Summary:
Attempt to fix T68951888 where (1) ComponentHandle is zero, and/or (2) ComponentHandle is missing in the registry. Either will cause a crash and both should be trivial to work around. I was able to repro once accidentally in about 1/200 sessions, so I am not 100% sure if this fixes the root cause.

Changelog: [Internal]

Reviewed By: shergin

Differential Revision: D22216030

fbshipit-source-id: b6986adee6fe739ce58579a2b031a2d252e73e35
This commit is contained in:
Joshua Gross 2020-06-24 16:34:24 -07:00 коммит произвёл Facebook GitHub Bot
Родитель 2e27fb6a97
Коммит 6342e6e3f1
4 изменённых файлов: 44 добавлений и 10 удалений

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

@ -521,8 +521,8 @@ LayoutAnimationKeyFrameManager::pullTransaction(
mutation.type == ShadowViewMutation::Type::Remove
? mutation.oldChildShadowView
: mutation.newChildShadowView);
auto const &componentDescriptor =
getComponentDescriptorForShadowView(baselineShadowView);
bool haveComponentDescriptor =
hasComponentDescriptorForShadowView(baselineShadowView);
auto mutationConfig =
(mutation.type == ShadowViewMutation::Type::Delete
@ -660,8 +660,11 @@ LayoutAnimationKeyFrameManager::pullTransaction(
AnimationKeyFrame keyFrame{};
if (mutation.type == ShadowViewMutation::Type::Insert) {
if (mutationConfig->animationProperty ==
AnimationProperty::Opacity) {
auto props = componentDescriptor.cloneProps(viewStart.props, {});
AnimationProperty::Opacity &&
haveComponentDescriptor) {
auto props =
getComponentDescriptorForShadowView(baselineShadowView)
.cloneProps(viewStart.props, {});
const auto viewProps =
dynamic_cast<const ViewProps *>(props.get());
if (viewProps != nullptr) {
@ -675,8 +678,10 @@ LayoutAnimationKeyFrameManager::pullTransaction(
bool isScaleY = mutationConfig->animationProperty ==
AnimationProperty::ScaleY ||
mutationConfig->animationProperty == AnimationProperty::ScaleXY;
if (isScaleX || isScaleY) {
auto props = componentDescriptor.cloneProps(viewStart.props, {});
if ((isScaleX || isScaleY) && haveComponentDescriptor) {
auto props =
getComponentDescriptorForShadowView(baselineShadowView)
.cloneProps(viewStart.props, {});
const auto viewProps =
dynamic_cast<const ViewProps *>(props.get());
if (viewProps != nullptr) {
@ -695,8 +700,11 @@ LayoutAnimationKeyFrameManager::pullTransaction(
0};
} else if (mutation.type == ShadowViewMutation::Type::Delete) {
if (mutationConfig->animationProperty ==
AnimationProperty::Opacity) {
auto props = componentDescriptor.cloneProps(viewFinal.props, {});
AnimationProperty::Opacity &&
haveComponentDescriptor) {
auto props =
getComponentDescriptorForShadowView(baselineShadowView)
.cloneProps(viewFinal.props, {});
const auto viewProps =
dynamic_cast<const ViewProps *>(props.get());
if (viewProps != nullptr) {
@ -710,8 +718,10 @@ LayoutAnimationKeyFrameManager::pullTransaction(
bool isScaleY = mutationConfig->animationProperty ==
AnimationProperty::ScaleY ||
mutationConfig->animationProperty == AnimationProperty::ScaleXY;
if (isScaleX || isScaleY) {
auto props = componentDescriptor.cloneProps(viewFinal.props, {});
if ((isScaleX || isScaleY) && haveComponentDescriptor) {
auto props =
getComponentDescriptorForShadowView(baselineShadowView)
.cloneProps(viewFinal.props, {});
const auto viewProps =
dynamic_cast<const ViewProps *>(props.get());
if (viewProps != nullptr) {
@ -983,6 +993,12 @@ bool LayoutAnimationKeyFrameManager::mutatedViewIsVirtual(
return viewIsVirtual;
}
bool LayoutAnimationKeyFrameManager::hasComponentDescriptorForShadowView(
ShadowView const &shadowView) const {
return componentDescriptorRegistry_->hasComponentDescriptorAt(
shadowView.componentHandle);
}
ComponentDescriptor const &
LayoutAnimationKeyFrameManager::getComponentDescriptorForShadowView(
ShadowView const &shadowView) const {
@ -1008,6 +1024,9 @@ ShadowView LayoutAnimationKeyFrameManager::createInterpolatedShadowView(
AnimationConfig const &animationConfig,
ShadowView startingView,
ShadowView finalView) const {
if (!hasComponentDescriptorForShadowView(startingView)) {
return finalView;
}
ComponentDescriptor const &componentDescriptor =
getComponentDescriptorForShadowView(startingView);
auto mutatedShadowView = ShadowView(startingView);

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

@ -148,6 +148,7 @@ class LayoutAnimationKeyFrameManager : public UIManagerAnimationDelegate,
protected:
bool mutatedViewIsVirtual(ShadowViewMutation const &mutation) const;
bool hasComponentDescriptorForShadowView(ShadowView const &shadowView) const;
ComponentDescriptor const &getComponentDescriptorForShadowView(
ShadowView const &shadowView) const;
std::pair<double, double> calculateAnimationProgress(

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

@ -168,6 +168,18 @@ ComponentDescriptor const &ComponentDescriptorRegistry::at(
return *_registryByHandle.at(componentHandle);
}
bool ComponentDescriptorRegistry::hasComponentDescriptorAt(
ComponentHandle componentHandle) const {
std::shared_lock<better::shared_mutex> lock(mutex_);
auto iterator = _registryByHandle.find(componentHandle);
if (iterator == _registryByHandle.end()) {
return false;
}
return true;
}
SharedShadowNode ComponentDescriptorRegistry::createNode(
Tag tag,
std::string const &viewName,

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

@ -51,6 +51,8 @@ class ComponentDescriptorRegistry {
ComponentDescriptor const &at(std::string const &componentName) const;
ComponentDescriptor const &at(ComponentHandle componentHandle) const;
bool hasComponentDescriptorAt(ComponentHandle componentHandle) const;
ShadowNode::Shared createNode(
Tag tag,
std::string const &viewName,