Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef nsINode_h___
7 #define nsINode_h___
9 #include "mozilla/Likely.h"
10 #include "nsCOMPtr.h" // for member, local
11 #include "nsGkAtoms.h" // for nsGkAtoms::baseURIProperty
12 #include "nsIDOMNode.h"
13 #include "nsINodeInfo.h" // member (in nsCOMPtr)
14 #include "nsIVariant.h" // for use in GetUserData()
15 #include "nsNodeInfoManager.h" // for use in NodePrincipal()
16 #include "nsPropertyTable.h" // for typedefs
17 #include "nsTObserverArray.h" // for member
18 #include "mozilla/ErrorResult.h"
19 #include "mozilla/MemoryReporting.h"
20 #include "mozilla/dom/EventTarget.h" // for base class
21 #include "js/TypeDecls.h" // for Handle, Value, JSObject, JSContext
22 #include "mozilla/dom/DOMString.h"
23 #include "mozilla/dom/BindingDeclarations.h"
25 // Including 'windows.h' will #define GetClassInfo to something else.
26 #ifdef XP_WIN
27 #ifdef GetClassInfo
28 #undef GetClassInfo
29 #endif
30 #endif
32 class nsAttrAndChildArray;
33 class nsChildContentList;
34 class nsCSSSelectorList;
35 class nsDOMAttributeMap;
36 class nsIContent;
37 class nsIDocument;
38 class nsIDOMElement;
39 class nsIDOMNodeList;
40 class nsIDOMUserDataHandler;
41 class nsIEditor;
42 class nsIFrame;
43 class nsIMutationObserver;
44 class nsINodeList;
45 class nsIPresShell;
46 class nsIPrincipal;
47 class nsIURI;
48 class nsNodeSupportsWeakRefTearoff;
49 class nsNodeWeakReference;
50 class nsXPCClassInfo;
51 class nsDOMMutationObserver;
53 namespace mozilla {
54 class EventListenerManager;
55 namespace dom {
56 /**
57 * @return true if aChar is what the DOM spec defines as 'space character'.
58 * http://dom.spec.whatwg.org/#space-character
59 */
60 inline bool IsSpaceCharacter(char16_t aChar) {
61 return aChar == ' ' || aChar == '\t' || aChar == '\n' || aChar == '\r' ||
62 aChar == '\f';
63 }
64 inline bool IsSpaceCharacter(char aChar) {
65 return aChar == ' ' || aChar == '\t' || aChar == '\n' || aChar == '\r' ||
66 aChar == '\f';
67 }
68 struct BoxQuadOptions;
69 struct ConvertCoordinateOptions;
70 class DOMPoint;
71 class DOMQuad;
72 class DOMRectReadOnly;
73 class Element;
74 class EventHandlerNonNull;
75 class OnErrorEventHandlerNonNull;
76 template<typename T> class Optional;
77 class TextOrElementOrDocument;
78 struct DOMPointInit;
79 } // namespace dom
80 } // namespace mozilla
82 #define NODE_FLAG_BIT(n_) (1U << (WRAPPER_CACHE_FLAGS_BITS_USED + (n_)))
84 enum {
85 // This bit will be set if the node has a listener manager.
86 NODE_HAS_LISTENERMANAGER = NODE_FLAG_BIT(0),
88 // Whether this node has had any properties set on it
89 NODE_HAS_PROPERTIES = NODE_FLAG_BIT(1),
91 // Whether this node is the root of an anonymous subtree. Note that this
92 // need not be a native anonymous subtree. Any anonymous subtree, including
93 // XBL-generated ones, will do. This flag is set-once: once a node has it,
94 // it must not be removed.
95 // NOTE: Should only be used on nsIContent nodes
96 NODE_IS_ANONYMOUS_ROOT = NODE_FLAG_BIT(2),
98 // Whether the node has some ancestor, possibly itself, that is native
99 // anonymous. This includes ancestors crossing XBL scopes, in cases when an
100 // XBL binding is attached to an element which has a native anonymous
101 // ancestor. This flag is set-once: once a node has it, it must not be
102 // removed.
103 // NOTE: Should only be used on nsIContent nodes
104 NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE = NODE_FLAG_BIT(3),
106 // Whether this node is the root of a native anonymous (from the perspective
107 // of its parent) subtree. This flag is set-once: once a node has it, it
108 // must not be removed.
109 // NOTE: Should only be used on nsIContent nodes
110 NODE_IS_NATIVE_ANONYMOUS_ROOT = NODE_FLAG_BIT(4),
112 // Forces the XBL code to treat this node as if it were
113 // in the document and therefore should get bindings attached.
114 NODE_FORCE_XBL_BINDINGS = NODE_FLAG_BIT(5),
116 // Whether a binding manager may have a pointer to this
117 NODE_MAY_BE_IN_BINDING_MNGR = NODE_FLAG_BIT(6),
119 NODE_IS_EDITABLE = NODE_FLAG_BIT(7),
121 // For all Element nodes, NODE_MAY_HAVE_CLASS is guaranteed to be set if the
122 // node in fact has a class, but may be set even if it doesn't.
123 NODE_MAY_HAVE_CLASS = NODE_FLAG_BIT(8),
125 // Whether the node participates in a shadow tree.
126 NODE_IS_IN_SHADOW_TREE = NODE_FLAG_BIT(9),
128 // Node has an :empty or :-moz-only-whitespace selector
129 NODE_HAS_EMPTY_SELECTOR = NODE_FLAG_BIT(10),
131 // A child of the node has a selector such that any insertion,
132 // removal, or appending of children requires restyling the parent.
133 NODE_HAS_SLOW_SELECTOR = NODE_FLAG_BIT(11),
135 // A child of the node has a :first-child, :-moz-first-node,
136 // :only-child, :last-child or :-moz-last-node selector.
137 NODE_HAS_EDGE_CHILD_SELECTOR = NODE_FLAG_BIT(12),
139 // A child of the node has a selector such that any insertion or
140 // removal of children requires restyling later siblings of that
141 // element. Additionally (in this manner it is stronger than
142 // NODE_HAS_SLOW_SELECTOR), if a child's style changes due to any
143 // other content tree changes (e.g., the child changes to or from
144 // matching :empty due to a grandchild insertion or removal), the
145 // child's later siblings must also be restyled.
146 NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS = NODE_FLAG_BIT(13),
148 NODE_ALL_SELECTOR_FLAGS = NODE_HAS_EMPTY_SELECTOR |
149 NODE_HAS_SLOW_SELECTOR |
150 NODE_HAS_EDGE_CHILD_SELECTOR |
151 NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS,
153 NODE_ATTACH_BINDING_ON_POSTCREATE = NODE_FLAG_BIT(14),
155 // This node needs to go through frame construction to get a frame (or
156 // undisplayed entry).
157 NODE_NEEDS_FRAME = NODE_FLAG_BIT(15),
159 // At least one descendant in the flattened tree has NODE_NEEDS_FRAME set.
160 // This should be set on every node on the flattened tree path between the
161 // node(s) with NODE_NEEDS_FRAME and the root content.
162 NODE_DESCENDANTS_NEED_FRAMES = NODE_FLAG_BIT(16),
164 // Set if the node has the accesskey attribute set.
165 NODE_HAS_ACCESSKEY = NODE_FLAG_BIT(17),
167 // Set if the node has right-to-left directionality
168 NODE_HAS_DIRECTION_RTL = NODE_FLAG_BIT(18),
170 // Set if the node has left-to-right directionality
171 NODE_HAS_DIRECTION_LTR = NODE_FLAG_BIT(19),
173 NODE_ALL_DIRECTION_FLAGS = NODE_HAS_DIRECTION_LTR |
174 NODE_HAS_DIRECTION_RTL,
176 NODE_CHROME_ONLY_ACCESS = NODE_FLAG_BIT(20),
178 NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS = NODE_FLAG_BIT(21),
180 // Remaining bits are node type specific.
181 NODE_TYPE_SPECIFIC_BITS_OFFSET = 22
182 };
184 // Make sure we have space for our bits
185 #define ASSERT_NODE_FLAGS_SPACE(n) \
186 static_assert(WRAPPER_CACHE_FLAGS_BITS_USED + (n) <= 32, \
187 "Not enough space for our bits")
188 ASSERT_NODE_FLAGS_SPACE(NODE_TYPE_SPECIFIC_BITS_OFFSET);
190 /**
191 * Class used to detect unexpected mutations. To use the class create an
192 * nsMutationGuard on the stack before unexpected mutations could occur.
193 * You can then at any time call Mutated to check if any unexpected mutations
194 * have occurred.
195 *
196 * When a guard is instantiated sMutationCount is set to 300. It is then
197 * decremented by every mutation (capped at 0). This means that we can only
198 * detect 300 mutations during the lifetime of a single guard, however that
199 * should be more then we ever care about as we usually only care if more then
200 * one mutation has occurred.
201 *
202 * When the guard goes out of scope it will adjust sMutationCount so that over
203 * the lifetime of the guard the guard itself has not affected sMutationCount,
204 * while mutations that happened while the guard was alive still will. This
205 * allows a guard to be instantiated even if there is another guard higher up
206 * on the callstack watching for mutations.
207 *
208 * The only thing that has to be avoided is for an outer guard to be used
209 * while an inner guard is alive. This can be avoided by only ever
210 * instantiating a single guard per scope and only using the guard in the
211 * current scope.
212 */
213 class nsMutationGuard {
214 public:
215 nsMutationGuard()
216 {
217 mDelta = eMaxMutations - sMutationCount;
218 sMutationCount = eMaxMutations;
219 }
220 ~nsMutationGuard()
221 {
222 sMutationCount =
223 mDelta > sMutationCount ? 0 : sMutationCount - mDelta;
224 }
226 /**
227 * Returns true if any unexpected mutations have occurred. You can pass in
228 * an 8-bit ignore count to ignore a number of expected mutations.
229 */
230 bool Mutated(uint8_t aIgnoreCount)
231 {
232 return sMutationCount < static_cast<uint32_t>(eMaxMutations - aIgnoreCount);
233 }
235 // This function should be called whenever a mutation that we want to keep
236 // track of happen. For now this is only done when children are added or
237 // removed, but we might do it for attribute changes too in the future.
238 static void DidMutate()
239 {
240 if (sMutationCount) {
241 --sMutationCount;
242 }
243 }
245 private:
246 // mDelta is the amount sMutationCount was adjusted when the guard was
247 // initialized. It is needed so that we can undo that adjustment once
248 // the guard dies.
249 uint32_t mDelta;
251 // The value 300 is not important, as long as it is bigger then anything
252 // ever passed to Mutated().
253 enum { eMaxMutations = 300 };
256 // sMutationCount is a global mutation counter which is decreased by one at
257 // every mutation. It is capped at 0 to avoid wrapping.
258 // Its value is always between 0 and 300, inclusive.
259 static uint32_t sMutationCount;
260 };
262 // This should be used for any nsINode sub-class that has fields of its own
263 // that it needs to measure; any sub-class that doesn't use it will inherit
264 // SizeOfExcludingThis from its super-class. SizeOfIncludingThis() need not be
265 // defined, it is inherited from nsINode.
266 // This macro isn't actually specific to nodes, and bug 956400 will move it into MFBT.
267 #define NS_DECL_SIZEOF_EXCLUDING_THIS \
268 virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
270 // Categories of node properties
271 // 0 is global.
272 #define DOM_USER_DATA 1
273 #define DOM_USER_DATA_HANDLER 2
274 #define SMIL_MAPPED_ATTR_ANIMVAL 3
276 // IID for the nsINode interface
277 #define NS_INODE_IID \
278 { 0x77a62cd0, 0xb34f, 0x42cb, \
279 { 0x94, 0x52, 0xae, 0xb2, 0x4d, 0x93, 0x2c, 0xb4 } }
281 /**
282 * An internal interface that abstracts some DOMNode-related parts that both
283 * nsIContent and nsIDocument share. An instance of this interface has a list
284 * of nsIContent children and provides access to them.
285 */
286 class nsINode : public mozilla::dom::EventTarget
287 {
288 public:
289 typedef mozilla::dom::BoxQuadOptions BoxQuadOptions;
290 typedef mozilla::dom::ConvertCoordinateOptions ConvertCoordinateOptions;
291 typedef mozilla::dom::DOMPoint DOMPoint;
292 typedef mozilla::dom::DOMPointInit DOMPointInit;
293 typedef mozilla::dom::DOMQuad DOMQuad;
294 typedef mozilla::dom::DOMRectReadOnly DOMRectReadOnly;
295 typedef mozilla::dom::TextOrElementOrDocument TextOrElementOrDocument;
296 typedef mozilla::ErrorResult ErrorResult;
298 NS_DECLARE_STATIC_IID_ACCESSOR(NS_INODE_IID)
300 // Among the sub-classes that inherit (directly or indirectly) from nsINode,
301 // measurement of the following members may be added later if DMD finds it is
302 // worthwhile:
303 // - nsGenericHTMLElement: mForm, mFieldSet
304 // - nsGenericHTMLFrameElement: mFrameLoader (bug 672539)
305 // - HTMLBodyElement: mContentStyleRule
306 // - HTMLDataListElement: mOptions
307 // - HTMLFieldSetElement: mElements, mDependentElements, mFirstLegend
308 // - HTMLFormElement: many!
309 // - HTMLFrameSetElement: mRowSpecs, mColSpecs
310 // - HTMLInputElement: mInputData, mFiles, mFileList, mStaticDocfileList
311 // - nsHTMLMapElement: mAreas
312 // - HTMLMediaElement: many!
313 // - nsHTMLOutputElement: mDefaultValue, mTokenList
314 // - nsHTMLRowElement: mCells
315 // - nsHTMLSelectElement: mOptions, mRestoreState
316 // - nsHTMLTableElement: mTBodies, mRows, mTableInheritedAttributes
317 // - nsHTMLTableSectionElement: mRows
318 // - nsHTMLTextAreaElement: mControllers, mState
319 //
320 // The following members don't need to be measured:
321 // - nsIContent: mPrimaryFrame, because it's non-owning and measured elsewhere
322 //
323 NS_DECL_SIZEOF_EXCLUDING_THIS
325 // SizeOfIncludingThis doesn't need to be overridden by sub-classes because
326 // sub-classes of nsINode are guaranteed to be laid out in memory in such a
327 // way that |this| points to the start of the allocated object, even in
328 // methods of nsINode's sub-classes, and so |aMallocSizeOf(this)| is always
329 // safe to call no matter which object it was invoked on.
330 virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
331 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
332 }
334 friend class nsNodeUtils;
335 friend class nsNodeWeakReference;
336 friend class nsNodeSupportsWeakRefTearoff;
337 friend class nsAttrAndChildArray;
339 #ifdef MOZILLA_INTERNAL_API
340 nsINode(already_AddRefed<nsINodeInfo>& aNodeInfo)
341 : mNodeInfo(aNodeInfo),
342 mParent(nullptr),
343 mBoolFlags(0),
344 mNextSibling(nullptr),
345 mPreviousSibling(nullptr),
346 mFirstChild(nullptr),
347 mSubtreeRoot(MOZ_THIS_IN_INITIALIZER_LIST()),
348 mSlots(nullptr)
349 {
350 SetIsDOMBinding();
351 }
352 #endif
354 virtual ~nsINode();
356 /**
357 * Bit-flags to pass (or'ed together) to IsNodeOfType()
358 */
359 enum {
360 /** nsIContent nodes */
361 eCONTENT = 1 << 0,
362 /** nsIDocument nodes */
363 eDOCUMENT = 1 << 1,
364 /** nsIAttribute nodes */
365 eATTRIBUTE = 1 << 2,
366 /** text nodes */
367 eTEXT = 1 << 3,
368 /** xml processing instructions */
369 ePROCESSING_INSTRUCTION = 1 << 4,
370 /** comment nodes */
371 eCOMMENT = 1 << 5,
372 /** form control elements */
373 eHTML_FORM_CONTROL = 1 << 6,
374 /** document fragments */
375 eDOCUMENT_FRAGMENT = 1 << 7,
376 /** data nodes (comments, PIs, text). Nodes of this type always
377 returns a non-null value for nsIContent::GetText() */
378 eDATA_NODE = 1 << 8,
379 /** HTMLMediaElement */
380 eMEDIA = 1 << 9,
381 /** animation elements */
382 eANIMATION = 1 << 10,
383 /** filter elements that implement SVGFilterPrimitiveStandardAttributes */
384 eFILTER = 1 << 11
385 };
387 /**
388 * API for doing a quick check if a content is of a given
389 * type, such as Text, Document, Comment ... Use this when you can instead of
390 * checking the tag.
391 *
392 * @param aFlags what types you want to test for (see above)
393 * @return whether the content matches ALL flags passed in
394 */
395 virtual bool IsNodeOfType(uint32_t aFlags) const = 0;
397 virtual JSObject* WrapObject(JSContext *aCx) MOZ_OVERRIDE;
399 protected:
400 /**
401 * WrapNode is called from WrapObject to actually wrap this node, WrapObject
402 * does some additional checks and fix-up that's common to all nodes. WrapNode
403 * should just call the DOM binding's Wrap function.
404 */
405 virtual JSObject* WrapNode(JSContext *aCx)
406 {
407 MOZ_ASSERT(!IsDOMBinding(), "Someone forgot to override WrapNode");
408 return nullptr;
409 }
411 // Subclasses that wish to override the parent behavior should return the
412 // result of GetParentObjectIntenral, which handles the XBL scope stuff.
413 //
414 mozilla::dom::ParentObject GetParentObjectInternal(nsINode* aNativeParent) const {
415 mozilla::dom::ParentObject p(aNativeParent);
416 // Note that mUseXBLScope is a no-op for chrome, and other places where we
417 // don't use XBL scopes.
418 p.mUseXBLScope = IsInAnonymousSubtree() && !IsAnonymousContentInSVGUseSubtree();
419 return p;
420 }
422 public:
423 mozilla::dom::ParentObject GetParentObject() const; // Implemented in nsIDocument.h
425 /**
426 * Return whether the node is an Element node
427 */
428 bool IsElement() const {
429 return GetBoolFlag(NodeIsElement);
430 }
432 /**
433 * Return this node as an Element. Should only be used for nodes
434 * for which IsElement() is true. This is defined inline in Element.h.
435 */
436 mozilla::dom::Element* AsElement();
437 const mozilla::dom::Element* AsElement() const;
439 /**
440 * Return this node as nsIContent. Should only be used for nodes for which
441 * IsContent() is true. This is defined inline in nsIContent.h.
442 */
443 nsIContent* AsContent();
444 const nsIContent* AsContent() const
445 {
446 return const_cast<nsINode*>(this)->AsContent();
447 }
449 virtual nsIDOMNode* AsDOMNode() = 0;
451 /**
452 * Return if this node has any children.
453 */
454 bool HasChildren() const { return !!mFirstChild; }
456 /**
457 * Get the number of children
458 * @return the number of children
459 */
460 virtual uint32_t GetChildCount() const = 0;
462 /**
463 * Get a child by index
464 * @param aIndex the index of the child to get
465 * @return the child, or null if index out of bounds
466 */
467 virtual nsIContent* GetChildAt(uint32_t aIndex) const = 0;
469 /**
470 * Get a raw pointer to the child array. This should only be used if you
471 * plan to walk a bunch of the kids, promise to make sure that nothing ever
472 * mutates (no attribute changes, not DOM tree changes, no script execution,
473 * NOTHING), and will never ever peform an out-of-bounds access here. This
474 * method may return null if there are no children, or it may return a
475 * garbage pointer. In all cases the out param will be set to the number of
476 * children.
477 */
478 virtual nsIContent * const * GetChildArray(uint32_t* aChildCount) const = 0;
480 /**
481 * Get the index of a child within this content
482 * @param aPossibleChild the child to get the index of.
483 * @return the index of the child, or -1 if not a child
484 *
485 * If the return value is not -1, then calling GetChildAt() with that value
486 * will return aPossibleChild.
487 */
488 virtual int32_t IndexOf(const nsINode* aPossibleChild) const = 0;
490 /**
491 * Return the "owner document" of this node. Note that this is not the same
492 * as the DOM ownerDocument -- that's null for Document nodes, whereas for a
493 * nsIDocument GetOwnerDocument returns the document itself. For nsIContent
494 * implementations the two are the same.
495 */
496 nsIDocument *OwnerDoc() const
497 {
498 return mNodeInfo->GetDocument();
499 }
501 /**
502 * Return the "owner document" of this node as an nsINode*. Implemented
503 * in nsIDocument.h.
504 */
505 nsINode *OwnerDocAsNode() const;
507 /**
508 * Returns true if the content has an ancestor that is a document.
509 *
510 * @return whether this content is in a document tree
511 */
512 bool IsInDoc() const
513 {
514 return GetBoolFlag(IsInDocument);
515 }
517 /**
518 * Get the document that this content is currently in, if any. This will be
519 * null if the content has no ancestor that is a document.
520 *
521 * @return the current document
522 */
523 nsIDocument *GetCurrentDoc() const
524 {
525 return IsInDoc() ? OwnerDoc() : nullptr;
526 }
528 /**
529 * The values returned by this function are the ones defined for
530 * nsIDOMNode.nodeType
531 */
532 uint16_t NodeType() const
533 {
534 return mNodeInfo->NodeType();
535 }
536 const nsString& NodeName() const
537 {
538 return mNodeInfo->NodeName();
539 }
540 const nsString& LocalName() const
541 {
542 return mNodeInfo->LocalName();
543 }
545 /**
546 * Get the tag for this element. This will always return a non-null atom
547 * pointer (as implied by the naming of the method). For elements this is
548 * the non-namespaced tag, and for other nodes it's something like "#text",
549 * "#comment", "#document", etc.
550 */
551 nsIAtom* Tag() const
552 {
553 return mNodeInfo->NameAtom();
554 }
556 /**
557 * Insert a content node at a particular index. This method handles calling
558 * BindToTree on the child appropriately.
559 *
560 * @param aKid the content to insert
561 * @param aIndex the index it is being inserted at (the index it will have
562 * after it is inserted)
563 * @param aNotify whether to notify the document (current document for
564 * nsIContent, and |this| for nsIDocument) that the insert has
565 * occurred
566 *
567 * @throws NS_ERROR_DOM_HIERARCHY_REQUEST_ERR if one attempts to have more
568 * than one element node as a child of a document. Doing this will also
569 * assert -- you shouldn't be doing it! Check with
570 * nsIDocument::GetRootElement() first if you're not sure. Apart from this
571 * one constraint, this doesn't do any checking on whether aKid is a valid
572 * child of |this|.
573 *
574 * @throws NS_ERROR_OUT_OF_MEMORY in some cases (from BindToTree).
575 */
576 virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
577 bool aNotify) = 0;
579 /**
580 * Append a content node to the end of the child list. This method handles
581 * calling BindToTree on the child appropriately.
582 *
583 * @param aKid the content to append
584 * @param aNotify whether to notify the document (current document for
585 * nsIContent, and |this| for nsIDocument) that the append has
586 * occurred
587 *
588 * @throws NS_ERROR_DOM_HIERARCHY_REQUEST_ERR if one attempts to have more
589 * than one element node as a child of a document. Doing this will also
590 * assert -- you shouldn't be doing it! Check with
591 * nsIDocument::GetRootElement() first if you're not sure. Apart from this
592 * one constraint, this doesn't do any checking on whether aKid is a valid
593 * child of |this|.
594 *
595 * @throws NS_ERROR_OUT_OF_MEMORY in some cases (from BindToTree).
596 */
597 nsresult AppendChildTo(nsIContent* aKid, bool aNotify)
598 {
599 return InsertChildAt(aKid, GetChildCount(), aNotify);
600 }
602 /**
603 * Remove a child from this node. This method handles calling UnbindFromTree
604 * on the child appropriately.
605 *
606 * @param aIndex the index of the child to remove
607 * @param aNotify whether to notify the document (current document for
608 * nsIContent, and |this| for nsIDocument) that the remove has
609 * occurred
610 *
611 * Note: If there is no child at aIndex, this method will simply do nothing.
612 */
613 virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) = 0;
615 /**
616 * Get a property associated with this node.
617 *
618 * @param aPropertyName name of property to get.
619 * @param aStatus out parameter for storing resulting status.
620 * Set to NS_PROPTABLE_PROP_NOT_THERE if the property
621 * is not set.
622 * @return the property. Null if the property is not set
623 * (though a null return value does not imply the
624 * property was not set, i.e. it can be set to null).
625 */
626 void* GetProperty(nsIAtom *aPropertyName,
627 nsresult *aStatus = nullptr) const
628 {
629 return GetProperty(0, aPropertyName, aStatus);
630 }
632 /**
633 * Get a property associated with this node.
634 *
635 * @param aCategory category of property to get.
636 * @param aPropertyName name of property to get.
637 * @param aStatus out parameter for storing resulting status.
638 * Set to NS_PROPTABLE_PROP_NOT_THERE if the property
639 * is not set.
640 * @return the property. Null if the property is not set
641 * (though a null return value does not imply the
642 * property was not set, i.e. it can be set to null).
643 */
644 virtual void* GetProperty(uint16_t aCategory,
645 nsIAtom *aPropertyName,
646 nsresult *aStatus = nullptr) const;
648 /**
649 * Set a property to be associated with this node. This will overwrite an
650 * existing value if one exists. The existing value is destroyed using the
651 * destructor function given when that value was set.
652 *
653 * @param aPropertyName name of property to set.
654 * @param aValue new value of property.
655 * @param aDtor destructor function to be used when this property
656 * is destroyed.
657 * @param aTransfer if true the property will not be deleted when the
658 * ownerDocument of the node changes, if false it
659 * will be deleted.
660 *
661 * @return NS_PROPTABLE_PROP_OVERWRITTEN (success value) if the property
662 * was already set
663 * @throws NS_ERROR_OUT_OF_MEMORY if that occurs
664 */
665 nsresult SetProperty(nsIAtom *aPropertyName,
666 void *aValue,
667 NSPropertyDtorFunc aDtor = nullptr,
668 bool aTransfer = false)
669 {
670 return SetProperty(0, aPropertyName, aValue, aDtor, aTransfer);
671 }
673 /**
674 * Set a property to be associated with this node. This will overwrite an
675 * existing value if one exists. The existing value is destroyed using the
676 * destructor function given when that value was set.
677 *
678 * @param aCategory category of property to set.
679 * @param aPropertyName name of property to set.
680 * @param aValue new value of property.
681 * @param aDtor destructor function to be used when this property
682 * is destroyed.
683 * @param aTransfer if true the property will not be deleted when the
684 * ownerDocument of the node changes, if false it
685 * will be deleted.
686 * @param aOldValue [out] previous value of property.
687 *
688 * @return NS_PROPTABLE_PROP_OVERWRITTEN (success value) if the property
689 * was already set
690 * @throws NS_ERROR_OUT_OF_MEMORY if that occurs
691 */
692 virtual nsresult SetProperty(uint16_t aCategory,
693 nsIAtom *aPropertyName,
694 void *aValue,
695 NSPropertyDtorFunc aDtor = nullptr,
696 bool aTransfer = false,
697 void **aOldValue = nullptr);
699 /**
700 * A generic destructor for property values allocated with new.
701 */
702 template<class T>
703 static void DeleteProperty(void *, nsIAtom *, void *aPropertyValue, void *)
704 {
705 delete static_cast<T *>(aPropertyValue);
706 }
708 /**
709 * Destroys a property associated with this node. The value is destroyed
710 * using the destruction function given when that value was set.
711 *
712 * @param aPropertyName name of property to destroy.
713 */
714 void DeleteProperty(nsIAtom *aPropertyName)
715 {
716 DeleteProperty(0, aPropertyName);
717 }
719 /**
720 * Destroys a property associated with this node. The value is destroyed
721 * using the destruction function given when that value was set.
722 *
723 * @param aCategory category of property to destroy.
724 * @param aPropertyName name of property to destroy.
725 */
726 virtual void DeleteProperty(uint16_t aCategory, nsIAtom *aPropertyName);
728 /**
729 * Unset a property associated with this node. The value will not be
730 * destroyed but rather returned. It is the caller's responsibility to
731 * destroy the value after that point.
732 *
733 * @param aPropertyName name of property to unset.
734 * @param aStatus out parameter for storing resulting status.
735 * Set to NS_PROPTABLE_PROP_NOT_THERE if the property
736 * is not set.
737 * @return the property. Null if the property is not set
738 * (though a null return value does not imply the
739 * property was not set, i.e. it can be set to null).
740 */
741 void* UnsetProperty(nsIAtom *aPropertyName,
742 nsresult *aStatus = nullptr)
743 {
744 return UnsetProperty(0, aPropertyName, aStatus);
745 }
747 /**
748 * Unset a property associated with this node. The value will not be
749 * destroyed but rather returned. It is the caller's responsibility to
750 * destroy the value after that point.
751 *
752 * @param aCategory category of property to unset.
753 * @param aPropertyName name of property to unset.
754 * @param aStatus out parameter for storing resulting status.
755 * Set to NS_PROPTABLE_PROP_NOT_THERE if the property
756 * is not set.
757 * @return the property. Null if the property is not set
758 * (though a null return value does not imply the
759 * property was not set, i.e. it can be set to null).
760 */
761 virtual void* UnsetProperty(uint16_t aCategory,
762 nsIAtom *aPropertyName,
763 nsresult *aStatus = nullptr);
765 bool HasProperties() const
766 {
767 return HasFlag(NODE_HAS_PROPERTIES);
768 }
770 /**
771 * Return the principal of this node. This is guaranteed to never be a null
772 * pointer.
773 */
774 nsIPrincipal* NodePrincipal() const {
775 return mNodeInfo->NodeInfoManager()->DocumentPrincipal();
776 }
778 /**
779 * Get the parent nsIContent for this node.
780 * @return the parent, or null if no parent or the parent is not an nsIContent
781 */
782 nsIContent* GetParent() const {
783 return MOZ_LIKELY(GetBoolFlag(ParentIsContent)) ?
784 reinterpret_cast<nsIContent*>(mParent) : nullptr;
785 }
787 /**
788 * Get the parent nsINode for this node. This can be either an nsIContent,
789 * an nsIDocument or an nsIAttribute.
790 * @return the parent node
791 */
792 nsINode* GetParentNode() const
793 {
794 return mParent;
795 }
797 /**
798 * Get the parent nsINode for this node if it is an Element.
799 * @return the parent node
800 */
801 mozilla::dom::Element* GetParentElement() const
802 {
803 return mParent && mParent->IsElement() ? mParent->AsElement() : nullptr;
804 }
806 /**
807 * Get the root of the subtree this node belongs to. This never returns
808 * null. It may return 'this' (e.g. for document nodes, and nodes that
809 * are the roots of disconnected subtrees).
810 */
811 nsINode* SubtreeRoot() const
812 {
813 // There are three cases of interest here. nsINodes that are really:
814 // 1. nsIDocument nodes - Are always in the document.
815 // 2. nsIContent nodes - Are either in the document, or mSubtreeRoot
816 // is updated in BindToTree/UnbindFromTree.
817 // 3. nsIAttribute nodes - Are never in the document, and mSubtreeRoot
818 // is always 'this' (as set in nsINode's ctor).
819 nsINode* node = IsInDoc() ? OwnerDocAsNode() : mSubtreeRoot;
820 NS_ASSERTION(node, "Should always have a node here!");
821 #ifdef DEBUG
822 {
823 const nsINode* slowNode = this;
824 const nsINode* iter = slowNode;
825 while ((iter = iter->GetParentNode())) {
826 slowNode = iter;
827 }
829 NS_ASSERTION(slowNode == node, "These should always be in sync!");
830 }
831 #endif
832 return node;
833 }
835 /**
836 * See nsIDOMEventTarget
837 */
838 NS_DECL_NSIDOMEVENTTARGET
840 virtual mozilla::EventListenerManager*
841 GetExistingListenerManager() const MOZ_OVERRIDE;
842 virtual mozilla::EventListenerManager*
843 GetOrCreateListenerManager() MOZ_OVERRIDE;
845 using mozilla::dom::EventTarget::RemoveEventListener;
846 using nsIDOMEventTarget::AddEventListener;
847 virtual void AddEventListener(const nsAString& aType,
848 mozilla::dom::EventListener* aListener,
849 bool aUseCapture,
850 const mozilla::dom::Nullable<bool>& aWantsUntrusted,
851 mozilla::ErrorResult& aRv) MOZ_OVERRIDE;
852 using nsIDOMEventTarget::AddSystemEventListener;
853 virtual nsIDOMWindow* GetOwnerGlobal() MOZ_OVERRIDE;
855 /**
856 * Adds a mutation observer to be notified when this node, or any of its
857 * descendants, are modified. The node will hold a weak reference to the
858 * observer, which means that it is the responsibility of the observer to
859 * remove itself in case it dies before the node. If an observer is added
860 * while observers are being notified, it may also be notified. In general,
861 * adding observers while inside a notification is not a good idea. An
862 * observer that is already observing the node must not be added without
863 * being removed first.
864 */
865 void AddMutationObserver(nsIMutationObserver* aMutationObserver)
866 {
867 nsSlots* s = Slots();
868 NS_ASSERTION(s->mMutationObservers.IndexOf(aMutationObserver) ==
869 nsTArray<int>::NoIndex,
870 "Observer already in the list");
871 s->mMutationObservers.AppendElement(aMutationObserver);
872 }
874 /**
875 * Same as above, but only adds the observer if its not observing
876 * the node already.
877 */
878 void AddMutationObserverUnlessExists(nsIMutationObserver* aMutationObserver)
879 {
880 nsSlots* s = Slots();
881 s->mMutationObservers.AppendElementUnlessExists(aMutationObserver);
882 }
884 /**
885 * Removes a mutation observer.
886 */
887 void RemoveMutationObserver(nsIMutationObserver* aMutationObserver)
888 {
889 nsSlots* s = GetExistingSlots();
890 if (s) {
891 s->mMutationObservers.RemoveElement(aMutationObserver);
892 }
893 }
895 /**
896 * Clones this node. This needs to be overriden by all node classes. aNodeInfo
897 * should be identical to this node's nodeInfo, except for the document which
898 * may be different. When cloning an element, all attributes of the element
899 * will be cloned. The children of the node will not be cloned.
900 *
901 * @param aNodeInfo the nodeinfo to use for the clone
902 * @param aResult the clone
903 */
904 virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const = 0;
906 // This class can be extended by subclasses that wish to store more
907 // information in the slots.
908 class nsSlots
909 {
910 public:
911 nsSlots()
912 : mChildNodes(nullptr),
913 mWeakReference(nullptr)
914 {
915 }
917 // If needed we could remove the vtable pointer this dtor causes by
918 // putting a DestroySlots function on nsINode
919 virtual ~nsSlots();
921 void Traverse(nsCycleCollectionTraversalCallback &cb);
922 void Unlink();
924 /**
925 * A list of mutation observers
926 */
927 nsTObserverArray<nsIMutationObserver*> mMutationObservers;
929 /**
930 * An object implementing nsIDOMNodeList for this content (childNodes)
931 * @see nsIDOMNodeList
932 * @see nsGenericHTMLElement::GetChildNodes
933 *
934 * MSVC 7 doesn't like this as an nsRefPtr
935 */
936 nsChildContentList* mChildNodes;
938 /**
939 * Weak reference to this node
940 */
941 nsNodeWeakReference* mWeakReference;
942 };
944 /**
945 * Functions for managing flags and slots
946 */
947 #ifdef DEBUG
948 nsSlots* DebugGetSlots()
949 {
950 return Slots();
951 }
952 #endif
954 void SetFlags(uint32_t aFlagsToSet)
955 {
956 NS_ASSERTION(!(aFlagsToSet & (NODE_IS_ANONYMOUS_ROOT |
957 NODE_IS_NATIVE_ANONYMOUS_ROOT |
958 NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
959 NODE_ATTACH_BINDING_ON_POSTCREATE |
960 NODE_DESCENDANTS_NEED_FRAMES |
961 NODE_NEEDS_FRAME |
962 NODE_CHROME_ONLY_ACCESS)) ||
963 IsNodeOfType(eCONTENT),
964 "Flag only permitted on nsIContent nodes");
965 nsWrapperCache::SetFlags(aFlagsToSet);
966 }
968 void UnsetFlags(uint32_t aFlagsToUnset)
969 {
970 NS_ASSERTION(!(aFlagsToUnset &
971 (NODE_IS_ANONYMOUS_ROOT |
972 NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
973 NODE_IS_NATIVE_ANONYMOUS_ROOT)),
974 "Trying to unset write-only flags");
975 nsWrapperCache::UnsetFlags(aFlagsToUnset);
976 }
978 void SetEditableFlag(bool aEditable)
979 {
980 if (aEditable) {
981 SetFlags(NODE_IS_EDITABLE);
982 }
983 else {
984 UnsetFlags(NODE_IS_EDITABLE);
985 }
986 }
988 bool IsEditable() const
989 {
990 #ifdef MOZILLA_INTERNAL_API
991 return IsEditableInternal();
992 #else
993 return IsEditableExternal();
994 #endif
995 }
997 /**
998 * Returns true if |this| or any of its ancestors is native anonymous.
999 */
1000 bool IsInNativeAnonymousSubtree() const
1001 {
1002 #ifdef DEBUG
1003 if (HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE)) {
1004 return true;
1005 }
1006 CheckNotNativeAnonymous();
1007 return false;
1008 #else
1009 return HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
1010 #endif
1011 }
1013 bool IsInAnonymousSubtree() const;
1015 // Note: This asserts |IsInAnonymousSubtree()|.
1016 bool IsAnonymousContentInSVGUseSubtree() const;
1018 // True for native anonymous content and for XBL content if the binging
1019 // has chromeOnlyContent="true".
1020 bool ChromeOnlyAccess() const
1021 {
1022 return HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE | NODE_CHROME_ONLY_ACCESS);
1023 }
1025 /**
1026 * Returns true if |this| node is the common ancestor of the start/end
1027 * nodes of a Range in a Selection or a descendant of such a common ancestor.
1028 * This node is definitely not selected when |false| is returned, but it may
1029 * or may not be selected when |true| is returned.
1030 */
1031 bool IsSelectionDescendant() const
1032 {
1033 return IsDescendantOfCommonAncestorForRangeInSelection() ||
1034 IsCommonAncestorForRangeInSelection();
1035 }
1037 /**
1038 * Get the root content of an editor. So, this node must be a descendant of
1039 * an editor. Note that this should be only used for getting input or textarea
1040 * editor's root content. This method doesn't support HTML editors.
1041 */
1042 nsIContent* GetTextEditorRootContent(nsIEditor** aEditor = nullptr);
1044 /**
1045 * Get the nearest selection root, ie. the node that will be selected if the
1046 * user does "Select All" while the focus is in this node. Note that if this
1047 * node is not in an editor, the result comes from the nsFrameSelection that
1048 * is related to aPresShell, so the result might not be the ancestor of this
1049 * node. Be aware that if this node and the computed selection limiter are
1050 * not in same subtree, this returns the root content of the closeset subtree.
1051 */
1052 nsIContent* GetSelectionRootContent(nsIPresShell* aPresShell);
1054 virtual nsINodeList* ChildNodes();
1055 nsIContent* GetFirstChild() const { return mFirstChild; }
1056 nsIContent* GetLastChild() const
1057 {
1058 uint32_t count;
1059 nsIContent* const* children = GetChildArray(&count);
1061 return count > 0 ? children[count - 1] : nullptr;
1062 }
1064 /**
1065 * Implementation is in nsIDocument.h, because it needs to cast from
1066 * nsIDocument* to nsINode*.
1067 */
1068 nsIDocument* GetOwnerDocument() const;
1070 void Normalize();
1072 /**
1073 * Get the base URI for any relative URIs within this piece of
1074 * content. Generally, this is the document's base URI, but certain
1075 * content carries a local base for backward compatibility, and XML
1076 * supports setting a per-node base URI.
1077 *
1078 * @return the base URI
1079 */
1080 virtual already_AddRefed<nsIURI> GetBaseURI(bool aTryUseXHRDocBaseURI = false) const = 0;
1081 already_AddRefed<nsIURI> GetBaseURIObject() const;
1083 /**
1084 * Facility for explicitly setting a base URI on a node.
1085 */
1086 nsresult SetExplicitBaseURI(nsIURI* aURI);
1087 /**
1088 * The explicit base URI, if set, otherwise null
1089 */
1090 protected:
1091 nsIURI* GetExplicitBaseURI() const {
1092 if (HasExplicitBaseURI()) {
1093 return static_cast<nsIURI*>(GetProperty(nsGkAtoms::baseURIProperty));
1094 }
1095 return nullptr;
1096 }
1098 public:
1099 void GetTextContent(nsAString& aTextContent)
1100 {
1101 GetTextContentInternal(aTextContent);
1102 }
1103 void SetTextContent(const nsAString& aTextContent,
1104 mozilla::ErrorResult& aError)
1105 {
1106 SetTextContentInternal(aTextContent, aError);
1107 }
1109 mozilla::dom::Element* QuerySelector(const nsAString& aSelector,
1110 mozilla::ErrorResult& aResult);
1111 already_AddRefed<nsINodeList> QuerySelectorAll(const nsAString& aSelector,
1112 mozilla::ErrorResult& aResult);
1114 nsresult QuerySelector(const nsAString& aSelector, nsIDOMElement **aReturn);
1115 nsresult QuerySelectorAll(const nsAString& aSelector, nsIDOMNodeList **aReturn);
1117 protected:
1118 // nsIDocument overrides this with its own (faster) version. This
1119 // should really only be called for elements and document fragments.
1120 mozilla::dom::Element* GetElementById(const nsAString& aId);
1122 public:
1123 /**
1124 * Associate an object aData to aKey on this node. If aData is null any
1125 * previously registered object and UserDataHandler associated to aKey on
1126 * this node will be removed.
1127 * Should only be used to implement the DOM Level 3 UserData API.
1128 *
1129 * @param aKey the key to associate the object to
1130 * @param aData the object to associate to aKey on this node (may be null)
1131 * @param aHandler the UserDataHandler to call when the node is
1132 * cloned/deleted/imported/renamed (may be null)
1133 * @param aResult [out] the previously registered object for aKey on this
1134 * node, if any
1135 * @return whether adding the object and UserDataHandler succeeded
1136 */
1137 nsresult SetUserData(const nsAString& aKey, nsIVariant* aData,
1138 nsIDOMUserDataHandler* aHandler, nsIVariant** aResult);
1140 /**
1141 * Get the UserData object registered for a Key on this node, if any.
1142 * Should only be used to implement the DOM Level 3 UserData API.
1143 *
1144 * @param aKey the key to get UserData for
1145 * @return aResult the previously registered object for aKey on this node, if
1146 * any
1147 */
1148 nsIVariant* GetUserData(const nsAString& aKey);
1150 nsresult GetUserData(const nsAString& aKey, nsIVariant** aResult)
1151 {
1152 NS_IF_ADDREF(*aResult = GetUserData(aKey));
1154 return NS_OK;
1155 }
1157 void LookupPrefix(const nsAString& aNamespace, nsAString& aResult);
1158 bool IsDefaultNamespace(const nsAString& aNamespaceURI)
1159 {
1160 nsAutoString defaultNamespace;
1161 LookupNamespaceURI(EmptyString(), defaultNamespace);
1162 return aNamespaceURI.Equals(defaultNamespace);
1163 }
1164 void LookupNamespaceURI(const nsAString& aNamespacePrefix,
1165 nsAString& aNamespaceURI);
1167 nsresult IsEqualNode(nsIDOMNode* aOther, bool* aReturn);
1169 nsIContent* GetNextSibling() const { return mNextSibling; }
1170 nsIContent* GetPreviousSibling() const { return mPreviousSibling; }
1172 /**
1173 * Get the next node in the pre-order tree traversal of the DOM. If
1174 * aRoot is non-null, then it must be an ancestor of |this|
1175 * (possibly equal to |this|) and only nodes that are descendants of
1176 * aRoot, not including aRoot itself, will be returned. Returns
1177 * null if there are no more nodes to traverse.
1178 */
1179 nsIContent* GetNextNode(const nsINode* aRoot = nullptr) const
1180 {
1181 return GetNextNodeImpl(aRoot, false);
1182 }
1184 /**
1185 * Get the next node in the pre-order tree traversal of the DOM but ignoring
1186 * the children of this node. If aRoot is non-null, then it must be an
1187 * ancestor of |this| (possibly equal to |this|) and only nodes that are
1188 * descendants of aRoot, not including aRoot itself, will be returned.
1189 * Returns null if there are no more nodes to traverse.
1190 */
1191 nsIContent* GetNextNonChildNode(const nsINode* aRoot = nullptr) const
1192 {
1193 return GetNextNodeImpl(aRoot, true);
1194 }
1196 /**
1197 * Returns true if 'this' is either document or element or
1198 * document fragment and aOther is a descendant in the same
1199 * anonymous tree.
1200 */
1201 bool Contains(const nsINode* aOther) const;
1202 nsresult Contains(nsIDOMNode* aOther, bool* aReturn);
1204 bool UnoptimizableCCNode() const;
1206 private:
1208 nsIContent* GetNextNodeImpl(const nsINode* aRoot,
1209 const bool aSkipChildren) const
1210 {
1211 // Can't use nsContentUtils::ContentIsDescendantOf here, since we
1212 // can't include it here.
1213 #ifdef DEBUG
1214 if (aRoot) {
1215 const nsINode* cur = this;
1216 for (; cur; cur = cur->GetParentNode())
1217 if (cur == aRoot) break;
1218 NS_ASSERTION(cur, "aRoot not an ancestor of |this|?");
1219 }
1220 #endif
1221 if (!aSkipChildren) {
1222 nsIContent* kid = GetFirstChild();
1223 if (kid) {
1224 return kid;
1225 }
1226 }
1227 if (this == aRoot) {
1228 return nullptr;
1229 }
1230 const nsINode* cur = this;
1231 while (1) {
1232 nsIContent* next = cur->GetNextSibling();
1233 if (next) {
1234 return next;
1235 }
1236 nsINode* parent = cur->GetParentNode();
1237 if (parent == aRoot) {
1238 return nullptr;
1239 }
1240 cur = parent;
1241 }
1242 NS_NOTREACHED("How did we get here?");
1243 }
1245 public:
1247 /**
1248 * Get the previous nsIContent in the pre-order tree traversal of the DOM. If
1249 * aRoot is non-null, then it must be an ancestor of |this|
1250 * (possibly equal to |this|) and only nsIContents that are descendants of
1251 * aRoot, including aRoot itself, will be returned. Returns
1252 * null if there are no more nsIContents to traverse.
1253 */
1254 nsIContent* GetPreviousContent(const nsINode* aRoot = nullptr) const
1255 {
1256 // Can't use nsContentUtils::ContentIsDescendantOf here, since we
1257 // can't include it here.
1258 #ifdef DEBUG
1259 if (aRoot) {
1260 const nsINode* cur = this;
1261 for (; cur; cur = cur->GetParentNode())
1262 if (cur == aRoot) break;
1263 NS_ASSERTION(cur, "aRoot not an ancestor of |this|?");
1264 }
1265 #endif
1267 if (this == aRoot) {
1268 return nullptr;
1269 }
1270 nsIContent* cur = this->GetParent();
1271 nsIContent* iter = this->GetPreviousSibling();
1272 while (iter) {
1273 cur = iter;
1274 iter = reinterpret_cast<nsINode*>(iter)->GetLastChild();
1275 }
1276 return cur;
1277 }
1279 /**
1280 * Boolean flags
1281 */
1282 private:
1283 enum BooleanFlag {
1284 // Set if we're being used from -moz-element
1285 NodeHasRenderingObservers,
1286 // Set if our parent chain (including this node itself) terminates
1287 // in a document
1288 IsInDocument,
1289 // Set if mParent is an nsIContent
1290 ParentIsContent,
1291 // Set if this node is an Element
1292 NodeIsElement,
1293 // Set if the element has a non-empty id attribute. This can in rare
1294 // cases lie for nsXMLElement, such as when the node has been moved between
1295 // documents with different id mappings.
1296 ElementHasID,
1297 // Set if the element might have inline style.
1298 ElementMayHaveStyle,
1299 // Set if the element has a name attribute set.
1300 ElementHasName,
1301 // Set if the element might have a contenteditable attribute set.
1302 ElementMayHaveContentEditableAttr,
1303 // Set if the node is the common ancestor of the start/end nodes of a Range
1304 // that is in a Selection.
1305 NodeIsCommonAncestorForRangeInSelection,
1306 // Set if the node is a descendant of a node with the above bit set.
1307 NodeIsDescendantOfCommonAncestorForRangeInSelection,
1308 // Set if CanSkipInCC check has been done for this subtree root.
1309 NodeIsCCMarkedRoot,
1310 // Maybe set if this node is in black subtree.
1311 NodeIsCCBlackTree,
1312 // Maybe set if the node is a root of a subtree
1313 // which needs to be kept in the purple buffer.
1314 NodeIsPurpleRoot,
1315 // Set if the node has an explicit base URI stored
1316 NodeHasExplicitBaseURI,
1317 // Set if the element has some style states locked
1318 ElementHasLockedStyleStates,
1319 // Set if element has pointer locked
1320 ElementHasPointerLock,
1321 // Set if the node may have DOMMutationObserver attached to it.
1322 NodeMayHaveDOMMutationObserver,
1323 // Set if node is Content
1324 NodeIsContent,
1325 // Set if the node has animations or transitions
1326 ElementHasAnimations,
1327 // Set if node has a dir attribute with a valid value (ltr, rtl, or auto)
1328 NodeHasValidDirAttribute,
1329 // Set if node has a dir attribute with a fixed value (ltr or rtl, NOT auto)
1330 NodeHasFixedDir,
1331 // Set if the node has dir=auto and has a property pointing to the text
1332 // node that determines its direction
1333 NodeHasDirAutoSet,
1334 // Set if the node is a text node descendant of a node with dir=auto
1335 // and has a TextNodeDirectionalityMap property listing the elements whose
1336 // direction it determines.
1337 NodeHasTextNodeDirectionalityMap,
1338 // Set if the node has dir=auto.
1339 NodeHasDirAuto,
1340 // Set if a node in the node's parent chain has dir=auto.
1341 NodeAncestorHasDirAuto,
1342 // Set if the element is in the scope of a scoped style sheet; this flag is
1343 // only accurate for elements bound to a document
1344 ElementIsInStyleScope,
1345 // Set if the element is a scoped style sheet root
1346 ElementIsScopedStyleRoot,
1347 // Set if the node is handling a click.
1348 NodeHandlingClick,
1349 // Set if the node has had :hover selectors matched against it
1350 NodeHasRelevantHoverRules,
1351 // Set if the element has a parser insertion mode other than "in body",
1352 // per the HTML5 "Parse state" section.
1353 ElementHasWeirdParserInsertionMode,
1354 // Guard value
1355 BooleanFlagCount
1356 };
1358 void SetBoolFlag(BooleanFlag name, bool value) {
1359 static_assert(BooleanFlagCount <= 8*sizeof(mBoolFlags),
1360 "Too many boolean flags");
1361 mBoolFlags = (mBoolFlags & ~(1 << name)) | (value << name);
1362 }
1364 void SetBoolFlag(BooleanFlag name) {
1365 static_assert(BooleanFlagCount <= 8*sizeof(mBoolFlags),
1366 "Too many boolean flags");
1367 mBoolFlags |= (1 << name);
1368 }
1370 void ClearBoolFlag(BooleanFlag name) {
1371 static_assert(BooleanFlagCount <= 8*sizeof(mBoolFlags),
1372 "Too many boolean flags");
1373 mBoolFlags &= ~(1 << name);
1374 }
1376 bool GetBoolFlag(BooleanFlag name) const {
1377 static_assert(BooleanFlagCount <= 8*sizeof(mBoolFlags),
1378 "Too many boolean flags");
1379 return mBoolFlags & (1 << name);
1380 }
1382 public:
1383 bool HasRenderingObservers() const
1384 { return GetBoolFlag(NodeHasRenderingObservers); }
1385 void SetHasRenderingObservers(bool aValue)
1386 { SetBoolFlag(NodeHasRenderingObservers, aValue); }
1387 bool IsContent() const { return GetBoolFlag(NodeIsContent); }
1388 bool HasID() const { return GetBoolFlag(ElementHasID); }
1389 bool MayHaveStyle() const { return GetBoolFlag(ElementMayHaveStyle); }
1390 bool HasName() const { return GetBoolFlag(ElementHasName); }
1391 bool MayHaveContentEditableAttr() const
1392 { return GetBoolFlag(ElementMayHaveContentEditableAttr); }
1393 bool IsCommonAncestorForRangeInSelection() const
1394 { return GetBoolFlag(NodeIsCommonAncestorForRangeInSelection); }
1395 void SetCommonAncestorForRangeInSelection()
1396 { SetBoolFlag(NodeIsCommonAncestorForRangeInSelection); }
1397 void ClearCommonAncestorForRangeInSelection()
1398 { ClearBoolFlag(NodeIsCommonAncestorForRangeInSelection); }
1399 bool IsDescendantOfCommonAncestorForRangeInSelection() const
1400 { return GetBoolFlag(NodeIsDescendantOfCommonAncestorForRangeInSelection); }
1401 void SetDescendantOfCommonAncestorForRangeInSelection()
1402 { SetBoolFlag(NodeIsDescendantOfCommonAncestorForRangeInSelection); }
1403 void ClearDescendantOfCommonAncestorForRangeInSelection()
1404 { ClearBoolFlag(NodeIsDescendantOfCommonAncestorForRangeInSelection); }
1406 void SetCCMarkedRoot(bool aValue)
1407 { SetBoolFlag(NodeIsCCMarkedRoot, aValue); }
1408 bool CCMarkedRoot() const { return GetBoolFlag(NodeIsCCMarkedRoot); }
1409 void SetInCCBlackTree(bool aValue)
1410 { SetBoolFlag(NodeIsCCBlackTree, aValue); }
1411 bool InCCBlackTree() const { return GetBoolFlag(NodeIsCCBlackTree); }
1412 void SetIsPurpleRoot(bool aValue)
1413 { SetBoolFlag(NodeIsPurpleRoot, aValue); }
1414 bool IsPurpleRoot() const { return GetBoolFlag(NodeIsPurpleRoot); }
1415 bool MayHaveDOMMutationObserver()
1416 { return GetBoolFlag(NodeMayHaveDOMMutationObserver); }
1417 void SetMayHaveDOMMutationObserver()
1418 { SetBoolFlag(NodeMayHaveDOMMutationObserver, true); }
1419 bool HasListenerManager() { return HasFlag(NODE_HAS_LISTENERMANAGER); }
1420 bool HasPointerLock() const { return GetBoolFlag(ElementHasPointerLock); }
1421 void SetPointerLock() { SetBoolFlag(ElementHasPointerLock); }
1422 void ClearPointerLock() { ClearBoolFlag(ElementHasPointerLock); }
1423 bool MayHaveAnimations() { return GetBoolFlag(ElementHasAnimations); }
1424 void SetMayHaveAnimations() { SetBoolFlag(ElementHasAnimations); }
1425 void SetHasValidDir() { SetBoolFlag(NodeHasValidDirAttribute); }
1426 void ClearHasValidDir() { ClearBoolFlag(NodeHasValidDirAttribute); }
1427 bool HasValidDir() const { return GetBoolFlag(NodeHasValidDirAttribute); }
1428 void SetHasFixedDir() {
1429 MOZ_ASSERT(NodeType() != nsIDOMNode::TEXT_NODE,
1430 "SetHasFixedDir on text node");
1431 SetBoolFlag(NodeHasFixedDir);
1432 }
1433 void ClearHasFixedDir() {
1434 MOZ_ASSERT(NodeType() != nsIDOMNode::TEXT_NODE,
1435 "ClearHasFixedDir on text node");
1436 ClearBoolFlag(NodeHasFixedDir);
1437 }
1438 bool HasFixedDir() const { return GetBoolFlag(NodeHasFixedDir); }
1439 void SetHasDirAutoSet() {
1440 MOZ_ASSERT(NodeType() != nsIDOMNode::TEXT_NODE,
1441 "SetHasDirAutoSet on text node");
1442 SetBoolFlag(NodeHasDirAutoSet);
1443 }
1444 void ClearHasDirAutoSet() {
1445 MOZ_ASSERT(NodeType() != nsIDOMNode::TEXT_NODE,
1446 "ClearHasDirAutoSet on text node");
1447 ClearBoolFlag(NodeHasDirAutoSet);
1448 }
1449 bool HasDirAutoSet() const
1450 { return GetBoolFlag(NodeHasDirAutoSet); }
1451 void SetHasTextNodeDirectionalityMap() {
1452 MOZ_ASSERT(NodeType() == nsIDOMNode::TEXT_NODE,
1453 "SetHasTextNodeDirectionalityMap on non-text node");
1454 SetBoolFlag(NodeHasTextNodeDirectionalityMap);
1455 }
1456 void ClearHasTextNodeDirectionalityMap() {
1457 MOZ_ASSERT(NodeType() == nsIDOMNode::TEXT_NODE,
1458 "ClearHasTextNodeDirectionalityMap on non-text node");
1459 ClearBoolFlag(NodeHasTextNodeDirectionalityMap);
1460 }
1461 bool HasTextNodeDirectionalityMap() const
1462 { return GetBoolFlag(NodeHasTextNodeDirectionalityMap); }
1464 void SetHasDirAuto() { SetBoolFlag(NodeHasDirAuto); }
1465 void ClearHasDirAuto() { ClearBoolFlag(NodeHasDirAuto); }
1466 bool HasDirAuto() const { return GetBoolFlag(NodeHasDirAuto); }
1468 void SetAncestorHasDirAuto() { SetBoolFlag(NodeAncestorHasDirAuto); }
1469 void ClearAncestorHasDirAuto() { ClearBoolFlag(NodeAncestorHasDirAuto); }
1470 bool AncestorHasDirAuto() const { return GetBoolFlag(NodeAncestorHasDirAuto); }
1472 bool NodeOrAncestorHasDirAuto() const
1473 { return HasDirAuto() || AncestorHasDirAuto(); }
1475 void SetIsElementInStyleScope(bool aValue) {
1476 MOZ_ASSERT(IsElement(), "SetIsInStyleScope on a non-Element node");
1477 SetBoolFlag(ElementIsInStyleScope, aValue);
1478 }
1479 void SetIsElementInStyleScope() {
1480 MOZ_ASSERT(IsElement(), "SetIsInStyleScope on a non-Element node");
1481 SetBoolFlag(ElementIsInStyleScope);
1482 }
1483 void ClearIsElementInStyleScope() {
1484 MOZ_ASSERT(IsElement(), "ClearIsInStyleScope on a non-Element node");
1485 ClearBoolFlag(ElementIsInStyleScope);
1486 }
1487 bool IsElementInStyleScope() const { return GetBoolFlag(ElementIsInStyleScope); }
1489 void SetIsScopedStyleRoot() { SetBoolFlag(ElementIsScopedStyleRoot); }
1490 void ClearIsScopedStyleRoot() { ClearBoolFlag(ElementIsScopedStyleRoot); }
1491 bool IsScopedStyleRoot() { return GetBoolFlag(ElementIsScopedStyleRoot); }
1492 bool HasRelevantHoverRules() const { return GetBoolFlag(NodeHasRelevantHoverRules); }
1493 void SetHasRelevantHoverRules() { SetBoolFlag(NodeHasRelevantHoverRules); }
1494 protected:
1495 void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
1496 void SetInDocument() { SetBoolFlag(IsInDocument); }
1497 void SetNodeIsContent() { SetBoolFlag(NodeIsContent); }
1498 void ClearInDocument() { ClearBoolFlag(IsInDocument); }
1499 void SetIsElement() { SetBoolFlag(NodeIsElement); }
1500 void SetHasID() { SetBoolFlag(ElementHasID); }
1501 void ClearHasID() { ClearBoolFlag(ElementHasID); }
1502 void SetMayHaveStyle() { SetBoolFlag(ElementMayHaveStyle); }
1503 void SetHasName() { SetBoolFlag(ElementHasName); }
1504 void ClearHasName() { ClearBoolFlag(ElementHasName); }
1505 void SetMayHaveContentEditableAttr()
1506 { SetBoolFlag(ElementMayHaveContentEditableAttr); }
1507 bool HasExplicitBaseURI() const { return GetBoolFlag(NodeHasExplicitBaseURI); }
1508 void SetHasExplicitBaseURI() { SetBoolFlag(NodeHasExplicitBaseURI); }
1509 void SetHasLockedStyleStates() { SetBoolFlag(ElementHasLockedStyleStates); }
1510 void ClearHasLockedStyleStates() { ClearBoolFlag(ElementHasLockedStyleStates); }
1511 bool HasLockedStyleStates() const
1512 { return GetBoolFlag(ElementHasLockedStyleStates); }
1513 void SetHasWeirdParserInsertionMode() { SetBoolFlag(ElementHasWeirdParserInsertionMode); }
1514 bool HasWeirdParserInsertionMode() const
1515 { return GetBoolFlag(ElementHasWeirdParserInsertionMode); }
1516 bool HandlingClick() const { return GetBoolFlag(NodeHandlingClick); }
1517 void SetHandlingClick() { SetBoolFlag(NodeHandlingClick); }
1518 void ClearHandlingClick() { ClearBoolFlag(NodeHandlingClick); }
1520 void SetSubtreeRootPointer(nsINode* aSubtreeRoot)
1521 {
1522 NS_ASSERTION(aSubtreeRoot, "aSubtreeRoot can never be null!");
1523 NS_ASSERTION(!(IsNodeOfType(eCONTENT) && IsInDoc()), "Shouldn't be here!");
1524 mSubtreeRoot = aSubtreeRoot;
1525 }
1527 void ClearSubtreeRootPointer()
1528 {
1529 mSubtreeRoot = nullptr;
1530 }
1532 public:
1533 // Makes nsINode object to keep aObject alive.
1534 void BindObject(nsISupports* aObject);
1535 // After calling UnbindObject nsINode object doesn't keep
1536 // aObject alive anymore.
1537 void UnbindObject(nsISupports* aObject);
1539 void GetBoundMutationObservers(nsTArray<nsRefPtr<nsDOMMutationObserver> >& aResult);
1541 /**
1542 * Returns the length of this node, as specified at
1543 * <http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node-length>
1544 */
1545 uint32_t Length() const;
1547 void GetNodeName(mozilla::dom::DOMString& aNodeName)
1548 {
1549 const nsString& nodeName = NodeName();
1550 aNodeName.SetStringBuffer(nsStringBuffer::FromString(nodeName),
1551 nodeName.Length());
1552 }
1553 void GetBaseURI(nsAString& aBaseURI) const;
1554 // Return the base URI for the document.
1555 // The returned value may differ if the document is loaded via XHR, and
1556 // when accessed from chrome privileged script and
1557 // from content privileged script for compatibility.
1558 void GetBaseURIFromJS(nsAString& aBaseURI) const;
1559 bool HasChildNodes() const
1560 {
1561 return HasChildren();
1562 }
1563 uint16_t CompareDocumentPosition(nsINode& aOther) const;
1564 void GetNodeValue(nsAString& aNodeValue)
1565 {
1566 GetNodeValueInternal(aNodeValue);
1567 }
1568 void SetNodeValue(const nsAString& aNodeValue,
1569 mozilla::ErrorResult& aError)
1570 {
1571 SetNodeValueInternal(aNodeValue, aError);
1572 }
1573 virtual void GetNodeValueInternal(nsAString& aNodeValue);
1574 virtual void SetNodeValueInternal(const nsAString& aNodeValue,
1575 mozilla::ErrorResult& aError)
1576 {
1577 // The DOM spec says that when nodeValue is defined to be null "setting it
1578 // has no effect", so we don't throw an exception.
1579 }
1580 nsINode* InsertBefore(nsINode& aNode, nsINode* aChild,
1581 mozilla::ErrorResult& aError)
1582 {
1583 return ReplaceOrInsertBefore(false, &aNode, aChild, aError);
1584 }
1585 nsINode* AppendChild(nsINode& aNode, mozilla::ErrorResult& aError)
1586 {
1587 return InsertBefore(aNode, nullptr, aError);
1588 }
1589 nsINode* ReplaceChild(nsINode& aNode, nsINode& aChild,
1590 mozilla::ErrorResult& aError)
1591 {
1592 return ReplaceOrInsertBefore(true, &aNode, &aChild, aError);
1593 }
1594 nsINode* RemoveChild(nsINode& aChild, mozilla::ErrorResult& aError);
1595 already_AddRefed<nsINode> CloneNode(bool aDeep, mozilla::ErrorResult& aError);
1596 bool IsEqualNode(nsINode* aNode);
1597 void GetNamespaceURI(nsAString& aNamespaceURI) const
1598 {
1599 mNodeInfo->GetNamespaceURI(aNamespaceURI);
1600 }
1601 #ifdef MOZILLA_INTERNAL_API
1602 void GetPrefix(nsAString& aPrefix)
1603 {
1604 mNodeInfo->GetPrefix(aPrefix);
1605 }
1606 #endif
1607 void GetLocalName(mozilla::dom::DOMString& aLocalName)
1608 {
1609 const nsString& localName = LocalName();
1610 if (localName.IsVoid()) {
1611 aLocalName.SetNull();
1612 } else {
1613 aLocalName.SetStringBuffer(nsStringBuffer::FromString(localName),
1614 localName.Length());
1615 }
1616 }
1617 // HasAttributes is defined inline in Element.h.
1618 bool HasAttributes() const;
1619 nsDOMAttributeMap* GetAttributes();
1620 void SetUserData(JSContext* aCx, const nsAString& aKey,
1621 JS::Handle<JS::Value> aData,
1622 nsIDOMUserDataHandler* aHandler,
1623 JS::MutableHandle<JS::Value> aRetval,
1624 mozilla::ErrorResult& aError);
1625 void GetUserData(JSContext* aCx, const nsAString& aKey,
1626 JS::MutableHandle<JS::Value> aRetval,
1627 mozilla::ErrorResult& aError);
1629 // Helper method to remove this node from its parent. This is not exposed
1630 // through WebIDL.
1631 // Only call this if the node has a parent node.
1632 nsresult RemoveFromParent()
1633 {
1634 nsINode* parent = GetParentNode();
1635 mozilla::ErrorResult rv;
1636 parent->RemoveChild(*this, rv);
1637 return rv.ErrorCode();
1638 }
1640 // ChildNode methods
1641 mozilla::dom::Element* GetPreviousElementSibling() const;
1642 mozilla::dom::Element* GetNextElementSibling() const;
1643 /**
1644 * Remove this node from its parent, if any.
1645 */
1646 void Remove();
1648 // ParentNode methods
1649 mozilla::dom::Element* GetFirstElementChild() const;
1650 mozilla::dom::Element* GetLastElementChild() const;
1652 void GetBoxQuads(const BoxQuadOptions& aOptions,
1653 nsTArray<nsRefPtr<DOMQuad> >& aResult,
1654 mozilla::ErrorResult& aRv);
1656 already_AddRefed<DOMQuad> ConvertQuadFromNode(DOMQuad& aQuad,
1657 const TextOrElementOrDocument& aFrom,
1658 const ConvertCoordinateOptions& aOptions,
1659 ErrorResult& aRv);
1660 already_AddRefed<DOMQuad> ConvertRectFromNode(DOMRectReadOnly& aRect,
1661 const TextOrElementOrDocument& aFrom,
1662 const ConvertCoordinateOptions& aOptions,
1663 ErrorResult& aRv);
1664 already_AddRefed<DOMPoint> ConvertPointFromNode(const DOMPointInit& aPoint,
1665 const TextOrElementOrDocument& aFrom,
1666 const ConvertCoordinateOptions& aOptions,
1667 ErrorResult& aRv);
1669 protected:
1671 // Override this function to create a custom slots class.
1672 // Must not return null.
1673 virtual nsINode::nsSlots* CreateSlots();
1675 bool HasSlots() const
1676 {
1677 return mSlots != nullptr;
1678 }
1680 nsSlots* GetExistingSlots() const
1681 {
1682 return mSlots;
1683 }
1685 nsSlots* Slots()
1686 {
1687 if (!HasSlots()) {
1688 mSlots = CreateSlots();
1689 MOZ_ASSERT(mSlots);
1690 }
1691 return GetExistingSlots();
1692 }
1694 nsTObserverArray<nsIMutationObserver*> *GetMutationObservers()
1695 {
1696 return HasSlots() ? &GetExistingSlots()->mMutationObservers : nullptr;
1697 }
1699 bool IsEditableInternal() const;
1700 virtual bool IsEditableExternal() const
1701 {
1702 return IsEditableInternal();
1703 }
1705 virtual void GetTextContentInternal(nsAString& aTextContent);
1706 virtual void SetTextContentInternal(const nsAString& aTextContent,
1707 mozilla::ErrorResult& aError)
1708 {
1709 }
1711 #ifdef DEBUG
1712 // Note: virtual so that IsInNativeAnonymousSubtree can be called accross
1713 // module boundaries.
1714 virtual void CheckNotNativeAnonymous() const;
1715 #endif
1717 // These are just used to implement nsIDOMNode using
1718 // NS_FORWARD_NSIDOMNODE_TO_NSINODE_HELPER and for quickstubs.
1719 nsresult GetParentNode(nsIDOMNode** aParentNode);
1720 nsresult GetParentElement(nsIDOMElement** aParentElement);
1721 nsresult GetChildNodes(nsIDOMNodeList** aChildNodes);
1722 nsresult GetFirstChild(nsIDOMNode** aFirstChild);
1723 nsresult GetLastChild(nsIDOMNode** aLastChild);
1724 nsresult GetPreviousSibling(nsIDOMNode** aPrevSibling);
1725 nsresult GetNextSibling(nsIDOMNode** aNextSibling);
1726 nsresult GetOwnerDocument(nsIDOMDocument** aOwnerDocument);
1727 nsresult CompareDocumentPosition(nsIDOMNode* aOther,
1728 uint16_t* aReturn);
1730 nsresult ReplaceOrInsertBefore(bool aReplace, nsIDOMNode *aNewChild,
1731 nsIDOMNode *aRefChild, nsIDOMNode **aReturn);
1732 nsINode* ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
1733 nsINode* aRefChild,
1734 mozilla::ErrorResult& aError);
1735 nsresult RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn);
1737 /**
1738 * Returns the Element that should be used for resolving namespaces
1739 * on this node (ie the ownerElement for attributes, the documentElement for
1740 * documents, the node itself for elements and for other nodes the parentNode
1741 * if it is an element).
1742 */
1743 virtual mozilla::dom::Element* GetNameSpaceElement() = 0;
1745 /**
1746 * Most of the implementation of the nsINode RemoveChildAt method.
1747 * Should only be called on document, element, and document fragment
1748 * nodes. The aChildArray passed in should be the one for |this|.
1749 *
1750 * @param aIndex The index to remove at.
1751 * @param aNotify Whether to notify.
1752 * @param aKid The kid at aIndex. Must not be null.
1753 * @param aChildArray The child array to work with.
1754 * @param aMutationEvent whether to fire a mutation event for this removal.
1755 */
1756 void doRemoveChildAt(uint32_t aIndex, bool aNotify, nsIContent* aKid,
1757 nsAttrAndChildArray& aChildArray);
1759 /**
1760 * Most of the implementation of the nsINode InsertChildAt method.
1761 * Should only be called on document, element, and document fragment
1762 * nodes. The aChildArray passed in should be the one for |this|.
1763 *
1764 * @param aKid The child to insert.
1765 * @param aIndex The index to insert at.
1766 * @param aNotify Whether to notify.
1767 * @param aChildArray The child array to work with
1768 */
1769 nsresult doInsertChildAt(nsIContent* aKid, uint32_t aIndex,
1770 bool aNotify, nsAttrAndChildArray& aChildArray);
1772 /**
1773 * Parse the given selector string into an nsCSSSelectorList.
1774 *
1775 * A null return value with a non-failing aRv means the string only
1776 * contained pseudo-element selectors.
1777 *
1778 * A failing aRv means the string was not a valid selector.
1779 */
1780 nsCSSSelectorList* ParseSelectorList(const nsAString& aSelectorString,
1781 mozilla::ErrorResult& aRv);
1783 public:
1784 /* Event stuff that documents and elements share. This needs to be
1785 NS_IMETHOD because some subclasses implement DOM methods with
1786 this exact name and signature and then the calling convention
1787 needs to match.
1789 Note that we include DOCUMENT_ONLY_EVENT events here so that we
1790 can forward all the document stuff to this implementation.
1791 */
1792 #define EVENT(name_, id_, type_, struct_) \
1793 mozilla::dom::EventHandlerNonNull* GetOn##name_(); \
1794 void SetOn##name_(mozilla::dom::EventHandlerNonNull* listener);
1795 #define TOUCH_EVENT EVENT
1796 #define DOCUMENT_ONLY_EVENT EVENT
1797 #include "mozilla/EventNameList.h"
1798 #undef DOCUMENT_ONLY_EVENT
1799 #undef TOUCH_EVENT
1800 #undef EVENT
1802 protected:
1803 static bool Traverse(nsINode *tmp, nsCycleCollectionTraversalCallback &cb);
1804 static void Unlink(nsINode *tmp);
1806 nsCOMPtr<nsINodeInfo> mNodeInfo;
1808 nsINode* mParent;
1810 private:
1811 // Boolean flags.
1812 uint32_t mBoolFlags;
1814 protected:
1815 nsIContent* mNextSibling;
1816 nsIContent* mPreviousSibling;
1817 nsIContent* mFirstChild;
1819 union {
1820 // Pointer to our primary frame. Might be null.
1821 nsIFrame* mPrimaryFrame;
1823 // Pointer to the root of our subtree. Might be null.
1824 nsINode* mSubtreeRoot;
1825 };
1827 // Storage for more members that are usually not needed; allocated lazily.
1828 nsSlots* mSlots;
1829 };
1831 // Useful inline function for getting a node given an nsIContent and an
1832 // nsIDocument. Returns the first argument cast to nsINode if it is non-null,
1833 // otherwise returns the second (which may be null). We use type variables
1834 // instead of nsIContent* and nsIDocument* because the actual types must be
1835 // known for the cast to work.
1836 template<class C, class D>
1837 inline nsINode* NODE_FROM(C& aContent, D& aDocument)
1838 {
1839 if (aContent)
1840 return static_cast<nsINode*>(aContent);
1841 return static_cast<nsINode*>(aDocument);
1842 }
1844 NS_DEFINE_STATIC_IID_ACCESSOR(nsINode, NS_INODE_IID)
1846 inline nsISupports*
1847 ToSupports(nsINode* aPointer)
1848 {
1849 return aPointer;
1850 }
1852 inline nsISupports*
1853 ToCanonicalSupports(nsINode* aPointer)
1854 {
1855 return aPointer;
1856 }
1858 #define NS_FORWARD_NSIDOMNODE_TO_NSINODE_HELPER(...) \
1859 NS_IMETHOD GetNodeName(nsAString& aNodeName) __VA_ARGS__ \
1860 { \
1861 aNodeName = nsINode::NodeName(); \
1862 return NS_OK; \
1863 } \
1864 NS_IMETHOD GetNodeValue(nsAString& aNodeValue) __VA_ARGS__ \
1865 { \
1866 nsINode::GetNodeValue(aNodeValue); \
1867 return NS_OK; \
1868 } \
1869 NS_IMETHOD SetNodeValue(const nsAString& aNodeValue) __VA_ARGS__ \
1870 { \
1871 mozilla::ErrorResult rv; \
1872 nsINode::SetNodeValue(aNodeValue, rv); \
1873 return rv.ErrorCode(); \
1874 } \
1875 NS_IMETHOD GetNodeType(uint16_t* aNodeType) __VA_ARGS__ \
1876 { \
1877 *aNodeType = nsINode::NodeType(); \
1878 return NS_OK; \
1879 } \
1880 NS_IMETHOD GetParentNode(nsIDOMNode** aParentNode) __VA_ARGS__ \
1881 { \
1882 return nsINode::GetParentNode(aParentNode); \
1883 } \
1884 NS_IMETHOD GetParentElement(nsIDOMElement** aParentElement) __VA_ARGS__ \
1885 { \
1886 return nsINode::GetParentElement(aParentElement); \
1887 } \
1888 NS_IMETHOD GetChildNodes(nsIDOMNodeList** aChildNodes) __VA_ARGS__ \
1889 { \
1890 return nsINode::GetChildNodes(aChildNodes); \
1891 } \
1892 NS_IMETHOD GetFirstChild(nsIDOMNode** aFirstChild) __VA_ARGS__ \
1893 { \
1894 return nsINode::GetFirstChild(aFirstChild); \
1895 } \
1896 NS_IMETHOD GetLastChild(nsIDOMNode** aLastChild) __VA_ARGS__ \
1897 { \
1898 return nsINode::GetLastChild(aLastChild); \
1899 } \
1900 NS_IMETHOD GetPreviousSibling(nsIDOMNode** aPreviousSibling) __VA_ARGS__ \
1901 { \
1902 return nsINode::GetPreviousSibling(aPreviousSibling); \
1903 } \
1904 NS_IMETHOD GetNextSibling(nsIDOMNode** aNextSibling) __VA_ARGS__ \
1905 { \
1906 return nsINode::GetNextSibling(aNextSibling); \
1907 } \
1908 NS_IMETHOD GetOwnerDocument(nsIDOMDocument** aOwnerDocument) __VA_ARGS__ \
1909 { \
1910 return nsINode::GetOwnerDocument(aOwnerDocument); \
1911 } \
1912 NS_IMETHOD InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMNode** aResult) __VA_ARGS__ \
1913 { \
1914 return ReplaceOrInsertBefore(false, aNewChild, aRefChild, aResult); \
1915 } \
1916 NS_IMETHOD ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild, nsIDOMNode** aResult) __VA_ARGS__ \
1917 { \
1918 return ReplaceOrInsertBefore(true, aNewChild, aOldChild, aResult); \
1919 } \
1920 NS_IMETHOD RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aResult) __VA_ARGS__ \
1921 { \
1922 return nsINode::RemoveChild(aOldChild, aResult); \
1923 } \
1924 NS_IMETHOD AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aResult) __VA_ARGS__ \
1925 { \
1926 return InsertBefore(aNewChild, nullptr, aResult); \
1927 } \
1928 NS_IMETHOD HasChildNodes(bool* aResult) __VA_ARGS__ \
1929 { \
1930 *aResult = nsINode::HasChildNodes(); \
1931 return NS_OK; \
1932 } \
1933 NS_IMETHOD CloneNode(bool aDeep, uint8_t aArgc, nsIDOMNode** aResult) __VA_ARGS__ \
1934 { \
1935 if (aArgc == 0) { \
1936 aDeep = true; \
1937 } \
1938 mozilla::ErrorResult rv; \
1939 nsCOMPtr<nsINode> clone = nsINode::CloneNode(aDeep, rv); \
1940 if (rv.Failed()) { \
1941 return rv.ErrorCode(); \
1942 } \
1943 *aResult = clone.forget().take()->AsDOMNode(); \
1944 return NS_OK; \
1945 } \
1946 NS_IMETHOD Normalize() __VA_ARGS__ \
1947 { \
1948 nsINode::Normalize(); \
1949 return NS_OK; \
1950 } \
1951 NS_IMETHOD GetNamespaceURI(nsAString& aNamespaceURI) __VA_ARGS__ \
1952 { \
1953 nsINode::GetNamespaceURI(aNamespaceURI); \
1954 return NS_OK; \
1955 } \
1956 NS_IMETHOD GetPrefix(nsAString& aPrefix) __VA_ARGS__ \
1957 { \
1958 nsINode::GetPrefix(aPrefix); \
1959 return NS_OK; \
1960 } \
1961 NS_IMETHOD GetLocalName(nsAString& aLocalName) __VA_ARGS__ \
1962 { \
1963 aLocalName = nsINode::LocalName(); \
1964 return NS_OK; \
1965 } \
1966 using nsINode::HasAttributes; \
1967 NS_IMETHOD HasAttributes(bool* aResult) __VA_ARGS__ \
1968 { \
1969 *aResult = nsINode::HasAttributes(); \
1970 return NS_OK; \
1971 } \
1972 NS_IMETHOD GetDOMBaseURI(nsAString& aBaseURI) __VA_ARGS__ \
1973 { \
1974 nsINode::GetBaseURI(aBaseURI); \
1975 return NS_OK; \
1976 } \
1977 NS_IMETHOD CompareDocumentPosition(nsIDOMNode* aOther, uint16_t* aResult) __VA_ARGS__ \
1978 { \
1979 return nsINode::CompareDocumentPosition(aOther, aResult); \
1980 } \
1981 NS_IMETHOD GetTextContent(nsAString& aTextContent) __VA_ARGS__ \
1982 { \
1983 nsINode::GetTextContent(aTextContent); \
1984 return NS_OK; \
1985 } \
1986 NS_IMETHOD SetTextContent(const nsAString& aTextContent) __VA_ARGS__ \
1987 { \
1988 mozilla::ErrorResult rv; \
1989 nsINode::SetTextContent(aTextContent, rv); \
1990 return rv.ErrorCode(); \
1991 } \
1992 NS_IMETHOD LookupPrefix(const nsAString& aNamespaceURI, nsAString& aResult) __VA_ARGS__ \
1993 { \
1994 nsINode::LookupPrefix(aNamespaceURI, aResult); \
1995 return NS_OK; \
1996 } \
1997 NS_IMETHOD IsDefaultNamespace(const nsAString& aNamespaceURI, bool* aResult) __VA_ARGS__ \
1998 { \
1999 *aResult = nsINode::IsDefaultNamespace(aNamespaceURI); \
2000 return NS_OK; \
2001 } \
2002 NS_IMETHOD LookupNamespaceURI(const nsAString& aPrefix, nsAString& aResult) __VA_ARGS__ \
2003 { \
2004 nsINode::LookupNamespaceURI(aPrefix, aResult); \
2005 return NS_OK; \
2006 } \
2007 NS_IMETHOD IsEqualNode(nsIDOMNode* aArg, bool* aResult) __VA_ARGS__ \
2008 { \
2009 return nsINode::IsEqualNode(aArg, aResult); \
2010 } \
2011 NS_IMETHOD SetUserData(const nsAString& aKey, nsIVariant* aData, nsIDOMUserDataHandler* aHandler, nsIVariant** aResult) __VA_ARGS__ \
2012 { \
2013 return nsINode::SetUserData(aKey, aData, aHandler, aResult); \
2014 } \
2015 NS_IMETHOD GetUserData(const nsAString& aKey, nsIVariant** aResult) __VA_ARGS__ \
2016 { \
2017 return nsINode::GetUserData(aKey, aResult); \
2018 } \
2019 NS_IMETHOD Contains(nsIDOMNode* aOther, bool* aResult) __VA_ARGS__ \
2020 { \
2021 return nsINode::Contains(aOther, aResult); \
2022 }
2024 #define NS_FORWARD_NSIDOMNODE_TO_NSINODE \
2025 NS_FORWARD_NSIDOMNODE_TO_NSINODE_HELPER(MOZ_FINAL)
2027 #define NS_FORWARD_NSIDOMNODE_TO_NSINODE_OVERRIDABLE \
2028 NS_FORWARD_NSIDOMNODE_TO_NSINODE_HELPER()
2030 #endif /* nsINode_h___ */