Add common base for element iterators
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 31 Aug 2013 13:04:33 +0000 (13:04 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 31 Aug 2013 13:04:33 +0000 (13:04 +0000)
https://bugs.webkit.org/show_bug.cgi?id=120557

Reviewed by Andreas Kling.

Add ElementIterator and use it as the base for child and descendant iterators. The only difference is the definition of operator++.

Also renamed DescendantIteratorAssertions to ElementIteratorAssertions.

* GNUmakefile.list.am:
* Target.pri:
* WebCore.vcxproj/WebCore.vcxproj:
* WebCore.xcodeproj/project.pbxproj:
* dom/ChildIterator.h:
(WebCore::::ChildIterator):
(WebCore::::operator):
(WebCore::::ChildConstIterator):
(WebCore::::begin):
(WebCore::::end):
* dom/DescendantIterator.h:
(WebCore::::DescendantIterator):
(WebCore::::operator):
(WebCore::::DescendantConstIterator):
* dom/DescendantIteratorAssertions.h: Removed.
* dom/ElementIterator.h: Added.
(WebCore::::ElementIterator):
(WebCore::::traverseNext):
(WebCore::::traversePrevious):
(WebCore::::traverseNextSibling):
(WebCore::::traversePreviousSibling):
(WebCore::::operator):
(WebCore::=):
(WebCore::::ElementConstIterator):
* dom/ElementIteratorAssertions.h: Copied from Source/WebCore/dom/DescendantIteratorAssertions.h.
(WebCore::ElementIteratorAssertions::ElementIteratorAssertions):
(WebCore::ElementIteratorAssertions::domTreeHasMutated):
(WebCore::ElementIteratorAssertions::dropEventDispatchAssertion):

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

Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Target.pri
Source/WebCore/WebCore.vcxproj/WebCore.vcxproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/dom/ChildIterator.h
Source/WebCore/dom/DescendantIterator.h
Source/WebCore/dom/ElementIterator.h [new file with mode: 0644]
Source/WebCore/dom/ElementIteratorAssertions.h [moved from Source/WebCore/dom/DescendantIteratorAssertions.h with 80% similarity]

index 0a42cc4..fa59929 100644 (file)
@@ -1,3 +1,43 @@
+2013-08-31  Antti Koivisto  <antti@apple.com>
+
+        Add common base for element iterators
+        https://bugs.webkit.org/show_bug.cgi?id=120557
+
+        Reviewed by Andreas Kling.
+
+        Add ElementIterator and use it as the base for child and descendant iterators. The only difference is the definition of operator++.
+        
+        Also renamed DescendantIteratorAssertions to ElementIteratorAssertions.
+
+        * GNUmakefile.list.am:
+        * Target.pri:
+        * WebCore.vcxproj/WebCore.vcxproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * dom/ChildIterator.h:
+        (WebCore::::ChildIterator):
+        (WebCore::::operator):
+        (WebCore::::ChildConstIterator):
+        (WebCore::::begin):
+        (WebCore::::end):
+        * dom/DescendantIterator.h:
+        (WebCore::::DescendantIterator):
+        (WebCore::::operator):
+        (WebCore::::DescendantConstIterator):
+        * dom/DescendantIteratorAssertions.h: Removed.
+        * dom/ElementIterator.h: Added.
+        (WebCore::::ElementIterator):
+        (WebCore::::traverseNext):
+        (WebCore::::traversePrevious):
+        (WebCore::::traverseNextSibling):
+        (WebCore::::traversePreviousSibling):
+        (WebCore::::operator):
+        (WebCore::=):
+        (WebCore::::ElementConstIterator):
+        * dom/ElementIteratorAssertions.h: Copied from Source/WebCore/dom/DescendantIteratorAssertions.h.
+        (WebCore::ElementIteratorAssertions::ElementIteratorAssertions):
+        (WebCore::ElementIteratorAssertions::domTreeHasMutated):
+        (WebCore::ElementIteratorAssertions::dropEventDispatchAssertion):
+
 2013-08-30  Brent Fulgham  <bfulgham@apple.com>
 
         [Windows] Build fix after r154921.
index b7a8e54..da5f07e 100644 (file)
@@ -2821,7 +2821,6 @@ webcore_sources += \
        Source/WebCore/dom/default/PlatformMessagePortChannel.cpp \
        Source/WebCore/dom/default/PlatformMessagePortChannel.h \
        Source/WebCore/dom/DescendantIterator.h \
-       Source/WebCore/dom/DescendantIteratorAssertions.h \
        Source/WebCore/dom/DeviceMotionClient.h \
        Source/WebCore/dom/DeviceMotionController.cpp \
        Source/WebCore/dom/DeviceMotionController.h \
@@ -2874,6 +2873,8 @@ webcore_sources += \
        Source/WebCore/dom/Element.h \
        Source/WebCore/dom/ElementData.cpp \
        Source/WebCore/dom/ElementData.h \
+       Source/WebCore/dom/ElementIterator.h \
+       Source/WebCore/dom/ElementIteratorAssertions.h \
        Source/WebCore/dom/ElementRareData.cpp \
        Source/WebCore/dom/ElementRareData.h \
        Source/WebCore/dom/ElementTraversal.h \
index dd3dddd..dae14ff 100644 (file)
@@ -1589,7 +1589,6 @@ HEADERS += \
     dom/CustomEvent.h \
     dom/default/PlatformMessagePortChannel.h \
     dom/DescendantIterator.h \
-    dom/DescendantIteratorAssertions.h \
     dom/DeviceMotionClient.h \
     dom/DeviceMotionController.h \
     dom/DeviceMotionData.h \
@@ -1614,6 +1613,8 @@ HEADERS += \
     dom/DatasetDOMStringMap.h \
     dom/Element.h \
     dom/ElementData.h \
+    dom/ElementIterator.h \
+    dom/ElementIteratorAssertions.h \
     dom/ElementTraversal.h \
     dom/Entity.h \
     dom/EntityReference.h \
index 7f75169..2ccb74a 100644 (file)
     <ClInclude Include="..\dom\DataTransferItemList.h" />
     <ClInclude Include="..\dom\DecodedDataDocumentParser.h" />
     <ClInclude Include="..\dom\DescendantIterator.h" />
-    <ClInclude Include="..\dom\DescendantIteratorAssertions.h" />
     <ClInclude Include="..\dom\DeviceMotionClient.h" />
     <ClInclude Include="..\dom\DeviceMotionController.h" />
     <ClInclude Include="..\dom\DeviceMotionData.h" />
     <ClInclude Include="..\dom\DOMTimeStamp.h" />
     <ClInclude Include="..\dom\Element.h" />
     <ClInclude Include="..\dom\ElementData.h" />
+    <ClInclude Include="..\dom\ElementIterator.h" />
+    <ClInclude Include="..\dom\ElementIteratorAssertions.h" />
     <ClInclude Include="..\dom\ElementTraversal.h" />
     <ClInclude Include="..\dom\Entity.h" />
     <ClInclude Include="..\dom\EntityReference.h" />
index d5dbbe8..b3c10e4 100644 (file)
                E1F1E8300C3C2BB9006DB391 /* XSLTExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = E1F1E82E0C3C2BB9006DB391 /* XSLTExtensions.h */; };
                E1FF57A30F01255B00891EBB /* ThreadGlobalData.h in Headers */ = {isa = PBXBuildFile; fileRef = E1FF57A20F01255B00891EBB /* ThreadGlobalData.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E1FF57A60F01256B00891EBB /* ThreadGlobalData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1FF57A50F01256B00891EBB /* ThreadGlobalData.cpp */; };
