From 07fbe6c00c4f7550613cab8abc070f8b8bfb5d41 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Mon, 16 Jul 2012 09:11:33 -0400 Subject: [PATCH] Limit the hashless color quirk to the properties where it's needed, per http://simon.html5.org/specs/quirks-mode#the-hashless-hex-color-quirk . (Bug 774122, patch 1) r=bzbarsky This changes test_property_syntax_errors.html in the following ways: (1) removes the "known failures" handling, since there aren't any (2) changes it to test syntax errors in both quirks mode and standards mode, instead of only in standards mode (3) uses a (new) quirks_values mechanism to property_database.js to test cases that should be invalid in standards mode but accepted in quirks mode --- layout/style/nsCSSParser.cpp | 48 +++++++--- layout/style/nsCSSPropList.h | 21 ++-- layout/style/nsCSSProps.h | 3 +- layout/style/test/property_database.js | 57 ++++++----- .../test/test_property_syntax_errors.html | 95 +++++++++++++------ 5 files changed, 153 insertions(+), 71 deletions(-) diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 54bc08d34c8..836e0a11d2a 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -653,6 +653,9 @@ protected: // True if we are in quirks mode; false in standards or almost standards mode bool mNavQuirkMode : 1; + // True when the hashless color quirk applies. + bool mHashlessColorQuirk : 1; + // True if unsafe rules should be allowed bool mUnsafeRulesEnabled : 1; @@ -746,6 +749,7 @@ CSSParserImpl::CSSParserImpl() mNameSpaceMap(nsnull), mHavePushBack(false), mNavQuirkMode(false), + mHashlessColorQuirk(false), mUnsafeRulesEnabled(false), mHTMLMediaMode(false), mParsingCompoundProperty(false) @@ -3752,7 +3756,7 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue) } // try 'xxyyzz' without '#' prefix for compatibility with IE and Nav4x (bug 23236 and 45804) - if (mNavQuirkMode && !IsParsingCompoundProperty()) { + if (mHashlessColorQuirk) { // - If the string starts with 'a-f', the nsCSSScanner builds the // token as a eCSSToken_Ident and we can parse the string as a // 'xxyyzz' RGB color. @@ -4553,7 +4557,7 @@ CSSParserImpl::ParseVariant(nsCSSValue& aValue, return ParseElement(aValue); } if ((aVariantMask & VARIANT_COLOR) != 0) { - if ((mNavQuirkMode && !IsParsingCompoundProperty()) || // NONSTANDARD: Nav interprets 'xxyyzz' values even without '#' prefix + if (mHashlessColorQuirk || // NONSTANDARD: Nav interprets 'xxyyzz' values even without '#' prefix (eCSSToken_ID == tk->mType) || (eCSSToken_Ref == tk->mType) || (eCSSToken_Ident == tk->mType) || @@ -5614,36 +5618,58 @@ static const nsCSSProperty kOutlineRadiusIDs[] = { bool CSSParserImpl::ParseProperty(nsCSSProperty aPropID) { + // Can't use AutoRestore because it's a bitfield. + NS_ABORT_IF_FALSE(!mHashlessColorQuirk, + "hashless color quirk should not be set"); + if (mNavQuirkMode) { + mHashlessColorQuirk = + nsCSSProps::PropHasFlags(aPropID, CSS_PROPERTY_HASHLESS_COLOR_QUIRK); + } + NS_ASSERTION(aPropID < eCSSProperty_COUNT, "index out of range"); + bool result; switch (nsCSSProps::PropertyParseType(aPropID)) { case CSS_PROPERTY_PARSE_INACCESSIBLE: { // The user can't use these REPORT_UNEXPECTED(PEInaccessibleProperty2); - return false; + result = false; + break; } case CSS_PROPERTY_PARSE_FUNCTION: { - return ParsePropertyByFunction(aPropID); + result = ParsePropertyByFunction(aPropID); + break; } case CSS_PROPERTY_PARSE_VALUE: { + result = false; nsCSSValue value; if (ParseSingleValueProperty(value, aPropID)) { if (ExpectEndProperty()) { AppendValue(aPropID, value); - return true; + result = true; } // XXX Report errors? } // XXX Report errors? - return false; + break; } case CSS_PROPERTY_PARSE_VALUE_LIST: { - return ParseValueList(aPropID); + result = ParseValueList(aPropID); + break; + } + default: { + result = false; + NS_ABORT_IF_FALSE(false, + "Property's flags field in nsCSSPropList.h is missing " + "one of the CSS_PROPERTY_PARSE_* constants"); + break; } } - NS_ABORT_IF_FALSE(false, - "Property's flags field in nsCSSPropList.h is missing " - "one of the CSS_PROPERTY_PARSE_* constants"); - return false; + + if (mNavQuirkMode) { + mHashlessColorQuirk = false; + } + + return result; } bool diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index 915e60000ce..a397fb10d2a 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -482,7 +482,8 @@ CSS_PROP_BACKGROUND( BackgroundColor, CSS_PROPERTY_PARSE_VALUE | CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE | - CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED, + CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED | + CSS_PROPERTY_HASHLESS_COLOR_QUIRK, "", VARIANT_HC, nsnull, @@ -592,7 +593,8 @@ CSS_PROP_BORDER( BorderBottomColor, CSS_PROPERTY_PARSE_VALUE | CSS_PROPERTY_APPLIES_TO_FIRST_LETTER | - CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED, + CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED | + CSS_PROPERTY_HASHLESS_COLOR_QUIRK, "", VARIANT_HCK, kBorderColorKTable, @@ -647,7 +649,8 @@ CSS_PROP_SHORTHAND( border-color, border_color, BorderColor, - CSS_PROPERTY_PARSE_FUNCTION, + CSS_PROPERTY_PARSE_FUNCTION | + CSS_PROPERTY_HASHLESS_COLOR_QUIRK, "") CSS_PROP_SHORTHAND( -moz-border-end, @@ -785,7 +788,8 @@ CSS_PROP_SHORTHAND( border-left-color, border_left_color, BorderLeftColor, - CSS_PROPERTY_PARSE_FUNCTION, + CSS_PROPERTY_PARSE_FUNCTION | + CSS_PROPERTY_HASHLESS_COLOR_QUIRK, "") #ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_BORDER( @@ -939,7 +943,8 @@ CSS_PROP_SHORTHAND( border-right-color, border_right_color, BorderRightColor, - CSS_PROPERTY_PARSE_FUNCTION, + CSS_PROPERTY_PARSE_FUNCTION | + CSS_PROPERTY_HASHLESS_COLOR_QUIRK, "") #ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_BORDER( @@ -1176,7 +1181,8 @@ CSS_PROP_BORDER( BorderTopColor, CSS_PROPERTY_PARSE_VALUE | CSS_PROPERTY_APPLIES_TO_FIRST_LETTER | - CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED, + CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED | + CSS_PROPERTY_HASHLESS_COLOR_QUIRK, "", VARIANT_HCK, kBorderColorKTable, @@ -1352,7 +1358,8 @@ CSS_PROP_COLOR( Color, CSS_PROPERTY_PARSE_VALUE | CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE | - CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED, + CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED | + CSS_PROPERTY_HASHLESS_COLOR_QUIRK, "", VARIANT_HC, nsnull, diff --git a/layout/style/nsCSSProps.h b/layout/style/nsCSSProps.h index 32eefb5464c..92a6676dd8e 100644 --- a/layout/style/nsCSSProps.h +++ b/layout/style/nsCSSProps.h @@ -92,7 +92,8 @@ MOZ_STATIC_ASSERT((CSS_PROPERTY_PARSE_PROPERTY_MASK & // should enforce that the value of this property must be 1 or larger. #define CSS_PROPERTY_VALUE_AT_LEAST_ONE (2<<13) -// NOTE: next free bit is (1<<15) +// Does this property suppor the hashless hex color quirk in quirks mode? +#define CSS_PROPERTY_HASHLESS_COLOR_QUIRK (1<<15) /** * Types of animatable values. diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index a6d8806ed37..87182ab869a 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -29,6 +29,8 @@ const CSS_TYPE_SHORTHAND_AND_LONGHAND = 2; // may not be the same as for the property's initial value. // invalid_values: Things that are not values for the property and // should be rejected. +// quirks_values: Values that should be accepted in quirks mode only, +// mapped to the values they are equivalent to. // Helper functions used to construct gCSSProperties. @@ -148,7 +150,7 @@ var gCSSProperties = { type: CSS_TYPE_LONGHAND, initial_values: [ "none" ], other_values: [ "red green", "red #fc3", "#ff00cc", "currentColor", "blue currentColor orange currentColor" ], - invalid_values: [ "red none", "red inherit", "red, green", "none red", "inherit red" ] + invalid_values: [ "red none", "red inherit", "red, green", "none red", "inherit red", "ff00cc" ] }, "-moz-border-end": { domProp: "MozBorderEnd", @@ -166,7 +168,7 @@ var gCSSProperties = { get_computed: logical_box_prop_get_computed, initial_values: [ "currentColor" ], other_values: [ "green", "rgba(255,128,0,0.5)", "transparent" ], - invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000" ] + invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000", "000000" ] }, "-moz-border-end-style": { domProp: "MozBorderEndStyle", @@ -279,7 +281,7 @@ var gCSSProperties = { type: CSS_TYPE_LONGHAND, initial_values: [ "none" ], other_values: [ "red green", "red #fc3", "#ff00cc", "currentColor", "blue currentColor orange currentColor" ], - invalid_values: [ "red none", "red inherit", "red, green", "none red", "inherit red" ] + invalid_values: [ "red none", "red inherit", "red, green", "none red", "inherit red", "ff00cc" ] }, "border-radius": { domProp: "borderRadius", @@ -385,7 +387,7 @@ var gCSSProperties = { type: CSS_TYPE_LONGHAND, initial_values: [ "none" ], other_values: [ "red green", "red #fc3", "#ff00cc", "currentColor", "blue currentColor orange currentColor" ], - invalid_values: [ "red none", "red inherit", "red, green", "none red", "inherit red" ] + invalid_values: [ "red none", "red inherit", "red, green", "none red", "inherit red", "ff00cc" ] }, "-moz-border-start": { domProp: "MozBorderStart", @@ -403,7 +405,7 @@ var gCSSProperties = { get_computed: logical_box_prop_get_computed, initial_values: [ "currentColor" ], other_values: [ "green", "rgba(255,128,0,0.5)", "transparent" ], - invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000" ] + invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000", "000000" ] }, "-moz-border-start-style": { domProp: "MozBorderStartStyle", @@ -440,7 +442,7 @@ var gCSSProperties = { type: CSS_TYPE_LONGHAND, initial_values: [ "none" ], other_values: [ "red green", "red #fc3", "#ff00cc", "currentColor", "blue currentColor orange currentColor" ], - invalid_values: [ "red none", "red inherit", "red, green", "none red", "inherit red" ] + invalid_values: [ "red none", "red inherit", "red, green", "none red", "inherit red", "ff00cc" ] }, "-moz-box-align": { domProp: "MozBoxAlign", @@ -829,7 +831,7 @@ var gCSSProperties = { prerequisites: { "color": "green" }, initial_values: [ "currentColor", "-moz-use-text-color" ], other_values: [ "red", "blue", "#ffff00" ], - invalid_values: [ ] + invalid_values: [ "ffff00" ] }, "-moz-column-width": { domProp: "MozColumnWidth", @@ -1468,6 +1470,8 @@ var gCSSProperties = { invalid_values: [ /* mixes with keywords have to be in correct order */ "50% left", "top 50%", + /* no quirks mode colors */ + "-moz-radial-gradient(10% bottom, ffffff, black) scroll no-repeat", /* bug 258080: don't accept background-position separated */ "left url(404.png) top", "top url(404.png) left", /* not allowed to have color in non-bottom layer */ @@ -1512,7 +1516,8 @@ var gCSSProperties = { type: CSS_TYPE_LONGHAND, initial_values: [ "transparent", "rgba(255, 127, 15, 0)", "hsla(240, 97%, 50%, 0.0)", "rgba(0, 0, 0, 0)", "rgba(255,255,255,-3.7)" ], other_values: [ "green", "rgb(255, 0, 128)", "#fc2", "#96ed2a", "black", "rgba(255,255,0,3)" ], - invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000", "rgb(255.0,0.387,3489)" ] + invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000", "rgb(255.0,0.387,3489)" ], + quirks_values: { "000000": "#000000", "96ed2a": "#96ed2a" }, }, "background-image": { domProp: "backgroundImage", @@ -1793,6 +1798,8 @@ var gCSSProperties = { "-moz-element(#a a)", "-moz-element(#a+a)", "-moz-element(#a()", + /* no quirks mode colors */ + "linear-gradient(red, ff00ff)", /* Old syntax */ "-moz-linear-gradient(10px 10px, 20px, 30px 30px, 40px, from(blue), to(red))", "-moz-radial-gradient(20px 20px, 10px 10px, from(green), to(#ff00ff))", @@ -2105,7 +2112,7 @@ var gCSSProperties = { subproperties: [ "border-bottom-color", "border-bottom-style", "border-bottom-width", "border-left-color", "border-left-style", "border-left-width", "border-right-color", "border-right-style", "border-right-width", "border-top-color", "border-top-style", "border-top-width", "-moz-border-top-colors", "-moz-border-right-colors", "-moz-border-bottom-colors", "-moz-border-left-colors", "border-image-source", "border-image-slice", "border-image-width", "border-image-outset", "border-image-repeat" ], initial_values: [ "none", "medium", "currentColor", "thin", "none medium currentcolor", "calc(4px - 1px) none" ], other_values: [ "solid", "medium solid", "green solid", "10px solid", "thick solid", "calc(2px) solid blue" ], - invalid_values: [ "5%" ] + invalid_values: [ "5%", "medium solid ff00ff" ] }, "border-bottom": { domProp: "borderBottom", @@ -2123,7 +2130,8 @@ var gCSSProperties = { prerequisites: { "color": "black" }, initial_values: [ "currentColor", "-moz-use-text-color" ], other_values: [ "green", "rgba(255,128,0,0.5)", "transparent" ], - invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000" ] + invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000" ], + quirks_values: { "000000": "#000000", "96ed2a": "#96ed2a" }, }, "border-bottom-style": { domProp: "borderBottomStyle", @@ -2167,7 +2175,8 @@ var gCSSProperties = { subproperties: [ "border-top-color", "border-right-color", "border-bottom-color", "border-left-color" ], initial_values: [ "currentColor", "currentColor currentColor", "currentColor currentColor currentColor", "currentColor currentColor currentcolor CURRENTcolor" ], other_values: [ "green", "currentColor green", "currentColor currentColor green", "currentColor currentColor currentColor green", "rgba(255,128,0,0.5)", "transparent" ], - invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000" ] + invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000" ], + quirks_values: { "000000": "#000000", "96ed2a": "#96ed2a" }, }, "border-left": { domProp: "borderLeft", @@ -2185,7 +2194,8 @@ var gCSSProperties = { prerequisites: { "color": "black" }, initial_values: [ "currentColor", "-moz-use-text-color" ], other_values: [ "green", "rgba(255,128,0,0.5)", "transparent" ], - invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000" ] + invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000" ], + quirks_values: { "000000": "#000000", "96ed2a": "#96ed2a" }, }, "border-left-style": { domProp: "borderLeftStyle", @@ -2230,7 +2240,8 @@ var gCSSProperties = { prerequisites: { "color": "black" }, initial_values: [ "currentColor", "-moz-use-text-color" ], other_values: [ "green", "rgba(255,128,0,0.5)", "transparent" ], - invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000" ] + invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000" ], + quirks_values: { "000000": "#000000", "96ed2a": "#96ed2a" }, }, "border-right-style": { domProp: "borderRightStyle", @@ -2293,7 +2304,8 @@ var gCSSProperties = { prerequisites: { "color": "black" }, initial_values: [ "currentColor", "-moz-use-text-color" ], other_values: [ "green", "rgba(255,128,0,0.5)", "transparent" ], - invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000" ] + invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000" ], + quirks_values: { "000000": "#000000", "96ed2a": "#96ed2a" }, }, "border-top-style": { domProp: "borderTopStyle", @@ -2403,7 +2415,8 @@ var gCSSProperties = { /* XXX should test currentColor, but may or may not be initial */ initial_values: [ "black", "#000" ], other_values: [ "green", "#f3c", "#fed292", "rgba(45,300,12,2)", "transparent", "-moz-nativehyperlinktext", "rgba(255,128,0,0.5)" ], - invalid_values: [ "fff", "ffffff", "#f", "#ff", "#ffff", "#fffff", "#fffffff", "#ffffffff", "#fffffffff" ] + invalid_values: [ "#f", "#ff", "#ffff", "#fffff", "#fffffff", "#ffffffff", "#fffffffff" ], + quirks_values: { "000000": "#000000", "96ed2a": "#96ed2a", "fff": "#ffffff", "ffffff": "#ffffff", }, }, "content": { domProp: "content", @@ -2925,7 +2938,7 @@ var gCSSProperties = { prerequisites: { "color": "black" }, initial_values: [ "currentColor", "-moz-use-text-color" ], // XXX should be invert other_values: [ "green", "rgba(255,128,0,0.5)", "transparent" ], - invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000" ] + invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000", "000000", "cc00ff" ] }, "outline-offset": { domProp: "outlineOffset", @@ -3198,7 +3211,7 @@ var gCSSProperties = { prerequisites: { "color": "black" }, initial_values: [ "currentColor", "-moz-use-text-color" ], other_values: [ "green", "rgba(255,128,0,0.5)", "transparent" ], - invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000" ] + invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000", "000000", "ff00ff" ] }, "-moz-text-decoration-line": { domProp: "MozTextDecorationLine", @@ -3569,7 +3582,7 @@ var gCSSProperties = { prerequisites: { "color": "blue" }, initial_values: [ "black", "#000", "#000000", "rgb(0,0,0)", "rgba(0,0,0,1)" ], other_values: [ "green", "#fc3", "url('#myserver')", "url(foo.svg#myserver)", 'url("#myserver") green', "none", "currentColor" ], - invalid_values: [] + invalid_values: [ "000000", "ff00ff" ] }, "fill-opacity": { domProp: "fillOpacity", @@ -3602,7 +3615,7 @@ var gCSSProperties = { prerequisites: { "color": "blue" }, initial_values: [ "black", "#000", "#000000", "rgb(0,0,0)", "rgba(0,0,0,1)" ], other_values: [ "green", "#fc3", "currentColor" ], - invalid_values: [ "url('#myserver')", "url(foo.svg#myserver)", 'url("#myserver") green' ] + invalid_values: [ "url('#myserver')", "url(foo.svg#myserver)", 'url("#myserver") green', "000000", "ff00ff" ] }, "flood-opacity": { domProp: "floodOpacity", @@ -3627,7 +3640,7 @@ var gCSSProperties = { prerequisites: { "color": "blue" }, initial_values: [ "white", "#fff", "#ffffff", "rgb(255,255,255)", "rgba(255,255,255,1.0)", "rgba(255,255,255,42.0)" ], other_values: [ "green", "#fc3", "currentColor" ], - invalid_values: [ "url('#myserver')", "url(foo.svg#myserver)", 'url("#myserver") green' ] + invalid_values: [ "url('#myserver')", "url(foo.svg#myserver)", 'url("#myserver") green', "000000", "ff00ff" ] }, "marker": { domProp: "marker", @@ -3685,7 +3698,7 @@ var gCSSProperties = { prerequisites: { "color": "blue" }, initial_values: [ "black", "#000", "#000000", "rgb(0,0,0)", "rgba(0,0,0,1)" ], other_values: [ "green", "#fc3", "currentColor" ], - invalid_values: [ "url('#myserver')", "url(foo.svg#myserver)", 'url("#myserver") green' ] + invalid_values: [ "url('#myserver')", "url(foo.svg#myserver)", 'url("#myserver") green', "000000", "ff00ff" ] }, "stop-opacity": { domProp: "stopOpacity", @@ -3701,7 +3714,7 @@ var gCSSProperties = { type: CSS_TYPE_LONGHAND, initial_values: [ "none" ], other_values: [ "black", "#000", "#000000", "rgb(0,0,0)", "rgba(0,0,0,1)", "green", "#fc3", "url('#myserver')", "url(foo.svg#myserver)", 'url("#myserver") green', "currentColor" ], - invalid_values: [] + invalid_values: [ "000000", "ff00ff" ] }, "stroke-dasharray": { domProp: "strokeDasharray", diff --git a/layout/style/test/test_property_syntax_errors.html b/layout/style/test/test_property_syntax_errors.html index 8f373272027..e9dbeacb5a5 100644 --- a/layout/style/test/test_property_syntax_errors.html +++ b/layout/style/test/test_property_syntax_errors.html @@ -8,8 +8,9 @@ - +

+