• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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, 2009, 2010, 2011 Apple Inc. All rights reserved.
6  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  */
24 
25 #ifndef Node_h
26 #define Node_h
27 
28 #include "bindings/v8/ExceptionStatePlaceholder.h"
29 #include "bindings/v8/ScriptWrappable.h"
30 #include "core/dom/MutationObserver.h"
31 #include "core/dom/SimulatedClickOptions.h"
32 #include "core/dom/TreeScope.h"
33 #include "core/dom/TreeShared.h"
34 #include "core/editing/EditingBoundary.h"
35 #include "core/events/EventTarget.h"
36 #include "core/inspector/InspectorCounters.h"
37 #include "core/rendering/style/RenderStyleConstants.h"
38 #include "platform/geometry/LayoutRect.h"
39 #include "platform/weborigin/KURLHash.h"
40 #include "wtf/Forward.h"
41 #include "wtf/ListHashSet.h"
42 #include "wtf/text/AtomicString.h"
43 
44 // This needs to be here because Document.h also depends on it.
45 #define DUMP_NODE_STATISTICS 0
46 
47 namespace WebCore {
48 
49 class Attribute;
50 class ClassNodeList;
51 class ContainerNode;
52 class DOMSettableTokenList;
53 class Document;
54 class Element;
55 class Event;
56 class EventContext;
57 class EventDispatchMediator;
58 class EventListener;
59 class ExceptionState;
60 class FloatPoint;
61 class Frame;
62 class HTMLInputElement;
63 class IntRect;
64 class KeyboardEvent;
65 class NSResolver;
66 class NameNodeList;
67 class NamedNodeMap;
68 class NodeList;
69 class NodeListsNodeData;
70 class NodeRareData;
71 class NodeRenderingContext;
72 class PlatformGestureEvent;
73 class PlatformKeyboardEvent;
74 class PlatformMouseEvent;
75 class PlatformWheelEvent;
76 class QualifiedName;
77 class RadioNodeList;
78 class RegisteredEventListener;
79 class RenderBox;
80 class RenderBoxModelObject;
81 class RenderObject;
82 class RenderStyle;
83 class ShadowRoot;
84 class TagNodeList;
85 class Text;
86 class TouchEvent;
87 
88 const int nodeStyleChangeShift = 14;
89 
90 enum StyleChangeType {
91     NoStyleChange = 0,
92     LocalStyleChange = 1 << nodeStyleChangeShift,
93     SubtreeStyleChange = 2 << nodeStyleChangeShift,
94     NeedsReattachStyleChange = 3 << nodeStyleChangeShift,
95 };
96 
97 // If the style change is from the renderer then we'll call setStyle on the
98 // renderer even if the style computed from CSS is identical.
99 enum StyleChangeSource {
100     StyleChangeFromCSS,
101     StyleChangeFromRenderer
102 };
103 
104 class NodeRareDataBase {
105 public:
renderer()106     RenderObject* renderer() const { return m_renderer; }
setRenderer(RenderObject * renderer)107     void setRenderer(RenderObject* renderer) { m_renderer = renderer; }
108 
109 protected:
NodeRareDataBase(RenderObject * renderer)110     NodeRareDataBase(RenderObject* renderer)
111         : m_renderer(renderer)
112     { }
113 
114 private:
115     RenderObject* m_renderer;
116 };
117 
118 class Node : public EventTarget, public ScriptWrappable, public TreeShared<Node> {
119     friend class Document;
120     friend class TreeScope;
121     friend class TreeScopeAdopter;
122 
123     DEFINE_EVENT_TARGET_REFCOUNTING(TreeShared<Node>);
124 public:
125     enum NodeType {
126         ELEMENT_NODE = 1,
127         ATTRIBUTE_NODE = 2,
128         TEXT_NODE = 3,
129         CDATA_SECTION_NODE = 4,
130         ENTITY_NODE = 6,
131         PROCESSING_INSTRUCTION_NODE = 7,
132         COMMENT_NODE = 8,
133         DOCUMENT_NODE = 9,
134         DOCUMENT_TYPE_NODE = 10,
135         DOCUMENT_FRAGMENT_NODE = 11,
136         NOTATION_NODE = 12,
137         XPATH_NAMESPACE_NODE = 13,
138     };
139 
140     // EntityReference nodes are deprecated and impossible to create in WebKit.
141     // We want Node.ENTITY_REFERNCE_NODE to exist in JS and this enum, makes the bindings
142     // generation not complain about ENTITY_REFERENCE_NODE being missing from the implementation
143     // while not requiring all switch(NodeType) blocks to include this deprecated constant.
144     enum DeprecatedNodeType {
145         ENTITY_REFERENCE_NODE = 5
146     };
147 
148     enum DocumentPosition {
149         DOCUMENT_POSITION_EQUIVALENT = 0x00,
150         DOCUMENT_POSITION_DISCONNECTED = 0x01,
151         DOCUMENT_POSITION_PRECEDING = 0x02,
152         DOCUMENT_POSITION_FOLLOWING = 0x04,
153         DOCUMENT_POSITION_CONTAINS = 0x08,
154         DOCUMENT_POSITION_CONTAINED_BY = 0x10,
155         DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20,
156     };
157 
158     // All Nodes are placed in their own heap partition for security.
159     // See http://crbug.com/246860 for detail.
160     void* operator new(size_t);
161     void operator delete(void*);
162 
163     static bool isSupported(const String& feature, const String& version);
164     static void dumpStatistics();
165 
166     virtual ~Node();
167 
168     // DOM methods & attributes for Node
169 
170     bool hasTagName(const QualifiedName&) const;
171     virtual String nodeName() const = 0;
172     virtual String nodeValue() const;
173     virtual void setNodeValue(const String&);
174     virtual NodeType nodeType() const = 0;
175     ContainerNode* parentNode() const;
176     Element* parentElement() const;
previousSibling()177     Node* previousSibling() const { return m_previous; }
nextSibling()178     Node* nextSibling() const { return m_next; }
179     PassRefPtr<NodeList> childNodes();
180     Node* firstChild() const;
181     Node* lastChild() const;
182 
183     // ChildNode interface API
184     Element* previousElementSibling() const;
185     Element* nextElementSibling() const;
186     void remove(ExceptionState&);
187 
188     Node* pseudoAwareNextSibling() const;
189     Node* pseudoAwarePreviousSibling() const;
190     Node* pseudoAwareFirstChild() const;
191     Node* pseudoAwareLastChild() const;
192 
193     virtual KURL baseURI() const;
194 
195     // These should all actually return a node, but this is only important for language bindings,
196     // which will already know and hold a ref on the right node to return.
197     void insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionState& = ASSERT_NO_EXCEPTION);
198     void replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionState& = ASSERT_NO_EXCEPTION);
199     void removeChild(Node* child, ExceptionState&);
200     void appendChild(PassRefPtr<Node> newChild, ExceptionState& = ASSERT_NO_EXCEPTION);
201 
hasChildNodes()202     bool hasChildNodes() const { return firstChild(); }
203     virtual PassRefPtr<Node> cloneNode(bool deep = false) = 0;
204     virtual const AtomicString& localName() const;
205     virtual const AtomicString& namespaceURI() const;
206     virtual const AtomicString& prefix() const;
207     virtual void setPrefix(const AtomicString&, ExceptionState&);
208     void normalize();
209 
isSameNode(Node * other)210     bool isSameNode(Node* other) const { return this == other; }
211     bool isEqualNode(Node*) const;
212     bool isDefaultNamespace(const AtomicString& namespaceURI) const;
213     const AtomicString& lookupPrefix(const AtomicString& namespaceURI) const;
214     const AtomicString& lookupNamespaceURI(const String& prefix) const;
215     const AtomicString& lookupNamespacePrefix(const AtomicString& namespaceURI, const Element* originalElement) const;
216 
217     String textContent(bool convertBRsToNewlines = false) const;
218     void setTextContent(const String&);
219 
220     Node& lastDescendant() const;
221 
222     // Other methods (not part of DOM)
223 
isElementNode()224     bool isElementNode() const { return getFlag(IsElementFlag); }
isContainerNode()225     bool isContainerNode() const { return getFlag(IsContainerFlag); }
isTextNode()226     bool isTextNode() const { return getFlag(IsTextFlag); }
isHTMLElement()227     bool isHTMLElement() const { return getFlag(IsHTMLFlag); }
isSVGElement()228     bool isSVGElement() const { return getFlag(IsSVGFlag); }
229 
isPseudoElement()230     bool isPseudoElement() const { return pseudoId() != NOPSEUDO; }
isBeforePseudoElement()231     bool isBeforePseudoElement() const { return pseudoId() == BEFORE; }
isAfterPseudoElement()232     bool isAfterPseudoElement() const { return pseudoId() == AFTER; }
pseudoId()233     PseudoId pseudoId() const { return (isElementNode() && hasCustomStyleCallbacks()) ? customPseudoId() : NOPSEUDO; }
234 
isCustomElement()235     bool isCustomElement() const { return getFlag(CustomElement); }
236     enum CustomElementState {
237         NotCustomElement  = 0,
238         WaitingForUpgrade = 1 << 0,
239         Upgraded          = 1 << 1
240     };
customElementState()241     CustomElementState customElementState() const
242     {
243         return isCustomElement()
244             ? (getFlag(CustomElementUpgraded) ? Upgraded : WaitingForUpgrade)
245             : NotCustomElement;
246     }
247     void setCustomElementState(CustomElementState newState);
248 
isMediaControlElement()249     virtual bool isMediaControlElement() const { return false; }
isMediaControls()250     virtual bool isMediaControls() const { return false; }
isVTTElement()251     virtual bool isVTTElement() const { return false; }
isAttributeNode()252     virtual bool isAttributeNode() const { return false; }
isCharacterDataNode()253     virtual bool isCharacterDataNode() const { return false; }
isFrameOwnerElement()254     virtual bool isFrameOwnerElement() const { return false; }
isPluginElement()255     virtual bool isPluginElement() const { return false; }
256 
257     // StyledElements allow inline style (style="border: 1px"), presentational attributes (ex. color),
258     // class names (ex. class="foo bar") and other non-basic styling features. They and also control
259     // if this element can participate in style sharing.
260     //
261     // FIXME: The only things that ever go through StyleResolver that aren't StyledElements are
262     // PseudoElements and VTTElements. It's possible we can just eliminate all the checks
263     // since those elements will never have class names, inline style, or other things that
264     // this apparently guards against.
isStyledElement()265     bool isStyledElement() const { return isHTMLElement() || isSVGElement(); }
266 
267     bool isDocumentNode() const;
isTreeScope()268     bool isTreeScope() const { return treeScope().rootNode() == this; }
isDocumentFragment()269     bool isDocumentFragment() const { return getFlag(IsDocumentFragmentFlag); }
isShadowRoot()270     bool isShadowRoot() const { return isDocumentFragment() && isTreeScope(); }
isInsertionPoint()271     bool isInsertionPoint() const { return getFlag(IsInsertionPointFlag); }
272 
inNamedFlow()273     bool inNamedFlow() const { return getFlag(InNamedFlowFlag); }
hasCustomStyleCallbacks()274     bool hasCustomStyleCallbacks() const { return getFlag(HasCustomStyleCallbacksFlag); }
275 
276     bool isRegisteredWithNamedFlow() const;
277 
hasSyntheticAttrChildNodes()278     bool hasSyntheticAttrChildNodes() const { return getFlag(HasSyntheticAttrChildNodesFlag); }
setHasSyntheticAttrChildNodes(bool flag)279     void setHasSyntheticAttrChildNodes(bool flag) { setFlag(flag, HasSyntheticAttrChildNodesFlag); }
280 
281     // If this node is in a shadow tree, returns its shadow host. Otherwise, returns 0.
282     Element* shadowHost() const;
283     // If this node is in a shadow tree, returns its shadow host. Otherwise, returns this.
284     // Deprecated. Should use shadowHost() and check the return value.
285     Node* deprecatedShadowAncestorNode() const;
286     ShadowRoot* containingShadowRoot() const;
287     ShadowRoot* youngestShadowRoot() const;
288 
289     // Returns 0, a child of ShadowRoot, or a legacy shadow root.
290     Node* nonBoundaryShadowTreeRootNode();
291 
292     // Node's parent, shadow tree host.
293     ContainerNode* parentOrShadowHostNode() const;
294     Element* parentOrShadowHostElement() const;
295     void setParentOrShadowHostNode(ContainerNode*);
296     Node* highestAncestor() const;
297 
298     // Knows about all kinds of hosts.
299     ContainerNode* parentOrShadowHostOrTemplateHostNode() const;
300 
301     // Returns the parent node, but 0 if the parent node is a ShadowRoot.
302     ContainerNode* nonShadowBoundaryParentNode() const;
303 
selfOrAncestorHasDirAutoAttribute()304     bool selfOrAncestorHasDirAutoAttribute() const { return getFlag(SelfOrAncestorHasDirAutoFlag); }
setSelfOrAncestorHasDirAutoAttribute(bool flag)305     void setSelfOrAncestorHasDirAutoAttribute(bool flag) { setFlag(flag, SelfOrAncestorHasDirAutoFlag); }
306 
307     // Returns the enclosing event parent node (or self) that, when clicked, would trigger a navigation.
308     Node* enclosingLinkEventParentOrSelf();
309 
310     bool isBlockFlowElement() const;
311 
312     // These low-level calls give the caller responsibility for maintaining the integrity of the tree.
setPreviousSibling(Node * previous)313     void setPreviousSibling(Node* previous) { m_previous = previous; }
setNextSibling(Node * next)314     void setNextSibling(Node* next) { m_next = next; }
315 
canContainRangeEndPoint()316     virtual bool canContainRangeEndPoint() const { return false; }
317 
318     // FIXME: These two functions belong in editing -- "atomic node" is an editing concept.
319     Node* previousNodeConsideringAtomicNodes() const;
320     Node* nextNodeConsideringAtomicNodes() const;
321 
322     // Returns the next leaf node or 0 if there are no more.
323     // Delivers leaf nodes as if the whole DOM tree were a linear chain of its leaf nodes.
324     // Uses an editing-specific concept of what a leaf node is, and should probably be moved
325     // out of the Node class into an editing-specific source file.
326     Node* nextLeafNode() const;
327 
328     // Returns the previous leaf node or 0 if there are no more.
329     // Delivers leaf nodes as if the whole DOM tree were a linear chain of its leaf nodes.
330     // Uses an editing-specific concept of what a leaf node is, and should probably be moved
331     // out of the Node class into an editing-specific source file.
332     Node* previousLeafNode() const;
333 
334     // enclosingBlockFlowElement() is deprecated. Use enclosingBlock instead.
335     Element* enclosingBlockFlowElement() const;
336 
337     bool isRootEditableElement() const;
338     Element* rootEditableElement() const;
339     Element* rootEditableElement(EditableType) const;
340 
341     bool inSameContainingBlockFlowElement(Node*);
342 
343     // Called by the parser when this element's close tag is reached,
344     // signaling that all child tags have been parsed and added.
345     // This is needed for <applet> and <object> elements, which can't lay themselves out
346     // until they know all of their nested <param>s. [Radar 3603191, 4040848].
347     // Also used for script elements and some SVG elements for similar purposes,
348     // but making parsing a special case in this respect should be avoided if possible.
finishParsingChildren()349     virtual void finishParsingChildren() { }
beginParsingChildren()350     virtual void beginParsingChildren() { }
351 
352     // For <link> and <style> elements.
sheetLoaded()353     virtual bool sheetLoaded() { return true; }
notifyLoadedSheetAndAllCriticalSubresources(bool)354     virtual void notifyLoadedSheetAndAllCriticalSubresources(bool /* error loading subresource */) { }
startLoadingDynamicSheet()355     virtual void startLoadingDynamicSheet() { ASSERT_NOT_REACHED(); }
356 
hasName()357     bool hasName() const { return !isTextNode() && getFlag(HasNameOrIsEditingTextFlag); }
358     bool hasID() const;
359     bool hasClass() const;
360 
isUserActionElement()361     bool isUserActionElement() const { return getFlag(IsUserActionElement); }
setUserActionElement(bool flag)362     void setUserActionElement(bool flag) { setFlag(flag, IsUserActionElement); }
363 
active()364     bool active() const { return isUserActionElement() && isUserActionElementActive(); }
inActiveChain()365     bool inActiveChain() const { return isUserActionElement() && isUserActionElementInActiveChain(); }
hovered()366     bool hovered() const { return isUserActionElement() && isUserActionElementHovered(); }
focused()367     bool focused() const { return isUserActionElement() && isUserActionElementFocused(); }
368 
needsAttach()369     bool needsAttach() const { return styleChangeType() == NeedsReattachStyleChange; }
needsStyleRecalc()370     bool needsStyleRecalc() const { return styleChangeType() != NoStyleChange; }
styleChangeType()371     StyleChangeType styleChangeType() const { return static_cast<StyleChangeType>(m_nodeFlags & StyleChangeMask); }
childNeedsStyleRecalc()372     bool childNeedsStyleRecalc() const { return getFlag(ChildNeedsStyleRecalcFlag); }
isLink()373     bool isLink() const { return getFlag(IsLinkFlag); }
isEditingText()374     bool isEditingText() const { return isTextNode() && getFlag(HasNameOrIsEditingTextFlag); }
375 
setHasName(bool f)376     void setHasName(bool f) { ASSERT(!isTextNode()); setFlag(f, HasNameOrIsEditingTextFlag); }
setChildNeedsStyleRecalc()377     void setChildNeedsStyleRecalc() { setFlag(ChildNeedsStyleRecalcFlag); }
clearChildNeedsStyleRecalc()378     void clearChildNeedsStyleRecalc() { clearFlag(ChildNeedsStyleRecalcFlag); }
379 
380     void setNeedsStyleRecalc(StyleChangeType = SubtreeStyleChange, StyleChangeSource = StyleChangeFromCSS);
381     void clearNeedsStyleRecalc();
382 
childNeedsDistributionRecalc()383     bool childNeedsDistributionRecalc() const { return getFlag(ChildNeedsDistributionRecalc); }
setChildNeedsDistributionRecalc()384     void setChildNeedsDistributionRecalc()  { setFlag(ChildNeedsDistributionRecalc); }
clearChildNeedsDistributionRecalc()385     void clearChildNeedsDistributionRecalc()  { clearFlag(ChildNeedsDistributionRecalc); }
386     void markAncestorsWithChildNeedsDistributionRecalc();
387 
388     void recalcDistribution();
389 
shouldNotifyRendererWithIdenticalStyles()390     bool shouldNotifyRendererWithIdenticalStyles() const { return getFlag(NotifyRendererWithIdenticalStyles); }
391 
392     void setIsLink(bool f);
393 
setInNamedFlow()394     void setInNamedFlow() { setFlag(InNamedFlowFlag); }
clearInNamedFlow()395     void clearInNamedFlow() { clearFlag(InNamedFlowFlag); }
396 
hasScopedHTMLStyleChild()397     bool hasScopedHTMLStyleChild() const { return getFlag(HasScopedHTMLStyleChildFlag); }
setHasScopedHTMLStyleChild(bool flag)398     void setHasScopedHTMLStyleChild(bool flag) { setFlag(flag, HasScopedHTMLStyleChildFlag); }
399 
hasEventTargetData()400     bool hasEventTargetData() const { return getFlag(HasEventTargetDataFlag); }
setHasEventTargetData(bool flag)401     void setHasEventTargetData(bool flag) { setFlag(flag, HasEventTargetDataFlag); }
402 
isV8CollectableDuringMinorGC()403     bool isV8CollectableDuringMinorGC() const { return getFlag(V8CollectableDuringMinorGCFlag); }
setV8CollectableDuringMinorGC(bool flag)404     void setV8CollectableDuringMinorGC(bool flag) { setFlag(flag, V8CollectableDuringMinorGCFlag); }
405 
406     virtual void setFocus(bool flag);
407     virtual void setActive(bool flag = true);
408     virtual void setHovered(bool flag = true);
409 
410     virtual short tabIndex() const;
411 
412     virtual Node* focusDelegate();
413     // This is called only when the node is focused.
414     virtual bool shouldHaveFocusAppearance() const;
415 
416     // Whether the node is inert. This can't be in Element because text nodes
417     // must be recognized as inert to prevent text selection.
418     bool isInert() const;
419 
420     enum UserSelectAllTreatment {
421         UserSelectAllDoesNotAffectEditability,
422         UserSelectAllIsAlwaysNonEditable
423     };
424     bool isContentEditable(UserSelectAllTreatment = UserSelectAllDoesNotAffectEditability);
425     bool isContentRichlyEditable();
426 
427     bool rendererIsEditable(EditableType editableType = ContentIsEditable, UserSelectAllTreatment treatment = UserSelectAllIsAlwaysNonEditable) const
428     {
429         switch (editableType) {
430         case ContentIsEditable:
431             return rendererIsEditable(Editable, treatment);
432         case HasEditableAXRole:
433             return isEditableToAccessibility(Editable);
434         }
435         ASSERT_NOT_REACHED();
436         return false;
437     }
438 
439     bool rendererIsRichlyEditable(EditableType editableType = ContentIsEditable) const
440     {
441         switch (editableType) {
442         case ContentIsEditable:
443             return rendererIsEditable(RichlyEditable, UserSelectAllIsAlwaysNonEditable);
444         case HasEditableAXRole:
445             return isEditableToAccessibility(RichlyEditable);
446         }
447         ASSERT_NOT_REACHED();
448         return false;
449     }
450 
451     virtual bool shouldUseInputMethod();
452     virtual LayoutRect boundingBox() const;
pixelSnappedBoundingBox()453     IntRect pixelSnappedBoundingBox() const { return pixelSnappedIntRect(boundingBox()); }
454 
455     // Returns true if the node has a non-empty bounding box in layout.
456     // This does not 100% guarantee the user can see it, but is pretty close.
457     // Note: This method only works properly after layout has occurred.
458     bool hasNonEmptyBoundingBox() const;
459 
460     unsigned nodeIndex() const;
461 
462     // Returns the DOM ownerDocument attribute. This method never returns NULL, except in the case
463     // of a Document node.
464     Document* ownerDocument() const;
465 
466     // Returns the document associated with this node. A Document node returns itself.
document()467     Document& document() const
468     {
469         ASSERT(this);
470         ASSERT(documentInternal());
471         return *documentInternal();
472     }
473 
treeScope()474     TreeScope& treeScope() const
475     {
476         ASSERT(m_treeScope);
477         return *m_treeScope;
478     }
479 
480     bool inActiveDocument() const;
481 
482     // Returns true if this node is associated with a document and is in its associated document's
483     // node tree, false otherwise.
inDocument()484     bool inDocument() const
485     {
486         ASSERT(documentInternal() || !getFlag(InDocumentFlag));
487         return getFlag(InDocumentFlag);
488     }
isInShadowTree()489     bool isInShadowTree() const { return getFlag(IsInShadowTreeFlag); }
isInTreeScope()490     bool isInTreeScope() const { return getFlag(static_cast<NodeFlags>(InDocumentFlag | IsInShadowTreeFlag)); }
491 
isDocumentTypeNode()492     bool isDocumentTypeNode() const { return nodeType() == DOCUMENT_TYPE_NODE; }
childTypeAllowed(NodeType)493     virtual bool childTypeAllowed(NodeType) const { return false; }
494     unsigned childNodeCount() const;
495     Node* childNode(unsigned index) const;
496 
497     void checkSetPrefix(const AtomicString& prefix, ExceptionState&);
498     bool isDescendantOf(const Node*) const;
499     bool contains(const Node*) const;
500     bool containsIncludingShadowDOM(const Node*) const;
501     bool containsIncludingHostElements(const Node&) const;
502     Node* commonAncestor(const Node&, Node* (*parent)(const Node&));
503 
504     // FIXME: Remove this when crbug.com/265716 cleans up contains semantics.
bindingsContains(const Node * node)505     bool bindingsContains(const Node* node) const { return containsIncludingShadowDOM(node); }
506 
507     // Used to determine whether range offsets use characters or node indices.
508     virtual bool offsetInCharacters() const;
509     // Number of DOM 16-bit units contained in node. Note that rendered text length can be different - e.g. because of
510     // css-transform:capitalize breaking up precomposed characters and ligatures.
511     virtual int maxCharacterOffset() const;
512 
513     // Whether or not a selection can be started in this object
514     virtual bool canStartSelection() const;
515 
516     // Getting points into and out of screen space
517     FloatPoint convertToPage(const FloatPoint&) const;
518     FloatPoint convertFromPage(const FloatPoint&) const;
519 
520     // -----------------------------------------------------------------------------
521     // Integration with rendering tree
522 
523     // As renderer() includes a branch you should avoid calling it repeatedly in hot code paths.
524     // Note that if a Node has a renderer, it's parentNode is guaranteed to have one as well.
renderer()525     RenderObject* renderer() const { return hasRareData() ? m_data.m_rareData->renderer() : m_data.m_renderer; };
setRenderer(RenderObject * renderer)526     void setRenderer(RenderObject* renderer)
527     {
528         if (hasRareData())
529             m_data.m_rareData->setRenderer(renderer);
530         else
531             m_data.m_renderer = renderer;
532     }
hasRenderer()533     bool hasRenderer() const { return renderer(); }
534 
535     // Use these two methods with caution.
536     RenderBox* renderBox() const;
537     RenderBoxModelObject* renderBoxModelObject() const;
538 
539     struct AttachContext {
540         RenderStyle* resolvedStyle;
541         bool performingReattach;
542 
AttachContextAttachContext543         AttachContext() : resolvedStyle(0), performingReattach(false) { }
544     };
545 
546     // Attaches this node to the rendering tree. This calculates the style to be applied to the node and creates an
547     // appropriate RenderObject which will be inserted into the tree (except when the style has display: none). This
548     // makes the node visible in the FrameView.
549     virtual void attach(const AttachContext& = AttachContext());
550 
551     // Detaches the node from the rendering tree, making it invisible in the rendered view. This method will remove
552     // the node's rendering object from the rendering tree and delete it.
553     virtual void detach(const AttachContext& = AttachContext());
554 
555 #ifndef NDEBUG
556     bool inDetach() const;
557 #endif
558 
559     void reattach(const AttachContext& = AttachContext());
560     void lazyReattachIfAttached();
561 
562     // Wrapper for nodes that don't have a renderer, but still cache the style (like HTMLOptionElement).
563     RenderStyle* renderStyle() const;
564     RenderStyle* parentRenderStyle() const;
565 
566     RenderStyle* computedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return virtualComputedStyle(pseudoElementSpecifier); }
567 
568     // -----------------------------------------------------------------------------
569     // Notification of document structure changes (see ContainerNode.h for more notification methods)
570     //
571     // At first, WebKit notifies the node that it has been inserted into the document. This is called during document parsing, and also
572     // when a node is added through the DOM methods insertBefore(), appendChild() or replaceChild(). The call happens _after_ the node has been added to the tree.
573     // This is similar to the DOMNodeInsertedIntoDocument DOM event, but does not require the overhead of event
574     // dispatching.
575     //
576     // WebKit notifies this callback regardless if the subtree of the node is a document tree or a floating subtree.
577     // Implementation can determine the type of subtree by seeing insertionPoint->inDocument().
578     // For a performance reason, notifications are delivered only to ContainerNode subclasses if the insertionPoint is out of document.
579     //
580     // There are another callback named didNotifySubtreeInsertionsToDocument(), which is called after all the descendant is notified,
581     // if this node was inserted into the document tree. Only a few subclasses actually need this. To utilize this, the node should
582     // return InsertionShouldCallDidNotifySubtreeInsertions from insrtedInto().
583     //
584     enum InsertionNotificationRequest {
585         InsertionDone,
586         InsertionShouldCallDidNotifySubtreeInsertions
587     };
588 
589     virtual InsertionNotificationRequest insertedInto(ContainerNode* insertionPoint);
didNotifySubtreeInsertionsToDocument()590     virtual void didNotifySubtreeInsertionsToDocument() { }
591 
592     // Notifies the node that it is no longer part of the tree.
593     //
594     // This is a dual of insertedInto(), and is similar to the DOMNodeRemovedFromDocument DOM event, but does not require the overhead of event
595     // dispatching, and is called _after_ the node is removed from the tree.
596     //
597     virtual void removedFrom(ContainerNode* insertionPoint);
598 
599     String debugName() const;
600 
601 #ifndef NDEBUG
602     virtual void formatForDebugger(char* buffer, unsigned length) const;
603 
604     void showNode(const char* prefix = "") const;
605     void showTreeForThis() const;
606     void showNodePathForThis() const;
607     void showTreeAndMark(const Node* markedNode1, const char* markedLabel1, const Node* markedNode2 = 0, const char* markedLabel2 = 0) const;
608     void showTreeForThisAcrossFrame() const;
609 #endif
610 
611     void invalidateNodeListCachesInAncestors(const QualifiedName* attrName = 0, Element* attributeOwnerElement = 0);
612     NodeListsNodeData* nodeLists();
613     void clearNodeLists();
614 
615     PassRefPtr<NodeList> getElementsByTagName(const AtomicString&);
616     PassRefPtr<NodeList> getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName);
617     PassRefPtr<NodeList> getElementsByName(const String& elementName);
618     PassRefPtr<NodeList> getElementsByClassName(const String& classNames);
619     PassRefPtr<RadioNodeList> radioNodeList(const AtomicString&);
620 
621     virtual bool willRespondToMouseMoveEvents();
622     virtual bool willRespondToMouseClickEvents();
623     virtual bool willRespondToTouchEvents();
624 
625     PassRefPtr<Element> querySelector(const AtomicString& selectors, ExceptionState&);
626     PassRefPtr<NodeList> querySelectorAll(const AtomicString& selectors, ExceptionState&);
627 
628     unsigned short compareDocumentPosition(const Node*) const;
629 
630     enum ShadowTreesTreatment {
631         TreatShadowTreesAsDisconnected,
632         TreatShadowTreesAsComposed
633     };
634 
635     unsigned short compareDocumentPositionInternal(const Node*, ShadowTreesTreatment) const;
636 
637     virtual Node* toNode();
638 
639     virtual const AtomicString& interfaceName() const OVERRIDE;
640     virtual ExecutionContext* executionContext() const OVERRIDE;
641 
642     virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
643     virtual bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture);
644 
645     // Handlers to do/undo actions on the target node before an event is dispatched to it and after the event
646     // has been dispatched.  The data pointer is handed back by the preDispatch and passed to postDispatch.
preDispatchEventHandler(Event *)647     virtual void* preDispatchEventHandler(Event*) { return 0; }
postDispatchEventHandler(Event *,void *)648     virtual void postDispatchEventHandler(Event*, void* /*dataFromPreDispatch*/) { }
649 
650     using EventTarget::dispatchEvent;
651     virtual bool dispatchEvent(PassRefPtr<Event>) OVERRIDE;
652 
653     void dispatchScopedEvent(PassRefPtr<Event>);
654     void dispatchScopedEventDispatchMediator(PassRefPtr<EventDispatchMediator>);
655 
656     virtual void handleLocalEvents(Event*);
657 
658     void dispatchSubtreeModifiedEvent();
659     bool dispatchDOMActivateEvent(int detail, PassRefPtr<Event> underlyingEvent);
660 
661     bool dispatchKeyEvent(const PlatformKeyboardEvent&);
662     bool dispatchWheelEvent(const PlatformWheelEvent&);
663     bool dispatchMouseEvent(const PlatformMouseEvent&, const AtomicString& eventType, int clickCount = 0, Node* relatedTarget = 0);
664     bool dispatchGestureEvent(const PlatformGestureEvent&);
665     bool dispatchTouchEvent(PassRefPtr<TouchEvent>);
666 
667     void dispatchSimulatedClick(Event* underlyingEvent, SimulatedClickMouseEventOptions = SendNoEvents);
668 
669     virtual bool dispatchBeforeLoadEvent(const String& sourceURL);
670     virtual void dispatchChangeEvent();
671     virtual void dispatchInputEvent();
672 
673     // Perform the default action for an event.
674     virtual void defaultEventHandler(Event*);
675     virtual void willCallDefaultEventHandler(const Event&);
676 
677     virtual EventTargetData* eventTargetData() OVERRIDE;
678     virtual EventTargetData& ensureEventTargetData() OVERRIDE;
679 
680     void getRegisteredMutationObserversOfType(HashMap<MutationObserver*, MutationRecordDeliveryOptions>&, MutationObserver::MutationType, const QualifiedName* attributeName);
681     void registerMutationObserver(MutationObserver*, MutationObserverOptions, const HashSet<AtomicString>& attributeFilter);
682     void unregisterMutationObserver(MutationObserverRegistration*);
683     void registerTransientMutationObserver(MutationObserverRegistration*);
684     void unregisterTransientMutationObserver(MutationObserverRegistration*);
685     void notifyMutationObserversNodeWillDetach();
686 
687     virtual void registerScopedHTMLStyleChild();
688     virtual void unregisterScopedHTMLStyleChild();
689     size_t numberOfScopedHTMLStyleChildren() const;
690 
691     unsigned connectedSubframeCount() const;
692     void incrementConnectedSubframeCount(unsigned amount = 1);
693     void decrementConnectedSubframeCount(unsigned amount = 1);
694     void updateAncestorConnectedSubframeCountForRemoval() const;
695     void updateAncestorConnectedSubframeCountForInsertion() const;
696 
697     PassRefPtr<NodeList> getDestinationInsertionPoints();
698 
setAlreadySpellChecked(bool flag)699     void setAlreadySpellChecked(bool flag) { setFlag(flag, AlreadySpellCheckedFlag); }
isAlreadySpellChecked()700     bool isAlreadySpellChecked() { return getFlag(AlreadySpellCheckedFlag); }
701 
702 private:
703     enum NodeFlags {
704         IsTextFlag = 1,
705         IsContainerFlag = 1 << 1,
706         IsElementFlag = 1 << 2,
707         IsHTMLFlag = 1 << 3,
708         IsSVGFlag = 1 << 4,
709 
710         ChildNeedsDistributionRecalc = 1 << 5,
711         ChildNeedsStyleRecalcFlag = 1 << 6,
712         InDocumentFlag = 1 << 7,
713         IsLinkFlag = 1 << 8,
714         IsUserActionElement = 1 << 9,
715         HasRareDataFlag = 1 << 10,
716         IsDocumentFragmentFlag = 1 << 11,
717 
718         // These bits are used by derived classes, pulled up here so they can
719         // be stored in the same memory word as the Node bits above.
720         IsParsingChildrenFinishedFlag = 1 << 12, // Element
721         HasSVGRareDataFlag = 1 << 13, // SVGElement
722 
723         StyleChangeMask = 1 << nodeStyleChangeShift | 1 << (nodeStyleChangeShift + 1),
724 
725         SelfOrAncestorHasDirAutoFlag = 1 << 16,
726 
727         HasNameOrIsEditingTextFlag = 1 << 17,
728 
729         InNamedFlowFlag = 1 << 18,
730         HasSyntheticAttrChildNodesFlag = 1 << 19,
731         HasCustomStyleCallbacksFlag = 1 << 20,
732         HasScopedHTMLStyleChildFlag = 1 << 21,
733         HasEventTargetDataFlag = 1 << 22,
734         V8CollectableDuringMinorGCFlag = 1 << 23,
735         IsInsertionPointFlag = 1 << 24,
736         IsInShadowTreeFlag = 1 << 25,
737 
738         NotifyRendererWithIdenticalStyles = 1 << 26,
739 
740         CustomElement = 1 << 27,
741         CustomElementUpgraded = 1 << 28,
742 
743         AlreadySpellCheckedFlag = 1 << 29,
744 
745         DefaultNodeFlags = IsParsingChildrenFinishedFlag | ChildNeedsStyleRecalcFlag | NeedsReattachStyleChange
746     };
747 
748     // 3 bits remaining.
749 
getFlag(NodeFlags mask)750     bool getFlag(NodeFlags mask) const { return m_nodeFlags & mask; }
setFlag(bool f,NodeFlags mask)751     void setFlag(bool f, NodeFlags mask) const { m_nodeFlags = (m_nodeFlags & ~mask) | (-(int32_t)f & mask); }
setFlag(NodeFlags mask)752     void setFlag(NodeFlags mask) const { m_nodeFlags |= mask; }
clearFlag(NodeFlags mask)753     void clearFlag(NodeFlags mask) const { m_nodeFlags &= ~mask; }
754 
755 protected:
756     enum ConstructionType {
757         CreateOther = DefaultNodeFlags,
758         CreateText = DefaultNodeFlags | IsTextFlag,
759         CreateContainer = DefaultNodeFlags | IsContainerFlag,
760         CreateElement = CreateContainer | IsElementFlag,
761         CreateShadowRoot = CreateContainer | IsDocumentFragmentFlag | IsInShadowTreeFlag,
762         CreateDocumentFragment = CreateContainer | IsDocumentFragmentFlag,
763         CreateHTMLElement = CreateElement | IsHTMLFlag,
764         CreateSVGElement = CreateElement | IsSVGFlag,
765         CreateDocument = CreateContainer | InDocumentFlag,
766         CreateInsertionPoint = CreateHTMLElement | IsInsertionPointFlag,
767         CreateEditingText = CreateText | HasNameOrIsEditingTextFlag,
768     };
769 
Node(TreeScope * treeScope,ConstructionType type)770     Node(TreeScope* treeScope, ConstructionType type)
771         : m_nodeFlags(type)
772         , m_parentOrShadowHostNode(0)
773         , m_treeScope(treeScope)
774         , m_previous(0)
775         , m_next(0)
776     {
777         ASSERT(m_treeScope || type == CreateDocument || type == CreateShadowRoot);
778         ScriptWrappable::init(this);
779         if (m_treeScope)
780             m_treeScope->guardRef();
781 
782 #if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS)
783         trackForDebugging();
784 #endif
785         InspectorCounters::incrementCounter(InspectorCounters::NodeCounter);
786     }
787 
788     virtual void didMoveToNewDocument(Document& oldDocument);
789 
addSubresourceAttributeURLs(ListHashSet<KURL> &)790     virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const { }
791 
792     static void reattachWhitespaceSiblings(Text* start);
793 
794     void willBeDeletedFromDocument();
795 
hasRareData()796     bool hasRareData() const { return getFlag(HasRareDataFlag); }
797 
798     NodeRareData* rareData() const;
799     NodeRareData& ensureRareData();
800     void clearRareData();
801 
802     void clearEventTargetData();
803 
setHasCustomStyleCallbacks()804     void setHasCustomStyleCallbacks() { setFlag(true, HasCustomStyleCallbacksFlag); }
805 
documentInternal()806     Document* documentInternal() const { return treeScope().documentScope(); }
setTreeScope(TreeScope * scope)807     void setTreeScope(TreeScope* scope) { m_treeScope = scope; }
808 
809     // isTreeScopeInitialized() can be false
810     // - in the destruction of Document or ShadowRoot where m_treeScope is set to null or
811     // - in the Node constructor called by these two classes where m_treeScope is set by TreeScope ctor.
isTreeScopeInitialized()812     bool isTreeScopeInitialized() const { return m_treeScope; }
813 
814     void markAncestorsWithChildNeedsStyleRecalc();
815 
816 private:
817     friend class TreeShared<Node>;
818 
customPseudoId()819     virtual PseudoId customPseudoId() const
820     {
821         ASSERT(hasCustomStyleCallbacks());
822         return NOPSEUDO;
823     }
824 
825     void removedLastRef();
hasTreeSharedParent()826     bool hasTreeSharedParent() const { return !!parentOrShadowHostNode(); }
827 
828     enum EditableLevel { Editable, RichlyEditable };
829     bool rendererIsEditable(EditableLevel, UserSelectAllTreatment = UserSelectAllIsAlwaysNonEditable) const;
830     bool isEditableToAccessibility(EditableLevel) const;
831 
832     bool isUserActionElementActive() const;
833     bool isUserActionElementInActiveChain() const;
834     bool isUserActionElementHovered() const;
835     bool isUserActionElementFocused() const;
836 
837     void traceStyleChange(StyleChangeType);
838     void traceStyleChangeIfNeeded(StyleChangeType);
839     void setStyleChange(StyleChangeType);
840 
nonRendererStyle()841     virtual RenderStyle* nonRendererStyle() const { return 0; }
842 
843     virtual RenderStyle* virtualComputedStyle(PseudoId = NOPSEUDO);
844 
845     Element* ancestorElement() const;
846 
847     void trackForDebugging();
848 
849     Vector<OwnPtr<MutationObserverRegistration> >* mutationObserverRegistry();
850     HashSet<MutationObserverRegistration*>* transientMutationObserverRegistry();
851 
852     mutable uint32_t m_nodeFlags;
853     ContainerNode* m_parentOrShadowHostNode;
854     TreeScope* m_treeScope;
855     Node* m_previous;
856     Node* m_next;
857     // When a node has rare data we move the renderer into the rare data.
858     union DataUnion {
DataUnion()859         DataUnion() : m_renderer(0) { }
860         RenderObject* m_renderer;
861         NodeRareDataBase* m_rareData;
862     } m_data;
863 
864 protected:
isParsingChildrenFinished()865     bool isParsingChildrenFinished() const { return getFlag(IsParsingChildrenFinishedFlag); }
setIsParsingChildrenFinished()866     void setIsParsingChildrenFinished() { setFlag(IsParsingChildrenFinishedFlag); }
clearIsParsingChildrenFinished()867     void clearIsParsingChildrenFinished() { clearFlag(IsParsingChildrenFinishedFlag); }
868 
hasSVGRareData()869     bool hasSVGRareData() const { return getFlag(HasSVGRareDataFlag); }
setHasSVGRareData()870     void setHasSVGRareData() { setFlag(HasSVGRareDataFlag); }
clearHasSVGRareData()871     void clearHasSVGRareData() { clearFlag(HasSVGRareDataFlag); }
872 };
873 
874 // Used in Node::addSubresourceAttributeURLs() and in addSubresourceStyleURLs()
addSubresourceURL(ListHashSet<KURL> & urls,const KURL & url)875 inline void addSubresourceURL(ListHashSet<KURL>& urls, const KURL& url)
876 {
877     if (!url.isNull())
878         urls.add(url);
879 }
880 
setParentOrShadowHostNode(ContainerNode * parent)881 inline void Node::setParentOrShadowHostNode(ContainerNode* parent)
882 {
883     ASSERT(isMainThread());
884     m_parentOrShadowHostNode = parent;
885 }
886 
parentOrShadowHostNode()887 inline ContainerNode* Node::parentOrShadowHostNode() const
888 {
889     ASSERT(isMainThread());
890     return m_parentOrShadowHostNode;
891 }
892 
parentNode()893 inline ContainerNode* Node::parentNode() const
894 {
895     return isShadowRoot() ? 0 : parentOrShadowHostNode();
896 }
897 
lazyReattachIfAttached()898 inline void Node::lazyReattachIfAttached()
899 {
900     if (styleChangeType() == NeedsReattachStyleChange)
901         return;
902     if (!inActiveDocument())
903         return;
904 
905     AttachContext context;
906     context.performingReattach = true;
907 
908     detach(context);
909     markAncestorsWithChildNeedsStyleRecalc();
910 }
911 
shouldRecalcStyle(StyleRecalcChange change,const Node * node)912 inline bool shouldRecalcStyle(StyleRecalcChange change, const Node* node)
913 {
914     return change >= Inherit || node->childNeedsStyleRecalc() || node->needsStyleRecalc();
915 }
916 
isTreeScopeRoot(const Node * node)917 inline bool isTreeScopeRoot(const Node* node)
918 {
919     return !node || node->isDocumentNode() || node->isShadowRoot();
920 }
921 
isTreeScopeRoot(const Node & node)922 inline bool isTreeScopeRoot(const Node& node)
923 {
924     return node.isDocumentNode() || node.isShadowRoot();
925 }
926 
927 // Allow equality comparisons of Nodes by reference or pointer, interchangeably.
928 inline bool operator==(const Node& a, const Node& b) { return &a == &b; }
929 inline bool operator==(const Node& a, const Node* b) { return &a == b; }
930 inline bool operator==(const Node* a, const Node& b) { return a == &b; }
931 inline bool operator!=(const Node& a, const Node& b) { return !(a == b); }
932 inline bool operator!=(const Node& a, const Node* b) { return !(a == b); }
933 inline bool operator!=(const Node* a, const Node& b) { return !(a == b); }
934 inline bool operator==(const PassRefPtr<Node>& a, const Node& b) { return a.get() == &b; }
935 inline bool operator==(const Node& a, const PassRefPtr<Node>& b) { return &a == b.get(); }
936 inline bool operator!=(const PassRefPtr<Node>& a, const Node& b) { return !(a == b); }
937 inline bool operator!=(const Node& a, const PassRefPtr<Node>& b) { return !(a == b); }
938 
939 
940 #define DEFINE_NODE_TYPE_CASTS(thisType, predicate) \
941     template<typename T> inline thisType* to##thisType(const RefPtr<T>& node) { return to##thisType(node.get()); } \
942     DEFINE_TYPE_CASTS(thisType, Node, node, node->predicate, node.predicate)
943 
944 // This requires isClassName(const Node&).
945 #define DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(thisType) \
946     template<typename T> inline thisType* to##thisType(const RefPtr<T>& node) { return to##thisType(node.get()); } \
947     DEFINE_TYPE_CASTS(thisType, Node, node, is##thisType(*node), is##thisType(node))
948 
949 } // namespace WebCore
950 
951 #ifndef NDEBUG
952 // Outside the WebCore namespace for ease of invocation from gdb.
953 void showTree(const WebCore::Node*);
954 void showNodePath(const WebCore::Node*);
955 #endif
956 
957 #endif
958