-               E401C27517CE53EC00C41A35 /* DescendantIteratorAssertions.h in Headers */ = {isa = PBXBuildFile; fileRef = E401C27417CE53EC00C41A35 /* DescendantIteratorAssertions.h */; };
+               E401C27517CE53EC00C41A35 /* ElementIteratorAssertions.h in Headers */ = {isa = PBXBuildFile; fileRef = E401C27417CE53EC00C41A35 /* ElementIteratorAssertions.h */; };
                E4295FA412B0614E00D1ACE0 /* ResourceLoadPriority.h in Headers */ = {isa = PBXBuildFile; fileRef = E4295FA312B0614E00D1ACE0 /* ResourceLoadPriority.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E43105B816750F0C00DB2FB8 /* NodeTraversal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43105B716750F0C00DB2FB8 /* NodeTraversal.cpp */; };
                E43105BB16750F1600DB2FB8 /* NodeTraversal.h in Headers */ = {isa = PBXBuildFile; fileRef = E43105BA16750F1600DB2FB8 /* NodeTraversal.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E4946EAF156E64DD00D3297F /* StyleRuleImport.h in Headers */ = {isa = PBXBuildFile; fileRef = E4946EAD156E64DD00D3297F /* StyleRuleImport.h */; };
                E49BD9FA131FD2ED003C56F0 /* CSSValuePool.h in Headers */ = {isa = PBXBuildFile; fileRef = E49BD9F9131FD2ED003C56F0 /* CSSValuePool.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E49BDA0B131FD3E5003C56F0 /* CSSValuePool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E49BDA0A131FD3E5003C56F0 /* CSSValuePool.cpp */; };
+               E4AE7C1617D1BB950009FB31 /* ElementIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AE7C1517D1BB950009FB31 /* ElementIterator.h */; };
                E4AFCFA50DAF29A300F5F55C /* UnitBezier.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AFCFA40DAF29A300F5F55C /* UnitBezier.h */; };
                E4AFD00B0DAF335400F5F55C /* SMILTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4AFD0050DAF335400F5F55C /* SMILTime.cpp */; };
                E4AFD00C0DAF335400F5F55C /* SMILTime.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AFD0060DAF335400F5F55C /* SMILTime.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E1F1E82E0C3C2BB9006DB391 /* XSLTExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XSLTExtensions.h; sourceTree = "<group>"; };
                E1FF57A20F01255B00891EBB /* ThreadGlobalData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadGlobalData.h; sourceTree = "<group>"; };
                E1FF57A50F01256B00891EBB /* ThreadGlobalData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadGlobalData.cpp; sourceTree = "<group>"; };
-               E401C27417CE53EC00C41A35 /* DescendantIteratorAssertions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DescendantIteratorAssertions.h; sourceTree = "<group>"; };
+               E401C27417CE53EC00C41A35 /* ElementIteratorAssertions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementIteratorAssertions.h; sourceTree = "<group>"; };
                E406F3FB1198307D009D59D6 /* ColorData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ColorData.cpp; sourceTree = "<group>"; };
                E41EA038119836DB00710BC5 /* CSSPropertyNames.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSPropertyNames.cpp; sourceTree = "<group>"; };
                E41EA0391198374900710BC5 /* CSSValueKeywords.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSValueKeywords.cpp; sourceTree = "<group>"; };
                E4946EAD156E64DD00D3297F /* StyleRuleImport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleRuleImport.h; sourceTree = "<group>"; };
                E49BD9F9131FD2ED003C56F0 /* CSSValuePool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSValuePool.h; sourceTree = "<group>"; };
                E49BDA0A131FD3E5003C56F0 /* CSSValuePool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSValuePool.cpp; sourceTree = "<group>"; };
+               E4AE7C1517D1BB950009FB31 /* ElementIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementIterator.h; sourceTree = "<group>"; };
                E4AFCFA40DAF29A300F5F55C /* UnitBezier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnitBezier.h; sourceTree = "<group>"; };
                E4AFD0050DAF335400F5F55C /* SMILTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SMILTime.cpp; sourceTree = "<group>"; };
                E4AFD0060DAF335400F5F55C /* SMILTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SMILTime.h; sourceTree = "<group>"; };
                                A8C228A011D5722E00D5A7D3 /* DecodedDataDocumentParser.cpp */,
                                A8C2289F11D5722E00D5A7D3 /* DecodedDataDocumentParser.h */,
                                E46A2B1B17CA65B9000DBCD8 /* DescendantIterator.h */,
