mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
589 lines
22 KiB
C++
589 lines
22 KiB
C++
/*
|
|
* 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-2011, 2014 Apple Inc. All rights reserved.
|
|
* Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#ifndef SKY_ENGINE_CORE_DOM_NODE_H_
|
|
#define SKY_ENGINE_CORE_DOM_NODE_H_
|
|
|
|
#include "sky/engine/bindings/exception_state_placeholder.h"
|
|
#include "sky/engine/core/dom/MutationObserver.h"
|
|
#include "sky/engine/core/dom/TreeScope.h"
|
|
#include "sky/engine/core/dom/TreeShared.h"
|
|
#include "sky/engine/core/editing/EditingBoundary.h"
|
|
#include "sky/engine/core/inspector/InspectorCounters.h"
|
|
#include "sky/engine/core/rendering/style/RenderStyleConstants.h"
|
|
#include "sky/engine/platform/geometry/LayoutRect.h"
|
|
#include "sky/engine/platform/heap/Handle.h"
|
|
#include "sky/engine/platform/weborigin/KURLHash.h"
|
|
#include "sky/engine/wtf/Forward.h"
|
|
|
|
// This needs to be here because Document.h also depends on it.
|
|
#define DUMP_NODE_STATISTICS 0
|
|
|
|
namespace blink {
|
|
|
|
class Attribute;
|
|
class ContainerNode;
|
|
class Document;
|
|
class Element;
|
|
class Event;
|
|
class EventDispatchMediator;
|
|
class EventListener;
|
|
class ExceptionState;
|
|
class FloatPoint;
|
|
class LocalFrame;
|
|
class IntRect;
|
|
class KeyboardEvent;
|
|
class NSResolver;
|
|
class NodeList;
|
|
class NodeRareData;
|
|
class QualifiedName;
|
|
class RegisteredEventListener;
|
|
class RenderBox;
|
|
class RenderBoxModelObject;
|
|
class RenderObject;
|
|
class RenderStyle;
|
|
template <typename NodeType> class StaticNodeTypeList;
|
|
typedef StaticNodeTypeList<Node> StaticNodeList;
|
|
class Text;
|
|
class WeakNodeMap;
|
|
|
|
const int nodeStyleChangeShift = 19;
|
|
|
|
enum StyleChangeType {
|
|
NoStyleChange = 0,
|
|
LocalStyleChange = 1 << nodeStyleChangeShift,
|
|
SubtreeStyleChange = 2 << nodeStyleChangeShift,
|
|
NeedsReattachStyleChange = 3 << nodeStyleChangeShift,
|
|
};
|
|
|
|
class NodeRareDataBase {
|
|
public:
|
|
RenderObject* renderer() const { return m_renderer; }
|
|
void setRenderer(RenderObject* renderer) { m_renderer = renderer; }
|
|
|
|
protected:
|
|
NodeRareDataBase(RenderObject* renderer)
|
|
: m_renderer(renderer)
|
|
{ }
|
|
|
|
private:
|
|
RenderObject* m_renderer;
|
|
};
|
|
|
|
// TreeShared should be the last to pack TreeShared::m_refCount and
|
|
// Node::m_nodeFlags on 64bit platforms.
|
|
class Node : public DartWrappable, public TreeShared<Node> {
|
|
DEFINE_WRAPPERTYPEINFO();
|
|
friend class Document;
|
|
friend class TreeScope;
|
|
friend class TreeScopeAdopter;
|
|
public:
|
|
enum NodeType {
|
|
ELEMENT_NODE = 1,
|
|
TEXT_NODE = 3,
|
|
DOCUMENT_NODE = 9,
|
|
DOCUMENT_FRAGMENT_NODE = 11,
|
|
};
|
|
|
|
enum DocumentPosition {
|
|
DOCUMENT_POSITION_EQUIVALENT = 0x00,
|
|
DOCUMENT_POSITION_DISCONNECTED = 0x01,
|
|
DOCUMENT_POSITION_PRECEDING = 0x02,
|
|
DOCUMENT_POSITION_FOLLOWING = 0x04,
|
|
DOCUMENT_POSITION_CONTAINS = 0x08,
|
|
DOCUMENT_POSITION_CONTAINED_BY = 0x10,
|
|
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20,
|
|
};
|
|
|
|
#if !ENABLE(OILPAN)
|
|
// All Nodes are placed in their own heap partition for security.
|
|
// See http://crbug.com/246860 for detail.
|
|
void* operator new(size_t);
|
|
void operator delete(void*);
|
|
#endif
|
|
|
|
static void dumpStatistics();
|
|
|
|
virtual ~Node();
|
|
|
|
// DOM methods & attributes for Node
|
|
|
|
virtual String nodeName() const = 0;
|
|
virtual NodeType nodeType() const = 0;
|
|
ContainerNode* parentNode() const;
|
|
void setParentNode(ContainerNode*);
|
|
Element* parentElement() const;
|
|
Node* previousSibling() const { return m_previous; }
|
|
Node* nextSibling() const { return m_next; }
|
|
Node* firstChild() const;
|
|
Node* lastChild() const;
|
|
|
|
Element* previousElementSibling();
|
|
Element* nextElementSibling();
|
|
|
|
// These functions release the nodes from |nodes|.
|
|
void newInsertBefore(Vector<RefPtr<Node>>& nodes, ExceptionState&);
|
|
void newInsertAfter(Vector<RefPtr<Node>>& nodes, ExceptionState&);
|
|
void replaceWith(Vector<RefPtr<Node>>& nodes, ExceptionState&);
|
|
|
|
void remove(ExceptionState&);
|
|
|
|
// These should all actually return a node, but this is only important for language bindings,
|
|
// which will already know and hold a ref on the right node to return.
|
|
PassRefPtr<Node> insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionState& = ASSERT_NO_EXCEPTION);
|
|
PassRefPtr<Node> replaceChild(PassRefPtr<Node> newChild, PassRefPtr<Node> oldChild, ExceptionState& = ASSERT_NO_EXCEPTION);
|
|
PassRefPtr<Node> removeChild(PassRefPtr<Node> child, ExceptionState& = ASSERT_NO_EXCEPTION);
|
|
PassRefPtr<Node> appendChild(PassRefPtr<Node> newChild, ExceptionState& = ASSERT_NO_EXCEPTION);
|
|
|
|
bool hasChildren() const { return firstChild(); }
|
|
virtual PassRefPtr<Node> cloneNode(bool deep = false) = 0;
|
|
virtual const AtomicString& localName() const;
|
|
|
|
String textContent() const;
|
|
void setTextContent(const String&);
|
|
|
|
// Other methods (not part of DOM)
|
|
|
|
bool isElementNode() const { return getFlag(IsElementFlag); }
|
|
bool isContainerNode() const { return getFlag(IsContainerFlag); }
|
|
bool isTextNode() const { return getFlag(IsTextFlag); }
|
|
bool isHTMLElement() const { return getFlag(IsHTMLFlag); }
|
|
|
|
// StyledElements allow inline style (style="border: 1px"), presentational attributes (ex. color),
|
|
// class names (ex. class="foo bar") and other non-basic styling features. They and also control
|
|
// if this element can participate in style sharing.
|
|
//
|
|
// FIXME: The only things that ever go through StyleResolver that aren't StyledElements are
|
|
// PseudoElements and VTTElements. It's possible we can just eliminate all the checks
|
|
// since those elements will never have class names, inline style, or other things that
|
|
// this apparently guards against.
|
|
bool isStyledElement() const { return isElementNode(); }
|
|
|
|
bool isDocumentNode() const;
|
|
bool isTreeScope() const;
|
|
bool isDocumentFragment() const { return getFlag(IsDocumentFragmentFlag); }
|
|
|
|
// Returns the enclosing event parent Element (or self) that, when clicked, would trigger a navigation.
|
|
Element* enclosingLinkEventParentOrSelf();
|
|
|
|
// These low-level calls give the caller responsibility for maintaining the integrity of the tree.
|
|
void setPreviousSibling(Node* previous) { m_previous = previous; }
|
|
void setNextSibling(Node* next) { m_next = next; }
|
|
|
|
virtual bool canContainRangeEndPoint() const { return false; }
|
|
|
|
// FIXME: These two functions belong in editing -- "atomic node" is an editing concept.
|
|
Node* previousNodeConsideringAtomicNodes() const;
|
|
Node* nextNodeConsideringAtomicNodes() const;
|
|
|
|
// Returns the next leaf node or 0 if there are no more.
|
|
// Delivers leaf nodes as if the whole DOM tree were a linear chain of its leaf nodes.
|
|
// Uses an editing-specific concept of what a leaf node is, and should probably be moved
|
|
// out of the Node class into an editing-specific source file.
|
|
Node* nextLeafNode() const;
|
|
|
|
// Returns the previous leaf node or 0 if there are no more.
|
|
// Delivers leaf nodes as if the whole DOM tree were a linear chain of its leaf nodes.
|
|
// Uses an editing-specific concept of what a leaf node is, and should probably be moved
|
|
// out of the Node class into an editing-specific source file.
|
|
Node* previousLeafNode() const;
|
|
|
|
bool isRootEditableElement() const;
|
|
Element* rootEditableElement() const;
|
|
Element* rootEditableElement(EditableType) const;
|
|
|
|
bool isUserActionElement() const { return getFlag(IsUserActionElementFlag); }
|
|
void setUserActionElement(bool flag) { setFlag(flag, IsUserActionElementFlag); }
|
|
|
|
bool active() const { return isUserActionElement() && isUserActionElementActive(); }
|
|
bool inActiveChain() const { return isUserActionElement() && isUserActionElementInActiveChain(); }
|
|
bool hovered() const { return isUserActionElement() && isUserActionElementHovered(); }
|
|
|
|
bool needsAttach() const { return styleChangeType() == NeedsReattachStyleChange; }
|
|
bool needsStyleRecalc() const { return styleChangeType() != NoStyleChange; }
|
|
StyleChangeType styleChangeType() const { return static_cast<StyleChangeType>(m_nodeFlags & StyleChangeMask); }
|
|
bool childNeedsStyleRecalc() const { return getFlag(ChildNeedsStyleRecalcFlag); }
|
|
bool isLink() const { return getFlag(IsLinkFlag); }
|
|
bool isEditingText() const { return isTextNode() && getFlag(IsEditingTextFlag); }
|
|
|
|
void setChildNeedsStyleRecalc() { setFlag(ChildNeedsStyleRecalcFlag); }
|
|
void clearChildNeedsStyleRecalc() { clearFlag(ChildNeedsStyleRecalcFlag); }
|
|
|
|
void setNeedsStyleRecalc(StyleChangeType);
|
|
void clearNeedsStyleRecalc();
|
|
|
|
void setIsLink(bool f);
|
|
|
|
bool isV8CollectableDuringMinorGC() const { return getFlag(V8CollectableDuringMinorGCFlag); }
|
|
void markV8CollectableDuringMinorGC() { setFlag(true, V8CollectableDuringMinorGCFlag); }
|
|
void clearV8CollectableDuringMinorGC() { setFlag(false, V8CollectableDuringMinorGCFlag); }
|
|
|
|
virtual void setActive(bool flag = true);
|
|
virtual void setHovered(bool flag = true);
|
|
|
|
enum UserSelectAllTreatment {
|
|
UserSelectAllDoesNotAffectEditability,
|
|
UserSelectAllIsAlwaysNonEditable
|
|
};
|
|
bool isContentEditable(UserSelectAllTreatment = UserSelectAllDoesNotAffectEditability);
|
|
bool isContentRichlyEditable();
|
|
|
|
bool hasEditableStyle(EditableType editableType = ContentIsEditable, UserSelectAllTreatment treatment = UserSelectAllIsAlwaysNonEditable) const
|
|
{
|
|
switch (editableType) {
|
|
case ContentIsEditable:
|
|
return hasEditableStyle(Editable, treatment);
|
|
case HasEditableAXRole:
|
|
return isEditableToAccessibility(Editable);
|
|
}
|
|
ASSERT_NOT_REACHED();
|
|
return false;
|
|
}
|
|
|
|
bool rendererIsRichlyEditable(EditableType editableType = ContentIsEditable) const
|
|
{
|
|
switch (editableType) {
|
|
case ContentIsEditable:
|
|
return hasEditableStyle(RichlyEditable, UserSelectAllIsAlwaysNonEditable);
|
|
case HasEditableAXRole:
|
|
return isEditableToAccessibility(RichlyEditable);
|
|
}
|
|
ASSERT_NOT_REACHED();
|
|
return false;
|
|
}
|
|
|
|
virtual LayoutRect boundingBox() const;
|
|
IntRect pixelSnappedBoundingBox() const { return pixelSnappedIntRect(boundingBox()); }
|
|
|
|
unsigned nodeIndex() const;
|
|
|
|
// Returns the DOM ownerDocument attribute. This method never returns NULL, except in the case
|
|
// of a Document node.
|
|
Document* ownerDocument() const;
|
|
|
|
// Returns the document associated with this node. A Document node returns itself.
|
|
Document& document() const
|
|
{
|
|
return treeScope().document();
|
|
}
|
|
|
|
TreeScope& treeScope() const
|
|
{
|
|
ASSERT(m_treeScope);
|
|
return *m_treeScope;
|
|
}
|
|
|
|
ContainerNode* owner() const;
|
|
|
|
bool inActiveDocument() const;
|
|
|
|
// Returns true if this node is associated with a document and is in its associated document's
|
|
// node tree, false otherwise.
|
|
bool inDocument() const
|
|
{
|
|
return getFlag(InDocumentFlag);
|
|
}
|
|
bool isInTreeScope() const { return getFlag(static_cast<NodeFlags>(InDocumentFlag)); }
|
|
|
|
unsigned countChildren() const;
|
|
|
|
bool isDescendantOf(const Node*) const;
|
|
bool contains(const Node*) const;
|
|
|
|
// Used to determine whether range offsets use characters or node indices.
|
|
virtual bool offsetInCharacters() const;
|
|
// Number of DOM 16-bit units contained in node. Note that rendered text length can be different - e.g. because of
|
|
// css-transform:capitalize breaking up precomposed characters and ligatures.
|
|
virtual int maxCharacterOffset() const;
|
|
|
|
// Whether or not a selection can be started in this object
|
|
virtual bool canStartSelection() const;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Integration with rendering tree
|
|
|
|
// As renderer() includes a branch you should avoid calling it repeatedly in hot code paths.
|
|
// Note that if a Node has a renderer, it's parentNode is guaranteed to have one as well.
|
|
RenderObject* renderer() const { return hasRareData() ? m_data.m_rareData->renderer() : m_data.m_renderer; };
|
|
void setRenderer(RenderObject* renderer)
|
|
{
|
|
if (hasRareData())
|
|
m_data.m_rareData->setRenderer(renderer);
|
|
else
|
|
m_data.m_renderer = renderer;
|
|
}
|
|
|
|
// Use these two methods with caution.
|
|
RenderBox* renderBox() const;
|
|
RenderBoxModelObject* renderBoxModelObject() const;
|
|
|
|
struct AttachContext {
|
|
RenderStyle* resolvedStyle;
|
|
bool performingReattach;
|
|
|
|
AttachContext() : resolvedStyle(0), performingReattach(false) { }
|
|
};
|
|
|
|
// Attaches this node to the rendering tree. This calculates the style to be applied to the node and creates an
|
|
// appropriate RenderObject which will be inserted into the tree (except when the style has display: none). This
|
|
// makes the node visible in the FrameView.
|
|
virtual void attach(const AttachContext& = AttachContext());
|
|
|
|
// Detaches the node from the rendering tree, making it invisible in the rendered view. This method will remove
|
|
// the node's rendering object from the rendering tree and delete it.
|
|
virtual void detach(const AttachContext& = AttachContext());
|
|
|
|
#if ENABLE(ASSERT)
|
|
bool inDetach() const;
|
|
#endif
|
|
|
|
void reattach(const AttachContext& = AttachContext());
|
|
void lazyReattachIfAttached();
|
|
|
|
// Returns true if recalcStyle should be called on the object, if there is such a method (on Document and Element).
|
|
bool shouldCallRecalcStyle(StyleRecalcChange);
|
|
|
|
// Wrapper for nodes that don't have a renderer, but still cache the style (like HTMLOptionElement).
|
|
RenderStyle* renderStyle() const;
|
|
RenderStyle* parentRenderStyle() const;
|
|
|
|
RenderStyle* computedStyle() { return virtualComputedStyle(); }
|
|
|
|
virtual void insertedInto(ContainerNode* insertionPoint);
|
|
virtual void removedFrom(ContainerNode* insertionPoint);
|
|
|
|
String debugName() const;
|
|
|
|
#ifndef NDEBUG
|
|
virtual void formatForDebugger(char* buffer, unsigned length) const;
|
|
|
|
void showNode(const char* prefix = "") const;
|
|
void showTreeForThis() const;
|
|
void showNodePathForThis() const;
|
|
void showTreeAndMark(const Node* markedNode1, const char* markedLabel1, const Node* markedNode2 = 0, const char* markedLabel2 = 0) const;
|
|
#endif
|
|
|
|
unsigned short compareDocumentPosition(const Node*) const;
|
|
|
|
void AcceptDartGCVisitor(DartGCVisitor& visitor) const override;
|
|
|
|
void getRegisteredMutationObserversOfType(HashMap<RawPtr<MutationObserver>, MutationRecordDeliveryOptions>&, MutationObserver::MutationType, const QualifiedName* attributeName);
|
|
void registerMutationObserver(MutationObserver&, MutationObserverOptions, const HashSet<AtomicString>& attributeFilter);
|
|
void unregisterMutationObserver(MutationObserverRegistration*);
|
|
void registerTransientMutationObserver(MutationObserverRegistration*);
|
|
void unregisterTransientMutationObserver(MutationObserverRegistration*);
|
|
void notifyMutationObserversNodeWillDetach();
|
|
|
|
Vector<RefPtr<Node>> getDestinationInsertionPoints();
|
|
|
|
void setAlreadySpellChecked(bool flag) { setFlag(flag, AlreadySpellCheckedFlag); }
|
|
bool isAlreadySpellChecked() { return getFlag(AlreadySpellCheckedFlag); }
|
|
|
|
unsigned lengthOfContents() const;
|
|
|
|
private:
|
|
enum NodeFlags {
|
|
HasRareDataFlag = 1,
|
|
|
|
// Node type flags. These never change once created.
|
|
IsTextFlag = 1 << 1,
|
|
IsContainerFlag = 1 << 2,
|
|
IsElementFlag = 1 << 3,
|
|
IsHTMLFlag = 1 << 4,
|
|
IsSVGFlag = 1 << 5,
|
|
IsDocumentFragmentFlag = 1 << 6,
|
|
IsInsertionPointFlag = 1 << 7,
|
|
|
|
// Changes based on if the element should be treated like a link,
|
|
// ex. When setting the href attribute on an <a>.
|
|
IsLinkFlag = 1 << 8,
|
|
|
|
// Changes based on :hover and :active state.
|
|
IsUserActionElementFlag = 1 << 9,
|
|
|
|
// Tree state flags. These change when the element is added/removed
|
|
// from a DOM tree.
|
|
InDocumentFlag = 1 << 10,
|
|
|
|
// Flags related to recalcStyle.
|
|
|
|
// FIXME(sky): Flags 11-17 are free.
|
|
|
|
ChildNeedsStyleRecalcFlag = 1 << 18,
|
|
StyleChangeMask = 1 << nodeStyleChangeShift | 1 << (nodeStyleChangeShift + 1),
|
|
|
|
IsEditingTextFlag = 1 << 21,
|
|
HasWeakReferencesFlag = 1 << 22,
|
|
V8CollectableDuringMinorGCFlag = 1 << 23,
|
|
AlreadySpellCheckedFlag = 1 << 24,
|
|
|
|
DefaultNodeFlags = ChildNeedsStyleRecalcFlag | NeedsReattachStyleChange
|
|
};
|
|
|
|
// 9 bits remaining.
|
|
|
|
bool getFlag(NodeFlags mask) const { return m_nodeFlags & mask; }
|
|
void setFlag(bool f, NodeFlags mask) { m_nodeFlags = (m_nodeFlags & ~mask) | (-(int32_t)f & mask); }
|
|
void setFlag(NodeFlags mask) { m_nodeFlags |= mask; }
|
|
void clearFlag(NodeFlags mask) { m_nodeFlags &= ~mask; }
|
|
|
|
protected:
|
|
enum ConstructionType {
|
|
CreateOther = DefaultNodeFlags,
|
|
CreateText = DefaultNodeFlags | IsTextFlag,
|
|
CreateContainer = DefaultNodeFlags | IsContainerFlag,
|
|
CreateElement = CreateContainer | IsElementFlag,
|
|
CreateDocumentFragment = CreateContainer | IsDocumentFragmentFlag,
|
|
CreateHTMLElement = CreateElement | IsHTMLFlag,
|
|
CreateDocument = CreateContainer | InDocumentFlag,
|
|
CreateInsertionPoint = CreateHTMLElement | IsInsertionPointFlag,
|
|
CreateEditingText = CreateText | IsEditingTextFlag,
|
|
};
|
|
|
|
Node(TreeScope*, ConstructionType);
|
|
|
|
virtual void didMoveToNewDocument(Document& oldDocument);
|
|
|
|
void willBeDeletedFromDocument();
|
|
|
|
bool hasRareData() const { return getFlag(HasRareDataFlag); }
|
|
|
|
NodeRareData* rareData() const;
|
|
NodeRareData& ensureRareData();
|
|
void clearRareData();
|
|
|
|
void setTreeScope(TreeScope* scope) { m_treeScope = scope; }
|
|
|
|
// isTreeScopeInitialized() can be false
|
|
// - in the Node constructor called by these two classes where m_treeScope is set by TreeScope ctor.
|
|
bool isTreeScopeInitialized() const { return m_treeScope; }
|
|
|
|
void markAncestorsWithChildNeedsStyleRecalc();
|
|
|
|
private:
|
|
friend class TreeShared<Node>;
|
|
friend class WeakNodeMap;
|
|
|
|
unsigned styledSubtreeSize() const;
|
|
|
|
#if !ENABLE(OILPAN)
|
|
void removedLastRef();
|
|
#endif
|
|
bool hasTreeSharedParent() const { return !!parentNode(); }
|
|
|
|
enum EditableLevel { Editable, RichlyEditable };
|
|
bool hasEditableStyle(EditableLevel, UserSelectAllTreatment = UserSelectAllIsAlwaysNonEditable) const;
|
|
bool isEditableToAccessibility(EditableLevel) const;
|
|
|
|
bool isUserActionElementActive() const;
|
|
bool isUserActionElementInActiveChain() const;
|
|
bool isUserActionElementHovered() const;
|
|
|
|
void traceStyleChange(StyleChangeType);
|
|
void traceStyleChangeIfNeeded(StyleChangeType);
|
|
void setStyleChange(StyleChangeType);
|
|
|
|
virtual RenderStyle* virtualComputedStyle();
|
|
|
|
void trackForDebugging();
|
|
|
|
Vector<OwnPtr<MutationObserverRegistration> >* mutationObserverRegistry();
|
|
HashSet<RawPtr<MutationObserverRegistration> >* transientMutationObserverRegistry();
|
|
|
|
uint32_t m_nodeFlags;
|
|
ContainerNode* m_parentNode;
|
|
TreeScope* m_treeScope;
|
|
Node* m_previous;
|
|
Node* m_next;
|
|
// When a node has rare data we move the renderer into the rare data.
|
|
union DataUnion {
|
|
DataUnion() : m_renderer(0) { }
|
|
RenderObject* m_renderer;
|
|
NodeRareDataBase* m_rareData;
|
|
} m_data;
|
|
};
|
|
|
|
inline void Node::setParentNode(ContainerNode* parent)
|
|
{
|
|
ASSERT(isMainThread());
|
|
m_parentNode = parent;
|
|
}
|
|
|
|
inline ContainerNode* Node::parentNode() const
|
|
{
|
|
ASSERT(isMainThread());
|
|
return m_parentNode;
|
|
}
|
|
|
|
inline void Node::lazyReattachIfAttached()
|
|
{
|
|
if (styleChangeType() == NeedsReattachStyleChange)
|
|
return;
|
|
if (!inActiveDocument())
|
|
return;
|
|
|
|
AttachContext context;
|
|
context.performingReattach = true;
|
|
|
|
detach(context);
|
|
markAncestorsWithChildNeedsStyleRecalc();
|
|
}
|
|
|
|
inline bool Node::shouldCallRecalcStyle(StyleRecalcChange change)
|
|
{
|
|
return change >= Inherit || needsStyleRecalc() || childNeedsStyleRecalc();
|
|
}
|
|
|
|
// Allow equality comparisons of Nodes by reference or pointer, interchangeably.
|
|
DEFINE_COMPARISON_OPERATORS_WITH_REFERENCES_REFCOUNTED(Node)
|
|
|
|
|
|
#define DEFINE_NODE_TYPE_CASTS(thisType, predicate) \
|
|
template<typename T> inline thisType* to##thisType(const RefPtr<T>& node) { return to##thisType(node.get()); } \
|
|
DEFINE_TYPE_CASTS(thisType, Node, node, node->predicate, node.predicate)
|
|
|
|
// This requires isClassName(const Node&).
|
|
#define DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(thisType) \
|
|
template<typename T> inline thisType* to##thisType(const RefPtr<T>& node) { return to##thisType(node.get()); } \
|
|
DEFINE_TYPE_CASTS(thisType, Node, node, is##thisType(*node), is##thisType(node))
|
|
|
|
#define DECLARE_NODE_FACTORY(T) \
|
|
static PassRefPtr<T> create(Document&)
|
|
#define DEFINE_NODE_FACTORY(T) \
|
|
PassRefPtr<T> T::create(Document& document) \
|
|
{ \
|
|
return adoptRef(new T(document)); \
|
|
}
|
|
|
|
} // namespace blink
|
|
|
|
#ifndef NDEBUG
|
|
// Outside the WebCore namespace for ease of invocation from gdb.
|
|
void showNode(const blink::Node*);
|
|
void showTree(const blink::Node*);
|
|
void showNodePath(const blink::Node*);
|
|
#endif
|
|
|
|
#endif // SKY_ENGINE_CORE_DOM_NODE_H_
|