Bug 1370123 - Ignore animation restyle requests for elements in documents without a pres shell; r=heycam
authorBrian Birtles <birtles@gmail.com>
Wed, 21 Jun 2017 08:48:21 +0900
changeset 607444 9858b929fbb6331575770362b8b8bcf0b7f9f5b5
parent 607443 cd8e522d279890d6f3732b59b8823defa9bd8a24
child 607445 f8610fc5aa2f69020b64e8aae40089f2ddd7a5a2
push id67985
push userbmo:emilio+bugs@crisal.io
push dateWed, 12 Jul 2017 08:36:44 +0000
reviewersheycam
bugs1370123
milestone56.0a1
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
dom/animation/EffectCompositor.cpp
--- 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);