Bug 1260543 - Treat currentcolor as computed value which is not interpolatable with actual color for text-emphasis-color and -webkit-text-fill-color. r=birtles
authorXidorn Quan <quanxunzhen@gmail.com>
Fri, 08 Apr 2016 13:43:09 +1000
changeset 294430 29debcd8e53a49ae130a3b2954f9e0898b655921
parent 294429 d9c905c8e1d102de622cbcf17f1e8797f7f5fa7b
child 294431 479e9cb32dc93bb6cbfc343f97468c6e46b4035d
push id30203
push usercbook@mozilla.com
push dateFri, 22 Apr 2016 13:56:37 +0000
treeherdermozilla-central@fc15477ce628 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbirtles
bugs1260543
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 1260543 - Treat currentcolor as computed value which is not interpolatable with actual color for text-emphasis-color and -webkit-text-fill-color. r=birtles MozReview-Commit-ID: GUXEDHxOdNC
layout/reftests/bugs/1260543-1-ref.html
layout/reftests/bugs/1260543-1.html
layout/reftests/bugs/reftest.list
layout/style/StyleAnimationValue.cpp
layout/style/StyleAnimationValue.h
layout/style/nsStyleContext.cpp
layout/style/test/test_transitions_events.html
layout/style/test/test_transitions_per_property.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1260543-1-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<style>
+#outer {
+  font-size: 52px;
+  color: green;
+}
+</style>
+<p>Test passes if the block below is green.</p>
+<div id="outer"><span id="inner">&#x2588;</span></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1260543-1.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<style>
+#outer {
+  font-size: 52px;
+  transition: all 100s step-start;
+  color: transparent;
+}
+#outer.red {
+  color: red;
+}
+#outer.red > #inner {
+  color: green;
+}
+</style>
+<!--
+This is testing that -webkit-text-fill-color should inherit currentcolor
+keyword value, rather than the computed value of color (used value of
+-webkit-text-fill-color) from the transition.
+-->
+<p>Test passes if the block below is green.</p>
+<div id="outer"><span id="inner">&#x2588;</span></div>
+<script>
+window.addEventListener("load", () => {
+  // Wait for the second frame to ensure that we will
+  // actually start the transition.
+  requestAnimationFrame(() => {
+    requestAnimationFrame(() => {
+      let outer = document.getElementById("outer");
+      outer.className = "red";
+      document.documentElement.className = "";
+    });
+  });
+});
+</script>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1944,8 +1944,9 @@ fuzzy(1,74) fuzzy-if(gtkWidget,6,79) == 
 == 1222226-1.html 1222226-1-ref.html
 pref(layout.css.overflow-clip-box.enabled,true) == 1226278.html 1226278-ref.html
 == 1230466.html about:blank
 random-if(gtkWidget) != 1238243-1.html 1238243-1-notref.html # may fail on Linux, depending on Korean fonts available
 random-if(OSX==1006) == 1238243-2.html 1238243-2-ref.html # fails on 10.6 with default fonts because filler has a visible glyph
 fuzzy(100,2000) == 1239564.html 1239564-ref.html
 == 1242172-1.html 1242172-1-ref.html
 == 1242172-2.html 1242172-2-ref.html
