Add Element-specific traversal functions
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 12 Dec 2012 03:12:23 +0000 (03:12 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 12 Dec 2012 03:12:23 +0000 (03:12 +0000)
https://bugs.webkit.org/show_bug.cgi?id=104685

Reviewed by Ryosuke Niwa.

In many cases where we use NodeTraversal we really only want Elements. By having
Element specific iteration functions we can tighten the code and make it faster too.

This patch adds ElementTraversal namespace, similar to NodeTraversal. It also switches
bunch of NodeTraversal call sites that obviously only care about elements to using
the new interface.

This should be a speedup too as we avoid number of branches by not having to look
for children of non-ContainerNodes and by allowing use of ContainerNode specific
accessors.

* accessibility/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::addImageMapChildren):
* css/SelectorChecker.cpp:
(WebCore::linkAttribute):
(WebCore::SelectorChecker::allVisitedStateChanged):
(WebCore::SelectorChecker::visitedStateChanged):
* css/StyleInvalidationAnalysis.cpp:
(WebCore::elementMatchesSelectorScopes):
(WebCore::StyleInvalidationAnalysis::invalidateStyle):
* dom/ContainerNodeAlgorithms.h:
(WebCore::ChildFrameDisconnector::collectDescendant):
* dom/Document.cpp:
(WebCore::Document::buildAccessKeyMap):
(WebCore::Document::updateBaseURL):
(WebCore::Document::processBaseElement):
* dom/DocumentOrderedMap.cpp:
(WebCore::DocumentOrderedMap::get):
* dom/Element.cpp:
(WebCore::Element::firstElementChild):
* dom/Element.h:
(WebCore):
* dom/ElementShadow.cpp:
(WebCore::ElementShadow::collectSelectFeatureSetFrom):
* dom/NodeTraversal.h:
(ElementTraversal):
(WebCore):
(WebCore::ElementTraversal::traverseNextElementTemplate):
(WebCore::ElementTraversal::next):
(WebCore::ElementTraversal::firstWithin):
(WebCore::ElementTraversal::traverseNextElementSkippingChildrenTemplate):
(WebCore::ElementTraversal::nextSkippingChildren):
(NodeTraversal):
* dom/TreeScope.cpp:
(WebCore::TreeScope::labelElementForId):
(WebCore::TreeScope::findAnchor):
* editing/CompositeEditCommand.cpp:
(WebCore::CompositeEditCommand::cloneParagraphUnderNewElement):
* editing/DeleteSelectionCommand.cpp:
(WebCore::DeleteSelectionCommand::handleGeneralDelete):
* editing/FrameSelection.cpp:
(WebCore::scanForForm):
* editing/markup.cpp:
(WebCore::completeURLs):
* html/HTMLFieldSetElement.cpp:
(WebCore::HTMLFieldSetElement::invalidateDisabledStateUnder):
(WebCore::HTMLFieldSetElement::childrenChanged):
(WebCore::HTMLFieldSetElement::legend):
(WebCore::HTMLFieldSetElement::refreshElementsIfNeeded):
* html/HTMLFormElement.cpp:
(WebCore::HTMLFormElement::formElementIndex):
* html/HTMLLabelElement.cpp:
(WebCore::HTMLLabelElement::control):
* html/HTMLLegendElement.cpp:
(WebCore::HTMLLegendElement::associatedControl):
* html/HTMLMapElement.cpp:
(WebCore::HTMLMapElement::mapMouseEvent):
* html/HTMLNameCollection.cpp:
(WebCore::HTMLNameCollection::virtualItemAfter):
* html/HTMLObjectElement.cpp:
(WebCore::HTMLObjectElement::containsJavaApplet):
* html/HTMLSelectElement.cpp:
(WebCore::HTMLSelectElement::recalcListItems):
* html/shadow/ContentDistributor.cpp:
(WebCore::ShadowRootContentDistributionData::ensureInsertionPointList):
* page/FocusController.cpp:
(WebCore::FocusController::findFocusCandidateInContainer):
* rendering/RenderCounter.cpp:
(WebCore::nextInPreOrder):
* svg/SVGSVGElement.cpp:
(WebCore::SVGSVGElement::collectIntersectionOrEnclosureList):
* svg/SVGStyledElement.cpp:
(WebCore::SVGStyledElement::title):
* svg/SVGUseElement.cpp:
(WebCore::removeDisallowedElementsFromSubtree):
* svg/animation/SMILTimeContainer.cpp:
(WebCore::SMILTimeContainer::updateDocumentOrderIndexes):

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

32 files changed:
Source/WebCore/ChangeLog
Source/WebCore/accessibility/AccessibilityRenderObject.cpp
Source/WebCore/css/SelectorChecker.cpp
Source/WebCore/css/StyleInvalidationAnalysis.cpp
Source/WebCore/dom/ContainerNodeAlgorithms.h
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/DocumentOrderedMap.cpp
Source/WebCore/dom/Element.cpp
Source/WebCore/dom/Element.h
Source/WebCore/dom/ElementShadow.cpp
Source/WebCore/dom/NodeTraversal.h
Source/WebCore/dom/TreeScope.cpp
Source/WebCore/editing/CompositeEditCommand.cpp
Source/WebCore/editing/DeleteSelectionCommand.cpp
Source/WebCore/editing/FrameSelection.cpp
Source/WebCore/editing/markup.cpp
Source/WebCore/html/BaseMultipleFieldsDateAndTimeInputType.cpp
Source/WebCore/html/HTMLFieldSetElement.cpp
Source/WebCore/html/HTMLFormElement.cpp
Source/WebCore/html/HTMLLabelElement.cpp
Source/WebCore/html/HTMLLegendElement.cpp
Source/WebCore/html/HTMLMapElement.cpp
Source/WebCore/html/HTMLNameCollection.cpp
Source/WebCore/html/HTMLObjectElement.cpp
Source/WebCore/html/HTMLSelectElement.cpp
Source/WebCore/html/shadow/ContentDistributor.cpp
Source/WebCore/page/FocusController.cpp
Source/WebCore/rendering/RenderCounter.cpp
Source/WebCore/svg/SVGSVGElement.cpp
Source/WebCore/svg/SVGStyledElement.cpp
Source/WebCore/svg/SVGUseElement.cpp
Source/WebCore/svg/animation/SMILTimeContainer.cpp

