Bug 1254761 - Part 1: Implement getAnimations({ subtree: true }). r=smaug
authorDaisuke Akatsuka <daisuke@mozilla-japan.org>
Tue, 22 Mar 2016 09:33:02 +0900
changeset 289978 b2bc470bfbc3409702c24838d1a0029aa961fb96
parent 289977 038c00218cf4afd880152ecbb2f9924aaf678e3b
child 289979 e5233a84bd57c99fd367bc96c286ed14bb849fd9
push id18337
push usercbook@mozilla.com
push dateWed, 23 Mar 2016 15:30:25 +0000
treeherderfx-team@67ac681f7e53 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1254761
milestone48.0a1
Bug 1254761 - Part 1: Implement getAnimations({ subtree: true }). r=smaug
dom/animation/CSSPseudoElement.cpp
dom/animation/CSSPseudoElement.h
dom/base/Element.cpp
dom/base/Element.h
dom/base/nsDocument.cpp
dom/webidl/Animatable.webidl
--- a/dom/animation/CSSPseudoElement.cpp
+++ b/dom/animation/CSSPseudoElement.cpp
@@ -45,17 +45,18 @@ CSSPseudoElement::GetParentObject() cons
 
 JSObject*
 CSSPseudoElement::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return CSSPseudoElementBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
-CSSPseudoElement::GetAnimations(nsTArray<RefPtr<Animation>>& aRetVal)
+CSSPseudoElement::GetAnimations(const AnimationFilter& filter,
+                                nsTArray<RefPtr<Animation>>& aRetVal)
 {
   nsIDocument* doc = mParentElement->GetComposedDoc();
   if (doc) {
     doc->FlushPendingNotifications(Flush_Style);
   }
 
   Element::GetAnimationsUnsorted(mParentElement, mPseudoType, aRetVal);
   aRetVal.Sort(AnimationPtrComparator<RefPtr<Animation>>());
--- a/dom/animation/CSSPseudoElement.h
+++ b/dom/animation/CSSPseudoElement.h
@@ -52,17 +52,18 @@ public:
       nsDependentAtomString(nsCSSPseudoElements::GetPseudoAtom(mPseudoType)));
   }
   already_AddRefed<Element> ParentElement() const
   {
     RefPtr<Element> retVal(mParentElement);
     return retVal.forget();
   }
 
-  void GetAnimations(nsTArray<RefPtr<Animation>>& aRetVal);
+  void GetAnimations(const AnimationFilter& filter,
+                     nsTArray<RefPtr<Animation>>& aRetVal);
   already_AddRefed<Animation>
     Animate(JSContext* aContext,
             JS::Handle<JSObject*> aFrames,
             const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
             ErrorResult& aError);
 
   // Given an element:pseudoType pair, returns the CSSPseudoElement stored as a
   // property on |aElement|. If there is no CSSPseudoElement for the specified
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -3374,17 +3374,18 @@ Element::Animate(const Nullable<ElementO
   if (aError.Failed()) {
     return nullptr;
   }
 
   return animation.forget();
 }
 
 void
