Bug 1216872 - Make 100% Keyframe returned by getFrames() have easing:linear. r=birtles
authorCameron McCormack <cam@mcc.id.au>
Thu, 22 Oct 2015 19:22:38 +1100
changeset 304137 37f496398521e93ebbea912b1c104e1ea07a6fbc
parent 304136 be64b1deaba958456eb6262f80c65ffd00978ca4
child 304138 3ff5a24c4364c2c30db6a93b94295d0583290249
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbirtles
bugs1216872
milestone44.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 1216872 - Make 100% Keyframe returned by getFrames() have easing:linear. r=birtles
dom/animation/KeyframeEffect.cpp
dom/animation/test/css-animations/file_keyframeeffect-getframes.html
dom/animation/test/css-transitions/file_keyframeeffect-getframes.html
testing/web-platform/tests/web-animations/keyframe-effect/constructor.html
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -1658,17 +1658,18 @@ KeyframeEffectReadOnly::GetFrames(JSCont
           ValuePosition::Right;
 
       if (i == n - 1 ||
           segment.mToValue != property.mSegments[i + 1].mFromValue) {
         entry = entries.AppendElement();
         entry->mProperty = property.mProperty;
         entry->mValue = segment.mToValue;
         entry->mOffset = segment.mToKey;
-        entry->mTimingFunction = &segment.mTimingFunction;
+        entry->mTimingFunction =
+          segment.mToKey == 1.0f ? nullptr : &segment.mTimingFunction;
         entry->mPosition =
           segment.mFromKey == segment.mToKey && segment.mToKey == 1.0f ?
             ValuePosition::Last :
             ValuePosition::Left;
       }
     }
   }
 