+== 1260543-1.html 1260543-1-ref.html
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -463,16 +463,17 @@ StyleAnimationValue::ComputeDistance(nsC
 
   switch (commonUnit) {
     case eUnit_Null:
     case eUnit_Auto:
     case eUnit_None:
     case eUnit_Normal:
     case eUnit_UnparsedString:
     case eUnit_URL:
+    case eUnit_CurrentColor:
       return false;
 
     case eUnit_Enumerated:
       switch (aProperty) {
         case eCSSProperty_font_stretch: {
           // just like eUnit_Integer.
           int32_t startInt = aStartValue.GetIntValue();
           int32_t endInt = aEndValue.GetIntValue();
@@ -2207,16 +2208,17 @@ StyleAnimationValue::AddWeighted(nsCSSPr
 
   switch (commonUnit) {
     case eUnit_Null:
     case eUnit_Auto:
     case eUnit_None:
     case eUnit_Normal:
     case eUnit_UnparsedString:
     case eUnit_URL:
+    case eUnit_CurrentColor:
       return false;
 
     case eUnit_Enumerated:
       switch (aProperty) {
         case eCSSProperty_font_stretch: {
           // Animate just like eUnit_Integer.
           int32_t result = floor(aCoeff1 * double(aValue1.GetIntValue()) +
                                  aCoeff2 * double(aValue2.GetIntValue()));
@@ -3002,16 +3004,19 @@ StyleAnimationValue::UncomputeValue(nsCS
     case eUnit_Float:
       aSpecifiedValue.
         SetFloatValue(aComputedValue.GetFloatValue(), eCSSUnit_Number);
       break;
     case eUnit_Color:
       // colors can be alone, or part of a paint server
       aSpecifiedValue.SetColorValue(aComputedValue.GetColorValue());
       break;
+    case eUnit_CurrentColor:
+      aSpecifiedValue.SetIntValue(NS_COLOR_CURRENTCOLOR, eCSSUnit_EnumColor);
+      break;
     case eUnit_Calc:
     case eUnit_ObjectPosition:
     case eUnit_URL: {
       nsCSSValue* val = aComputedValue.GetCSSValueValue();
       // Sanity-check that the underlying unit in the nsCSSValue is what we
       // expect for our StyleAnimationValue::Unit:
       MOZ_ASSERT((unit == eUnit_Calc && val->GetUnit() == eCSSUnit_Calc) ||
                  (unit == eUnit_ObjectPosition &&
@@ -3144,16 +3149,27 @@ StyleDataAtOffset(const void* aStyleStru
 
 inline void*
 StyleDataAtOffset(void* aStyleStruct, ptrdiff_t aOffset)
 {
   return reinterpret_cast<char*>(aStyleStruct) + aOffset;
 }
 
 static void
+SetCurrentOrActualColor(bool aIsForeground, nscolor aActualColor,
+                        StyleAnimationValue& aComputedValue)
+{
+  if (aIsForeground) {
+    aComputedValue.SetCurrentColorValue();
+  } else {
+    aComputedValue.SetColorValue(aActualColor);
+  }
+}
+
+static void
 ExtractBorderColor(nsStyleContext* aStyleContext, const void* aStyleBorder,
                    mozilla::css::Side aSide,
                    StyleAnimationValue& aComputedValue)
 {
   nscolor color;
   bool foreground;
   static_cast<const nsStyleBorder*>(aStyleBorder)->
     GetBorderColor(aSide, color, foreground);
@@ -3600,24 +3616,27 @@ StyleAnimationValue::ExtractComputedValu
             static_cast<const nsStyleTextReset*>(styleStruct)->
               GetDecorationStyle();
           aComputedValue.SetIntValue(decorationStyle, eUnit_Enumerated);
           break;
         }
 
         case eCSSProperty_text_emphasis_color: {
           auto styleText = static_cast<const nsStyleText*>(styleStruct);
-          nscolor color = styleText->mTextEmphasisColorForeground ?
-            aStyleContext->StyleColor()->mColor : styleText->mTextEmphasisColor;
-          aComputedValue.SetColorValue(color);
+          SetCurrentOrActualColor(styleText->mTextEmphasisColorForeground,
+                                  styleText->mTextEmphasisColor,
+                                  aComputedValue);
           break;
         }
 
         case eCSSProperty__webkit_text_fill_color: {
-          aComputedValue.SetColorValue(aStyleContext->GetTextFillColor());
+          auto styleText = static_cast<const nsStyleText*>(styleStruct);
+          SetCurrentOrActualColor(styleText->mWebkitTextFillColorForeground,
+                                  styleText->mWebkitTextFillColor,
+                                  aComputedValue);
           break;
         }
 
         case eCSSProperty_border_spacing: {
           const nsStyleTableBorder *styleTableBorder =
             static_cast<const nsStyleTableBorder*>(styleStruct);
           nsAutoPtr<nsCSSValuePair> pair(new nsCSSValuePair);
           nscoordToCSSValue(styleTableBorder->mBorderSpacingCol, pair->mXValue);
@@ -4173,16 +4192,17 @@ StyleAnimationValue::operator=(const Sty
   FreeValue();
 
   mUnit = aOther.mUnit;
   switch (mUnit) {
     case eUnit_Null:
     case eUnit_Normal:
     case eUnit_Auto:
     case eUnit_None:
+    case eUnit_CurrentColor:
       break;
     case eUnit_Enumerated:
     case eUnit_Visibility:
     case eUnit_Integer:
       mValue.mInt = aOther.mValue.mInt;
       break;
     case eUnit_Coord:
       mValue.mCoord = aOther.mValue.mCoord;
@@ -4315,16 +4335,23 @@ void
 StyleAnimationValue::SetColorValue(nscolor aColor)
 {
   FreeValue();
   mUnit = eUnit_Color;
   mValue.mColor = aColor;
 }
 
 void
+StyleAnimationValue::SetCurrentColorValue()
+{
+  FreeValue();
+  mUnit = eUnit_CurrentColor;
+}
+
+void
 StyleAnimationValue::SetUnparsedStringValue(const nsString& aString)
 {
   FreeValue();
   mUnit = eUnit_UnparsedString;
   mValue.mString = nsCSSValue::BufferFromString(aString).take();
 }
 
 void
@@ -4444,16 +4471,17 @@ StyleAnimationValue::operator==(const St
     return false;
   }
 
   switch (mUnit) {
     case eUnit_Null:
     case eUnit_Normal:
     case eUnit_Auto:
     case eUnit_None:
+    case eUnit_CurrentColor:
       return true;
     case eUnit_Enumerated:
     case eUnit_Visibility:
     case eUnit_Integer:
       return mValue.mInt == aOther.mValue.mInt;
     case eUnit_Coord:
       return mValue.mCoord == aOther.mValue.mCoord;
     case eUnit_Percent:
--- a/layout/style/StyleAnimationValue.h
+++ b/layout/style/StyleAnimationValue.h
@@ -266,16 +266,17 @@ public:
     eUnit_Enumerated,
     eUnit_Visibility, // special case for transitions (which converts
                       // Enumerated to Visibility as needed)
     eUnit_Integer,
     eUnit_Coord,
     eUnit_Percent,
     eUnit_Float,
     eUnit_Color,
+    eUnit_CurrentColor,
     eUnit_Calc, // nsCSSValue* (never null), always with a single
                 // calc() expression that's either length or length+percent
     eUnit_ObjectPosition, // nsCSSValue* (never null), always with a
                           // 4-entry nsCSSValue::Array
     eUnit_URL, // nsCSSValue* (never null), always with a css::URLValue
     eUnit_CSSValuePair, // nsCSSValuePair* (never null)
     eUnit_CSSValueTriplet, // nsCSSValueTriplet* (never null)
     eUnit_CSSRect, // nsCSSRect* (never null)
@@ -428,16 +429,17 @@ public:
   void SetNormalValue();
   void SetAutoValue();
   void SetNoneValue();
   void SetIntValue(int32_t aInt, Unit aUnit);
   void SetCoordValue(nscoord aCoord);
   void SetPercentValue(float aPercent);
   void SetFloatValue(float aFloat);
   void SetColorValue(nscolor aColor);
+  void SetCurrentColorValue();
   void SetUnparsedStringValue(const nsString& aString);
 
   // These setters take ownership of |aValue|, and are therefore named
   // "SetAndAdopt*".
   void SetAndAdoptCSSValueValue(nsCSSValue *aValue, Unit aUnit);
   void SetAndAdoptCSSValuePairValue(nsCSSValuePair *aValue, Unit aUnit);
   void SetAndAdoptCSSValueTripletValue(nsCSSValueTriplet *aValue, Unit aUnit);
   void SetAndAdoptCSSRectValue(nsCSSRect *aValue, Unit aUnit);
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -1311,27 +1311,30 @@ ExtractAnimationValue(nsCSSProperty aPro
 }
 
 static nscolor
 ExtractColor(nsCSSProperty aProperty,
              nsStyleContext *aStyleContext)
 {
   StyleAnimationValue val;
   ExtractAnimationValue(aProperty, aStyleContext, val);
-  return val.GetColorValue();
+  return val.GetUnit() == StyleAnimationValue::eUnit_CurrentColor
+    ? aStyleContext->StyleColor()->mColor : val.GetColorValue();
 }
 
 static nscolor
 ExtractColorLenient(nsCSSProperty aProperty,
                     nsStyleContext *aStyleContext)
 {
   StyleAnimationValue val;
   ExtractAnimationValue(aProperty, aStyleContext, val);
   if (val.GetUnit() == StyleAnimationValue::eUnit_Color) {
     return val.GetColorValue();
+  } else if (val.GetUnit() == StyleAnimationValue::eUnit_CurrentColor) {
+    return aStyleContext->StyleColor()->mColor;
   }
   return NS_RGBA(0, 0, 0, 0);
 }
 
 struct ColorIndexSet {
   uint8_t colorIndex, alphaIndex;
 };
 
--- a/layout/style/test/test_transitions_events.html
+++ b/layout/style/test/test_transitions_events.html
@@ -17,18 +17,16 @@ https://bugzilla.mozilla.org/show_bug.cg
 #three { transition: margin 0.5s 0.25s; }
 
 #four, #five, #six, #seven::before, #seven::after {
   transition: 500ms color;
   border-color: black; /* don't derive from color */
   -moz-column-rule-color: black; /* don't derive from color */
   text-decoration-color: black; /* don't derive from color */
   outline-color: black; /* don't derive from color */
-  text-emphasis-color: black; /* don't derive from color */
-  -webkit-text-fill-color: black; /* don't derive from color */
 }
 
 #four {
   /* give the reversing transition a long duration; the reversing will
      still be quick */
   transition-duration: 30s;
   transition-timing-function: cubic-bezier(0, 1, 1, 0);
 }
@@ -70,18 +68,16 @@ function cs(id) { return getComputedStyl
 var got_one_root = false;
 var got_one_target = false;
 var got_one_target_bordertop = false;
 var got_one_target_borderright = false;
 var got_one_target_borderbottom = false;
 var got_one_target_borderleft = false;
 var got_one_target_columnrule = false;
 var got_one_target_textdecorationcolor = false;
-var got_one_target_textemphasiscolor = false;
-var got_one_target_webkittextfillcolor = false;
 var got_one_target_outlinecolor = false;
 var got_two_target = false;
 var got_three_top = false;
 var got_three_right = false;
 var got_three_bottom = false;
 var got_three_left = false;
 var got_four_root = false;
 var got_body = false;
@@ -189,28 +185,16 @@ document.documentElement.addEventListene
         event.stopPropagation();
         break;
       case "text-decoration-color":
         ok(!got_one_target_textdecorationcolor,
            "transitionend on one on target (text-decoration-color)");
         got_one_target_textdecorationcolor = true;
         event.stopPropagation();
         break;
-      case "text-emphasis-color":
-        ok(!got_one_target_textemphasiscolor,
-           "transitionend on one on target (text-emphasis-color)");
-        got_one_target_textemphasiscolor = true;
-        event.stopPropagation();
-        break;
-      case "-webkit-text-fill-color":
-        ok(!got_one_target_webkittextfillcolor,
-           "transitionend on one on target (-webkit-text-fill-color)");
-        got_one_target_webkittextfillcolor = true;
-        event.stopPropagation();
-        break;
       case "outline-color":
         ok(!got_one_target_outlinecolor,
            "transitionend on one on target (outline-color)");
         got_one_target_outlinecolor = true;
         event.stopPropagation();
         break;
       default:
         ok(false, "unexpected property name " + event.propertyName +
@@ -226,22 +210,16 @@ document.documentElement.addEventListene
 started_test(); // color on #one
 started_test(); // border-top-color on #one
 started_test(); // border-right-color on #one
 started_test(); // border-right-color on #one (listener on root)
 started_test(); // border-bottom-color on #one
 started_test(); // border-left-color on #one
 started_test(); // -moz-column-rule-color on #one
 started_test(); // text-decoration-color on #one
-if (SpecialPowers.getBoolPref("layout.css.text-emphasis.enabled")) {
-  started_test(); // text-emphasis-color on #one
-}
-if (SpecialPowers.getBoolPref("layout.css.prefixes.webkit")) {
-  started_test(); // -webkit-text-fill-color on #one
-}
 started_test(); // outline-color on #one
 $("one").style.color = "lime";
 
 
 $("two").addEventListener("transitionend",
   function(event) {
     event.stopPropagation();
 
--- a/layout/style/test/test_transitions_per_property.html
+++ b/layout/style/test/test_transitions_per_property.html
@@ -66,75 +66,84 @@ var supported_properties = {
     "-moz-box-flex": [ test_float_zeroToOne_transition,
                        test_float_aboveOne_transition,
                        test_float_zeroToOne_clamped ],
     "box-shadow": [ test_shadow_transition ],
     "-moz-column-count": [ test_pos_integer_or_auto_transition,
                            test_integer_at_least_one_clamping ],
     "-moz-column-gap": [ test_length_transition,
                          test_length_clamped ],
-    "-moz-column-rule-color": [ test_color_transition,
+    "-moz-column-rule-color": [ test_general_color_transition,
+                                test_currentcolor_transition,
                                 test_border_color_transition ],
     "-moz-column-rule-width": [ test_length_transition,
                                 test_length_clamped ],
     "-moz-column-width": [ test_length_transition,
                            test_length_clamped ],
     "-moz-image-region": [ test_rect_transition ],
     "-moz-outline-radius-bottomleft": [ test_radius_transition ],
     "-moz-outline-radius-bottomright": [ test_radius_transition ],
     "-moz-outline-radius-topleft": [ test_radius_transition ],
     "-moz-outline-radius-topright": [ test_radius_transition ],
-    "background-color": [ test_color_transition ],
+    "background-color": [ test_general_color_transition,
+                          test_currentcolor_transition ],
     "background-position": [ test_background_position_transition,
                              // FIXME: We don't currently test clamping,
                              // since background-position uses calc() as
                              // an intermediate form.
                              /* test_length_percent_pair_unclamped */ ],
     "background-size": [ test_background_size_transition,
                          // FIXME: We don't currently test clamping,
                          // since background-size uses calc() as an
                          // intermediate form.
                          /* test_length_percent_pair_clamped */ ],
-    "border-bottom-color": [ test_color_transition,
+    "border-bottom-color": [ test_general_color_transition,
+                             test_currentcolor_transition,
                              test_border_color_transition ],
     "border-bottom-width": [ test_length_transition,
                              test_length_clamped ],
-    "border-left-color": [ test_color_transition,
+    "border-left-color": [ test_general_color_transition,
+                           test_currentcolor_transition,
                            test_border_color_transition ],
     "border-left-width": [ test_length_transition,
                            test_length_clamped ],
-    "border-right-color": [ test_color_transition,
+    "border-right-color": [ test_general_color_transition,
+                            test_currentcolor_transition,
                             test_border_color_transition ],
     "border-right-width": [ test_length_transition,
                             test_length_clamped ],
     "border-spacing": [ test_length_pair_transition,
                         test_length_pair_transition_clamped ],
-    "border-top-color": [ test_color_transition,
+    "border-top-color": [ test_general_color_transition,
+                          test_currentcolor_transition,
                           test_border_color_transition ],
     "border-top-width": [ test_length_transition,
                            test_length_clamped ],
     "bottom": [ test_length_transition, test_percent_transition,
                 test_length_percent_calc_transition,
                 test_length_unclamped, test_percent_unclamped ],
     "clip": [ test_rect_transition ],
     "clip-path": [ test_clip_path_transition ],
-    "color": [ test_color_transition ],
-    "fill": [ test_color_transition ],
+    "color": [ test_general_color_transition,
+               test_currentcolor_transition ],
+    "fill": [ test_general_color_transition,
+              test_currentcolor_transition ],
     "fill-opacity" : [ test_float_zeroToOne_transition,
                        // opacity is clamped in computed style
                        // (not parsing/interpolation)
                        test_float_zeroToOne_clamped ],
     "filter" : [ test_filter_transition ],
     "flex-basis": [ test_length_transition, test_percent_transition,
                     test_length_clamped, test_percent_clamped ],
     "flex-grow": [ test_float_zeroToOne_transition,
                    test_float_aboveOne_transition ],
     "flex-shrink": [ test_float_zeroToOne_transition,
                      test_float_aboveOne_transition ],
-    "flood-color": [ test_color_transition ],
+    "flood-color": [ test_general_color_transition,
+                     test_currentcolor_transition ],
     "flood-opacity" : [ test_float_zeroToOne_transition,
                         // opacity is clamped in computed style
                         // (not parsing/interpolation)
                         test_float_zeroToOne_clamped ],
     "font-size": [ test_length_transition, test_percent_transition,
                    test_length_percent_calc_transition,
                    test_length_clamped, test_percent_clamped ],
     "font-size-adjust": [ test_float_zeroToOne_transition,
@@ -147,17 +156,18 @@ var supported_properties = {
     "grid-row-gap": [ test_grid_gap ],
     "height": [ test_length_transition, test_percent_transition,
                 test_length_percent_calc_transition,
                 test_length_clamped, test_percent_clamped ],
     "left": [ test_length_transition, test_percent_transition,
               test_length_percent_calc_transition,
               test_length_unclamped, test_percent_unclamped ],
     "letter-spacing": [ test_length_transition, test_length_unclamped ],
-    "lighting-color": [ test_color_transition ],
+    "lighting-color": [ test_general_color_transition,
+                        test_currentcolor_transition ],
     // NOTE: when calc() is supported on 'line-height', we should add
     // test_length_percent_calc_transition.
     "line-height": [ test_length_transition, test_percent_transition,
                      test_length_clamped, test_percent_clamped ],
     "margin-bottom": [ test_length_transition, test_percent_transition,
                        test_length_percent_calc_transition,
                        test_length_unclamped, test_percent_unclamped ],
     "margin-left": [ test_length_transition, test_percent_transition,
@@ -184,17 +194,18 @@ var supported_properties = {
                    test_length_percent_calc_transition,
                    test_length_clamped, test_percent_clamped ],
     "object-position": [ test_background_position_transition ],
     "opacity" : [ test_float_zeroToOne_transition,
                   // opacity is clamped in computed style
                   // (not parsing/interpolation)
                   test_float_zeroToOne_clamped ],
     "order": [ test_integer_transition ],
-    "outline-color": [ test_color_transition ],
+    "outline-color": [ test_general_color_transition,
+                       test_currentcolor_transition ],
     "outline-offset": [ test_length_transition, test_length_unclamped ],
     "outline-width": [ test_length_transition, test_length_clamped ],
     "padding-bottom": [ test_length_transition, test_percent_transition,
                         test_length_percent_calc_transition,
                         test_length_clamped, test_percent_clamped ],
     "padding-left": [ test_length_transition, test_percent_transition,
                       test_length_percent_calc_transition,
                       test_length_clamped, test_percent_clamped ],
@@ -206,43 +217,46 @@ var supported_properties = {
                      test_length_clamped, test_percent_clamped ],
     "perspective": [ test_length_transition ],
     "perspective-origin": [ test_length_pair_transition,
                             test_length_percent_pair_transition,
                             test_length_percent_pair_unclamped ],
     "right": [ test_length_transition, test_percent_transition,
                test_length_percent_calc_transition,
                test_length_unclamped, test_percent_unclamped ],
-    "stop-color": [ test_color_transition ],
+    "stop-color": [ test_general_color_transition,
+                    test_currentcolor_transition ],
     "stop-opacity" : [ test_float_zeroToOne_transition,
                        // opacity is clamped in computed style
                        // (not parsing/interpolation)
                        test_float_zeroToOne_clamped ],
-    "stroke": [ test_color_transition ],
+    "stroke": [ test_general_color_transition,
+                test_currentcolor_transition ],
     "stroke-dasharray": [ test_dasharray_transition ],
     // NOTE: when calc() is supported on 'stroke-dashoffset', we should
     // add test_length_percent_calc_transition.
     "stroke-dashoffset": [ test_length_transition_svg, test_percent_transition,
                            test_length_unclamped_svg, test_percent_unclamped ],
     "stroke-miterlimit": [ test_float_aboveOne_transition,
                            test_float_aboveOne_clamped ],
     "stroke-opacity" : [ test_float_zeroToOne_transition,
                          // opacity is clamped in computed style
                          // (not parsing/interpolation)
                          test_float_zeroToOne_clamped ],
     // NOTE: when calc() is supported on 'stroke-width', we should add
     // test_length_percent_calc_transition.
     "stroke-width": [ test_length_transition_svg, test_percent_transition,
                       test_length_clamped_svg, test_percent_clamped ],
-    "text-decoration": [ test_color_shorthand_transition,
+    "text-decoration": [ test_general_color_shorthand_transition,
+                         test_currentcolor_shorthand_transition,
                          test_border_color_shorthand_transition ],
-    "text-decoration-color": [ test_color_transition,
+    "text-decoration-color": [ test_general_color_transition,
+                               test_currentcolor_transition,
                                test_border_color_transition ],
-    "text-emphasis-color": [ test_color_transition,
-                             test_border_color_transition ],
+    "text-emphasis-color": [ test_general_color_transition ],
     "text-indent": [ test_length_transition, test_percent_transition,
                      test_length_percent_calc_transition,
                      test_length_unclamped, test_percent_unclamped ],
     "text-shadow": [ test_shadow_transition ],
     "top": [ test_length_transition, test_percent_transition,
              test_length_percent_calc_transition,
              test_length_unclamped, test_percent_unclamped ],
     "transform": [ test_transform_transition ],
@@ -253,18 +267,17 @@ var supported_properties = {
                         test_length_percent_calc_transition,
                         test_length_unclamped, test_percent_unclamped ],
     "visibility": [ test_visibility_transition ],
     "width": [ test_length_transition, test_percent_transition,
                test_length_percent_calc_transition,
                test_length_clamped, test_percent_clamped ],
     "word-spacing": [ test_length_transition, test_length_unclamped ],
     "z-index": [ test_integer_transition, test_pos_integer_or_auto_transition ],
-    "-webkit-text-fill-color": [ test_color_transition,
-                                 test_border_color_transition ]
+    "-webkit-text-fill-color": [ test_general_color_transition ]
 };
 
 if (SupportsMaskShorthand()) {
   supported_properties["mask-position"] = [ test_background_position_transition,
                                      // FIXME: We don't currently test clamping,
                                      // since mask-position uses calc() as
                                      // an intermediate form.
                                      /* test_length_percent_pair_unclamped */ ];
@@ -1220,46 +1233,31 @@ function test_length_percent_calc_transi
 
   check_distance(prop, "50%", "calc(37.5% + 50px)", "200px");
   check_distance(prop, "calc(25% + 100px)", "calc(37.5% + 75px)",
                        "75%");
   check_distance(prop, "150px", "calc(125px + 12.5%)",
                        "calc(50% + 50px)");
 }
 
-function test_color_transition(prop, get_color=(x => x), is_shorthand=false) {
+function test_general_color_transition(prop, get_color=(x => x), is_shorthand=false) {
   div.style.setProperty("transition-property", "none", "");
   div.style.setProperty(prop, "rgb(255, 28, 0)", "");
   is(get_color(cs.getPropertyValue(prop)), "rgb(255, 28, 0)",
      "color-valued property " + prop + ": computed value before transition");
   div.style.setProperty("transition-property", prop, "");
   div.style.setProperty(prop, "rgb(75, 84, 128)", "");
   is(get_color(cs.getPropertyValue(prop)), "rgb(210, 42, 32)",
      "color-valued property " + prop + ": interpolation of colors");
 
-  div.style.setProperty("transition-property", "none", "");
-  div.style.setProperty(prop, "rgb(128, 64, 0)", "");
-  (prop == "color" ? div.parentNode : div).style.
-    setProperty("color", "rgb(0, 0, 128)", "");
-  is(get_color(cs.getPropertyValue(prop)), "rgb(128, 64, 0)",
-     "color-valued property " + prop + ": computed value before transition");
-  div.style.setProperty("transition-property", prop, "");
-  div.style.setProperty(prop, "currentColor", "");
-  is(get_color(cs.getPropertyValue(prop)), "rgb(96, 48, 32)",
-     "color-valued property " + prop + ": interpolation of currentColor");
-
   if (!is_shorthand) {
     check_distance(prop, "rgb(255, 28, 0)", "rgb(210, 42, 32)",
                          "rgb(75, 84, 128)");
-    check_distance(prop, "rgb(128, 64, 0)", "rgb(96, 48, 32)",
-                         "currentColor");
   }
 
-  (prop == "color" ? div.parentNode : div).style.removeProperty("color");
-
   div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
   div.style.setProperty("transition-property", "none", "");
   div.style.setProperty(prop, "rgb(0, 255, 0)", "");
   var vals = cs.getPropertyValue(prop).match(/rgb\(([^, ]*), ([^, ]*), ([^, ]*)\)/);
   is(vals.length, 4,
      "color-valued property " + prop + ": flush before clamping test (length)");
   is(vals[1], "0",
      "color-valued property " + prop + ": flush before clamping test (red)");
@@ -1277,16 +1275,36 @@ function test_color_transition(prop, get
      "color-valued property " + prop + ": clamping of negatives (red)");
   is(vals[2], "255",
      "color-valued property " + prop + ": clamping of above-range (green)");
   is(vals[3], "0",
      "color-valued property " + prop + ": clamping of negatives (blue)");
   div.style.setProperty("transition-timing-function", "linear", "");
 }
 
+function test_currentcolor_transition(prop, get_color=(x => x), is_shorthand=false) {
+  div.style.setProperty("transition-property", "none", "");
+  div.style.setProperty(prop, "rgb(128, 64, 0)", "");
+  (prop == "color" ? div.parentNode : div).style.
+    setProperty("color", "rgb(0, 0, 128)", "");
+  is(get_color(cs.getPropertyValue(prop)), "rgb(128, 64, 0)",
+     "color-valued property " + prop + ": computed value before transition");
+  div.style.setProperty("transition-property", prop, "");
+  div.style.setProperty(prop, "currentColor", "");
+  is(get_color(cs.getPropertyValue(prop)), "rgb(96, 48, 32)",
+     "color-valued property " + prop + ": interpolation of currentColor");
+
+  if (!is_shorthand) {
+    check_distance(prop, "rgb(128, 64, 0)", "rgb(96, 48, 32)",
+                         "currentColor");
+  }
+
+  (prop == "color" ? div.parentNode : div).style.removeProperty("color");
+}
+
 function test_border_color_transition(prop, get_color=(x => x), is_shorthand=false) {
   div.style.setProperty("transition-property", "none", "");
   div.style.setProperty(prop, "rgb(128, 64, 0)", "");
   div.style.setProperty("color", "rgb(0, 0, 128)", "");
   is(get_color(cs.getPropertyValue(prop)), "rgb(128, 64, 0)",
      "color-valued property " + prop + ": computed value before transition");
   div.style.setProperty("transition-property", prop, "");
   div.style.removeProperty(prop);
@@ -1301,18 +1319,22 @@ function test_border_color_transition(pr
 }
 
 function get_color_from_shorthand_value(value) {
   var m = value.match(/rgb\([^, ]*, [^, ]*, [^, ]*\)/);
   isnot(m, null, "shorthand property value should contain color");
   return m[0];
 }
 
-function test_color_shorthand_transition(prop) {
-  test_color_transition(prop, get_color_from_shorthand_value, true);
+function test_general_color_shorthand_transition(prop) {
+  test_general_color_transition(prop, get_color_from_shorthand_value, true);
+}
+
+function test_currentcolor_shorthand_transition(prop) {
+  test_currentcolor_transition(prop, get_color_from_shorthand_value, true);
 }
 
 function test_border_color_shorthand_transition(prop) {
   test_border_color_transition(prop, get_color_from_shorthand_value, true);
 }
 
 function test_clip_path_equals(computedValStr, expectedList)
 {