Bug 1210575 part 8: Implement -webkit-linear-gradient parse quirks with "to", angles, and "center". r=heycam
authorDaniel Holbert <dholbert@cs.stanford.edu>
Thu, 22 Oct 2015 16:36:50 -0700
changeset 304297 88e2038fc5f18e8ccfa77add459aac75e2c6eb76
parent 304296 6008b75fe289d593f362a92e6626d05ebdf43bf6
child 304298 781f5d938ed3a146fb4256756632ef838b707292
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)
reviewersheycam
bugs1210575
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 1210575 part 8: Implement -webkit-linear-gradient parse quirks with "to", angles, and "center". r=heycam
layout/style/nsCSSParser.cpp
layout/style/test/property_database.js
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -9455,17 +9455,19 @@ CSSParserImpl::ParseLinearGradient(nsCSS
 {
   RefPtr<nsCSSValueGradient> cssGradient
     = new nsCSSValueGradient(false, aFlags & eGradient_Repeating);
 
   if (!GetToken(true)) {
     return false;
   }
 
-  if (mToken.mType == eCSSToken_Ident &&
+  // Check for "to" syntax (but not if parsing a -webkit-linear-gradient)
+  if (!(aFlags & eGradient_WebkitLegacy) &&
+      mToken.mType == eCSSToken_Ident &&
       mToken.mIdent.LowerCaseEqualsLiteral("to")) {
 
     // "to" syntax doesn't allow explicit "center"
     if (!ParseBoxPositionValues(cssGradient->mBgPos, false, false)) {
       SkipUntil(')');
       return false;
     }
 
@@ -9478,17 +9480,17 @@ CSSParserImpl::ParseLinearGradient(nsCSS
     if (!ExpectSymbol(',', true)) {
       SkipUntil(')');
       return false;
     }
 
     return ParseGradientColorStops(cssGradient, aValue);
   }
 
-  if (!(aFlags & eGradient_MozLegacy)) {
+  if (!(aFlags & eGradient_AnyLegacy)) {
     // We're parsing an unprefixed linear-gradient, and we tried & failed to
     // parse a 'to' token above. Put the token back & try to re-parse our
     // expression as <angle>? <color-stop-list>
     UngetToken();
 
     // <angle> ,
     if (ParseSingleTokenVariant(cssGradient->mAngle, VARIANT_ANGLE, nullptr) &&
         !ExpectSymbol(',', true)) {
@@ -9508,28 +9510,42 @@ CSSParserImpl::ParseLinearGradient(nsCSS
   if (haveGradientLine) {
     // Parse a <legacy-gradient-line>
     cssGradient->mIsLegacySyntax = true;
     bool haveAngle =
       ParseSingleTokenVariant(cssGradient->mAngle, VARIANT_ANGLE, nullptr);
 
     // if we got an angle, we might now have a comma, ending the gradient-line
     bool haveAngleComma = haveAngle && ExpectSymbol(',', true);
-    // XXXdholbert (Note: the logic here gets a bit more interesting when we
-    // add support for -webkit-linear-gradient's quirks.)
-    if (!haveAngleComma) {
-      if (!ParseBoxPositionValues(cssGradient->mBgPos, false)) {
+
+    // 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)) {
+      // (Note: 3rd arg controls whether the "center" keyword is allowed.
+      // -moz-linear-gradient allows it; -webkit-linear-gradient does not.)
+      if (!ParseBoxPositionValues(cssGradient->mBgPos, false,
+                                  (aFlags & eGradient_MozLegacy))) {
+        SkipUntil(')');
+        return false;
+      }
+
+      // -webkit-linear-gradient only supports edge keywords here.
+      if ((aFlags & eGradient_WebkitLegacy) &&
+          !IsBoxPositionStrictlyEdgeKeywords(cssGradient->mBgPos)) {
         SkipUntil(')');
         return false;
       }
 
       if (!ExpectSymbol(',', true) &&
-          // if we didn't already get an angle, we might have one now,
-          // otherwise it's an error
+          // 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
            !ExpectSymbol(',', true))) {
         SkipUntil(')');
         return false;
       }
     }
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -642,16 +642,19 @@ if (IsCSSPropertyPrefEnabled("layout.css
 
     // Contain/cover keywords (valid only for -moz/-webkit prefixed):
     "-webkit-radial-gradient(cover, red, blue)",
     "-webkit-radial-gradient(cover circle, red, blue)",
     "-webkit-radial-gradient(contain, red, blue)",
     "-webkit-radial-gradient(contain ellipse, red, blue)",
 
     // Initial side/corner/point (valid only for -moz/-webkit prefixed):
+    "-webkit-linear-gradient(left, red, blue)",
+    "-webkit-linear-gradient(right top, red, blue)",
+    "-webkit-linear-gradient(top right, red, blue)",
     "-webkit-radial-gradient(right, red, blue)",
     "-webkit-radial-gradient(left bottom, red, blue)",
     "-webkit-radial-gradient(bottom left, red, blue)",
     "-webkit-radial-gradient(center, red, blue)",
     "-webkit-radial-gradient(center right, red, blue)",
     "-webkit-radial-gradient(center center, red, blue)",
     "-webkit-radial-gradient(center top, red, blue)",
     "-webkit-radial-gradient(left 50%, red, blue)",
@@ -661,16 +664,18 @@ if (IsCSSPropertyPrefEnabled("layout.css
     // Point + keyword-sized shape (valid only for -moz/-webkit prefixed):
     "-webkit-radial-gradient(center, circle closest-corner, red, blue)",
     "-webkit-radial-gradient(10px 20px, cover circle, red, blue)",
     "-webkit-radial-gradient(5em 50%, ellipse contain, red, blue)",
 
     // Repeating examples:
     "-webkit-repeating-linear-gradient(red 10%, blue 30%)",
     "-webkit-repeating-linear-gradient(30deg, pink 20px, orange 70px)",
+    "-webkit-repeating-linear-gradient(left, red, blue)",
+    "-webkit-repeating-linear-gradient(left, red 10%, blue 30%)",
     "-webkit-repeating-radial-gradient(circle, red, blue 10%, red 20%)",
     "-webkit-repeating-radial-gradient(circle farthest-corner, gray 10px, yellow 20px)",
     "-webkit-repeating-radial-gradient(top left, circle, red, blue 4%, red 8%)"
   );
 
   invalidGradientAndElementValues.push(
     // Syntax that's invalid for all types of gradients:
     // * empty gradient expressions:
@@ -679,18 +684,33 @@ if (IsCSSPropertyPrefEnabled("layout.css
     "-webkit-repeating-linear-gradient()",
     "-webkit-repeating-radial-gradient()",
 
     // Syntax that's invalid for both -webkit & -moz, but valid for unprefixed:
     // XXXdholbert (populated in a later patch)
 
     // Linear syntax that's invalid for both -webkit & unprefixed, but valid
     // for -moz:
-    // * initial length
+    // * initial <legacy-gradient-line> which includes a length:
     "-webkit-linear-gradient(10px, red, blue)",
+    "-webkit-linear-gradient(10px top, red, blue)",
+    // * initial <legacy-gradient-line> which includes a side *and* an angle:
+    "-webkit-linear-gradient(bottom 30deg, red, blue)",
+    "-webkit-linear-gradient(30deg bottom, red, blue)",
+    "-webkit-linear-gradient(10px top 50deg, red, blue)",
+    "-webkit-linear-gradient(50deg 10px top, red, blue)",
+    // * initial <legacy-gradient-line> which includes explicit "center":
+    "-webkit-linear-gradient(center, red, blue)",
+    "-webkit-linear-gradient(left center, red, blue)",
+    "-webkit-linear-gradient(top center, red, blue)",
+    "-webkit-linear-gradient(center top, red, blue)",
+
+    // Linear syntax that's invalid for -webkit, but valid for -moz & unprefixed:
+    // * "to" syntax:
+    "-webkit-linear-gradient(to top, red, blue)",
 
     // * <shape> followed by angle:
     "-webkit-radial-gradient(circle 10deg, red, blue)",
 
     // Radial syntax that's invalid for both -webkit & -moz, but valid for
     // unprefixed:
     // * "<shape> at <position>" syntax:
     "-webkit-radial-gradient(circle at left bottom, red, blue)",