<https://webkit.org/b/120166> Add Traversal<ElementType> template
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Aug 2013 12:40:49 +0000 (12:40 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Aug 2013 12:40:49 +0000 (12:40 +0000)
Reviewed by Andreas Kling.

It is common to traverse through a subtree looking for elements of specific type and then casting to the type. This pattern can be generalized.

This patch adds a new Traversal<typename ElementType> template. It works like ElementTraversal except that the traversal is limited to the specified type.
The patch also uses the template in a bunch of applicable places.

* WebCore.exp.in:
* accessibility/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::addImageMapChildren):
* dom/Document.cpp:
(WebCore::Document::removeTitle):
(WebCore::Document::updateBaseURL):
(WebCore::Document::processBaseElement):
* dom/Element.h:
* dom/ElementTraversal.h:
(WebCore::::firstChildTemplate):
(WebCore::::firstWithinTemplate):
(WebCore::::lastChildTemplate):
(WebCore::::lastWithinTemplate):
(WebCore::::nextTemplate):
(WebCore::::previousTemplate):
(WebCore::::nextSiblingTemplate):
(WebCore::::previousSiblingTemplate):
(WebCore::::nextSkippingChildrenTemplate):
(WebCore::::firstChild):
(WebCore::::lastChild):
(WebCore::::firstWithin):
(WebCore::::lastWithin):
(WebCore::::next):
(WebCore::::previous):
(WebCore::::nextSibling):
(WebCore::::previousSibling):
(WebCore::::nextSkippingChildren):
(WebCore::ElementTraversal::previousIncludingPseudo):
(WebCore::ElementTraversal::nextIncludingPseudo):
(WebCore::ElementTraversal::nextIncludingPseudoSkippingChildren):
(WebCore::ElementTraversal::pseudoAwarePreviousSibling):
* dom/Node.cpp:
(WebCore::Node::numberOfScopedHTMLStyleChildren):
* dom/NodeIterator.cpp:
(WebCore::NodeIterator::NodeIterator):
* dom/NodeIterator.h:
* dom/Traversal.cpp:
(WebCore::NodeIteratorBase::NodeIteratorBase):
(WebCore::NodeIteratorBase::acceptNode):
* dom/Traversal.h:

    Renamed existing class called Traversal to less generic NodeIteratorBase.

* dom/TreeScope.cpp:
(WebCore::TreeScope::labelElementForId):
(WebCore::TreeScope::findAnchor):
* dom/TreeWalker.cpp:
(WebCore::TreeWalker::TreeWalker):
* dom/TreeWalker.h:
* editing/FrameSelection.cpp:
(WebCore::scanForForm):
* editing/markup.cpp:
(WebCore::createContextualFragment):
* html/HTMLAnchorElement.h:
(WebCore::isHTMLAnchorElement):
(WebCore::HTMLAnchorElement):
* html/HTMLAreaElement.h:
(WebCore::isHTMLAreaElement):
(WebCore::HTMLAreaElement):
* html/HTMLBaseElement.h:
(WebCore::isHTMLBaseElement):
(WebCore::HTMLBaseElement):
* html/HTMLElement.h:
(WebCore::HTMLElement):
* html/HTMLFieldSetElement.cpp:
(WebCore::HTMLFieldSetElement::invalidateDisabledStateUnder):
(WebCore::HTMLFieldSetElement::childrenChanged):
(WebCore::HTMLFieldSetElement::legend):
* html/HTMLFormControlElement.h:
(WebCore::toHTMLFormControlElement):
(WebCore::HTMLFormControlElement):
* html/HTMLLabelElement.cpp:
(WebCore::nodeAsSupportedLabelableElement):
(WebCore::HTMLLabelElement::control):
* html/HTMLLabelElement.h:
(WebCore::isHTMLLabelElement):
(WebCore::HTMLLabelElement):
* html/HTMLLegendElement.h:
(WebCore::isHTMLLegendElement):
(WebCore::HTMLLegendElement):
* html/HTMLMapElement.cpp:
(WebCore::HTMLMapElement::mapMouseEvent):
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::finishParsingChildren):
* html/HTMLStyleElement.h:
(WebCore::isHTMLStyleElement):
(WebCore::HTMLStyleElement):
* html/HTMLTitleElement.h:
(WebCore::HTMLTitleElement):
* html/HTMLTrackElement.h:
(WebCore::isHTMLTrackElement):
(WebCore::HTMLTrackElement):
* html/LabelableElement.h:
(WebCore::isLabelableElement):
(WebCore::LabelableElement):
* rendering/FilterEffectRenderer.cpp:
(WebCore::FilterEffectRenderer::buildReferenceFilter):
* svg/SVGElement.h:
(WebCore::SVGElement):
* svg/SVGForeignObjectElement.h:
(WebCore::isSVGForeignObjectElement):
(WebCore::SVGForeignObjectElement):
* svg/SVGSVGElement.cpp:
(WebCore::SVGSVGElement::collectIntersectionOrEnclosureList):
(WebCore::SVGSVGElement::getElementById):
* svg/SVGStyledElement.cpp:
(WebCore::SVGStyledElement::title):
* svg/SVGTitleElement.h:
(WebCore::SVGTitleElement):
* svg/animation/SMILTimeContainer.cpp:
(WebCore::SMILTimeContainer::updateDocumentOrderIndexes):
* svg/animation/SVGSMILElement.cpp:
(WebCore::SVGSMILElement::isSMILElement):
* svg/animation/SVGSMILElement.h:
(WebCore::SVGSMILElement):
* svg/graphics/SVGImage.cpp:
(WebCore::SVGImage::hasSingleSecurityOrigin):

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

41 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/accessibility/AccessibilityRenderObject.cpp
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Element.h
Source/WebCore/dom/ElementTraversal.h
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/NodeIterator.cpp
Source/WebCore/dom/NodeIterator.h
Source/WebCore/dom/Traversal.cpp
Source/WebCore/dom/Traversal.h
Source/WebCore/dom/TreeScope.cpp
Source/WebCore/dom/TreeWalker.cpp
Source/WebCore/dom/TreeWalker.h
Source/WebCore/editing/FrameSelection.cpp
Source/WebCore/editing/markup.cpp
Source/WebCore/html/HTMLAnchorElement.h
Source/WebCore/html/HTMLAreaElement.h
Source/WebCore/html/HTMLBaseElement.h
Source/WebCore/html/HTMLElement.h
Source/WebCore/html/HTMLFieldSetElement.cpp
Source/WebCore/html/HTMLFormControlElement.h
Source/WebCore/html/HTMLLabelElement.cpp
Source/WebCore/html/HTMLLabelElement.h
Source/WebCore/html/HTMLLegendElement.h
Source/WebCore/html/HTMLMapElement.cpp
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLStyleElement.h
Source/WebCore/html/HTMLTitleElement.h
Source/WebCore/html/HTMLTrackElement.h
Source/WebCore/html/LabelableElement.h
Source/WebCore/rendering/FilterEffectRenderer.cpp
Source/WebCore/svg/SVGElement.cpp
Source/WebCore/svg/SVGElement.h
Source/WebCore/svg/SVGForeignObjectElement.h
Source/WebCore/svg/SVGSVGElement.cpp
Source/WebCore/svg/SVGTitleElement.h
Source/WebCore/svg/animation/SMILTimeContainer.cpp
Source/WebCore/svg/animation/SVGSMILElement.cpp
Source/WebCore/svg/animation/SVGSMILElement.h
Source/WebCore/svg/graphics/SVGImage.cpp

