Bug 1307049 - Remove nsCSSValueGradient.mIsLegacySyntax, remove support for -webkit-gradient; r?dholbert draft
authorManish Goregaokar <manishsmail@gmail.com>
Mon, 03 Oct 2016 13:14:29 +0530
changeset 420098 a94d010e0a96229d87dcaa2490b4ba0502101958
parent 420067 c65e472dc755b610e9a1b64e7482227d195a8ffb
child 532719 f95228617eb54db79e71a858e1220dd3b95cde84
push id31093
push userbmo:manishearth@gmail.com
push dateMon, 03 Oct 2016 09:56:09 +0000
reviewersdholbert
bugs1307049
milestone52.0a1
Bug 1307049 - Remove nsCSSValueGradient.mIsLegacySyntax, remove support for -webkit-gradient; r?dholbert MozReview-Commit-ID: AejhUcgo2dJ
layout/style/nsCSSParser.cpp
layout/style/nsCSSValue.cpp
layout/style/nsCSSValue.h
layout/style/nsRuleNode.cpp
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -1304,33 +1304,16 @@ protected:
   };
   bool ParseLinearGradient(nsCSSValue& aValue, uint8_t aFlags);
   bool ParseRadialGradient(nsCSSValue& aValue, uint8_t aFlags);
   bool IsLegacyGradientLine(const nsCSSTokenType& aType,
                             const nsString& aId);
   bool ParseGradientColorStops(nsCSSValueGradient* aGradient,
                                nsCSSValue& aValue);
 
-  // For the ancient "-webkit-gradient(linear|radial, ...)" syntax:
-  bool ParseWebkitGradientPointComponent(nsCSSValue& aComponent,
-                                         bool aIsHorizontal);
-  bool ParseWebkitGradientPoint(nsCSSValuePair& aPoint);
-  bool ParseWebkitGradientRadius(float& aRadius);
-  bool ParseWebkitGradientColorStop(nsCSSValueGradient* aGradient);
-  bool ParseWebkitGradientColorStops(nsCSSValueGradient* aGradient);
-  void FinalizeLinearWebkitGradient(nsCSSValueGradient* aGradient,
-                                    const nsCSSValuePair& aStartPoint,
-                                    const nsCSSValuePair& aSecondPoint);
-  void FinalizeRadialWebkitGradient(nsCSSValueGradient* aGradient,
-                                    const nsCSSValuePair& aFirstCenter,
-                                    const nsCSSValuePair& aSecondCenter,
-                                    const float aFirstRadius,
-                                    const float aSecondRadius);
-  bool ParseWebkitGradient(nsCSSValue& aValue);
-
   void SetParsingCompoundProperty(bool aBool) {
     mParsingCompoundProperty = aBool;
   }
   bool IsParsingCompoundProperty(void) const {
     return mParsingCompoundProperty;
   }
 
   /* Functions for basic shapes */
@@ -7901,27 +7884,16 @@ CSSParserImpl::ParseVariant(nsCSSValue& 
       return CSSParseResult::Ok;
     }
     if (tmp.LowerCaseEqualsLiteral("radial-gradient")) {
       if (!ParseRadialGradient(aValue, gradientFlags)) {
         return CSSParseResult::Error;
       }
       return CSSParseResult::Ok;
     }
-    if ((gradientFlags == eGradient_WebkitLegacy) &&
-        tmp.LowerCaseEqualsLiteral("gradient")) {
-      // Note: we check gradientFlags using '==' to select *exactly*
-      // eGradient_WebkitLegacy -- and exclude eGradient_Repeating -- because
-      // we don't want to accept -webkit-repeating-gradient() expressions.
-      // (This is not a recognized syntax.)
-      if (!ParseWebkitGradient(aValue)) {
-        return CSSParseResult::Error;
-      }
-      return CSSParseResult::Ok;
-    }
 
     if (ShouldUseUnprefixingService() &&
         !gradientFlags &&
         StringBeginsWith(tmp, NS_LITERAL_STRING("-webkit-"))) {
       // Copy 'tmp' into a string on the stack, since as soon as we
       // start parsing, its backing store (in "tk") will be overwritten
       nsAutoString prefixedFuncName(tmp);
       if (!ParseWebkitPrefixedGradientWithService(prefixedFuncName, aValue)) {
@@ -10107,30 +10079,59 @@ IsBoxPositionStrictlyEdgeKeywords(nsCSSV
                                    NS_STYLE_IMAGELAYER_POSITION_CENTER |
                                    NS_STYLE_IMAGELAYER_POSITION_RIGHT)) &&
           yValue.GetUnit() == eCSSUnit_Enumerated &&
           (yValue.GetIntValue() & (NS_STYLE_IMAGELAYER_POSITION_TOP |
                                    NS_STYLE_IMAGELAYER_POSITION_CENTER |
                                    NS_STYLE_IMAGELAYER_POSITION_BOTTOM)));
 }
 
