Bug 1370123 - Ignore animation restyle requests for elements in documents without a pres shell; r?heycam
This patch makes us ignore animation restyle requests for elements in documents
without a pres shell made by either:
* Calls to EffectCompositor::RequestRestyle (e.g. by calling Web Animations API
methods on animations that target such elements)
* Calls to EffectCompostior::PreTraverse(dom::Element*, CSSPseudoElementType)
(e.g. by calling getComputedStyle(elem).prop on such an element).
The other overloads of PreTraverse should presumably be called during regular
document restyling where the element is expected to be in a displayed document
and hence we simply assert that that is the case for those methods.
MozReview-Commit-ID: FZD0hKAXYEf
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -254,18 +254,19 @@ EffectCompositor::RequestRestyle(dom::El
RestyleType aRestyleType,
CascadeLevel aCascadeLevel)
{
if (!mPresContext) {
// Pres context will be null after the effect compositor is disconnected.
return;
}
- // Ignore animations on orphaned elements.
- if (!aElement->IsInComposedDoc()) {
+ // Ignore animations on orphaned elements and elements in documents without
+ // a pres shell (e.g. XMLHttpRequest responseXML documents).
+ if (!nsComputedDOMStyle::GetPresShellForContent(aElement)) {
return;
}
auto& elementsToRestyle = mElementsToRestyle[aCascadeLevel];
PseudoElementHashEntry::KeyType key = { aElement, aPseudoType };
if (aRestyleType == RestyleType::Throttled) {
elementsToRestyle.LookupForAdd(key).OrInsert([]() { return false; });
@@ -482,16 +483,20 @@ EffectCompositor::GetServoAnimationRule(
const dom::Element* aElement,
CSSPseudoElementType aPseudoType,
CascadeLevel aCascadeLevel,
RawServoAnimationValueMapBorrowedMut aAnimationValues)
{
MOZ_ASSERT(aAnimationValues);
MOZ_ASSERT(mPresContext && mPresContext->IsDynamic(),
"Should not be in print preview");
+ // Gecko_GetAnimationRule should have already checked this
+ MOZ_ASSERT(nsComputedDOMStyle::GetPresShellForContent(aElement),
+ "Should not be trying to run animations on elements in documents"
+ " without a pres shell (e.g. XMLHttpRequest documents)");
EffectSet* effectSet = EffectSet::GetEffectSet(aElement, aPseudoType);
if (!effectSet) {
return false;
}
// Get a list of effects sorted by composite order.
nsTArray<KeyframeEffectReadOnly*> sortedEffectList(effectSet->Count());
@@ -960,16 +965,19 @@ EffectCompositor::PreTraverse(AnimationR
}
bool
EffectCompositor::PreTraverseInSubtree(Element* aRoot,
AnimationRestyleType aRestyleType)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mPresContext->RestyleManager()->IsServo());
+ MOZ_ASSERT(!aRoot || nsComputedDOMStyle::GetPresShellForContent(aRoot),
+ "Traversal root, if provided, should be bound to a display "
+ "document");
AutoRestore<bool> guard(mIsInPreTraverse);
mIsInPreTraverse = true;
// We need to force flush all throttled animations if we also have
// non-animation restyles (since we'll want the up-to-date animation style
// when we go to process them so we can trigger transitions correctly), and
// if we are currently flushing all throttled animation restyles.
@@ -1078,16 +1086,23 @@ EffectCompositor::PreTraverseInSubtree(E
bool
EffectCompositor::PreTraverse(dom::Element* aElement,
CSSPseudoElementType aPseudoType)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mPresContext->RestyleManager()->IsServo());
+ // If |aElement|'s document does not have a pres shell, e.g. it is document
+ // without a browsing context such as we might get from an XMLHttpRequest, we
+ // should not run animations on it.
+ if (!nsComputedDOMStyle::GetPresShellForContent(aElement)) {
+ return false;
+ }
+
bool found = false;
if (aPseudoType != CSSPseudoElementType::NotPseudo &&
aPseudoType != CSSPseudoElementType::before &&
aPseudoType != CSSPseudoElementType::after) {
return found;
}
AutoRestore<bool> guard(mIsInPreTraverse);