Changeset 154940 in webkit
- Timestamp:
- Sep 1, 2013, 3:33:08 AM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 1 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r154939 r154940 1 2013-08-31 Antti Koivisto <antti@apple.com> 2 3 Add element ancestor iterator 4 https://bugs.webkit.org/show_bug.cgi?id=120563 5 6 Reviewed by Andreas Kling. 7 8 This patch adds ancestor iterators. They iterate over elements parent chain up to the root. 9 10 To iterate over Element ancestors: 11 12 auto ancestors = elementAncestors(this); 13 for (auto it = ancestors.begin(), end = ancestors.end(); it != end; ++it) { 14 Element& element = *it; 15 ... 16 17 To iterate over Element ancestors including the current element: 18 19 auto lineage = elementLineage(this); 20 for (auto it = lineage.begin(), end = lineage.end(); it != end; ++it) { 21 Element& element = *it; 22 ... 23 24 To iterate over ancestors of a specific Element subclass: 25 26 auto htmlAncestors = ancestorsOfType<HTMLElement>(this); 27 for (auto it = htmlAncestors.begin(), end = htmlAncestors.end(); it != end; ++it) { 28 HTMLElement& htmlElement = *it; 29 ... 30 31 To iterate over ancestors of a specific Element subclass including the current element: 32 33 auto htmlLineage = lineageOfType<HTMLElement>(this); 34 for (auto it = htmlLineage.begin(), end = htmlLineage.end(); it != end; ++it) { 35 HTMLElement& htmlElement = *it; 36 ... 37 38 The patch also uses the new types in a few places. 39 40 * WebCore.xcodeproj/project.pbxproj: 41 * accessibility/AccessibilityNodeObject.cpp: 42 (WebCore::AccessibilityNodeObject::mouseButtonListener): 43 (WebCore::AccessibilityNodeObject::labelForElement): 44 * dom/ElementAncestorIterator.h: Added. 45 (WebCore::::ElementAncestorIterator): 46 (WebCore::::operator): 47 (WebCore::::ElementAncestorConstIterator): 48 (WebCore::::ElementAncestorIteratorAdapter): 49 (WebCore::::begin): 50 (WebCore::::end): 51 (WebCore::::ElementAncestorConstIteratorAdapter): 52 (WebCore::elementLineage): 53 (WebCore::elementAncestors): 54 (WebCore::ancestorsOfType): 55 * dom/ElementIterator.h: 56 (WebCore::findElementAncestorOfType): 57 (WebCore::::traverseAncestor): 58 (WebCore::=): 59 * html/HTMLElement.cpp: 60 (WebCore::HTMLElement::adjustDirectionalityIfNeededAfterChildAttributeChanged): 61 * html/HTMLFieldSetElement.h: 62 (WebCore::isHTMLFieldSetElement): 63 (WebCore::HTMLFieldSetElement): 64 * html/HTMLFrameSetElement.cpp: 65 (WebCore::HTMLFrameSetElement::findContaining): 66 * html/HTMLFrameSetElement.h: 67 (WebCore::HTMLFrameSetElement): 68 * html/HTMLInputElement.h: 69 (WebCore::isHTMLInputElement): 70 (WebCore::toHTMLInputElement): 71 * html/HTMLLegendElement.cpp: 72 (WebCore::HTMLLegendElement::associatedControl): 73 1 74 2013-08-31 Darin Adler <darin@apple.com> 2 75 -
trunk/Source/WebCore/GNUmakefile.list.am
r154928 r154940 2870 2870 Source/WebCore/dom/Element.cpp \ 2871 2871 Source/WebCore/dom/Element.h \ 2872 Source/WebCore/dom/ElementAncestorIterator.h \ 2872 2873 Source/WebCore/dom/ElementChildIterator.h \ 2873 2874 Source/WebCore/dom/ElementData.cpp \ -
trunk/Source/WebCore/Target.pri
r154928 r154940 1611 1611 dom/DatasetDOMStringMap.h \ 1612 1612 dom/Element.h \ 1613 dom/ElementAncestorIterator.h \ 1613 1614 dom/ElementChildIterator.h \ 1614 1615 dom/ElementData.h \ -
trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj
r154928 r154940 1 <?xml version="1.0" encoding="utf-8"?>1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 3 3 <ItemGroup Label="ProjectConfigurations"> … … 20263 20263 <ClInclude Include="..\dom\DOMTimeStamp.h" /> 20264 20264 <ClInclude Include="..\dom\Element.h" /> 20265 <ClInclude Include="..\dom\ElementAncestorIterator.h" /> 20265 20266 <ClInclude Include="..\dom\ElementChildIterator.h" /> 20266 20267 <ClInclude Include="..\dom\ElementData.h" /> -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r154928 r154940 5507 5507 E49BDA0B131FD3E5003C56F0 /* CSSValuePool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E49BDA0A131FD3E5003C56F0 /* CSSValuePool.cpp */; }; 5508 5508 E4AE7C1617D1BB950009FB31 /* ElementIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AE7C1517D1BB950009FB31 /* ElementIterator.h */; }; 5509 E4AE7C1A17D232350009FB31 /* ElementAncestorIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AE7C1917D232350009FB31 /* ElementAncestorIterator.h */; }; 5509 5510 E4AFCFA50DAF29A300F5F55C /* UnitBezier.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AFCFA40DAF29A300F5F55C /* UnitBezier.h */; }; 5510 5511 E4AFD00B0DAF335400F5F55C /* SMILTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4AFD0050DAF335400F5F55C /* SMILTime.cpp */; }; … … 12281 12282 E49BDA0A131FD3E5003C56F0 /* CSSValuePool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSValuePool.cpp; sourceTree = "<group>"; }; 12282 12283 E4AE7C1517D1BB950009FB31 /* ElementIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementIterator.h; sourceTree = "<group>"; }; 12284 E4AE7C1917D232350009FB31 /* ElementAncestorIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementAncestorIterator.h; sourceTree = "<group>"; }; 12283 12285 E4AFCFA40DAF29A300F5F55C /* UnitBezier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnitBezier.h; sourceTree = "<group>"; }; 12284 12286 E4AFD0050DAF335400F5F55C /* SMILTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SMILTime.cpp; sourceTree = "<group>"; }; … … 20224 20226 A8C4A7F509D563270003AC8D /* Element.h */, 20225 20227 93EEC1EA09C2877700C515D1 /* Element.idl */, 20228 E4AE7C1917D232350009FB31 /* ElementAncestorIterator.h */, 20226 20229 E46A2B1D17CA76B1000DBCD8 /* ElementChildIterator.h */, 20227 20230 B5B7A16F17C1080600E4AA0A /* ElementData.cpp */, … … 22226 22229 59A86008119DAFA100DEF1EF /* JSDeviceOrientationEvent.h in Headers */, 22227 22230 BCE4389C140B1BA8005E437E /* JSDictionary.h in Headers */, 22231 E4AE7C1A17D232350009FB31 /* ElementAncestorIterator.h in Headers */, 22228 22232 8987858B122CA26A003AABDA /* JSDirectoryEntry.h in Headers */, 22229 22233 893C483312495472002B3D86 /* JSDirectoryEntrySync.h in Headers */, -
trunk/Source/WebCore/accessibility/AccessibilityNodeObject.cpp
r154928 r154940 978 978 979 979 // check if our parent is a mouse button listener 980 while (node && !node->isElementNode())981 node = node->parentNode();982 983 if (!node)984 return 0;985 986 980 // FIXME: Do the continuation search like anchorElement does 987 for (Element* element = toElement(node); element; element = element->parentElement()) { 981 auto lineage = elementLineage(node->isElementNode() ? toElement(node) : node->parentElement()); 982 for (auto element = lineage.begin(), end = lineage.end(); element != end; ++element) { 988 983 // If we've reached the body and this is not a control element, do not expose press action for this element. 989 984 // It can cause false positives, where every piece of text is labeled as accepting press actions. … … 992 987 993 988 if (element->hasEventListeners(eventNames().clickEvent) || element->hasEventListeners(eventNames().mousedownEvent) || element->hasEventListeners(eventNames().mouseupEvent)) 994 return element;989 return &*element; 995 990 } 996 991 … … 1100 1095 } 1101 1096 1102 for (Element* parent = element->parentElement(); parent; parent = parent->parentElement()) { 1103 if (isHTMLLabelElement(parent)) 1104 return toHTMLLabelElement(parent); 1105 } 1106 1107 return 0; 1097 auto labelAncestors = ancestorsOfType<HTMLLabelElement>(element); 1098 auto enclosingLabel = labelAncestors.begin(); 1099 return enclosingLabel != labelAncestors.end() ? &*enclosingLabel : nullptr; 1108 1100 } 1109 1101 -
trunk/Source/WebCore/dom/ElementIterator.h
r154928 r154940 44 44 ElementType* operator->(); 45 45 46 bool operator==(const ElementIterator& other) const; 46 47 bool operator!=(const ElementIterator& other) const; 47 48 … … 50 51 ElementIterator& traverseNextSibling(); 51 52 ElementIterator& traversePreviousSibling(); 53 ElementIterator& traverseAncestor(); 52 54 53 55 private: … … 69 71 const ElementType* operator->() const; 70 72 73 bool operator==(const ElementConstIterator& other) const; 71 74 bool operator!=(const ElementConstIterator& other) const; 72 75 … … 75 78 ElementConstIterator& traverseNextSibling(); 76 79 ElementConstIterator& traversePreviousSibling(); 80 ElementConstIterator& traverseAncestor(); 77 81 78 82 private: … … 160 164 } 161 165 166 template <typename ElementTypeWithConst> 167 inline ElementTypeWithConst* findElementAncestorOfType(const Element& current) 168 { 169 ContainerNode* ancestor = current.parentNode(); 170 while (ancestor && ancestor->isElementNode()) { 171 // Non-root containers are always Elements. 172 Element* element = toElement(ancestor); 173 if (isElementOfType<ElementTypeWithConst>(element)) 174 return static_cast<ElementTypeWithConst*>(element); 175 ancestor = ancestor->parentNode(); 176 } 177 return nullptr; 178 } 179 180 template <typename ElementType> 181 inline ElementIterator<ElementType>& ElementIterator<ElementType>::traverseAncestor() 182 { 183 ASSERT(m_current); 184 ASSERT(m_current != m_root); 185 ASSERT(!m_assertions.domTreeHasMutated()); 186 187 m_current = findElementAncestorOfType<ElementType>(*m_current); 188 189 #if !ASSERT_DISABLED 190 // Drop the assertion when the iterator reaches the end. 191 if (!m_current) 192 m_assertions.dropEventDispatchAssertion(); 193 #endif 194 return *this; 195 } 196 162 197 template <typename ElementType> 163 198 inline ElementType& ElementIterator<ElementType>::operator*() … … 177 212 178 213 template <typename ElementType> 214 inline bool ElementIterator<ElementType>::operator==(const ElementIterator& other) const 215 { 216 ASSERT(m_root == other.m_root); 217 ASSERT(!m_assertions.domTreeHasMutated()); 218 return m_current == other.m_current; 219 } 220 221 template <typename ElementType> 179 222 inline bool ElementIterator<ElementType>::operator!=(const ElementIterator& other) const 180 223 { 181 ASSERT(m_root == other.m_root); 182 ASSERT(!m_assertions.domTreeHasMutated()); 183 return m_current != other.m_current; 224 return !(*this == other); 184 225 } 185 226 … … 260 301 261 302 template <typename ElementType> 303 inline ElementConstIterator<ElementType>& ElementConstIterator<ElementType>::traverseAncestor() 304 { 305 ASSERT(m_current); 306 ASSERT(m_current != m_root); 307 ASSERT(!m_assertions.domTreeHasMutated()); 308 309 m_current = findElementAncestorOfType<const ElementType>(*m_current); 310 311 #if !ASSERT_DISABLED 312 // Drop the assertion when the iterator reaches the end. 313 if (!m_current) 314 m_assertions.dropEventDispatchAssertion(); 315 #endif 316 return *this; 317 } 318 319 template <typename ElementType> 262 320 inline const ElementType& ElementConstIterator<ElementType>::operator*() const 263 321 { … … 276 334 277 335 template <typename ElementType> 336 inline bool ElementConstIterator<ElementType>::operator==(const ElementConstIterator& other) const 337 { 338 ASSERT(m_root == other.m_root); 339 ASSERT(!m_assertions.domTreeHasMutated()); 340 return m_current == other.m_current; 341 } 342 343 template <typename ElementType> 278 344 inline bool ElementConstIterator<ElementType>::operator!=(const ElementConstIterator& other) const 279 345 { 280 ASSERT(m_root == other.m_root); 281 ASSERT(!m_assertions.domTreeHasMutated()); 282 return m_current != other.m_current; 283 } 284 285 } 286 346 return !(*this == other); 347 } 348 349 } 350 351 #include "ElementAncestorIterator.h" 287 352 #include "ElementChildIterator.h" 288 353 #include "ElementDescendantIterator.h" -
trunk/Source/WebCore/html/HTMLElement.cpp
r154877 r154940 33 33 #include "DOMSettableTokenList.h" 34 34 #include "DocumentFragment.h" 35 #include "ElementIterator.h" 35 36 #include "Event.h" 36 37 #include "EventListener.h" … … 890 891 TextDirection textDirection = directionality(&strongDirectionalityTextNode); 891 892 setHasDirAutoFlagRecursively(child, false); 892 if ( renderer() && renderer()->style() && renderer()->style()->direction() != textDirection) {893 Element* elementToAdjust = this;894 for (; elementToAdjust; elementToAdjust = elementToAdjust->parentElement()) {895 if (elementAffectsDirectionality(elementToAdjust)) {896 elementToAdjust->setNeedsStyleRecalc();897 return;898 }893 if (!renderer() || !renderer()->style() || renderer()->style()->direction() == textDirection) 894 return; 895 auto lineage = elementLineage(this); 896 for (auto elementToAdjust = lineage.begin(), end = lineage.end(); elementToAdjust != end; ++elementToAdjust) { 897 if (elementAffectsDirectionality(&*elementToAdjust)) { 898 elementToAdjust->setNeedsStyleRecalc(); 899 return; 899 900 } 900 901 } … … 931 932 setHasDirAutoFlagRecursively(oldMarkedNode, false); 932 933 933 for (Element* elementToAdjust = this; elementToAdjust; elementToAdjust = elementToAdjust->parentElement()) { 934 if (elementAffectsDirectionality(elementToAdjust)) { 935 toHTMLElement(elementToAdjust)->calculateAndAdjustDirectionality(); 934 auto lineage = lineageOfType<HTMLElement>(this); 935 for (auto elementToAdjust = lineage.begin(), end = lineage.end(); elementToAdjust != end; ++elementToAdjust) { 936 if (elementAffectsDirectionality(&*elementToAdjust)) { 937 elementToAdjust->calculateAndAdjustDirectionality(); 936 938 return; 937 939 } -
trunk/Source/WebCore/html/HTMLFieldSetElement.h
r154769 r154940 64 64 }; 65 65 66 inline bool isHTMLFieldSetElement(const Node* node) 67 { 68 return node->isElementNode() && toElement(node)->hasTagName(HTMLNames::fieldsetTag); 69 } 70 71 inline bool isHTMLFieldSetElement(const Element* element) 72 { 73 return element->hasTagName(HTMLNames::fieldsetTag); 74 } 75 76 template <> inline bool isElementOfType<HTMLFieldSetElement>(const Element* element) { return isHTMLFieldSetElement(element); } 77 78 66 79 } // namespace 67 80 -
trunk/Source/WebCore/html/HTMLFrameSetElement.cpp
r154877 r154940 28 28 #include "CSSPropertyNames.h" 29 29 #include "Document.h" 30 #include "ElementIterator.h" 30 31 #include "Event.h" 31 32 #include "EventNames.h" … … 164 165 } 165 166 166 HTMLFrameSetElement* HTMLFrameSetElement::findContaining(Node* node) 167 { 168 for (Element* parent = node->parentElement(); parent; parent = parent->parentElement()) { 169 if (isHTMLFrameSetElement(parent)) 170 return toHTMLFrameSetElement(parent); 171 } 172 return 0; 167 HTMLFrameSetElement* HTMLFrameSetElement::findContaining(Element* descendant) 168 { 169 auto ancestorFrameSets = ancestorsOfType<HTMLFrameSetElement>(descendant); 170 auto enclosingFrameSet = ancestorFrameSets.begin(); 171 return enclosingFrameSet != ancestorFrameSets.end() ? &*enclosingFrameSet : nullptr; 173 172 } 174 173 -
trunk/Source/WebCore/html/HTMLFrameSetElement.h
r154358 r154940 46 46 const Length* colLengths() const { return m_colLengths.get(); } 47 47 48 static HTMLFrameSetElement* findContaining( Node* descendant);48 static HTMLFrameSetElement* findContaining(Element* descendant); 49 49 50 50 // Declared virtual in Element … … 123 123 } 124 124 125 template <> inline bool isElementOfType<HTMLFrameSetElement>(const Element* element) { return isHTMLFrameSetElement(element); } 126 125 127 } // namespace WebCore 126 128 -
trunk/Source/WebCore/html/HTMLInputElement.h
r154358 r154940 444 444 }; 445 445 446 inline bool isHTMLInputElement( Node* node)446 inline bool isHTMLInputElement(const Node* node) 447 447 { 448 448 return node->hasTagName(HTMLNames::inputTag); 449 449 } 450 450 451 inline bool isHTMLInputElement( Element* element)451 inline bool isHTMLInputElement(const Element* element) 452 452 { 453 453 return element->hasTagName(HTMLNames::inputTag); … … 460 460 } 461 461 462 inline const HTMLInputElement* toHTMLInputElement(const Node* node) 463 { 464 ASSERT_WITH_SECURITY_IMPLICATION(!node || isHTMLInputElement(node)); 465 return static_cast<const HTMLInputElement*>(node); 466 } 467 462 468 } //namespace 463 469 #endif -
trunk/Source/WebCore/html/HTMLLegendElement.cpp
r153939 r154940 26 26 #include "HTMLLegendElement.h" 27 27 28 #include "Element Traversal.h"28 #include "ElementIterator.h" 29 29 #include "HTMLFieldSetElement.h" 30 30 #include "HTMLFormControlElement.h" … … 50 50 { 51 51 // Check if there's a fieldset belonging to this legend. 52 Element* fieldset = parentElement(); 53 while (fieldset && !fieldset->hasTagName(fieldsetTag)) 54 fieldset = fieldset->parentElement(); 55 if (!fieldset) 52 auto fieldsetAncestors = ancestorsOfType<HTMLFieldSetElement>(this); 53 auto enclosingFieldset = fieldsetAncestors.begin(); 54 if (enclosingFieldset == fieldsetAncestors.end()) 56 55 return 0; 57 56 58 57 // Find first form element inside the fieldset that is not a legend element. 59 58 // FIXME: Should we consider tabindex? 60 Element* element = fieldset; 61 while ((element = ElementTraversal::next(element, fieldset))) { 62 if (element->isFormControlElement()) 63 return static_cast<HTMLFormControlElement*>(element); 64 } 65 66 return 0; 59 auto fieldsetFormControlDescendants = descendantsOfType<HTMLFormControlElement>(&*enclosingFieldset); 60 auto firstFormControl = fieldsetFormControlDescendants.begin(); 61 return firstFormControl != fieldsetFormControlDescendants.end() ? &*firstFormControl : nullptr; 67 62 } 68 63
Note:
See TracChangeset
for help on using the changeset viewer.