+// Helper for ParseLinearGradient -- `to top left` is `bottom right`
+// in legacy mode, and we need to inver them
+static void
+FlipBoxPositionEdges(nsCSSValuePair& aPosition)
+{
+  nsCSSValue& xValue = aPosition.mXValue;
+  nsCSSValue& yValue = aPosition.mYValue;
+  switch (xValue.GetIntValue()) {
+    case NS_STYLE_IMAGELAYER_POSITION_LEFT:
+      xValue.SetIntValue(NS_STYLE_IMAGELAYER_POSITION_RIGHT,
+                         eCSSUnit_Enumerated);
+      break;
+    case NS_STYLE_IMAGELAYER_POSITION_RIGHT:
+      xValue.SetIntValue(NS_STYLE_IMAGELAYER_POSITION_LEFT,
+                         eCSSUnit_Enumerated);
+      break;
+  }
+  switch (yValue.GetIntValue()) {
+    case NS_STYLE_IMAGELAYER_POSITION_TOP:
+      yValue.SetIntValue(NS_STYLE_IMAGELAYER_POSITION_BOTTOM,
+                         eCSSUnit_Enumerated);
+      break;
+    case NS_STYLE_IMAGELAYER_POSITION_BOTTOM:
+      yValue.SetIntValue(NS_STYLE_IMAGELAYER_POSITION_TOP,
+                         eCSSUnit_Enumerated);
+      break;
+  }
+}
+
 // <gradient>
 //    : linear-gradient( <linear-gradient-line>? <color-stops> ')'
 //    | radial-gradient( <radial-gradient-line>? <color-stops> ')'
 //
 // <linear-gradient-line> : [ to [left | right] || [top | bottom] ] ,
 //                        | <legacy-gradient-line>
 // <radial-gradient-line> : [ <shape> || <size> ] [ at <position> ]? ,
 //                        | [ at <position> ] ,
 //                        | <legacy-gradient-line>? <legacy-shape-size>?
 // <shape> : circle | ellipse
 // <size> : closest-side | closest-corner | farthest-side | farthest-corner
 //        | <length> | [<length> | <percentage>]{2}
 //
