| 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)
|
|
|