Add traverseNextSkippingChildren to ElementIterators
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 13 Oct 2013 13:26:07 +0000 (13:26 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 13 Oct 2013 13:26:07 +0000 (13:26 +0000)
https://bugs.webkit.org/show_bug.cgi?id=122727

Reviewed by Andreas Kling.

Also switch some code using ElementTraversal over to iterators.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@157368 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/css/StyleInvalidationAnalysis.cpp
Source/WebCore/dom/ElementIterator.h
Source/WebCore/editing/ReplaceSelectionCommand.cpp
Source/WebCore/svg/SVGUseElement.cpp

index b5f1fa3..5be89d9 100644 (file)
@@ -1,5 +1,14 @@
 2013-10-13  Antti Koivisto  <antti@apple.com>
 
+        Add traverseNextSkippingChildren to ElementIterators
+        https://bugs.webkit.org/show_bug.cgi?id=122727
+
+        Reviewed by Andreas Kling.
+
+        Also switch some code using ElementTraversal over to iterators.
+
+2013-10-13  Antti Koivisto  <antti@apple.com>
+
         Rename InlineBox::remove() to removeFromParent
         https://bugs.webkit.org/show_bug.cgi?id=122725
 
index 5a4e3d6..b566a77 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "CSSSelectorList.h"
 #include "Document.h"
-#include "ElementTraversal.h"
+#include "ElementIterator.h"
 #include "StyleRuleImport.h"
 #include "StyleSheetContents.h"
 #include "StyledElement.h"
@@ -98,13 +98,13 @@ void StyleInvalidationAnalysis::analyzeStyleSheet(StyleSheetContents* styleSheet
     }
 }
 
