2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
29 #include "PlatformString.h"
30 #include "TreeShared.h"
31 #include "FloatPoint.h"
32 #include <wtf/Assertions.h>
33 #include <wtf/ListHashSet.h>
34 #include <wtf/OwnPtr.h>
35 #include <wtf/PassRefPtr.h>
42 class DynamicNodeList
;
51 class PlatformKeyboardEvent
;
52 class PlatformMouseEvent
;
53 class PlatformWheelEvent
;
62 typedef int ExceptionCode
;
64 enum StyleChangeType
{ NoStyleChange
, InlineStyleChange
, FullStyleChange
, AnimationStyleChange
};
66 const unsigned short DOCUMENT_POSITION_EQUIVALENT
= 0x00;
67 const unsigned short DOCUMENT_POSITION_DISCONNECTED
= 0x01;
68 const unsigned short DOCUMENT_POSITION_PRECEDING
= 0x02;
69 const unsigned short DOCUMENT_POSITION_FOLLOWING
= 0x04;
70 const unsigned short DOCUMENT_POSITION_CONTAINS
= 0x08;
71 const unsigned short DOCUMENT_POSITION_CONTAINED_BY
= 0x10;
72 const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC
= 0x20;
74 // this class implements nodes, which can have a parent but no children:
75 class Node
: public TreeShared
<Node
> {
76 friend class Document
;
82 CDATA_SECTION_NODE
= 4,
83 ENTITY_REFERENCE_NODE
= 5,
85 PROCESSING_INSTRUCTION_NODE
= 7,
88 DOCUMENT_TYPE_NODE
= 10,
89 DOCUMENT_FRAGMENT_NODE
= 11,
91 XPATH_NAMESPACE_NODE
= 13
94 static bool isSupported(const String
& feature
, const String
& version
);
96 static void startIgnoringLeaks();
97 static void stopIgnoringLeaks();
99 static void dumpStatistics();
101 enum StyleChange
{ NoChange
, NoInherit
, Inherit
, Detach
, Force
};
102 static StyleChange
diff(RenderStyle
*, RenderStyle
*);
104 Node(Document
*, bool isElement
= false, bool isContainer
= false, bool isText
= false);
107 // DOM methods & attributes for Node
109 bool hasTagName(const QualifiedName
&) const;
110 virtual String
nodeName() const = 0;
111 virtual String
nodeValue() const;
112 virtual void setNodeValue(const String
&, ExceptionCode
&);
113 virtual NodeType
nodeType() const = 0;
114 Node
* parentNode() const { return parent(); }
115 Element
* parentElement() const;
116 Node
* previousSibling() const { return m_previous
; }
117 Node
* nextSibling() const { return m_next
; }
118 PassRefPtr
<NodeList
> childNodes();
119 Node
* firstChild() const { return isContainerNode() ? containerFirstChild() : 0; }
120 Node
* lastChild() const { return isContainerNode() ? containerLastChild() : 0; }
121 bool hasAttributes() const;
122 NamedAttrMap
* attributes() const;
124 virtual KURL
baseURI() const;
126 void getSubresourceURLs(ListHashSet
<KURL
>&) const;
128 // These should all actually return a node, but this is only important for language bindings,
129 // which will already know and hold a ref on the right node to return. Returning bool allows
130 // these methods to be more efficient since they don't need to return a ref
131 virtual bool insertBefore(PassRefPtr
<Node
> newChild
, Node
* refChild
, ExceptionCode
&, bool shouldLazyAttach
= false);
132 virtual bool replaceChild(PassRefPtr
<Node
> newChild
, Node
* oldChild
, ExceptionCode
&, bool shouldLazyAttach
= false);
133 virtual bool removeChild(Node
* child
, ExceptionCode
&);
134 virtual bool appendChild(PassRefPtr
<Node
> newChild
, ExceptionCode
&, bool shouldLazyAttach
= false);
136 void remove(ExceptionCode
&);
137 bool hasChildNodes() const { return firstChild(); }
138 virtual PassRefPtr
<Node
> cloneNode(bool deep
) = 0;
139 const AtomicString
& localName() const { return virtualLocalName(); }
140 const AtomicString
& namespaceURI() const { return virtualNamespaceURI(); }
141 const AtomicString
& prefix() const { return virtualPrefix(); }
142 virtual void setPrefix(const AtomicString
&, ExceptionCode
&);
145 bool isSameNode(Node
* other
) const { return this == other
; }
146 bool isEqualNode(Node
*) const;
147 bool isDefaultNamespace(const AtomicString
& namespaceURI
) const;
148 String
lookupPrefix(const AtomicString
& namespaceURI
) const;
149 String
lookupNamespaceURI(const String
& prefix
) const;
150 String
lookupNamespacePrefix(const AtomicString
& namespaceURI
, const Element
* originalElement
) const;
152 String
textContent(bool convertBRsToNewlines
= false) const;
153 void setTextContent(const String
&, ExceptionCode
&);
155 Node
* lastDescendant() const;
156 Node
* firstDescendant() const;
158 // Other methods (not part of DOM)
160 bool isElementNode() const { return m_isElement
; }
161 bool isContainerNode() const { return m_isContainer
; }
162 bool isTextNode() const { return m_isText
; }
164 virtual bool isHTMLElement() const { return false; }
167 virtual bool isSVGElement() const { return false; }
169 static bool isSVGElement() { return false; }
173 virtual bool isWMLElement() const { return false; }
175 static bool isWMLElement() { return false; }
178 virtual bool isStyledElement() const { return false; }
179 virtual bool isFrameOwnerElement() const { return false; }
180 virtual bool isAttributeNode() const { return false; }
181 virtual bool isCommentNode() const { return false; }
182 virtual bool isCharacterDataNode() const { return false; }
183 bool isDocumentNode() const;
184 virtual bool isEventTargetNode() const { return false; }
185 virtual bool isShadowNode() const { return false; }
186 virtual Node
* shadowParentNode() { return 0; }
187 Node
* shadowAncestorNode();
188 Node
* shadowTreeRootNode();
189 bool isInShadowTree();
191 // The node's parent for the purpose of event capture and bubbling.
192 virtual ContainerNode
* eventParentNode();
194 bool isBlockFlow() const;
195 bool isBlockFlowOrBlockTable() const;
197 // These low-level calls give the caller responsibility for maintaining the integrity of the tree.
198 void setPreviousSibling(Node
* previous
) { m_previous
= previous
; }
199 void setNextSibling(Node
* next
) { m_next
= next
; }
201 // FIXME: These two functions belong in editing -- "atomic node" is an editing concept.
202 Node
* previousNodeConsideringAtomicNodes() const;
203 Node
* nextNodeConsideringAtomicNodes() const;
205 /** (Not part of the official DOM)
206 * Returns the next leaf node.
208 * Using this function delivers leaf nodes as if the whole DOM tree were a linear chain of its leaf nodes.
209 * @return next leaf node or 0 if there are no more.
211 Node
* nextLeafNode() const;
213 /** (Not part of the official DOM)
214 * Returns the previous leaf node.
216 * Using this function delivers leaf nodes as if the whole DOM tree were a linear chain of its leaf nodes.
217 * @return previous leaf node or 0 if there are no more.
219 Node
* previousLeafNode() const;
221 bool isEditableBlock() const;
223 // enclosingBlockFlowElement() is deprecated. Use enclosingBlock instead.
224 Element
* enclosingBlockFlowElement() const;
226 Element
* enclosingInlineElement() const;
227 Element
* rootEditableElement() const;
229 bool inSameContainingBlockFlowElement(Node
*);
231 // Used by the parser. Checks against the DTD, unlike DOM operations like appendChild().
232 // Also does not dispatch DOM mutation events.
233 // Returns the appropriate container node for future insertions as you parse, or 0 for failure.
234 virtual ContainerNode
* addChild(PassRefPtr
<Node
>);
236 // Called by the parser when this element's close tag is reached,
237 // signalling that all child tags have been parsed and added.
238 // This is needed for <applet> and <object> elements, which can't lay themselves out
239 // until they know all of their nested <param>s. [Radar 3603191, 4040848].
240 // Also used for script elements and some SVG elements for similar purposes,
241 // but making parsing a special case in this respect should be avoided if possible.
242 virtual void finishParsingChildren() { }
243 virtual void beginParsingChildren() { }
245 // Called by the frame right before dispatching an unloadEvent. [Radar 4532113]
246 // This is needed for HTMLInputElements to tell the frame that it is done editing
247 // (sends textFieldDidEndEditing notification)
248 virtual void aboutToUnload() { }
250 // For <link> and <style> elements.
251 virtual bool sheetLoaded() { return true; }
253 bool hasID() const { return m_hasId
; }
254 bool hasClass() const { return m_hasClass
; }
255 bool active() const { return m_active
; }
256 bool inActiveChain() const { return m_inActiveChain
; }
257 bool inDetach() const { return m_inDetach
; }
258 bool hovered() const { return m_hovered
; }
259 bool focused() const { return hasRareData() ? rareDataFocused() : false; }
260 bool attached() const { return m_attached
; }
261 void setAttached(bool b
= true) { m_attached
= b
; }
262 bool changed() const { return m_styleChange
!= NoStyleChange
; }
263 StyleChangeType
styleChangeType() const { return static_cast<StyleChangeType
>(m_styleChange
); }
264 bool hasChangedChild() const { return m_hasChangedChild
; }
265 bool isLink() const { return m_isLink
; }
266 void setHasID(bool b
= true) { m_hasId
= b
; }
267 void setHasClass(bool b
= true) { m_hasClass
= b
; }
268 void setHasChangedChild( bool b
= true ) { m_hasChangedChild
= b
; }
269 void setInDocument(bool b
= true) { m_inDocument
= b
; }
270 void setInActiveChain(bool b
= true) { m_inActiveChain
= b
; }
271 void setChanged(StyleChangeType changeType
= FullStyleChange
);
272 void setIsLink(bool b
= true) { m_isLink
= b
; }
274 bool inSubtreeMark() const { return m_inSubtreeMark
; }
275 void setInSubtreeMark(bool b
= true) { m_inSubtreeMark
= b
; }
278 virtual bool canLazyAttach();
280 virtual void setFocus(bool b
= true);
281 virtual void setActive(bool b
= true, bool /*pause*/ = false) { m_active
= b
; }
282 virtual void setHovered(bool b
= true) { m_hovered
= b
; }
284 virtual short tabIndex() const;
287 * Whether this node can receive the keyboard focus.
289 virtual bool supportsFocus() const { return isFocusable(); }
290 virtual bool isFocusable() const;
291 virtual bool isKeyboardFocusable(KeyboardEvent
*) const;
292 virtual bool isMouseFocusable() const;
294 virtual bool isAutofilled() const { return false; }
295 virtual bool isControl() const { return false; } // Eventually the notion of what is a control will be extensible.
296 virtual bool isEnabled() const { return true; }
297 virtual bool isChecked() const { return false; }
298 virtual bool isIndeterminate() const { return false; }
299 virtual bool isReadOnlyControl() const { return false; }
300 virtual bool isTextControl() const { return false; }
302 virtual bool isContentEditable() const;
303 virtual bool isContentRichlyEditable() const;
304 virtual bool shouldUseInputMethod() const;
305 virtual IntRect
getRect() const;
307 virtual void recalcStyle(StyleChange
= NoChange
) { }
309 unsigned nodeIndex() const;
311 // Returns the DOM ownerDocument attribute. This method never returns NULL, except in the case
312 // of (1) a Document node or (2) a DocumentType node that is not used with any Document yet.
313 virtual Document
* ownerDocument() const;
315 // Returns the document associated with this node. This method never returns NULL, except in the case
316 // of a DocumentType node that is not used with any Document yet. A Document node returns itself.
317 Document
* document() const
320 ASSERT(m_document
|| nodeType() == DOCUMENT_TYPE_NODE
&& !inDocument());
321 return m_document
.get();
323 void setDocument(Document
*);
325 // Returns true if this node is associated with a document and is in its associated document's
326 // node tree, false otherwise.
327 bool inDocument() const
329 ASSERT(m_document
|| !m_inDocument
);
333 bool isReadOnlyNode() const { return nodeType() == ENTITY_REFERENCE_NODE
; }
334 virtual bool childTypeAllowed(NodeType
) { return false; }
335 unsigned childNodeCount() const { return isContainerNode() ? containerChildNodeCount() : 0; }
336 Node
* childNode(unsigned index
) const { return isContainerNode() ? containerChildNode(index
) : 0; }
339 * Does a pre-order traversal of the tree to find the node next node after this one. This uses the same order that
340 * the tags appear in the source file.
342 * @param stayWithin If not null, the traversal will stop once the specified node is reached. This can be used to
343 * restrict traversal to a particular sub-tree.
345 * @return The next node, in document order
347 * see @ref traversePreviousNode()
349 Node
* traverseNextNode(const Node
* stayWithin
= 0) const;
351 // Like traverseNextNode, but skips children and starts with the next sibling.
352 Node
* traverseNextSibling(const Node
* stayWithin
= 0) const;
355 * Does a reverse pre-order traversal to find the node that comes before the current one in document order
357 * see @ref traverseNextNode()
359 Node
* traversePreviousNode(const Node
* stayWithin
= 0) const;
361 // Like traverseNextNode, but visits parents after their children.
362 Node
* traverseNextNodePostOrder() const;
364 // Like traversePreviousNode, but visits parents before their children.
365 Node
* traversePreviousNodePostOrder(const Node
*stayWithin
= 0) const;
366 Node
* traversePreviousSiblingPostOrder(const Node
*stayWithin
= 0) const;
369 * Finds previous or next editable leaf node.
371 Node
* previousEditable() const;
372 Node
* nextEditable() const;
374 RenderObject
* renderer() const { return m_renderer
; }
375 RenderObject
* nextRenderer();
376 RenderObject
* previousRenderer();
377 void setRenderer(RenderObject
* renderer
) { m_renderer
= renderer
; }
379 // Use with caution. Does no type checking. Mostly a convenience method for shadow nodes of form controls, where we know exactly
380 // what kind of renderer we made.
381 RenderBox
* renderBox() const;
383 void checkSetPrefix(const AtomicString
& prefix
, ExceptionCode
&);
384 bool isDescendantOrShadowDescendantOf(const Node
* otherNode
);
385 bool isDescendantOf(const Node
*) const;
386 bool contains(const Node
*) const;
388 // These two methods are mutually exclusive. The former is used to do strict error-checking
389 // when adding children via the public DOM API (e.g., appendChild()). The latter is called only when parsing,
390 // to sanity-check against the DTD for error recovery.
391 void checkAddChild(Node
* newChild
, ExceptionCode
&); // Error-checking when adding via the DOM API
392 virtual bool childAllowed(Node
* newChild
); // Error-checking during parsing that checks the DTD
394 void checkReplaceChild(Node
* newChild
, Node
* oldChild
, ExceptionCode
&);
395 virtual bool canReplaceChild(Node
* newChild
, Node
* oldChild
);
397 // Used to determine whether range offsets use characters or node indices.
398 virtual bool offsetInCharacters() const;
399 // Number of DOM 16-bit units contained in node. Note that rendered text length can be different - e.g. because of
400 // css-transform:capitalize breaking up precomposed characters and ligatures.
401 virtual int maxCharacterOffset() const;
403 // FIXME: We should try to find a better location for these methods.
404 virtual bool canSelectAll() const { return false; }
405 virtual void selectAll() { }
407 // Whether or not a selection can be started in this object
408 virtual bool canStartSelection() const;
410 // Getting points into and out of screen space
411 FloatPoint
convertToPage(const FloatPoint
& p
) const;
412 FloatPoint
convertFromPage(const FloatPoint
& p
) const;
414 // -----------------------------------------------------------------------------
415 // Integration with rendering tree
418 * Attaches this node to the rendering tree. This calculates the style to be applied to the node and creates an
419 * appropriate RenderObject which will be inserted into the tree (except when the style has display: none). This
420 * makes the node visible in the FrameView.
422 virtual void attach();
425 * Detaches the node from the rendering tree, making it invisible in the rendered view. This method will remove
426 * the node's rendering object from the rendering tree and delete it.
428 virtual void detach();
430 virtual void willRemove();
431 void createRendererIfNeeded();
432 PassRefPtr
<RenderStyle
> styleForRenderer();
433 virtual bool rendererIsNeeded(RenderStyle
*);
435 virtual bool childShouldCreateRenderer(Node
*) const { return true; }
437 virtual RenderObject
* createRenderer(RenderArena
*, RenderStyle
*);
439 // Wrapper for nodes that don't have a renderer, but still cache the style (like HTMLOptionElement).
440 RenderStyle
* renderStyle() const;
441 virtual void setRenderStyle(PassRefPtr
<RenderStyle
>);
443 virtual RenderStyle
* computedStyle();
445 // -----------------------------------------------------------------------------
446 // Notification of document structure changes
449 * Notifies the node that it has been inserted into the document. This is called during document parsing, and also
450 * when a node is added through the DOM methods insertBefore(), appendChild() or replaceChild(). Note that this only
451 * happens when the node becomes part of the document tree, i.e. only when the document is actually an ancestor of
452 * the node. The call happens _after_ the node has been added to the tree.
454 * This is similar to the DOMNodeInsertedIntoDocument DOM event, but does not require the overhead of event
457 virtual void insertedIntoDocument();
460 * Notifies the node that it is no longer part of the document tree, i.e. when the document is no longer an ancestor
463 * This is similar to the DOMNodeRemovedFromDocument DOM event, but does not require the overhead of event
464 * dispatching, and is called _after_ the node is removed from the tree.
466 virtual void removedFromDocument();
468 // These functions are called whenever you are connected or disconnected from a tree. That tree may be the main
469 // document tree, or it could be another disconnected tree. Override these functions to do any work that depends
470 // on connectedness to some ancestor (e.g., an ancestor <form> for example).
471 virtual void insertedIntoTree(bool /*deep*/) { }
472 virtual void removedFromTree(bool /*deep*/) { }
475 * Notifies the node that it's list of children have changed (either by adding or removing child nodes), or a child
476 * node that is of the type CDATA_SECTION_NODE, TEXT_NODE or COMMENT_NODE has changed its value.
478 virtual void childrenChanged(bool /*changedByParser*/ = false, Node
* /*beforeChange*/ = 0, Node
* /*afterChange*/ = 0, int /*childCountDelta*/ = 0) { }
481 virtual void formatForDebugger(char* buffer
, unsigned length
) const;
483 void showNode(const char* prefix
= "") const;
484 void showTreeForThis() const;
485 void showTreeAndMark(const Node
* markedNode1
, const char* markedLabel1
, const Node
* markedNode2
= 0, const char* markedLabel2
= 0) const;
488 void registerDynamicNodeList(DynamicNodeList
*);
489 void unregisterDynamicNodeList(DynamicNodeList
*);
490 void notifyNodeListsChildrenChanged();
491 void notifyLocalNodeListsChildrenChanged();
492 void notifyNodeListsAttributeChanged();
493 void notifyLocalNodeListsAttributeChanged();
495 PassRefPtr
<NodeList
> getElementsByTagName(const String
&);
496 PassRefPtr
<NodeList
> getElementsByTagNameNS(const AtomicString
& namespaceURI
, const String
& localName
);
497 PassRefPtr
<NodeList
> getElementsByName(const String
& elementName
);
498 PassRefPtr
<NodeList
> getElementsByClassName(const String
& classNames
);
500 virtual bool willRespondToMouseMoveEvents();
501 virtual bool willRespondToMouseWheelEvents();
502 virtual bool willRespondToMouseClickEvents();
504 PassRefPtr
<Element
> querySelector(const String
& selectors
, ExceptionCode
&);
505 PassRefPtr
<NodeList
> querySelectorAll(const String
& selectors
, ExceptionCode
&);
507 unsigned short compareDocumentPosition(Node
*);
510 virtual void willMoveToNewOwnerDocument() { }
511 virtual void didMoveToNewOwnerDocument() { }
513 virtual void addSubresourceAttributeURLs(ListHashSet
<KURL
>&) const { }
514 void setTabIndexExplicitly(short);
516 bool hasRareData() const { return m_hasRareData
; }
518 NodeRareData
* rareData() const;
519 NodeRareData
* ensureRareData();
522 virtual NodeRareData
* createRareData();
523 Node
* containerChildNode(unsigned index
) const;
524 unsigned containerChildNodeCount() const;
525 Node
* containerFirstChild() const;
526 Node
* containerLastChild() const;
527 bool rareDataFocused() const;
529 virtual RenderStyle
* nonRendererRenderStyle() const;
531 virtual const AtomicString
& virtualPrefix() const;
532 virtual const AtomicString
& virtualLocalName() const;
533 virtual const AtomicString
& virtualNamespaceURI() const;
535 Element
* ancestorElement() const;
537 void appendTextContent(bool convertBRsToNewlines
, StringBuilder
&) const;
539 DocPtr
<Document
> m_document
;
542 RenderObject
* m_renderer
;
544 unsigned m_styleChange
: 2;
548 bool m_hasChangedChild
: 1;
549 bool m_inDocument
: 1;
553 bool m_inActiveChain
: 1;
555 bool m_inSubtreeMark
: 1;
556 bool m_hasRareData
: 1;
557 const bool m_isElement
: 1;
558 const bool m_isContainer
: 1;
559 const bool m_isText
: 1;
562 // These bits are used by the Element derived class, pulled up here so they can
563 // be stored in the same memory word as the Node bits above.
564 bool m_parsingChildrenFinished
: 1;
566 mutable bool m_areSVGAttributesValid
: 1;
569 // These bits are used by the StyledElement derived class, and live here for the
570 // same reason as above.
571 mutable bool m_isStyleAttributeValid
: 1;
572 mutable bool m_synchronizingStyleAttribute
: 1;
575 // This bit is used by the SVGElement derived class, and lives here for the same
577 mutable bool m_synchronizingSVGAttributes
: 1;
583 // Used in Node::addSubresourceAttributeURLs() and in addSubresourceStyleURLs()
584 inline void addSubresourceURL(ListHashSet
<KURL
>& urls
, const KURL
& url
)
593 // Outside the WebCore namespace for ease of invocation from gdb.
594 void showTree(const WebCore::Node
*);