Index: Source/core/dom/TreeScope.cpp |
diff --git a/Source/core/dom/TreeScope.cpp b/Source/core/dom/TreeScope.cpp |
index 801eafbc6ec8c056517e19f50aa3d1c0749c8d40..339484fbcb05bd9ca8067bfff5294ae7ad005612 100644 |
--- a/Source/core/dom/TreeScope.cpp |
+++ b/Source/core/dom/TreeScope.cpp |
@@ -64,6 +64,7 @@ TreeScope::TreeScope(ContainerNode& rootNode, Document& document) |
, m_guardRefCount(0) |
#endif |
, m_idTargetObserverRegistry(IdTargetObserverRegistry::create()) |
+ , m_selfOrDescendantsHaveActiveStyleSheets(false) |
{ |
ASSERT(rootNode != document); |
#if !ENABLE(OILPAN) |
@@ -80,6 +81,7 @@ TreeScope::TreeScope(Document& document) |
, m_guardRefCount(0) |
#endif |
, m_idTargetObserverRegistry(IdTargetObserverRegistry::create()) |
+ , m_selfOrDescendantsHaveActiveStyleSheets(false) |
{ |
m_rootNode->setTreeScope(this); |
} |
@@ -95,6 +97,9 @@ TreeScope::~TreeScope() |
m_selection = nullptr; |
} |
+ if (m_selfOrDescendantsHaveActiveStyleSheets) |
+ clearSelfOrDescendantsHaveActiveStyleSheets(); |
+ |
if (m_parentTreeScope) |
m_parentTreeScope->guardDeref(); |
#endif |
@@ -137,6 +142,8 @@ void TreeScope::setParentTreeScope(TreeScope& newParentScope) |
// A document node cannot be re-parented. |
ASSERT(!rootNode().isDocumentNode()); |
+ if (m_selfOrDescendantsHaveActiveStyleSheets) |
+ clearSelfOrDescendantsHaveActiveStyleSheets(); |
#if !ENABLE(OILPAN) |
newParentScope.guardRef(); |
if (m_parentTreeScope) |
@@ -568,6 +575,188 @@ void TreeScope::setNeedsStyleRecalcForViewportUnits() |
} |
} |
+TreeScopeStyleSheetCollection* TreeScope::styleSheetCollection() |
+{ |
+ return document().styleEngine().styleSheetCollectionFor(*this); |
+} |
+ |
+bool TreeScope::OrderedTreeScopeSet::insert(TreeScope* treeScope) |
+{ |
+ if (m_treeScopes.isEmpty()) { |
+ m_treeScopes.append(treeScope); |
+ m_hash.add(treeScope); |
+ return true; |
+ } |
+ if (m_hash.contains(treeScope)) |
+ return false; |
+ |
+ int end = m_treeScopes.size() - 1; |
+ int start = 0; |
+ int position = 0; |
+ unsigned result = 0; |
+ |
+ while (start <= end) { |
+ position = (start + end) / 2; |
+ result = m_treeScopes[position]->comparePosition(*treeScope); |
+ |
+ if (result & Node::DOCUMENT_POSITION_PRECEDING) { |
+ end = position - 1; |
+ } else { |
+ ASSERT(result & Node::DOCUMENT_POSITION_FOLLOWING); |
+ start = position + 1; |
+ } |
+ } |
+ |
+ if (result & Node::DOCUMENT_POSITION_FOLLOWING) { |
+ ++position; |
+ ASSERT(static_cast<size_t>(position) == m_treeScopes.size() || (m_treeScopes[position]->comparePosition(*treeScope) & Node::DOCUMENT_POSITION_PRECEDING)); |
+ } |
+ m_treeScopes.insert(position, treeScope); |
+ m_hash.add(treeScope); |
+ |
+#if ENABLE(ASSERT) |
+ // Check whether m_treeScopes is sorted in document order or not. |
+ for (unsigned i = 0; i < m_treeScopes.size() - 1; ++i) { |
+ unsigned result = m_treeScopes[i]->comparePosition(*m_treeScopes[i + 1]); |
+ ASSERT(result & Node::DOCUMENT_POSITION_FOLLOWING); |
+ } |
+#endif |
+ return true; |
+} |
+ |
+bool TreeScope::OrderedTreeScopeSet::remove(TreeScope* treeScope) |
+{ |
+ if (!m_hash.contains(treeScope)) |
+ return false; |
+ size_t position = m_treeScopes.find(treeScope); |
+ m_treeScopes.remove(position); |
+ m_hash.remove(treeScope); |
+ return true; |
+} |
+ |
+DEFINE_TRACE(TreeScope::OrderedTreeScopeSet) |
+{ |
+#if ENABLE(OILPAN) |
+ visitor->trace(m_treeScopes); |
+ visitor->trace(m_hash); |
+#endif |
+} |
+ |
+TreeScope::TreeScopesWithActiveStyleSheetsTraversal::TreeScopesWithActiveStyleSheetsTraversal(TreeScope& treeScope) |
+ : m_current(&treeScope), m_iterator(nullptr), m_end(nullptr) |
+{ |
+ skipIfNoStyleSheetCollection(); |
+} |
+ |
+TreeScope::TreeScopesWithActiveStyleSheetsTraversal::TreeScopesWithActiveStyleSheetsTraversal(OrderedTreeScopeSet& treeScopes) |
+ : m_current(nullptr), m_iterator(treeScopes.begin()), m_end(treeScopes.end()) |
+{ |
+ if (m_iterator != m_end) |
+ m_current = *m_iterator; |
+ skipIfNoStyleSheetCollection(); |
+} |
+ |
+void TreeScope::TreeScopesWithActiveStyleSheetsTraversal::skipIfNoStyleSheetCollection() |
+{ |
+ while (m_current && !m_current->styleSheetCollection()) |
+ next(); |
+} |
+ |
+void TreeScope::TreeScopesWithActiveStyleSheetsTraversal::nextWithStyleSheetCollection() |
+{ |
+ do { |
+ next(); |
+ } while (m_current && !m_current->styleSheetCollection()); |
+} |
+ |
+void TreeScope::TreeScopesWithActiveStyleSheetsTraversal::next() |
+{ |
+ if (!m_current) |
+ return; |
+ |
+ OrderedTreeScopeSet& children = m_current->m_childTreeScopesWithActiveStyleSheets; |
+ if (!children.isEmpty()) { |
+ if (m_iterator) { |
+ ++m_iterator; |
+ if (m_iterator != m_end) |
+ m_stack.append(std::make_pair(m_iterator, m_end)); |
+ } |
+ m_iterator = children.begin(); |
+ m_end = children.end(); |
+ ASSERT(m_iterator != m_end); |
+ m_current = *m_iterator; |
+ return; |
+ } |
+ |
+ if (!m_iterator) { |
+ m_current = nullptr; |
+ return; |
+ } |
+ |
+ ++m_iterator; |
+ if (m_iterator != m_end) { |
+ m_current = *m_iterator; |
+ return; |
+ } |
+ |
+ if (m_stack.isEmpty()) { |
+ m_current = nullptr; |
+ return; |
+ } |
+ |
+ m_iterator = m_stack.last().first; |
+ m_end = m_stack.last().second; |
+ ASSERT(m_iterator != m_end); |
+ m_stack.removeLast(); |
+ m_current = *m_iterator; |
+} |
+ |
+DEFINE_TRACE(TreeScope::TreeScopesWithActiveStyleSheetsTraversal) |
+{ |
+#if ENABLE(OILPAN) |
+ visitor->trace(m_current); |
+ visitor->trace(m_iterator); |
+ visitor->trace(m_end); |
+ visitor->trace(m_stack); |
+#endif |
+} |
+ |
+void TreeScope::setSelfOrDescendantsHaveActiveStyleSheets() |
+{ |
+ ASSERT(this != m_document); |
+ for (TreeScope* treeScope = this;;) { |
+ TreeScope* parent = treeScope->parentTreeScope(); |
+ if (!parent) |
+ break; |
+ parent->m_childTreeScopesWithActiveStyleSheets.insert(treeScope); |
+ treeScope->m_selfOrDescendantsHaveActiveStyleSheets= true; |
+ |
+ // Make sure to include parents so that we can traverse to this from the root treeScope. |
+ treeScope = parent; |
+ if (treeScope->m_selfOrDescendantsHaveActiveStyleSheets) |
+ break; |
+ } |
+} |
+ |
+void TreeScope::clearSelfOrDescendantsHaveActiveStyleSheets() |
+{ |
+ ASSERT(this != m_document); |
+ ASSERT(parentTreeScope()); |
+ ASSERT(m_selfOrDescendantsHaveActiveStyleSheets); |
+ for (TreeScope* treeScope = this;;) { |
+ TreeScope* parent = treeScope->parentTreeScope(); |
+ if (!parent) |
+ break; |
+ parent->m_childTreeScopesWithActiveStyleSheets.remove(treeScope); |
+ treeScope->m_selfOrDescendantsHaveActiveStyleSheets = false; |
+ |
+ // Remove parents if they were included only to traverse to this. |
+ treeScope = parent; |
+ if (!treeScope->m_selfOrDescendantsHaveActiveStyleSheets || !treeScope->m_childTreeScopesWithActiveStyleSheets.isEmpty()) |
+ break; |
+ } |
+} |
+ |
DEFINE_TRACE(TreeScope) |
{ |
visitor->trace(m_rootNode); |
@@ -579,6 +768,7 @@ DEFINE_TRACE(TreeScope) |
visitor->trace(m_imageMapsByName); |
visitor->trace(m_labelsByForAttribute); |
visitor->trace(m_scopedStyleResolver); |
+ visitor->trace(m_childTreeScopesWithActiveStyleSheets); |
} |
} // namespace blink |