index b19f857..0d978b9 100644 (file)
@@ -1,3 +1,132 @@
+2013-08-23  Antti Koivisto  <antti@apple.com>
+
+        <https://webkit.org/b/120166> Add Traversal<ElementType> template
+
+        Reviewed by Andreas Kling.
+
+        It is common to traverse through a subtree looking for elements of specific type and then casting to the type. This pattern can be generalized.
+        
+        This patch adds a new Traversal<typename ElementType> template. It works like ElementTraversal except that the traversal is limited to the specified type.
+        The patch also uses the template in a bunch of applicable places.
+
+        * WebCore.exp.in:
+        * accessibility/AccessibilityRenderObject.cpp:
+        (WebCore::AccessibilityRenderObject::addImageMapChildren):
+        * dom/Document.cpp:
+        (WebCore::Document::removeTitle):
+        (WebCore::Document::updateBaseURL):
+        (WebCore::Document::processBaseElement):
+        * dom/Element.h:
+        * dom/ElementTraversal.h:
+        (WebCore::::firstChildTemplate):
+        (WebCore::::firstWithinTemplate):
+        (WebCore::::lastChildTemplate):
+        (WebCore::::lastWithinTemplate):
+        (WebCore::::nextTemplate):
+        (WebCore::::previousTemplate):
+        (WebCore::::nextSiblingTemplate):
+        (WebCore::::previousSiblingTemplate):
+        (WebCore::::nextSkippingChildrenTemplate):
+        (WebCore::::firstChild):
+        (WebCore::::lastChild):
+        (WebCore::::firstWithin):
+        (WebCore::::lastWithin):
+        (WebCore::::next):
+        (WebCore::::previous):
+        (WebCore::::nextSibling):
+        (WebCore::::previousSibling):
+        (WebCore::::nextSkippingChildren):
+        (WebCore::ElementTraversal::previousIncludingPseudo):
+        (WebCore::ElementTraversal::nextIncludingPseudo):
+        (WebCore::ElementTraversal::nextIncludingPseudoSkippingChildren):
+        (WebCore::ElementTraversal::pseudoAwarePreviousSibling):
+        * dom/Node.cpp:
+        (WebCore::Node::numberOfScopedHTMLStyleChildren):
+        * dom/NodeIterator.cpp:
+        (WebCore::NodeIterator::NodeIterator):
+        * dom/NodeIterator.h:
+        * dom/Traversal.cpp:
+        (WebCore::NodeIteratorBase::NodeIteratorBase):
+        (WebCore::NodeIteratorBase::acceptNode):
+        * dom/Traversal.h:
+        
+            Renamed existing class called Traversal to less generic NodeIteratorBase.
+
+        * dom/TreeScope.cpp:
+        (WebCore::TreeScope::labelElementForId):
+        (WebCore::TreeScope::findAnchor):
+        * dom/TreeWalker.cpp:
+        (WebCore::TreeWalker::TreeWalker):
+        * dom/TreeWalker.h:
+        * editing/FrameSelection.cpp:
+        (WebCore::scanForForm):
+        * editing/markup.cpp:
+        (WebCore::createContextualFragment):
+        * html/HTMLAnchorElement.h:
+        (WebCore::isHTMLAnchorElement):
+        (WebCore::HTMLAnchorElement):
+        * html/HTMLAreaElement.h:
+        (WebCore::isHTMLAreaElement):
+        (WebCore::HTMLAreaElement):
+        * html/HTMLBaseElement.h:
+        (WebCore::isHTMLBaseElement):
+        (WebCore::HTMLBaseElement):
+        * html/HTMLElement.h:
+        (WebCore::HTMLElement):
+        * html/HTMLFieldSetElement.cpp:
+        (WebCore::HTMLFieldSetElement::invalidateDisabledStateUnder):
+        (WebCore::HTMLFieldSetElement::childrenChanged):
+        (WebCore::HTMLFieldSetElement::legend):
+        * html/HTMLFormControlElement.h:
+        (WebCore::toHTMLFormControlElement):
+        (WebCore::HTMLFormControlElement):
+        * html/HTMLLabelElement.cpp:
+        (WebCore::nodeAsSupportedLabelableElement):
+        (WebCore::HTMLLabelElement::control):
+        * html/HTMLLabelElement.h:
+        (WebCore::isHTMLLabelElement):
+        (WebCore::HTMLLabelElement):
+        * html/HTMLLegendElement.h:
+        (WebCore::isHTMLLegendElement):
+        (WebCore::HTMLLegendElement):
+        * html/HTMLMapElement.cpp:
+        (WebCore::HTMLMapElement::mapMouseEvent):
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::finishParsingChildren):
+        * html/HTMLStyleElement.h:
+        (WebCore::isHTMLStyleElement):
+        (WebCore::HTMLStyleElement):
+        * html/HTMLTitleElement.h:
+        (WebCore::HTMLTitleElement):
+        * html/HTMLTrackElement.h:
+        (WebCore::isHTMLTrackElement):
+        (WebCore::HTMLTrackElement):
+        * html/LabelableElement.h:
+        (WebCore::isLabelableElement):
+        (WebCore::LabelableElement):
+        * rendering/FilterEffectRenderer.cpp:
+        (WebCore::FilterEffectRenderer::buildReferenceFilter):
+        * svg/SVGElement.h:
+        (WebCore::SVGElement):
+        * svg/SVGForeignObjectElement.h:
+        (WebCore::isSVGForeignObjectElement):
+        (WebCore::SVGForeignObjectElement):
+        * svg/SVGSVGElement.cpp:
+        (WebCore::SVGSVGElement::collectIntersectionOrEnclosureList):
+        (WebCore::SVGSVGElement::getElementById):
+        * svg/SVGStyledElement.cpp:
+        (WebCore::SVGStyledElement::title):
+        * svg/SVGTitleElement.h:
+        (WebCore::SVGTitleElement):
+        * svg/animation/SMILTimeContainer.cpp:
+        (WebCore::SMILTimeContainer::updateDocumentOrderIndexes):
+        * svg/animation/SVGSMILElement.cpp:
+        (WebCore::SVGSMILElement::isSMILElement):
+        * svg/animation/SVGSMILElement.h:
+        (WebCore::SVGSMILElement):
+        * svg/graphics/SVGImage.cpp:
+        (WebCore::SVGImage::hasSingleSecurityOrigin):
+
 2013-08-23  Arpita Bahuguna  <a.bah@samsung.com>
 
         <br> does not get deleted when inlined after some non-textual content.
index 9620631..8211e38 100644 (file)
@@ -2694,7 +2694,6 @@ __ZN7WebCore22RuntimeEnabledFeatures22isDialogElementEnabledE
 #endif
 
 #if ENABLE(SVG)
-__ZN7WebCore14SVGSMILElement13isSMILElementEPNS_4NodeE
 __ZN7WebCore8Document13svgExtensionsEv
 __ZN7WebCore8Document19accessSVGExtensionsEv
 #endif
index d7a0ca8..d7aa8e5 100644 (file)
@@ -2753,9 +2753,9 @@ void AccessibilityRenderObject::addImageMapChildren()
     if (!map)
         return;
 
