summaryrefslogtreecommitdiff
path: root/Source/WebCore/dom/ContainerNode.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/dom/ContainerNode.h')
-rw-r--r--Source/WebCore/dom/ContainerNode.h256
1 files changed, 107 insertions, 149 deletions
diff --git a/Source/WebCore/dom/ContainerNode.h b/Source/WebCore/dom/ContainerNode.h
index 163753026..8a8e0a2d7 100644
--- a/Source/WebCore/dom/ContainerNode.h
+++ b/Source/WebCore/dom/ContainerNode.h
@@ -2,7 +2,7 @@
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2001 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2015 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -21,222 +21,177 @@
*
*/
-#ifndef ContainerNode_h
-#define ContainerNode_h
+#pragma once
-#include "ExceptionCodePlaceholder.h"
+#include "CollectionType.h"
#include "Node.h"
-#include <wtf/OwnPtr.h>
-#include <wtf/Vector.h>
-
namespace WebCore {
-class FloatPoint;
+class HTMLCollection;
+class RadioNodeList;
class RenderElement;
-typedef void (*NodeCallback)(Node&, unsigned);
-
-namespace Private {
- template<class GenericNode, class GenericNodeContainer>
- void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer&);
-};
-
-class NoEventDispatchAssertion {
-public:
- NoEventDispatchAssertion()
- {
-#ifndef NDEBUG
- if (!isMainThread())
- return;
- s_count++;
-#endif
- }
-
- ~NoEventDispatchAssertion()
- {
-#ifndef NDEBUG
- if (!isMainThread())
- return;
- ASSERT(s_count);
- s_count--;
-#endif
- }
-
-#ifndef NDEBUG
- static bool isEventDispatchForbidden()
- {
- if (!isMainThread())
- return false;
- return s_count;
- }
-#endif
-
-private:
-#ifndef NDEBUG
- static unsigned s_count;
-#endif
-};
-
class ContainerNode : public Node {
- friend class PostAttachCallbackDisabler;
public:
virtual ~ContainerNode();
Node* firstChild() const { return m_firstChild; }
+ static ptrdiff_t firstChildMemoryOffset() { return OBJECT_OFFSETOF(ContainerNode, m_firstChild); }
Node* lastChild() const { return m_lastChild; }
+ static ptrdiff_t lastChildMemoryOffset() { return OBJECT_OFFSETOF(ContainerNode, m_lastChild); }
bool hasChildNodes() const { return m_firstChild; }
+ bool hasOneChild() const { return m_firstChild && !m_firstChild->nextSibling(); }
+
+ bool directChildNeedsStyleRecalc() const { return getFlag(DirectChildNeedsStyleRecalcFlag); }
+ void setDirectChildNeedsStyleRecalc() { setFlag(DirectChildNeedsStyleRecalcFlag); }
- unsigned childNodeCount() const;
- Node* childNode(unsigned index) const;
+ WEBCORE_EXPORT unsigned countChildNodes() const;
+ WEBCORE_EXPORT Node* traverseToChildAt(unsigned) const;
- bool insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& = ASSERT_NO_EXCEPTION);
- bool replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& = ASSERT_NO_EXCEPTION);
- bool removeChild(Node* child, ExceptionCode& = ASSERT_NO_EXCEPTION);
- bool appendChild(PassRefPtr<Node> newChild, ExceptionCode& = ASSERT_NO_EXCEPTION);
+ ExceptionOr<void> insertBefore(Node& newChild, Node* refChild);
+ ExceptionOr<void> replaceChild(Node& newChild, Node& oldChild);
+ WEBCORE_EXPORT ExceptionOr<void> removeChild(Node& child);
+ WEBCORE_EXPORT ExceptionOr<void> appendChild(Node& newChild);
+ void replaceAllChildren(Ref<Node>&&);
+ void replaceAllChildren(std::nullptr_t);
// These methods are only used during parsing.
// They don't send DOM mutation events or handle reparenting.
// However, arbitrary code may be run by beforeload handlers.
- void parserAppendChild(PassRefPtr<Node>);
+ void parserAppendChild(Node&);
void parserRemoveChild(Node&);
- void parserInsertBefore(PassRefPtr<Node> newChild, Node* refChild);
+ void parserInsertBefore(Node& newChild, Node& refChild);
void removeChildren();
- void takeAllChildrenFrom(ContainerNode*);
- void cloneChildNodes(ContainerNode* clone);
+ void takeAllChildrenFrom(ContainerNode*);
- virtual LayoutRect boundingBox() const override;
+ void cloneChildNodes(ContainerNode& clone);
- enum ChildChangeType { ElementInserted, ElementRemoved, TextInserted, TextRemoved, TextChanged, AllChildrenRemoved, NonContentsChildChanged };
+ enum ChildChangeType { ElementInserted, ElementRemoved, TextInserted, TextRemoved, TextChanged, AllChildrenRemoved, NonContentsChildRemoved, NonContentsChildInserted, AllChildrenReplaced };
enum ChildChangeSource { ChildChangeSourceParser, ChildChangeSourceAPI };
struct ChildChange {
ChildChangeType type;
Element* previousSiblingElement;
Element* nextSiblingElement;
ChildChangeSource source;
+
+ bool isInsertion() const
+ {
+ switch (type) {
+ case ElementInserted:
+ case TextInserted:
+ case NonContentsChildInserted:
+ case AllChildrenReplaced:
+ return true;
+ case ElementRemoved:
+ case TextRemoved:
+ case TextChanged:
+ case AllChildrenRemoved:
+ case NonContentsChildRemoved:
+ return false;
+ }
+ ASSERT_NOT_REACHED();
+ return false;
+ }
};
virtual void childrenChanged(const ChildChange&);
void disconnectDescendantFrames();
- virtual bool childShouldCreateRenderer(const Node&) const { return true; }
-
- using Node::setAttributeEventListener;
- void setAttributeEventListener(const AtomicString& eventType, const QualifiedName& attributeName, const AtomicString& value);
-
RenderElement* renderer() const;
- Element* querySelector(const AtomicString& selectors, ExceptionCode&);
- RefPtr<NodeList> querySelectorAll(const AtomicString& selectors, ExceptionCode&);
+ // Return a bounding box in absolute coordinates enclosing this node and all its descendants.
+ // This gives the area within which events may get handled by a hander registered on this node.
+ virtual LayoutRect absoluteEventHandlerBounds(bool& /* includesFixedPositionElements */) { return LayoutRect(); }
- PassRefPtr<NodeList> getElementsByTagName(const AtomicString&);
- PassRefPtr<NodeList> getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName);
- PassRefPtr<NodeList> getElementsByName(const String& elementName);
- PassRefPtr<NodeList> getElementsByClassName(const String& classNames);
- PassRefPtr<RadioNodeList> radioNodeList(const AtomicString&);
+ WEBCORE_EXPORT ExceptionOr<Element*> querySelector(const String& selectors);
+ WEBCORE_EXPORT ExceptionOr<Ref<NodeList>> querySelectorAll(const String& selectors);
-protected:
- explicit ContainerNode(Document*, ConstructionType = CreateContainer);
+ WEBCORE_EXPORT Ref<HTMLCollection> getElementsByTagName(const AtomicString&);
+ WEBCORE_EXPORT Ref<HTMLCollection> getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName);
+ WEBCORE_EXPORT Ref<NodeList> getElementsByName(const String& elementName);
+ WEBCORE_EXPORT Ref<HTMLCollection> getElementsByClassName(const AtomicString& classNames);
+ Ref<RadioNodeList> radioNodeList(const AtomicString&);
- static void queuePostAttachCallback(NodeCallback, Node&, unsigned = 0);
- static bool postAttachCallbacksAreSuspended();
+ // From the ParentNode interface - https://dom.spec.whatwg.org/#interface-parentnode
+ WEBCORE_EXPORT Ref<HTMLCollection> children();
+ WEBCORE_EXPORT Element* firstElementChild() const;
+ WEBCORE_EXPORT Element* lastElementChild() const;
+ WEBCORE_EXPORT unsigned childElementCount() const;
+ ExceptionOr<void> append(Vector<NodeOrString>&&);
+ ExceptionOr<void> prepend(Vector<NodeOrString>&&);
- template<class GenericNode, class GenericNodeContainer>
- friend void appendChildToContainer(GenericNode* child, GenericNodeContainer&);
+ ExceptionOr<void> ensurePreInsertionValidity(Node& newChild, Node* refChild);
- template<class GenericNode, class GenericNodeContainer>
- friend void Private::addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer&);
+protected:
+ explicit ContainerNode(Document&, ConstructionType = CreateContainer);
+
+ friend void addChildNodesToDeletionQueue(Node*& head, Node*& tail, ContainerNode&);
void removeDetachedChildren();
void setFirstChild(Node* child) { m_firstChild = child; }
void setLastChild(Node* child) { m_lastChild = child; }
+ HTMLCollection* cachedHTMLCollection(CollectionType);
+
private:
void removeBetween(Node* previousChild, Node* nextChild, Node& oldChild);
+ ExceptionOr<void> appendChildWithoutPreInsertionValidityCheck(Node&);
void insertBeforeCommon(Node& nextChild, Node& oldChild);
+ void appendChildCommon(Node&);
- static void dispatchPostAttachCallbacks();
- static void suspendPostAttachCallbacks(Document&);
- static void resumePostAttachCallbacks(Document&);
-
- bool getUpperLeftCorner(FloatPoint&) const;
- bool getLowerRightCorner(FloatPoint&) const;
-
- void notifyChildInserted(Node& child, ChildChangeSource);
+ void notifyChildInserted(Node& child, const ChildChange&);
void notifyChildRemoved(Node& child, Node* previousSibling, Node* nextSibling, ChildChangeSource);
- void updateTreeAfterInsertion(Node& child);
+ enum class ReplacedAllChildren { No, Yes };
+ void updateTreeAfterInsertion(Node& child, ReplacedAllChildren = ReplacedAllChildren::No);
+ static ChildChange changeForChildInsertion(Node& child, ChildChangeSource, ReplacedAllChildren = ReplacedAllChildren::No);
+ void rebuildSVGExtensionsElementsIfNecessary();
bool isContainerNode() const = delete;
- void willRemoveChild(Node& child);
-
- Node* m_firstChild;
- Node* m_lastChild;
+ Node* m_firstChild { nullptr };
+ Node* m_lastChild { nullptr };
};
-inline bool isContainerNode(const Node& node) { return node.isContainerNode(); }
-void isContainerNode(const ContainerNode&); // Catch unnecessary runtime check of type known at compile time.
-
-NODE_TYPE_CASTS(ContainerNode)
-
-inline ContainerNode::ContainerNode(Document* document, ConstructionType type)
+inline ContainerNode::ContainerNode(Document& document, ConstructionType type)
: Node(document, type)
- , m_firstChild(0)
- , m_lastChild(0)
{
}
-inline unsigned Node::childNodeCount() const
+inline unsigned Node::countChildNodes() const
{
- if (!isContainerNode())
+ if (!is<ContainerNode>(*this))
return 0;
- return toContainerNode(this)->childNodeCount();
+ return downcast<ContainerNode>(*this).countChildNodes();
}
-inline Node* Node::childNode(unsigned index) const
+inline Node* Node::traverseToChildAt(unsigned index) const
{
- if (!isContainerNode())
- return 0;
- return toContainerNode(this)->childNode(index);
+ if (!is<ContainerNode>(*this))
+ return nullptr;
+ return downcast<ContainerNode>(*this).traverseToChildAt(index);
}
inline Node* Node::firstChild() const
{
- if (!isContainerNode())
- return 0;
- return toContainerNode(this)->firstChild();
+ if (!is<ContainerNode>(*this))
+ return nullptr;
+ return downcast<ContainerNode>(*this).firstChild();
}
inline Node* Node::lastChild() const
{
- if (!isContainerNode())
- return 0;
- return toContainerNode(this)->lastChild();
-}
-
-inline Node* Node::highestAncestor() const
-{
- Node* node = const_cast<Node*>(this);
- Node* highest = node;
- for (; node; node = node->parentNode())
- highest = node;
- return highest;
-}
-
-inline bool Node::needsNodeRenderingTraversalSlowPath() const
-{
- if (getFlag(NeedsNodeRenderingTraversalSlowPathFlag))
- return true;
- ContainerNode* parent = parentOrShadowHostNode();
- return parent && parent->getFlag(NeedsNodeRenderingTraversalSlowPathFlag);
+ if (!is<ContainerNode>(*this))
+ return nullptr;
+ return downcast<ContainerNode>(*this).lastChild();
}
inline bool Node::isTreeScope() const
{
- return treeScope().rootNode() == this;
+ return &treeScope().rootNode() == this;
}
// This constant controls how much buffer is initially allocated
@@ -259,45 +214,45 @@ public:
explicit ChildNodesLazySnapshot(Node& parentNode)
: m_currentNode(parentNode.firstChild())
, m_currentIndex(0)
+ , m_hasSnapshot(false)
{
m_nextSnapshot = latestSnapshot;
latestSnapshot = this;
}
- ~ChildNodesLazySnapshot()
+ ALWAYS_INLINE ~ChildNodesLazySnapshot()
{
latestSnapshot = m_nextSnapshot;
}
// Returns 0 if there is no next Node.
- PassRefPtr<Node> nextNode()
+ RefPtr<Node> nextNode()
{
if (LIKELY(!hasSnapshot())) {
- RefPtr<Node> node = m_currentNode;
+ RefPtr<Node> node = WTFMove(m_currentNode);
if (node)
m_currentNode = node->nextSibling();
- return node.release();
+ return node;
}
- Vector<RefPtr<Node>>& nodeVector = *m_childNodes;
- if (m_currentIndex >= nodeVector.size())
- return 0;
- return nodeVector[m_currentIndex++];
+ if (m_currentIndex >= m_snapshot.size())
+ return nullptr;
+ return m_snapshot[m_currentIndex++];
}
void takeSnapshot()
{
if (hasSnapshot())
return;
- m_childNodes = adoptPtr(new Vector<RefPtr<Node>>());
+ m_hasSnapshot = true;
Node* node = m_currentNode.get();
while (node) {
- m_childNodes->append(node);
+ m_snapshot.append(node);
node = node->nextSibling();
}
}
ChildNodesLazySnapshot* nextSnapshot() { return m_nextSnapshot; }
- bool hasSnapshot() { return !!m_childNodes.get(); }
+ bool hasSnapshot() { return m_hasSnapshot; }
static void takeChildNodesLazySnapshot()
{
@@ -313,10 +268,13 @@ private:
RefPtr<Node> m_currentNode;
unsigned m_currentIndex;
- OwnPtr<Vector<RefPtr<Node>>> m_childNodes; // Lazily instantiated.
+ bool m_hasSnapshot;
+ Vector<RefPtr<Node>> m_snapshot; // Lazily instantiated.
ChildNodesLazySnapshot* m_nextSnapshot;
};
} // namespace WebCore
-#endif // ContainerNode_h
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ContainerNode)
+ static bool isType(const WebCore::Node& node) { return node.isContainerNode(); }
+SPECIALIZE_TYPE_TRAITS_END()