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 289974 b2bc470bfbc3409702c24838d1a0029aa961fb96
parent 289973 038c00218cf4afd880152ecbb2f9924aaf678e3b
child 289975 e5233a84bd57c99fd367bc96c286ed14bb849fd9
push id30112
push usercbook@mozilla.com
push dateWed, 23 Mar 2016 15:25:32 +0000
treeherdermozilla-central@6202ade0e6d6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1254761
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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);
 };