--- a/dom/animation/test/css-animations/file_keyframeeffect-getframes.html
+++ b/dom/animation/test/css-animations/file_keyframeeffect-getframes.html
@@ -170,17 +170,17 @@ test(function(t) {
   div.style.animation = 'anim-simple 100s';
   var frames = getFrames(div);
 
   assert_equals(frames.length, 2, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease", composite: "replace",
       color: "rgb(0, 0, 0)" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: "replace",
+    { offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
       color: "rgb(255, 255, 255)" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
 }, 'KeyframeEffectReadOnly.getFrames() returns expected frames for a simple ' +
    'animation');
@@ -190,17 +190,17 @@ test(function(t) {
     var div = addDiv(t);
 
     div.style.animation = 'anim-simple-three 100s ' + easing;
     var frames = getFrames(div);
 
     assert_equals(frames.length, 3, "number of frames");
 
     for (var i = 0; i < frames.length; i++) {
-      assert_equals(frames[i].easing, easing,
+      assert_equals(frames[i].easing, i == frames.length - 1 ? "linear" : easing,
                     "value for 'easing' on ComputedKeyframe #" + i);
     }
   });
 }, 'KeyframeEffectReadOnly.getFrames() returns frames with expected easing ' +
    'values, when the easing comes from animation-timing-function on the ' +
    'element');
 
 test(function(t) {
@@ -209,50 +209,50 @@ test(function(t) {
   div.style.animation = 'anim-simple-timing 100s';
   var frames = getFrames(div);
 
   assert_equals(frames.length, 3, "number of frames");
   assert_equals(frames[0].easing, "linear",
                 "value of 'easing' on ComputedKeyframe #0");
   assert_equals(frames[1].easing, "ease-in-out",
                 "value of 'easing' on ComputedKeyframe #1");
-  assert_equals(frames[2].easing, "ease-in-out",
+  assert_equals(frames[2].easing, "linear",
                 "value of 'easing' on ComputedKeyframe #2");
 }, 'KeyframeEffectReadOnly.getFrames() returns frames with expected easing ' +
    'values, when the easing is specified on each keyframe');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-simple-timing-some 100s step-start';
   var frames = getFrames(div);
 
   assert_equals(frames.length, 3, "number of frames");
   assert_equals(frames[0].easing, "linear",
                 "value of 'easing' on ComputedKeyframe #0");
   assert_equals(frames[1].easing, "step-start",
                 "value of 'easing' on ComputedKeyframe #1");
-  assert_equals(frames[2].easing, "step-start",
+  assert_equals(frames[2].easing, "linear",
                 "value of 'easing' on ComputedKeyframe #2");
 }, 'KeyframeEffectReadOnly.getFrames() returns frames with expected easing ' +
    'values, when the easing is specified on some keyframes');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-simple-shorthand 100s';
   var frames = getFrames(div);
 
   assert_equals(frames.length, 2, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease", composite: "replace",
       marginTop: "8px", marginRight: "8px",
       marginBottom: "8px", marginLeft: "8px" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: "replace",
+    { offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
       marginTop: "16px", marginRight: "16px",
       marginBottom: "16px", marginLeft: "16px" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
 }, 'KeyframeEffectReadOnly.getFrames() returns expected frames for a simple ' +
@@ -265,17 +265,17 @@ test(function(t) {
   div.style.color = 'white';
   var frames = getFrames(div);
 
   assert_equals(frames.length, 2, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease", composite: "replace",
       color: "rgb(0, 0, 255)" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: "replace",
+    { offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
       color: "rgb(255, 255, 255)" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
 }, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
    'animation with a 0% keyframe and no 100% keyframe');
@@ -287,17 +287,17 @@ test(function(t) {
   div.style.color = 'white';
   var frames = getFrames(div);
 
   assert_equals(frames.length, 2, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease", composite: "replace",
       color: "rgb(255, 255, 255)" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: "replace",
+    { offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
       color: "rgb(0, 0, 255)" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
 }, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
    'animation with a 100% keyframe and no 0% keyframe');
@@ -311,17 +311,17 @@ test(function(t) {
 
   assert_equals(frames.length, 3, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease", composite: "replace",
       color: "rgb(255, 255, 255)" },
     { offset: 0.5, computedOffset: 0.5, easing: "ease", composite: "replace",
       color: "rgb(0, 0, 255)" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: "replace",
+    { offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
       color: "rgb(255, 255, 255)" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
 }, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
    'animation with no 0% or 100% keyframe but with a 50% keyframe');
@@ -336,46 +336,44 @@ test(function(t) {
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease", composite: "replace",
       color: "rgb(0, 0, 0)", marginTop: "8px" },
     { offset: 0.25, computedOffset: 0.25, easing: "ease", composite: "replace",
       color: "rgb(0, 0, 255)" },
     { offset: 0.75, computedOffset: 0.75, easing: "ease", composite: "replace",
       marginTop: "12px" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: "replace",
+    { offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
       color: "rgb(255, 255, 255)", marginTop: "16px" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
 }, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
    'animation with different properties on different keyframes, all ' +
    'with the same easing function');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-different-props-and-easing 100s';
   var frames = getFrames(div);
 
-  assert_equals(frames.length, 5, "number of frames");
+  assert_equals(frames.length, 4, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "linear", composite: "replace",
       color: "rgb(0, 0, 0)", marginTop: "8px" },
     { offset: 0.25, computedOffset: 0.25, easing: "step-end", composite: "replace",
       color: "rgb(0, 0, 255)" },
     { offset: 0.75, computedOffset: 0.75, easing: "ease-in", composite: "replace",
       marginTop: "12px" },
-    { offset: 1, computedOffset: 1, easing: "ease-in", composite: "replace",
-      marginTop: "16px" },
-    { offset: 1, computedOffset: 1, easing: "step-end", composite: "replace",
-      color: "rgb(255, 255, 255)" },
+    { offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
+      color: "rgb(255, 255, 255)", marginTop: "16px" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
 }, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
    'animation with different properties on different keyframes, with ' +
    'a different easing function on each');
@@ -386,44 +384,43 @@ test(function(t) {
   div.style.animation = 'anim-merge-offset 100s';
   var frames = getFrames(div);
 
   assert_equals(frames.length, 2, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease", composite: "replace",
       color: "rgb(0, 0, 0)", marginTop: "8px" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: "replace",
+    { offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
       color: "rgb(255, 255, 255)", marginTop: "16px" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
 }, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
    'animation with multiple keyframes for the same time, and all with ' +
    'the same easing function');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-merge-offset-and-easing 100s';
   var frames = getFrames(div);
 
-  assert_equals(frames.length, 4, "number of frames");
+  assert_equals(frames.length, 3, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "linear", composite: "replace",
       marginTop: "8px", paddingLeft: "2px" },
     { offset: 0, computedOffset: 0, easing: "step-end", composite: "replace",
       color: "rgb(0, 0, 0)", fontSize: "16px" },
     { offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
-      marginTop: "16px", paddingLeft: "4px" },
-    { offset: 1, computedOffset: 1, easing: "step-end", composite: "replace",
-      color: "rgb(255, 255, 255)", fontSize: "32px" },
+      color: "rgb(255, 255, 255)", fontSize: "32px", marginTop: "16px",
+      paddingLeft: "4px" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
 }, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
    'animation with multiple keyframes for the same time and with ' +
    'different easing functions');
@@ -440,17 +437,17 @@ test(function(t) {
     { offset: 0, computedOffset: 0, easing: "step-end", composite: "replace",
       marginRight: "0px" },
     { offset: 0, computedOffset: 0, easing: "steps(1)", composite: "replace",
       marginBottom: "0px" },
     { offset: 0, computedOffset: 0, easing: "steps(1, end)", composite: "replace",
       marginTop: "0px" },
     { offset: 0.5, computedOffset: 0.5, easing: "step-end", composite: "replace",
       marginTop: "10px", marginRight: "10px", marginBottom: "10px" },
-    { offset: 1, computedOffset: 1, easing: "step-end", composite: "replace",
+    { offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
       marginTop: "20px", marginRight: "20px", marginBottom: "20px" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
 }, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
    'animation with multiple keyframes for the same time and with ' +
--- a/dom/animation/test/css-transitions/file_keyframeeffect-getframes.html
+++ b/dom/animation/test/css-transitions/file_keyframeeffect-getframes.html
@@ -28,17 +28,17 @@ test(function(t) {
 
   var frames = getFrames(div);
   
   assert_equals(frames.length, 2, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease", composite: "replace",
       left: "0px" },
-    { offset: 1, computedOffset: 1, easing: "ease", composite: "replace",
+    { offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
       left: "100px" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
 }, 'KeyframeEffectReadOnly.getFrames() returns expected frames for a simple ' +
    'transition');
@@ -53,17 +53,17 @@ test(function(t) {
 
   var frames = getFrames(div);
   
   assert_equals(frames.length, 2, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "steps(2, end)", composite: "replace",
       left: "0px" },
-    { offset: 1, computedOffset: 1, easing: "steps(2, end)", composite: "replace",
+    { offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
       left: "100px" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
 }, 'KeyframeEffectReadOnly.getFrames() returns expected frames for a simple ' +
    'transition with a non-default easing function');
--- a/testing/web-platform/tests/web-animations/keyframe-effect/constructor.html
+++ b/testing/web-platform/tests/web-animations/keyframe-effect/constructor.html
@@ -16,27 +16,20 @@
 }
 </style>
 <script>
 "use strict";
 
 var target = document.getElementById("target");
 
 function assert_frames_equal(a, b, name) {
-  // TODO: Test the value for easing on the 100% keyframe.
-  function include(p) {
-    return !(b.offset == 1 && p == "easing");
-  }
-  assert_equals(Object.keys(a).sort().filter(include).toString(),
-                Object.keys(b).sort().filter(include).toString(),
+  assert_equals(Object.keys(a).sort().toString(),
+                Object.keys(b).sort().toString(),
                 "properties on " + name);
   for (var p in a) {
-    if (!include(p)) {
-      continue;
-    }
     assert_equals(a[p], b[p], "value for '" + p + "' on " + name);
   }
 }
 
 function assert_frame_lists_equal(a, b) {
   assert_equals(a.length, b.length, "number of frames");
   for (var i = 0; i < Math.min(a.length, b.length); i++) {
     assert_frames_equal(a[i], b[i], "ComputedKeyframe #" + i);
@@ -185,87 +178,87 @@ test(function(t) {
                                  });
   });
 }, "composite values are parsed correctly when passed to the " +
    "KeyframeEffectReadOnly constructor in KeyframeTimingOptions");
 
 var gPropertyIndexedKeyframesTests = [
   { desc:   "a one property two value PropertyIndexedKeyframes specification",
     input:  { left: ["10px", "20px"] },
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace", left: "10px" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", left: "20px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "20px" }] },
   { desc:   "a one shorthand property two value PropertyIndexedKeyframes specification",
     input:  { margin: ["10px", "10px 20px 30px 40px"] },
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace", marginTop: "10px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", marginTop: "10px", marginRight: "20px", marginBottom: "30px", marginLeft: "40px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginTop: "10px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginTop: "10px", marginRight: "20px", marginBottom: "30px", marginLeft: "40px" }] },
   { desc:   "a two property (one shorthand and one of its longhand components) two value PropertyIndexedKeyframes specification",
     input:  { marginTop: ["50px", "60px"],
               margin: ["10px", "10px 20px 30px 40px"] },
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace", marginTop: "50px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", marginTop: "60px", marginRight: "20px", marginBottom: "30px", marginLeft: "40px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginTop: "50px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginTop: "60px", marginRight: "20px", marginBottom: "30px", marginLeft: "40px" }] },
   { desc:   "a two property two value PropertyIndexedKeyframes specification",
     input:  { left: ["10px", "20px"],
               top: ["30px", "40px"] },
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace", left: "10px", top: "30px" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", left: "20px", top: "40px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px", top: "30px" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "20px", top: "40px" }] },
   { desc:   "a two property PropertyIndexedKeyframes specification with different numbers of values",
     input:  { left: ["10px", "20px", "30px"],
               top: ["40px", "50px"] },
-    output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear",       composite: "replace", left: "10px", top: "40px" },
-             { offset: 0.5, computedOffset: 0.5, easing: "linear",       composite: "replace", left: "20px" },
-             { offset: 1.0, computedOffset: 1.0, /* easing: "linear", */ composite: "replace", left: "30px", top: "50px" }] },
+    output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", composite: "replace", left: "10px", top: "40px" },
+             { offset: 0.5, computedOffset: 0.5, easing: "linear", composite: "replace", left: "20px" },
+             { offset: 1.0, computedOffset: 1.0, easing: "linear", composite: "replace", left: "30px", top: "50px" }] },
   { desc:   "a PropertyIndexedKeyframes specification with an invalid value",
     input:  { left: ["10px", "20px", "30px", "40px", "50px"],
               top:  ["15px", "25px", "invalid", "45px", "55px"] },
-    output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear",       composite: "replace", left: "10px", top: "15px" },
-             { offset: 0.25, computedOffset: 0.25, easing: "linear",       composite: "replace", left: "20px", top: "25px" },
-             { offset: 0.50, computedOffset: 0.50, easing: "linear",       composite: "replace", left: "30px" },
-             { offset: 0.75, computedOffset: 0.75, easing: "linear",       composite: "replace", left: "40px", top: "45px" },
-             { offset: 1.00, computedOffset: 1.00, /* easing: "linear", */ composite: "replace", left: "50px", top: "55px" }] },
+    output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", composite: "replace", left: "10px", top: "15px" },
+             { offset: 0.25, computedOffset: 0.25, easing: "linear", composite: "replace", left: "20px", top: "25px" },
+             { offset: 0.50, computedOffset: 0.50, easing: "linear", composite: "replace", left: "30px" },
+             { offset: 0.75, computedOffset: 0.75, easing: "linear", composite: "replace", left: "40px", top: "45px" },
+             { offset: 1.00, computedOffset: 1.00, easing: "linear", composite: "replace", left: "50px", top: "55px" }] },
   { desc:   "a one property two value PropertyIndexedKeyframes specification that needs to stringify its values",
     input:  { opacity: [0, 1] },
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace", opacity: "0" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", opacity: "1" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", opacity: "0" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", opacity: "1" }] },
   { desc:   "a one property one value PropertyIndexedKeyframes specification",
     input:  { left: ["10px"] },
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", left: "10px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "10px" }] },
   { desc:   "a one property one non-array value PropertyIndexedKeyframes specification",
     input:  { left: "10px" },
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", left: "10px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "10px" }] },
   { desc:   "a one property two value PropertyIndexedKeyframes specification where the first value is invalid",
     input:  { left: ["invalid", "10px"] },
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", left: "10px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "10px" }] },
   { desc:   "a one property two value PropertyIndexedKeyframes specification where the second value is invalid",
     input:  { left: ["10px", "invalid"] },
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace", left: "10px" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace" }] },
   { desc:   "a two property PropertyIndexedKeyframes specification where one property is missing from the first Keyframe",
     input:  [{ offset: 0, left: "10px" },
              { offset: 1, left: "20px", top: "30px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace", left: "10px" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", left: "20px", top: "30px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "20px", top: "30px" }] },
   { desc:   "a two property PropertyIndexedKeyframes specification where one property is missing from the last Keyframe",
     input:  [{ offset: 0, left: "10px", top: "20px" },
              { offset: 1, left: "30px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace", left: "10px" , top: "20px" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", left: "30px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px" , top: "20px" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "30px" }] },
   { desc:   "a PropertyIndexedKeyframes specification with repeated values at offset 0 with different easings",
     input:  [{ offset: 0.0, left: "100px", easing: "ease" },
              { offset: 0.0, left: "200px", easing: "ease" },
              { offset: 0.5, left: "300px", easing: "linear" },
              { offset: 1.0, left: "400px", easing: "ease-out" },
              { offset: 1.0, left: "500px", easing: "step-end" }],
-    output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease",         composite: "replace", left: "100px" },
-             { offset: 0.0, computedOffset: 0.0, easing: "ease",         composite: "replace", left: "200px" },
-             { offset: 0.5, computedOffset: 0.5, easing: "linear",       composite: "replace", left: "300px" },
-             { offset: 1.0, computedOffset: 1.0, easing: "ease-out",     composite: "replace", left: "400px" },
-             { offset: 1.0, computedOffset: 1.0, /* easing: "linear", */ composite: "replace", left: "500px" }] },
+    output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease",     composite: "replace", left: "100px" },
+             { offset: 0.0, computedOffset: 0.0, easing: "ease",     composite: "replace", left: "200px" },
+             { offset: 0.5, computedOffset: 0.5, easing: "linear",   composite: "replace", left: "300px" },
+             { offset: 1.0, computedOffset: 1.0, easing: "ease-out", composite: "replace", left: "400px" },
+             { offset: 1.0, computedOffset: 1.0, easing: "linear",   composite: "replace", left: "500px" }] },
 ];
 
 gPropertyIndexedKeyframesTests.forEach(function(subtest) {
   test(function(t) {
     var effect = new KeyframeEffectReadOnly(target, subtest.input);
     assert_frame_lists_equal(effect.getFrames(), subtest.output);
   }, "a KeyframeEffectReadOnly can be constructed with " + subtest.desc);
 
@@ -296,151 +289,151 @@ test(function(t) {
   assert_array_equals(actualOrder, expectedOrder, "property access order");
 }, "the KeyframeEffectReadOnly constructor reads Keyframe properties in the " +
    "expected order");
 
 var gKeyframeSequenceTests = [
   { desc:   "a one property two Keyframe sequence",
     input:  [{ offset: 0, left: "10px" },
              { offset: 1, left: "20px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace", left: "10px" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", left: "20px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "20px" }] },
   { desc:   "a two property two Keyframe sequence",
     input:  [{ offset: 0, left: "10px", top: "30px" },
              { offset: 1, left: "20px", top: "40px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace", left: "10px", top: "30px" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", left: "20px", top: "40px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px", top: "30px" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "20px", top: "40px" }] },
   { desc:   "a one shorthand property two Keyframe sequence",
     input:  [{ offset: 0, margin: "10px" },
              { offset: 1, margin: "20px 30px 40px 50px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace", marginTop: "10px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", marginTop: "20px", marginRight: "30px", marginBottom: "40px", marginLeft: "50px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginTop: "10px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginTop: "20px", marginRight: "30px", marginBottom: "40px", marginLeft: "50px" }] },
   { desc:   "a two property (a shorthand and one of its component longhands) two Keyframe sequence",
     input:  [{ offset: 0, margin: "10px", marginTop: "20px" },
              { offset: 1, marginTop: "70px", margin: "30px 40px 50px 60px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace", marginTop: "20px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", marginTop: "70px", marginRight: "40px", marginBottom: "50px", marginLeft: "60px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginTop: "20px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginTop: "70px", marginRight: "40px", marginBottom: "50px", marginLeft: "60px" }] },
   { desc:   "a Keyframe sequence with duplicate values for a given interior offset",
     input:  [{ offset: 0.0, left: "10px" },
              { offset: 0.5, left: "20px" },
              { offset: 0.5, left: "30px" },
              { offset: 0.5, left: "40px" },
              { offset: 1.0, left: "50px" }],
-    output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear",       composite: "replace", left: "10px" },
-             { offset: 0.5, computedOffset: 0.5, easing: "linear",       composite: "replace", left: "20px" },
-             { offset: 0.5, computedOffset: 0.5, easing: "linear",       composite: "replace", left: "40px" },
-             { offset: 1.0, computedOffset: 1.0, /* easing: "linear", */ composite: "replace", left: "50px" }] },
+    output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", composite: "replace", left: "10px" },
+             { offset: 0.5, computedOffset: 0.5, easing: "linear", composite: "replace", left: "20px" },
+             { offset: 0.5, computedOffset: 0.5, easing: "linear", composite: "replace", left: "40px" },
+             { offset: 1.0, computedOffset: 1.0, easing: "linear", composite: "replace", left: "50px" }] },
   { desc:   "a Keyframe sequence with duplicate values for offsets 0 and 1",
     input:  [{ offset: 0, left: "10px" },
              { offset: 0, left: "20px" },
              { offset: 0, left: "30px" },
              { offset: 1, left: "40px" },
              { offset: 1, left: "50px" },
              { offset: 1, left: "60px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace", left: "10px" },
-             { offset: 0, computedOffset: 0, easing: "linear",       composite: "replace", left: "30px" },
-             { offset: 1, computedOffset: 1, easing: "linear",       composite: "replace", left: "40px" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", left: "60px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px" },
+             { offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "30px" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "40px" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "60px" }] },
   { desc:   "a two property four Keyframe sequence",
     input:  [{ offset: 0, left: "10px" },
              { offset: 0, top: "20px" },
              { offset: 1, top: "30px" },
              { offset: 1, left: "40px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace", left: "10px", top: "20px" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", left: "40px", top: "30px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px", top: "20px" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "40px", top: "30px" }] },
   { desc:   "a one property Keyframe sequence with some omitted offsets",
     input:  [{ offset: 0.00, left: "10px" },
              { offset: 0.25, left: "20px" },
              { left: "30px" },
              { left: "40px" },
              { offset: 1.00, left: "50px" }],
-    output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear",       composite: "replace", left: "10px" },
-             { offset: 0.25, computedOffset: 0.25, easing: "linear",       composite: "replace", left: "20px" },
-             { offset: 0.50, computedOffset: 0.50, easing: "linear",       composite: "replace", left: "30px" },
-             { offset: 0.75, computedOffset: 0.75, easing: "linear",       composite: "replace", left: "40px" },
-             { offset: 1.00, computedOffset: 1.00, /* easing: "linear", */ composite: "replace", left: "50px" }] },
+    output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", composite: "replace", left: "10px" },
+             { offset: 0.25, computedOffset: 0.25, easing: "linear", composite: "replace", left: "20px" },
+             { offset: 0.50, computedOffset: 0.50, easing: "linear", composite: "replace", left: "30px" },
+             { offset: 0.75, computedOffset: 0.75, easing: "linear", composite: "replace", left: "40px" },
+             { offset: 1.00, computedOffset: 1.00, easing: "linear", composite: "replace", left: "50px" }] },
   { desc:   "a two property Keyframe sequence with some omitted offsets",
     input:  [{ offset: 0.00, left: "10px", top: "20px" },
              { offset: 0.25, left: "30px" },
              { left: "40px" },
              { left: "50px", top: "60px" },
              { offset: 1.00, left: "70px", top: "80px" }],
-    output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear",       composite: "replace", left: "10px", top: "20px" },
-             { offset: 0.25, computedOffset: 0.25, easing: "linear",       composite: "replace", left: "30px" },
-             { offset: 0.50, computedOffset: 0.50, easing: "linear",       composite: "replace", left: "40px" },
-             { offset: 0.75, computedOffset: 0.75, easing: "linear",       composite: "replace", left: "50px", top: "60px" },
-             { offset: 1.00, computedOffset: 1.00, /* easing: "linear", */ composite: "replace", left: "70px", top: "80px" }] },
+    output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", composite: "replace", left: "10px", top: "20px" },
+             { offset: 0.25, computedOffset: 0.25, easing: "linear", composite: "replace", left: "30px" },
+             { offset: 0.50, computedOffset: 0.50, easing: "linear", composite: "replace", left: "40px" },
+             { offset: 0.75, computedOffset: 0.75, easing: "linear", composite: "replace", left: "50px", top: "60px" },
+             { offset: 1.00, computedOffset: 1.00, easing: "linear", composite: "replace", left: "70px", top: "80px" }] },
   { desc:   "a one property Keyframe sequence with all omitted offsets",
     input:  [{ left: "10px" },
              { left: "20px" },
              { left: "30px" },
              { left: "40px" },
              { left: "50px" }],
-    output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear",       composite: "replace", left: "10px" },
-             { offset: 0.25, computedOffset: 0.25, easing: "linear",       composite: "replace", left: "20px" },
-             { offset: 0.50, computedOffset: 0.50, easing: "linear",       composite: "replace", left: "30px" },
-             { offset: 0.75, computedOffset: 0.75, easing: "linear",       composite: "replace", left: "40px" },
-             { offset: 1.00, computedOffset: 1.00, /* easing: "linear", */ composite: "replace", left: "50px" }] },
+    output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", composite: "replace", left: "10px" },
+             { offset: 0.25, computedOffset: 0.25, easing: "linear", composite: "replace", left: "20px" },
+             { offset: 0.50, computedOffset: 0.50, easing: "linear", composite: "replace", left: "30px" },
+             { offset: 0.75, computedOffset: 0.75, easing: "linear", composite: "replace", left: "40px" },
+             { offset: 1.00, computedOffset: 1.00, easing: "linear", composite: "replace", left: "50px" }] },
   { desc:   "a Keyframe sequence with different easing values, but the same easing value for a given offset",
     input:  [{ offset: 0.0, easing: "ease",     left: "10px"},
              { offset: 0.0, easing: "ease",     top: "20px"},
              { offset: 0.5, easing: "linear",   left: "30px" },
              { offset: 0.5, easing: "linear",   top: "40px" },
              { offset: 1.0, easing: "step-end", left: "50px" },
              { offset: 1.0, easing: "step-end", top: "60px" }],
     output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease",         composite: "replace", left: "10px", top: "20px" },
-             { offset: 0.5, computedOffset: 0.5, easing: "linear",       composite: "replace", left: "30px", top: "40px" },
-             { offset: 1.0, computedOffset: 1.0, /* easing: "linear", */ composite: "replace", left: "50px", top: "60px" }] },
+             { offset: 0.5, computedOffset: 0.5, easing: "linear", composite: "replace", left: "30px", top: "40px" },
+             { offset: 1.0, computedOffset: 1.0, easing: "linear", composite: "replace", left: "50px", top: "60px" }] },
   { desc:   "a Keyframe sequence with different composite values, but the same composite value for a given offset",
     input:  [{ offset: 0.0, composite: "replace", left: "10px" },
              { offset: 0.0, composite: "replace", top: "20px" },
              { offset: 0.5, composite: "add",     left: "30px" },
              { offset: 0.5, composite: "add",     top: "40px" },
              { offset: 1.0, composite: "replace", left: "50px" },
              { offset: 1.0, composite: "replace", top: "60px" }],
-    output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear",       composite: "replace", left: "10px", top: "20px" },
-             { offset: 0.5, computedOffset: 0.5, easing: "linear",       composite: "add",     left: "30px", top: "40px" },
-             { offset: 1.0, computedOffset: 1.0, /* easing: "linear", */ composite: "replace", left: "50px", top: "60px" }] },
+    output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", composite: "replace", left: "10px", top: "20px" },
+             { offset: 0.5, computedOffset: 0.5, easing: "linear", composite: "add",     left: "30px", top: "40px" },
+             { offset: 1.0, computedOffset: 1.0, easing: "linear", composite: "replace", left: "50px", top: "60px" }] },
   { desc:   "a one property two Keyframe sequence that needs to stringify its values",
     input:  [{ offset: 0, opacity: 0 },
              { offset: 1, opacity: 1 }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace", opacity: "0" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", opacity: "1" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", opacity: "0" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", opacity: "1" }] },
   { desc:   "a Keyframe sequence where shorthand precedes longhand",
     input:  [{ offset: 0, margin: "10px", marginRight: "20px" },
              { offset: 1, margin: "30px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace", marginBottom: "10px", marginLeft: "10px", marginRight: "20px", marginTop: "10px" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", marginBottom: "30px", marginLeft: "30px", marginRight: "30px", marginTop: "30px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginBottom: "10px", marginLeft: "10px", marginRight: "20px", marginTop: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginBottom: "30px", marginLeft: "30px", marginRight: "30px", marginTop: "30px" }] },
   { desc:   "a Keyframe sequence where longhand precedes shorthand",
     input:  [{ offset: 0, marginRight: "20px", margin: "10px" },
              { offset: 1, margin: "30px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace", marginBottom: "10px", marginLeft: "10px", marginRight: "20px", marginTop: "10px" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace", marginBottom: "30px", marginLeft: "30px", marginRight: "30px", marginTop: "30px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginBottom: "10px", marginLeft: "10px", marginRight: "20px", marginTop: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginBottom: "30px", marginLeft: "30px", marginRight: "30px", marginTop: "30px" }] },
   { desc:   "a Keyframe sequence where lesser shorthand precedes greater shorthand",
     input:  [{ offset: 0, borderLeft: "1px solid rgb(1, 2, 3)", border: "2px dotted rgb(4, 5, 6)" },
              { offset: 1, border: "3px dashed rgb(7, 8, 9)" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace",
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace",
                  borderBottomColor: "rgb(4, 5, 6)", borderBottomWidth: "2px",
                  borderLeftColor:   "rgb(1, 2, 3)", borderLeftWidth:   "1px",
                  borderRightColor:  "rgb(4, 5, 6)", borderRightWidth:  "2px",
                  borderTopColor:    "rgb(4, 5, 6)", borderTopWidth:    "2px" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace",
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
                  borderBottomColor: "rgb(7, 8, 9)", borderBottomWidth: "3px",
                  borderLeftColor:   "rgb(7, 8, 9)", borderLeftWidth:   "3px",
                  borderRightColor:  "rgb(7, 8, 9)", borderRightWidth:  "3px",
                  borderTopColor:    "rgb(7, 8, 9)", borderTopWidth:    "3px" }] },
   { desc:   "a Keyframe sequence where greater shorthand precedes lesser shorthand",
     input:  [{ offset: 0, border: "2px dotted rgb(4, 5, 6)", borderLeft: "1px solid rgb(1, 2, 3)" },
              { offset: 1, border: "3px dashed rgb(7, 8, 9)" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear",       composite: "replace",
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace",
                  borderBottomColor: "rgb(4, 5, 6)", borderBottomWidth: "2px",
                  borderLeftColor:   "rgb(1, 2, 3)", borderLeftWidth:   "1px",
                  borderRightColor:  "rgb(4, 5, 6)", borderRightWidth:  "2px",
                  borderTopColor:    "rgb(4, 5, 6)", borderTopWidth:    "2px" },
-             { offset: 1, computedOffset: 1, /* easing: "linear", */ composite: "replace",
+             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
                  borderBottomColor: "rgb(7, 8, 9)", borderBottomWidth: "3px",
                  borderLeftColor:   "rgb(7, 8, 9)", borderLeftWidth:   "3px",
                  borderRightColor:  "rgb(7, 8, 9)", borderRightWidth:  "3px",
                  borderTopColor:    "rgb(7, 8, 9)", borderTopWidth:    "3px" }] },
 ];
 
 gKeyframeSequenceTests.forEach(function(subtest) {
   test(function(t) {