Index: Source/core/css/resolver/MatchResult.h |
diff --git a/Source/core/css/resolver/MatchResult.h b/Source/core/css/resolver/MatchResult.h |
index 8170d451d5f000a2093d6543a17758d4515bea2c..6c304106c801a721bd0ce2a2cbb8af884fb9b23f 100644 |
--- a/Source/core/css/resolver/MatchResult.h |
+++ b/Source/core/css/resolver/MatchResult.h |
@@ -59,21 +59,98 @@ WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(blink::MatchedProperties); |
namespace blink { |
+using MatchedPropertiesVector = WillBeHeapVector<MatchedProperties, 64>; |
+ |
+// MatchedPropertiesRange is used to represent a subset of the matched properties from |
+// a given origin, for instance UA rules, author rules, or a shadow tree scope. This is |
+// needed because rules from different origins are applied in the opposite order for |
+// !important rules, yet in the same order as for normal rules within the same origin. |
+ |
+class MatchedPropertiesRange { |
+public: |
+ MatchedPropertiesRange(MatchedPropertiesVector::const_iterator begin, MatchedPropertiesVector::const_iterator end) |
+ : m_begin(begin) |
+ , m_end(end) |
+ { |
+ } |
+ |
+ MatchedPropertiesVector::const_iterator begin() const { return m_begin; } |
+ MatchedPropertiesVector::const_iterator end() const { return m_end; } |
+ |
+private: |
+ MatchedPropertiesVector::const_iterator m_begin; |
+ MatchedPropertiesVector::const_iterator m_end; |
+}; |
+ |
class MatchResult { |
STACK_ALLOCATED(); |
public: |
void addMatchedProperties(const StylePropertySet* properties, unsigned linkMatchType = CSSSelector::MatchAll, PropertyWhitelistType = PropertyWhitelistNone); |
+ bool hasMatchedProperties() const { return m_matchedProperties.size(); } |
+ |
+ void closeOriginOrScope(bool isUAOrigin); |
+ |
+ void setIsCacheable(bool cacheable) { m_isCacheable = cacheable; } |
+ bool isCacheable() const { return m_isCacheable; } |
+ |
+ MatchedPropertiesRange allRules() const { return MatchedPropertiesRange(m_matchedProperties.begin(), m_matchedProperties.end()); } |
+ MatchedPropertiesRange uaRules() const { return MatchedPropertiesRange(m_matchedProperties.begin(), m_matchedProperties.begin() + m_rangeEnd.first()); } |
+ MatchedPropertiesRange authorRules() const { return MatchedPropertiesRange(m_matchedProperties.begin() + m_rangeEnd.first(), m_matchedProperties.end()); } |
+ |
+ const MatchedPropertiesVector& matchedProperties() const { return m_matchedProperties; } |
+ |
+private: |
+ friend class ImportantAuthorRanges; |
+ friend class ImportantAuthorRangeIterator; |
+ |
+ MatchedPropertiesVector m_matchedProperties; |
+ |
+ // End indices for all MatchedPropertiesRanges of m_matchedProperties. |
+ // That is, the index of the first element of the next range. We always |
+ // store an end index for UA rules even if we have no UA rules, |
+ // hence this vector's length is >= 1. If there are No UA rules, the first |
+ // entry will be 0 indicating an empty range. |
+ Vector<unsigned, 16> m_rangeEnd; |
+ |
+ bool m_isCacheable = true; |
+}; |
+ |
+class ImportantAuthorRangeIterator { |
+public: |
+ ImportantAuthorRangeIterator(const MatchResult& result, unsigned index) |
+ : m_result(result) |
+ , m_index(index) { } |
+ |
+ MatchedPropertiesRange operator*() const |
+ { |
+ // index = 0 is the UA rule range. |
+ ASSERT(m_index); |
+ return MatchedPropertiesRange(m_result.m_matchedProperties.begin() + m_result.m_rangeEnd[m_index - 1], m_result.m_matchedProperties.begin() + m_result.m_rangeEnd[m_index]); |
+ } |
+ |
+ ImportantAuthorRangeIterator& operator++() |
+ { |
+ ASSERT(m_index); |
+ --m_index; |
+ return *this; |
+ } |
+ |
+ bool operator!=(const ImportantAuthorRangeIterator& other) const { return m_index != other.m_index || &m_result != &other.m_result; } |
+ |
+private: |
+ const MatchResult& m_result; |
+ unsigned m_index; |
+}; |
+ |
+class ImportantAuthorRanges { |
+public: |
+ explicit ImportantAuthorRanges(const MatchResult& result) : m_result(result) { } |
- unsigned begin() const { return 0; } |
- unsigned end() const { return matchedProperties.size(); } |
- unsigned beginUA() const { return 0; } |
- unsigned endUA() const { return uaEnd; } |
- unsigned beginAuthor() const { return uaEnd; } |
- unsigned endAuthor() const { return matchedProperties.size(); } |
+ ImportantAuthorRangeIterator begin() const { return ImportantAuthorRangeIterator(m_result, m_result.m_rangeEnd.size() - 1); } |
+ ImportantAuthorRangeIterator end() const { return ImportantAuthorRangeIterator(m_result, 0); } |
- WillBeHeapVector<MatchedProperties, 64> matchedProperties; |
- unsigned uaEnd = 0; |
- bool isCacheable = true; |
+private: |
+ const MatchResult& m_result; |
}; |
inline bool operator==(const MatchedProperties& a, const MatchedProperties& b) |