Index: Source/core/dom/TreeScope.h |
diff --git a/Source/core/dom/TreeScope.h b/Source/core/dom/TreeScope.h |
index 1bfcdf91861bd05cc0b548b98cc7eebc3ba2422e..72877b63df1f15fcf59b5938dc834a14904f8ce9 100644 |
--- a/Source/core/dom/TreeScope.h |
+++ b/Source/core/dom/TreeScope.h |
@@ -43,8 +43,9 @@ class HTMLMapElement; |
class HitTestResult; |
class HitTestRequest; |
class IdTargetObserverRegistry; |
-class ScopedStyleResolver; |
class Node; |
+class ScopedStyleResolver; |
+class TreeScopeStyleSheetCollection; |
// A class which inherits both Node and TreeScope must call clearRareData() in its destructor |
// so that the Node destructor no longer does problematic NodeList cache manipulation in |
@@ -141,6 +142,96 @@ public: |
ScopedStyleResolver& ensureScopedStyleResolver(); |
void clearScopedStyleResolver(); |
+ TreeScopeStyleSheetCollection* styleSheetCollection(); |
+ |
+ typedef WillBeHeapHashSet<RawPtrWillBeMember<TreeScope>> UnorderedTreeScopeSet; |
+ |
+ // A class which holds document-ordered treescopes which have stylesheets. |
+ // ListHashSet allows only sequential access, not random access. |
+ // So it gets slow when the size of treescopes gets larger when finding |
+ // the best place to insert a treescope into the document-ordered |
+ // treescopes (requires linear search). |
+ // To solve this, use a vector for the document-ordered treescopes and |
+ // use a hashset for quickly checking whether a given treescope is |
+ // in the document-ordered treescopes or not. |
+ class OrderedTreeScopeSet final { |
+ DISALLOW_ALLOCATION(); |
+ WTF_MAKE_NONCOPYABLE(OrderedTreeScopeSet); |
+ public: |
+ OrderedTreeScopeSet() { } |
+ |
+ bool insert(TreeScope*); |
+ bool remove(TreeScope*); |
+ |
+ // When we don't need to consider document-order, use this iterator. |
+ // Otherwise, use [] operator. |
+ UnorderedTreeScopeSet& unordered() { return m_hash; } |
+ |
+ bool isEmpty() const { return m_treeScopes.isEmpty(); } |
+ void clear() |
+ { |
+ m_treeScopes.clear(); |
+ m_hash.clear(); |
+ } |
+ |
+ size_t size() const { return m_treeScopes.size(); } |
+ |
+ TreeScope* operator[](size_t i) { return m_treeScopes[i]; } |
+ const TreeScope* operator[](size_t i) const { return m_treeScopes[i]; } |
+ |
+ typedef WillBeHeapVector<RawPtrWillBeMember<TreeScope>, 16>::iterator iterator; |
+ iterator begin() { return m_treeScopes.begin(); } |
+ iterator end() { return m_treeScopes.end(); } |
+ |
+ DECLARE_TRACE(); |
+ |
+ private: |
+ WillBeHeapVector<RawPtrWillBeMember<TreeScope>, 16> m_treeScopes; |
+ UnorderedTreeScopeSet m_hash; |
+ }; |
+ |
+ class TreeScopesWithActiveStyleSheetsTraversal final { |
+ DISALLOW_ALLOCATION(); |
+ WTF_MAKE_NONCOPYABLE(TreeScopesWithActiveStyleSheetsTraversal); |
+ public: |
+ TreeScopesWithActiveStyleSheetsTraversal(TreeScope&); |
+ TreeScopesWithActiveStyleSheetsTraversal(OrderedTreeScopeSet&); |
+ |
+ class iterator { |
+ public: |
+ iterator(TreeScopesWithActiveStyleSheetsTraversal* traversal) : m_traversal(traversal) { } |
+ iterator(const iterator& iterator) : m_traversal(iterator.m_traversal) { } |
+ |
+ TreeScope* operator*() { return m_traversal->m_current; } |
+ void operator++() { m_traversal->nextWithStyleSheetCollection(); } |
+ bool operator!=(const iterator& other) const { return m_traversal->m_current; } |
+ |
+ private: |
+ TreeScopesWithActiveStyleSheetsTraversal* m_traversal; |
+ }; |
+ |
+ iterator begin() { return iterator(this); } |
+ iterator end() { return iterator(nullptr); } |
+ |
+ DECLARE_TRACE(); |
+ |
+ private: |
+ void skipIfNoStyleSheetCollection(); |
+ void nextWithStyleSheetCollection(); |
+ void next(); |
+ |
+ RawPtrWillBeMember<TreeScope> m_current; |
+ OrderedTreeScopeSet::iterator m_iterator; |
+ OrderedTreeScopeSet::iterator m_end; |
+ WillBeHeapVector<std::pair<OrderedTreeScopeSet::iterator, OrderedTreeScopeSet::iterator>, 8> m_stack; |
+ }; |
+ |
+ bool selfOrDescendantsHaveActiveStyleSheets() const { return m_selfOrDescendantsHaveActiveStyleSheets; } |
+ OrderedTreeScopeSet& childTreeScopesWithActiveStyleSheets() { return m_childTreeScopesWithActiveStyleSheets; } |
+ bool hasChildTreeScopesWithActiveStyleSheets() const { return !m_childTreeScopesWithActiveStyleSheets.isEmpty(); } |
+ void setSelfOrDescendantsHaveActiveStyleSheets(); |
+ void clearSelfOrDescendantsHaveActiveStyleSheets(); |
+ |
protected: |
TreeScope(ContainerNode&, Document&); |
TreeScope(Document&); |
@@ -191,8 +282,11 @@ private: |
OwnPtrWillBeMember<IdTargetObserverRegistry> m_idTargetObserverRegistry; |
OwnPtrWillBeMember<ScopedStyleResolver> m_scopedStyleResolver; |
+ OrderedTreeScopeSet m_childTreeScopesWithActiveStyleSheets; |
mutable RefPtrWillBeMember<DOMSelection> m_selection; |
+ |
+ bool m_selfOrDescendantsHaveActiveStyleSheets; |
}; |
inline bool TreeScope::hasElementWithId(const AtomicString& id) const |