index 78bbc9f..8d12cf9 100644 (file)
@@ -1,3 +1,98 @@
+2012-12-11  Antti Koivisto  <antti@apple.com>
+
+        Add Element-specific traversal functions
+        https://bugs.webkit.org/show_bug.cgi?id=104685
+
+        Reviewed by Ryosuke Niwa.
+
+        In many cases where we use NodeTraversal we really only want Elements. By having
+        Element specific iteration functions we can tighten the code and make it faster too.
+
+        This patch adds ElementTraversal namespace, similar to NodeTraversal. It also switches
+        bunch of NodeTraversal call sites that obviously only care about elements to using
+        the new interface.
+        
+        This should be a speedup too as we avoid number of branches by not having to look
+        for children of non-ContainerNodes and by allowing use of ContainerNode specific
+        accessors.
+
+        * accessibility/AccessibilityRenderObject.cpp:
+        (WebCore::AccessibilityRenderObject::addImageMapChildren):
+        * css/SelectorChecker.cpp:
+        (WebCore::linkAttribute):
+        (WebCore::SelectorChecker::allVisitedStateChanged):
+        (WebCore::SelectorChecker::visitedStateChanged):
+        * css/StyleInvalidationAnalysis.cpp:
+        (WebCore::elementMatchesSelectorScopes):
+        (WebCore::StyleInvalidationAnalysis::invalidateStyle):
+        * dom/ContainerNodeAlgorithms.h:
+        (WebCore::ChildFrameDisconnector::collectDescendant):
+        * dom/Document.cpp:
+        (WebCore::Document::buildAccessKeyMap):
+        (WebCore::Document::updateBaseURL):
+        (WebCore::Document::processBaseElement):
+        * dom/DocumentOrderedMap.cpp:
+        (WebCore::DocumentOrderedMap::get):
+        * dom/Element.cpp:
+        (WebCore::Element::firstElementChild):
+        * dom/Element.h:
+        (WebCore):
+        * dom/ElementShadow.cpp:
+        (WebCore::ElementShadow::collectSelectFeatureSetFrom):
+        * dom/NodeTraversal.h:
+        (ElementTraversal):
+        (WebCore):
+        (WebCore::ElementTraversal::traverseNextElementTemplate):
+        (WebCore::ElementTraversal::next):
+        (WebCore::ElementTraversal::firstWithin):
+        (WebCore::ElementTraversal::traverseNextElementSkippingChildrenTemplate):
+        (WebCore::ElementTraversal::nextSkippingChildren):
+        (NodeTraversal):
+        * dom/TreeScope.cpp:
+        (WebCore::TreeScope::labelElementForId):
+        (WebCore::TreeScope::findAnchor):
+        * editing/CompositeEditCommand.cpp:
+        (WebCore::CompositeEditCommand::cloneParagraphUnderNewElement):
+        * editing/DeleteSelectionCommand.cpp:
+        (WebCore::DeleteSelectionCommand::handleGeneralDelete):
+        * editing/FrameSelection.cpp:
+        (WebCore::scanForForm):
+        * editing/markup.cpp:
+        (WebCore::completeURLs):
+        * html/HTMLFieldSetElement.cpp:
+        (WebCore::HTMLFieldSetElement::invalidateDisabledStateUnder):
+        (WebCore::HTMLFieldSetElement::childrenChanged):
+        (WebCore::HTMLFieldSetElement::legend):
+        (WebCore::HTMLFieldSetElement::refreshElementsIfNeeded):
+        * html/HTMLFormElement.cpp:
+        (WebCore::HTMLFormElement::formElementIndex):
+        * html/HTMLLabelElement.cpp:
+        (WebCore::HTMLLabelElement::control):
+        * html/HTMLLegendElement.cpp:
+        (WebCore::HTMLLegendElement::associatedControl):
+        * html/HTMLMapElement.cpp:
+        (WebCore::HTMLMapElement::mapMouseEvent):
+        * html/HTMLNameCollection.cpp:
+        (WebCore::HTMLNameCollection::virtualItemAfter):
+        * html/HTMLObjectElement.cpp:
+        (WebCore::HTMLObjectElement::containsJavaApplet):
+        * html/HTMLSelectElement.cpp:
+        (WebCore::HTMLSelectElement::recalcListItems):
+        * html/shadow/ContentDistributor.cpp:
+        (WebCore::ShadowRootContentDistributionData::ensureInsertionPointList):
+        * page/FocusController.cpp:
+        (WebCore::FocusController::findFocusCandidateInContainer):
+        * rendering/RenderCounter.cpp:
+        (WebCore::nextInPreOrder):
+        * svg/SVGSVGElement.cpp:
+        (WebCore::SVGSVGElement::collectIntersectionOrEnclosureList):
+        * svg/SVGStyledElement.cpp:
+        (WebCore::SVGStyledElement::title):
+        * svg/SVGUseElement.cpp:
+        (WebCore::removeDisallowedElementsFromSubtree):
+        * svg/animation/SMILTimeContainer.cpp:
+        (WebCore::SMILTimeContainer::updateDocumentOrderIndexes):
+
 2012-12-11  KyungTae Kim  <ktf.kim@samsung.com>
 
         [soup] Unused parameter in ResourceHandleSoup.cpp
index 8d5149a..e0e0847 100644 (file)
@@ -2657,8 +2657,7 @@ void AccessibilityRenderObject::addImageMapChildren()
     if (!map)
         return;
 
