Bug 1171817 part 14 - Add AnimationPtrComparator class; r=dbaron
authorBrian Birtles <birtles@gmail.com>
Tue, 09 Jun 2015 11:13:54 +0900
changeset 251991 6a5491acd59ccdeaa0baf2ca3b4329dcf677f8dd
parent 251990 30804bf4a909146d613c2d0f90ca21fa2c583348
child 251992 1a626010d4d9eafb2b26fb8cfd939bc79ae9d14b
push id29020
push usercbook@mozilla.com
push dateThu, 09 Jul 2015 15:56:37 +0000
treeherdermozilla-central@d656ef3c4936 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs1171817, 1150810
milestone42.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 1171817 part 14 - Add AnimationPtrComparator class; r=dbaron Having created composite ordering methods for the different kinds of animations this patch adds a Comparator class so that they can be used to sort an array of such animations. This patch uses this Comparator object to sort the results returned by Element.getAnimations. For this case, the order in which we create animations and transitions happens to almost perfectly correspond with the composite ordering defined so that no sorting is necessary. One exception is that some -moz-* transitions may be created after transitions that they should sort before when sorting by transition property. In this case the sorting added in this patch should ensure they are returned in the correct sequence. Unfortunately, we can't easily test this since the test files we have are intended to be cross-browser (where -moz-* properties won't be supported). Once we implement AnimationTimeline.getAnimations (bug 1150810) we'll have a better opportunity to test this sorting. For now, the added tests in this patch just serve as a regression test that the sorting hasn't upset the already correct order (and an interop test in future once we move them to web-platform-tests).
dom/animation/AnimationComparator.h
dom/animation/moz.build
dom/animation/test/css-transitions/file_element-get-animations.html
dom/animation/test/testcommon.js
dom/base/Element.cpp
new file mode 100644
--- /dev/null
+++ b/dom/animation/AnimationComparator.h
@@ -0,0 +1,32 @@
+/* -*- 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/. */
+
+#ifndef mozilla_AnimationComparator_h
+#define mozilla_AnimationComparator_h
+
+namespace mozilla {
+
+// Although this file is called AnimationComparator, we don't actually
+// implement AnimationComparator (to compare const Animation& parameters)
+// since it's not actually needed (yet).
+
+template<typename AnimationPtrType>
+class AnimationPtrComparator {
+public:
+  bool Equals(const AnimationPtrType& a, const AnimationPtrType& b) const
+  {
+    return a == b;
+  }
+
+  bool LessThan(const AnimationPtrType& a, const AnimationPtrType& b) const
+  {
+    return a->HasLowerCompositeOrderThan(*b);
+  }
+};
+
+} // namespace mozilla
+
+#endif // mozilla_AnimationComparator_h
--- a/dom/animation/moz.build
+++ b/dom/animation/moz.build
@@ -11,16 +11,17 @@ EXPORTS.mozilla.dom += [
     'Animation.h',
     'AnimationEffectReadOnly.h',
     'AnimationTimeline.h',
     'DocumentTimeline.h',
     'KeyframeEffect.h',
 ]
 
 EXPORTS.mozilla += [
+    'AnimationComparator.h',
     'AnimationUtils.h',
     'PendingAnimationTracker.h',
 ]
 
 UNIFIED_SOURCES += [
     'Animation.cpp',
     'AnimationEffectReadOnly.cpp',
     'AnimationTimeline.cpp',
--- a/dom/animation/test/css-transitions/file_element-get-animations.html
+++ b/dom/animation/test/css-transitions/file_element-get-animations.html
@@ -32,17 +32,17 @@ async_test(function(t) {
     return waitForFrame();
   })).then(t.step_func(function() {
     div.style.backgroundColor = 'green';
     animations = div.getAnimations();
     assert_equals(animations.length, 3,
       'getAnimations returns Animations for all running CSS Transitions');
     return waitForAllAnimations(animations);
   })).then(t.step_func(function() {
-    assert_true(animations[1].startTime < animations[2].startTime,
+    assert_less_than(animations[1].startTime, animations[2].startTime,
       'Animation for additional CSS transition starts after the original'
       + ' transitions and appears later in the list');
     t.done();
   }));
 }, 'getAnimations for CSS Transitions');
 
 test(function(t) {
   var div = addDiv(t, { style: 'left: 0px; transition: all 100s' });
@@ -96,11 +96,52 @@ test(function(t) {
   div.style.transition = 'all 100s';
   div.style.setProperty('-vendor-unsupported', '100px', '');
 
   assert_equals(div.getAnimations().length, 0,
     'getAnimations returns an empty sequence for a transition'
     + ' of an unsupported property');
 }, 'getAnimations for transition on unsupported property');
 
+test(function(t) {
+  var div = addDiv(t, { style: 'transform: translate(0px); ' +
+                               'opacity: 0; ' +
+                               'border-width: 0px; ' + // Shorthand
+                               'border-style: solid' });
+  getComputedStyle(div).transform;
+
+  div.style.transition = 'all 100s';
+  div.style.transform = 'translate(100px)';
+  div.style.opacity = '1';
+  div.style.borderWidth = '1px';
+
+  var animations = div.getAnimations();
+  assert_equals(animations.length, 6,
+                'Generated expected number of transitions');
+  assert_equals(animations[0].transitionProperty, 'border-bottom-width');
+  assert_equals(animations[1].transitionProperty, 'border-left-width');
+  assert_equals(animations[2].transitionProperty, 'border-right-width');
+  assert_equals(animations[3].transitionProperty, 'border-top-width');
+  assert_equals(animations[4].transitionProperty, 'opacity');
+  assert_equals(animations[5].transitionProperty, 'transform');
+}, 'getAnimations sorts simultaneous transitions by name');
+
+test(function(t) {
+  var div = addDiv(t, { style: 'transform: translate(0px); ' +
+                               'opacity: 0' });
+  getComputedStyle(div).transform;
+
+  div.style.transition = 'all 100s';
+  div.style.transform = 'translate(100px)';
+  assert_equals(div.getAnimations().length, 1,
+                'Initially there is only one (transform) transition');
+  div.style.opacity = '1';
+  assert_equals(div.getAnimations().length, 2,
+                'Then a second (opacity) transition is added');
+
+  var animations = div.getAnimations();
+  assert_equals(animations[0].transitionProperty, 'transform');
+  assert_equals(animations[1].transitionProperty, 'opacity');
+}, 'getAnimations sorts transitions by when they were generated');
+
 done();
 </script>
 </body>
--- a/dom/animation/test/testcommon.js
+++ b/dom/animation/test/testcommon.js
@@ -73,18 +73,19 @@ function waitForAllAnimations(animations
  * we actually get a transition instead of that being the initial value.
  */
 function flushComputedStyle(elem) {
   var cs = window.getComputedStyle(elem);
   cs.marginLeft;
 }
 
 for (var funcName of ["async_test", "assert_not_equals", "assert_equals",
-                      "assert_approx_equals", "assert_less_than_equal",
-                      "assert_between_inclusive", "assert_true", "assert_false",
+                      "assert_approx_equals", "assert_less_than",
+                      "assert_less_than_equal", "assert_between_inclusive",
+                      "assert_true", "assert_false",
                       "assert_class_string", "assert_throws", "test"]) {
   window[funcName] = opener[funcName].bind(opener);
 }
 
 window.EventWatcher = opener.EventWatcher;
 
 function done() {
   opener.add_completion_callback(function() {
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -46,16 +46,17 @@
 #include "nsVariant.h"
 #include "nsDOMSettableTokenList.h"
 #include "nsDOMTokenList.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsError.h"
 #include "nsDOMString.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIDOMMutationEvent.h"
+#include "mozilla/AnimationComparator.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/ContentEvents.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "mozilla/MouseEvents.h"
@@ -3196,16 +3197,18 @@ Element::GetAnimations(nsTArray<nsRefPtr
          animIdx < collection->mAnimations.Length();
          animIdx++) {
       Animation* anim = collection->mAnimations[animIdx];
       if (anim->IsRelevant()) {
         aAnimations.AppendElement(anim);
       }
     }
   }
+
+  aAnimations.Sort(AnimationPtrComparator<nsRefPtr<Animation>>());
 }
 
 NS_IMETHODIMP
 Element::GetInnerHTML(nsAString& aInnerHTML)
 {
   GetMarkup(false, aInnerHTML);
   return NS_OK;
 }