Diff
Modified: trunk/Source/WebCore/ChangeLog (154768 => 154769)
--- trunk/Source/WebCore/ChangeLog 2013-08-28 19:41:56 UTC (rev 154768)
+++ trunk/Source/WebCore/ChangeLog 2013-08-28 19:43:51 UTC (rev 154769)
@@ -1,3 +1,50 @@
+2013-08-28 Antti Koivisto <[email protected]>
+
+ Add child and descendant const iterators
+ https://bugs.webkit.org/show_bug.cgi?id=120430
+
+ Reviewed by Andreas Kling
+
+ This patch adds const-correct DOM tree traversal iterators. It also uses them in a few places.
+
+ Some const_casts have been applied where constness breaks.
+
+ * dom/ChildIterator.h:
+ (WebCore::::ChildConstIterator):
+ (WebCore::::operator):
+ (WebCore::=):
+ (WebCore::::ChildConstIteratorAdapter):
+ (WebCore::::begin):
+ (WebCore::::end):
+ (WebCore::elementChildren):
+ (WebCore::childrenOfType):
+ * dom/DescendantIterator.h:
+ (WebCore::::DescendantConstIterator):
+ (WebCore::::operator):
+ (WebCore::=):
+ (WebCore::::DescendantConstIteratorAdapter):
+ (WebCore::::begin):
+ (WebCore::::end):
+ (WebCore::elementDescendants):
+ (WebCore::descendantsOfType):
+ * dom/Node.cpp:
+ (WebCore::Node::numberOfScopedHTMLStyleChildren):
+ * html/HTMLFieldSetElement.cpp:
+ (WebCore::HTMLFieldSetElement::legend):
+ * html/HTMLFieldSetElement.h:
+ * html/HTMLMediaElement.cpp:
+ (WebCore::HTMLMediaElement::finishParsingChildren):
+ * html/HTMLObjectElement.cpp:
+ (WebCore::HTMLObjectElement::containsJavaApplet):
+ * svg/SVGElement.cpp:
+ (WebCore::SVGElement::title):
+ * svg/SVGSVGElement.cpp:
+ (WebCore::SVGSVGElement::collectIntersectionOrEnclosureList):
+ (WebCore::SVGSVGElement::checkIntersection):
+ (WebCore::SVGSVGElement::checkEnclosure):
+ (WebCore::SVGSVGElement::getElementById):
+ * svg/SVGSVGElement.h:
+
2013-08-28 Lukasz Gajowy <[email protected]>
AX:Null pointer may be dereferenced.
Modified: trunk/Source/WebCore/dom/ChildIterator.h (154768 => 154769)
--- trunk/Source/WebCore/dom/ChildIterator.h 2013-08-28 19:41:56 UTC (rev 154768)
+++ trunk/Source/WebCore/dom/ChildIterator.h 2013-08-28 19:43:51 UTC (rev 154769)
@@ -53,6 +53,24 @@
};
template <typename ElementType>
+class ChildConstIterator {
+public:
+ ChildConstIterator();
+ ChildConstIterator(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>
class ChildIteratorAdapter {
public:
ChildIteratorAdapter(ContainerNode* root);
@@ -63,9 +81,24 @@
const ContainerNode* m_root;
};
+template <typename ElementType>
+class ChildConstIteratorAdapter {
+public:
+ ChildConstIteratorAdapter(const ContainerNode* root);
+ ChildConstIterator<ElementType> begin() const;
+ ChildConstIterator<ElementType> end() const;
+
+private:
+ const ContainerNode* m_root;
+};
+
ChildIteratorAdapter<Element> elementChildren(ContainerNode* root);
+ChildConstIteratorAdapter<Element> elementChildren(const ContainerNode* root);
template <typename ElementType> ChildIteratorAdapter<ElementType> childrenOfType(ContainerNode* root);
+template <typename ElementType> ChildConstIteratorAdapter<ElementType> childrenOfType(const ContainerNode* root);
+// ChildIterator
+
template <typename ElementType>
inline ChildIterator<ElementType>::ChildIterator()
: m_current(nullptr)
@@ -118,7 +151,63 @@
return m_current != other.m_current;
}
+// ChildConstIterator
+
template <typename ElementType>
+inline ChildConstIterator<ElementType>::ChildConstIterator()
+ : m_current(nullptr)
+{
+}
+
+template <typename ElementType>
+inline ChildConstIterator<ElementType>::ChildConstIterator(const ElementType* current)
+ : m_current(current)
+#if !ASSERT_DISABLED
+ , m_assertions(current)
+#endif
+{
+}
+
+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;
+}
+
+// ChildIteratorAdapter
+
+template <typename ElementType>
inline ChildIteratorAdapter<ElementType>::ChildIteratorAdapter(ContainerNode* root)
: m_root(root)
{
@@ -136,6 +225,28 @@
return ChildIterator<ElementType>();
}
+// ChildConstIteratorAdapter
+
+template <typename ElementType>
+inline ChildConstIteratorAdapter<ElementType>::ChildConstIteratorAdapter(const ContainerNode* root)
+ : m_root(root)
+{
+}
+
+template <typename ElementType>
+inline ChildConstIterator<ElementType> ChildConstIteratorAdapter<ElementType>::begin() const
+{
+ return ChildConstIterator<ElementType>(Traversal<ElementType>::firstChild(m_root));
+}
+
+template <typename ElementType>
+inline ChildConstIterator<ElementType> ChildConstIteratorAdapter<ElementType>::end() const
+{
+ return ChildConstIterator<ElementType>();
+}
+
+// Standalone functions
+
inline ChildIteratorAdapter<Element> elementChildren(ContainerNode* root)
{
return ChildIteratorAdapter<Element>(root);
@@ -147,6 +258,17 @@
return ChildIteratorAdapter<ElementType>(root);
}
+inline ChildConstIteratorAdapter<Element> elementChildren(const ContainerNode* root)
+{
+ return ChildConstIteratorAdapter<Element>(root);
}
+template <typename ElementType>
+inline ChildConstIteratorAdapter<ElementType> childrenOfType(const ContainerNode* root)
+{
+ return ChildConstIteratorAdapter<ElementType>(root);
+}
+
+}
+
#endif
Modified: trunk/Source/WebCore/dom/DescendantIterator.h (154768 => 154769)
--- trunk/Source/WebCore/dom/DescendantIterator.h 2013-08-28 19:41:56 UTC (rev 154768)
+++ trunk/Source/WebCore/dom/DescendantIterator.h 2013-08-28 19:43:51 UTC (rev 154769)
@@ -54,6 +54,25 @@
};
template <typename ElementType>
+class DescendantConstIterator {
+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>
class DescendantIteratorAdapter {
public:
DescendantIteratorAdapter(ContainerNode* root);
@@ -64,9 +83,24 @@
ContainerNode* m_root;
};
+template <typename ElementType>
+class DescendantConstIteratorAdapter {
+public:
+ DescendantConstIteratorAdapter(const ContainerNode* root);
+ DescendantConstIterator<ElementType> begin() const;
+ DescendantConstIterator<ElementType> end() const;
+
+private:
+ const ContainerNode* m_root;
+};
+
DescendantIteratorAdapter<Element> elementDescendants(ContainerNode* root);
+DescendantConstIteratorAdapter<Element> elementDescendants(const ContainerNode* root);
template <typename ElementType> DescendantIteratorAdapter<ElementType> descendantsOfType(ContainerNode* root);
+template <typename ElementType> DescendantConstIteratorAdapter<ElementType> descendantsOfType(const ContainerNode* root);
+// DescendantIterator
+
template <typename ElementType>
inline DescendantIterator<ElementType>::DescendantIterator(const ContainerNode* root)
: m_root(root)
@@ -122,7 +156,66 @@
return m_current != other.m_current;
}
+// DescendantConstIterator
+
template <typename ElementType>
+inline DescendantConstIterator<ElementType>::DescendantConstIterator(const ContainerNode* root)
+ : m_root(root)
+ , m_current(nullptr)
+{
+}
+
+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
+{
+}
+
+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;
+}
+
+// DescendantIteratorAdapter
+
+template <typename ElementType>
inline DescendantIteratorAdapter<ElementType>::DescendantIteratorAdapter(ContainerNode* root)
: m_root(root)
{
@@ -140,6 +233,28 @@
return DescendantIterator<ElementType>(m_root);
}
+// DescendantConstIteratorAdapter
+
+template <typename ElementType>
+inline DescendantConstIteratorAdapter<ElementType>::DescendantConstIteratorAdapter(const ContainerNode* root)
+ : m_root(root)
+{
+}
+
+template <typename ElementType>
+inline DescendantConstIterator<ElementType> DescendantConstIteratorAdapter<ElementType>::begin() const
+{
+ return DescendantConstIterator<ElementType>(m_root, Traversal<ElementType>::firstWithin(m_root));
+}
+
+template <typename ElementType>
+inline DescendantConstIterator<ElementType> DescendantConstIteratorAdapter<ElementType>::end() const
+{
+ return DescendantConstIterator<ElementType>(m_root);
+}
+
+// Standalone functions
+
inline DescendantIteratorAdapter<Element> elementDescendants(ContainerNode* root)
{
return DescendantIteratorAdapter<Element>(root);
@@ -151,6 +266,17 @@
return DescendantIteratorAdapter<ElementType>(root);
}
+inline DescendantConstIteratorAdapter<Element> elementDescendants(const ContainerNode* root)
+{
+ return DescendantConstIteratorAdapter<Element>(root);
}
+template <typename ElementType>
+inline DescendantConstIteratorAdapter<ElementType> descendantsOfType(const ContainerNode* root)
+{
+ return DescendantConstIteratorAdapter<ElementType>(root);
+}
+
+}
+
#endif
Modified: trunk/Source/WebCore/dom/Node.cpp (154768 => 154769)
--- trunk/Source/WebCore/dom/Node.cpp 2013-08-28 19:41:56 UTC (rev 154768)
+++ trunk/Source/WebCore/dom/Node.cpp 2013-08-28 19:43:51 UTC (rev 154769)
@@ -44,12 +44,12 @@
#include "ContextMenuController.h"
#include "DOMImplementation.h"
#include "DOMSettableTokenList.h"
+#include "DescendantIterator.h"
#include "Document.h"
#include "DocumentFragment.h"
#include "DocumentType.h"
#include "Element.h"
#include "ElementRareData.h"
-#include "ElementTraversal.h"
#include "Event.h"
#include "EventContext.h"
#include "EventDispatchMediator.h"
@@ -2392,8 +2392,11 @@
size_t Node::numberOfScopedHTMLStyleChildren() const
{
+ if (!isContainerNode())
+ return 0;
size_t count = 0;
- for (HTMLStyleElement* style = Traversal<HTMLStyleElement>::firstWithin(this); style; style = Traversal<HTMLStyleElement>::next(style, this)) {
+ auto styleDescendants = descendantsOfType<HTMLStyleElement>(toContainerNode(this));
+ for (auto style = styleDescendants.begin(), end = styleDescendants.end(); style != end; ++style) {
if (style->isRegisteredAsScoped())
count++;
}
Modified: trunk/Source/WebCore/html/HTMLFieldSetElement.cpp (154768 => 154769)
--- trunk/Source/WebCore/html/HTMLFieldSetElement.cpp 2013-08-28 19:41:56 UTC (rev 154768)
+++ trunk/Source/WebCore/html/HTMLFieldSetElement.cpp 2013-08-28 19:43:51 UTC (rev 154769)
@@ -89,9 +89,13 @@
return new (arena) RenderFieldset(this);
}
-HTMLLegendElement* HTMLFieldSetElement::legend() const
+const HTMLLegendElement* HTMLFieldSetElement::legend() const
{
- return Traversal<HTMLLegendElement>::firstWithin(this);
+ auto legendDescendants = descendantsOfType<HTMLLegendElement>(this);
+ auto firstLegend = legendDescendants.begin();
+ if (firstLegend != legendDescendants.end())
+ return &*firstLegend;
+ return nullptr;
}
PassRefPtr<HTMLCollection> HTMLFieldSetElement::elements()
Modified: trunk/Source/WebCore/html/HTMLFieldSetElement.h (154768 => 154769)
--- trunk/Source/WebCore/html/HTMLFieldSetElement.h 2013-08-28 19:41:56 UTC (rev 154768)
+++ trunk/Source/WebCore/html/HTMLFieldSetElement.h 2013-08-28 19:43:51 UTC (rev 154769)
@@ -34,8 +34,8 @@
class HTMLFieldSetElement FINAL : public HTMLFormControlElement {
public:
static PassRefPtr<HTMLFieldSetElement> create(const QualifiedName&, Document*, HTMLFormElement*);
- HTMLLegendElement* legend() const;
+ const HTMLLegendElement* legend() const;
PassRefPtr<HTMLCollection> elements();
const Vector<FormAssociatedElement*>& associatedElements() const;
Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (154768 => 154769)
--- trunk/Source/WebCore/html/HTMLMediaElement.cpp 2013-08-28 19:41:56 UTC (rev 154768)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp 2013-08-28 19:43:51 UTC (rev 154769)
@@ -39,6 +39,7 @@
#include "ContentType.h"
#include "CSSPropertyNames.h"
#include "CSSValueKeywords.h"
+#include "DescendantIterator.h"
#include "DiagnosticLoggingKeys.h"
#include "DocumentLoader.h"
#include "Event.h"
@@ -537,7 +538,8 @@
if (!RuntimeEnabledFeatures::webkitVideoTrackEnabled())
return;
- if (Traversal<HTMLTrackElement>::firstWithin(this))
+ auto trackDescendants = descendantsOfType<HTMLTrackElement>(this);
+ if (trackDescendants.begin() != trackDescendants.end())
scheduleDelayedAction(ConfigureTextTracks);
#endif
}
Modified: trunk/Source/WebCore/html/HTMLObjectElement.cpp (154768 => 154769)
--- trunk/Source/WebCore/html/HTMLObjectElement.cpp 2013-08-28 19:41:56 UTC (rev 154768)
+++ trunk/Source/WebCore/html/HTMLObjectElement.cpp 2013-08-28 19:43:51 UTC (rev 154769)
@@ -461,14 +461,12 @@
{
if (MIMETypeRegistry::isJavaAppletMIMEType(getAttribute(typeAttr)))
return true;
-
- for (auto child = ElementTraversal::firstChild(this); child; child = ElementTraversal::nextSibling(child)) {
- if (child->hasTagName(paramTag)
- && equalIgnoringCase(child->getNameAttribute(), "type")
- && MIMETypeRegistry::isJavaAppletMIMEType(child->getAttribute(valueAttr).string()))
+
+ for (auto child = elementChildren(this).begin(), end = elementChildren(this).end(); child != end; ++child) {
+ if (child->hasTagName(paramTag) && equalIgnoringCase(child->getNameAttribute(), "type")
+ && MIMETypeRegistry::isJavaAppletMIMEType(child->getAttribute(valueAttr).string()))
return true;
- if (child->hasTagName(objectTag)
- && static_cast<HTMLObjectElement*>(child)->containsJavaApplet())
+ if (child->hasTagName(objectTag) && static_cast<const HTMLObjectElement&>(*child).containsJavaApplet())
return true;
if (child->hasTagName(appletTag))
return true;
Modified: trunk/Source/WebCore/svg/SVGElement.cpp (154768 => 154769)
--- trunk/Source/WebCore/svg/SVGElement.cpp 2013-08-28 19:41:56 UTC (rev 154768)
+++ trunk/Source/WebCore/svg/SVGElement.cpp 2013-08-28 19:43:51 UTC (rev 154769)
@@ -31,8 +31,8 @@
#include "CSSCursorImageValue.h"
#include "CSSParser.h"
#include "DOMImplementation.h"
+#include "DescendantIterator.h"
#include "Document.h"
-#include "ElementTraversal.h"
#include "Event.h"
#include "EventNames.h"
#include "HTMLNames.h"
@@ -879,8 +879,10 @@
// 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.
// If a title child was found, return the text contents.
- if (SVGTitleElement* titleElement = Traversal<SVGTitleElement>::firstWithin(this))
- return titleElement->innerText();
+ auto titleDescendants = descendantsOfType<SVGTitleElement>(this);
+ auto firstTitle = titleDescendants.begin();
+ if (firstTitle != titleDescendants.end())
+ return const_cast<SVGTitleElement&>(*firstTitle).innerText();
// Otherwise return a null/empty string.
return String();
Modified: trunk/Source/WebCore/svg/SVGSVGElement.cpp (154768 => 154769)
--- trunk/Source/WebCore/svg/SVGSVGElement.cpp 2013-08-28 19:41:56 UTC (rev 154768)
+++ trunk/Source/WebCore/svg/SVGSVGElement.cpp 2013-08-28 19:43:51 UTC (rev 154769)
@@ -27,8 +27,8 @@
#include "AffineTransform.h"
#include "Attribute.h"
#include "CSSHelper.h"
+#include "DescendantIterator.h"
#include "Document.h"
-#include "ElementTraversal.h"
#include "EventListener.h"
#include "EventNames.h"
#include "FloatConversion.h"
@@ -337,16 +337,17 @@
PassRefPtr<NodeList> SVGSVGElement::collectIntersectionOrEnclosureList(const FloatRect& rect, SVGElement* referenceElement, CollectIntersectionOrEnclosure collect) const
{
Vector<RefPtr<Node> > nodes;
- SVGElement* svgElement = Traversal<SVGElement>::firstWithin(referenceElement ? referenceElement : this);
- while (svgElement) {
+
+ auto svgDescendants = descendantsOfType<SVGElement>(referenceElement ? referenceElement : this);
+ for (auto it = svgDescendants.begin(), end = svgDescendants.end(); it != end; ++it) {
+ const SVGElement* svgElement = &*it;
if (collect == CollectIntersectionList) {
if (checkIntersection(svgElement, rect))
- nodes.append(svgElement);
+ nodes.append(const_cast<SVGElement*>(svgElement));
} else {
if (checkEnclosure(svgElement, rect))
- nodes.append(svgElement);
+ nodes.append(const_cast<SVGElement*>(svgElement));
}
- svgElement = Traversal<SVGElement>::next(svgElement, referenceElement ? referenceElement : this);
}
return StaticNodeList::adopt(nodes);
}
@@ -361,14 +362,14 @@
return collectIntersectionOrEnclosureList(rect, referenceElement, CollectEnclosureList);
}
-bool SVGSVGElement::checkIntersection(SVGElement* element, const FloatRect& rect) const
+bool SVGSVGElement::checkIntersection(const SVGElement* element, const FloatRect& rect) const
{
if (!element)
return false;
return RenderSVGModelObject::checkIntersection(element->renderer(), rect);
}
-bool SVGSVGElement::checkEnclosure(SVGElement* element, const FloatRect& rect) const
+bool SVGSVGElement::checkEnclosure(const SVGElement* element, const FloatRect& rect) const
{
if (!element)
return false;
@@ -768,7 +769,7 @@
// getElementById on SVGSVGElement is restricted to only the child subtree defined by the <svg> element.
// See http://www.w3.org/TR/SVG11/struct.html#InterfaceSVGSVGElement
-Element* SVGSVGElement::getElementById(const AtomicString& id) const
+Element* SVGSVGElement::getElementById(const AtomicString& id)
{
Element* element = treeScope()->getElementById(id);
if (element && element->isDescendantOf(this))
@@ -776,9 +777,9 @@
// Fall back to traversing our subtree. Duplicate ids are allowed, the first found will
// be returned.
- for (Element* element = ElementTraversal::firstWithin(this); element; element = ElementTraversal::next(element, this)) {
+ for (auto element = elementDescendants(this).begin(), end = elementDescendants(this).end(); element != end; ++element) {
if (element->getIdAttribute() == id)
- return element;
+ return &*element;
}
return 0;
}
Modified: trunk/Source/WebCore/svg/SVGSVGElement.h (154768 => 154769)
--- trunk/Source/WebCore/svg/SVGSVGElement.h 2013-08-28 19:41:56 UTC (rev 154768)
+++ trunk/Source/WebCore/svg/SVGSVGElement.h 2013-08-28 19:43:51 UTC (rev 154769)
@@ -106,8 +106,8 @@
PassRefPtr<NodeList> getIntersectionList(const FloatRect&, SVGElement* referenceElement) const;
PassRefPtr<NodeList> getEnclosureList(const FloatRect&, SVGElement* referenceElement) const;
- bool checkIntersection(SVGElement*, const FloatRect&) const;
- bool checkEnclosure(SVGElement*, const FloatRect&) const;
+ bool checkIntersection(const SVGElement*, const FloatRect&) const;
+ bool checkEnclosure(const SVGElement*, const FloatRect&) const;
void deselectAll();
static float createSVGNumber();
@@ -123,7 +123,7 @@
void setupInitialView(const String& fragmentIdentifier, Element* anchorNode);
- Element* getElementById(const AtomicString&) const;
+ Element* getElementById(const AtomicString&);
bool widthAttributeEstablishesViewport() const;
bool heightAttributeEstablishesViewport() const;