-                               E401C27417CE53EC00C41A35 /* DescendantIteratorAssertions.h */,
                                31FB1A4F120A5D0600DC02A0 /* DeviceMotionClient.h */,
                                31FB1A50120A5D0600DC02A0 /* DeviceMotionController.cpp */,
                                31FB1A51120A5D0600DC02A0 /* DeviceMotionController.h */,
                                B5B7A16E17C1048000E4AA0A /* ElementData.h */,
                                4FAB48641643A66D00F70C07 /* ElementRareData.cpp */,
                                637B7ADE0E8767B800E32194 /* ElementRareData.h */,
+                               E4AE7C1517D1BB950009FB31 /* ElementIterator.h */,
+                               E401C27417CE53EC00C41A35 /* ElementIteratorAssertions.h */,
                                E4D58EBA17B8F12800CBDCA8 /* ElementTraversal.h */,
                                A8EA7EBA0A1945D000A8EF5F /* Entity.h */,
                                93EEC1EB09C2877700C515D1 /* Entity.idl */,
                                976D6C7F122B8A3D001FD1F7 /* BlobURL.h in Headers */,
                                93F199BE08245E59001E9ABC /* BlockExceptions.h in Headers */,
                                BC5EB5E10E81BE8700B25965 /* BorderData.h in Headers */,
-                               E401C27517CE53EC00C41A35 /* DescendantIteratorAssertions.h in Headers */,
+                               E401C27517CE53EC00C41A35 /* ElementIteratorAssertions.h in Headers */,
                                BC5EB5DB0E81B7EA00B25965 /* BorderValue.h in Headers */,
                                BCEA4855097D93020094C9E4 /* break_lines.h in Headers */,
                                93309DDB099E64920056E581 /* BreakBlockquoteCommand.h in Headers */,
                                B2227AB60D00BF220071B782 /* SVGGraphicsElement.h in Headers */,
                                650FBF2B0D9AF047008FC292 /* SVGHKernElement.h in Headers */,
                                B25599A40D00D8BA00BB825C /* SVGImage.h in Headers */,
+                               E4AE7C1617D1BB950009FB31 /* ElementIterator.h in Headers */,
                                08F859D51463F9CD0067D933 /* SVGImageCache.h in Headers */,
                                AAC08CEF15F933D600F1E188 /* SVGImageChromeClient.h in Headers */,
                                B2227A2D0D00BF220071B782 /* SVGImageElement.h in Headers */,
