mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-21 09:15:35 +00:00
7a10d13a65
Currently we avoid posting animation restyles when unbinding an element by removing the element from the document before deleting its animation collections. As a result, when canceled animations go to post a restyle, they can't find a pres context and give up posting a restyle. However, this is problematic for two reasons: * It means we can't remove such canceled animations from the PendingAnimationTracker if they are present there (i.e. it regresses the fix from bug 1223445). * It means we can't post cancel events for such animations/transitions since we can't lookup the appropriate AnimationEventDispatcher. In the next patch in this series we will change that order to fix the above problems but before we do that, we need to introduce another mechanism to make sure that we don't post restyles when unbinding an element or else we will regress bug 1396041. This patch does that by introducing a flag which causes us to not post restyles when we are doing DOM surgery. For all other cases we actually _do_ need to post restyles in order to update the style correctly. Without this patch, layout/style/crashtests/1396041.html would fail after applying the next patch in this series. Differential Revision: https://phabricator.services.mozilla.com/D28021 --HG-- extra : moz-landing-system : lando
137 lines
4.5 KiB
C++
137 lines
4.5 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "mozilla/AnimationCollection.h"
|
|
|
|
#include "mozilla/RestyleManager.h"
|
|
#include "nsAnimationManager.h" // For dom::CSSAnimation
|
|
#include "nsPresContext.h"
|
|
#include "nsTransitionManager.h" // For dom::CSSTransition
|
|
|
|
namespace mozilla {
|
|
|
|
template <class AnimationType>
|
|
/* static */ void AnimationCollection<AnimationType>::PropertyDtor(
|
|
void* aObject, nsAtom* aPropertyName, void* aPropertyValue, void* aData) {
|
|
AnimationCollection* collection =
|
|
static_cast<AnimationCollection*>(aPropertyValue);
|
|
#ifdef DEBUG
|
|
MOZ_ASSERT(!collection->mCalledPropertyDtor, "can't call dtor twice");
|
|
collection->mCalledPropertyDtor = true;
|
|
#endif
|
|
|
|
PostRestyleMode postRestyle = collection->mCalledDestroy
|
|
? PostRestyleMode::IfNeeded
|
|
: PostRestyleMode::Never;
|
|
{
|
|
nsAutoAnimationMutationBatch mb(collection->mElement->OwnerDoc());
|
|
|
|
for (size_t animIdx = collection->mAnimations.Length(); animIdx-- != 0;) {
|
|
collection->mAnimations[animIdx]->CancelFromStyle(postRestyle);
|
|
}
|
|
}
|
|
delete collection;
|
|
}
|
|
|
|
template <class AnimationType>
|
|
/* static */ AnimationCollection<AnimationType>*
|
|
AnimationCollection<AnimationType>::GetAnimationCollection(
|
|
const dom::Element* aElement, PseudoStyleType aPseudoType) {
|
|
if (!aElement->MayHaveAnimations()) {
|
|
// Early return for the most common case.
|
|
return nullptr;
|
|
}
|
|
|
|
nsAtom* propName = GetPropertyAtomForPseudoType(aPseudoType);
|
|
if (!propName) {
|
|
return nullptr;
|
|
}
|
|
|
|
return static_cast<AnimationCollection<AnimationType>*>(
|
|
aElement->GetProperty(propName));
|
|
}
|
|
|
|
template <class AnimationType>
|
|
/* static */ AnimationCollection<AnimationType>*
|
|
AnimationCollection<AnimationType>::GetAnimationCollection(
|
|
const nsIFrame* aFrame) {
|
|
Maybe<NonOwningAnimationTarget> pseudoElement =
|
|
EffectCompositor::GetAnimationElementAndPseudoForFrame(aFrame);
|
|
if (!pseudoElement) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (!pseudoElement->mElement->MayHaveAnimations()) {
|
|
return nullptr;
|
|
}
|
|
|
|
return GetAnimationCollection(pseudoElement->mElement,
|
|
pseudoElement->mPseudoType);
|
|
}
|
|
|
|
template <class AnimationType>
|
|
/* static */ AnimationCollection<AnimationType>*
|
|
AnimationCollection<AnimationType>::GetOrCreateAnimationCollection(
|
|
dom::Element* aElement, PseudoStyleType aPseudoType,
|
|
bool* aCreatedCollection) {
|
|
MOZ_ASSERT(aCreatedCollection);
|
|
*aCreatedCollection = false;
|
|
|
|
nsAtom* propName = GetPropertyAtomForPseudoType(aPseudoType);
|
|
MOZ_ASSERT(propName,
|
|
"Should only try to create animations for one of the"
|
|
" recognized pseudo types");
|
|
|
|
auto collection = static_cast<AnimationCollection<AnimationType>*>(
|
|
aElement->GetProperty(propName));
|
|
if (!collection) {
|
|
// FIXME: Consider arena-allocating?
|
|
collection = new AnimationCollection<AnimationType>(aElement, propName);
|
|
nsresult rv = aElement->SetProperty(
|
|
propName, collection, &AnimationCollection<AnimationType>::PropertyDtor,
|
|
false);
|
|
if (NS_FAILED(rv)) {
|
|
NS_WARNING("SetProperty failed");
|
|
// The collection must be destroyed via PropertyDtor, otherwise
|
|
// mCalledPropertyDtor assertion is triggered in destructor.
|
|
AnimationCollection<AnimationType>::PropertyDtor(aElement, propName,
|
|
collection, nullptr);
|
|
return nullptr;
|
|
}
|
|
|
|
*aCreatedCollection = true;
|
|
aElement->SetMayHaveAnimations();
|
|
}
|
|
|
|
return collection;
|
|
}
|
|
|
|
template <class AnimationType>
|
|
/*static*/ nsAtom*
|
|
AnimationCollection<AnimationType>::GetPropertyAtomForPseudoType(
|
|
PseudoStyleType aPseudoType) {
|
|
nsAtom* propName = nullptr;
|
|
|
|
if (aPseudoType == PseudoStyleType::NotPseudo) {
|
|
propName = TraitsType::ElementPropertyAtom();
|
|
} else if (aPseudoType == PseudoStyleType::before) {
|
|
propName = TraitsType::BeforePropertyAtom();
|
|
} else if (aPseudoType == PseudoStyleType::after) {
|
|
propName = TraitsType::AfterPropertyAtom();
|
|
} else if (aPseudoType == PseudoStyleType::marker) {
|
|
propName = TraitsType::MarkerPropertyAtom();
|
|
}
|
|
|
|
return propName;
|
|
}
|
|
|
|
// Explicit class instantiations
|
|
|
|
template class AnimationCollection<dom::CSSAnimation>;
|
|
template class AnimationCollection<dom::CSSTransition>;
|
|
|
|
} // namespace mozilla
|