-static bool elementMatchesSelectorScopes(const Element* element, const HashSet<AtomicStringImpl*>& idScopes, const HashSet<AtomicStringImpl*>& classScopes)
+static bool elementMatchesSelectorScopes(const Element& element, const HashSet<AtomicStringImpl*>& idScopes, const HashSet<AtomicStringImpl*>& classScopes)
 {
-    if (!idScopes.isEmpty() && element->hasID() && idScopes.contains(element->idForStyleResolution().impl()))
+    if (!idScopes.isEmpty() && element.hasID() && idScopes.contains(element.idForStyleResolution().impl()))
         return true;
-    if (classScopes.isEmpty() || !element->hasClass())
+    if (classScopes.isEmpty() || !element.hasClass())
         return false;
-    const SpaceSplitString& classNames = element->classNames();
+    const SpaceSplitString& classNames = element.classNames();
     for (unsigned i = 0; i < classNames.size(); ++i) {
         if (classScopes.contains(classNames[i].impl()))
             return true;
@@ -117,15 +117,17 @@ void StyleInvalidationAnalysis::invalidateStyle(Document* document)
     ASSERT(!m_dirtiesAllStyle);
     if (m_idScopes.isEmpty() && m_classScopes.isEmpty())
         return;
-    Element* element = ElementTraversal::firstWithin(document);
-    while (element) {
-        if (elementMatchesSelectorScopes(element, m_idScopes, m_classScopes)) {
-            element->setNeedsStyleRecalc();
+
+    auto it = elementDescendants(document).begin();
+    auto end = elementDescendants(document).end();
+    while (it != end) {
+        if (elementMatchesSelectorScopes(*it, m_idScopes, m_classScopes)) {
+            it->setNeedsStyleRecalc();
             // The whole subtree is now invalidated, we can skip to the next sibling.
-            element = ElementTraversal::nextSkippingChildren(element);
+            it.traverseNextSkippingChildren();
             continue;
         }
-        element = ElementTraversal::next(element);
+        ++it;
     }
 }
 
index a9dcd0c..47138a1 100644 (file)
@@ -50,6 +50,7 @@ public:
     ElementIterator& traversePrevious();
     ElementIterator& traverseNextSibling();
     ElementIterator& traversePreviousSibling();
+    ElementIterator& traverseNextSkippingChildren();
     ElementIterator& traverseAncestor();
 
 private:
@@ -77,6 +78,7 @@ public:
     ElementConstIterator& traversePrevious();
     ElementConstIterator& traverseNextSibling();
     ElementConstIterator& traversePreviousSibling();
+    ElementConstIterator& traverseNextSkippingChildren();
     ElementConstIterator& traverseAncestor();
 
 private:
@@ -163,6 +165,20 @@ inline ElementIterator<ElementType>& ElementIterator<ElementType>::traversePrevi
     return *this;
 }
 
+template <typename ElementType>
+inline ElementIterator<ElementType>& ElementIterator<ElementType>::traverseNextSkippingChildren()
+{
+    ASSERT(m_current);
+    ASSERT(!m_assertions.domTreeHasMutated());
+    m_current = Traversal<ElementType>::nextSkippingChildren(m_current, m_root);
+#if !ASSERT_DISABLED
+    // Drop the assertion when the iterator reaches the end.
+    if (!m_current)
+        m_assertions.dropEventDispatchAssertion();
+#endif
+    return *this;
+}
+
 template <typename ElementTypeWithConst>
 inline ElementTypeWithConst* findElementAncestorOfType(const Element& current)
 {
@@ -300,6 +316,20 @@ inline ElementConstIterator<ElementType>& ElementConstIterator<ElementType>::tra
 }
 
 template <typename ElementType>
+inline ElementConstIterator<ElementType>& ElementConstIterator<ElementType>::traverseNextSkippingChildren()
+{
+    ASSERT(m_current);
+    ASSERT(!m_assertions.domTreeHasMutated());
+    m_current = Traversal<ElementType>::nextSkippingChildren(m_current, m_root);
+#if !ASSERT_DISABLED
+    // Drop the assertion when the iterator reaches the end.
+    if (!m_current)
+        m_assertions.dropEventDispatchAssertion();
+#endif
+    return *this;
+}
+
+template <typename ElementType>
 inline ElementConstIterator<ElementType>& ElementConstIterator<ElementType>::traverseAncestor()
 {
     ASSERT(m_current);
index f6daad9..0bc2d53 100644 (file)
@@ -36,6 +36,7 @@
 #include "Document.h"
 #include "DocumentFragment.h"
 #include "Element.h"
+#include "ElementIterator.h"
 #include "EventNames.h"
 #include "ExceptionCodePlaceholder.h"
 #include "Frame.h"
@@ -75,6 +76,8 @@ class ReplacementFragment {
 public:
     ReplacementFragment(Document&, DocumentFragment*, const VisibleSelection&);
 
+    DocumentFragment* fragment() { return m_fragment.get(); }
+
     Node* firstChild() const;
     Node* lastChild() const;
 
@@ -704,18 +707,24 @@ VisiblePosition ReplaceSelectionCommand::positionAtStartOfInsertedContent() cons
 
 static void removeHeadContents(ReplacementFragment& fragment)
 {
-    Node* next = 0;
-    for (Node* node = fragment.firstChild(); node; node = next) {
-        if (node->hasTagName(baseTag)
-            || node->hasTagName(linkTag)
-            || node->hasTagName(metaTag)
-            || node->hasTagName(styleTag)
-            || isHTMLTitleElement(node)) {
-            next = NodeTraversal::nextSkippingChildren(node);
-            fragment.removeNode(node);
-        } else
-            next = NodeTraversal::next(node);
+    if (fragment.isEmpty())
+        return;
+
+    Vector<Element*> toRemove;
+
+    auto it = elementDescendants(fragment.fragment()).begin();
+    auto end = elementDescendants(fragment.fragment()).end();
+    while (it != end) {
+        if (it->hasTagName(baseTag) || it->hasTagName(linkTag) || it->hasTagName(metaTag) || it->hasTagName(styleTag) || isHTMLTitleElement(*it)) {
+            toRemove.append(&*it);
+            it.traverseNextSkippingChildren();
+            continue;
+        }
+        ++it;
     }
+
+    for (unsigned i = 0; i < toRemove.size(); ++i)
+        fragment.removeNode(toRemove[i]);
 }
 
 // Remove style spans before insertion if they are unnecessary.  It's faster because we'll 
index e54e1aa..c7115dd 100644 (file)
@@ -663,16 +663,20 @@ bool SVGUseElement::hasCycleUseReferencing(SVGUseElement* use, SVGElementInstanc
 static inline void removeDisallowedElementsFromSubtree(SVGElement& subtree)
 {
     ASSERT(!subtree.inDocument());
-    Element* element = ElementTraversal::firstWithin(&subtree);
-    while (element) {
-        if (isDisallowedElement(*element)) {
-            Element* next = ElementTraversal::nextSkippingChildren(element, &subtree);
-            // The subtree is not in document so this won't generate events that could mutate the tree.
-            element->parentNode()->removeChild(element);
-            element = next;
-        } else
-            element = ElementTraversal::next(element, &subtree);
+    Vector<Element*> toRemove;
+    auto it = elementDescendants(&subtree).begin();
+    auto end = elementDescendants(&subtree).end();
+    while (it != end) {
+        if (isDisallowedElement(*it)) {
+            toRemove.append(&*it);
+            it.traverseNextSkippingChildren();
+            continue;
+        }
+        ++it;
     }
+    // The subtree is not in document so this won't generate events that could mutate the tree.
+    for (unsigned i = 0; i < toRemove.size(); ++i)
+        toRemove[i]->parentNode()->removeChild(toRemove[i]);
 }
 
 void SVGUseElement::buildShadowTree(SVGElement* target, SVGElementInstance* targetInstance)