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