content/base/public/nsINode.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial