Index: third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp |
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp |
index c21a17aebd834fa25cb8d8ba7f89d1473ed2f51e..e5ea4aa69be8a6d1e0b80ee0e032b8f69f444edb 100644 |
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp |
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp |
@@ -1884,34 +1884,98 @@ bool CSSPropertyParser::ConsumeColumns(bool important) { |
bool CSSPropertyParser::ConsumeShorthandGreedily( |
const StylePropertyShorthand& shorthand, |
bool important) { |
+ return ConsumeShorthandViaLonghand(shorthand, important, |
+ LonghandsOrder::kNoOrder); |
+} |
+ |
+bool CSSPropertyParser::ConsumeShorthandViaLonghand( |
+ const StylePropertyShorthand& shorthand, |
+ bool important, |
+ LonghandsOrder order) { |
// Existing shorthands have at most 6 longhands. |
DCHECK_LE(shorthand.length(), 6u); |
+ |
+ const bool ordered_parsing = order != LonghandsOrder::kNoOrder; |
+ |
const CSSValue* longhands[6] = {nullptr, nullptr, nullptr, |
nullptr, nullptr, nullptr}; |
+ |
const CSSPropertyID* shorthand_properties = shorthand.properties(); |
- do { |
+ |
+ if (range_.AtEnd()) { |
+ return false; |
+ } |
+ |
+ // Only set "next" to the next ordered longhand. It will remain 0 for |
+ // unordered case. |
+ size_t next = 0; |
+ // For ordered longhands only. It becomes false when the parser fails to parse |
+ // a longhand. In this case, we want to stop subsequent parsing immediately. |
+ bool continue_parsing = true; |
+ |
+ while (!range_.AtEnd()) { |
+ size_t i = next; |
bool found_longhand = false; |
- for (size_t i = 0; !found_longhand && i < shorthand.length(); ++i) { |
- if (longhands[i]) |
+ |
+ while (i < shorthand.length() && continue_parsing) { |
+ if (longhands[i]) { |
+ DCHECK(!ordered_parsing); |
+ ++i; |
continue; |
+ } |
longhands[i] = ParseSingleValue(shorthand_properties[i], shorthand.id()); |
- if (longhands[i]) |
+ if (longhands[i]) { |
found_longhand = true; |
+ if (ordered_parsing) { |
+ ++next; |
+ } |
+ break; |
+ } |
+ if (ordered_parsing) { |
+ if (i == 0) { |
+ return false; |
+ } |
+ continue_parsing = false; |
+ break; |
+ } |
+ ++i; |
} |
- if (!found_longhand) |
+ |
+ if (!found_longhand && !ordered_parsing) { |
return false; |
- } while (!range_.AtEnd()); |
+ } |
+ if (!continue_parsing || next == shorthand.length()) { |
+ DCHECK_GT(next, 0u); |
+ break; |
+ } |
+ } |
+ |
+ if (ordered_parsing) { |
+ DCHECK(longhands[0]); |
+ } |
+ |
+ std::map<size_t, size_t> default_property_index = {{1u, 0}}; |
+ if (order == LonghandsOrder::kOrderBy4Values) { |
+ default_property_index[2u] = 0; |
+ default_property_index[3u] = 1u; |
+ } |
for (size_t i = 0; i < shorthand.length(); ++i) { |
- if (longhands[i]) { |
- AddParsedProperty(shorthand_properties[i], shorthand.id(), *longhands[i], |
- important); |
- } else { |
- AddParsedProperty(shorthand_properties[i], shorthand.id(), |
- *CSSInitialValue::Create(), important); |
+ if (!longhands[i]) { |
+ if (ordered_parsing) { |
+ std::map<size_t, size_t>::iterator iter = |
+ default_property_index.find(i); |
+ DCHECK(iter != default_property_index.end()); |
+ longhands[i] = longhands[iter->second]; |
+ } else { |
+ longhands[i] = CSSInitialValue::Create(); |
+ } |
} |
+ AddParsedProperty(shorthand_properties[i], shorthand.id(), *longhands[i], |
+ important); |
} |
- return true; |
+ |
+ return range_.AtEnd(); |
} |
bool CSSPropertyParser::ConsumeFlex(bool important) { |
@@ -2027,51 +2091,14 @@ bool CSSPropertyParser::ConsumeBorder(bool important) { |
bool CSSPropertyParser::Consume2Values(const StylePropertyShorthand& shorthand, |
bool important) { |
- DCHECK_EQ(shorthand.length(), 2u); |
- const CSSPropertyID* longhands = shorthand.properties(); |
- const CSSValue* start = ParseSingleValue(longhands[0], shorthand.id()); |
- if (!start) |
- return false; |
- |
- const CSSValue* end = ParseSingleValue(longhands[1], shorthand.id()); |
- if (!end) |
- end = start; |
- AddParsedProperty(longhands[0], shorthand.id(), *start, important); |
- AddParsedProperty(longhands[1], shorthand.id(), *end, important); |
- |
- return range_.AtEnd(); |
+ return ConsumeShorthandViaLonghand(shorthand, important, |
+ LonghandsOrder::kOrderBy2Values); |
} |
bool CSSPropertyParser::Consume4Values(const StylePropertyShorthand& shorthand, |
bool important) { |
- DCHECK_EQ(shorthand.length(), 4u); |
- const CSSPropertyID* longhands = shorthand.properties(); |
- const CSSValue* top = ParseSingleValue(longhands[0], shorthand.id()); |
- if (!top) |
- return false; |
- |
- const CSSValue* right = ParseSingleValue(longhands[1], shorthand.id()); |
- const CSSValue* bottom = nullptr; |
- const CSSValue* left = nullptr; |
- if (right) { |
- bottom = ParseSingleValue(longhands[2], shorthand.id()); |
- if (bottom) |
- left = ParseSingleValue(longhands[3], shorthand.id()); |
- } |
- |
- if (!right) |
- right = top; |
- if (!bottom) |
- bottom = top; |
- if (!left) |
- left = right; |
- |
- AddParsedProperty(longhands[0], shorthand.id(), *top, important); |
- AddParsedProperty(longhands[1], shorthand.id(), *right, important); |
- AddParsedProperty(longhands[2], shorthand.id(), *bottom, important); |
- AddParsedProperty(longhands[3], shorthand.id(), *left, important); |
- |
- return range_.AtEnd(); |
+ return ConsumeShorthandViaLonghand(shorthand, important, |
+ LonghandsOrder::kOrderBy4Values); |
} |
// TODO(crbug.com/668012): refactor out property specific logic from this method |