-    for (Element* current = ElementTraversal::firstWithin(map); current; current = ElementTraversal::next(current, map)) {
+    for (HTMLAreaElement* current = Traversal<HTMLAreaElement>::firstWithin(map); current; current = Traversal<HTMLAreaElement>::next(current, map)) {
         // add an <area> element for this child if it has a link
-        if (isHTMLAreaElement(current) && current->isLink()) {
+        if (current->isLink()) {
             AccessibilityImageMapLink* areaObject = static_cast<AccessibilityImageMapLink*>(axObjectCache()->getOrCreate(ImageMapLinkRole));
             areaObject->setHTMLAreaElement(toHTMLAreaElement(current));
             areaObject->setHTMLMapElement(map);
index 1ea796c..2a22d5c 100644 (file)
@@ -78,6 +78,7 @@
 #include "History.h"
 #include "HTMLAllCollection.h"
 #include "HTMLAnchorElement.h"
+#include "HTMLBaseElement.h"
 #include "HTMLCanvasElement.h"
 #include "HTMLCollection.h"
 #include "HTMLDocument.h"
@@ -1559,13 +1560,8 @@ void Document::removeTitle(Element* titleElement)
 
     // Update title based on first title element in the head, if one exists.
     if (HTMLElement* headElement = head()) {
-        for (Element* element = ElementTraversal::firstWithin(headElement); element; element = ElementTraversal::nextSibling(element)) {
-            if (isHTMLTitleElement(element)) {
-                HTMLTitleElement* titleElement = toHTMLTitleElement(element);
-                setTitleElement(titleElement->textWithDirection(), titleElement);
-                break;
-            }
-        }
+        if (HTMLTitleElement* titleElement = Traversal<HTMLTitleElement>::firstWithin(headElement))
+            setTitleElement(titleElement->textWithDirection(), titleElement);
     }
 
     if (!m_titleElement)
@@ -2613,10 +2609,8 @@ 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 (Element* element = ElementTraversal::firstWithin(this); element; element = ElementTraversal::next(element)) {
-            if (isHTMLAnchorElement(element))
-                toHTMLAnchorElement(element)->invalidateCachedVisitedLinkHash();
-        }
+        for (HTMLAnchorElement* anchor = Traversal<HTMLAnchorElement>::firstWithin(this); anchor; anchor = Traversal<HTMLAnchorElement>::next(anchor))
+            anchor->invalidateCachedVisitedLinkHash();
     }
 }
 
@@ -2631,18 +2625,16 @@ 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 (Element* element = ElementTraversal::firstWithin(this); element && (!href || !target); element = ElementTraversal::next(element)) {
-        if (element->hasTagName(baseTag)) {
-            if (!href) {
-                const AtomicString& value = element->fastGetAttribute(hrefAttr);
-                if (!value.isNull())
-                    href = &value;
-            }
-            if (!target) {
-                const AtomicString& value = element->fastGetAttribute(targetAttr);
-                if (!value.isNull())
-                    target = &value;
-            }
+    for (HTMLBaseElement* base = Traversal<HTMLBaseElement>::firstWithin(this); base && (!href || !target); base = Traversal<HTMLBaseElement>::next(base)) {
+        if (!href) {
+            const AtomicString& value = base->fastGetAttribute(hrefAttr);
+            if (!value.isNull())
+                href = &value;
+        }
+        if (!target) {
+            const AtomicString& value = base->fastGetAttribute(targetAttr);
+            if (!value.isNull())
+                target = &value;
         }
     }
 
index 1ccd3c8..3a8e6c6 100644 (file)
@@ -692,6 +692,10 @@ inline const Element* toElement(const Node* node)
 // This will catch anyone doing an unnecessary cast.
 void toElement(const Element*);
 
+template <typename Type> bool isElementOfType(const Element*);
+template <typename Type> bool isElementOfType(const Node* node) { return node->isElementNode() && isElementOfType<Type>(toElement(node)); }
+template <> inline bool isElementOfType<Element>(const Element*) { return true; }
+
 inline bool isDisabledFormControl(const Node* node)
 {
     return node->isElementNode() && toElement(node)->isDisabledFormControl();
index fb51756..6c2b1d2 100644 (file)
 #include "NodeTraversal.h"
 
 namespace WebCore {
-namespace ElementTraversal {
 
-// First or last element child of the node.
-Element* firstWithin(const Node*);
-Element* firstWithin(const ContainerNode*);
-Element* lastWithin(const Node*);
-Element* lastWithin(const ContainerNode*);
+template <typename ElementType>
+class Traversal {
+public:
+    // First or last ElementType child of the node.
+    static ElementType* firstChild(const Node*);
+    static ElementType* firstChild(const ContainerNode*);
+    static ElementType* lastChild(const Node*);
+    static ElementType* lastChild(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);
+    // First or last ElementType descendant of the node. For Elements this is always the same as first/last child.
+    static ElementType* firstWithin(const Node*);
+    static ElementType* firstWithin(const ContainerNode*);
+    static ElementType* lastWithin(const Node*);
+    static ElementType* lastWithin(const ContainerNode*);
 
-// Next or previous Element sibling if there is one.
-Element* nextSibling(const Node*);
-Element* nextSibling(const ContainerNode*);
-Element* previousSibling(const Node*);
-Element* previousSibling(const ContainerNode*);
+    // Pre-order traversal skipping non-ElementType nodes.
+    static ElementType* next(const Node*);
+    static ElementType* next(const Node*, const Node* stayWithin);
+    static ElementType* next(const ContainerNode*);
+    static ElementType* next(const ContainerNode*, const Node* stayWithin);
+    static ElementType* previous(const Node*);
+    static ElementType* previous(const Node*, const Node* stayWithin);
+    static ElementType* previous(const ContainerNode*);
+    static ElementType* previous(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);
+    // Next or previous ElementType sibling if there is one.
+    static ElementType* nextSibling(const Node*);
+    static ElementType* nextSibling(const ContainerNode*);
+    static ElementType* previousSibling(const Node*);
+    static ElementType* previousSibling(const ContainerNode*);
 
-// Pre-order traversal including the pseudo-elements.
-Element* previousIncludingPseudo(const Node*, const Node* = 0);
-Element* nextIncludingPseudo(const Node*, const Node* = 0);
-Element* nextIncludingPseudoSkippingChildren(const Node*, const Node* = 0);
+    // Like next, but skips children.
+    static ElementType* nextSkippingChildren(const Node*);
+    static ElementType* nextSkippingChildren(const Node*, const Node* stayWithin);
+    static ElementType* nextSkippingChildren(const ContainerNode*);
+    static ElementType* nextSkippingChildren(const ContainerNode*, const Node* stayWithin);
 
-// Utility function to traverse only the element and pseudo-element siblings of a node.
-Element* pseudoAwarePreviousSibling(const Node*);
+private:
+    template <typename CurrentType> static ElementType* firstChildTemplate(CurrentType*);
+    template <typename CurrentType> static ElementType* lastChildTemplate(CurrentType*);
+    template <typename CurrentType> static ElementType* firstWithinTemplate(CurrentType*);
+    template <typename CurrentType> static ElementType* lastWithinTemplate(CurrentType*);
+    template <typename CurrentType> static ElementType* nextTemplate(CurrentType*);
+    template <typename CurrentType> static ElementType* nextTemplate(CurrentType*, const Node* stayWithin);
+    template <typename CurrentType> static ElementType* previousTemplate(CurrentType*);
+    template <typename CurrentType> static ElementType* previousTemplate(CurrentType*, const Node* stayWithin);
+    template <typename CurrentType> static ElementType* nextSiblingTemplate(CurrentType*);
+    template <typename CurrentType> static ElementType* previousSiblingTemplate(CurrentType*);
+    template <typename CurrentType> static ElementType* nextSkippingChildrenTemplate(CurrentType*);
+    template <typename CurrentType> static ElementType* nextSkippingChildrenTemplate(CurrentType*, const Node* stayWithin);
+};
 
-}
+class ElementTraversal : public Traversal<Element> {
+public:
+    // FIXME: These should go somewhere else.
+    // Pre-order traversal including the pseudo-elements.
+    static Element* previousIncludingPseudo(const Node*, const Node* = 0);
+    static Element* nextIncludingPseudo(const Node*, const Node* = 0);
+    static Element* nextIncludingPseudoSkippingChildren(const Node*, const Node* = 0);
 
-namespace ElementTraversal {
+    // Utility function to traverse only the element and pseudo-element siblings of a node.
+    static Element* pseudoAwarePreviousSibling(const Node*);
+};
 
-template <class NodeType>
-inline Element* firstElementWithinTemplate(NodeType* current)
+// Specialized for pure Element to exploit the fact that Elements parent is always either another Element or the root.
+template <>
+template <typename CurrentType>
+inline Element* Traversal<Element>::firstWithinTemplate(CurrentType* 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);
+    return firstChildTemplate(current);
 }
-inline Element* firstWithin(const ContainerNode* current) { return firstElementWithinTemplate(current); }
-inline Element* firstWithin(const Node* current) { return firstElementWithinTemplate(current); }
 
-template <class NodeType>
-inline Element* lastElementWithinTemplate(NodeType* current)
+template <>
+template <typename CurrentType>
+inline Element* Traversal<Element>::lastWithinTemplate(CurrentType* current)
 {
-    Node* node = current->lastChild();
-    while (node && !node->isElementNode())
-        node = node->previousSibling();
-    return toElement(node);
+    return lastChildTemplate(current);
 }
-inline Element* lastWithin(const ContainerNode* current) { return lastElementWithinTemplate(current); }
-inline Element* lastWithin(const Node* current) { return lastElementWithinTemplate(current); }
 
-template <class NodeType>
-inline Element* traverseNextElementTemplate(NodeType* current)
+template <>
+template <typename CurrentType>
+inline Element* Traversal<Element>::nextTemplate(CurrentType* current)
 {
     Node* node = NodeTraversal::next(current);
     while (node && !node->isElementNode())
         node = NodeTraversal::nextSkippingChildren(node);
-    return toElement(node);
+    return static_cast<Element*>(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)
+template <>
+template <typename CurrentType>
+inline Element* Traversal<Element>::nextTemplate(CurrentType* current, const Node* stayWithin)
 {
     Node* node = NodeTraversal::next(current, stayWithin);
     while (node && !node->isElementNode())
         node = NodeTraversal::nextSkippingChildren(node, stayWithin);
-    return toElement(node);
+    return static_cast<Element*>(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* traverseNextSiblingElementTemplate(NodeType* current)
+template <>
+template <typename CurrentType>
+inline Element* Traversal<Element>::previousTemplate(CurrentType* current)
 {
-    Node* node = current->nextSibling();
+    Node* node = NodeTraversal::previous(current);
+    while (node && !node->isElementNode())
+        node = NodeTraversal::previousSkippingChildren(node);
+    return static_cast<Element*>(node);
+}
+
+template <>
+template <typename CurrentType>
+inline Element* Traversal<Element>::previousTemplate(CurrentType* current, const Node* stayWithin)
+{
+    Node* node = NodeTraversal::previous(current, stayWithin);
     while (node && !node->isElementNode())
+        node = NodeTraversal::previousSkippingChildren(node, stayWithin);
+    return static_cast<Element*>(node);
+}
+
+// Generic versions.
+template <typename ElementType>
+template <typename CurrentType>
+inline ElementType* Traversal<ElementType>::firstChildTemplate(CurrentType* current)
+{
+    Node* node = current->firstChild();
+    while (node && !isElementOfType<ElementType>(node))
         node = node->nextSibling();
-    return toElement(node);
+    return static_cast<ElementType*>(node);
+}
+
+template <typename ElementType>
+template <typename CurrentType>
+inline ElementType* Traversal<ElementType>::lastChildTemplate(CurrentType* current)
+{
+    Node* node = current->lastChild();
+    while (node && !isElementOfType<ElementType>(node))
+        node = node->previousSibling();
+    return static_cast<ElementType*>(node);
+}
+
+template <typename ElementType>
+template <typename CurrentType>
+inline ElementType* Traversal<ElementType>::firstWithinTemplate(CurrentType* current)
+{
+    Element* element = Traversal<Element>::firstWithin(current);
+    while (element && !isElementOfType<ElementType>(element))
+        element = Traversal<Element>::next(element, current);
+    return static_cast<ElementType*>(element);
 }
-inline Element* nextSibling(const ContainerNode* current) { return traverseNextSiblingElementTemplate(current); }
-inline Element* nextSibling(const Node* current) { return traverseNextSiblingElementTemplate(current); }
 
-template <class NodeType>
-inline Element* traversePreviousSiblingElementTemplate(NodeType* current)
+template <typename ElementType>
+template <typename CurrentType>
+inline ElementType* Traversal<ElementType>::lastWithinTemplate(CurrentType* current)
+{
+    Element* element = Traversal<Element>::lastWithin(current);
+    while (element && !isElementOfType<ElementType>(element))
+        element = Traversal<Element>::previous(element, current);
+    return static_cast<ElementType*>(element);
+}
+
+template <typename ElementType>
+template <typename CurrentType>
+inline ElementType* Traversal<ElementType>::nextTemplate(CurrentType* current)
+{
+    Element* element = Traversal<Element>::next(current);
+    while (element && !isElementOfType<ElementType>(element))
+        element = Traversal<Element>::next(element);
+    return static_cast<ElementType*>(element);
+}
+
+template <typename ElementType>
+template <typename CurrentType>
+inline ElementType* Traversal<ElementType>::nextTemplate(CurrentType* current, const Node* stayWithin)
+{
+    Element* element = Traversal<Element>::next(current, stayWithin);
+    while (element && !isElementOfType<ElementType>(element))
+        element = Traversal<Element>::next(element, stayWithin);
+    return static_cast<ElementType*>(element);
+}
+
+template <typename ElementType>
+template <typename CurrentType>
+inline ElementType* Traversal<ElementType>::previousTemplate(CurrentType* current)
+{
+    Element* element = Traversal<Element>::previous(current);
+    while (element && !isElementOfType<ElementType>(element))
+        element = Traversal<Element>::previous(element);
+    return static_cast<ElementType*>(element);
+}
+
+template <typename ElementType>
+template <typename CurrentType>
+inline ElementType* Traversal<ElementType>::previousTemplate(CurrentType* current, const Node* stayWithin)
+{
+    Element* element = Traversal<Element>::previous(current, stayWithin);
+    while (element && !isElementOfType<ElementType>(element))
+        element = Traversal<Element>::previous(element, stayWithin);
+    return static_cast<ElementType*>(element);
+}
+
+template <typename ElementType>
+template <typename CurrentType>
+inline ElementType* Traversal<ElementType>::nextSiblingTemplate(CurrentType* current)
+{
+    Node* node = current->nextSibling();
+    while (node && !isElementOfType<ElementType>(node))
+        node = node->nextSibling();
+    return static_cast<ElementType*>(node);
+}
+
+template <typename ElementType>
+template <typename CurrentType>
+inline ElementType* Traversal<ElementType>::previousSiblingTemplate(CurrentType* current)
 {
     Node* node = current->previousSibling();
-    while (node && !node->isElementNode())
+    while (node && !isElementOfType<ElementType>(node))
         node = node->previousSibling();
-    return toElement(node);
+    return static_cast<ElementType*>(node);
 }
-inline Element* previousSibling(const ContainerNode* current) { return traversePreviousSiblingElementTemplate(current); }
-inline Element* previousSibling(const Node* current) { return traversePreviousSiblingElementTemplate(current); }
 
-template <class NodeType>
-inline Element* traverseNextElementSkippingChildrenTemplate(NodeType* current)
+template <typename ElementType>
+template <typename CurrentType>
+inline ElementType* Traversal<ElementType>::nextSkippingChildrenTemplate(CurrentType* current)
 {
     Node* node = NodeTraversal::nextSkippingChildren(current);
-    while (node && !node->isElementNode())
+    while (node && !isElementOfType<ElementType>(node))
         node = NodeTraversal::nextSkippingChildren(node);
-    return toElement(node);
+    return static_cast<ElementType*>(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)
+template <typename ElementType>
+template <typename CurrentType>
+inline ElementType* Traversal<ElementType>::nextSkippingChildrenTemplate(CurrentType* current, const Node* stayWithin)
 {
     Node* node = NodeTraversal::nextSkippingChildren(current, stayWithin);
-    while (node && !node->isElementNode())
+    while (node && !isElementOfType<ElementType>(node))
         node = NodeTraversal::nextSkippingChildren(node, stayWithin);
-    return toElement(node);
+    return static_cast<ElementType*>(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); }
 
-inline Element* previousIncludingPseudo(const Node* current, const Node* stayWithin)
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::firstChild(const ContainerNode* current) { return firstWithinTemplate(current); }
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::firstChild(const Node* current) { return firstWithinTemplate(current); }
+template <typename ElementType>
+
+inline ElementType* Traversal<ElementType>::lastChild(const ContainerNode* current) { return lastWithinTemplate(current); }
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::lastChild(const Node* current) { return lastWithinTemplate(current); }
+
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::firstWithin(const ContainerNode* current) { return firstWithinTemplate(current); }
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::firstWithin(const Node* current) { return firstWithinTemplate(current); }
+template <typename ElementType>
+
+inline ElementType* Traversal<ElementType>::lastWithin(const ContainerNode* current) { return lastWithinTemplate(current); }
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::lastWithin(const Node* current) { return lastWithinTemplate(current); }
+
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::next(const ContainerNode* current) { return nextTemplate(current); }
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::next(const Node* current) { return nextTemplate(current); }
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::next(const ContainerNode* current, const Node* stayWithin) { return nextTemplate(current, stayWithin); }
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::next(const Node* current, const Node* stayWithin) { return nextTemplate(current, stayWithin); }
+
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::previous(const ContainerNode* current) { return previousTemplate(current); }
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::previous(const Node* current) { return previousTemplate(current); }
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::previous(const ContainerNode* current, const Node* stayWithin) { return previousTemplate(current, stayWithin); }
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::previous(const Node* current, const Node* stayWithin) { return previousTemplate(current, stayWithin); }
+
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::nextSibling(const ContainerNode* current) { return nextSiblingTemplate(current); }
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::nextSibling(const Node* current) { return nextSiblingTemplate(current); }
+
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::previousSibling(const ContainerNode* current) { return previousSiblingTemplate(current); }
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::previousSibling(const Node* current) { return previousSiblingTemplate(current); }
+
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::nextSkippingChildren(const ContainerNode* current) { return nextSkippingChildrenTemplate(current); }
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::nextSkippingChildren(const Node* current) { return nextSkippingChildrenTemplate(current); }
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::nextSkippingChildren(const ContainerNode* current, const Node* stayWithin) { return nextSkippingChildrenTemplate(current, stayWithin); }
+template <typename ElementType>
+inline ElementType* Traversal<ElementType>::nextSkippingChildren(const Node* current, const Node* stayWithin) { return nextSkippingChildrenTemplate(current, stayWithin); }
+
+// FIXME: These should go somewhere else.
+inline Element* ElementTraversal::previousIncludingPseudo(const Node* current, const Node* stayWithin)
 {
     Node* node = NodeTraversal::previousIncludingPseudo(current, stayWithin);
     while (node && !node->isElementNode())
@@ -164,7 +336,7 @@ inline Element* previousIncludingPseudo(const Node* current, const Node* stayWit
     return toElement(node);
 }
 
-inline Element* nextIncludingPseudo(const Node* current, const Node* stayWithin)
+inline Element* ElementTraversal::nextIncludingPseudo(const Node* current, const Node* stayWithin)
 {
     Node* node = NodeTraversal::nextIncludingPseudo(current, stayWithin);
     while (node && !node->isElementNode())
@@ -172,7 +344,7 @@ inline Element* nextIncludingPseudo(const Node* current, const Node* stayWithin)
     return toElement(node);
 }
 
-inline Element* nextIncludingPseudoSkippingChildren(const Node* current, const Node* stayWithin)
+inline Element* ElementTraversal::nextIncludingPseudoSkippingChildren(const Node* current, const Node* stayWithin)
 {
     Node* node = NodeTraversal::nextIncludingPseudoSkippingChildren(current, stayWithin);
     while (node && !node->isElementNode())
@@ -180,7 +352,7 @@ inline Element* nextIncludingPseudoSkippingChildren(const Node* current, const N
     return toElement(node);
 }
 
-inline Element* pseudoAwarePreviousSibling(const Node* current)
+inline Element* ElementTraversal::pseudoAwarePreviousSibling(const Node* current)
 {
     Node* node = current->pseudoAwarePreviousSibling();
     while (node && !node->isElementNode())
@@ -189,6 +361,5 @@ inline Element* pseudoAwarePreviousSibling(const Node* current)
 }
 
 }
-}
 
 #endif
index c33f367..ced8bef 100644 (file)
@@ -2380,9 +2380,10 @@ void Node::unregisterScopedHTMLStyleChild()
 size_t Node::numberOfScopedHTMLStyleChildren() const
 {
     size_t count = 0;
-    for (Element* element = ElementTraversal::firstWithin(this); element; element = ElementTraversal::next(element, this))
-        if (isHTMLStyleElement(element) && toHTMLStyleElement(element)->isRegisteredAsScoped())
+    for (HTMLStyleElement* style = Traversal<HTMLStyleElement>::firstWithin(this); style; style = Traversal<HTMLStyleElement>::next(style, this)) {
+        if (style->isRegisteredAsScoped())
             count++;
+    }
 
     return count;
 }
index d03724d..91c01da 100644 (file)
@@ -73,7 +73,7 @@ bool NodeIterator::NodePointer::moveToPrevious(Node* root)
 }
 
 NodeIterator::NodeIterator(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> filter, bool expandEntityReferences)
-    : Traversal(rootNode, whatToShow, filter, expandEntityReferences)
+    : NodeIteratorBase(rootNode, whatToShow, filter, expandEntityReferences)
     , m_referenceNode(root(), true)
     , m_detached(false)
 {
index 1fad1f7..ea4526a 100644 (file)
@@ -35,7 +35,7 @@ namespace WebCore {
 
     typedef int ExceptionCode;
 
-    class NodeIterator : public ScriptWrappable, public RefCounted<NodeIterator>, public Traversal {
+    class NodeIterator : public ScriptWrappable, public RefCounted<NodeIterator>, public NodeIteratorBase {
     public:
         static PassRefPtr<NodeIterator> create(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> filter, bool expandEntityReferences)
         {
index f82ee2c..0be3687 100644 (file)
@@ -30,7 +30,7 @@
 
 namespace WebCore {
 
-Traversal::Traversal(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> nodeFilter, bool expandEntityReferences)
+NodeIteratorBase::NodeIteratorBase(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> nodeFilter, bool expandEntityReferences)
     : m_root(rootNode)
     , m_whatToShow(whatToShow)
     , m_filter(nodeFilter)
@@ -38,7 +38,7 @@ Traversal::Traversal(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<
 {
 }
 
-short Traversal::acceptNode(ScriptState* state, Node* node) const
+short NodeIteratorBase::acceptNode(ScriptState* state, Node* node) const
 {
     // FIXME: To handle XML properly we would have to check m_expandEntityReferences.
 
index 8b4f764..4fff90f 100644 (file)
@@ -33,7 +33,7 @@ namespace WebCore {
     class Node;
     class NodeFilter;
 
-    class Traversal {
+    class NodeIteratorBase {
     public:
         Node* root() const { return m_root.get(); }
         unsigned whatToShow() const { return m_whatToShow; }
@@ -41,7 +41,7 @@ namespace WebCore {
         bool expandEntityReferences() const { return m_expandEntityReferences; }
 
     protected:
-        Traversal(PassRefPtr<Node>, unsigned whatToShow, PassRefPtr<NodeFilter>, bool expandEntityReferences);
+        NodeIteratorBase(PassRefPtr<Node>, unsigned whatToShow, PassRefPtr<NodeFilter>, bool expandEntityReferences);
         short acceptNode(ScriptState*, Node*) const;
 
     private:
index 122eab8..4599c97 100644 (file)
@@ -298,13 +298,10 @@ HTMLLabelElement* TreeScope::labelElementForId(const AtomicString& forAttributeV
     if (!m_labelsByForAttribute) {
         // Populate the map on first access.
         m_labelsByForAttribute = adoptPtr(new DocumentOrderedMap);
-        for (Element* element = ElementTraversal::firstWithin(rootNode()); element; element = ElementTraversal::next(element)) {
-            if (isHTMLLabelElement(element)) {
-                HTMLLabelElement* label = toHTMLLabelElement(element);
-                const AtomicString& forValue = label->fastGetAttribute(forAttr);
-                if (!forValue.isEmpty())
-                    addLabel(forValue, label);
-            }
+        for (HTMLLabelElement* label = Traversal<HTMLLabelElement>::firstWithin(rootNode()); label; label = Traversal<HTMLLabelElement>::next(label)) {
+            const AtomicString& forValue = label->fastGetAttribute(forAttr);
+            if (!forValue.isEmpty())
+                addLabel(forValue, label);
         }
     }
 
@@ -342,18 +339,15 @@ Element* TreeScope::findAnchor(const String& name)
         return 0;
     if (Element* element = getElementById(name))
         return element;
-    for (Element* element = ElementTraversal::firstWithin(rootNode()); element; element = ElementTraversal::next(element)) {
-        if (isHTMLAnchorElement(element)) {
-            HTMLAnchorElement* anchor = toHTMLAnchorElement(element);
-            if (rootNode()->document()->inQuirksMode()) {
-                // Quirks mode, case insensitive comparison of names.
-                if (equalIgnoringCase(anchor->name(), name))
-                    return anchor;
-            } else {
-                // Strict mode, names need to match exactly.
-                if (anchor->name() == name)
-                    return anchor;
-            }
+    for (HTMLAnchorElement* anchor = Traversal<HTMLAnchorElement>::firstWithin(rootNode()); anchor; anchor = Traversal<HTMLAnchorElement>::next(anchor)) {
+        if (rootNode()->document()->inQuirksMode()) {
+            // Quirks mode, case insensitive comparison of names.
+            if (equalIgnoringCase(anchor->name(), name))
+                return anchor;
+        } else {
+            // Strict mode, names need to match exactly.
+            if (anchor->name() == name)
+                return anchor;
         }
     }
     return 0;
index f9b3bbc..74e791d 100644 (file)
@@ -35,7 +35,7 @@
 namespace WebCore {
 
 TreeWalker::TreeWalker(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> filter, bool expandEntityReferences)
-    : Traversal(rootNode, whatToShow, filter, expandEntityReferences)
+    : NodeIteratorBase(rootNode, whatToShow, filter, expandEntityReferences)
     , m_current(root())
 {
 }
index 5a5d586..591fd6b 100644 (file)
@@ -35,7 +35,7 @@ namespace WebCore {
 
     typedef int ExceptionCode;
 
-    class TreeWalker : public ScriptWrappable, public RefCounted<TreeWalker>, public Traversal {
+    class TreeWalker : public ScriptWrappable, public RefCounted<TreeWalker>, public NodeIteratorBase {
     public:
         static PassRefPtr<TreeWalker> create(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> filter, bool expandEntityReferences)
         {
index 291c439..a535a48 100644 (file)
@@ -1970,11 +1970,11 @@ static HTMLFormElement* scanForForm(Node* start)
 {
     if (!start)
         return 0;
-    Element* element = start->isElementNode() ? toElement(start) : ElementTraversal::next(start);
-    for (; element; element = ElementTraversal::next(element)) {
+    HTMLElement* element = start->isHTMLElement() ? toHTMLElement(start) : Traversal<HTMLElement>::next(start);
+    for (; element; element = Traversal<HTMLElement>::next(element)) {
         if (isHTMLFormElement(element))
             return toHTMLFormElement(element);
-        if (element->isHTMLElement() && toHTMLElement(element)->isFormControlElement())
+        if (element->isFormControlElement())
             return static_cast<HTMLFormControlElement*>(element)->form();
         if (element->hasTagName(frameTag) || element->hasTagName(iframeTag))
             if (HTMLFormElement* frameResult = scanForForm(toHTMLFrameElementBase(element)->contentDocument()))
index 9e05453..21ef8b2 100644 (file)
@@ -1055,14 +1055,13 @@ PassRefPtr<DocumentFragment> createContextualFragment(const String& markup, HTML
     // accommodate folks passing complete HTML documents to make the
     // child of an element.
 
-    RefPtr<Element> nextElement;
-    for (RefPtr<Element> element = ElementTraversal::firstWithin(fragment.get()); element; element = nextElement) {
-        nextElement = ElementTraversal::nextSibling(element.get());
+    RefPtr<HTMLElement> nextElement;
+    for (RefPtr<HTMLElement> element = Traversal<HTMLElement>::firstWithin(fragment.get()); element; element = nextElement) {
+        nextElement = Traversal<HTMLElement>::nextSibling(element.get());
         if (element->hasTagName(htmlTag) || element->hasTagName(headTag) || element->hasTagName(bodyTag)) {
-            HTMLElement* htmlElement = toHTMLElement(element.get());
-            if (Element* firstChild = ElementTraversal::firstWithin(htmlElement))
+            if (HTMLElement* firstChild = Traversal<HTMLElement>::firstChild(element.get()))
                 nextElement = firstChild;
-            removeElementPreservingChildren(fragment, htmlElement);
+            removeElementPreservingChildren(fragment, element.get());
         }
     }
     return fragment.release();
index 489ca19..4ad8ab9 100644 (file)
@@ -149,12 +149,12 @@ inline LinkHash HTMLAnchorElement::visitedLinkHash() const
     return m_cachedVisitedLinkHash; 
 }
 
-inline bool isHTMLAnchorElement(Node* node)
+inline bool isHTMLAnchorElement(const Node* node)
 {
     return node->hasTagName(HTMLNames::aTag);
 }
 
-inline bool isHTMLAnchorElement(Element* element)
+inline bool isHTMLAnchorElement(const Element* element)
 {
     return element->hasTagName(HTMLNames::aTag);
 }
@@ -165,6 +165,8 @@ inline HTMLAnchorElement* toHTMLAnchorElement(Node* node)
     return static_cast<HTMLAnchorElement*>(node);
 }
 
+template <> inline bool isElementOfType<HTMLAnchorElement>(const Element* element) { return isHTMLAnchorElement(element); }
+
 // Functions shared with the other anchor elements (i.e., SVG).
 
 bool isEnterKeyKeydownEvent(Event*);
index 96fff13..8ffc025 100644 (file)
@@ -70,16 +70,18 @@ private:
     Shape m_shape;
 };
 
-inline bool isHTMLAreaElement(Node* node)
+inline bool isHTMLAreaElement(const Node* node)
 {
     return node->hasTagName(HTMLNames::areaTag);
 }
 
-inline bool isHTMLAreaElement(Element* element)
+inline bool isHTMLAreaElement(const Element* element)
 {
     return element->hasTagName(HTMLNames::areaTag);
 }
 
+template <> inline bool isElementOfType<HTMLAreaElement>(const Element* element) { return isHTMLAreaElement(element); }
+
 inline HTMLAreaElement* toHTMLAreaElement(Node* node)
 {
     ASSERT_WITH_SECURITY_IMPLICATION(!node || isHTMLAreaElement(node));
index 88ef7c7..1a35f47 100644 (file)
@@ -44,6 +44,18 @@ private:
     virtual void removedFrom(ContainerNode*) OVERRIDE;
 };
 
+inline bool isHTMLBaseElement(const Node* node)
+{
+    return node->hasTagName(HTMLNames::baseTag);
+}
+
+inline bool isHTMLBaseElement(const Element* element)
+{
+    return element->hasTagName(HTMLNames::baseTag);
+}
+
+template <> inline bool isElementOfType<HTMLBaseElement>(const Element* element) { return isHTMLBaseElement(element); }
+
 } // namespace
 
 #endif
index b53c1d8..0a6aa9b 100644 (file)
@@ -154,6 +154,8 @@ inline HTMLElement::HTMLElement(const QualifiedName& tagName, Document* document
     ASSERT(tagName.localName().impl());
 }
 
+template <> inline bool isElementOfType<HTMLElement>(const Element* element) { return element->isHTMLElement(); }
+
 } // namespace WebCore
 
 #endif // HTMLElement_h
index 81a98fa..45a5ac5 100644 (file)
@@ -51,10 +51,8 @@ PassRefPtr<HTMLFieldSetElement> HTMLFieldSetElement::create(const QualifiedName&
 
 void HTMLFieldSetElement::invalidateDisabledStateUnder(Element* base)
 {
-    for (Element* element = ElementTraversal::firstWithin(base); element; element = ElementTraversal::next(element, base)) {
-        if (element->isFormControlElement())
-            static_cast<HTMLFormControlElement*>(element)->ancestorDisabledStateWasChanged();
-    }
+    for (HTMLFormControlElement* control = Traversal<HTMLFormControlElement>::firstWithin(base); control; control = Traversal<HTMLFormControlElement>::next(control, base))
+        control->ancestorDisabledStateWasChanged();
 }
 
 void HTMLFieldSetElement::disabledAttributeChanged()
@@ -67,10 +65,8 @@ void HTMLFieldSetElement::disabledAttributeChanged()
 void HTMLFieldSetElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
 {
     HTMLFormControlElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
-    for (Element* element = ElementTraversal::firstWithin(this); element; element = ElementTraversal::nextSibling(element)) {
-        if (element->hasTagName(legendTag))
-            invalidateDisabledStateUnder(element);
-    }
+    for (HTMLLegendElement* legend = Traversal<HTMLLegendElement>::firstChild(this); legend; legend = Traversal<HTMLLegendElement>::nextSibling(legend))
+        invalidateDisabledStateUnder(legend);
 }
 
 bool HTMLFieldSetElement::supportsFocus() const
@@ -91,11 +87,7 @@ RenderObject* HTMLFieldSetElement::createRenderer(RenderArena* arena, RenderStyl
 
 HTMLLegendElement* HTMLFieldSetElement::legend() const
 {
-    for (Element* child = ElementTraversal::firstWithin(this); child; child = ElementTraversal::nextSibling(child)) {
-        if (child->hasTagName(legendTag))
-            return static_cast<HTMLLegendElement*>(child);
-    }
-    return 0;
+    return Traversal<HTMLLegendElement>::firstWithin(this);
 }
 
 PassRefPtr<HTMLCollection> HTMLFieldSetElement::elements()
index c44626e..0047dfb 100644 (file)
@@ -180,10 +180,12 @@ inline HTMLFormControlElement* toHTMLFormControlElement(Node* node)
     ASSERT_WITH_SECURITY_IMPLICATION(!node || isHTMLFormControlElement(node));
     return static_cast<HTMLFormControlElement*>(node);
 }
-
 // This will catch anyone doing an unnecessary cast.
 void toHTMLFormControlElement(const HTMLFormControlElement*);
 
+template <> inline bool isElementOfType<HTMLFormControlElement>(const Element* element) { return isHTMLFormControlElement(element); }
+
+
 } // namespace
 
 #endif
index 2769666..c9c089d 100644 (file)
@@ -36,19 +36,13 @@ namespace WebCore {
 
 using namespace HTMLNames;
 
-static LabelableElement* nodeAsLabelableElement(Node* node)
+static LabelableElement* nodeAsSupportedLabelableElement(Node* node)
 {
-    if (!node || !node->isHTMLElement())
+    if (!node || !isLabelableElement(node))
         return 0;
-    
-    HTMLElement* element = static_cast<HTMLElement*>(node);
-    if (!element->isLabelable())
-        return 0;
-
-    LabelableElement* labelableElement = static_cast<LabelableElement*>(element);
+    LabelableElement* labelableElement = static_cast<LabelableElement*>(node);
     if (!labelableElement->supportLabels())
         return 0;
-
     return labelableElement;
 }
 
@@ -75,9 +69,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".
-        Element* element = this;
-        while ((element = ElementTraversal::next(element, this))) {
-            if (LabelableElement* labelableElement = nodeAsLabelableElement(element))
+
+        LabelableElement* labelableElement = Traversal<LabelableElement>::firstWithin(this);
+        for (; labelableElement; labelableElement = Traversal<LabelableElement>::next(labelableElement, this)) {
+            if (labelableElement->supportLabels())
                 return labelableElement;
         }
         return 0;
@@ -85,7 +80,7 @@ LabelableElement* HTMLLabelElement::control()
     
     // Find the first element whose id is controlId. If it is found and it is a labelable form control,
     // return it, otherwise return 0.
-    return nodeAsLabelableElement(treeScope()->getElementById(controlId));
+    return nodeAsSupportedLabelableElement(treeScope()->getElementById(controlId));
 }
 
 HTMLFormElement* HTMLLabelElement::form() const
index 22366d9..ab31583 100644 (file)
@@ -55,16 +55,18 @@ private:
     virtual void focus(bool restorePreviousSelection, FocusDirection) OVERRIDE;
 };
 
-inline bool isHTMLLabelElement(Node* node)
+inline bool isHTMLLabelElement(const Node* node)
 {
     return node->hasTagName(HTMLNames::labelTag);
 }
 
-inline bool isHTMLLabelElement(Element* element)
+inline bool isHTMLLabelElement(const Element* element)
 {
     return element->hasTagName(HTMLNames::labelTag);
 }
 
+template <> inline bool isElementOfType<HTMLLabelElement>(const Element* element) { return isHTMLLabelElement(element); }
+
 inline HTMLLabelElement* toHTMLLabelElement(Node* node)
 {
     ASSERT_WITH_SECURITY_IMPLICATION(!node || isHTMLLabelElement(node));
index dcc0d38..583172a 100644 (file)
@@ -45,6 +45,18 @@ private:
     virtual HTMLFormElement* virtualForm() const OVERRIDE;
 };
 
+inline bool isHTMLLegendElement(const Node* node)
+{
+    return node->hasTagName(HTMLNames::legendTag);
+}
+
+inline bool isHTMLLegendElement(const Element* element)
+{
+    return element->hasTagName(HTMLNames::legendTag);
+}
+
+template <> inline bool isElementOfType<HTMLLegendElement>(const Element* element) { return isHTMLLegendElement(element); }
+
 } //namespace
 
 #endif
index 59befb9..9555716 100644 (file)
@@ -62,16 +62,12 @@ HTMLMapElement::~HTMLMapElement()
 bool HTMLMapElement::mapMouseEvent(LayoutPoint location, const LayoutSize& size, HitTestResult& result)
 {
     HTMLAreaElement* defaultArea = 0;
-    Element* element = this;
-    while ((element = ElementTraversal::next(element, this))) {
-        if (isHTMLAreaElement(element)) {
-            HTMLAreaElement* areaElt = toHTMLAreaElement(element);
-            if (areaElt->isDefault()) {
-                if (!defaultArea)
-                    defaultArea = areaElt;
-            } else if (areaElt->mapMouseEvent(location, size, result))
-                return true;
-        }
+    for (HTMLAreaElement* area = Traversal<HTMLAreaElement>::firstWithin(this); area; area = Traversal<HTMLAreaElement>::next(area, this)) {
+        if (area->isDefault()) {
+            if (!defaultArea)
+                defaultArea = area;
+        } else if (area->mapMouseEvent(location, size, result))
+            return true;
     }
     
     if (defaultArea) {
index 5cac762..58a6388 100644 (file)
@@ -535,12 +535,8 @@ void HTMLMediaElement::finishParsingChildren()
     if (!RuntimeEnabledFeatures::webkitVideoTrackEnabled())
         return;
 
-    for (Element* element = ElementTraversal::firstWithin(this); element; element = ElementTraversal::nextSibling(element)) {
-        if (element->hasTagName(trackTag)) {
-            scheduleDelayedAction(ConfigureTextTracks);
-            break;
-        }
-    }
+    if (Traversal<HTMLTrackElement>::firstWithin(this))
+        scheduleDelayedAction(ConfigureTextTracks);
 #endif
 }
 
index 332fe9f..dbf14d3 100644 (file)
@@ -93,12 +93,12 @@ private:
     ScopedStyleRegistrationState m_scopedStyleRegistrationState;
 };
 
-inline bool isHTMLStyleElement(Node* node)
+inline bool isHTMLStyleElement(const Node* node)
 {
     return node->hasTagName(HTMLNames::styleTag);
 }
 
-inline bool isHTMLStyleElement(Element* element)
+inline bool isHTMLStyleElement(const Element* element)
 {
     return element->hasTagName(HTMLNames::styleTag);
 }
@@ -109,6 +109,8 @@ inline HTMLStyleElement* toHTMLStyleElement(Node* node)
     return static_cast<HTMLStyleElement*>(node);
 }
 
+template <> inline bool isElementOfType<HTMLStyleElement>(const Element* element) { return isHTMLStyleElement(element); }
+
 } //namespace
 
 #endif
index 4829a52..cd23310 100644 (file)
@@ -62,6 +62,8 @@ inline HTMLTitleElement* toHTMLTitleElement(Node* node)
     return static_cast<HTMLTitleElement*>(node);
 }
 
+template <> inline bool isElementOfType<HTMLTitleElement>(const Element* element) { return isHTMLTitleElement(element); }
+
 } //namespace
 
 #endif
index 9d8eb3b..c793b34 100644 (file)
@@ -97,6 +97,19 @@ private:
     Timer<HTMLTrackElement> m_loadTimer;
 };
 
+inline bool isHTMLTrackElement(const Node* node)
+{
+    return node->hasTagName(HTMLNames::trackTag);
+}
+
+inline bool isHTMLTrackElement(const Element* element)
+{
+    return element->hasTagName(HTMLNames::trackTag);
+}
+
+template <> inline bool isElementOfType<HTMLTrackElement>(const Element* element) { return isHTMLTrackElement(element); }
+
+
 }
 
 #endif
index ffab2b1..4c7dfe6 100644 (file)
@@ -50,6 +50,15 @@ private:
     virtual bool isLabelable() const OVERRIDE FINAL { return true; }
 };
 
+inline bool isLabelableElement(const Node* node)
+{
+    if (!node->isHTMLElement())
+        return false;
+    return static_cast<const HTMLElement*>(node)->isLabelable();
+}
+
+template <> inline bool isElementOfType<LabelableElement>(const Element* element) { return isLabelableElement(element); }
+
 } // namespace WebCore
 
 #endif
index fc211f4..869a7f0 100644 (file)
@@ -160,10 +160,7 @@ PassRefPtr<FilterEffect> FilterEffectRenderer::buildReferenceFilter(RenderObject
     // This may need a spec clarification.
     RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(previousEffect, SourceAlpha::create(this));
 
-    for (Element* element = ElementTraversal::firstWithin(filter); element; element = ElementTraversal::nextSibling(element)) {
-        if (!element->isSVGElement())
-            continue;
-        SVGElement* svgElement = toSVGElement(element);
+    for (SVGElement* svgElement = Traversal<SVGElement>::firstChild(filter); svgElement; svgElement = Traversal<SVGElement>::nextSibling(svgElement)) {
         if (!svgElement->isFilterEffect())
             continue;
         SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(svgElement);
index 541e48f..0bb4074 100644 (file)
@@ -51,6 +51,7 @@
 #include "SVGRenderStyle.h"
 #include "SVGRenderSupport.h"
 #include "SVGSVGElement.h"
+#include "SVGTitleElement.h"
 #include "SVGUseElement.h"
 #include "ScriptEventListener.h"
 #include "ShadowRoot.h"
@@ -877,14 +878,8 @@ String SVGElement::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 = ElementTraversal::firstWithin(this);
-    for (; titleElement; titleElement = ElementTraversal::nextSibling(titleElement)) {
-        if (titleElement->hasTagName(SVGNames::titleTag) && titleElement->isSVGElement())
-            break;
-    }
-
     // If a title child was found, return the text contents.
-    if (titleElement)
+    if (SVGTitleElement* titleElement = Traversal<SVGTitleElement>::firstWithin(this))
         return titleElement->innerText();
 
     // Otherwise return a null/empty string.
index f833521..3dc4ff5 100644 (file)
@@ -217,6 +217,8 @@ inline const SVGElement* toSVGElement(const Node* node)
     return static_cast<const SVGElement*>(node);
 }
 
+template <> inline bool isElementOfType<SVGElement>(const Element* element) { return element->isSVGElement(); }
+
 }
 
 #endif
index 41e37d8..b0dc620 100644 (file)
@@ -25,6 +25,7 @@
 #include "SVGAnimatedLength.h"
 #include "SVGExternalResourcesRequired.h"
 #include "SVGGraphicsElement.h"
+#include "SVGNames.h"
 #include "SVGURIReference.h"
 
 namespace WebCore {
@@ -58,6 +59,19 @@ private:
     END_DECLARE_ANIMATED_PROPERTIES
 };
 
+inline bool isSVGForeignObjectElement(const Node* node)
+{
+    return node->hasTagName(SVGNames::foreignObjectTag);
+}
+
+inline bool isSVGForeignObjectElement(const Element* element)
+{
+    return element->hasTagName(SVGNames::foreignObjectTag);
+}
+
+template <> inline bool isElementOfType<SVGForeignObjectElement>(const Element* element) { return isSVGForeignObjectElement(element); }
+
+
 } // namespace WebCore
 
 #endif // ENABLE(SVG)
index c778639..551cc60 100644 (file)
@@ -342,20 +342,16 @@ void SVGSVGElement::forceRedraw()
 PassRefPtr<NodeList> SVGSVGElement::collectIntersectionOrEnclosureList(const FloatRect& rect, SVGElement* referenceElement, CollectIntersectionOrEnclosure collect) const
 {
     Vector<RefPtr<Node> > nodes;
-    Element* element = ElementTraversal::next(referenceElement ? referenceElement : this);
-    while (element) {
-        if (element->isSVGElement()) { 
-            SVGElement* svgElement = toSVGElement(element);
-            if (collect == CollectIntersectionList) {
-                if (checkIntersection(svgElement, rect))
-                    nodes.append(element);
-            } else {
-                if (checkEnclosure(svgElement, rect))
-                    nodes.append(element);
-            }
+    SVGElement* svgElement = Traversal<SVGElement>::firstWithin(referenceElement ? referenceElement : this);
+    while (svgElement) {
+        if (collect == CollectIntersectionList) {
+            if (checkIntersection(svgElement, rect))
+                nodes.append(svgElement);
+        } else {
+            if (checkEnclosure(svgElement, rect))
+                nodes.append(svgElement);
         }
-
-        element = ElementTraversal::next(element, referenceElement ? referenceElement : this);
+        svgElement = Traversal<SVGElement>::next(svgElement, referenceElement ? referenceElement : this);
     }
     return StaticNodeList::adopt(nodes);
 }
@@ -785,11 +781,7 @@ Element* SVGSVGElement::getElementById(const AtomicString& id) const
 
     // Fall back to traversing our subtree. Duplicate ids are allowed, the first found will
     // be returned.
-    for (Node* node = firstChild(); node; node = NodeTraversal::next(node, this)) {
-        if (!node->isElementNode())
-            continue;
-
-        Element* element = toElement(node);
+    for (Element* element = ElementTraversal::firstWithin(this); element; element = ElementTraversal::next(element, this)) {
         if (element->getIdAttribute() == id)
             return element;
     }
index e4de48c..92ec1d7 100644 (file)
@@ -23,6 +23,7 @@
 #if ENABLE(SVG)
 
 #include "SVGElement.h"
+#include "SVGNames.h"
 
 namespace WebCore {
 
@@ -40,6 +41,8 @@ private:
     virtual bool rendererIsNeeded(const RenderStyle&) { return false; }
 };
 
+template <> inline bool isElementOfType<SVGTitleElement>(const Element* element) { return element->hasTagName(SVGNames::titleTag); }
+
 } // namespace WebCore
 
 #endif // ENABLE(SVG)
index e63bd48..c3f90cf 100644 (file)
@@ -222,10 +222,9 @@ void SMILTimeContainer::timerFired(Timer<SMILTimeContainer>*)
 void SMILTimeContainer::updateDocumentOrderIndexes()
 {
     unsigned timingElementCount = 0;
-    for (Element* element = m_ownerSVGElement; element; element = ElementTraversal::next(element, m_ownerSVGElement)) {
-        if (SVGSMILElement::isSMILElement(element))
-            toSVGSMILElement(element)->setDocumentOrderIndex(timingElementCount++);
-    }
+    SVGSMILElement* smilElement = Traversal<SVGSMILElement>::firstWithin(m_ownerSVGElement);
+    for (; smilElement; smilElement = Traversal<SVGSMILElement>::next(smilElement, m_ownerSVGElement))
+        smilElement->setDocumentOrderIndex(timingElementCount++);
     m_documentOrderIndexesDirty = false;
 }
 
index ae2bc49..34af1c2 100644 (file)
@@ -415,7 +415,7 @@ bool SVGSMILElement::parseCondition(const String& value, BeginOrEnd beginOrEnd)
     return true;
 }
 
-bool SVGSMILElement::isSMILElement(Node* node)
+bool SVGSMILElement::isSMILElement(const Node* node)
 {
     if (!node)
         return false;
index f7150f3..3b1afce 100644 (file)
@@ -42,7 +42,7 @@ public:
     SVGSMILElement(const QualifiedName&, Document*);
     virtual ~SVGSMILElement();
 
-    static bool isSMILElement(Node*);
+    static bool isSMILElement(const Node*);
 
     bool isSupportedAttribute(const QualifiedName&);
     virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;
@@ -242,6 +242,8 @@ inline SVGSMILElement* toSVGSMILElement(Element* element)
     return static_cast<SVGSMILElement*>(element);
 }
 
+template <> inline bool isElementOfType<SVGSMILElement>(const Element* element) { return SVGSMILElement::isSMILElement(element); }
+
 }
 
 #endif // ENABLE(SVG)
index 4b30c7a..bcdbcbf 100644 (file)
@@ -40,6 +40,7 @@
 #include "RenderSVGRoot.h"
 #include "RenderStyle.h"
 #include "SVGDocument.h"
+#include "SVGForeignObjectElement.h"
 #include "SVGImageChromeClient.h"
 #include "SVGSVGElement.h"
 #include "Settings.h"
@@ -74,10 +75,8 @@ bool SVGImage::hasSingleSecurityOrigin() const
         return true;
 
     // Don't allow foreignObject elements since they can leak information with arbitrary HTML (like spellcheck or control theme).
-    for (Element* current = ElementTraversal::firstWithin(rootElement); current; current = ElementTraversal::next(current, rootElement)) {
-        if (current->hasTagName(SVGNames::foreignObjectTag))
-            return false;
-    }
+    if (Traversal<SVGForeignObjectElement>::firstWithin(rootElement))
+        return false;
 
     // Because SVG image rendering disallows external resources and links,
     // these images effectively are restricted to a single security origin.