-// <legacy-gradient-line> : [ <position> || <angle>] ,
+// <legacy-gradient-line> : [ [left | right] || [top | bottom] || <angle>] ,
 //
 // <legacy-shape-size> : [ <shape> || <legacy-size> ] ,
 // <legacy-size> : closest-side | closest-corner | farthest-side
 //               | farthest-corner | contain | cover
 //
 // <color-stops> : <color-stop> , <color-stop> [, <color-stop>]*
 bool
 CSSParserImpl::ParseLinearGradient(nsCSSValue& aValue,
@@ -10187,26 +10188,31 @@ CSSParserImpl::ParseLinearGradient(nsCSS
   // If we get here, we're parsing a prefixed linear-gradient expression.  Put
   // back the first token (which we may have checked for "to" above) and try to
   // parse expression as <legacy-gradient-line>? <color-stop-list>
   bool haveGradientLine = IsLegacyGradientLine(mToken.mType, mToken.mIdent);
   UngetToken();
 
   if (haveGradientLine) {
     // Parse a <legacy-gradient-line>
-    cssGradient->mIsLegacySyntax = true;
+
     // In -webkit-linear-gradient expressions (handled below), we need to accept
     // unitless 0 for angles, to match WebKit/Blink.
     int32_t angleFlags = (aFlags & eGradient_WebkitLegacy) ?
       VARIANT_ANGLE | VARIANT_ZERO_ANGLE :
       VARIANT_ANGLE;
 
     bool haveAngle =
       ParseSingleTokenVariant(cssGradient->mAngle, angleFlags, nullptr);
 
+    if (haveAngle) {
+      cssGradient->mAngle.SetFloatValue(M_PI_2 - cssGradient->mAngle.GetAngleValueInRadians(),
+                                        eCSSUnit_Radian);
+    }
+
     // If we got an angle, we might now have a comma, ending the gradient-line.
     bool haveAngleComma = haveAngle && ExpectSymbol(',', true);
 
     // If we're webkit-prefixed & didn't get an angle,
     // OR if we're moz-prefixed & didn't get an angle+comma,
     // then proceed to parse a box-position.
     if (((aFlags & eGradient_WebkitLegacy) && !haveAngle) ||
         ((aFlags & eGradient_MozLegacy) && !haveAngleComma)) {
@@ -10220,16 +10226,19 @@ CSSParserImpl::ParseLinearGradient(nsCSS
 
       // -webkit-linear-gradient only supports edge keywords here.
       // -moz-linear-gradient used to, but not anymore (see bug 1307049)
       if (!IsBoxPositionStrictlyEdgeKeywords(cssGradient->mBgPos)) {
         SkipUntil(')');
         return false;
       }
 
+      // legacy gradients use the corner as "from", not "to"
+      FlipBoxPositionEdges(cssGradient->mBgPos);
+
       if (!ExpectSymbol(',', true) &&
           // If we didn't already get an angle, and we're not -webkit prefixed,
           // we can parse an angle+comma now.  Otherwise it's an error.
           (haveAngle ||
            (aFlags & eGradient_WebkitLegacy) ||
            !ParseSingleTokenVariant(cssGradient->mAngle, VARIANT_ANGLE,
                                     nullptr) ||
            // now we better have a comma
@@ -10372,20 +10381,16 @@ CSSParserImpl::ParseRadialGradient(nsCSS
            !ParseSingleTokenVariant(cssGradient->mAngle, VARIANT_ANGLE,
                                     nullptr) ||
            // now we better have a comma
            !ExpectSymbol(',', true))) {
         SkipUntil(')');
         return false;
       }
     }
-
-    if (cssGradient->mAngle.GetUnit() != eCSSUnit_None) {
-      cssGradient->mIsLegacySyntax = true;
-    }
   }
 
   // radial gradients might have a shape and size here for legacy syntax
   if (!haveShape && !haveSize) {
     haveShape =
       ParseSingleTokenVariant(cssGradient->GetRadialShape(), VARIANT_KEYWORD,
                               nsCSSProps::kRadialGradientShapeKTable);
     haveSize =
@@ -10497,478 +10502,16 @@ CSSParserImpl::ParseGradientColorStops(n
   if (previousPointWasInterpolationHint) {
     return false;
   }
 
   aValue.SetGradientValue(aGradient);
   return true;
 }
 
-// Parses the x or y component of a -webkit-gradient() <point> expression.
-// See ParseWebkitGradientPoint() documentation for more.
-bool
-CSSParserImpl::ParseWebkitGradientPointComponent(nsCSSValue& aComponent,
-                                                 bool aIsHorizontal)
-{
-  if (!GetToken(true)) {
-    return false;
-  }
-
-  // Keyword tables to use for keyword-matching
-  // (Keyword order is important; we assume the index can be multiplied by 50%
-  // to convert to a percent-valued component.)
-  static const nsCSSKeyword kHorizKeywords[] = {
-    eCSSKeyword_left,   //   0%
-    eCSSKeyword_center, //  50%
-    eCSSKeyword_right   // 100%
-  };
-  static const nsCSSKeyword kVertKeywords[] = {
-    eCSSKeyword_top,     //   0%
-    eCSSKeyword_center,  //  50%
-    eCSSKeyword_bottom   // 100%
-  };
-  static const size_t kNumKeywords = MOZ_ARRAY_LENGTH(kHorizKeywords);
-  static_assert(kNumKeywords == MOZ_ARRAY_LENGTH(kVertKeywords),
-                "Horizontal & vertical keyword tables must have same count");
-
-  // Try to parse the component as a number, or a percent, or a
-  // keyword-converted-to-percent.
-  if (mToken.mType == eCSSToken_Number) {
-    aComponent.SetFloatValue(mToken.mNumber, eCSSUnit_Pixel);
-  } else if (mToken.mType == eCSSToken_Percentage) {
-    aComponent.SetPercentValue(mToken.mNumber);
-  } else if (mToken.mType == eCSSToken_Ident) {
-    nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent);
-    if (keyword == eCSSKeyword_UNKNOWN) {
-      return false;
-    }
-    // Choose our keyword table:
-    const nsCSSKeyword* kwTable = aIsHorizontal ? kHorizKeywords : kVertKeywords;
-    // Convert keyword to percent value (0%, 50%, or 100%)
-    bool didAcceptKeyword = false;
-    for (size_t i = 0; i < kNumKeywords; i++) {
-      if (keyword == kwTable[i]) {
-        // 0%, 50%, or 100%:
-        aComponent.SetPercentValue(i * 0.5);
-        didAcceptKeyword = true;
-        break;
-      }
-    }
-    if (!didAcceptKeyword) {
-      return false;
-    }
-  } else {
-    // Unrecognized token type. Put it back. (It might be a closing-paren of an
-    // invalid -webkit-gradient(...) expression, and we need to be sure caller
-    // can see it & stops parsing at that point.)
-    UngetToken();
-    return false;
-  }
-
-  MOZ_ASSERT(aComponent.GetUnit() == eCSSUnit_Pixel ||
-             aComponent.GetUnit() == eCSSUnit_Percent,
-             "If we get here, we should've successfully parsed a number (as a "
-             "pixel length), a percent, or a keyword (converted to percent)");
-  return true;
-}
-
-// This function parses a "<point>" expression for -webkit-gradient(...)
-// Quoting https://www.webkit.org/blog/175/introducing-css-gradients/ :
-//   "A point is a pair of space-separated values.
-//    The syntax supports numbers, percentages or
-//    the keywords top, bottom, left and right
-//    for point values."
-//
-// Two additional notes:
-//  - WebKit also accepts the "center" keyword (not listed in the text above).
-//  - WebKit only accepts horizontal-flavored keywords (left/center/right) in
-//    the first ("x") component, and vertical-flavored keywords
-//    (top/center/bottom) in the second ("y") component. (This is different
-//    from the standard gradient syntax, which accepts both orderings, e.g.
-//    "top left" as well as "left top".)
-bool
-CSSParserImpl::ParseWebkitGradientPoint(nsCSSValuePair& aPoint)
-{
-  return ParseWebkitGradientPointComponent(aPoint.mXValue, true) &&
-    ParseWebkitGradientPointComponent(aPoint.mYValue, false);
-}
-
-// Parse the next token as a <number> (for a <radius> in a -webkit-gradient
-// expresison).  Returns true on success; returns false & puts back
-// whatever it parsed on failure.
-bool
-CSSParserImpl::ParseWebkitGradientRadius(float& aRadius)
-{
-  if (!GetToken(true)) {
-    return false;
-  }
-
-  if (mToken.mType != eCSSToken_Number) {
-    UngetToken();
-    return false;
-  }
-
-  aRadius = mToken.mNumber;
-  return true;
-}
-
-// Parse one of:
-//  color-stop(number|percent, color)
-//  from(color)
-//  to(color)
-//
-// Quoting https://www.webkit.org/blog/175/introducing-css-gradients/ :
-//   A stop is a function, color-stop, that takes two arguments, the stop value
-//   (either a percentage or a number between 0 and 1.0), and a color (any
-//   valid CSS color). In addition the shorthand functions from and to are
-//   supported. These functions only require a color argument and are
-//   equivalent to color-stop(0, ...) and color-stop(1.0, …) respectively.
-bool
-CSSParserImpl::ParseWebkitGradientColorStop(nsCSSValueGradient* aGradient)
-{
-  MOZ_ASSERT(aGradient, "null gradient");
-
-  if (!GetToken(true)) {
-    return false;
-  }
-
-  // We're expecting color-stop(...), from(...), or to(...) which are all
-  // functions. Bail if we got anything else.
-  if (mToken.mType != eCSSToken_Function) {
-    UngetToken();
-    return false;
-  }
-
-  nsCSSValueGradientStop* stop = aGradient->mStops.AppendElement();
-
-  // Parse color-stop location (or infer it, for shorthands "from"/"to"):
-  if (mToken.mIdent.LowerCaseEqualsLiteral("color-stop")) {
-    // Parse stop location, followed by comma.
-    if (!ParseSingleTokenVariant(stop->mLocation,
-                                 VARIANT_NUMBER | VARIANT_PERCENT,
-                                 nullptr) ||
-        !ExpectSymbol(',', true)) {
-      SkipUntil(')'); // Skip to end of color-stop(...) expression.
-      return false;
-    }
-
-    // If we got a <number>, convert it to percentage for consistency:
-    if (stop->mLocation.GetUnit() == eCSSUnit_Number) {
-      stop->mLocation.SetPercentValue(stop->mLocation.GetFloatValue());
-    }
-  } else if (mToken.mIdent.LowerCaseEqualsLiteral("from")) {
-    // Shorthand for color-stop(0%, ...)
-    stop->mLocation.SetPercentValue(0.0f);
-  } else if (mToken.mIdent.LowerCaseEqualsLiteral("to")) {
-    // Shorthand for color-stop(100%, ...)
-    stop->mLocation.SetPercentValue(1.0f);
-  } else {
-    // Unrecognized function name (invalid for a -webkit-gradient color stop).
-    UngetToken();
-    return false;
-  }
-
-  CSSParseResult result = ParseVariant(stop->mColor, VARIANT_COLOR, nullptr);
-  if (result != CSSParseResult::Ok ||
-      (stop->mColor.GetUnit() == eCSSUnit_EnumColor &&
-       stop->mColor.GetIntValue() == NS_COLOR_CURRENTCOLOR)) {
-    // Parse failure, or parsed "currentColor" which is forbidden in
-    // -webkit-gradient for some reason.
-    SkipUntil(')');
-    return false;
-  }
-
-  // Parse color-stop function close-paren
-  if (!ExpectSymbol(')', true)) {
-    SkipUntil(')');
-    return false;
-  }
-
-  MOZ_ASSERT(stop->mLocation.GetUnit() == eCSSUnit_Percent,
-             "Should produce only percent-valued stop-locations. "
-             "(Caller depends on this when sorting color stops.)");
-
-  return true;
-}
-
-// Comparatison function to use for sorting -webkit-gradient() stops by
-// location. This function assumes stops have percent-valued locations (and
-// CSSParserImpl::ParseWebkitGradientColorStop should enforce this).
-static bool
-IsColorStopPctLocationLessThan(const nsCSSValueGradientStop& aStop1,
-                               const nsCSSValueGradientStop& aStop2) {
-  return (aStop1.mLocation.GetPercentValue() <
-          aStop2.mLocation.GetPercentValue());
-}
-
-// This function parses a list of comma-separated color-stops for a
-// -webkit-gradient(...) expression, and then pads & sorts the list as-needed.
-bool
-CSSParserImpl::ParseWebkitGradientColorStops(nsCSSValueGradient* aGradient)
-{
-  MOZ_ASSERT(aGradient, "null gradient");
-
-  // Parse any number of ", <color-stop>" expressions. (0 or more)
-  // Note: This is different from unprefixed gradient syntax, which
-  // requires at least 2 stops.
-  while (ExpectSymbol(',', true)) {
-    if (!ParseWebkitGradientColorStop(aGradient)) {
-      return false;
-    }
-  }
-
-  // Pad up to 2 stops as-needed:
-  // (Modern gradient expressions are required to have at least 2 stops, so we
-  // depend on this internally -- e.g. we have an assertion about this in
-  // nsCSSRendering.cpp. -webkit-gradient syntax allows 0 stops or 1 stop,
-  // though, so we just pad up to 2 stops in this case).
-
-  // If we have no stops, pad with transparent-black:
-  if (aGradient->mStops.IsEmpty()) {
-    nsCSSValueGradientStop* stop1 = aGradient->mStops.AppendElement();
-    stop1->mColor.SetIntegerColorValue(NS_RGBA(0, 0, 0, 0),
-                                       eCSSUnit_RGBAColor);
-    stop1->mLocation.SetPercentValue(0.0f);
-
-    nsCSSValueGradientStop* stop2 = aGradient->mStops.AppendElement();
-    stop2->mColor.SetIntegerColorValue(NS_RGBA(0, 0, 0, 0),
-                                       eCSSUnit_RGBAColor);
-    stop2->mLocation.SetPercentValue(1.0f);
-  } else if (aGradient->mStops.Length() == 1) {
-    // Copy whatever the author provided in the first stop:
-    nsCSSValueGradientStop* stop = aGradient->mStops.AppendElement();
-    *stop = aGradient->mStops[0];
-  } else {
-    // We have >2 stops. Sort them in order of increasing location.
-    std::stable_sort(aGradient->mStops.begin(),
-                     aGradient->mStops.end(),
-                     IsColorStopPctLocationLessThan);
-  }
-  return true;
-}
-
-// Compares aStartCoord to aEndCoord, and returns true iff they share the same
-// unit (both pixel, or both percent) and aStartCoord is larger.
-static bool
-IsWebkitGradientCoordLarger(const nsCSSValue& aStartCoord,
-                            const nsCSSValue& aEndCoord)
-{
-  if (aStartCoord.GetUnit() == eCSSUnit_Percent &&
-      aEndCoord.GetUnit() == eCSSUnit_Percent) {
-    return aStartCoord.GetPercentValue() > aEndCoord.GetPercentValue();
-  }
-
-  if (aStartCoord.GetUnit() == eCSSUnit_Pixel &&
-      aEndCoord.GetUnit() == eCSSUnit_Pixel) {
-    return aStartCoord.GetFloatValue() > aEndCoord.GetFloatValue();
-  }
-
-  // We can't compare them, since their units differ. Returning false suggests
-  // that aEndCoord is larger, which is probably a decent guess anyway.
-  return false;
-}
-
-// Finalize our internal representation of a -webkit-gradient(linear, ...)
-// expression, given the parsed points.  (The parsed color stops
-// should already be hanging off of the passed-in nsCSSValueGradient.)
-//
-// Note: linear gradients progress along a line between two points.  The
-// -webkit-gradient(linear, ...) syntax lets the author precisely specify the
-// starting and ending point. However, our internal gradient structures
-// only store one point, and the other point is implicitly its reflection
-// across the painted area's center. (The legacy -moz-linear-gradient syntax
-// also lets us store an angle.)
-//
-// In this function, we try to go from the two-point representation to an
-// equivalent or approximately-equivalent one-point representation.
-void
-CSSParserImpl::FinalizeLinearWebkitGradient(nsCSSValueGradient* aGradient,
-                                            const nsCSSValuePair& aStartPoint,
-                                            const nsCSSValuePair& aEndPoint)
-{
-  MOZ_ASSERT(!aGradient->mIsRadial, "passed-in gradient must be linear");
-
-  // If the start & end points have the same Y-coordinate, then we can treat
-  // this as a horizontal gradient progressing towards the center of the left
-  // or right side.
-  if (aStartPoint.mYValue == aEndPoint.mYValue) {
-    aGradient->mBgPos.mYValue.SetIntValue(NS_STYLE_IMAGELAYER_POSITION_CENTER,
-                                          eCSSUnit_Enumerated);
-    if (IsWebkitGradientCoordLarger(aStartPoint.mXValue, aEndPoint.mXValue)) {
-      aGradient->mBgPos.mXValue.SetIntValue(NS_STYLE_IMAGELAYER_POSITION_LEFT,
-                                            eCSSUnit_Enumerated);
-    } else {
-      aGradient->mBgPos.mXValue.SetIntValue(NS_STYLE_IMAGELAYER_POSITION_RIGHT,
-                                            eCSSUnit_Enumerated);
-    }
-    return;
-  }
-
-  // If the start & end points have the same X-coordinate, then we can treat
-  // this as a horizontal gradient progressing towards the center of the top
-  // or bottom side.
-  if (aStartPoint.mXValue == aEndPoint.mXValue) {
-    aGradient->mBgPos.mXValue.SetIntValue(NS_STYLE_IMAGELAYER_POSITION_CENTER,
-                                          eCSSUnit_Enumerated);
-    if (IsWebkitGradientCoordLarger(aStartPoint.mYValue, aEndPoint.mYValue)) {
-      aGradient->mBgPos.mYValue.SetIntValue(NS_STYLE_IMAGELAYER_POSITION_TOP,
-                                            eCSSUnit_Enumerated);
-    } else {
-      aGradient->mBgPos.mYValue.SetIntValue(NS_STYLE_IMAGELAYER_POSITION_BOTTOM,
-                                            eCSSUnit_Enumerated);
-    }
-    return;
-  }
-
-  // OK, the gradient is angled, which means we likely can't represent it
-  // exactly in |aGradient|, without doing analysis on the two points to
-  // extract an angle (which we might not be able to do depending on the units
-  // used).  For now, we'll just do something really basic -- just use the
-  // first point as if it were the starting point in a legacy
-  // -moz-linear-gradient() expression. That way, the rendered gradient will
-  // progress from this first point, towards the center of the covered element,
-  // to a reflected end point on the far side. Note that we have to use
-  // mIsLegacySyntax=true for this to work, because standardized (non-legacy)
-  // gradients place some restrictions on the reference point [namely, that it
-  // use percent units & be on the border of the element].
-  aGradient->mIsLegacySyntax = true;
-  aGradient->mBgPos = aStartPoint;
-}
-
-// Finalize our internal representation of a -webkit-gradient(radial, ...)
-// expression, given the parsed points & radii.  (The parsed color-stops
-// should already be hanging off of the passed-in nsCSSValueGradient).
-void
-CSSParserImpl::FinalizeRadialWebkitGradient(nsCSSValueGradient* aGradient,
-                                            const nsCSSValuePair& aFirstCenter,
-                                            const nsCSSValuePair& aSecondCenter,
-                                            const float aFirstRadius,
-                                            const float aSecondRadius)
-{
-  MOZ_ASSERT(aGradient->mIsRadial, "passed-in gradient must be radial");
-
-  // NOTE: -webkit-gradient(radial, ...) has *two arbitrary circles*, with the
-  // gradient stretching between the circles' edges.  In contrast, the standard
-  // syntax (and hence our data structures) can only represent *one* circle,
-  // with the gradient going from its center to its edge.  To bridge this gap
-  // in expressiveness, we'll just see which of our two circles is smaller, and
-  // we'll treat that circle as if it were zero-sized and located at the center
-  // of the larger circle. Then, we'll be able to use the same data structures
-  // that we use for the standard radial-gradient syntax.
-  if (aSecondRadius >= aFirstRadius) {
-    // Second circle is larger.
-    aGradient->mBgPos = aSecondCenter;
-    aGradient->mIsExplicitSize = true;
-    aGradient->GetRadiusX().SetFloatValue(aSecondRadius, eCSSUnit_Pixel);
-    return;
-  }
-
-  // First circle is larger, so we'll have it be the outer circle.
-  aGradient->mBgPos = aFirstCenter;
-  aGradient->mIsExplicitSize = true;
-  aGradient->GetRadiusX().SetFloatValue(aFirstRadius, eCSSUnit_Pixel);
-
-  // For this to work properly (with the earlier color stops attached to the
-  // first circle), we need to also reverse the color-stop list, so that
-  // e.g. the author's "from" color is attached to the outer edge (the first
-  // circle), rather than attached to the center (the collapsed second circle).
-  std::reverse(aGradient->mStops.begin(), aGradient->mStops.end());
-
-  // And now invert the stop locations:
-  for (nsCSSValueGradientStop& colorStop : aGradient->mStops) {
-    float origLocation = colorStop.mLocation.GetPercentValue();
-    colorStop.mLocation.SetPercentValue(1.0f - origLocation);
-  }
-}
-
-bool
-CSSParserImpl::ParseWebkitGradient(nsCSSValue& aValue)
-{
-  // Parse type of gradient
-  if (!GetToken(true)) {
-    return false;
-  }
-
-  if (mToken.mType != eCSSToken_Ident) {
-    UngetToken(); // Important; the token might be ")", which we're about to
-                  // seek to.
-    SkipUntil(')');
-    return false;
-  }
-
-  bool isRadial;
-  if (mToken.mIdent.LowerCaseEqualsLiteral("radial")) {
-    isRadial = true;
-  } else if (mToken.mIdent.LowerCaseEqualsLiteral("linear")) {
-    isRadial = false;
-  } else {
-    // Unrecognized gradient type.
-    SkipUntil(')');
-    return false;
-  }
-
-  // Parse a comma + first point:
-  nsCSSValuePair firstPoint;
-  if (!ExpectSymbol(',', true) ||
-      !ParseWebkitGradientPoint(firstPoint)) {
-    SkipUntil(')');
-    return false;
-  }
-
-  // If radial, parse comma + first radius:
-  float firstRadius;
-  if (isRadial) {
-    if (!ExpectSymbol(',', true) ||
-        !ParseWebkitGradientRadius(firstRadius)) {
-      SkipUntil(')');
-      return false;
-    }
-  }
-
-  // Parse a comma + second point:
-  nsCSSValuePair secondPoint;
-  if (!ExpectSymbol(',', true) ||
-      !ParseWebkitGradientPoint(secondPoint)) {
-    SkipUntil(')');
-    return false;
-  }
-
-  // If radial, parse comma + second radius:
-  float secondRadius;
-  if (isRadial) {
-    if (!ExpectSymbol(',', true) ||
-        !ParseWebkitGradientRadius(secondRadius)) {
-      SkipUntil(')');
-      return false;
-    }
-  }
-
-  // Construct a nsCSSValueGradient object, and parse color stops into it:
-  RefPtr<nsCSSValueGradient> cssGradient =
-    new nsCSSValueGradient(isRadial, false /* aIsRepeating */);
-
-  if (!ParseWebkitGradientColorStops(cssGradient) ||
-      !ExpectSymbol(')', true)) {
-    // Failed to parse color-stops, or found trailing junk between them & ')'.
-    SkipUntil(')');
-    return false;
-  }
-
-  // Finish building cssGradient, based on our parsed positioning/sizing info:
-  if (isRadial) {
-    FinalizeRadialWebkitGradient(cssGradient, firstPoint, secondPoint,
-                           firstRadius, secondRadius);
-  } else {
-    FinalizeLinearWebkitGradient(cssGradient, firstPoint, secondPoint);
-  }
-
-  aValue.SetGradientValue(cssGradient);
-  return true;
-}
-
 bool
 CSSParserImpl::ParseWebkitTextStroke()
 {
   static const nsCSSPropertyID kWebkitTextStrokeIDs[] = {
     eCSSProperty__webkit_text_stroke_width,
     eCSSProperty__webkit_text_stroke_color
   };
 
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -1619,30 +1619,27 @@ nsCSSValue::AppendToString(nsCSSProperty
     aResult.AppendFloat(GetPercentValue() * 100.0f);
   }
   else if (eCSSUnit_Percent < unit) {  // length unit
     aResult.AppendFloat(GetFloatValue());
   }
   else if (eCSSUnit_Gradient == unit) {
     nsCSSValueGradient* gradient = GetGradientValue();
 
-    if (gradient->mIsLegacySyntax) {
-      aResult.AppendLiteral("-moz-");
-    }
     if (gradient->mIsRepeating) {
       aResult.AppendLiteral("repeating-");
     }
     if (gradient->mIsRadial) {
       aResult.AppendLiteral("radial-gradient(");
     } else {
       aResult.AppendLiteral("linear-gradient(");
     }
 
     bool needSep = false;
-    if (gradient->mIsRadial && !gradient->mIsLegacySyntax) {
+    if (gradient->mIsRadial) {
       if (!gradient->mIsExplicitSize) {
         if (gradient->GetRadialShape().GetUnit() != eCSSUnit_None) {
           MOZ_ASSERT(gradient->GetRadialShape().GetUnit() ==
                      eCSSUnit_Enumerated,
                      "bad unit for radial gradient shape");
           int32_t intValue = gradient->GetRadialShape().GetIntValue();
           MOZ_ASSERT(intValue != NS_STYLE_GRADIENT_SHAPE_LINEAR,
                      "radial gradient with linear shape?!");
@@ -1672,17 +1669,17 @@ nsCSSValue::AppendToString(nsCSSProperty
         if (gradient->GetRadiusY().GetUnit() != eCSSUnit_None) {
           aResult.Append(' ');
           gradient->GetRadiusY().AppendToString(aProperty, aResult,
                                                 aSerialization);
         }
         needSep = true;
       }
     }
-    if (!gradient->mIsRadial && !gradient->mIsLegacySyntax) {
+    if (!gradient->mIsRadial) {
       if (gradient->mBgPos.mXValue.GetUnit() != eCSSUnit_None ||
           gradient->mBgPos.mYValue.GetUnit() != eCSSUnit_None) {
         MOZ_ASSERT(gradient->mAngle.GetUnit() == eCSSUnit_None);
         MOZ_ASSERT(gradient->mBgPos.mXValue.GetUnit() == eCSSUnit_Enumerated &&
                    gradient->mBgPos.mYValue.GetUnit() == eCSSUnit_Enumerated,
                    "unexpected unit");
         aResult.AppendLiteral("to");
         if (!(gradient->mBgPos.mXValue.GetIntValue() & NS_STYLE_IMAGELAYER_POSITION_CENTER)) {
@@ -1701,66 +1698,32 @@ nsCSSValue::AppendToString(nsCSSProperty
         needSep = true;
       }
     } else if (gradient->mBgPos.mXValue.GetUnit() != eCSSUnit_None ||
         gradient->mBgPos.mYValue.GetUnit() != eCSSUnit_None ||
         gradient->mAngle.GetUnit() != eCSSUnit_None) {
       if (needSep) {
         aResult.Append(' ');
       }
-      if (gradient->mIsRadial && !gradient->mIsLegacySyntax) {
+      if (gradient->mIsRadial) {
         aResult.AppendLiteral("at ");
       }
       if (gradient->mBgPos.mXValue.GetUnit() != eCSSUnit_None) {
         gradient->mBgPos.mXValue.AppendToString(eCSSProperty_background_position_x,
                                                 aResult, aSerialization);
         aResult.Append(' ');
       }
       if (gradient->mBgPos.mYValue.GetUnit() != eCSSUnit_None) {
         gradient->mBgPos.mYValue.AppendToString(eCSSProperty_background_position_y,
                                                 aResult, aSerialization);
         aResult.Append(' ');
       }
-      if (gradient->mAngle.GetUnit() != eCSSUnit_None) {
-        MOZ_ASSERT(gradient->mIsLegacySyntax,
-                   "angle is allowed only for legacy syntax");
-        gradient->mAngle.AppendToString(aProperty, aResult, aSerialization);
-      }
       needSep = true;
     }
 
-    if (gradient->mIsRadial && gradient->mIsLegacySyntax &&
-        (gradient->GetRadialShape().GetUnit() != eCSSUnit_None ||
-         gradient->GetRadialSize().GetUnit() != eCSSUnit_None)) {
-      MOZ_ASSERT(!gradient->mIsExplicitSize);
-      if (needSep) {
-        aResult.AppendLiteral(", ");
-      }
-      if (gradient->GetRadialShape().GetUnit() != eCSSUnit_None) {
-        MOZ_ASSERT(gradient->GetRadialShape().GetUnit() == eCSSUnit_Enumerated,
-                   "bad unit for radial gradient shape");
-        int32_t intValue = gradient->GetRadialShape().GetIntValue();
-        MOZ_ASSERT(intValue != NS_STYLE_GRADIENT_SHAPE_LINEAR,
-                   "radial gradient with linear shape?!");
-        AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
-                               nsCSSProps::kRadialGradientShapeKTable),
-                           aResult);
-        aResult.Append(' ');
-      }
-
-      if (gradient->GetRadialSize().GetUnit() != eCSSUnit_None) {
-        MOZ_ASSERT(gradient->GetRadialSize().GetUnit() == eCSSUnit_Enumerated,
-                   "bad unit for radial gradient size");
-        int32_t intValue = gradient->GetRadialSize().GetIntValue();
-        AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
-                               nsCSSProps::kRadialGradientSizeKTable),
-                           aResult);
-      }
-      needSep = true;
-    }
     if (needSep) {
       aResult.AppendLiteral(", ");
     }
 
     for (uint32_t i = 0 ;;) {
       bool isInterpolationHint = gradient->mStops[i].mIsInterpolationHint;
       if (!isInterpolationHint) {
         gradient->mStops[i].mColor.AppendToString(aProperty, aResult,
@@ -2861,17 +2824,16 @@ nsCSSValueGradientStop::SizeOfExcludingT
   n += mColor   .SizeOfExcludingThis(aMallocSizeOf);
   return n;
 }
 
 nsCSSValueGradient::nsCSSValueGradient(bool aIsRadial,
                                        bool aIsRepeating)
   : mIsRadial(aIsRadial),
     mIsRepeating(aIsRepeating),
-    mIsLegacySyntax(false),
     mIsExplicitSize(false),
     mBgPos(eCSSUnit_None),
     mAngle(eCSSUnit_None)
 {
   mRadialValues[0].SetNoneValue();
   mRadialValues[1].SetNoneValue();
 }
 
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -1602,17 +1602,16 @@ public:
 };
 
 struct nsCSSValueGradient final {
   nsCSSValueGradient(bool aIsRadial, bool aIsRepeating);
 
   // true if gradient is radial, false if it is linear
   bool mIsRadial;
   bool mIsRepeating;
-  bool mIsLegacySyntax;
   bool mIsExplicitSize;
   // line position and angle
   nsCSSValuePair mBgPos;
   nsCSSValue mAngle;
 
   // Only meaningful if mIsRadial is true
 private:
   nsCSSValue mRadialValues[2];
@@ -1659,17 +1658,16 @@ public:
   }
 
   InfallibleTArray<nsCSSValueGradientStop> mStops;
 
   bool operator==(const nsCSSValueGradient& aOther) const
   {
     if (mIsRadial != aOther.mIsRadial ||
         mIsRepeating != aOther.mIsRepeating ||
-        mIsLegacySyntax != aOther.mIsLegacySyntax ||
         mIsExplicitSize != aOther.mIsExplicitSize ||
         mBgPos != aOther.mBgPos ||
         mAngle != aOther.mAngle ||
         mRadialValues[0] != aOther.mRadialValues[0] ||
         mRadialValues[1] != aOther.mRadialValues[1])
       return false;
 
     if (mStops.Length() != aOther.mStops.Length())
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -1216,22 +1216,16 @@ static void SetGradient(const nsCSSValue
   const nsStyleCoord dummyParentCoord;
   if (!SetCoord(gradient->mAngle, aResult.mAngle, dummyParentCoord, SETCOORD_ANGLE,
                 aContext, aPresContext, aConditions)) {
     NS_ASSERTION(gradient->mAngle.GetUnit() == eCSSUnit_None,
                  "bad unit for gradient angle");
     aResult.mAngle.SetNoneValue();
   }
 
-  if (gradient->mIsLegacySyntax) {
-    MOZ_ASSERT(aResult.mAngle.IsAngleValue());
-    aResult.mAngle.SetAngleValue(M_PI_2 - aResult.mAngle.GetAngleValueInRadians(),
-                                 eStyleUnit_Radian);
-  }
-
   // stops
   for (uint32_t i = 0; i < gradient->mStops.Length(); i++) {
     nsStyleGradientStop stop;
     const nsCSSValueGradientStop &valueStop = gradient->mStops[i];
 
     if (!SetCoord(valueStop.mLocation, stop.mLocation,
                   nsStyleCoord(), SETCOORD_LPO | SETCOORD_STORE_CALC,
                   aContext, aPresContext, aConditions)) {