content/base/public/nsINode.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/content/base/public/nsINode.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2030 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef nsINode_h___
    1.10 +#define nsINode_h___
    1.11 +
    1.12 +#include "mozilla/Likely.h"
    1.13 +#include "nsCOMPtr.h"               // for member, local
    1.14 +#include "nsGkAtoms.h"              // for nsGkAtoms::baseURIProperty
    1.15 +#include "nsIDOMNode.h"
    1.16 +#include "nsINodeInfo.h"            // member (in nsCOMPtr)
    1.17 +#include "nsIVariant.h"             // for use in GetUserData()
    1.18 +#include "nsNodeInfoManager.h"      // for use in NodePrincipal()
    1.19 +#include "nsPropertyTable.h"        // for typedefs
    1.20 +#include "nsTObserverArray.h"       // for member
    1.21 +#include "mozilla/ErrorResult.h"
    1.22 +#include "mozilla/MemoryReporting.h"
    1.23 +#include "mozilla/dom/EventTarget.h" // for base class
    1.24 +#include "js/TypeDecls.h"     // for Handle, Value, JSObject, JSContext
    1.25 +#include "mozilla/dom/DOMString.h"
    1.26 +#include "mozilla/dom/BindingDeclarations.h"
    1.27 +
    1.28 +// Including 'windows.h' will #define GetClassInfo to something else.
    1.29 +#ifdef XP_WIN
    1.30 +#ifdef GetClassInfo
    1.31 +#undef GetClassInfo
    1.32 +#endif
    1.33 +#endif
    1.34 +
    1.35 +class nsAttrAndChildArray;
    1.36 +class nsChildContentList;
    1.37 +class nsCSSSelectorList;
    1.38 +class nsDOMAttributeMap;
    1.39 +class nsIContent;
    1.40 +class nsIDocument;
    1.41 +class nsIDOMElement;
    1.42 +class nsIDOMNodeList;
    1.43 +class nsIDOMUserDataHandler;
    1.44 +class nsIEditor;
    1.45 +class nsIFrame;
    1.46 +class nsIMutationObserver;
    1.47 +class nsINodeList;
    1.48 +class nsIPresShell;
    1.49 +class nsIPrincipal;
    1.50 +class nsIURI;
    1.51 +class nsNodeSupportsWeakRefTearoff;
    1.52 +class nsNodeWeakReference;
    1.53 +class nsXPCClassInfo;
    1.54 +class nsDOMMutationObserver;
    1.55 +
    1.56 +namespace mozilla {
    1.57 +class EventListenerManager;
    1.58 +namespace dom {
    1.59 +/**
    1.60 + * @return true if aChar is what the DOM spec defines as 'space character'.
    1.61 + * http://dom.spec.whatwg.org/#space-character
    1.62 + */
    1.63 +inline bool IsSpaceCharacter(char16_t aChar) {
    1.64 +  return aChar == ' ' || aChar == '\t' || aChar == '\n' || aChar == '\r' ||
    1.65 +         aChar == '\f';
    1.66 +}
    1.67 +inline bool IsSpaceCharacter(char aChar) {
    1.68 +  return aChar == ' ' || aChar == '\t' || aChar == '\n' || aChar == '\r' ||
    1.69 +         aChar == '\f';
    1.70 +}
    1.71 +struct BoxQuadOptions;
    1.72 +struct ConvertCoordinateOptions;
    1.73 +class DOMPoint;
    1.74 +class DOMQuad;
    1.75 +class DOMRectReadOnly;
    1.76 +class Element;
    1.77 +class EventHandlerNonNull;
    1.78 +class OnErrorEventHandlerNonNull;
    1.79 +template<typename T> class Optional;
    1.80 +class TextOrElementOrDocument;
    1.81 +struct DOMPointInit;
    1.82 +} // namespace dom
    1.83 +} // namespace mozilla
    1.84 +
    1.85 +#define NODE_FLAG_BIT(n_) (1U << (WRAPPER_CACHE_FLAGS_BITS_USED + (n_)))
    1.86 +
    1.87 +enum {
    1.88 +  // This bit will be set if the node has a listener manager.
    1.89 +  NODE_HAS_LISTENERMANAGER =              NODE_FLAG_BIT(0),
    1.90 +
    1.91 +  // Whether this node has had any properties set on it
    1.92 +  NODE_HAS_PROPERTIES =                   NODE_FLAG_BIT(1),
    1.93 +
    1.94 +  // Whether this node is the root of an anonymous subtree.  Note that this
    1.95 +  // need not be a native anonymous subtree.  Any anonymous subtree, including
    1.96 +  // XBL-generated ones, will do.  This flag is set-once: once a node has it,
    1.97 +  // it must not be removed.
    1.98 +  // NOTE: Should only be used on nsIContent nodes
    1.99 +  NODE_IS_ANONYMOUS_ROOT =                NODE_FLAG_BIT(2),
   1.100 +
   1.101 +  // Whether the node has some ancestor, possibly itself, that is native
   1.102 +  // anonymous.  This includes ancestors crossing XBL scopes, in cases when an
   1.103 +  // XBL binding is attached to an element which has a native anonymous
   1.104 +  // ancestor.  This flag is set-once: once a node has it, it must not be
   1.105 +  // removed.
   1.106 +  // NOTE: Should only be used on nsIContent nodes
   1.107 +  NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE =          NODE_FLAG_BIT(3),
   1.108 +
   1.109 +  // Whether this node is the root of a native anonymous (from the perspective
   1.110 +  // of its parent) subtree.  This flag is set-once: once a node has it, it
   1.111 +  // must not be removed.
   1.112 +  // NOTE: Should only be used on nsIContent nodes
   1.113 +  NODE_IS_NATIVE_ANONYMOUS_ROOT =         NODE_FLAG_BIT(4),
   1.114 +
   1.115 +  // Forces the XBL code to treat this node as if it were
   1.116 +  // in the document and therefore should get bindings attached.
   1.117 +  NODE_FORCE_XBL_BINDINGS =               NODE_FLAG_BIT(5),
   1.118 +
   1.119 +  // Whether a binding manager may have a pointer to this
   1.120 +  NODE_MAY_BE_IN_BINDING_MNGR =           NODE_FLAG_BIT(6),
   1.121 +
   1.122 +  NODE_IS_EDITABLE =                      NODE_FLAG_BIT(7),
   1.123 +
   1.124 +  // For all Element nodes, NODE_MAY_HAVE_CLASS is guaranteed to be set if the
   1.125 +  // node in fact has a class, but may be set even if it doesn't.
   1.126 +  NODE_MAY_HAVE_CLASS =                   NODE_FLAG_BIT(8),
   1.127 +
   1.128 +  // Whether the node participates in a shadow tree.
   1.129 +  NODE_IS_IN_SHADOW_TREE =                NODE_FLAG_BIT(9),
   1.130 +
   1.131 +  // Node has an :empty or :-moz-only-whitespace selector
   1.132 +  NODE_HAS_EMPTY_SELECTOR =               NODE_FLAG_BIT(10),
   1.133 +
   1.134 +  // A child of the node has a selector such that any insertion,
   1.135 +  // removal, or appending of children requires restyling the parent.
   1.136 +  NODE_HAS_SLOW_SELECTOR =                NODE_FLAG_BIT(11),
   1.137 +
   1.138 +  // A child of the node has a :first-child, :-moz-first-node,
   1.139 +  // :only-child, :last-child or :-moz-last-node selector.
   1.140 +  NODE_HAS_EDGE_CHILD_SELECTOR =          NODE_FLAG_BIT(12),
   1.141 +
   1.142 +  // A child of the node has a selector such that any insertion or
   1.143 +  // removal of children requires restyling later siblings of that
   1.144 +  // element.  Additionally (in this manner it is stronger than
   1.145 +  // NODE_HAS_SLOW_SELECTOR), if a child's style changes due to any
   1.146 +  // other content tree changes (e.g., the child changes to or from
   1.147 +  // matching :empty due to a grandchild insertion or removal), the
   1.148 +  // child's later siblings must also be restyled.
   1.149 +  NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS = NODE_FLAG_BIT(13),
   1.150 +
   1.151 +  NODE_ALL_SELECTOR_FLAGS =               NODE_HAS_EMPTY_SELECTOR |
   1.152 +                                          NODE_HAS_SLOW_SELECTOR |
   1.153 +                                          NODE_HAS_EDGE_CHILD_SELECTOR |
   1.154 +                                          NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS,
   1.155 +
   1.156 +  NODE_ATTACH_BINDING_ON_POSTCREATE =     NODE_FLAG_BIT(14),
   1.157 +
   1.158 +  // This node needs to go through frame construction to get a frame (or
   1.159 +  // undisplayed entry).
   1.160 +  NODE_NEEDS_FRAME =                      NODE_FLAG_BIT(15),
   1.161 +
   1.162 +  // At least one descendant in the flattened tree has NODE_NEEDS_FRAME set.
   1.163 +  // This should be set on every node on the flattened tree path between the
   1.164 +  // node(s) with NODE_NEEDS_FRAME and the root content.
   1.165 +  NODE_DESCENDANTS_NEED_FRAMES =          NODE_FLAG_BIT(16),
   1.166 +
   1.167 +  // Set if the node has the accesskey attribute set.
   1.168 +  NODE_HAS_ACCESSKEY =                    NODE_FLAG_BIT(17),
   1.169 +
   1.170 +  // Set if the node has right-to-left directionality
   1.171 +  NODE_HAS_DIRECTION_RTL =                NODE_FLAG_BIT(18),
   1.172 +
   1.173 +  // Set if the node has left-to-right directionality
   1.174 +  NODE_HAS_DIRECTION_LTR =                NODE_FLAG_BIT(19),
   1.175 +
   1.176 +  NODE_ALL_DIRECTION_FLAGS =              NODE_HAS_DIRECTION_LTR |
   1.177 +                                          NODE_HAS_DIRECTION_RTL,
   1.178 +
   1.179 +  NODE_CHROME_ONLY_ACCESS =               NODE_FLAG_BIT(20),
   1.180 +
   1.181 +  NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS =    NODE_FLAG_BIT(21),
   1.182 +
   1.183 +  // Remaining bits are node type specific.
   1.184 +  NODE_TYPE_SPECIFIC_BITS_OFFSET =        22
   1.185 +};
   1.186 +
   1.187 +// Make sure we have space for our bits
   1.188 +#define ASSERT_NODE_FLAGS_SPACE(n) \
   1.189 +  static_assert(WRAPPER_CACHE_FLAGS_BITS_USED + (n) <= 32, \
   1.190 +                "Not enough space for our bits")
   1.191 +ASSERT_NODE_FLAGS_SPACE(NODE_TYPE_SPECIFIC_BITS_OFFSET);
   1.192 +
   1.193 +/**
   1.194 + * Class used to detect unexpected mutations. To use the class create an
   1.195 + * nsMutationGuard on the stack before unexpected mutations could occur.
   1.196 + * You can then at any time call Mutated to check if any unexpected mutations
   1.197 + * have occurred.
   1.198 + *
   1.199 + * When a guard is instantiated sMutationCount is set to 300. It is then
   1.200 + * decremented by every mutation (capped at 0). This means that we can only
   1.201 + * detect 300 mutations during the lifetime of a single guard, however that
   1.202 + * should be more then we ever care about as we usually only care if more then
   1.203 + * one mutation has occurred.
   1.204 + *
   1.205 + * When the guard goes out of scope it will adjust sMutationCount so that over
   1.206 + * the lifetime of the guard the guard itself has not affected sMutationCount,
   1.207 + * while mutations that happened while the guard was alive still will. This
   1.208 + * allows a guard to be instantiated even if there is another guard higher up
   1.209 + * on the callstack watching for mutations.
   1.210 + *
   1.211 + * The only thing that has to be avoided is for an outer guard to be used
   1.212 + * while an inner guard is alive. This can be avoided by only ever
   1.213 + * instantiating a single guard per scope and only using the guard in the
   1.214 + * current scope.
   1.215 + */
   1.216 +class nsMutationGuard {
   1.217 +public:
   1.218 +  nsMutationGuard()
   1.219 +  {
   1.220 +    mDelta = eMaxMutations - sMutationCount;
   1.221 +    sMutationCount = eMaxMutations;
   1.222 +  }
   1.223 +  ~nsMutationGuard()
   1.224 +  {
   1.225 +    sMutationCount =
   1.226 +      mDelta > sMutationCount ? 0 : sMutationCount - mDelta;
   1.227 +  }
   1.228 +
   1.229 +  /**
   1.230 +   * Returns true if any unexpected mutations have occurred. You can pass in
   1.231 +   * an 8-bit ignore count to ignore a number of expected mutations.
   1.232 +   */
   1.233 +  bool Mutated(uint8_t aIgnoreCount)
   1.234 +  {
   1.235 +    return sMutationCount < static_cast<uint32_t>(eMaxMutations - aIgnoreCount);
   1.236 +  }
   1.237 +
   1.238 +  // This function should be called whenever a mutation that we want to keep
   1.239 +  // track of happen. For now this is only done when children are added or
   1.240 +  // removed, but we might do it for attribute changes too in the future.
   1.241 +  static void DidMutate()
   1.242 +  {
   1.243 +    if (sMutationCount) {
   1.244 +      --sMutationCount;
   1.245 +    }
   1.246 +  }
   1.247 +
   1.248 +private:
   1.249 +  // mDelta is the amount sMutationCount was adjusted when the guard was
   1.250 +  // initialized. It is needed so that we can undo that adjustment once
   1.251 +  // the guard dies.
   1.252 +  uint32_t mDelta;
   1.253 +
   1.254 +  // The value 300 is not important, as long as it is bigger then anything
   1.255 +  // ever passed to Mutated().
   1.256 +  enum { eMaxMutations = 300 };
   1.257 +
   1.258 +
   1.259 +  // sMutationCount is a global mutation counter which is decreased by one at
   1.260 +  // every mutation. It is capped at 0 to avoid wrapping.
   1.261 +  // Its value is always between 0 and 300, inclusive.
   1.262 +  static uint32_t sMutationCount;
   1.263 +};
   1.264 +
   1.265 +// This should be used for any nsINode sub-class that has fields of its own
   1.266 +// that it needs to measure;  any sub-class that doesn't use it will inherit
   1.267 +// SizeOfExcludingThis from its super-class.  SizeOfIncludingThis() need not be
   1.268 +// defined, it is inherited from nsINode.
   1.269 +// This macro isn't actually specific to nodes, and bug 956400 will move it into MFBT.
   1.270 +#define NS_DECL_SIZEOF_EXCLUDING_THIS \
   1.271 +  virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   1.272 +
   1.273 +// Categories of node properties
   1.274 +// 0 is global.
   1.275 +#define DOM_USER_DATA         1
   1.276 +#define DOM_USER_DATA_HANDLER 2
   1.277 +#define SMIL_MAPPED_ATTR_ANIMVAL 3
   1.278 +
   1.279 +// IID for the nsINode interface
   1.280 +#define NS_INODE_IID \
   1.281 +{ 0x77a62cd0, 0xb34f, 0x42cb, \
   1.282 +  { 0x94, 0x52, 0xae, 0xb2, 0x4d, 0x93, 0x2c, 0xb4 } }
   1.283 +
   1.284 +/**
   1.285 + * An internal interface that abstracts some DOMNode-related parts that both
   1.286 + * nsIContent and nsIDocument share.  An instance of this interface has a list
   1.287 + * of nsIContent children and provides access to them.
   1.288 + */
   1.289 +class nsINode : public mozilla::dom::EventTarget
   1.290 +{
   1.291 +public:
   1.292 +  typedef mozilla::dom::BoxQuadOptions BoxQuadOptions;
   1.293 +  typedef mozilla::dom::ConvertCoordinateOptions ConvertCoordinateOptions;
   1.294 +  typedef mozilla::dom::DOMPoint DOMPoint;
   1.295 +  typedef mozilla::dom::DOMPointInit DOMPointInit;
   1.296 +  typedef mozilla::dom::DOMQuad DOMQuad;
   1.297 +  typedef mozilla::dom::DOMRectReadOnly DOMRectReadOnly;
   1.298 +  typedef mozilla::dom::TextOrElementOrDocument TextOrElementOrDocument;
   1.299 +  typedef mozilla::ErrorResult ErrorResult;
   1.300 +
   1.301 +  NS_DECLARE_STATIC_IID_ACCESSOR(NS_INODE_IID)
   1.302 +
   1.303 +  // Among the sub-classes that inherit (directly or indirectly) from nsINode,
   1.304 +  // measurement of the following members may be added later if DMD finds it is
   1.305 +  // worthwhile:
   1.306 +  // - nsGenericHTMLElement:  mForm, mFieldSet
   1.307 +  // - nsGenericHTMLFrameElement: mFrameLoader (bug 672539)
   1.308 +  // - HTMLBodyElement:       mContentStyleRule
   1.309 +  // - HTMLDataListElement:   mOptions
   1.310 +  // - HTMLFieldSetElement:   mElements, mDependentElements, mFirstLegend
   1.311 +  // - HTMLFormElement:       many!
   1.312 +  // - HTMLFrameSetElement:   mRowSpecs, mColSpecs
   1.313 +  // - HTMLInputElement:      mInputData, mFiles, mFileList, mStaticDocfileList
   1.314 +  // - nsHTMLMapElement:      mAreas
   1.315 +  // - HTMLMediaElement:      many!
   1.316 +  // - nsHTMLOutputElement:   mDefaultValue, mTokenList
   1.317 +  // - nsHTMLRowElement:      mCells
   1.318 +  // - nsHTMLSelectElement:   mOptions, mRestoreState
   1.319 +  // - nsHTMLTableElement:    mTBodies, mRows, mTableInheritedAttributes
   1.320 +  // - nsHTMLTableSectionElement: mRows
   1.321 +  // - nsHTMLTextAreaElement: mControllers, mState
   1.322 +  //
   1.323 +  // The following members don't need to be measured:
   1.324 +  // - nsIContent: mPrimaryFrame, because it's non-owning and measured elsewhere
   1.325 +  //
   1.326 +  NS_DECL_SIZEOF_EXCLUDING_THIS
   1.327 +
   1.328 +  // SizeOfIncludingThis doesn't need to be overridden by sub-classes because
   1.329 +  // sub-classes of nsINode are guaranteed to be laid out in memory in such a
   1.330 +  // way that |this| points to the start of the allocated object, even in
   1.331 +  // methods of nsINode's sub-classes, and so |aMallocSizeOf(this)| is always
   1.332 +  // safe to call no matter which object it was invoked on.
   1.333 +  virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
   1.334 +    return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
   1.335 +  }
   1.336 +
   1.337 +  friend class nsNodeUtils;
   1.338 +  friend class nsNodeWeakReference;
   1.339 +  friend class nsNodeSupportsWeakRefTearoff;
   1.340 +  friend class nsAttrAndChildArray;
   1.341 +
   1.342 +#ifdef MOZILLA_INTERNAL_API
   1.343 +  nsINode(already_AddRefed<nsINodeInfo>& aNodeInfo)
   1.344 +  : mNodeInfo(aNodeInfo),
   1.345 +    mParent(nullptr),
   1.346 +    mBoolFlags(0),
   1.347 +    mNextSibling(nullptr),
   1.348 +    mPreviousSibling(nullptr),
   1.349 +    mFirstChild(nullptr),
   1.350 +    mSubtreeRoot(MOZ_THIS_IN_INITIALIZER_LIST()),
   1.351 +    mSlots(nullptr)
   1.352 +  {
   1.353 +    SetIsDOMBinding();
   1.354 +  }
   1.355 +#endif
   1.356 +
   1.357 +  virtual ~nsINode();
   1.358 +
   1.359 +  /**
   1.360 +   * Bit-flags to pass (or'ed together) to IsNodeOfType()
   1.361 +   */
   1.362 +  enum {
   1.363 +    /** nsIContent nodes */
   1.364 +    eCONTENT             = 1 << 0,
   1.365 +    /** nsIDocument nodes */
   1.366 +    eDOCUMENT            = 1 << 1,
   1.367 +    /** nsIAttribute nodes */
   1.368 +    eATTRIBUTE           = 1 << 2,
   1.369 +    /** text nodes */
   1.370 +    eTEXT                = 1 << 3,
   1.371 +    /** xml processing instructions */
   1.372 +    ePROCESSING_INSTRUCTION = 1 << 4,
   1.373 +    /** comment nodes */
   1.374 +    eCOMMENT             = 1 << 5,
   1.375 +    /** form control elements */
   1.376 +    eHTML_FORM_CONTROL   = 1 << 6,
   1.377 +    /** document fragments */
   1.378 +    eDOCUMENT_FRAGMENT   = 1 << 7,
   1.379 +    /** data nodes (comments, PIs, text). Nodes of this type always
   1.380 +     returns a non-null value for nsIContent::GetText() */
   1.381 +    eDATA_NODE           = 1 << 8,
   1.382 +    /** HTMLMediaElement */
   1.383 +    eMEDIA               = 1 << 9,
   1.384 +    /** animation elements */
   1.385 +    eANIMATION           = 1 << 10,
   1.386 +    /** filter elements that implement SVGFilterPrimitiveStandardAttributes */
   1.387 +    eFILTER              = 1 << 11
   1.388 +  };
   1.389 +
   1.390 +  /**
   1.391 +   * API for doing a quick check if a content is of a given
   1.392 +   * type, such as Text, Document, Comment ...  Use this when you can instead of
   1.393 +   * checking the tag.
   1.394 +   *
   1.395 +   * @param aFlags what types you want to test for (see above)
   1.396 +   * @return whether the content matches ALL flags passed in
   1.397 +   */
   1.398 +  virtual bool IsNodeOfType(uint32_t aFlags) const = 0;
   1.399 +
   1.400 +  virtual JSObject* WrapObject(JSContext *aCx) MOZ_OVERRIDE;
   1.401 +
   1.402 +protected:
   1.403 +  /**
   1.404 +   * WrapNode is called from WrapObject to actually wrap this node, WrapObject
   1.405 +   * does some additional checks and fix-up that's common to all nodes. WrapNode
   1.406 +   * should just call the DOM binding's Wrap function.
   1.407 +   */
   1.408 +  virtual JSObject* WrapNode(JSContext *aCx)
   1.409 +  {
   1.410 +    MOZ_ASSERT(!IsDOMBinding(), "Someone forgot to override WrapNode");
   1.411 +    return nullptr;
   1.412 +  }
   1.413 +
   1.414 +  // Subclasses that wish to override the parent behavior should return the
   1.415 +  // result of GetParentObjectIntenral, which handles the XBL scope stuff.
   1.416 +  //
   1.417 +  mozilla::dom::ParentObject GetParentObjectInternal(nsINode* aNativeParent) const {
   1.418 +    mozilla::dom::ParentObject p(aNativeParent);
   1.419 +    // Note that mUseXBLScope is a no-op for chrome, and other places where we
   1.420 +    // don't use XBL scopes.
   1.421 +    p.mUseXBLScope = IsInAnonymousSubtree() && !IsAnonymousContentInSVGUseSubtree();
   1.422 +    return p;
   1.423 +  }
   1.424 +
   1.425 +public:
   1.426 +  mozilla::dom::ParentObject GetParentObject() const; // Implemented in nsIDocument.h
   1.427 +
   1.428 +  /**
   1.429 +   * Return whether the node is an Element node
   1.430 +   */
   1.431 +  bool IsElement() const {
   1.432 +    return GetBoolFlag(NodeIsElement);
   1.433 +  }
   1.434 +
   1.435 +  /**
   1.436 +   * Return this node as an Element.  Should only be used for nodes
   1.437 +   * for which IsElement() is true.  This is defined inline in Element.h.
   1.438 +   */
   1.439 +  mozilla::dom::Element* AsElement();
   1.440 +  const mozilla::dom::Element* AsElement() const;
   1.441 +
   1.442 +  /**
   1.443 +   * Return this node as nsIContent.  Should only be used for nodes for which
   1.444 +   * IsContent() is true.  This is defined inline in nsIContent.h.
   1.445 +   */
   1.446 +  nsIContent* AsContent();
   1.447 +  const nsIContent* AsContent() const
   1.448 +  {
   1.449 +    return const_cast<nsINode*>(this)->AsContent();
   1.450 +  }
   1.451 +
   1.452 +  virtual nsIDOMNode* AsDOMNode() = 0;
   1.453 +
   1.454 +  /**
   1.455 +   * Return if this node has any children.
   1.456 +   */
   1.457 +  bool HasChildren() const { return !!mFirstChild; }
   1.458 +
   1.459 +  /**
   1.460 +   * Get the number of children
   1.461 +   * @return the number of children
   1.462 +   */
   1.463 +  virtual uint32_t GetChildCount() const = 0;
   1.464 +
   1.465 +  /**
   1.466 +   * Get a child by index
   1.467 +   * @param aIndex the index of the child to get
   1.468 +   * @return the child, or null if index out of bounds
   1.469 +   */
   1.470 +  virtual nsIContent* GetChildAt(uint32_t aIndex) const = 0;
   1.471 +
   1.472 +  /**
   1.473 +   * Get a raw pointer to the child array.  This should only be used if you
   1.474 +   * plan to walk a bunch of the kids, promise to make sure that nothing ever
   1.475 +   * mutates (no attribute changes, not DOM tree changes, no script execution,
   1.476 +   * NOTHING), and will never ever peform an out-of-bounds access here.  This
   1.477 +   * method may return null if there are no children, or it may return a
   1.478 +   * garbage pointer.  In all cases the out param will be set to the number of
   1.479 +   * children.
   1.480 +   */
   1.481 +  virtual nsIContent * const * GetChildArray(uint32_t* aChildCount) const = 0;
   1.482 +
   1.483 +  /**
   1.484 +   * Get the index of a child within this content
   1.485 +   * @param aPossibleChild the child to get the index of.
   1.486 +   * @return the index of the child, or -1 if not a child
   1.487 +   *
   1.488 +   * If the return value is not -1, then calling GetChildAt() with that value
   1.489 +   * will return aPossibleChild.
   1.490 +   */
   1.491 +  virtual int32_t IndexOf(const nsINode* aPossibleChild) const = 0;
   1.492 +
   1.493 +  /**
   1.494 +   * Return the "owner document" of this node.  Note that this is not the same
   1.495 +   * as the DOM ownerDocument -- that's null for Document nodes, whereas for a
   1.496 +   * nsIDocument GetOwnerDocument returns the document itself.  For nsIContent
   1.497 +   * implementations the two are the same.
   1.498 +   */
   1.499 +  nsIDocument *OwnerDoc() const
   1.500 +  {
   1.501 +    return mNodeInfo->GetDocument();
   1.502 +  }
   1.503 +
   1.504 +  /**
   1.505 +   * Return the "owner document" of this node as an nsINode*.  Implemented
   1.506 +   * in nsIDocument.h.
   1.507 +   */
   1.508 +  nsINode *OwnerDocAsNode() const;
   1.509 +
   1.510 +  /**
   1.511 +   * Returns true if the content has an ancestor that is a document.
   1.512 +   *
   1.513 +   * @return whether this content is in a document tree
   1.514 +   */
   1.515 +  bool IsInDoc() const
   1.516 +  {
   1.517 +    return GetBoolFlag(IsInDocument);
   1.518 +  }
   1.519 +
   1.520 +  /**
   1.521 +   * Get the document that this content is currently in, if any. This will be
   1.522 +   * null if the content has no ancestor that is a document.
   1.523 +   *
   1.524 +   * @return the current document
   1.525 +   */
   1.526 +  nsIDocument *GetCurrentDoc() const
   1.527 +  {
   1.528 +    return IsInDoc() ? OwnerDoc() : nullptr;
   1.529 +  }
   1.530 +
   1.531 +  /**
   1.532 +   * The values returned by this function are the ones defined for
   1.533 +   * nsIDOMNode.nodeType
   1.534 +   */
   1.535 +  uint16_t NodeType() const
   1.536 +  {
   1.537 +    return mNodeInfo->NodeType();
   1.538 +  }
   1.539 +  const nsString& NodeName() const
   1.540 +  {
   1.541 +    return mNodeInfo->NodeName();
   1.542 +  }
   1.543 +  const nsString& LocalName() const
   1.544 +  {
   1.545 +    return mNodeInfo->LocalName();
   1.546 +  }
   1.547 +
   1.548 +  /**
   1.549 +   * Get the tag for this element. This will always return a non-null atom
   1.550 +   * pointer (as implied by the naming of the method).  For elements this is
   1.551 +   * the non-namespaced tag, and for other nodes it's something like "#text",
   1.552 +   * "#comment", "#document", etc.
   1.553 +   */
   1.554 +  nsIAtom* Tag() const
   1.555 +  {
   1.556 +    return mNodeInfo->NameAtom();
   1.557 +  }
   1.558 +
   1.559 +  /**
   1.560 +   * Insert a content node at a particular index.  This method handles calling
   1.561 +   * BindToTree on the child appropriately.
   1.562 +   *
   1.563 +   * @param aKid the content to insert
   1.564 +   * @param aIndex the index it is being inserted at (the index it will have
   1.565 +   *        after it is inserted)
   1.566 +   * @param aNotify whether to notify the document (current document for
   1.567 +   *        nsIContent, and |this| for nsIDocument) that the insert has
   1.568 +   *        occurred
   1.569 +   *
   1.570 +   * @throws NS_ERROR_DOM_HIERARCHY_REQUEST_ERR if one attempts to have more
   1.571 +   * than one element node as a child of a document.  Doing this will also
   1.572 +   * assert -- you shouldn't be doing it!  Check with
   1.573 +   * nsIDocument::GetRootElement() first if you're not sure.  Apart from this
   1.574 +   * one constraint, this doesn't do any checking on whether aKid is a valid
   1.575 +   * child of |this|.
   1.576 +   *
   1.577 +   * @throws NS_ERROR_OUT_OF_MEMORY in some cases (from BindToTree).
   1.578 +   */
   1.579 +  virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
   1.580 +                                 bool aNotify) = 0;
   1.581 +
   1.582 +  /**
   1.583 +   * Append a content node to the end of the child list.  This method handles
   1.584 +   * calling BindToTree on the child appropriately.
   1.585 +   *
   1.586 +   * @param aKid the content to append
   1.587 +   * @param aNotify whether to notify the document (current document for
   1.588 +   *        nsIContent, and |this| for nsIDocument) that the append has
   1.589 +   *        occurred
   1.590 +   *
   1.591 +   * @throws NS_ERROR_DOM_HIERARCHY_REQUEST_ERR if one attempts to have more
   1.592 +   * than one element node as a child of a document.  Doing this will also
   1.593 +   * assert -- you shouldn't be doing it!  Check with
   1.594 +   * nsIDocument::GetRootElement() first if you're not sure.  Apart from this
   1.595 +   * one constraint, this doesn't do any checking on whether aKid is a valid
   1.596 +   * child of |this|.
   1.597 +   *
   1.598 +   * @throws NS_ERROR_OUT_OF_MEMORY in some cases (from BindToTree).
   1.599 +   */
   1.600 +  nsresult AppendChildTo(nsIContent* aKid, bool aNotify)
   1.601 +  {
   1.602 +    return InsertChildAt(aKid, GetChildCount(), aNotify);
   1.603 +  }
   1.604 +  
   1.605 +  /**
   1.606 +   * Remove a child from this node.  This method handles calling UnbindFromTree
   1.607 +   * on the child appropriately.
   1.608 +   *
   1.609 +   * @param aIndex the index of the child to remove
   1.610 +   * @param aNotify whether to notify the document (current document for
   1.611 +   *        nsIContent, and |this| for nsIDocument) that the remove has
   1.612 +   *        occurred
   1.613 +   *
   1.614 +   * Note: If there is no child at aIndex, this method will simply do nothing.
   1.615 +   */
   1.616 +  virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) = 0;
   1.617 +
   1.618 +  /**
   1.619 +   * Get a property associated with this node.
   1.620 +   *
   1.621 +   * @param aPropertyName  name of property to get.
   1.622 +   * @param aStatus        out parameter for storing resulting status.
   1.623 +   *                       Set to NS_PROPTABLE_PROP_NOT_THERE if the property
   1.624 +   *                       is not set.
   1.625 +   * @return               the property. Null if the property is not set
   1.626 +   *                       (though a null return value does not imply the
   1.627 +   *                       property was not set, i.e. it can be set to null).
   1.628 +   */
   1.629 +  void* GetProperty(nsIAtom *aPropertyName,
   1.630 +                    nsresult *aStatus = nullptr) const
   1.631 +  {
   1.632 +    return GetProperty(0, aPropertyName, aStatus);
   1.633 +  }
   1.634 +
   1.635 +  /**
   1.636 +   * Get a property associated with this node.
   1.637 +   *
   1.638 +   * @param aCategory      category of property to get.
   1.639 +   * @param aPropertyName  name of property to get.
   1.640 +   * @param aStatus        out parameter for storing resulting status.
   1.641 +   *                       Set to NS_PROPTABLE_PROP_NOT_THERE if the property
   1.642 +   *                       is not set.
   1.643 +   * @return               the property. Null if the property is not set
   1.644 +   *                       (though a null return value does not imply the
   1.645 +   *                       property was not set, i.e. it can be set to null).
   1.646 +   */
   1.647 +  virtual void* GetProperty(uint16_t aCategory,
   1.648 +                            nsIAtom *aPropertyName,
   1.649 +                            nsresult *aStatus = nullptr) const;
   1.650 +
   1.651 +  /**
   1.652 +   * Set a property to be associated with this node. This will overwrite an
   1.653 +   * existing value if one exists. The existing value is destroyed using the
   1.654 +   * destructor function given when that value was set.
   1.655 +   *
   1.656 +   * @param aPropertyName  name of property to set.
   1.657 +   * @param aValue         new value of property.
   1.658 +   * @param aDtor          destructor function to be used when this property
   1.659 +   *                       is destroyed.
   1.660 +   * @param aTransfer      if true the property will not be deleted when the
   1.661 +   *                       ownerDocument of the node changes, if false it
   1.662 +   *                       will be deleted.
   1.663 +   *
   1.664 +   * @return NS_PROPTABLE_PROP_OVERWRITTEN (success value) if the property
   1.665 +   *                                       was already set
   1.666 +   * @throws NS_ERROR_OUT_OF_MEMORY if that occurs
   1.667 +   */
   1.668 +  nsresult SetProperty(nsIAtom *aPropertyName,
   1.669 +                       void *aValue,
   1.670 +                       NSPropertyDtorFunc aDtor = nullptr,
   1.671 +                       bool aTransfer = false)
   1.672 +  {
   1.673 +    return SetProperty(0, aPropertyName, aValue, aDtor, aTransfer);
   1.674 +  }
   1.675 +
   1.676 +  /**
   1.677 +   * Set a property to be associated with this node. This will overwrite an
   1.678 +   * existing value if one exists. The existing value is destroyed using the
   1.679 +   * destructor function given when that value was set.
   1.680 +   *
   1.681 +   * @param aCategory       category of property to set.
   1.682 +   * @param aPropertyName   name of property to set.
   1.683 +   * @param aValue          new value of property.
   1.684 +   * @param aDtor           destructor function to be used when this property
   1.685 +   *                        is destroyed.
   1.686 +   * @param aTransfer       if true the property will not be deleted when the
   1.687 +   *                        ownerDocument of the node changes, if false it
   1.688 +   *                        will be deleted.
   1.689 +   * @param aOldValue [out] previous value of property.
   1.690 +   *
   1.691 +   * @return NS_PROPTABLE_PROP_OVERWRITTEN (success value) if the property
   1.692 +   *                                       was already set
   1.693 +   * @throws NS_ERROR_OUT_OF_MEMORY if that occurs
   1.694 +   */
   1.695 +  virtual nsresult SetProperty(uint16_t aCategory,
   1.696 +                               nsIAtom *aPropertyName,
   1.697 +                               void *aValue,
   1.698 +                               NSPropertyDtorFunc aDtor = nullptr,
   1.699 +                               bool aTransfer = false,
   1.700 +                               void **aOldValue = nullptr);
   1.701 +
   1.702 +  /**
   1.703 +   * A generic destructor for property values allocated with new.
   1.704 +   */
   1.705 +  template<class T>
   1.706 +  static void DeleteProperty(void *, nsIAtom *, void *aPropertyValue, void *)
   1.707 +  {
   1.708 +    delete static_cast<T *>(aPropertyValue);
   1.709 +  }
   1.710 +
   1.711 +  /**
   1.712 +   * Destroys a property associated with this node. The value is destroyed
   1.713 +   * using the destruction function given when that value was set.
   1.714 +   *
   1.715 +   * @param aPropertyName  name of property to destroy.
   1.716 +   */
   1.717 +  void DeleteProperty(nsIAtom *aPropertyName)
   1.718 +  {
   1.719 +    DeleteProperty(0, aPropertyName);
   1.720 +  }
   1.721 +
   1.722 +  /**
   1.723 +   * Destroys a property associated with this node. The value is destroyed
   1.724 +   * using the destruction function given when that value was set.
   1.725 +   *
   1.726 +   * @param aCategory      category of property to destroy.
   1.727 +   * @param aPropertyName  name of property to destroy.
   1.728 +   */
   1.729 +  virtual void DeleteProperty(uint16_t aCategory, nsIAtom *aPropertyName);
   1.730 +
   1.731 +  /**
   1.732 +   * Unset a property associated with this node. The value will not be
   1.733 +   * destroyed but rather returned. It is the caller's responsibility to
   1.734 +   * destroy the value after that point.
   1.735 +   *
   1.736 +   * @param aPropertyName  name of property to unset.
   1.737 +   * @param aStatus        out parameter for storing resulting status.
   1.738 +   *                       Set to NS_PROPTABLE_PROP_NOT_THERE if the property
   1.739 +   *                       is not set.
   1.740 +   * @return               the property. Null if the property is not set
   1.741 +   *                       (though a null return value does not imply the
   1.742 +   *                       property was not set, i.e. it can be set to null).
   1.743 +   */
   1.744 +  void* UnsetProperty(nsIAtom  *aPropertyName,
   1.745 +                      nsresult *aStatus = nullptr)
   1.746 +  {
   1.747 +    return UnsetProperty(0, aPropertyName, aStatus);
   1.748 +  }
   1.749 +
   1.750 +  /**
   1.751 +   * Unset a property associated with this node. The value will not be
   1.752 +   * destroyed but rather returned. It is the caller's responsibility to
   1.753 +   * destroy the value after that point.
   1.754 +   *
   1.755 +   * @param aCategory      category of property to unset.
   1.756 +   * @param aPropertyName  name of property to unset.
   1.757 +   * @param aStatus        out parameter for storing resulting status.
   1.758 +   *                       Set to NS_PROPTABLE_PROP_NOT_THERE if the property
   1.759 +   *                       is not set.
   1.760 +   * @return               the property. Null if the property is not set
   1.761 +   *                       (though a null return value does not imply the
   1.762 +   *                       property was not set, i.e. it can be set to null).
   1.763 +   */
   1.764 +  virtual void* UnsetProperty(uint16_t aCategory,
   1.765 +                              nsIAtom *aPropertyName,
   1.766 +                              nsresult *aStatus = nullptr);
   1.767 +  
   1.768 +  bool HasProperties() const
   1.769 +  {
   1.770 +    return HasFlag(NODE_HAS_PROPERTIES);
   1.771 +  }
   1.772 +
   1.773 +  /**
   1.774 +   * Return the principal of this node.  This is guaranteed to never be a null
   1.775 +   * pointer.
   1.776 +   */
   1.777 +  nsIPrincipal* NodePrincipal() const {
   1.778 +    return mNodeInfo->NodeInfoManager()->DocumentPrincipal();
   1.779 +  }
   1.780 +
   1.781 +  /**
   1.782 +   * Get the parent nsIContent for this node.
   1.783 +   * @return the parent, or null if no parent or the parent is not an nsIContent
   1.784 +   */
   1.785 +  nsIContent* GetParent() const {
   1.786 +    return MOZ_LIKELY(GetBoolFlag(ParentIsContent)) ?
   1.787 +      reinterpret_cast<nsIContent*>(mParent) : nullptr;
   1.788 +  }
   1.789 +
   1.790 +  /**
   1.791 +   * Get the parent nsINode for this node. This can be either an nsIContent,
   1.792 +   * an nsIDocument or an nsIAttribute.
   1.793 +   * @return the parent node
   1.794 +   */
   1.795 +  nsINode* GetParentNode() const
   1.796 +  {
   1.797 +    return mParent;
   1.798 +  }
   1.799 +  
   1.800 +  /**
   1.801 +   * Get the parent nsINode for this node if it is an Element.
   1.802 +   * @return the parent node
   1.803 +   */
   1.804 +  mozilla::dom::Element* GetParentElement() const
   1.805 +  {
   1.806 +    return mParent && mParent->IsElement() ? mParent->AsElement() : nullptr;
   1.807 +  }
   1.808 +
   1.809 +  /**
   1.810 +   * Get the root of the subtree this node belongs to.  This never returns
   1.811 +   * null.  It may return 'this' (e.g. for document nodes, and nodes that
   1.812 +   * are the roots of disconnected subtrees).
   1.813 +   */
   1.814 +  nsINode* SubtreeRoot() const
   1.815 +  {
   1.816 +    // There are three cases of interest here.  nsINodes that are really:
   1.817 +    // 1. nsIDocument nodes - Are always in the document.
   1.818 +    // 2. nsIContent nodes - Are either in the document, or mSubtreeRoot
   1.819 +    //    is updated in BindToTree/UnbindFromTree.
   1.820 +    // 3. nsIAttribute nodes - Are never in the document, and mSubtreeRoot
   1.821 +    //    is always 'this' (as set in nsINode's ctor).
   1.822 +    nsINode* node = IsInDoc() ? OwnerDocAsNode() : mSubtreeRoot;
   1.823 +    NS_ASSERTION(node, "Should always have a node here!");
   1.824 +#ifdef DEBUG
   1.825 +    {
   1.826 +      const nsINode* slowNode = this;
   1.827 +      const nsINode* iter = slowNode;
   1.828 +      while ((iter = iter->GetParentNode())) {
   1.829 +        slowNode = iter;
   1.830 +      }
   1.831 +
   1.832 +      NS_ASSERTION(slowNode == node, "These should always be in sync!");
   1.833 +    }
   1.834 +#endif
   1.835 +    return node;
   1.836 +  }
   1.837 +
   1.838 +  /**
   1.839 +   * See nsIDOMEventTarget
   1.840 +   */
   1.841 +  NS_DECL_NSIDOMEVENTTARGET
   1.842 +
   1.843 +  virtual mozilla::EventListenerManager*
   1.844 +    GetExistingListenerManager() const MOZ_OVERRIDE;
   1.845 +  virtual mozilla::EventListenerManager*
   1.846 +    GetOrCreateListenerManager() MOZ_OVERRIDE;
   1.847 +
   1.848 +  using mozilla::dom::EventTarget::RemoveEventListener;
   1.849 +  using nsIDOMEventTarget::AddEventListener;
   1.850 +  virtual void AddEventListener(const nsAString& aType,
   1.851 +                                mozilla::dom::EventListener* aListener,
   1.852 +                                bool aUseCapture,
   1.853 +                                const mozilla::dom::Nullable<bool>& aWantsUntrusted,
   1.854 +                                mozilla::ErrorResult& aRv) MOZ_OVERRIDE;
   1.855 +  using nsIDOMEventTarget::AddSystemEventListener;
   1.856 +  virtual nsIDOMWindow* GetOwnerGlobal() MOZ_OVERRIDE;
   1.857 +
   1.858 +  /**
   1.859 +   * Adds a mutation observer to be notified when this node, or any of its
   1.860 +   * descendants, are modified. The node will hold a weak reference to the
   1.861 +   * observer, which means that it is the responsibility of the observer to
   1.862 +   * remove itself in case it dies before the node.  If an observer is added
   1.863 +   * while observers are being notified, it may also be notified.  In general,
   1.864 +   * adding observers while inside a notification is not a good idea.  An
   1.865 +   * observer that is already observing the node must not be added without
   1.866 +   * being removed first.
   1.867 +   */
   1.868 +  void AddMutationObserver(nsIMutationObserver* aMutationObserver)
   1.869 +  {
   1.870 +    nsSlots* s = Slots();
   1.871 +    NS_ASSERTION(s->mMutationObservers.IndexOf(aMutationObserver) ==
   1.872 +                 nsTArray<int>::NoIndex,
   1.873 +                 "Observer already in the list");
   1.874 +    s->mMutationObservers.AppendElement(aMutationObserver);
   1.875 +  }
   1.876 +
   1.877 +  /**
   1.878 +   * Same as above, but only adds the observer if its not observing
   1.879 +   * the node already.
   1.880 +   */
   1.881 +  void AddMutationObserverUnlessExists(nsIMutationObserver* aMutationObserver)
   1.882 +  {
   1.883 +    nsSlots* s = Slots();
   1.884 +    s->mMutationObservers.AppendElementUnlessExists(aMutationObserver);
   1.885 +  }
   1.886 +
   1.887 +  /**
   1.888 +   * Removes a mutation observer.
   1.889 +   */
   1.890 +  void RemoveMutationObserver(nsIMutationObserver* aMutationObserver)
   1.891 +  {
   1.892 +    nsSlots* s = GetExistingSlots();
   1.893 +    if (s) {
   1.894 +      s->mMutationObservers.RemoveElement(aMutationObserver);
   1.895 +    }
   1.896 +  }
   1.897 +
   1.898 +  /**
   1.899 +   * Clones this node. This needs to be overriden by all node classes. aNodeInfo
   1.900 +   * should be identical to this node's nodeInfo, except for the document which
   1.901 +   * may be different. When cloning an element, all attributes of the element
   1.902 +   * will be cloned. The children of the node will not be cloned.
   1.903 +   *
   1.904 +   * @param aNodeInfo the nodeinfo to use for the clone
   1.905 +   * @param aResult the clone
   1.906 +   */
   1.907 +  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const = 0;
   1.908 +
   1.909 +  // This class can be extended by subclasses that wish to store more
   1.910 +  // information in the slots.
   1.911 +  class nsSlots
   1.912 +  {
   1.913 +  public:
   1.914 +    nsSlots()
   1.915 +      : mChildNodes(nullptr),
   1.916 +        mWeakReference(nullptr)
   1.917 +    {
   1.918 +    }
   1.919 +
   1.920 +    // If needed we could remove the vtable pointer this dtor causes by
   1.921 +    // putting a DestroySlots function on nsINode
   1.922 +    virtual ~nsSlots();
   1.923 +
   1.924 +    void Traverse(nsCycleCollectionTraversalCallback &cb);
   1.925 +    void Unlink();
   1.926 +
   1.927 +    /**
   1.928 +     * A list of mutation observers
   1.929 +     */
   1.930 +    nsTObserverArray<nsIMutationObserver*> mMutationObservers;
   1.931 +
   1.932 +    /**
   1.933 +     * An object implementing nsIDOMNodeList for this content (childNodes)
   1.934 +     * @see nsIDOMNodeList
   1.935 +     * @see nsGenericHTMLElement::GetChildNodes
   1.936 +     *
   1.937 +     * MSVC 7 doesn't like this as an nsRefPtr
   1.938 +     */
   1.939 +    nsChildContentList* mChildNodes;
   1.940 +
   1.941 +    /**
   1.942 +     * Weak reference to this node
   1.943 +     */
   1.944 +    nsNodeWeakReference* mWeakReference;
   1.945 +  };
   1.946 +
   1.947 +  /**
   1.948 +   * Functions for managing flags and slots
   1.949 +   */
   1.950 +#ifdef DEBUG
   1.951 +  nsSlots* DebugGetSlots()
   1.952 +  {
   1.953 +    return Slots();
   1.954 +  }
   1.955 +#endif
   1.956 +
   1.957 +  void SetFlags(uint32_t aFlagsToSet)
   1.958 +  {
   1.959 +    NS_ASSERTION(!(aFlagsToSet & (NODE_IS_ANONYMOUS_ROOT |
   1.960 +                                  NODE_IS_NATIVE_ANONYMOUS_ROOT |
   1.961 +                                  NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
   1.962 +                                  NODE_ATTACH_BINDING_ON_POSTCREATE |
   1.963 +                                  NODE_DESCENDANTS_NEED_FRAMES |
   1.964 +                                  NODE_NEEDS_FRAME |
   1.965 +                                  NODE_CHROME_ONLY_ACCESS)) ||
   1.966 +                 IsNodeOfType(eCONTENT),
   1.967 +                 "Flag only permitted on nsIContent nodes");
   1.968 +    nsWrapperCache::SetFlags(aFlagsToSet);
   1.969 +  }
   1.970 +
   1.971 +  void UnsetFlags(uint32_t aFlagsToUnset)
   1.972 +  {
   1.973 +    NS_ASSERTION(!(aFlagsToUnset &
   1.974 +                   (NODE_IS_ANONYMOUS_ROOT |
   1.975 +                    NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
   1.976 +                    NODE_IS_NATIVE_ANONYMOUS_ROOT)),
   1.977 +                 "Trying to unset write-only flags");
   1.978 +    nsWrapperCache::UnsetFlags(aFlagsToUnset);
   1.979 +  }
   1.980 +
   1.981 +  void SetEditableFlag(bool aEditable)
   1.982 +  {
   1.983 +    if (aEditable) {
   1.984 +      SetFlags(NODE_IS_EDITABLE);
   1.985 +    }
   1.986 +    else {
   1.987 +      UnsetFlags(NODE_IS_EDITABLE);
   1.988 +    }
   1.989 +  }
   1.990 +
   1.991 +  bool IsEditable() const
   1.992 +  {
   1.993 +#ifdef MOZILLA_INTERNAL_API
   1.994 +    return IsEditableInternal();
   1.995 +#else
   1.996 +    return IsEditableExternal();
   1.997 +#endif
   1.998 +  }
   1.999 +
  1.1000 +  /**
  1.1001 +   * Returns true if |this| or any of its ancestors is native anonymous.
  1.1002 +   */
  1.1003 +  bool IsInNativeAnonymousSubtree() const
  1.1004 +  {
  1.1005 +#ifdef DEBUG
  1.1006 +    if (HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE)) {
  1.1007 +      return true;
  1.1008 +    }
  1.1009 +    CheckNotNativeAnonymous();
  1.1010 +    return false;
  1.1011 +#else
  1.1012 +    return HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
  1.1013 +#endif
  1.1014 +  }
  1.1015 +
  1.1016 +  bool IsInAnonymousSubtree() const;
  1.1017 +
  1.1018 +  // Note: This asserts |IsInAnonymousSubtree()|.
  1.1019 +  bool IsAnonymousContentInSVGUseSubtree() const;
  1.1020 +
  1.1021 +  // True for native anonymous content and for XBL content if the binging
  1.1022 +  // has chromeOnlyContent="true".
  1.1023 +  bool ChromeOnlyAccess() const
  1.1024 +  {
  1.1025 +    return HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE | NODE_CHROME_ONLY_ACCESS);
  1.1026 +  }
  1.1027 +
  1.1028 +  /**
  1.1029 +   * Returns true if |this| node is the common ancestor of the start/end
  1.1030 +   * nodes of a Range in a Selection or a descendant of such a common ancestor.
  1.1031 +   * This node is definitely not selected when |false| is returned, but it may
  1.1032 +   * or may not be selected when |true| is returned.
  1.1033 +   */
  1.1034 +  bool IsSelectionDescendant() const
  1.1035 +  {
  1.1036 +    return IsDescendantOfCommonAncestorForRangeInSelection() ||
  1.1037 +           IsCommonAncestorForRangeInSelection();
  1.1038 +  }
  1.1039 +
  1.1040 +  /**
  1.1041 +   * Get the root content of an editor. So, this node must be a descendant of
  1.1042 +   * an editor. Note that this should be only used for getting input or textarea
  1.1043 +   * editor's root content. This method doesn't support HTML editors.
  1.1044 +   */
  1.1045 +  nsIContent* GetTextEditorRootContent(nsIEditor** aEditor = nullptr);
  1.1046 +
  1.1047 +  /**
  1.1048 +   * Get the nearest selection root, ie. the node that will be selected if the
  1.1049 +   * user does "Select All" while the focus is in this node. Note that if this
  1.1050 +   * node is not in an editor, the result comes from the nsFrameSelection that
  1.1051 +   * is related to aPresShell, so the result might not be the ancestor of this
  1.1052 +   * node. Be aware that if this node and the computed selection limiter are
  1.1053 +   * not in same subtree, this returns the root content of the closeset subtree.
  1.1054 +   */
  1.1055 +  nsIContent* GetSelectionRootContent(nsIPresShell* aPresShell);
  1.1056 +
  1.1057 +  virtual nsINodeList* ChildNodes();
  1.1058 +  nsIContent* GetFirstChild() const { return mFirstChild; }
  1.1059 +  nsIContent* GetLastChild() const
  1.1060 +  {
  1.1061 +    uint32_t count;
  1.1062 +    nsIContent* const* children = GetChildArray(&count);
  1.1063 +
  1.1064 +    return count > 0 ? children[count - 1] : nullptr;
  1.1065 +  }
  1.1066 +
  1.1067 +  /**
  1.1068 +   * Implementation is in nsIDocument.h, because it needs to cast from
  1.1069 +   * nsIDocument* to nsINode*.
  1.1070 +   */
  1.1071 +  nsIDocument* GetOwnerDocument() const;
  1.1072 +
  1.1073 +  void Normalize();
  1.1074 +
  1.1075 +  /**
  1.1076 +   * Get the base URI for any relative URIs within this piece of
  1.1077 +   * content. Generally, this is the document's base URI, but certain
  1.1078 +   * content carries a local base for backward compatibility, and XML
  1.1079 +   * supports setting a per-node base URI.
  1.1080 +   *
  1.1081 +   * @return the base URI
  1.1082 +   */
  1.1083 +  virtual already_AddRefed<nsIURI> GetBaseURI(bool aTryUseXHRDocBaseURI = false) const = 0;
  1.1084 +  already_AddRefed<nsIURI> GetBaseURIObject() const;
  1.1085 +
  1.1086 +  /**
  1.1087 +   * Facility for explicitly setting a base URI on a node.
  1.1088 +   */
  1.1089 +  nsresult SetExplicitBaseURI(nsIURI* aURI);
  1.1090 +  /**
  1.1091 +   * The explicit base URI, if set, otherwise null
  1.1092 +   */
  1.1093 +protected:
  1.1094 +  nsIURI* GetExplicitBaseURI() const {
  1.1095 +    if (HasExplicitBaseURI()) {
  1.1096 +      return static_cast<nsIURI*>(GetProperty(nsGkAtoms::baseURIProperty));
  1.1097 +    }
  1.1098 +    return nullptr;
  1.1099 +  }
  1.1100 +  
  1.1101 +public:
  1.1102 +  void GetTextContent(nsAString& aTextContent)
  1.1103 +  {
  1.1104 +    GetTextContentInternal(aTextContent);
  1.1105 +  }
  1.1106 +  void SetTextContent(const nsAString& aTextContent,
  1.1107 +                      mozilla::ErrorResult& aError)
  1.1108 +  {
  1.1109 +    SetTextContentInternal(aTextContent, aError);
  1.1110 +  }
  1.1111 +
  1.1112 +  mozilla::dom::Element* QuerySelector(const nsAString& aSelector,
  1.1113 +                                       mozilla::ErrorResult& aResult);
  1.1114 +  already_AddRefed<nsINodeList> QuerySelectorAll(const nsAString& aSelector,
  1.1115 +                                                 mozilla::ErrorResult& aResult);
  1.1116 +
  1.1117 +  nsresult QuerySelector(const nsAString& aSelector, nsIDOMElement **aReturn);
  1.1118 +  nsresult QuerySelectorAll(const nsAString& aSelector, nsIDOMNodeList **aReturn);
  1.1119 +
  1.1120 +protected:
  1.1121 +  // nsIDocument overrides this with its own (faster) version.  This
  1.1122 +  // should really only be called for elements and document fragments.
  1.1123 +  mozilla::dom::Element* GetElementById(const nsAString& aId);
  1.1124 +
  1.1125 +public:
  1.1126 +  /**
  1.1127 +   * Associate an object aData to aKey on this node. If aData is null any
  1.1128 +   * previously registered object and UserDataHandler associated to aKey on
  1.1129 +   * this node will be removed.
  1.1130 +   * Should only be used to implement the DOM Level 3 UserData API.
  1.1131 +   *
  1.1132 +   * @param aKey the key to associate the object to
  1.1133 +   * @param aData the object to associate to aKey on this node (may be null)
  1.1134 +   * @param aHandler the UserDataHandler to call when the node is
  1.1135 +   *                 cloned/deleted/imported/renamed (may be null)
  1.1136 +   * @param aResult [out] the previously registered object for aKey on this
  1.1137 +   *                      node, if any
  1.1138 +   * @return whether adding the object and UserDataHandler succeeded
  1.1139 +   */
  1.1140 +  nsresult SetUserData(const nsAString& aKey, nsIVariant* aData,
  1.1141 +                       nsIDOMUserDataHandler* aHandler, nsIVariant** aResult);
  1.1142 +
  1.1143 +  /**
  1.1144 +   * Get the UserData object registered for a Key on this node, if any.
  1.1145 +   * Should only be used to implement the DOM Level 3 UserData API.
  1.1146 +   *
  1.1147 +   * @param aKey the key to get UserData for
  1.1148 +   * @return aResult the previously registered object for aKey on this node, if
  1.1149 +   *                 any
  1.1150 +   */
  1.1151 +  nsIVariant* GetUserData(const nsAString& aKey);
  1.1152 +
  1.1153 +  nsresult GetUserData(const nsAString& aKey, nsIVariant** aResult)
  1.1154 +  {
  1.1155 +    NS_IF_ADDREF(*aResult = GetUserData(aKey));
  1.1156 +  
  1.1157 +    return NS_OK;
  1.1158 +  }
  1.1159 +
  1.1160 +  void LookupPrefix(const nsAString& aNamespace, nsAString& aResult);
  1.1161 +  bool IsDefaultNamespace(const nsAString& aNamespaceURI)
  1.1162 +  {
  1.1163 +    nsAutoString defaultNamespace;
  1.1164 +    LookupNamespaceURI(EmptyString(), defaultNamespace);
  1.1165 +    return aNamespaceURI.Equals(defaultNamespace);
  1.1166 +  }
  1.1167 +  void LookupNamespaceURI(const nsAString& aNamespacePrefix,
  1.1168 +                          nsAString& aNamespaceURI);
  1.1169 +
  1.1170 +  nsresult IsEqualNode(nsIDOMNode* aOther, bool* aReturn);
  1.1171 +
  1.1172 +  nsIContent* GetNextSibling() const { return mNextSibling; }
  1.1173 +  nsIContent* GetPreviousSibling() const { return mPreviousSibling; }
  1.1174 +
  1.1175 +  /**
  1.1176 +   * Get the next node in the pre-order tree traversal of the DOM.  If
  1.1177 +   * aRoot is non-null, then it must be an ancestor of |this|
  1.1178 +   * (possibly equal to |this|) and only nodes that are descendants of
  1.1179 +   * aRoot, not including aRoot itself, will be returned.  Returns
  1.1180 +   * null if there are no more nodes to traverse.
  1.1181 +   */
  1.1182 +  nsIContent* GetNextNode(const nsINode* aRoot = nullptr) const
  1.1183 +  {
  1.1184 +    return GetNextNodeImpl(aRoot, false);
  1.1185 +  }
  1.1186 +
  1.1187 +  /**
  1.1188 +   * Get the next node in the pre-order tree traversal of the DOM but ignoring
  1.1189 +   * the children of this node.  If aRoot is non-null, then it must be an
  1.1190 +   * ancestor of |this| (possibly equal to |this|) and only nodes that are
  1.1191 +   * descendants of aRoot, not including aRoot itself, will be returned.
  1.1192 +   * Returns null if there are no more nodes to traverse.
  1.1193 +   */
  1.1194 +  nsIContent* GetNextNonChildNode(const nsINode* aRoot = nullptr) const
  1.1195 +  {
  1.1196 +    return GetNextNodeImpl(aRoot, true);
  1.1197 +  }
  1.1198 +
  1.1199 +  /**
  1.1200 +   * Returns true if 'this' is either document or element or
  1.1201 +   * document fragment and aOther is a descendant in the same
  1.1202 +   * anonymous tree.
  1.1203 +   */
  1.1204 +  bool Contains(const nsINode* aOther) const;
  1.1205 +  nsresult Contains(nsIDOMNode* aOther, bool* aReturn);
  1.1206 +
  1.1207 +  bool UnoptimizableCCNode() const;
  1.1208 +
  1.1209 +private:
  1.1210 +
  1.1211 +  nsIContent* GetNextNodeImpl(const nsINode* aRoot,
  1.1212 +                              const bool aSkipChildren) const
  1.1213 +  {
  1.1214 +    // Can't use nsContentUtils::ContentIsDescendantOf here, since we
  1.1215 +    // can't include it here.
  1.1216 +#ifdef DEBUG
  1.1217 +    if (aRoot) {
  1.1218 +      const nsINode* cur = this;
  1.1219 +      for (; cur; cur = cur->GetParentNode())
  1.1220 +        if (cur == aRoot) break;
  1.1221 +      NS_ASSERTION(cur, "aRoot not an ancestor of |this|?");
  1.1222 +    }
  1.1223 +#endif
  1.1224 +    if (!aSkipChildren) {
  1.1225 +      nsIContent* kid = GetFirstChild();
  1.1226 +      if (kid) {
  1.1227 +        return kid;
  1.1228 +      }
  1.1229 +    }
  1.1230 +    if (this == aRoot) {
  1.1231 +      return nullptr;
  1.1232 +    }
  1.1233 +    const nsINode* cur = this;
  1.1234 +    while (1) {
  1.1235 +      nsIContent* next = cur->GetNextSibling();
  1.1236 +      if (next) {
  1.1237 +        return next;
  1.1238 +      }
  1.1239 +      nsINode* parent = cur->GetParentNode();
  1.1240 +      if (parent == aRoot) {
  1.1241 +        return nullptr;
  1.1242 +      }
  1.1243 +      cur = parent;
  1.1244 +    }
  1.1245 +    NS_NOTREACHED("How did we get here?");
  1.1246 +  }
  1.1247 +
  1.1248 +public:
  1.1249 +
  1.1250 +  /**
  1.1251 +   * Get the previous nsIContent in the pre-order tree traversal of the DOM.  If
  1.1252 +   * aRoot is non-null, then it must be an ancestor of |this|
  1.1253 +   * (possibly equal to |this|) and only nsIContents that are descendants of
  1.1254 +   * aRoot, including aRoot itself, will be returned.  Returns
  1.1255 +   * null if there are no more nsIContents to traverse.
  1.1256 +   */
  1.1257 +  nsIContent* GetPreviousContent(const nsINode* aRoot = nullptr) const
  1.1258 +  {
  1.1259 +      // Can't use nsContentUtils::ContentIsDescendantOf here, since we
  1.1260 +      // can't include it here.
  1.1261 +#ifdef DEBUG
  1.1262 +      if (aRoot) {
  1.1263 +        const nsINode* cur = this;
  1.1264 +        for (; cur; cur = cur->GetParentNode())
  1.1265 +          if (cur == aRoot) break;
  1.1266 +        NS_ASSERTION(cur, "aRoot not an ancestor of |this|?");
  1.1267 +      }
  1.1268 +#endif
  1.1269 +
  1.1270 +    if (this == aRoot) {
  1.1271 +      return nullptr;
  1.1272 +    }
  1.1273 +    nsIContent* cur = this->GetParent();
  1.1274 +    nsIContent* iter = this->GetPreviousSibling();
  1.1275 +    while (iter) {
  1.1276 +      cur = iter;
  1.1277 +      iter = reinterpret_cast<nsINode*>(iter)->GetLastChild();
  1.1278 +    }
  1.1279 +    return cur;
  1.1280 +  }
  1.1281 +
  1.1282 +  /**
  1.1283 +   * Boolean flags
  1.1284 +   */
  1.1285 +private:
  1.1286 +  enum BooleanFlag {
  1.1287 +    // Set if we're being used from -moz-element
  1.1288 +    NodeHasRenderingObservers,
  1.1289 +    // Set if our parent chain (including this node itself) terminates
  1.1290 +    // in a document
  1.1291 +    IsInDocument,
  1.1292 +    // Set if mParent is an nsIContent
  1.1293 +    ParentIsContent,
  1.1294 +    // Set if this node is an Element
  1.1295 +    NodeIsElement,
  1.1296 +    // Set if the element has a non-empty id attribute. This can in rare
  1.1297 +    // cases lie for nsXMLElement, such as when the node has been moved between
  1.1298 +    // documents with different id mappings.
  1.1299 +    ElementHasID,
  1.1300 +    // Set if the element might have inline style.
  1.1301 +    ElementMayHaveStyle,
  1.1302 +    // Set if the element has a name attribute set.
  1.1303 +    ElementHasName,
  1.1304 +    // Set if the element might have a contenteditable attribute set.
  1.1305 +    ElementMayHaveContentEditableAttr,
  1.1306 +    // Set if the node is the common ancestor of the start/end nodes of a Range
  1.1307 +    // that is in a Selection.
  1.1308 +    NodeIsCommonAncestorForRangeInSelection,
  1.1309 +    // Set if the node is a descendant of a node with the above bit set.
  1.1310 +    NodeIsDescendantOfCommonAncestorForRangeInSelection,
  1.1311 +    // Set if CanSkipInCC check has been done for this subtree root.
  1.1312 +    NodeIsCCMarkedRoot,
  1.1313 +    // Maybe set if this node is in black subtree.
  1.1314 +    NodeIsCCBlackTree,
  1.1315 +    // Maybe set if the node is a root of a subtree 
  1.1316 +    // which needs to be kept in the purple buffer.
  1.1317 +    NodeIsPurpleRoot,
  1.1318 +    // Set if the node has an explicit base URI stored
  1.1319 +    NodeHasExplicitBaseURI,
  1.1320 +    // Set if the element has some style states locked
  1.1321 +    ElementHasLockedStyleStates,
  1.1322 +    // Set if element has pointer locked
  1.1323 +    ElementHasPointerLock,
  1.1324 +    // Set if the node may have DOMMutationObserver attached to it.
  1.1325 +    NodeMayHaveDOMMutationObserver,
  1.1326 +    // Set if node is Content
  1.1327 +    NodeIsContent,
  1.1328 +    // Set if the node has animations or transitions
  1.1329 +    ElementHasAnimations,
  1.1330 +    // Set if node has a dir attribute with a valid value (ltr, rtl, or auto)
  1.1331 +    NodeHasValidDirAttribute,
  1.1332 +    // Set if node has a dir attribute with a fixed value (ltr or rtl, NOT auto)
  1.1333 +    NodeHasFixedDir,
  1.1334 +    // Set if the node has dir=auto and has a property pointing to the text
  1.1335 +    // node that determines its direction
  1.1336 +    NodeHasDirAutoSet,
  1.1337 +    // Set if the node is a text node descendant of a node with dir=auto
  1.1338 +    // and has a TextNodeDirectionalityMap property listing the elements whose
  1.1339 +    // direction it determines.
  1.1340 +    NodeHasTextNodeDirectionalityMap,
  1.1341 +    // Set if the node has dir=auto.
  1.1342 +    NodeHasDirAuto,
  1.1343 +    // Set if a node in the node's parent chain has dir=auto.
  1.1344 +    NodeAncestorHasDirAuto,
  1.1345 +    // Set if the element is in the scope of a scoped style sheet; this flag is
  1.1346 +    // only accurate for elements bound to a document
  1.1347 +    ElementIsInStyleScope,
  1.1348 +    // Set if the element is a scoped style sheet root
  1.1349 +    ElementIsScopedStyleRoot,
  1.1350 +    // Set if the node is handling a click.
  1.1351 +    NodeHandlingClick,
  1.1352 +    // Set if the node has had :hover selectors matched against it
  1.1353 +    NodeHasRelevantHoverRules,
  1.1354 +    // Set if the element has a parser insertion mode other than "in body",
  1.1355 +    // per the HTML5 "Parse state" section.
  1.1356 +    ElementHasWeirdParserInsertionMode,
  1.1357 +    // Guard value
  1.1358 +    BooleanFlagCount
  1.1359 +  };
  1.1360 +
  1.1361 +  void SetBoolFlag(BooleanFlag name, bool value) {
  1.1362 +    static_assert(BooleanFlagCount <= 8*sizeof(mBoolFlags),
  1.1363 +                  "Too many boolean flags");
  1.1364 +    mBoolFlags = (mBoolFlags & ~(1 << name)) | (value << name);
  1.1365 +  }
  1.1366 +
  1.1367 +  void SetBoolFlag(BooleanFlag name) {
  1.1368 +    static_assert(BooleanFlagCount <= 8*sizeof(mBoolFlags),
  1.1369 +                  "Too many boolean flags");
  1.1370 +    mBoolFlags |= (1 << name);
  1.1371 +  }
  1.1372 +
  1.1373 +  void ClearBoolFlag(BooleanFlag name) {
  1.1374 +    static_assert(BooleanFlagCount <= 8*sizeof(mBoolFlags),
  1.1375 +                  "Too many boolean flags");
  1.1376 +    mBoolFlags &= ~(1 << name);
  1.1377 +  }
  1.1378 +
  1.1379 +  bool GetBoolFlag(BooleanFlag name) const {
  1.1380 +    static_assert(BooleanFlagCount <= 8*sizeof(mBoolFlags),
  1.1381 +                  "Too many boolean flags");
  1.1382 +    return mBoolFlags & (1 << name);
  1.1383 +  }
  1.1384 +
  1.1385 +public:
  1.1386 +  bool HasRenderingObservers() const
  1.1387 +    { return GetBoolFlag(NodeHasRenderingObservers); }
  1.1388 +  void SetHasRenderingObservers(bool aValue)
  1.1389 +    { SetBoolFlag(NodeHasRenderingObservers, aValue); }
  1.1390 +  bool IsContent() const { return GetBoolFlag(NodeIsContent); }
  1.1391 +  bool HasID() const { return GetBoolFlag(ElementHasID); }
  1.1392 +  bool MayHaveStyle() const { return GetBoolFlag(ElementMayHaveStyle); }
  1.1393 +  bool HasName() const { return GetBoolFlag(ElementHasName); }
  1.1394 +  bool MayHaveContentEditableAttr() const
  1.1395 +    { return GetBoolFlag(ElementMayHaveContentEditableAttr); }
  1.1396 +  bool IsCommonAncestorForRangeInSelection() const
  1.1397 +    { return GetBoolFlag(NodeIsCommonAncestorForRangeInSelection); }
  1.1398 +  void SetCommonAncestorForRangeInSelection()
  1.1399 +    { SetBoolFlag(NodeIsCommonAncestorForRangeInSelection); }
  1.1400 +  void ClearCommonAncestorForRangeInSelection()
  1.1401 +    { ClearBoolFlag(NodeIsCommonAncestorForRangeInSelection); }
  1.1402 +  bool IsDescendantOfCommonAncestorForRangeInSelection() const
  1.1403 +    { return GetBoolFlag(NodeIsDescendantOfCommonAncestorForRangeInSelection); }
  1.1404 +  void SetDescendantOfCommonAncestorForRangeInSelection()
  1.1405 +    { SetBoolFlag(NodeIsDescendantOfCommonAncestorForRangeInSelection); }
  1.1406 +  void ClearDescendantOfCommonAncestorForRangeInSelection()
  1.1407 +    { ClearBoolFlag(NodeIsDescendantOfCommonAncestorForRangeInSelection); }
  1.1408 +
  1.1409 +  void SetCCMarkedRoot(bool aValue)
  1.1410 +    { SetBoolFlag(NodeIsCCMarkedRoot, aValue); }
  1.1411 +  bool CCMarkedRoot() const { return GetBoolFlag(NodeIsCCMarkedRoot); }
  1.1412 +  void SetInCCBlackTree(bool aValue)
  1.1413 +    { SetBoolFlag(NodeIsCCBlackTree, aValue); }
  1.1414 +  bool InCCBlackTree() const { return GetBoolFlag(NodeIsCCBlackTree); }
  1.1415 +  void SetIsPurpleRoot(bool aValue)
  1.1416 +    { SetBoolFlag(NodeIsPurpleRoot, aValue); }
  1.1417 +  bool IsPurpleRoot() const { return GetBoolFlag(NodeIsPurpleRoot); }
  1.1418 +  bool MayHaveDOMMutationObserver()
  1.1419 +    { return GetBoolFlag(NodeMayHaveDOMMutationObserver); }
  1.1420 +  void SetMayHaveDOMMutationObserver()
  1.1421 +    { SetBoolFlag(NodeMayHaveDOMMutationObserver, true); }
  1.1422 +  bool HasListenerManager() { return HasFlag(NODE_HAS_LISTENERMANAGER); }
  1.1423 +  bool HasPointerLock() const { return GetBoolFlag(ElementHasPointerLock); }
  1.1424 +  void SetPointerLock() { SetBoolFlag(ElementHasPointerLock); }
  1.1425 +  void ClearPointerLock() { ClearBoolFlag(ElementHasPointerLock); }
  1.1426 +  bool MayHaveAnimations() { return GetBoolFlag(ElementHasAnimations); }
  1.1427 +  void SetMayHaveAnimations() { SetBoolFlag(ElementHasAnimations); }
  1.1428 +  void SetHasValidDir() { SetBoolFlag(NodeHasValidDirAttribute); }
  1.1429 +  void ClearHasValidDir() { ClearBoolFlag(NodeHasValidDirAttribute); }
  1.1430 +  bool HasValidDir() const { return GetBoolFlag(NodeHasValidDirAttribute); }
  1.1431 +  void SetHasFixedDir() {
  1.1432 +    MOZ_ASSERT(NodeType() != nsIDOMNode::TEXT_NODE,
  1.1433 +               "SetHasFixedDir on text node");
  1.1434 +    SetBoolFlag(NodeHasFixedDir);
  1.1435 +  }
  1.1436 +  void ClearHasFixedDir() {
  1.1437 +    MOZ_ASSERT(NodeType() != nsIDOMNode::TEXT_NODE,
  1.1438 +               "ClearHasFixedDir on text node");
  1.1439 +    ClearBoolFlag(NodeHasFixedDir);
  1.1440 +  }
  1.1441 +  bool HasFixedDir() const { return GetBoolFlag(NodeHasFixedDir); }
  1.1442 +  void SetHasDirAutoSet() {
  1.1443 +    MOZ_ASSERT(NodeType() != nsIDOMNode::TEXT_NODE,
  1.1444 +               "SetHasDirAutoSet on text node");
  1.1445 +    SetBoolFlag(NodeHasDirAutoSet);
  1.1446 +  }
  1.1447 +  void ClearHasDirAutoSet() {
  1.1448 +    MOZ_ASSERT(NodeType() != nsIDOMNode::TEXT_NODE,
  1.1449 +               "ClearHasDirAutoSet on text node");
  1.1450 +    ClearBoolFlag(NodeHasDirAutoSet);
  1.1451 +  }
  1.1452 +  bool HasDirAutoSet() const
  1.1453 +    { return GetBoolFlag(NodeHasDirAutoSet); }
  1.1454 +  void SetHasTextNodeDirectionalityMap() {
  1.1455 +    MOZ_ASSERT(NodeType() == nsIDOMNode::TEXT_NODE,
  1.1456 +               "SetHasTextNodeDirectionalityMap on non-text node");
  1.1457 +    SetBoolFlag(NodeHasTextNodeDirectionalityMap);
  1.1458 +  }
  1.1459 +  void ClearHasTextNodeDirectionalityMap() {
  1.1460 +    MOZ_ASSERT(NodeType() == nsIDOMNode::TEXT_NODE,
  1.1461 +               "ClearHasTextNodeDirectionalityMap on non-text node");
  1.1462 +    ClearBoolFlag(NodeHasTextNodeDirectionalityMap);
  1.1463 +  }
  1.1464 +  bool HasTextNodeDirectionalityMap() const
  1.1465 +    { return GetBoolFlag(NodeHasTextNodeDirectionalityMap); }
  1.1466 +
  1.1467 +  void SetHasDirAuto() { SetBoolFlag(NodeHasDirAuto); }
  1.1468 +  void ClearHasDirAuto() { ClearBoolFlag(NodeHasDirAuto); }
  1.1469 +  bool HasDirAuto() const { return GetBoolFlag(NodeHasDirAuto); }
  1.1470 +
  1.1471 +  void SetAncestorHasDirAuto() { SetBoolFlag(NodeAncestorHasDirAuto); }
  1.1472 +  void ClearAncestorHasDirAuto() { ClearBoolFlag(NodeAncestorHasDirAuto); }
  1.1473 +  bool AncestorHasDirAuto() const { return GetBoolFlag(NodeAncestorHasDirAuto); }
  1.1474 +
  1.1475 +  bool NodeOrAncestorHasDirAuto() const
  1.1476 +    { return HasDirAuto() || AncestorHasDirAuto(); }
  1.1477 +
  1.1478 +  void SetIsElementInStyleScope(bool aValue) {
  1.1479 +    MOZ_ASSERT(IsElement(), "SetIsInStyleScope on a non-Element node");
  1.1480 +    SetBoolFlag(ElementIsInStyleScope, aValue);
  1.1481 +  }
  1.1482 +  void SetIsElementInStyleScope() {
  1.1483 +    MOZ_ASSERT(IsElement(), "SetIsInStyleScope on a non-Element node");
  1.1484 +    SetBoolFlag(ElementIsInStyleScope);
  1.1485 +  }
  1.1486 +  void ClearIsElementInStyleScope() {
  1.1487 +    MOZ_ASSERT(IsElement(), "ClearIsInStyleScope on a non-Element node");
  1.1488 +    ClearBoolFlag(ElementIsInStyleScope);
  1.1489 +  }
  1.1490 +  bool IsElementInStyleScope() const { return GetBoolFlag(ElementIsInStyleScope); }
  1.1491 +
  1.1492 +  void SetIsScopedStyleRoot() { SetBoolFlag(ElementIsScopedStyleRoot); }
  1.1493 +  void ClearIsScopedStyleRoot() { ClearBoolFlag(ElementIsScopedStyleRoot); }
  1.1494 +  bool IsScopedStyleRoot() { return GetBoolFlag(ElementIsScopedStyleRoot); }
  1.1495 +  bool HasRelevantHoverRules() const { return GetBoolFlag(NodeHasRelevantHoverRules); }
  1.1496 +  void SetHasRelevantHoverRules() { SetBoolFlag(NodeHasRelevantHoverRules); }
  1.1497 +protected:
  1.1498 +  void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
  1.1499 +  void SetInDocument() { SetBoolFlag(IsInDocument); }
  1.1500 +  void SetNodeIsContent() { SetBoolFlag(NodeIsContent); }
  1.1501 +  void ClearInDocument() { ClearBoolFlag(IsInDocument); }
  1.1502 +  void SetIsElement() { SetBoolFlag(NodeIsElement); }
  1.1503 +  void SetHasID() { SetBoolFlag(ElementHasID); }
  1.1504 +  void ClearHasID() { ClearBoolFlag(ElementHasID); }
  1.1505 +  void SetMayHaveStyle() { SetBoolFlag(ElementMayHaveStyle); }
  1.1506 +  void SetHasName() { SetBoolFlag(ElementHasName); }
  1.1507 +  void ClearHasName() { ClearBoolFlag(ElementHasName); }
  1.1508 +  void SetMayHaveContentEditableAttr()
  1.1509 +    { SetBoolFlag(ElementMayHaveContentEditableAttr); }
  1.1510 +  bool HasExplicitBaseURI() const { return GetBoolFlag(NodeHasExplicitBaseURI); }
  1.1511 +  void SetHasExplicitBaseURI() { SetBoolFlag(NodeHasExplicitBaseURI); }
  1.1512 +  void SetHasLockedStyleStates() { SetBoolFlag(ElementHasLockedStyleStates); }
  1.1513 +  void ClearHasLockedStyleStates() { ClearBoolFlag(ElementHasLockedStyleStates); }
  1.1514 +  bool HasLockedStyleStates() const
  1.1515 +    { return GetBoolFlag(ElementHasLockedStyleStates); }
  1.1516 +  void SetHasWeirdParserInsertionMode() { SetBoolFlag(ElementHasWeirdParserInsertionMode); }
  1.1517 +  bool HasWeirdParserInsertionMode() const
  1.1518 +  { return GetBoolFlag(ElementHasWeirdParserInsertionMode); }
  1.1519 +  bool HandlingClick() const { return GetBoolFlag(NodeHandlingClick); }
  1.1520 +  void SetHandlingClick() { SetBoolFlag(NodeHandlingClick); }
  1.1521 +  void ClearHandlingClick() { ClearBoolFlag(NodeHandlingClick); }
  1.1522 +
  1.1523 +  void SetSubtreeRootPointer(nsINode* aSubtreeRoot)
  1.1524 +  {
  1.1525 +    NS_ASSERTION(aSubtreeRoot, "aSubtreeRoot can never be null!");
  1.1526 +    NS_ASSERTION(!(IsNodeOfType(eCONTENT) && IsInDoc()), "Shouldn't be here!");
  1.1527 +    mSubtreeRoot = aSubtreeRoot;
  1.1528 +  }
  1.1529 +
  1.1530 +  void ClearSubtreeRootPointer()
  1.1531 +  {
  1.1532 +    mSubtreeRoot = nullptr;
  1.1533 +  }
  1.1534 +
  1.1535 +public:
  1.1536 +  // Makes nsINode object to keep aObject alive.
  1.1537 +  void BindObject(nsISupports* aObject);
  1.1538 +  // After calling UnbindObject nsINode object doesn't keep
  1.1539 +  // aObject alive anymore.
  1.1540 +  void UnbindObject(nsISupports* aObject);
  1.1541 +
  1.1542 +  void GetBoundMutationObservers(nsTArray<nsRefPtr<nsDOMMutationObserver> >& aResult);
  1.1543 +
  1.1544 +  /**
  1.1545 +   * Returns the length of this node, as specified at
  1.1546 +   * <http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node-length>
  1.1547 +   */
  1.1548 +  uint32_t Length() const;
  1.1549 +
  1.1550 +  void GetNodeName(mozilla::dom::DOMString& aNodeName)
  1.1551 +  {
  1.1552 +    const nsString& nodeName = NodeName();
  1.1553 +    aNodeName.SetStringBuffer(nsStringBuffer::FromString(nodeName),
  1.1554 +                              nodeName.Length());
  1.1555 +  }
  1.1556 +  void GetBaseURI(nsAString& aBaseURI) const;
  1.1557 +  // Return the base URI for the document.
  1.1558 +  // The returned value may differ if the document is loaded via XHR, and
  1.1559 +  // when accessed from chrome privileged script and
  1.1560 +  // from content privileged script for compatibility.
  1.1561 +  void GetBaseURIFromJS(nsAString& aBaseURI) const;
  1.1562 +  bool HasChildNodes() const
  1.1563 +  {
  1.1564 +    return HasChildren();
  1.1565 +  }
  1.1566 +  uint16_t CompareDocumentPosition(nsINode& aOther) const;
  1.1567 +  void GetNodeValue(nsAString& aNodeValue)
  1.1568 +  {
  1.1569 +    GetNodeValueInternal(aNodeValue);
  1.1570 +  }
  1.1571 +  void SetNodeValue(const nsAString& aNodeValue,
  1.1572 +                    mozilla::ErrorResult& aError)
  1.1573 +  {
  1.1574 +    SetNodeValueInternal(aNodeValue, aError);
  1.1575 +  }
  1.1576 +  virtual void GetNodeValueInternal(nsAString& aNodeValue);
  1.1577 +  virtual void SetNodeValueInternal(const nsAString& aNodeValue,
  1.1578 +                                    mozilla::ErrorResult& aError)
  1.1579 +  {
  1.1580 +    // The DOM spec says that when nodeValue is defined to be null "setting it
  1.1581 +    // has no effect", so we don't throw an exception.
  1.1582 +  }
  1.1583 +  nsINode* InsertBefore(nsINode& aNode, nsINode* aChild,
  1.1584 +                        mozilla::ErrorResult& aError)
  1.1585 +  {
  1.1586 +    return ReplaceOrInsertBefore(false, &aNode, aChild, aError);
  1.1587 +  }
  1.1588 +  nsINode* AppendChild(nsINode& aNode, mozilla::ErrorResult& aError)
  1.1589 +  {
  1.1590 +    return InsertBefore(aNode, nullptr, aError);
  1.1591 +  }
  1.1592 +  nsINode* ReplaceChild(nsINode& aNode, nsINode& aChild,
  1.1593 +                        mozilla::ErrorResult& aError)
  1.1594 +  {
  1.1595 +    return ReplaceOrInsertBefore(true, &aNode, &aChild, aError);
  1.1596 +  }
  1.1597 +  nsINode* RemoveChild(nsINode& aChild, mozilla::ErrorResult& aError);
  1.1598 +  already_AddRefed<nsINode> CloneNode(bool aDeep, mozilla::ErrorResult& aError);
  1.1599 +  bool IsEqualNode(nsINode* aNode);
  1.1600 +  void GetNamespaceURI(nsAString& aNamespaceURI) const
  1.1601 +  {
  1.1602 +    mNodeInfo->GetNamespaceURI(aNamespaceURI);
  1.1603 +  }
  1.1604 +#ifdef MOZILLA_INTERNAL_API
  1.1605 +  void GetPrefix(nsAString& aPrefix)
  1.1606 +  {
  1.1607 +    mNodeInfo->GetPrefix(aPrefix);
  1.1608 +  }
  1.1609 +#endif
  1.1610 +  void GetLocalName(mozilla::dom::DOMString& aLocalName)
  1.1611 +  {
  1.1612 +    const nsString& localName = LocalName();
  1.1613 +    if (localName.IsVoid()) {
  1.1614 +      aLocalName.SetNull();
  1.1615 +    } else {
  1.1616 +      aLocalName.SetStringBuffer(nsStringBuffer::FromString(localName),
  1.1617 +                                 localName.Length());
  1.1618 +    }
  1.1619 +  }
  1.1620 +  // HasAttributes is defined inline in Element.h.
  1.1621 +  bool HasAttributes() const;
  1.1622 +  nsDOMAttributeMap* GetAttributes();
  1.1623 +  void SetUserData(JSContext* aCx, const nsAString& aKey,
  1.1624 +                   JS::Handle<JS::Value> aData,
  1.1625 +                   nsIDOMUserDataHandler* aHandler,
  1.1626 +                   JS::MutableHandle<JS::Value> aRetval,
  1.1627 +                   mozilla::ErrorResult& aError);
  1.1628 +  void GetUserData(JSContext* aCx, const nsAString& aKey,
  1.1629 +                   JS::MutableHandle<JS::Value> aRetval,
  1.1630 +                   mozilla::ErrorResult& aError);
  1.1631 +
  1.1632 +  // Helper method to remove this node from its parent. This is not exposed
  1.1633 +  // through WebIDL.
  1.1634 +  // Only call this if the node has a parent node.
  1.1635 +  nsresult RemoveFromParent()
  1.1636 +  {
  1.1637 +    nsINode* parent = GetParentNode();
  1.1638 +    mozilla::ErrorResult rv;
  1.1639 +    parent->RemoveChild(*this, rv);
  1.1640 +    return rv.ErrorCode();
  1.1641 +  }
  1.1642 +
  1.1643 +  // ChildNode methods
  1.1644 +  mozilla::dom::Element* GetPreviousElementSibling() const;
  1.1645 +  mozilla::dom::Element* GetNextElementSibling() const;
  1.1646 +  /**
  1.1647 +   * Remove this node from its parent, if any.
  1.1648 +   */
  1.1649 +  void Remove();
  1.1650 +
  1.1651 +  // ParentNode methods
  1.1652 +  mozilla::dom::Element* GetFirstElementChild() const;
  1.1653 +  mozilla::dom::Element* GetLastElementChild() const;
  1.1654 +
  1.1655 +  void GetBoxQuads(const BoxQuadOptions& aOptions,
  1.1656 +                   nsTArray<nsRefPtr<DOMQuad> >& aResult,
  1.1657 +                   mozilla::ErrorResult& aRv);
  1.1658 +
  1.1659 +  already_AddRefed<DOMQuad> ConvertQuadFromNode(DOMQuad& aQuad,
  1.1660 +                                                const TextOrElementOrDocument& aFrom,
  1.1661 +                                                const ConvertCoordinateOptions& aOptions,
  1.1662 +                                                ErrorResult& aRv);
  1.1663 +  already_AddRefed<DOMQuad> ConvertRectFromNode(DOMRectReadOnly& aRect,
  1.1664 +                                                const TextOrElementOrDocument& aFrom,
  1.1665 +                                                const ConvertCoordinateOptions& aOptions,
  1.1666 +                                                ErrorResult& aRv);
  1.1667 +  already_AddRefed<DOMPoint> ConvertPointFromNode(const DOMPointInit& aPoint,
  1.1668 +                                                  const TextOrElementOrDocument& aFrom,
  1.1669 +                                                  const ConvertCoordinateOptions& aOptions,
  1.1670 +                                                  ErrorResult& aRv);
  1.1671 +
  1.1672 +protected:
  1.1673 +
  1.1674 +  // Override this function to create a custom slots class.
  1.1675 +  // Must not return null.
  1.1676 +  virtual nsINode::nsSlots* CreateSlots();
  1.1677 +
  1.1678 +  bool HasSlots() const
  1.1679 +  {
  1.1680 +    return mSlots != nullptr;
  1.1681 +  }
  1.1682 +
  1.1683 +  nsSlots* GetExistingSlots() const
  1.1684 +  {
  1.1685 +    return mSlots;
  1.1686 +  }
  1.1687 +
  1.1688 +  nsSlots* Slots()
  1.1689 +  {
  1.1690 +    if (!HasSlots()) {
  1.1691 +      mSlots = CreateSlots();
  1.1692 +      MOZ_ASSERT(mSlots);
  1.1693 +    }
  1.1694 +    return GetExistingSlots();
  1.1695 +  }
  1.1696 +
  1.1697 +  nsTObserverArray<nsIMutationObserver*> *GetMutationObservers()
  1.1698 +  {
  1.1699 +    return HasSlots() ? &GetExistingSlots()->mMutationObservers : nullptr;
  1.1700 +  }
  1.1701 +
  1.1702 +  bool IsEditableInternal() const;
  1.1703 +  virtual bool IsEditableExternal() const
  1.1704 +  {
  1.1705 +    return IsEditableInternal();
  1.1706 +  }
  1.1707 +
  1.1708 +  virtual void GetTextContentInternal(nsAString& aTextContent);
  1.1709 +  virtual void SetTextContentInternal(const nsAString& aTextContent,
  1.1710 +                                      mozilla::ErrorResult& aError)
  1.1711 +  {
  1.1712 +  }
  1.1713 +
  1.1714 +#ifdef DEBUG
  1.1715 +  // Note: virtual so that IsInNativeAnonymousSubtree can be called accross
  1.1716 +  // module boundaries.
  1.1717 +  virtual void CheckNotNativeAnonymous() const;
  1.1718 +#endif
  1.1719 +
  1.1720 +  // These are just used to implement nsIDOMNode using
  1.1721 +  // NS_FORWARD_NSIDOMNODE_TO_NSINODE_HELPER and for quickstubs.
  1.1722 +  nsresult GetParentNode(nsIDOMNode** aParentNode);
  1.1723 +  nsresult GetParentElement(nsIDOMElement** aParentElement);
  1.1724 +  nsresult GetChildNodes(nsIDOMNodeList** aChildNodes);
  1.1725 +  nsresult GetFirstChild(nsIDOMNode** aFirstChild);
  1.1726 +  nsresult GetLastChild(nsIDOMNode** aLastChild);
  1.1727 +  nsresult GetPreviousSibling(nsIDOMNode** aPrevSibling);
  1.1728 +  nsresult GetNextSibling(nsIDOMNode** aNextSibling);
  1.1729 +  nsresult GetOwnerDocument(nsIDOMDocument** aOwnerDocument);
  1.1730 +  nsresult CompareDocumentPosition(nsIDOMNode* aOther,
  1.1731 +                                   uint16_t* aReturn);
  1.1732 +
  1.1733 +  nsresult ReplaceOrInsertBefore(bool aReplace, nsIDOMNode *aNewChild,
  1.1734 +                                 nsIDOMNode *aRefChild, nsIDOMNode **aReturn);
  1.1735 +  nsINode* ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
  1.1736 +                                 nsINode* aRefChild,
  1.1737 +                                 mozilla::ErrorResult& aError);
  1.1738 +  nsresult RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn);
  1.1739 +
  1.1740 +  /**
  1.1741 +   * Returns the Element that should be used for resolving namespaces
  1.1742 +   * on this node (ie the ownerElement for attributes, the documentElement for
  1.1743 +   * documents, the node itself for elements and for other nodes the parentNode
  1.1744 +   * if it is an element).
  1.1745 +   */
  1.1746 +  virtual mozilla::dom::Element* GetNameSpaceElement() = 0;
  1.1747 +
  1.1748 +  /**
  1.1749 +   * Most of the implementation of the nsINode RemoveChildAt method.
  1.1750 +   * Should only be called on document, element, and document fragment
  1.1751 +   * nodes.  The aChildArray passed in should be the one for |this|.
  1.1752 +   *
  1.1753 +   * @param aIndex The index to remove at.
  1.1754 +   * @param aNotify Whether to notify.
  1.1755 +   * @param aKid The kid at aIndex.  Must not be null.
  1.1756 +   * @param aChildArray The child array to work with.
  1.1757 +   * @param aMutationEvent whether to fire a mutation event for this removal.
  1.1758 +   */
  1.1759 +  void doRemoveChildAt(uint32_t aIndex, bool aNotify, nsIContent* aKid,
  1.1760 +                       nsAttrAndChildArray& aChildArray);
  1.1761 +
  1.1762 +  /**
  1.1763 +   * Most of the implementation of the nsINode InsertChildAt method.
  1.1764 +   * Should only be called on document, element, and document fragment
  1.1765 +   * nodes.  The aChildArray passed in should be the one for |this|.
  1.1766 +   *
  1.1767 +   * @param aKid The child to insert.
  1.1768 +   * @param aIndex The index to insert at.
  1.1769 +   * @param aNotify Whether to notify.
  1.1770 +   * @param aChildArray The child array to work with
  1.1771 +   */
  1.1772 +  nsresult doInsertChildAt(nsIContent* aKid, uint32_t aIndex,
  1.1773 +                           bool aNotify, nsAttrAndChildArray& aChildArray);
  1.1774 +
  1.1775 +  /**
  1.1776 +   * Parse the given selector string into an nsCSSSelectorList.
  1.1777 +   *
  1.1778 +   * A null return value with a non-failing aRv means the string only
  1.1779 +   * contained pseudo-element selectors.
  1.1780 +   *
  1.1781 +   * A failing aRv means the string was not a valid selector.
  1.1782 +   */
  1.1783 +  nsCSSSelectorList* ParseSelectorList(const nsAString& aSelectorString,
  1.1784 +                                       mozilla::ErrorResult& aRv);
  1.1785 +
  1.1786 +public:
  1.1787 +  /* Event stuff that documents and elements share.  This needs to be
  1.1788 +     NS_IMETHOD because some subclasses implement DOM methods with
  1.1789 +     this exact name and signature and then the calling convention
  1.1790 +     needs to match.
  1.1791 +
  1.1792 +     Note that we include DOCUMENT_ONLY_EVENT events here so that we
  1.1793 +     can forward all the document stuff to this implementation.
  1.1794 +  */
  1.1795 +#define EVENT(name_, id_, type_, struct_)                             \
  1.1796 +  mozilla::dom::EventHandlerNonNull* GetOn##name_();                  \
  1.1797 +  void SetOn##name_(mozilla::dom::EventHandlerNonNull* listener);
  1.1798 +#define TOUCH_EVENT EVENT
  1.1799 +#define DOCUMENT_ONLY_EVENT EVENT
  1.1800 +#include "mozilla/EventNameList.h"
  1.1801 +#undef DOCUMENT_ONLY_EVENT
  1.1802 +#undef TOUCH_EVENT
  1.1803 +#undef EVENT
  1.1804 +
  1.1805 +protected:
  1.1806 +  static bool Traverse(nsINode *tmp, nsCycleCollectionTraversalCallback &cb);
  1.1807 +  static void Unlink(nsINode *tmp);
  1.1808 +
  1.1809 +  nsCOMPtr<nsINodeInfo> mNodeInfo;
  1.1810 +
  1.1811 +  nsINode* mParent;
  1.1812 +
  1.1813 +private:
  1.1814 +  // Boolean flags.
  1.1815 +  uint32_t mBoolFlags;
  1.1816 +
  1.1817 +protected:
  1.1818 +  nsIContent* mNextSibling;
  1.1819 +  nsIContent* mPreviousSibling;
  1.1820 +  nsIContent* mFirstChild;
  1.1821 +
  1.1822 +  union {
  1.1823 +    // Pointer to our primary frame.  Might be null.
  1.1824 +    nsIFrame* mPrimaryFrame;
  1.1825 +
  1.1826 +    // Pointer to the root of our subtree.  Might be null.
  1.1827 +    nsINode* mSubtreeRoot;
  1.1828 +  };
  1.1829 +
  1.1830 +  // Storage for more members that are usually not needed; allocated lazily.
  1.1831 +  nsSlots* mSlots;
  1.1832 +};
  1.1833 +
  1.1834 +// Useful inline function for getting a node given an nsIContent and an
  1.1835 +// nsIDocument.  Returns the first argument cast to nsINode if it is non-null,
  1.1836 +// otherwise returns the second (which may be null).  We use type variables
  1.1837 +// instead of nsIContent* and nsIDocument* because the actual types must be
  1.1838 +// known for the cast to work.
  1.1839 +template<class C, class D>
  1.1840 +inline nsINode* NODE_FROM(C& aContent, D& aDocument)
  1.1841 +{
  1.1842 +  if (aContent)
  1.1843 +    return static_cast<nsINode*>(aContent);
  1.1844 +  return static_cast<nsINode*>(aDocument);
  1.1845 +}
  1.1846 +
  1.1847 +NS_DEFINE_STATIC_IID_ACCESSOR(nsINode, NS_INODE_IID)
  1.1848 +
  1.1849 +inline nsISupports*
  1.1850 +ToSupports(nsINode* aPointer)
  1.1851 +{
  1.1852 +  return aPointer;
  1.1853 +}
  1.1854 +
  1.1855 +inline nsISupports*
  1.1856 +ToCanonicalSupports(nsINode* aPointer)
  1.1857 +{
  1.1858 +  return aPointer;
  1.1859 +}
  1.1860 +
  1.1861 +#define NS_FORWARD_NSIDOMNODE_TO_NSINODE_HELPER(...) \
  1.1862 +  NS_IMETHOD GetNodeName(nsAString& aNodeName) __VA_ARGS__ \
  1.1863 +  { \
  1.1864 +    aNodeName = nsINode::NodeName(); \
  1.1865 +    return NS_OK; \
  1.1866 +  } \
  1.1867 +  NS_IMETHOD GetNodeValue(nsAString& aNodeValue) __VA_ARGS__ \
  1.1868 +  { \
  1.1869 +    nsINode::GetNodeValue(aNodeValue); \
  1.1870 +    return NS_OK; \
  1.1871 +  } \
  1.1872 +  NS_IMETHOD SetNodeValue(const nsAString& aNodeValue) __VA_ARGS__ \
  1.1873 +  { \
  1.1874 +    mozilla::ErrorResult rv; \
  1.1875 +    nsINode::SetNodeValue(aNodeValue, rv); \
  1.1876 +    return rv.ErrorCode(); \
  1.1877 +  } \
  1.1878 +  NS_IMETHOD GetNodeType(uint16_t* aNodeType) __VA_ARGS__ \
  1.1879 +  { \
  1.1880 +    *aNodeType = nsINode::NodeType(); \
  1.1881 +    return NS_OK; \
  1.1882 +  } \
  1.1883 +  NS_IMETHOD GetParentNode(nsIDOMNode** aParentNode) __VA_ARGS__ \
  1.1884 +  { \
  1.1885 +    return nsINode::GetParentNode(aParentNode); \
  1.1886 +  } \
  1.1887 +  NS_IMETHOD GetParentElement(nsIDOMElement** aParentElement) __VA_ARGS__ \
  1.1888 +  { \
  1.1889 +    return nsINode::GetParentElement(aParentElement); \
  1.1890 +  } \
  1.1891 +  NS_IMETHOD GetChildNodes(nsIDOMNodeList** aChildNodes) __VA_ARGS__ \
  1.1892 +  { \
  1.1893 +    return nsINode::GetChildNodes(aChildNodes); \
  1.1894 +  } \
  1.1895 +  NS_IMETHOD GetFirstChild(nsIDOMNode** aFirstChild) __VA_ARGS__ \
  1.1896 +  { \
  1.1897 +    return nsINode::GetFirstChild(aFirstChild); \
  1.1898 +  } \
  1.1899 +  NS_IMETHOD GetLastChild(nsIDOMNode** aLastChild) __VA_ARGS__ \
  1.1900 +  { \
  1.1901 +    return nsINode::GetLastChild(aLastChild); \
  1.1902 +  } \
  1.1903 +  NS_IMETHOD GetPreviousSibling(nsIDOMNode** aPreviousSibling) __VA_ARGS__ \
  1.1904 +  { \
  1.1905 +    return nsINode::GetPreviousSibling(aPreviousSibling); \
  1.1906 +  } \
  1.1907 +  NS_IMETHOD GetNextSibling(nsIDOMNode** aNextSibling) __VA_ARGS__ \
  1.1908 +  { \
  1.1909 +    return nsINode::GetNextSibling(aNextSibling); \
  1.1910 +  } \
  1.1911 +  NS_IMETHOD GetOwnerDocument(nsIDOMDocument** aOwnerDocument) __VA_ARGS__ \
  1.1912 +  { \
  1.1913 +    return nsINode::GetOwnerDocument(aOwnerDocument); \
  1.1914 +  } \
  1.1915 +  NS_IMETHOD InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMNode** aResult) __VA_ARGS__ \
  1.1916 +  { \
  1.1917 +    return ReplaceOrInsertBefore(false, aNewChild, aRefChild, aResult); \
  1.1918 +  } \
  1.1919 +  NS_IMETHOD ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild, nsIDOMNode** aResult) __VA_ARGS__ \
  1.1920 +  { \
  1.1921 +    return ReplaceOrInsertBefore(true, aNewChild, aOldChild, aResult); \
  1.1922 +  } \
  1.1923 +  NS_IMETHOD RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aResult) __VA_ARGS__ \
  1.1924 +  { \
  1.1925 +    return nsINode::RemoveChild(aOldChild, aResult); \
  1.1926 +  } \
  1.1927 +  NS_IMETHOD AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aResult) __VA_ARGS__ \
  1.1928 +  { \
  1.1929 +    return InsertBefore(aNewChild, nullptr, aResult); \
  1.1930 +  } \
  1.1931 +  NS_IMETHOD HasChildNodes(bool* aResult) __VA_ARGS__ \
  1.1932 +  { \
  1.1933 +    *aResult = nsINode::HasChildNodes(); \
  1.1934 +    return NS_OK; \
  1.1935 +  } \
  1.1936 +  NS_IMETHOD CloneNode(bool aDeep, uint8_t aArgc, nsIDOMNode** aResult) __VA_ARGS__ \
  1.1937 +  { \
  1.1938 +    if (aArgc == 0) { \
  1.1939 +      aDeep = true; \
  1.1940 +    } \
  1.1941 +    mozilla::ErrorResult rv; \
  1.1942 +    nsCOMPtr<nsINode> clone = nsINode::CloneNode(aDeep, rv); \
  1.1943 +    if (rv.Failed()) { \
  1.1944 +      return rv.ErrorCode(); \
  1.1945 +    } \
  1.1946 +    *aResult = clone.forget().take()->AsDOMNode(); \
  1.1947 +    return NS_OK; \
  1.1948 +  } \
  1.1949 +  NS_IMETHOD Normalize() __VA_ARGS__ \
  1.1950 +  { \
  1.1951 +    nsINode::Normalize(); \
  1.1952 +    return NS_OK; \
  1.1953 +  } \
  1.1954 +  NS_IMETHOD GetNamespaceURI(nsAString& aNamespaceURI) __VA_ARGS__ \
  1.1955 +  { \
  1.1956 +    nsINode::GetNamespaceURI(aNamespaceURI); \
  1.1957 +    return NS_OK; \
  1.1958 +  } \
  1.1959 +  NS_IMETHOD GetPrefix(nsAString& aPrefix) __VA_ARGS__ \
  1.1960 +  { \
  1.1961 +    nsINode::GetPrefix(aPrefix); \
  1.1962 +    return NS_OK; \
  1.1963 +  } \
  1.1964 +  NS_IMETHOD GetLocalName(nsAString& aLocalName) __VA_ARGS__ \
  1.1965 +  { \
  1.1966 +    aLocalName = nsINode::LocalName(); \
  1.1967 +    return NS_OK; \
  1.1968 +  } \
  1.1969 +  using nsINode::HasAttributes; \
  1.1970 +  NS_IMETHOD HasAttributes(bool* aResult) __VA_ARGS__ \
  1.1971 +  { \
  1.1972 +    *aResult = nsINode::HasAttributes(); \
  1.1973 +    return NS_OK; \
  1.1974 +  } \
  1.1975 +  NS_IMETHOD GetDOMBaseURI(nsAString& aBaseURI) __VA_ARGS__ \
  1.1976 +  { \
  1.1977 +    nsINode::GetBaseURI(aBaseURI); \
  1.1978 +    return NS_OK; \
  1.1979 +  } \
  1.1980 +  NS_IMETHOD CompareDocumentPosition(nsIDOMNode* aOther, uint16_t* aResult) __VA_ARGS__ \
  1.1981 +  { \
  1.1982 +    return nsINode::CompareDocumentPosition(aOther, aResult); \
  1.1983 +  } \
  1.1984 +  NS_IMETHOD GetTextContent(nsAString& aTextContent) __VA_ARGS__ \
  1.1985 +  { \
  1.1986 +    nsINode::GetTextContent(aTextContent); \
  1.1987 +    return NS_OK; \
  1.1988 +  } \
  1.1989 +  NS_IMETHOD SetTextContent(const nsAString& aTextContent) __VA_ARGS__ \
  1.1990 +  { \
  1.1991 +    mozilla::ErrorResult rv; \
  1.1992 +    nsINode::SetTextContent(aTextContent, rv); \
  1.1993 +    return rv.ErrorCode(); \
  1.1994 +  } \
  1.1995 +  NS_IMETHOD LookupPrefix(const nsAString& aNamespaceURI, nsAString& aResult) __VA_ARGS__ \
  1.1996 +  { \
  1.1997 +    nsINode::LookupPrefix(aNamespaceURI, aResult); \
  1.1998 +    return NS_OK; \
  1.1999 +  } \
  1.2000 +  NS_IMETHOD IsDefaultNamespace(const nsAString& aNamespaceURI, bool* aResult) __VA_ARGS__ \
  1.2001 +  { \
  1.2002 +    *aResult = nsINode::IsDefaultNamespace(aNamespaceURI); \
  1.2003 +    return NS_OK; \
  1.2004 +  } \
  1.2005 +  NS_IMETHOD LookupNamespaceURI(const nsAString& aPrefix, nsAString& aResult) __VA_ARGS__ \
  1.2006 +  { \
  1.2007 +    nsINode::LookupNamespaceURI(aPrefix, aResult); \
  1.2008 +    return NS_OK; \
  1.2009 +  } \
  1.2010 +  NS_IMETHOD IsEqualNode(nsIDOMNode* aArg, bool* aResult) __VA_ARGS__ \
  1.2011 +  { \
  1.2012 +    return nsINode::IsEqualNode(aArg, aResult); \
  1.2013 +  } \
  1.2014 +  NS_IMETHOD SetUserData(const nsAString& aKey, nsIVariant* aData, nsIDOMUserDataHandler* aHandler, nsIVariant** aResult) __VA_ARGS__ \
  1.2015 +  { \
  1.2016 +    return nsINode::SetUserData(aKey, aData, aHandler, aResult); \
  1.2017 +  } \
  1.2018 +  NS_IMETHOD GetUserData(const nsAString& aKey, nsIVariant** aResult) __VA_ARGS__ \
  1.2019 +  { \
  1.2020 +    return nsINode::GetUserData(aKey, aResult); \
  1.2021 +  } \
  1.2022 +  NS_IMETHOD Contains(nsIDOMNode* aOther, bool* aResult) __VA_ARGS__ \
  1.2023 +  { \
  1.2024 +    return nsINode::Contains(aOther, aResult); \
  1.2025 +  }
  1.2026 +
  1.2027 +#define NS_FORWARD_NSIDOMNODE_TO_NSINODE \
  1.2028 +  NS_FORWARD_NSIDOMNODE_TO_NSINODE_HELPER(MOZ_FINAL)
  1.2029 +
  1.2030 +#define NS_FORWARD_NSIDOMNODE_TO_NSINODE_OVERRIDABLE \
  1.2031 +  NS_FORWARD_NSIDOMNODE_TO_NSINODE_HELPER()
  1.2032 +
  1.2033 +#endif /* nsINode_h___ */

mercurial