index 0c0b4de..afd5016 100644 (file)
 #ifndef ChildIterator_h
 #define ChildIterator_h
 
-#include "ElementTraversal.h"
-
-#if !ASSERT_DISABLED
-#include "DescendantIteratorAssertions.h"
-#endif
+#include "ElementIterator.h"
 
 namespace WebCore {
 
 template <typename ElementType>
-class ChildIterator {
+class ChildIterator : public ElementIterator<ElementType> {
 public:
-    ChildIterator();
-    ChildIterator(ElementType* current);
+    ChildIterator(const ContainerNode* root);
+    ChildIterator(const ContainerNode* root, ElementType* current);
     ChildIterator& operator++();
-    ElementType& operator*();
-    ElementType* operator->();
-    bool operator!=(const ChildIterator& other) const;
-
-private:
-    ElementType* m_current;
-
-#if !ASSERT_DISABLED
-    DescendantIteratorAssertions m_assertions;
-#endif
 };
 
 template <typename ElementType>
-class ChildConstIterator {
+class ChildConstIterator : public ElementConstIterator<ElementType> {
 public:
-    ChildConstIterator();
-    ChildConstIterator(const ElementType* current);
+    ChildConstIterator(const ContainerNode* root);
+    ChildConstIterator(const ContainerNode* root, const ElementType* current);
     ChildConstIterator& operator++();
-    const ElementType& operator*() const;
-    const ElementType* operator->() const;
-    bool operator!=(const ChildConstIterator& other) const;
-
-private:
-    const ElementType* m_current;
-
-#if !ASSERT_DISABLED
-    DescendantIteratorAssertions m_assertions;
-#endif
 };
 
 template <typename ElementType>
@@ -100,109 +76,41 @@ template <typename ElementType> ChildConstIteratorAdapter<ElementType> childrenO
 // ChildIterator
 
 template <typename ElementType>
-inline ChildIterator<ElementType>::ChildIterator()
-    : m_current(nullptr)
+inline ChildIterator<ElementType>::ChildIterator(const ContainerNode* root)
+    : ElementIterator<ElementType>(root)
 {
 }
 
 template <typename ElementType>
-inline ChildIterator<ElementType>::ChildIterator(ElementType* current)
-    : m_current(current)
-#if !ASSERT_DISABLED
-    , m_assertions(current)
-#endif
+inline ChildIterator<ElementType>::ChildIterator(const ContainerNode* root, ElementType* current)
+    : ElementIterator<ElementType>(root, current)
 {
 }
 
 template <typename ElementType>
 inline ChildIterator<ElementType>& ChildIterator<ElementType>::operator++()
 {
-    ASSERT(m_current);
-    ASSERT(!m_assertions.domTreeHasMutated());
-    m_current = Traversal<ElementType>::nextSibling(m_current);
-#if !ASSERT_DISABLED
-    // Drop the assertion when the iterator reaches the end.
-    if (!m_current)
-        m_assertions.dropEventDispatchAssertion();
-#endif
-    return *this;
-}
-
-template <typename ElementType>
-inline ElementType& ChildIterator<ElementType>::operator*()
-{
-    ASSERT(m_current);
-    ASSERT(!m_assertions.domTreeHasMutated());
-    return *m_current;
-}
-
-template <typename ElementType>
-inline ElementType* ChildIterator<ElementType>::operator->()
-{
-    ASSERT(m_current);
-    ASSERT(!m_assertions.domTreeHasMutated());
-    return m_current;
-}
-
-template <typename ElementType>
-inline bool ChildIterator<ElementType>::operator!=(const ChildIterator& other) const
-{
-    ASSERT(!m_assertions.domTreeHasMutated());
-    return m_current != other.m_current;
+    return static_cast<ChildIterator<ElementType>&>(ElementIterator<ElementType>::traverseNextSibling());
 }
 
 // ChildConstIterator
 
 template <typename ElementType>
-inline ChildConstIterator<ElementType>::ChildConstIterator()
-    : m_current(nullptr)
+inline ChildConstIterator<ElementType>::ChildConstIterator(const ContainerNode* root)
+    : ElementConstIterator<ElementType>(root)
 {
 }
 
 template <typename ElementType>
-inline ChildConstIterator<ElementType>::ChildConstIterator(const ElementType* current)
-    : m_current(current)
-#if !ASSERT_DISABLED
-    , m_assertions(current)
-#endif
+inline ChildConstIterator<ElementType>::ChildConstIterator(const ContainerNode* root, const ElementType* current)
+    : ElementConstIterator<ElementType>(root, current)
 {
 }
 
 template <typename ElementType>
 inline ChildConstIterator<ElementType>& ChildConstIterator<ElementType>::operator++()
 {
-    ASSERT(m_current);
-    ASSERT(!m_assertions.domTreeHasMutated());
-    m_current = Traversal<ElementType>::nextSibling(m_current);
-#if !ASSERT_DISABLED
-    // Drop the assertion when the iterator reaches the end.
-    if (!m_current)
-        m_assertions.dropEventDispatchAssertion();
-#endif
-    return *this;
-}
-
-template <typename ElementType>
-inline const ElementType& ChildConstIterator<ElementType>::operator*() const
-{
-    ASSERT(m_current);
-    ASSERT(!m_assertions.domTreeHasMutated());
-    return *m_current;
-}
-
-template <typename ElementType>
-inline const ElementType* ChildConstIterator<ElementType>::operator->() const
-{
-    ASSERT(m_current);
-    ASSERT(!m_assertions.domTreeHasMutated());
-    return m_current;
-}
-
-template <typename ElementType>
-inline bool ChildConstIterator<ElementType>::operator!=(const ChildConstIterator& other) const
-{
-    ASSERT(!m_assertions.domTreeHasMutated());
-    return m_current != other.m_current;
+    return static_cast<ChildConstIterator<ElementType>&>(ElementConstIterator<ElementType>::traverseNextSibling());
 }
 
 // ChildIteratorAdapter
@@ -216,13 +124,13 @@ inline ChildIteratorAdapter<ElementType>::ChildIteratorAdapter(ContainerNode* ro
 template <typename ElementType>
 inline ChildIterator<ElementType> ChildIteratorAdapter<ElementType>::begin()
 {
-    return ChildIterator<ElementType>(Traversal<ElementType>::firstChild(m_root));
+    return ChildIterator<ElementType>(m_root, Traversal<ElementType>::firstChild(m_root));
 }
 
 template <typename ElementType>
 inline ChildIterator<ElementType> ChildIteratorAdapter<ElementType>::end()
 {
-    return ChildIterator<ElementType>();
+    return ChildIterator<ElementType>(m_root);
 }
 
 // ChildConstIteratorAdapter
@@ -236,13 +144,13 @@ inline ChildConstIteratorAdapter<ElementType>::ChildConstIteratorAdapter(const C
 template <typename ElementType>
 inline ChildConstIterator<ElementType> ChildConstIteratorAdapter<ElementType>::begin() const
 {
-    return ChildConstIterator<ElementType>(Traversal<ElementType>::firstChild(m_root));
+    return ChildConstIterator<ElementType>(m_root, Traversal<ElementType>::firstChild(m_root));
 }
 
 template <typename ElementType>
 inline ChildConstIterator<ElementType> ChildConstIteratorAdapter<ElementType>::end() const
 {
-    return ChildConstIterator<ElementType>();
+    return ChildConstIterator<ElementType>(m_root);
 }
 
 // Standalone functions
index 1f3463d..70b7fd1 100644 (file)
 #ifndef DescendantIterator_h
 #define DescendantIterator_h
 
-#include "ElementTraversal.h"
-
-#if !ASSERT_DISABLED
-#include "DescendantIteratorAssertions.h"
-#endif
+#include "ElementIterator.h"
 
 namespace WebCore {
 
 template <typename ElementType>
-class DescendantIterator {
+class DescendantIterator : public ElementIterator<ElementType> {
 public:
     DescendantIterator(const ContainerNode* root);
     DescendantIterator(const ContainerNode* root, ElementType* current);
     DescendantIterator& operator++();
-    ElementType& operator*();
-    ElementType* operator->();
-    bool operator!=(const DescendantIterator& other) const;
-
-private:
-    const ContainerNode* m_root;
-    ElementType* m_current;
-
-#if !ASSERT_DISABLED
-    DescendantIteratorAssertions m_assertions;
-#endif
 };
 
 template <typename ElementType>
-class DescendantConstIterator {
+class DescendantConstIterator : public ElementConstIterator<ElementType>  {
 public:
     DescendantConstIterator(const ContainerNode* root);
     DescendantConstIterator(const ContainerNode* root, const ElementType* current);
     DescendantConstIterator& operator++();
-    const ElementType& operator*() const;
-    const ElementType* operator->() const;
-    bool operator!=(const DescendantConstIterator& other) const;
-
-private:
-    const ContainerNode* m_root;
-    const ElementType* m_current;
-
-#if !ASSERT_DISABLED
-    DescendantIteratorAssertions m_assertions;
-#endif
 };
 
 template <typename ElementType>
@@ -103,114 +77,41 @@ template <typename ElementType> DescendantConstIteratorAdapter<ElementType> desc
 
 template <typename ElementType>
 inline DescendantIterator<ElementType>::DescendantIterator(const ContainerNode* root)
-    : m_root(root)
-    , m_current(nullptr)
+    : ElementIterator<ElementType>(root)
 {
 }
 
 template <typename ElementType>
 inline DescendantIterator<ElementType>::DescendantIterator(const ContainerNode* root, ElementType* current)
-    : m_root(root)
-    , m_current(current)
-#if !ASSERT_DISABLED
-    , m_assertions(current)
-#endif
+    : ElementIterator<ElementType>(root, current)
 {
 }
 
 template <typename ElementType>
 inline DescendantIterator<ElementType>& DescendantIterator<ElementType>::operator++()
 {
-    ASSERT(m_current);
-    ASSERT(!m_assertions.domTreeHasMutated());
-    m_current = Traversal<ElementType>::next(m_current, m_root);
-#if !ASSERT_DISABLED
-    // Drop the assertion when the iterator reaches the end.
-    if (!m_current)
-        m_assertions.dropEventDispatchAssertion();
-#endif
-    return *this;
-}
-
-template <typename ElementType>
-inline ElementType& DescendantIterator<ElementType>::operator*()
-{
-    ASSERT(m_current);
-    ASSERT(!m_assertions.domTreeHasMutated());
-    return *m_current;
-}
-
-template <typename ElementType>
-inline ElementType* DescendantIterator<ElementType>::operator->()
-{
-    ASSERT(m_current);
-    ASSERT(!m_assertions.domTreeHasMutated());
-    return m_current;
-}
-
-template <typename ElementType>
-inline bool DescendantIterator<ElementType>::operator!=(const DescendantIterator& other) const
-{
-    ASSERT(m_root == other.m_root);
-    ASSERT(!m_assertions.domTreeHasMutated());
-    return m_current != other.m_current;
+    return static_cast<DescendantIterator<ElementType>&>(ElementIterator<ElementType>::traverseNext());
 }
 
 // DescendantConstIterator
 
 template <typename ElementType>
 inline DescendantConstIterator<ElementType>::DescendantConstIterator(const ContainerNode* root)
-    : m_root(root)
-    , m_current(nullptr)
+    : ElementConstIterator<ElementType>(root)
+
 {
 }
 
 template <typename ElementType>
 inline DescendantConstIterator<ElementType>::DescendantConstIterator(const ContainerNode* root, const ElementType* current)
-    : m_root(root)
-    , m_current(current)
-#if !ASSERT_DISABLED
-    , m_assertions(current)
-#endif
+    : ElementConstIterator<ElementType>(root, current)
 {
 }
 
 template <typename ElementType>
 inline DescendantConstIterator<ElementType>& DescendantConstIterator<ElementType>::operator++()
 {
-    ASSERT(m_current);
-    ASSERT(!m_assertions.domTreeHasMutated());
-    m_current = Traversal<ElementType>::next(m_current, m_root);
-#if !ASSERT_DISABLED
-    // Drop the assertion when the iterator reaches the end.
-    if (!m_current)
-        m_assertions.dropEventDispatchAssertion();
-#endif
-    return *this;
-}
-
-template <typename ElementType>
-inline const ElementType& DescendantConstIterator<ElementType>::operator*() const
-{
-    ASSERT(m_current);
-    ASSERT(!m_assertions.domTreeHasMutated());
-    return *m_current;
-}
-
-template <typename ElementType>
-inline const ElementType* DescendantConstIterator<ElementType>::operator->() const
-{
-    ASSERT(m_current);
-    ASSERT(!m_assertions.domTreeHasMutated());
-    return m_current;
-}
-
-template <typename ElementType>
-inline bool DescendantConstIterator<ElementType>::operator!=(const DescendantConstIterator& other) const
-{
-    ASSERT(m_root == other.m_root);
-    ASSERT(!m_assertions.domTreeHasMutated());
-    return m_current != other.m_current;
+    return static_cast<DescendantConstIterator<ElementType>&>(ElementConstIterator<ElementType>::traverseNext());
 }
 
 // DescendantIteratorAdapter
diff --git a/Source/WebCore/dom/ElementIterator.h b/Source/WebCore/dom/ElementIterator.h
new file mode 100644 (file)
index 0000000..d35725e
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ElementIterator_h
+#define ElementIterator_h
+
+#include "ElementTraversal.h"
+
+#if !ASSERT_DISABLED
+#include "ElementIteratorAssertions.h"
+#endif
+
+namespace WebCore {
+
+template <typename ElementType>
+class ElementIterator {
+public:
+    ElementIterator(const ContainerNode* root);
+    ElementIterator(const ContainerNode* root, ElementType* current);
+
+    ElementType& operator*();
+    ElementType* operator->();
+
+    bool operator!=(const ElementIterator& other) const;
+
+    ElementIterator& traverseNext();
+    ElementIterator& traversePrevious();
+    ElementIterator& traverseNextSibling();
+    ElementIterator& traversePreviousSibling();
+
+private:
+    const ContainerNode* m_root;
+    ElementType* m_current;
+
+#if !ASSERT_DISABLED
+    ElementIteratorAssertions m_assertions;
+#endif
+};
+
+template <typename ElementType>
+class ElementConstIterator {
+public:
+    ElementConstIterator(const ContainerNode* root);
+    ElementConstIterator(const ContainerNode* root, const ElementType* current);
+
+    const ElementType& operator*() const;
+    const ElementType* operator->() const;
+
+    bool operator!=(const ElementConstIterator& other) const;
+
+    ElementConstIterator& traverseNext();
+    ElementConstIterator& traversePrevious();
+    ElementConstIterator& traverseNextSibling();
+    ElementConstIterator& traversePreviousSibling();
+
+private:
+    const ContainerNode* m_root;
+    const ElementType* m_current;
+
+#if !ASSERT_DISABLED
+    ElementIteratorAssertions m_assertions;
+#endif
+};
+
+// ElementIterator
+
+template <typename ElementType>
+inline ElementIterator<ElementType>::ElementIterator(const ContainerNode* root)
+    : m_root(root)
+    , m_current(nullptr)
+{
+}
+
+template <typename ElementType>
+inline ElementIterator<ElementType>::ElementIterator(const ContainerNode* root, ElementType* current)
+    : m_root(root)
+    , m_current(current)
+#if !ASSERT_DISABLED
+    , m_assertions(current)
+#endif
+{
+}
+
+template <typename ElementType>
+inline ElementIterator<ElementType>& ElementIterator<ElementType>::traverseNext()
+{
+    ASSERT(m_current);
+    ASSERT(!m_assertions.domTreeHasMutated());
+    m_current = Traversal<ElementType>::next(m_current, m_root);
+#if !ASSERT_DISABLED
+    // Drop the assertion when the iterator reaches the end.
+    if (!m_current)
+        m_assertions.dropEventDispatchAssertion();
+#endif
+    return *this;
+}
+
+template <typename ElementType>
+inline ElementIterator<ElementType>& ElementIterator<ElementType>::traversePrevious()
+{
+    ASSERT(m_current);
+    ASSERT(!m_assertions.domTreeHasMutated());
+    m_current = Traversal<ElementType>::previous(m_current, m_root);
+#if !ASSERT_DISABLED
+    // Drop the assertion when the iterator reaches the end.
+    if (!m_current)
+        m_assertions.dropEventDispatchAssertion();
+#endif
+    return *this;
+}
+
+template <typename ElementType>
+inline ElementIterator<ElementType>& ElementIterator<ElementType>::traverseNextSibling()
+{
+    ASSERT(m_current);
+    ASSERT(!m_assertions.domTreeHasMutated());
+    m_current = Traversal<ElementType>::nextSibling(m_current);
+#if !ASSERT_DISABLED
+    // Drop the assertion when the iterator reaches the end.
+    if (!m_current)
+        m_assertions.dropEventDispatchAssertion();
+#endif
+    return *this;
+}
+
+template <typename ElementType>
+inline ElementIterator<ElementType>& ElementIterator<ElementType>::traversePreviousSibling()
+{
+    ASSERT(m_current);
+    ASSERT(!m_assertions.domTreeHasMutated());
+    m_current = Traversal<ElementType>::previousSibling(m_current);
+#if !ASSERT_DISABLED
+    // Drop the assertion when the iterator reaches the end.
+    if (!m_current)
+        m_assertions.dropEventDispatchAssertion();
+#endif
+    return *this;
+}
+
+template <typename ElementType>
+inline ElementType& ElementIterator<ElementType>::operator*()
+{
+    ASSERT(m_current);
+    ASSERT(!m_assertions.domTreeHasMutated());
+    return *m_current;
+}
+
+template <typename ElementType>
+inline ElementType* ElementIterator<ElementType>::operator->()
+{
+    ASSERT(m_current);
+    ASSERT(!m_assertions.domTreeHasMutated());
+    return m_current;
+}
+
+template <typename ElementType>
+inline bool ElementIterator<ElementType>::operator!=(const ElementIterator& other) const
+{
+    ASSERT(m_root == other.m_root);
+    ASSERT(!m_assertions.domTreeHasMutated());
+    return m_current != other.m_current;
+}
+
+// ElementConstIterator
+
+template <typename ElementType>
+inline ElementConstIterator<ElementType>::ElementConstIterator(const ContainerNode* root)
+    : m_root(root)
+    , m_current(nullptr)
+{
+}
+
+template <typename ElementType>
+inline ElementConstIterator<ElementType>::ElementConstIterator(const ContainerNode* root, const ElementType* current)
+    : m_root(root)
+    , m_current(current)
+#if !ASSERT_DISABLED
+    , m_assertions(current)
+#endif
+{
+}
+
+template <typename ElementType>
+inline ElementConstIterator<ElementType>& ElementConstIterator<ElementType>::traverseNext()
+{
+    ASSERT(m_current);
+    ASSERT(!m_assertions.domTreeHasMutated());
+    m_current = Traversal<ElementType>::next(m_current, m_root);
+#if !ASSERT_DISABLED
+    // Drop the assertion when the iterator reaches the end.
+    if (!m_current)
+        m_assertions.dropEventDispatchAssertion();
+#endif
+    return *this;
+}
+
+template <typename ElementType>
+inline ElementConstIterator<ElementType>& ElementConstIterator<ElementType>::traversePrevious()
+{
+    ASSERT(m_current);
+    ASSERT(!m_assertions.domTreeHasMutated());
+    m_current = Traversal<ElementType>::previous(m_current, m_root);
+#if !ASSERT_DISABLED
+    // Drop the assertion when the iterator reaches the end.
+    if (!m_current)
+        m_assertions.dropEventDispatchAssertion();
+#endif
+    return *this;
+}
+
+template <typename ElementType>
+inline ElementConstIterator<ElementType>& ElementConstIterator<ElementType>::traverseNextSibling()
+{
+    ASSERT(m_current);
+    ASSERT(!m_assertions.domTreeHasMutated());
+    m_current = Traversal<ElementType>::nextSibling(m_current);
+#if !ASSERT_DISABLED
+    // Drop the assertion when the iterator reaches the end.
+    if (!m_current)
+        m_assertions.dropEventDispatchAssertion();
+#endif
+    return *this;
+}
+
+template <typename ElementType>
+inline ElementConstIterator<ElementType>& ElementConstIterator<ElementType>::traversePreviousSibling()
+{
+    ASSERT(m_current);
+    ASSERT(!m_assertions.domTreeHasMutated());
+    m_current = Traversal<ElementType>::previousSibling(m_current);
+#if !ASSERT_DISABLED
+    // Drop the assertion when the iterator reaches the end.
+    if (!m_current)
+        m_assertions.dropEventDispatchAssertion();
+#endif
+    return *this;
+}
+
+template <typename ElementType>
+inline const ElementType& ElementConstIterator<ElementType>::operator*() const
+{
+    ASSERT(m_current);
+    ASSERT(!m_assertions.domTreeHasMutated());
+    return *m_current;
+}
+
+template <typename ElementType>
+inline const ElementType* ElementConstIterator<ElementType>::operator->() const
+{
+    ASSERT(m_current);
+    ASSERT(!m_assertions.domTreeHasMutated());
+    return m_current;
+}
+
+template <typename ElementType>
+inline bool ElementConstIterator<ElementType>::operator!=(const ElementConstIterator& other) const
+{
+    ASSERT(m_root == other.m_root);
+    ASSERT(!m_assertions.domTreeHasMutated());
+    return m_current != other.m_current;
+}
+
+}
+
+#endif
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef DescendantIteratorAssertions_h
-#define DescendantIteratorAssertions_h
+#ifndef ElementIteratorAssertions_h
+#define ElementIteratorAssertions_h
 
 #include "Document.h"
 #include "Element.h"
 
 namespace WebCore {
 
-class DescendantIteratorAssertions {
+class ElementIteratorAssertions {
 public:
-    DescendantIteratorAssertions();
-    DescendantIteratorAssertions(const Element* first);
+    ElementIteratorAssertions();
+    ElementIteratorAssertions(const Element* first);
     bool domTreeHasMutated() const;
     void dropEventDispatchAssertion();
 
@@ -44,25 +44,25 @@ private:
     OwnPtr<NoEventDispatchAssertion> m_noEventDispatchAssertion;
 };
 
-inline DescendantIteratorAssertions::DescendantIteratorAssertions()
+inline ElementIteratorAssertions::ElementIteratorAssertions()
     : m_document(nullptr)
     , m_initialDOMTreeVersion(0)
 {
 }
 
-inline DescendantIteratorAssertions::DescendantIteratorAssertions(const Element* first)
+inline ElementIteratorAssertions::ElementIteratorAssertions(const Element* first)
     : m_document(first ? &first->document() : nullptr)
     , m_initialDOMTreeVersion(m_document ? m_document->domTreeVersion() : 0)
     , m_noEventDispatchAssertion(m_document ? adoptPtr(new NoEventDispatchAssertion) : nullptr)
 {
 }
 
-inline bool DescendantIteratorAssertions::domTreeHasMutated() const
+inline bool ElementIteratorAssertions::domTreeHasMutated() const
 {
     return m_initialDOMTreeVersion && m_document && m_document->domTreeVersion() != m_initialDOMTreeVersion;
 }
 
-inline void DescendantIteratorAssertions::dropEventDispatchAssertion()
+inline void ElementIteratorAssertions::dropEventDispatchAssertion()
 {
     m_noEventDispatchAssertion = nullptr;
 }