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