Index: Source/core/dom/NthIndexCache.h |
diff --git a/Source/core/dom/NthIndexCache.h b/Source/core/dom/NthIndexCache.h |
index 19923a06c51693bd33ed9fa45812f0bfe8817466..0cb69cfdd9463289f748311529c39e58bd6bb1bb 100644 |
--- a/Source/core/dom/NthIndexCache.h |
+++ b/Source/core/dom/NthIndexCache.h |
@@ -16,6 +16,13 @@ |
namespace blink { |
class Document; |
+class HasTagName { |
+public: |
+ explicit HasTagName(const QualifiedName& tagName) : m_tagName(tagName) { } |
+ bool operator() (const Element& element) const { return element.hasTagName(m_tagName); } |
+private: |
+ const QualifiedName m_tagName; |
+}; |
class CORE_EXPORT NthIndexCache final { |
STACK_ALLOCATED(); |
@@ -25,7 +32,9 @@ public: |
~NthIndexCache(); |
inline unsigned nthChildIndex(Element&); |
+ inline unsigned nthChildIndexOfType(Element&, const QualifiedName&); |
inline unsigned nthLastChildIndex(Element&); |
+ inline unsigned nthLastChildIndexOfType(Element&, const QualifiedName&); |
private: |
class NthIndexData final : public NoBaseWillBeGarbageCollected<NthIndexData> { |
@@ -35,9 +44,12 @@ private: |
NthIndexData() { } |
inline unsigned nthIndex(Element&); |
+ inline unsigned nthIndexOfType(Element&, const QualifiedName&); |
inline unsigned nthLastIndex(Element&); |
+ inline unsigned nthLastIndexOfType(Element&, const QualifiedName&); |
unsigned cacheNthIndices(Element&); |
+ unsigned cacheNthIndicesOfType(Element&, const QualifiedName&); |
WillBeHeapHashMap<RawPtrWillBeMember<Element>, unsigned> m_elementIndexMap; |
unsigned m_count = 0; |
@@ -45,11 +57,20 @@ private: |
DECLARE_TRACE(); |
}; |
+ using ParentMap = WillBeHeapHashMap<RefPtrWillBeMember<Node>, OwnPtrWillBeMember<NthIndexData>>; |
+ OwnPtrWillBeMember<ParentMap> m_parentMap; |
+ |
+ using IndexByType = WillBeHeapHashMap<String, OwnPtrWillBeMember<NthIndexData>>; |
+ |
+ using ParentMapForType = WillBeHeapHashMap<RefPtrWillBeMember<Node>, OwnPtrWillBeMember<IndexByType>>; |
+ OwnPtrWillBeMember<ParentMapForType> m_parentMapForType; |
+ |
+ |
NthIndexData& ensureNthIndexDataFor(Node&); |
+ NthIndexCache::IndexByType& ensureTypeIndexMap(Node&); |
- using ParentMap = WillBeHeapHashMap<RefPtrWillBeMember<Node>, OwnPtrWillBeMember<NthIndexData>>; |
+ NthIndexCache::NthIndexData& nthIndexDataWithTagName(Element&); |
- OwnPtrWillBeMember<ParentMap> m_parentMap; |
RawPtrWillBeMember<Document> m_document; |
uint64_t m_domTreeVersion; |
}; |
@@ -70,6 +91,21 @@ inline unsigned NthIndexCache::NthIndexData::nthIndex(Element& element) |
return index; |
} |
+inline unsigned NthIndexCache::NthIndexData::nthIndexOfType(Element& element, const QualifiedName& type) |
+{ |
+ if (element.isPseudoElement()) |
+ return 1; |
+ if (!m_count) |
+ return cacheNthIndicesOfType(element, type); |
+ unsigned index = 0; |
+ for (Element* sibling = &element; sibling; sibling = ElementTraversal::previousSibling(*sibling, HasTagName(type)), index++) { |
+ auto it = m_elementIndexMap.find(sibling); |
+ if (it != m_elementIndexMap.end()) |
+ return it->value + index; |
+ } |
+ return index; |
+} |
+ |
inline unsigned NthIndexCache::NthIndexData::nthLastIndex(Element& element) |
{ |
if (element.isPseudoElement()) |
@@ -78,18 +114,39 @@ inline unsigned NthIndexCache::NthIndexData::nthLastIndex(Element& element) |
return m_count - index + 1; |
} |
+inline unsigned NthIndexCache::NthIndexData::nthLastIndexOfType(Element& element, const QualifiedName& type) |
+{ |
+ if (element.isPseudoElement()) |
+ return 1; |
+ unsigned index = nthIndexOfType(element, type); |
+ return m_count - index + 1; |
+} |
+ |
inline unsigned NthIndexCache::nthChildIndex(Element& element) |
{ |
ASSERT(element.parentNode()); |
return ensureNthIndexDataFor(*element.parentNode()).nthIndex(element); |
} |
+inline unsigned NthIndexCache::nthChildIndexOfType(Element& element, const QualifiedName& type) |
+{ |
+ ASSERT(element.parentNode()); |
+ return nthIndexDataWithTagName(element).nthIndexOfType(element, type); |
+} |
+ |
inline unsigned NthIndexCache::nthLastChildIndex(Element& element) |
{ |
ASSERT(element.parentNode()); |
return ensureNthIndexDataFor(*element.parentNode()).nthLastIndex(element); |
} |
+inline unsigned NthIndexCache::nthLastChildIndexOfType(Element& element, const QualifiedName& type) |
+{ |
+ ASSERT(element.parentNode()); |
+ return nthIndexDataWithTagName(element).nthLastIndexOfType(element, type); |
+} |
+ |
+ |
} // namespace blink |
#endif // NthIndexCache_h |