-Element::GetAnimations(nsTArray<RefPtr<Animation>>& aAnimations)
+Element::GetAnimations(const AnimationFilter& filter,
+                       nsTArray<RefPtr<Animation>>& aAnimations)
 {
   nsIDocument* doc = GetComposedDoc();
   if (doc) {
     doc->FlushPendingNotifications(Flush_Style);
   }
 
   Element* elem = this;
   CSSPseudoElementType pseudoType = CSSPseudoElementType::NotPseudo;
@@ -3398,17 +3399,36 @@ Element::GetAnimations(nsTArray<RefPtr<A
     elem = GetParentElement();
     pseudoType = CSSPseudoElementType::after;
   }
 
   if (!elem) {
     return;
   }
 
-  GetAnimationsUnsorted(elem, pseudoType, aAnimations);
+  if (!filter.mSubtree ||
+      pseudoType == CSSPseudoElementType::before ||
+      pseudoType == CSSPseudoElementType::after) {
+    GetAnimationsUnsorted(elem, pseudoType, aAnimations);
+  } else {
+    for (nsIContent* node = this;
+         node;
+         node = node->GetNextNode(this)) {
+      if (!node->IsElement()) {
+        continue;
+      }
+      Element* element = node->AsElement();
+      Element::GetAnimationsUnsorted(element, CSSPseudoElementType::NotPseudo,
+                                     aAnimations);
+      Element::GetAnimationsUnsorted(element, CSSPseudoElementType::before,
+                                     aAnimations);
+      Element::GetAnimationsUnsorted(element, CSSPseudoElementType::after,
+                                     aAnimations);
+    }
+  }
   aAnimations.Sort(AnimationPtrComparator<RefPtr<Animation>>());
 }
 
 /* static */ void
 Element::GetAnimationsUnsorted(Element* aElement,
                                CSSPseudoElementType aPseudoType,
                                nsTArray<RefPtr<Animation>>& aAnimations)
 {
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -50,16 +50,17 @@ struct nsRect;
 class nsFocusManager;
 class nsGlobalWindow;
 class nsICSSDeclaration;
 class nsISMILAttr;
 class nsDocument;
 
 namespace mozilla {
 namespace dom {
+  struct AnimationFilter;
   struct ScrollIntoViewOptions;
   struct ScrollToOptions;
   class ElementOrCSSPseudoElement;
   class UnrestrictedDoubleOrKeyframeAnimationOptions;
 } // namespace dom
 } // namespace mozilla
 
 
@@ -839,17 +840,18 @@ public:
   static already_AddRefed<Animation>
   Animate(const Nullable<ElementOrCSSPseudoElement>& aTarget,
           JSContext* aContext,
           JS::Handle<JSObject*> aFrames,
           const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
           ErrorResult& aError);
 
   // Note: GetAnimations will flush style while GetAnimationsUnsorted won't.
-  void GetAnimations(nsTArray<RefPtr<Animation>>& aAnimations);
+  void GetAnimations(const AnimationFilter& filter,
+                     nsTArray<RefPtr<Animation>>& aAnimations);
   static void GetAnimationsUnsorted(Element* aElement,
                                     CSSPseudoElementType aPseudoType,
                                     nsTArray<RefPtr<Animation>>& aAnimations);
 
   NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML);
   virtual void SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError);
   void GetOuterHTML(nsAString& aOuterHTML);
   void SetOuterHTML(const nsAString& aOuterHTML, ErrorResult& aError);
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -196,16 +196,17 @@
 
 #include "mozilla/Preferences.h"
 
 #include "imgILoader.h"
 #include "imgRequestProxy.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsSandboxFlags.h"
 #include "nsIAppsService.h"
+#include "mozilla/dom/AnimatableBinding.h"
 #include "mozilla/dom/AnonymousContent.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/DocumentTimeline.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/HTMLBodyElement.h"
 #include "mozilla/dom/HTMLInputElement.h"
 #include "mozilla/dom/MediaQueryList.h"
@@ -3195,36 +3196,23 @@ nsDocument::Timeline()
   }
 
   return mDocumentTimeline;
 }
 
 void
 nsDocument::GetAnimations(nsTArray<RefPtr<Animation>>& aAnimations)
 {
-  FlushPendingNotifications(Flush_Style);
-
-  for (nsIContent* node = nsINode::GetFirstChild();
-       node;
-       node = node->GetNextNode(this)) {
-    if (!node->IsElement()) {
-      continue;
-    }
-
-    Element* element = node->AsElement();
-    Element::GetAnimationsUnsorted(element, CSSPseudoElementType::NotPseudo,
-                                   aAnimations);
-    Element::GetAnimationsUnsorted(element, CSSPseudoElementType::before,
-                                   aAnimations);
-    Element::GetAnimationsUnsorted(element, CSSPseudoElementType::after,
-                                   aAnimations);
-  }
-
-  // Sort animations by priority
-  aAnimations.Sort(AnimationPtrComparator<RefPtr<Animation>>());
+  Element* root = GetRootElement();
+  if (!root) {
+    return;
+  }
+  AnimationFilter filter;
+  filter.mSubtree = true;
+  root->GetAnimations(filter, aAnimations);
 }
 
 /* Return true if the document is in the focused top-level window, and is an
  * ancestor of the focused DOMWindow. */
 NS_IMETHODIMP
 nsDocument::HasFocus(bool* aResult)
 {
   ErrorResult rv;
--- a/dom/webidl/Animatable.webidl
+++ b/dom/webidl/Animatable.webidl
@@ -9,17 +9,21 @@
  * Copyright © 2014 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
 dictionary KeyframeAnimationOptions : KeyframeEffectOptions {
   DOMString id = "";
 };
 
+dictionary AnimationFilter {
+  boolean subtree = false;
+};
+
 [NoInterfaceObject]
 interface Animatable {
   [Func="nsDocument::IsWebAnimationsEnabled", Throws]
   Animation animate(object? frames,
                     optional (unrestricted double or KeyframeAnimationOptions)
                       options);
   [Func="nsDocument::IsWebAnimationsEnabled"]
-  sequence<Animation> getAnimations();
+  sequence<Animation> getAnimations(optional AnimationFilter filter);
 };