-    for (Node* current = map->firstChild(); current; current = NodeTraversal::next(current, map)) {
-        
+    for (Element* current = ElementTraversal::firstWithin(map); current; current = ElementTraversal::next(current, map)) {
         // add an <area> element for this child if it has a link
         if (current->hasTagName(areaTag) && current->isLink()) {
             AccessibilityImageMapLink* areaObject = static_cast<AccessibilityImageMapLink*>(axObjectCache()->getOrCreate(ImageMapLinkRole));
index 0c14198..a5305e3 100644 (file)
@@ -207,18 +207,14 @@ void SelectorChecker::collectIdentifierHashes(const CSSSelector* selector, unsig
     *hash = 0;
 }
 
-static inline const AtomicString* linkAttribute(Node* node)
+static inline const AtomicString* linkAttribute(Element* element)
 {
-    if (!node->isLink())
+    if (!element->isLink())
         return 0;
-
-    ASSERT(node->isElementNode());
-    Element* element = static_cast<Element*>(node);
     if (element->isHTMLElement())
         return &element->fastGetAttribute(hrefAttr);
     if (element->isSVGElement())
         return &element->getAttribute(XLinkNames::hrefAttr);
-
     return 0;
 }
 
@@ -1225,9 +1221,9 @@ void SelectorChecker::allVisitedStateChanged()
 {
     if (m_linksCheckedForVisitedState.isEmpty())
         return;
-    for (Node* node = m_document; node; node = NodeTraversal::next(node)) {
-        if (node->isLink())
-            node->setNeedsStyleRecalc();
+    for (Element* element = ElementTraversal::firstWithin(m_document); element; element = ElementTraversal::next(element)) {
+        if (element->isLink())
+            element->setNeedsStyleRecalc();
     }
 }
 
@@ -1235,14 +1231,14 @@ void SelectorChecker::visitedStateChanged(LinkHash visitedHash)
 {
     if (!m_linksCheckedForVisitedState.contains(visitedHash))
         return;
-    for (Node* node = m_document; node; node = NodeTraversal::next(node)) {
+    for (Element* element = ElementTraversal::firstWithin(m_document); element; element = ElementTraversal::next(element)) {
         LinkHash hash = 0;
-        if (node->hasTagName(aTag))
-            hash = static_cast<HTMLAnchorElement*>(node)->visitedLinkHash();
-        else if (const AtomicString* attr = linkAttribute(node))
+        if (element->hasTagName(aTag))
+            hash = static_cast<HTMLAnchorElement*>(element)->visitedLinkHash();
+        else if (const AtomicString* attr = linkAttribute(element))
             hash = visitedLinkHash(m_document->baseURL(), *attr);
         if (hash == visitedHash)
-            node->setNeedsStyleRecalc();
+            element->setNeedsStyleRecalc();
     }
 }
 
index b7c5983..6cdd595 100644 (file)
@@ -98,7 +98,7 @@ void StyleInvalidationAnalysis::analyzeStyleSheet(StyleSheetContents* styleSheet
     }
 }
 
-static bool elementMatchesSelectorScopes(const StyledElement* 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()))
         return true;
@@ -117,20 +117,15 @@ void StyleInvalidationAnalysis::invalidateStyle(Document* document)
     ASSERT(!m_dirtiesAllStyle);
     if (m_idScopes.isEmpty() && m_classScopes.isEmpty())
         return;
-    Node* node = document->firstChild();
-    while (node) {
-        if (!node->isStyledElement()) {
-            node = NodeTraversal::next(node);
-            continue;
-        }
-        StyledElement* element = static_cast<StyledElement*>(node);
+    Element* element = ElementTraversal::firstWithin(document);
+    while (element) {
         if (elementMatchesSelectorScopes(element, m_idScopes, m_classScopes)) {
             element->setNeedsStyleRecalc();
             // The whole subtree is now invalidated, we can skip to the next sibling.
-            node = NodeTraversal::nextSkippingChildren(node);
+            element = ElementTraversal::nextSkippingChildren(element);
             continue;
         }
-        node = NodeTraversal::next(node);
+        element = ElementTraversal::next(element);
     }
 }
 
index e99f645..ddb400f 100644 (file)
@@ -316,10 +316,8 @@ private:
 
 inline void ChildFrameDisconnector::collectDescendant(Node* root, ShouldIncludeRoot shouldIncludeRoot)
 {
-    for (Node* node = shouldIncludeRoot == IncludeRoot ? root : root->firstChild(); node; node = NodeTraversal::next(node, root)) {
-        if (!node->isElementNode())
-            continue;
-        Element* element = toElement(node);
+    Element* element = (shouldIncludeRoot == IncludeRoot && root->isElementNode()) ? toElement(root) : ElementTraversal::firstWithin(root);
+    for (; element; element = ElementTraversal::next(element, root)) {
         if (element->hasCustomCallbacks() && element->isFrameOwnerElement())
             m_list.append(toFrameOwnerElement(element));
         if (ElementShadow* shadow = element->shadow())
index 7e55754..154c232 100644 (file)
@@ -750,15 +750,12 @@ void Document::buildAccessKeyMap(TreeScope* scope)
 {
     ASSERT(scope);
     Node* rootNode = scope->rootNode();
-    for (Node* node = rootNode; node; node = NodeTraversal::next(node, rootNode)) {
-        if (!node->isElementNode())
-            continue;
-        Element* element = static_cast<Element*>(node);
+    for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) {
         const AtomicString& accessKey = element->getAttribute(accesskeyAttr);
         if (!accessKey.isEmpty())
             m_elementsByAccessKey.set(accessKey.impl(), element);
 
-        for (ShadowRoot* root = node->youngestShadowRoot(); root; root = root->olderShadowRoot())
+        for (ShadowRoot* root = element->youngestShadowRoot(); root; root = root->olderShadowRoot())
             buildAccessKeyMap(root);
     }
 }
@@ -844,7 +841,7 @@ void Document::childrenChanged(bool changedByParser, Node* beforeChange, Node* a
 {
     ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
     
-    Element* newDocumentElement = firstElementChild(this);
+    Element* newDocumentElement = ElementTraversal::firstWithin(this);
     if (newDocumentElement == m_documentElement)
         return;
     m_documentElement = newDocumentElement;
@@ -2667,9 +2664,9 @@ void Document::updateBaseURL()
     if (!equalIgnoringFragmentIdentifier(oldBaseURL, m_baseURL)) {
         // Base URL change changes any relative visited links.
         // FIXME: There are other URLs in the tree that would need to be re-evaluated on dynamic base URL change. Style should be invalidated too.
-        for (Node* node = firstChild(); node; node = NodeTraversal::next(node)) {
-            if (node->hasTagName(aTag))
-                static_cast<HTMLAnchorElement*>(node)->invalidateCachedVisitedLinkHash();
+        for (Element* element = ElementTraversal::firstWithin(this); element; element = ElementTraversal::next(element)) {
+            if (element->hasTagName(aTag))
+                static_cast<HTMLAnchorElement*>(element)->invalidateCachedVisitedLinkHash();
         }
     }
 }
@@ -2685,15 +2682,15 @@ void Document::processBaseElement()
     // Find the first href attribute in a base element and the first target attribute in a base element.
     const AtomicString* href = 0;
     const AtomicString* target = 0;
-    for (Node* node = document()->firstChild(); node && (!href || !target); node = NodeTraversal::next(node)) {
-        if (node->hasTagName(baseTag)) {
+    for (Element* element = ElementTraversal::firstWithin(this); element && (!href || !target); element = ElementTraversal::next(element)) {
+        if (element->hasTagName(baseTag)) {
             if (!href) {
-                const AtomicString& value = static_cast<Element*>(node)->fastGetAttribute(hrefAttr);
+                const AtomicString& value = element->fastGetAttribute(hrefAttr);
                 if (!value.isNull())
                     href = &value;
             }
             if (!target) {
-                const AtomicString& value = static_cast<Element*>(node)->fastGetAttribute(targetAttr);
+                const AtomicString& value = element->fastGetAttribute(targetAttr);
                 if (!value.isNull())
                     target = &value;
             }
index 5c4af42..a36b76d 100644 (file)
@@ -127,10 +127,7 @@ inline Element* DocumentOrderedMap::get(AtomicStringImpl* key, const TreeScope*
 
     if (m_duplicateCounts.contains(key)) {
         // We know there's at least one node that matches; iterate to find the first one.
-        for (Node* node = scope->rootNode()->firstChild(); node; node = NodeTraversal::next(node)) {
-            if (!node->isElementNode())
-                continue;
-            element = static_cast<Element*>(node);
+        for (element = ElementTraversal::firstWithin(scope->rootNode()); element; element = ElementTraversal::next(element)) {
             if (!keyMatches(key, element))
                 continue;
             m_duplicateCounts.remove(key);
index 35bbe53..888247c 100644 (file)
@@ -62,6 +62,7 @@
 #include "NodeList.h"
 #include "NodeRenderStyle.h"
 #include "NodeRenderingContext.h"
+#include "NodeTraversal.h"
 #include "Page.h"
 #include "PointerLockController.h"
 #include "PseudoElement.h"
@@ -2145,7 +2146,7 @@ PseudoElement* Element::afterPseudoElement() const
 // ElementTraversal API
 Element* Element::firstElementChild() const
 {
-    return WebCore::firstElementChild(this);
+    return ElementTraversal::firstWithin(this);
 }
 
 Element* Element::lastElementChild() const
index 62ebb55..9b63251 100644 (file)
@@ -797,15 +797,6 @@ inline void Element::updateInvalidAttributes() const
 #endif
 }
 
-inline Element* firstElementChild(const ContainerNode* container)
-{
-    ASSERT_ARG(container, container);
-    Node* child = container->firstChild();
-    while (child && !child->isElementNode())
-        child = child->nextSibling();
-    return static_cast<Element*>(child);
-}
-
 inline bool Element::hasID() const
 {
     return attributeData() && attributeData()->hasID();
index 1497fd0..9dbe684 100644 (file)
@@ -221,8 +221,8 @@ void ElementShadow::ensureSelectFeatureSetCollected()
 void ElementShadow::collectSelectFeatureSetFrom(ShadowRoot* root)
 {
     if (root->hasElementShadow()) {
-        for (Node* node = root->firstChild(); node; node = NodeTraversal::next(node)) {
-            if (ElementShadow* elementShadow = node->isElementNode() ? toElement(node)->shadow() : 0) {
+        for (Element* element = ElementTraversal::firstWithin(root); element; element = ElementTraversal::next(element)) {
+            if (ElementShadow* elementShadow = element->shadow()) {
                 elementShadow->ensureSelectFeatureSetCollected();
                 m_selectFeatures.add(elementShadow->m_selectFeatures);
             }
@@ -230,9 +230,9 @@ void ElementShadow::collectSelectFeatureSetFrom(ShadowRoot* root)
     }
 
     if (root->hasContentElement()) {
-        for (Node* node = root->firstChild(); node; node = NodeTraversal::next(node)) {
-            if (isHTMLContentElement(node)) {
-                const CSSSelectorList& list = toHTMLContentElement(node)->selectorList();
+        for (Element* element = ElementTraversal::firstWithin(root); element; element = ElementTraversal::next(element)) {
+            if (isHTMLContentElement(element)) {
+                const CSSSelectorList& list = toHTMLContentElement(element)->selectorList();
                 for (CSSSelector* selector = list.first(); selector; selector = list.next(selector))
                     m_selectFeatures.collectFeaturesFromSelector(selector);                    
             }
index 06a2a9c..7a3ca0e 100644 (file)
 #ifndef NodeTraversal_h
 #define NodeTraversal_h
 
+#include "Element.h"
+
 namespace WebCore {
 
-class Node;
-class ContainerNode;
+namespace ElementTraversal {
+
+// First element child of the node.
+Element* firstWithin(const Node*);
+Element* firstWithin(const ContainerNode*);
+// Pre-order traversal skipping non-element nodes.
+Element* next(const Node*);
+Element* next(const Node*, const Node* stayWithin);
+Element* next(const ContainerNode*);
+Element* next(const ContainerNode*, const Node* stayWithin);
+// Like next, but skips children.
+Element* nextSkippingChildren(const Node*);
+Element* nextSkippingChildren(const Node*, const Node* stayWithin);
+Element* nextSkippingChildren(const ContainerNode*);
+Element* nextSkippingChildren(const ContainerNode*, const Node* stayWithin);
+
+}
 
 namespace NodeTraversal {
 
@@ -60,6 +77,68 @@ Node* nextPostOrder(const Node*, const Node* stayWithin = 0);
 Node* previousPostOrder(const Node*, const Node* stayWithin = 0);
 Node* previousSkippingChildrenPostOrder(const Node*, const Node* stayWithin = 0);
 
+}
+
+namespace ElementTraversal {
+template <class NodeType>
+inline Element* firstElementWithinTemplate(NodeType* current)
+{
+    // Except for the root containers, only elements can have element children.
+    Node* node = current->firstChild();
+    while (node && !node->isElementNode())
+        node = node->nextSibling();
+    return toElement(node);
+}
+inline Element* firstWithin(const ContainerNode* current) { return firstElementWithinTemplate(current); }
+inline Element* firstWithin(const Node* current) { return firstElementWithinTemplate(current); }
+
+template <class NodeType>
+inline Element* traverseNextElementTemplate(NodeType* current)
+{
+    Node* node = NodeTraversal::next(current);
+    while (node && !node->isElementNode())
+        node = NodeTraversal::nextSkippingChildren(node);
+    return toElement(node);
+}
+inline Element* next(const ContainerNode* current) { return traverseNextElementTemplate(current); }
+inline Element* next(const Node* current) { return traverseNextElementTemplate(current); }
+
+template <class NodeType>
+inline Element* traverseNextElementTemplate(NodeType* current, const Node* stayWithin)
+{
+    Node* node = NodeTraversal::next(current, stayWithin);
+    while (node && !node->isElementNode())
+        node = NodeTraversal::nextSkippingChildren(node, stayWithin);
+    return toElement(node);
+}
+inline Element* next(const ContainerNode* current, const Node* stayWithin) { return traverseNextElementTemplate(current, stayWithin); }
+inline Element* next(const Node* current, const Node* stayWithin) { return traverseNextElementTemplate(current, stayWithin); }
+
+template <class NodeType>
+inline Element* traverseNextElementSkippingChildrenTemplate(NodeType* current)
+{
+    Node* node = NodeTraversal::nextSkippingChildren(current);
+    while (node && !node->isElementNode())
+        node = NodeTraversal::nextSkippingChildren(node);
+    return toElement(node);
+}
+inline Element* nextSkippingChildren(const ContainerNode* current) { return traverseNextElementSkippingChildrenTemplate(current); }
+inline Element* nextSkippingChildren(const Node* current) { return traverseNextElementSkippingChildrenTemplate(current); }
+
+template <class NodeType>
+inline Element* traverseNextElementSkippingChildrenTemplate(NodeType* current, const Node* stayWithin)
+{
+    Node* node = NodeTraversal::nextSkippingChildren(current, stayWithin);
+    while (node && !node->isElementNode())
+        node = NodeTraversal::nextSkippingChildren(node, stayWithin);
+    return toElement(node);
+}
+inline Element* nextSkippingChildren(const ContainerNode* current, const Node* stayWithin) { return traverseNextElementSkippingChildrenTemplate(current, stayWithin); }
+inline Element* nextSkippingChildren(const Node* current, const Node* stayWithin) { return traverseNextElementSkippingChildrenTemplate(current, stayWithin); }
+}
+
+namespace NodeTraversal {
+
 Node* nextAncestorSibling(const Node*);
 Node* nextAncestorSibling(const Node*, const Node* stayWithin);
 
index bcb7223..fe19a0f 100644 (file)
@@ -187,9 +187,9 @@ HTMLLabelElement* TreeScope::labelElementForId(const AtomicString& forAttributeV
     if (!m_labelsByForAttribute) {
         // Populate the map on first access.
         m_labelsByForAttribute = adoptPtr(new DocumentOrderedMap);
-        for (Node* node = rootNode(); node; node = NodeTraversal::next(node)) {
-            if (node->hasTagName(labelTag)) {
-                HTMLLabelElement* label = static_cast<HTMLLabelElement*>(node);
+        for (Element* element = ElementTraversal::firstWithin(rootNode()); element; element = ElementTraversal::next(element)) {
+            if (element->hasTagName(labelTag)) {
+                HTMLLabelElement* label = static_cast<HTMLLabelElement*>(element);
                 const AtomicString& forValue = label->fastGetAttribute(forAttr);
                 if (!forValue.isEmpty())
                     addLabel(forValue, label);
@@ -231,9 +231,9 @@ Element* TreeScope::findAnchor(const String& name)
         return 0;
     if (Element* element = getElementById(name))
         return element;
-    for (Node* node = rootNode(); node; node = NodeTraversal::next(node)) {
-        if (node->hasTagName(aTag)) {
-            HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(node);
+    for (Element* element = ElementTraversal::firstWithin(rootNode()); element; element = ElementTraversal::next(element)) {
+        if (element->hasTagName(aTag)) {
+            HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(element);
             if (rootNode()->document()->inQuirksMode()) {
                 // Quirks mode, case insensitive comparison of names.
                 if (equalIgnoringCase(anchor->name(), name))
index 6059de6..a199545 100644 (file)
@@ -1025,7 +1025,7 @@ void CompositeEditCommand::cloneParagraphUnderNewElement(Position& start, Positi
         Node* startNode = start.deprecatedNode();
         for (Node* node = NodeTraversal::nextSkippingChildren(startNode, outerNode.get()); node; node = NodeTraversal::nextSkippingChildren(node, outerNode.get())) {
             // Move lastNode up in the tree as much as node was moved up in the
-            // tree by NodeTraversal::nextSibling, so that the relative depth between
+            // tree by NodeTraversal::nextSkippingChildren, so that the relative depth between
             // node and the original start node is maintained in the clone.
             while (startNode->parentNode() != node->parentNode()) {
                 startNode = startNode->parentNode();
index ee47b57..b0e4b32 100644 (file)
@@ -504,7 +504,7 @@ void DeleteSelectionCommand::handleGeneralDelete()
         // handle deleting all nodes that are completely selected
         while (node && node != m_downstreamEnd.deprecatedNode()) {
             if (comparePositions(firstPositionInOrBeforeNode(node.get()), m_downstreamEnd) >= 0) {
-                // NodeTraversal::nextSibling just blew past the end position, so stop deleting
+                // NodeTraversal::nextSkippingChildren just blew past the end position, so stop deleting
                 node = 0;
             } else if (!m_downstreamEnd.deprecatedNode()->isDescendantOf(node.get())) {
                 RefPtr<Node> nextNode = NodeTraversal::nextSkippingChildren(node.get());
index afb8fee..af9c28b 100644 (file)
@@ -1953,13 +1953,14 @@ void FrameSelection::getClippedVisibleTextRectangles(Vector<FloatRect>& rectangl
 // Scans logically forward from "start", including any child frames.
 static HTMLFormElement* scanForForm(Node* start)
 {
-    for (Node* node = start; node; node = NodeTraversal::next(node)) {
-        if (node->hasTagName(formTag))
-            return static_cast<HTMLFormElement*>(node);
-        if (node->isHTMLElement() && toHTMLElement(node)->isFormControlElement())
-            return static_cast<HTMLFormControlElement*>(node)->form();
-        if (node->hasTagName(frameTag) || node->hasTagName(iframeTag)) {
-            Node* childDocument = static_cast<HTMLFrameElementBase*>(node)->contentDocument();
+    Element* element = start && start->isElementNode() ? toElement(start) : ElementTraversal::next(start);
+    for (; element; element = ElementTraversal::next(element)) {
+        if (element->hasTagName(formTag))
+            return static_cast<HTMLFormElement*>(element);
+        if (element->isHTMLElement() && toHTMLElement(element)->isFormControlElement())
+            return static_cast<HTMLFormControlElement*>(element)->form();
+        if (element->hasTagName(frameTag) || element->hasTagName(iframeTag)) {
+            Node* childDocument = static_cast<HTMLFrameElementBase*>(element)->contentDocument();
             if (HTMLFormElement* frameResult = scanForForm(childDocument))
                 return frameResult;
         }
index 160eaae..63abb5f 100644 (file)
@@ -96,24 +96,20 @@ private:
     String m_value;
 };
 
-static void completeURLs(Node* node, const String& baseURL)
+static void completeURLs(DocumentFragment* fragment, const String& baseURL)
 {
     Vector<AttributeChange> changes;
 
     KURL parsedBaseURL(ParsedURLString, baseURL);
 
-    Node* end = NodeTraversal::nextSkippingChildren(node);
-    for (Node* n = node; n != end; n = NodeTraversal::next(n)) {
-        if (n->isElementNode()) {
-            Element* e = static_cast<Element*>(n);
-            if (!e->hasAttributes())
-                continue;
-            unsigned length = e->attributeCount();
-            for (unsigned i = 0; i < length; i++) {
-                const Attribute* attribute = e->attributeItem(i);
-                if (e->isURLAttribute(*attribute) && !attribute->value().isEmpty())
-                    changes.append(AttributeChange(e, attribute->name(), KURL(parsedBaseURL, attribute->value()).string()));
-            }
+    for (Element* element = ElementTraversal::firstWithin(fragment); element; element = ElementTraversal::next(element, fragment)) {
+        if (!element->hasAttributes())
+            continue;
+        unsigned length = element->attributeCount();
+        for (unsigned i = 0; i < length; i++) {
+            const Attribute* attribute = element->attributeItem(i);
+            if (element->isURLAttribute(*attribute) && !attribute->value().isEmpty())
+                changes.append(AttributeChange(element, attribute->name(), KURL(parsedBaseURL, attribute->value()).string()));
         }
     }
 
index 723b38e..3b1df22 100644 (file)
@@ -42,6 +42,7 @@
 #include "HTMLOptionElement.h"
 #include "KeyboardEvent.h"
 #include "LocalizedStrings.h"
+#include "NodeTraversal.h"
 #include "Page.h"
 #include "PickerIndicatorElement.h"
 #include "PlatformLocale.h"
@@ -358,7 +359,7 @@ void BaseMultipleFieldsDateAndTimeInputType::updateInnerTextValue()
         return;
 
     AtomicString direction = element()->locale().isRTL() ? AtomicString("rtl", AtomicString::ConstructFromLiteral) : AtomicString("ltr", AtomicString::ConstructFromLiteral);
-    if (Element* container = firstElementChild(element()->userAgentShadowRoot()))
+    if (Element* container = ElementTraversal::firstWithin(element()->userAgentShadowRoot()))
         container->setAttribute(HTMLNames::dirAttr, direction);
 
     DateTimeEditElement::LayoutParameters layoutParameters(element()->locale(), createStepRange(AnyIsDefaultStep));
index ce553be..717905f 100644 (file)
@@ -51,9 +51,9 @@ PassRefPtr<HTMLFieldSetElement> HTMLFieldSetElement::create(const QualifiedName&
 
 void HTMLFieldSetElement::invalidateDisabledStateUnder(Element* base)
 {
-    for (Node* node = base->firstChild(); node; node = NodeTraversal::next(node, base)) {
-        if (node->isElementNode() && toElement(node)->isFormControlElement())
-            static_cast<HTMLFormControlElement*>(node)->ancestorDisabledStateWasChanged();
+    for (Element* element = ElementTraversal::firstWithin(base); element; element = ElementTraversal::next(element, base)) {
+        if (element->isFormControlElement())
+            static_cast<HTMLFormControlElement*>(element)->ancestorDisabledStateWasChanged();
     }
 }
 
@@ -67,7 +67,7 @@ void HTMLFieldSetElement::disabledAttributeChanged()
 void HTMLFieldSetElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
 {
     HTMLFormControlElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
-    for (Element* element = firstElementChild(); element; element = element->nextElementSibling()) {
+    for (Element* element = ElementTraversal::firstWithin(this); element; element = ElementTraversal::nextSkippingChildren(element, this)) {
         if (element->hasTagName(legendTag))
             invalidateDisabledStateUnder(element);
     }
@@ -91,9 +91,9 @@ RenderObject* HTMLFieldSetElement::createRenderer(RenderArena* arena, RenderStyl
 
 HTMLLegendElement* HTMLFieldSetElement::legend() const
 {
-    for (Element* node = firstElementChild(); node; node = node->nextElementSibling()) {
-        if (node->hasTagName(legendTag))
-            return static_cast<HTMLLegendElement*>(node);
+    for (Element* child = ElementTraversal::firstWithin(this); child; child = ElementTraversal::nextSkippingChildren(child, this)) {
+        if (child->hasTagName(legendTag))
+            return static_cast<HTMLLegendElement*>(child);
     }
     return 0;
 }
@@ -113,19 +113,16 @@ void HTMLFieldSetElement::refreshElementsIfNeeded() const
 
     m_associatedElements.clear();
 
-    for (Node* node = firstChild(); node; node = NodeTraversal::next(node, this)) {
-        if (!node->isElementNode())
-            continue;
-
-        if (node->hasTagName(objectTag)) {
-            m_associatedElements.append(static_cast<HTMLObjectElement*>(node));
+    for (Element* element = ElementTraversal::firstWithin(this); element; element = ElementTraversal::next(element, this)) {
+        if (element->hasTagName(objectTag)) {
+            m_associatedElements.append(static_cast<HTMLObjectElement*>(element));
             continue;
         }
 
-        if (!toElement(node)->isFormControlElement())
+        if (!element->isFormControlElement())
             continue;
 
-        m_associatedElements.append(static_cast<HTMLFormControlElement*>(node));
+        m_associatedElements.append(static_cast<HTMLFormControlElement*>(element));
     }
 }
 
index 4f731a0..8a83838 100644 (file)
@@ -505,36 +505,36 @@ unsigned HTMLFormElement::formElementIndexWithFormAttribute(Element* element, un
 
 unsigned HTMLFormElement::formElementIndex(FormAssociatedElement* associatedElement)
 {
-    HTMLElement* element = toHTMLElement(associatedElement);
+    HTMLElement* associatedHTMLElement = toHTMLElement(associatedElement);
     // Treats separately the case where this element has the form attribute
     // for performance consideration.
-    if (element->fastHasAttribute(formAttr)) {
-        unsigned short position = compareDocumentPosition(element);
+    if (associatedHTMLElement->fastHasAttribute(formAttr)) {
+        unsigned short position = compareDocumentPosition(associatedHTMLElement);
         if (position & DOCUMENT_POSITION_PRECEDING) {
             ++m_associatedElementsBeforeIndex;
             ++m_associatedElementsAfterIndex;
-            return HTMLFormElement::formElementIndexWithFormAttribute(element, 0, m_associatedElementsBeforeIndex - 1);
+            return HTMLFormElement::formElementIndexWithFormAttribute(associatedHTMLElement, 0, m_associatedElementsBeforeIndex - 1);
         }
         if (position & DOCUMENT_POSITION_FOLLOWING && !(position & DOCUMENT_POSITION_CONTAINED_BY))
-            return HTMLFormElement::formElementIndexWithFormAttribute(element, m_associatedElementsAfterIndex, m_associatedElements.size());
+            return HTMLFormElement::formElementIndexWithFormAttribute(associatedHTMLElement, m_associatedElementsAfterIndex, m_associatedElements.size());
     }
 
     // Check for the special case where this element is the very last thing in
     // the form's tree of children; we don't want to walk the entire tree in that
     // common case that occurs during parsing; instead we'll just return a value
     // that says "add this form element to the end of the array".
-    if (NodeTraversal::next(element, this)) {
+    if (ElementTraversal::next(associatedHTMLElement, this)) {
         unsigned i = m_associatedElementsBeforeIndex;
-        for (Node* node = this; node; node = NodeTraversal::next(node, this)) {
-            if (node == element) {
+        for (Element* element = this; element; element = ElementTraversal::next(element, this)) {
+            if (element == associatedHTMLElement) {
                 ++m_associatedElementsAfterIndex;
                 return i;
             }
-            if (node->isHTMLElement()
-                    && (static_cast<Element*>(node)->isFormControlElement()
-                        || node->hasTagName(objectTag))
-                    && toHTMLElement(node)->form() == this)
-                ++i;
+            if (!element->isFormControlElement() && !element->hasTagName(objectTag))
+                continue;
+            if (!element->isHTMLElement() || toHTMLElement(element)->form() != this)
+                continue;
+            ++i;
         }
     }
     return m_associatedElementsAfterIndex++;
index 062c6c8..1101aed 100644 (file)
@@ -75,10 +75,10 @@ LabelableElement* HTMLLabelElement::control()
         // Search the children and descendants of the label element for a form element.
         // per http://dev.w3.org/html5/spec/Overview.html#the-label-element
         // the form element must be "labelable form-associated element".
-        Node* node = this;
-        while ((node = NodeTraversal::next(node, this))) {
-            if (LabelableElement* element = nodeAsLabelableElement(node))
-                return element;
+        Element* element = this;
+        while ((element = ElementTraversal::next(element, this))) {
+            if (LabelableElement* labelableElement = nodeAsLabelableElement(element))
+                return labelableElement;
         }
         return 0;
     }
index dd4caaf..d46c6d9 100644 (file)
@@ -50,21 +50,18 @@ PassRefPtr<HTMLLegendElement> HTMLLegendElement::create(const QualifiedName& tag
 HTMLFormControlElement* HTMLLegendElement::associatedControl()
 {
     // Check if there's a fieldset belonging to this legend.
-    ContainerNode* fieldset = parentNode();
+    Element* fieldset = parentElement();
     while (fieldset && !fieldset->hasTagName(fieldsetTag))
-        fieldset = fieldset->parentNode();
+        fieldset = fieldset->parentElement();
     if (!fieldset)
         return 0;
 
     // Find first form element inside the fieldset that is not a legend element.
     // FIXME: Should we consider tabindex?
-    Node* node = fieldset;
-    while ((node = NodeTraversal::next(node, fieldset))) {
-        if (node->isElementNode()) {
-            Element* element = static_cast<Element*>(node);
-            if (element->isFormControlElement())
-                return static_cast<HTMLFormControlElement*>(element);
-        }
+    Element* element = fieldset;
+    while ((element = ElementTraversal::next(element, fieldset))) {
+        if (element->isFormControlElement())
+            return static_cast<HTMLFormControlElement*>(element);
     }
 
     return 0;
index be06f55..5ef1ae9 100644 (file)
@@ -62,10 +62,10 @@ HTMLMapElement::~HTMLMapElement()
 bool HTMLMapElement::mapMouseEvent(LayoutPoint location, const LayoutSize& size, HitTestResult& result)
 {
     HTMLAreaElement* defaultArea = 0;
-    Node *node = this;
-    while ((node = NodeTraversal::next(node, this))) {
-        if (node->hasTagName(areaTag)) {
-            HTMLAreaElement* areaElt = static_cast<HTMLAreaElement*>(node);
+    Element* element = this;
+    while ((element = ElementTraversal::next(element, this))) {
+        if (element->hasTagName(areaTag)) {
+            HTMLAreaElement* areaElt = static_cast<HTMLAreaElement*>(element);
             if (areaElt->isDefault()) {
                 if (!defaultArea)
                     defaultArea = areaElt;
index 7b32de4..8ec32f4 100644 (file)
@@ -54,49 +54,47 @@ Element* HTMLNameCollection::virtualItemAfter(unsigned& offsetInArray, Element*
     ASSERT_UNUSED(offsetInArray, !offsetInArray);
     ASSERT(previous != ownerNode());
 
-    Node* current;
+    Element* current;
     if (!previous)
-        current = ownerNode()->firstChild();
+        current = ElementTraversal::firstWithin(ownerNode());
     else
-        current = NodeTraversal::next(previous, ownerNode());
+        current = ElementTraversal::next(previous, ownerNode());
 
-    for (; current; current = NodeTraversal::next(current, ownerNode())) {
-        if (!current->isElementNode())
-            continue;
-        Element* e = static_cast<Element*>(current);
+    for (; current; current = ElementTraversal::next(current, ownerNode())) {
         switch (type()) {
-            case WindowNamedItems:
-                // find only images, forms, applets, embeds and objects by name, 
-                // but anything by id
-                if (e->hasTagName(imgTag) ||
-                    e->hasTagName(formTag) ||
-                    e->hasTagName(appletTag) ||
-                    e->hasTagName(embedTag) ||
-                    e->hasTagName(objectTag))
-                    if (e->getNameAttribute() == m_name)
-                        return e;
-                if (e->getIdAttribute() == m_name)
-                    return e;
-                break;
-            case DocumentNamedItems:
-                // find images, forms, applets, embeds, objects and iframes by name, 
-                // applets and object by id, and images by id but only if they have
-                // a name attribute (this very strange rule matches IE)
-                if (e->hasTagName(formTag) || e->hasTagName(embedTag) || e->hasTagName(iframeTag)) {
-                    if (e->getNameAttribute() == m_name)
-                        return e;
-                } else if (e->hasTagName(appletTag)) {
-                    if (e->getNameAttribute() == m_name || e->getIdAttribute() == m_name)
-                        return e;
-                } else if (e->hasTagName(objectTag)) {
-                    if ((e->getNameAttribute() == m_name || e->getIdAttribute() == m_name)
-                            && static_cast<HTMLObjectElement*>(e)->isDocNamedItem())
-                        return e;
-                } else if (e->hasTagName(imgTag)) {
-                    if (e->getNameAttribute() == m_name || (e->getIdAttribute() == m_name && e->hasName()))
-                        return e;
-                }
-                break;
+        case WindowNamedItems:
+            // find only images, forms, applets, embeds and objects by name, 
+            // but anything by id
+            if (current->hasTagName(imgTag)
+                || current->hasTagName(formTag)
+                || current->hasTagName(appletTag)
+                || current->hasTagName(embedTag)
+                || current->hasTagName(objectTag)) {
+                if (current->getNameAttribute() == m_name)
+                    return current;
+            }
+            if (current->getIdAttribute() == m_name)
+                return current;
+            break;
+        case DocumentNamedItems:
+            // find images, forms, applets, embeds, objects and iframes by name, 
+            // applets and object by id, and images by id but only if they have
+            // a name attribute (this very strange rule matches IE)
+            if (current->hasTagName(formTag) || current->hasTagName(embedTag) || current->hasTagName(iframeTag)) {
+                if (current->getNameAttribute() == m_name)
+                    return current;
+            } else if (current->hasTagName(appletTag)) {
+                if (current->getNameAttribute() == m_name || current->getIdAttribute() == m_name)
+                    return current;
+            } else if (current->hasTagName(objectTag)) {
+                if ((current->getNameAttribute() == m_name || current->getIdAttribute() == m_name)
+                    && static_cast<HTMLObjectElement*>(current)->isDocNamedItem())
+                    return current;
+            } else if (current->hasTagName(imgTag)) {
+                if (current->getNameAttribute() == m_name || (current->getIdAttribute() == m_name && current->hasName()))
+                    return current;
+            }
+            break;
         default:
             ASSERT_NOT_REACHED();
         }
index 8c60445..b366823 100644 (file)
@@ -41,6 +41,7 @@
 #include "HTMLParserIdioms.h"
 #include "MIMETypeRegistry.h"
 #include "NodeList.h"
+#include "NodeTraversal.h"
 #include "Page.h"
 #include "PluginViewBase.h"
 #include "RenderEmbeddedObject.h"
@@ -457,7 +458,7 @@ bool HTMLObjectElement::containsJavaApplet() const
     if (MIMETypeRegistry::isJavaAppletMIMEType(getAttribute(typeAttr)))
         return true;
         
-    for (Element* child = firstElementChild(); child; child = child->nextElementSibling()) {
+    for (Element* child = ElementTraversal::firstWithin(this); child; child = ElementTraversal::nextSkippingChildren(child, this)) {
         if (child->hasTagName(paramTag)
                 && equalIgnoringCase(child->getNameAttribute(), "type")
                 && MIMETypeRegistry::isJavaAppletMIMEType(child->getAttribute(valueAttr).string()))
index 2714f64..3587234 100644 (file)
@@ -735,13 +735,12 @@ void HTMLSelectElement::recalcListItems(bool updateSelectedStates) const
 
     HTMLOptionElement* foundSelected = 0;
     HTMLOptionElement* firstOption = 0;
-    for (Node* currentNode = this->firstChild(); currentNode;) {
-        if (!currentNode->isHTMLElement()) {
-            currentNode = NodeTraversal::nextSkippingChildren(currentNode, this);
+    for (Element* currentElement = ElementTraversal::firstWithin(this); currentElement; ) {
+        if (!currentElement->isHTMLElement()) {
+            currentElement = ElementTraversal::nextSkippingChildren(currentElement, this);
             continue;
         }
-
-        HTMLElement* current = toHTMLElement(currentNode);
+        HTMLElement* current = toHTMLElement(currentElement);
 
         // optgroup tags may not nest. However, both FireFox and IE will
         // flatten the tree automatically, so we follow suit.
@@ -749,7 +748,7 @@ void HTMLSelectElement::recalcListItems(bool updateSelectedStates) const
         if (current->hasTagName(optgroupTag)) {
             m_listItems.append(current);
             if (current->firstChild()) {
-                currentNode = current->firstChild();
+                currentElement = ElementTraversal::firstWithin(current);
                 continue;
             }
         }
@@ -776,12 +775,12 @@ void HTMLSelectElement::recalcListItems(bool updateSelectedStates) const
             m_listItems.append(current);
 
         // In conforming HTML code, only <optgroup> and <option> will be found
-        // within a <select>. We call NodeTraversal::nextSibling so that we only step
+        // within a <select>. We call NodeTraversal::nextSkippingChildren so that we only step
         // into those tags that we choose to. For web-compat, we should cope
         // with the case where odd tags like a <div> have been added but we
         // handle this because such tags have already been removed from the
         // <select>'s subtree at this point.
-        currentNode = NodeTraversal::nextSkippingChildren(currentNode, this);
+        currentElement = ElementTraversal::nextSkippingChildren(currentElement, this);
     }
 
     if (!foundSelected && m_size <= 1 && firstOption && !firstOption->selected())
index 5245309..dcf3989 100644 (file)
@@ -102,9 +102,9 @@ const Vector<InsertionPoint*>& ShadowRootContentDistributionData::ensureInsertio
     if (!shadowRoot->hasInsertionPoint())
         return m_insertionPointList;
 
-    for (Node* node = shadowRoot; node; node = NodeTraversal::next(node, shadowRoot)) {
-        if (node->isInsertionPoint())
-            m_insertionPointList.append(toInsertionPoint(node));
+    for (Element* element = ElementTraversal::firstWithin(shadowRoot); element; element = ElementTraversal::next(element, shadowRoot)) {
+        if (element->isInsertionPoint())
+            m_insertionPointList.append(toInsertionPoint(element));
     }
 
     return m_insertionPointList;
index 3b04c48..aef4e54 100644 (file)
@@ -770,23 +770,22 @@ void FocusController::findFocusCandidateInContainer(Node* container, const Layou
     ASSERT(container);
     Node* focusedNode = (focusedFrame() && focusedFrame()->document()) ? focusedFrame()->document()->focusedNode() : 0;
 
-    Node* node = container->firstChild();
+    Element* element = ElementTraversal::firstWithin(container);
     FocusCandidate current;
     current.rect = startingRect;
     current.focusableNode = focusedNode;
     current.visibleNode = focusedNode;
 
-    for (; node; node = (node->isFrameOwnerElement() || canScrollInDirection(node, direction)) ? NodeTraversal::nextSkippingChildren(node, container) : NodeTraversal::next(node, container)) {
-        if (node == focusedNode)
+    for (; element; element = (element->isFrameOwnerElement() || canScrollInDirection(element, direction))
+        ? ElementTraversal::nextSkippingChildren(element, container)
+        : ElementTraversal::next(element, container)) {
+        if (element == focusedNode)
             continue;
 
-        if (!node->isElementNode())
+        if (!element->isKeyboardFocusable(event) && !element->isFrameOwnerElement() && !canScrollInDirection(element, direction))
             continue;
 
-        if (!node->isKeyboardFocusable(event) && !node->isFrameOwnerElement() && !canScrollInDirection(node, direction))
-            continue;
-
-        FocusCandidate candidate = FocusCandidate(node, direction);
+        FocusCandidate candidate = FocusCandidate(element, direction);
         if (candidate.isNull())
             continue;
 
index b233c49..affc58d 100644 (file)
@@ -27,6 +27,7 @@
 #include "Element.h"
 #include "HTMLNames.h"
 #include "HTMLOListElement.h"
+#include "NodeTraversal.h"
 #include "RenderListItem.h"
 #include "RenderListMarker.h"
 #include "RenderStyle.h"
@@ -190,13 +191,13 @@ static RenderObject* nextInPreOrder(const RenderObject* object, const Element* s
         ASSERT_NOT_REACHED();
         return 0;
     }
-    child = self->firstElementChild();
+    child = ElementTraversal::firstWithin(self);
     while (true) {
         while (child) {
             result = child->renderer();
             if (result)
                 return result;
-            child = child->nextElementSibling();
+            child = ElementTraversal::nextSkippingChildren(child, self);
         }
         result = rendererOfAfterPseudoElement(self->renderer());
         if (result)
@@ -204,7 +205,7 @@ static RenderObject* nextInPreOrder(const RenderObject* object, const Element* s
 nextsibling:
         if (self == stayWithin)
             return 0;
-        child = self->nextElementSibling();
+        child = ElementTraversal::nextSkippingChildren(self);
         self = self->parentElement();
         if (!self) {
             ASSERT(!child); // We can only reach this if we are searching beyond the root element
index 044b03d..895b8e6 100644 (file)
@@ -346,19 +346,19 @@ void SVGSVGElement::forceRedraw()
 PassRefPtr<NodeList> SVGSVGElement::collectIntersectionOrEnclosureList(const FloatRect& rect, SVGElement* referenceElement, CollectIntersectionOrEnclosure collect) const
 {
     Vector<RefPtr<Node> > nodes;
-    Node* node = NodeTraversal::next(referenceElement ? referenceElement : this);
-    while (node) {
-        if (node->isSVGElement()) { 
+    Element* element = ElementTraversal::next(referenceElement ? referenceElement : this);
+    while (element) {
+        if (element->isSVGElement()) { 
             if (collect == CollectIntersectionList) {
-                if (checkIntersection(static_cast<SVGElement*>(node), rect))
-                    nodes.append(node);
+                if (checkIntersection(static_cast<SVGElement*>(element), rect))
+                    nodes.append(element);
             } else {
-                if (checkEnclosure(static_cast<SVGElement*>(node), rect))
-                    nodes.append(node);
+                if (checkEnclosure(static_cast<SVGElement*>(element), rect))
+                    nodes.append(element);
             }
         }
 
-        node = NodeTraversal::next(node, referenceElement ? referenceElement : this);
+        element = ElementTraversal::next(element, referenceElement ? referenceElement : this);
     }
     return StaticNodeList::adopt(nodes);
 }
index 989a028..df5ebb9 100644 (file)
@@ -28,6 +28,7 @@
 #include "Document.h"
 #include "EventNames.h"
 #include "HTMLNames.h"
+#include "NodeTraversal.h"
 #include "RenderObject.h"
 #include "RenderSVGResource.h"
 #include "RenderSVGResourceClipper.h"
@@ -100,8 +101,8 @@ String SVGStyledElement::title() const
 
     // If we aren't an instance in a <use> or the <use> title was not found, then find the first
     // <title> child of this element.
-    Element* titleElement = firstElementChild();
-    for (; titleElement; titleElement = titleElement->nextElementSibling()) {
+    Element* titleElement = ElementTraversal::firstWithin(this);
+    for (; titleElement; titleElement = ElementTraversal::nextSkippingChildren(titleElement, this)) {
         if (titleElement->hasTagName(SVGNames::titleTag) && titleElement->isSVGElement())
             break;
     }
index 32adfa7..0a77635 100644 (file)
@@ -684,18 +684,18 @@ bool SVGUseElement::hasCycleUseReferencing(SVGUseElement* use, SVGElementInstanc
     return false;
 }
 
-static inline void removeDisallowedElementsFromSubtree(Node* subtree)
+static inline void removeDisallowedElementsFromSubtree(Element* subtree)
 {
     ASSERT(!subtree->inDocument());
-    Node* node = subtree->firstChild();
-    while (node) {
-        if (isDisallowedElement(node)) {
-            Node* next = NodeTraversal::nextSkippingChildren(node, subtree);
+    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.
-            node->parentNode()->removeChild(node);
-            node = next;
+            element->parentNode()->removeChild(element);
+            element = next;
         } else
-            node = NodeTraversal::next(node, subtree);
+            element = ElementTraversal::next(element, subtree);
     }
 }
 
index 0cbceff..c77cf95 100644 (file)
@@ -225,9 +225,9 @@ void SMILTimeContainer::timerFired(Timer<SMILTimeContainer>*)
 void SMILTimeContainer::updateDocumentOrderIndexes()
 {
     unsigned timingElementCount = 0;
-    for (Node* node = m_ownerSVGElement; node; node = NodeTraversal::next(node, m_ownerSVGElement)) {
-        if (SVGSMILElement::isSMILElement(node))
-            static_cast<SVGSMILElement*>(node)->setDocumentOrderIndex(timingElementCount++);
+    for (Element* element = m_ownerSVGElement; element; element = ElementTraversal::next(element, m_ownerSVGElement)) {
+        if (SVGSMILElement::isSMILElement(element))
+            static_cast<SVGSMILElement*>(element)->setDocumentOrderIndex(timingElementCount++);
     }
     m_documentOrderIndexesDirty = false;
 }