tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Element.h (98342B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 /*
      8 * Base class for all element classes; this provides an implementation
      9 * of DOM Core's Element, implements nsIContent, provides
     10 * utility methods for subclasses, and so forth.
     11 */
     12 
     13 #ifndef mozilla_dom_Element_h__
     14 #define mozilla_dom_Element_h__
     15 
     16 #include <cstdint>
     17 #include <cstdio>
     18 #include <cstdlib>
     19 #include <utility>
     20 
     21 #include "AttrArray.h"
     22 #include "ErrorList.h"
     23 #include "Units.h"
     24 #include "js/RootingAPI.h"
     25 #include "mozilla/AlreadyAddRefed.h"
     26 #include "mozilla/Assertions.h"
     27 #include "mozilla/Attributes.h"
     28 #include "mozilla/BasicEvents.h"
     29 #include "mozilla/CORSMode.h"
     30 #include "mozilla/FlushType.h"
     31 #include "mozilla/Maybe.h"
     32 #include "mozilla/PseudoStyleType.h"
     33 #include "mozilla/RefPtr.h"
     34 #include "mozilla/Result.h"
     35 #include "mozilla/RustCell.h"
     36 #include "mozilla/UniquePtr.h"
     37 #include "mozilla/dom/BorrowedAttrInfo.h"
     38 #include "mozilla/dom/DOMString.h"
     39 #include "mozilla/dom/DOMTokenListSupportedTokens.h"
     40 #include "mozilla/dom/DirectionalityUtils.h"
     41 #include "mozilla/dom/FragmentOrElement.h"
     42 #include "mozilla/dom/NameSpaceConstants.h"
     43 #include "mozilla/dom/NodeInfo.h"
     44 #include "mozilla/dom/RustTypes.h"
     45 #include "mozilla/dom/ShadowRootBinding.h"
     46 #include "nsAtom.h"
     47 #include "nsAttrValue.h"
     48 #include "nsAttrValueInlines.h"
     49 #include "nsCaseTreatment.h"
     50 #include "nsChangeHint.h"
     51 #include "nsDebug.h"
     52 #include "nsError.h"
     53 #include "nsGkAtoms.h"
     54 #include "nsHashKeys.h"
     55 #include "nsIContent.h"
     56 #include "nsID.h"
     57 #include "nsINode.h"
     58 #include "nsLiteralString.h"
     59 #include "nsRect.h"
     60 #include "nsString.h"
     61 #include "nsStringFlags.h"
     62 #include "nsTHashMap.h"
     63 #include "nsTLiteralString.h"
     64 #include "nscore.h"
     65 
     66 class JSObject;
     67 class mozAutoDocUpdate;
     68 class nsAttrName;
     69 class nsAttrValueOrString;
     70 class nsContentList;
     71 class nsDOMAttributeMap;
     72 class nsDOMCSSAttributeDeclaration;
     73 class nsDOMStringMap;
     74 class nsDOMTokenList;
     75 class nsFocusManager;
     76 class nsGenericHTMLElement;
     77 class nsGenericHTMLFormControlElementWithState;
     78 class nsGlobalWindowInner;
     79 class nsGlobalWindowOuter;
     80 class nsImageLoadingContent;
     81 class nsIAutoCompletePopup;
     82 class nsIBrowser;
     83 class nsIDOMXULButtonElement;
     84 class nsIDOMXULContainerElement;
     85 class nsIDOMXULContainerItemElement;
     86 class nsIDOMXULControlElement;
     87 class nsIDOMXULMenuListElement;
     88 class nsIDOMXULMultiSelectControlElement;
     89 class nsIDOMXULRadioGroupElement;
     90 class nsIDOMXULRelatedElement;
     91 class nsIDOMXULSelectControlElement;
     92 class nsIDOMXULSelectControlItemElement;
     93 class nsIFrame;
     94 class nsIHTMLCollection;
     95 class nsIPrincipal;
     96 class nsIScreen;
     97 class nsIURI;
     98 class nsObjectLoadingContent;
     99 class nsPresContext;
    100 class nsWindowSizes;
    101 struct JSContext;
    102 struct ServoNodeData;
    103 template <class E>
    104 class nsTArray;
    105 template <class T>
    106 class nsGetterAddRefs;
    107 
    108 namespace mozilla {
    109 class DeclarationBlock;
    110 class MappedDeclarationsBuilder;
    111 class EditorBase;
    112 class ErrorResult;
    113 class OOMReporter;
    114 class ScrollContainerFrame;
    115 class SMILAttr;
    116 struct MutationClosureData;
    117 class TextEditor;
    118 namespace css {
    119 struct URLValue;
    120 }  // namespace css
    121 namespace dom {
    122 struct CheckVisibilityOptions;
    123 struct CustomElementData;
    124 struct SetHTMLUnsafeOptions;
    125 struct SetHTMLOptions;
    126 struct GetHTMLOptions;
    127 struct GetAnimationsOptions;
    128 struct ScrollIntoViewOptions;
    129 struct ScrollToOptions;
    130 struct FocusOptions;
    131 struct ShadowRootInit;
    132 struct ScrollOptions;
    133 class Attr;
    134 class BooleanOrScrollIntoViewOptions;
    135 class Document;
    136 class HTMLFormElement;
    137 class DOMIntersectionObserver;
    138 class DOMMatrixReadOnly;
    139 class Element;
    140 class ElementOrCSSPseudoElement;
    141 class PopoverData;
    142 class Promise;
    143 class Sanitizer;
    144 class ShadowRoot;
    145 class StylePropertyMapReadOnly;
    146 class TrustedHTMLOrString;
    147 class UnrestrictedDoubleOrKeyframeAnimationOptions;
    148 template <typename T>
    149 class Optional;
    150 enum class CallerType : uint32_t;
    151 enum class ReferrerPolicy : uint8_t;
    152 enum class FetchPriority : uint8_t;
    153 enum class PopoverAttributeState : uint8_t;
    154 }  // namespace dom
    155 }  // namespace mozilla
    156 
    157 using nsMapRuleToAttributesFunc = void (*)(mozilla::MappedDeclarationsBuilder&);
    158 
    159 // Declared here because of include hell.
    160 extern "C" bool Servo_Element_IsDisplayContents(const mozilla::dom::Element*);
    161 
    162 already_AddRefed<nsContentList> NS_GetContentList(nsINode* aRootNode,
    163                                                  int32_t aMatchNameSpaceId,
    164                                                  const nsAString& aTagname);
    165 
    166 #define ELEMENT_FLAG_BIT(n_) \
    167  NODE_FLAG_BIT(NODE_TYPE_SPECIFIC_BITS_OFFSET + (n_))
    168 
    169 // Element-specific flags
    170 enum : uint32_t {
    171  // Whether this node has dirty descendants for Servo's style system.
    172  ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO = ELEMENT_FLAG_BIT(0),
    173  // Whether this node has dirty descendants for animation-only restyle for
    174  // Servo's style system.
    175  ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO = ELEMENT_FLAG_BIT(1),
    176 
    177  // Whether the element has been snapshotted due to attribute or state changes
    178  // by the Servo restyle manager.
    179  ELEMENT_HAS_SNAPSHOT = ELEMENT_FLAG_BIT(2),
    180 
    181  // Whether the element has already handled its relevant snapshot.
    182  //
    183  // Used by the servo restyle process in order to accurately track whether the
    184  // style of an element is up-to-date, even during the same restyle process.
    185  ELEMENT_HANDLED_SNAPSHOT = ELEMENT_FLAG_BIT(3),
    186 
    187  // If this flag is set on an element, that means that it is a HTML datalist
    188  // element or has a HTML datalist element ancestor.
    189  ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR = ELEMENT_FLAG_BIT(4),
    190 
    191  // If this flag is set on an element, that means this element
    192  // has been considered by our LargestContentfulPaint algorithm and
    193  // it's not going to be considered again.
    194  ELEMENT_PROCESSED_BY_LCP_FOR_TEXT = ELEMENT_FLAG_BIT(5),
    195 
    196  // If this flag is set on an element, this means the HTML parser encountered
    197  // a duplicate attribute error:
    198  // https://html.spec.whatwg.org/multipage/parsing.html#parse-error-duplicate-attribute
    199  // This flag is used for detecting dangling markup attacks in the CSP
    200  // algorithm https://w3c.github.io/webappsec-csp/#is-element-nonceable.
    201  ELEMENT_PARSER_HAD_DUPLICATE_ATTR_ERROR = ELEMENT_FLAG_BIT(6),
    202 
    203  // If this flag is set, this element is in
    204  // Document::mContentIdentifiersForLCP.
    205  ELEMENT_IN_CONTENT_IDENTIFIER_FOR_LCP = ELEMENT_FLAG_BIT(7),
    206 
    207  // Remaining bits are for subclasses
    208  ELEMENT_TYPE_SPECIFIC_BITS_OFFSET = NODE_TYPE_SPECIFIC_BITS_OFFSET + 8
    209 };
    210 
    211 #undef ELEMENT_FLAG_BIT
    212 
    213 // Make sure we have space for our bits
    214 ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET);
    215 
    216 namespace mozilla {
    217 enum class PseudoStyleType : uint8_t;
    218 class EventChainPostVisitor;
    219 class EventChainPreVisitor;
    220 class EventChainVisitor;
    221 class EventListenerManager;
    222 class EventStateManager;
    223 
    224 enum class ContentEditableState {
    225  Inherit,
    226  False,
    227  True,
    228  PlainTextOnly,
    229 };
    230 
    231 namespace dom {
    232 
    233 struct CustomElementDefinition;
    234 class Animation;
    235 class CustomElementRegistry;
    236 class Link;
    237 class DOMRect;
    238 class DOMRectList;
    239 class Flex;
    240 class Grid;
    241 class OwningTrustedHTMLOrNullIsEmptyString;
    242 class TrustedHTML;
    243 class TrustedHTMLOrNullIsEmptyString;
    244 class TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString;
    245 
    246 // IID for the dom::Element interface
    247 #define NS_ELEMENT_IID \
    248  {0xc67ed254, 0xfd3b, 0x4b10, {0x96, 0xa2, 0xc5, 0x8b, 0x7b, 0x64, 0x97, 0xd1}}
    249 
    250 #define REFLECT_NULLABLE_DOMSTRING_ATTR(method, attr)            \
    251  void Get##method(nsAString& aValue) const {                    \
    252    const nsAttrValue* val = mAttrs.GetAttr(nsGkAtoms::attr);    \
    253    if (!val) {                                                  \
    254      SetDOMStringToNull(aValue);                                \
    255      return;                                                    \
    256    }                                                            \
    257    val->ToString(aValue);                                       \
    258  }                                                              \
    259  void Set##method(const nsAString& aValue, ErrorResult& aRv) {  \
    260    SetOrRemoveNullableStringAttr(nsGkAtoms::attr, aValue, aRv); \
    261  }
    262 
    263 #define REFLECT_NULLABLE_ELEMENT_ATTR(method, attr)      \
    264  Element* Get##method() const {                         \
    265    return GetAttrAssociatedElement(nsGkAtoms::attr);    \
    266  }                                                      \
    267                                                         \
    268  void Set##method(Element* aElement) {                  \
    269    ExplicitlySetAttrElement(nsGkAtoms::attr, aElement); \
    270  }
    271 
    272 #define REFLECT_NULLABLE_ELEMENTS_ATTR(method, attr)                        \
    273  void Get##method(bool* aUseCachedValue,                                   \
    274                   Nullable<nsTArray<RefPtr<Element>>>& aElements) {        \
    275    GetAttrAssociatedElements(nsGkAtoms::attr, aUseCachedValue, aElements); \
    276  }                                                                         \
    277                                                                            \
    278  void Set##method(                                                         \
    279      const Nullable<Sequence<OwningNonNull<Element>>>& aElements) {        \
    280    ExplicitlySetAttrElements(nsGkAtoms::attr, aElements);                  \
    281  }
    282 
    283 class Element : public FragmentOrElement {
    284 public:
    285 #ifdef MOZILLA_INTERNAL_API
    286  explicit Element(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
    287      : FragmentOrElement(std::move(aNodeInfo)),
    288        mState(ElementState::READONLY | ElementState::DEFINED |
    289               ElementState::LTR) {
    290    MOZ_ASSERT(mNodeInfo->NodeType() == ELEMENT_NODE,
    291               "Bad NodeType in aNodeInfo");
    292    SetIsElement();
    293  }
    294 
    295  ~Element() {
    296    NS_ASSERTION(!HasServoData(), "expected ServoData to be cleared earlier");
    297  }
    298 
    299 #endif  // MOZILLA_INTERNAL_API
    300 
    301  NS_INLINE_DECL_STATIC_IID(NS_ELEMENT_IID)
    302 
    303  NS_DECL_ADDSIZEOFEXCLUDINGTHIS
    304 
    305  NS_IMPL_FROMNODE_HELPER(Element, IsElement())
    306 
    307  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
    308 
    309  /**
    310   * Method to get the full state of this element. See dom/base/rust/lib.rs for
    311   * the possible bits that could be set here.
    312   */
    313  ElementState State() const { return mState; }
    314 
    315  /**
    316   * Returns the current disabled state of the element.
    317   */
    318  bool IsDisabled() const { return State().HasState(ElementState::DISABLED); }
    319  bool IsReadOnly() const { return State().HasState(ElementState::READONLY); }
    320  bool IsDisabledOrReadOnly() const {
    321    return State().HasAtLeastOneOfStates(ElementState::DISABLED |
    322                                         ElementState::READONLY);
    323  }
    324 
    325  /**
    326   * Return true if this element has contenteditable="plaintext-only".
    327   */
    328  [[nodiscard]] inline bool IsContentEditablePlainTextOnly() const;
    329 
    330  virtual int32_t TabIndexDefault() { return -1; }
    331 
    332  /**
    333   * Get tabIndex of this element. If not found, return TabIndexDefault.
    334   */
    335  int32_t TabIndex();
    336 
    337  /**
    338   * Get the parsed value of tabindex attribute.
    339   */
    340  Maybe<int32_t> GetTabIndexAttrValue();
    341 
    342  /**
    343   * Set tabIndex value to this element.
    344   */
    345  void SetTabIndex(int32_t aTabIndex, mozilla::ErrorResult& aError);
    346 
    347  /**
    348   * Sets the ShadowRoot binding for this element. The contents of the
    349   * binding is rendered in place of this node's children.
    350   *
    351   * @param aShadowRoot The ShadowRoot to be bound to this element.
    352   */
    353  void SetShadowRoot(ShadowRoot* aShadowRoot);
    354 
    355  void SetLastRememberedBSize(float aBSize);
    356  void SetLastRememberedISize(float aISize);
    357  void RemoveLastRememberedBSize();
    358  void RemoveLastRememberedISize();
    359 
    360  /**
    361   * Make focus on this element.
    362   */
    363  // TODO: Convert Focus() to MOZ_CAN_RUN_SCRIPT and get rid of the
    364  //       kungFuDeathGrip in it.
    365  MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void Focus(const FocusOptions& aOptions,
    366                                                 const CallerType aCallerType,
    367                                                 ErrorResult& aError);
    368 
    369  /**
    370   * Show blur and clear focus.
    371   */
    372  MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void Blur(mozilla::ErrorResult& aError);
    373 
    374  /**
    375   * The style state of this element. This is the real state of the element
    376   * with any style locks applied for pseudo-class inspecting.
    377   */
    378  ElementState StyleState() const {
    379    if (!HasLockedStyleStates()) {
    380      return mState;
    381    }
    382    return StyleStateFromLocks();
    383  }
    384 
    385  /**
    386   * StyleStateLocks is used to specify which event states should be locked,
    387   * and whether they should be locked to on or off.
    388   */
    389  struct StyleStateLocks {
    390    // mLocks tracks which event states should be locked.
    391    ElementState mLocks;
    392    // mValues tracks if the locked state should be on or off.
    393    ElementState mValues;
    394  };
    395 
    396  /**
    397   * The style state locks applied to this element.
    398   */
    399  StyleStateLocks LockedStyleStates() const;
    400 
    401  /**
    402   * Add a style state lock on this element.
    403   * aEnabled is the value to lock the given state bits to.
    404   */
    405  void LockStyleStates(ElementState aStates, bool aEnabled);
    406 
    407  /**
    408   * Remove a style state lock on this element.
    409   */
    410  void UnlockStyleStates(ElementState aStates);
    411 
    412  /**
    413   * Clear all style state locks on this element.
    414   */
    415  void ClearStyleStateLocks();
    416 
    417  /**
    418   * Accessors for the state of our dir attribute.
    419   */
    420  bool HasDirAuto() const {
    421    return State().HasState(ElementState::HAS_DIR_ATTR_LIKE_AUTO);
    422  }
    423 
    424  /**
    425   * Elements with dir="rtl" or dir="ltr".
    426   */
    427  bool HasFixedDir() const {
    428    return State().HasAtLeastOneOfStates(ElementState::HAS_DIR_ATTR_LTR |
    429                                         ElementState::HAS_DIR_ATTR_RTL);
    430  }
    431 
    432  /**
    433   * Get the inline style declaration, if any, for this element.
    434   */
    435  DeclarationBlock* GetInlineStyleDeclaration() const;
    436 
    437  /**
    438   * Get the mapped attributes, if any, for this element.
    439   */
    440  StyleLockedDeclarationBlock* GetMappedAttributeStyle() const {
    441    return mAttrs.GetMappedDeclarationBlock();
    442  }
    443 
    444  bool IsPendingMappedAttributeEvaluation() const {
    445    return mAttrs.IsPendingMappedAttributeEvaluation();
    446  }
    447 
    448  void SetMappedDeclarationBlock(already_AddRefed<StyleLockedDeclarationBlock>);
    449 
    450  /**
    451   * InlineStyleDeclarationWillChange is called before SetInlineStyleDeclaration
    452   * so that the element implementation can access the old style attribute
    453   * value.
    454   */
    455  virtual void InlineStyleDeclarationWillChange(MutationClosureData& aData);
    456 
    457  /**
    458   * Set the inline style declaration for this element.
    459   */
    460  virtual nsresult SetInlineStyleDeclaration(DeclarationBlock& aDeclaration,
    461                                             MutationClosureData& aData);
    462 
    463  /**
    464   * Get the SMIL override style declaration for this element. If the
    465   * rule hasn't been created, this method simply returns null.
    466   */
    467  DeclarationBlock* GetSMILOverrideStyleDeclaration();
    468 
    469  /**
    470   * Set the SMIL override style declaration for this element. This method will
    471   * notify the document's pres context, so that the style changes will be
    472   * noticed.
    473   */
    474  void SetSMILOverrideStyleDeclaration(DeclarationBlock&);
    475 
    476  /**
    477   * Returns a new SMILAttr that allows the caller to animate the given
    478   * attribute on this element.
    479   */
    480  virtual UniquePtr<SMILAttr> GetAnimatedAttr(int32_t aNamespaceID,
    481                                              nsAtom* aName);
    482 
    483  /**
    484   * Get the SMIL override style for this element. This is a style declaration
    485   * that is applied *after* the inline style, and it can be used e.g. to store
    486   * animated style values.
    487   *
    488   * Note: This method is analogous to the 'GetStyle' method in
    489   * nsGenericHTMLElement and nsStyledElement.
    490   */
    491  nsDOMCSSAttributeDeclaration* SMILOverrideStyle();
    492 
    493  /**
    494   * Returns if the element is labelable as per HTML specification.
    495   */
    496  virtual bool IsLabelable() const;
    497 
    498  /**
    499   * Returns if the element is interactive content as per HTML specification.
    500   */
    501  virtual bool IsInteractiveHTMLContent() const;
    502 
    503  /**
    504   * Is the attribute named aAttribute a mapped attribute?
    505   */
    506  NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const;
    507 
    508  nsresult BindToTree(BindContext&, nsINode& aParent) override;
    509  void UnbindFromTree(UnbindContext&) override;
    510  using nsIContent::UnbindFromTree;
    511 
    512  virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
    513  static void MapNoAttributesInto(mozilla::MappedDeclarationsBuilder&);
    514 
    515  /**
    516   * Get a hint that tells the style system what to do when
    517   * an attribute on this node changes, if something needs to happen
    518   * in response to the change *other* than the result of what is
    519   * mapped into style data via any type of style rule.
    520   */
    521  virtual nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
    522                                              AttrModType aModType) const;
    523 
    524  inline Directionality GetDirectionality() const {
    525    ElementState state = State();
    526    if (state.HasState(ElementState::RTL)) {
    527      return Directionality::Rtl;
    528    }
    529    if (state.HasState(ElementState::LTR)) {
    530      return Directionality::Ltr;
    531    }
    532    return Directionality::Unset;
    533  }
    534 
    535  inline void SetDirectionality(Directionality aDir, bool aNotify) {
    536    AutoStateChangeNotifier notifier(*this, aNotify);
    537    RemoveStatesSilently(ElementState::DIR_STATES);
    538    switch (aDir) {
    539      case Directionality::Rtl:
    540        AddStatesSilently(ElementState::RTL);
    541        break;
    542      case Directionality::Ltr:
    543        AddStatesSilently(ElementState::LTR);
    544        break;
    545      case Directionality::Unset:
    546      case Directionality::Auto:
    547        MOZ_ASSERT_UNREACHABLE("Setting unresolved directionality?");
    548        break;
    549    }
    550  }
    551 
    552  Directionality GetComputedDirectionality() const;
    553 
    554  static const uint32_t kAllServoDescendantBits =
    555      ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO |
    556      ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO |
    557      NODE_DESCENDANTS_NEED_FRAMES;
    558 
    559  /**
    560   * Notes that something in the given subtree of this element needs dirtying,
    561   * and that all the relevant dirty bits have already been propagated up to the
    562   * element.
    563   *
    564   * This is important because `NoteDirtyForServo` uses the dirty bits to reason
    565   * about the shape of the tree, so we can't just call into there.
    566   */
    567  void NoteDirtySubtreeForServo();
    568 
    569  void NoteDirtyForServo();
    570  void NoteAnimationOnlyDirtyForServo();
    571  void NoteDescendantsNeedFramesForServo();
    572 
    573  bool HasDirtyDescendantsForServo() const {
    574    return HasFlag(ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO);
    575  }
    576 
    577  void SetHasDirtyDescendantsForServo() {
    578    SetFlags(ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO);
    579  }
    580 
    581  void UnsetHasDirtyDescendantsForServo() {
    582    UnsetFlags(ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO);
    583  }
    584 
    585  bool HasAnimationOnlyDirtyDescendantsForServo() const {
    586    return HasFlag(ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO);
    587  }
    588 
    589  void SetHasAnimationOnlyDirtyDescendantsForServo() {
    590    SetFlags(ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO);
    591  }
    592 
    593  void UnsetHasAnimationOnlyDirtyDescendantsForServo() {
    594    UnsetFlags(ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO);
    595  }
    596 
    597  bool HasServoData() const { return !!mServoData.Get(); }
    598 
    599  void ClearServoData() { ClearServoData(GetComposedDoc()); }
    600  void ClearServoData(Document* aDocument);
    601 
    602  PopoverData* GetPopoverData() const {
    603    const nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
    604    return slots ? slots->mPopoverData.get() : nullptr;
    605  }
    606 
    607  PopoverData& EnsurePopoverData() {
    608    if (auto* popoverData = GetPopoverData()) {
    609      return *popoverData;
    610    }
    611    return CreatePopoverData();
    612  }
    613 
    614  bool IsPopoverOpenedInMode(PopoverAttributeState aMode) const;
    615  bool IsPopoverOpen() const;
    616 
    617  void SetAssociatedPopover(nsGenericHTMLElement& aPopover);
    618  nsGenericHTMLElement* GetAssociatedPopover() const;
    619 
    620  /**
    621   * https://html.spec.whatwg.org/multipage/popover.html#topmost-popover-ancestor
    622   */
    623  Element* GetTopmostPopoverAncestor(PopoverAttributeState aMode,
    624                                     const Element* aInvoker,
    625                                     bool isPopover) const;
    626 
    627  ElementAnimationData* GetAnimationData() const {
    628    if (!MayHaveAnimations()) {
    629      return nullptr;
    630    }
    631    const nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
    632    return slots ? slots->mAnimations.get() : nullptr;
    633  }
    634 
    635  ElementAnimationData& EnsureAnimationData() {
    636    if (auto* anim = GetAnimationData()) {
    637      return *anim;
    638    }
    639    return CreateAnimationData();
    640  }
    641 
    642 private:
    643  ElementAnimationData& CreateAnimationData();
    644  PopoverData& CreatePopoverData();
    645 
    646 public:
    647  void ClearPopoverData();
    648 
    649  /**
    650   * Gets the custom element data used by web components custom element.
    651   * Custom element data is created at the first attempt to enqueue a callback.
    652   *
    653   * @return The custom element data or null if none.
    654   */
    655  CustomElementData* GetCustomElementData() const {
    656    if (!HasCustomElementData()) {
    657      return nullptr;
    658    }
    659 
    660    const nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
    661    return slots ? slots->mCustomElementData.get() : nullptr;
    662  }
    663 
    664  /**
    665   * Sets the custom element data, ownership of the
    666   * callback data is taken by this element.
    667   *
    668   * @param aData The custom element data.
    669   */
    670  void SetCustomElementData(UniquePtr<CustomElementData> aData);
    671 
    672  nsTArray<RefPtr<nsAtom>>& EnsureCustomStates();
    673 
    674  /**
    675   * Gets the custom element definition used by web components custom element.
    676   *
    677   * @return The custom element definition or null if element is not a custom
    678   *         element or custom element is not defined yet.
    679   */
    680  CustomElementDefinition* GetCustomElementDefinition() const;
    681 
    682  /**
    683   * Sets the custom element definition, called when custom element is created
    684   * or upgraded.
    685   *
    686   * @param aDefinition The custom element definition.
    687   */
    688  virtual void SetCustomElementDefinition(CustomElementDefinition* aDefinition);
    689 
    690  const AttrArray& GetAttrs() const { return mAttrs; }
    691 
    692  void SetDefined(bool aSet) { SetStates(ElementState::DEFINED, aSet); }
    693 
    694  // AccessibilityRole
    695  REFLECT_NULLABLE_DOMSTRING_ATTR(Role, role)
    696 
    697  // AriaAttributes
    698  REFLECT_NULLABLE_ELEMENT_ATTR(AriaActiveDescendantElement,
    699                                aria_activedescendant)
    700  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaAtomic, aria_atomic)
    701  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaAutoComplete, aria_autocomplete)
    702  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaBrailleLabel, aria_braillelabel)
    703  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaBrailleRoleDescription,
    704                                  aria_brailleroledescription)
    705  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaBusy, aria_busy)
    706  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaChecked, aria_checked)
    707  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaColCount, aria_colcount)
    708  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaColIndex, aria_colindex)
    709  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaColIndexText, aria_colindextext)
    710  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaColSpan, aria_colspan)
    711  REFLECT_NULLABLE_ELEMENTS_ATTR(AriaControlsElements, aria_controls)
    712  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaCurrent, aria_current)
    713  REFLECT_NULLABLE_ELEMENTS_ATTR(AriaDescribedByElements, aria_describedby)
    714  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaDescription, aria_description)
    715  REFLECT_NULLABLE_ELEMENTS_ATTR(AriaDetailsElements, aria_details)
    716  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaDisabled, aria_disabled)
    717  REFLECT_NULLABLE_ELEMENTS_ATTR(AriaErrorMessageElements, aria_errormessage)
    718  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaExpanded, aria_expanded)
    719  REFLECT_NULLABLE_ELEMENTS_ATTR(AriaFlowToElements, aria_flowto)
    720  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaHasPopup, aria_haspopup)
    721  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaHidden, aria_hidden)
    722  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaInvalid, aria_invalid)
    723  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaKeyShortcuts, aria_keyshortcuts)
    724  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaLabel, aria_label)
    725  REFLECT_NULLABLE_ELEMENTS_ATTR(AriaLabelledByElements, aria_labelledby)
    726  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaLevel, aria_level)
    727  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaLive, aria_live)
    728  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaModal, aria_modal)
    729  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaMultiLine, aria_multiline)
    730  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaMultiSelectable, aria_multiselectable)
    731  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaOrientation, aria_orientation)
    732  REFLECT_NULLABLE_ELEMENTS_ATTR(AriaOwnsElements, aria_owns)
    733  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaPlaceholder, aria_placeholder)
    734  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaPosInSet, aria_posinset)
    735  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaPressed, aria_pressed)
    736  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaReadOnly, aria_readonly)
    737  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaRelevant, aria_relevant)
    738  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaRequired, aria_required)
    739  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaRoleDescription, aria_roledescription)
    740  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaRowCount, aria_rowcount)
    741  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaRowIndex, aria_rowindex)
    742  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaRowIndexText, aria_rowindextext)
    743  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaRowSpan, aria_rowspan)
    744  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaSelected, aria_selected)
    745  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaSetSize, aria_setsize)
    746  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaSort, aria_sort)
    747  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaValueMax, aria_valuemax)
    748  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaValueMin, aria_valuemin)
    749  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaValueNow, aria_valuenow)
    750  REFLECT_NULLABLE_DOMSTRING_ATTR(AriaValueText, aria_valuetext)
    751 
    752 protected:
    753  already_AddRefed<ShadowRoot> AttachShadowInternal(ShadowRootMode,
    754                                                    ErrorResult& aError);
    755 
    756 public:
    757  MOZ_CAN_RUN_SCRIPT
    758  ScrollContainerFrame* GetScrollContainerFrame(
    759      nsIFrame** aFrame = nullptr, FlushType aFlushType = FlushType::Layout);
    760 
    761 private:
    762  // Style state computed from element's state and style locks.
    763  ElementState StyleStateFromLocks() const;
    764 
    765  void NotifyStateChange(ElementState aStates);
    766  void NotifyStyleStateChange(ElementState aStates);
    767 
    768 public:
    769  struct AutoStateChangeNotifier {
    770    AutoStateChangeNotifier(Element& aElement, bool aNotify)
    771        : mElement(aElement), mOldState(aElement.State()), mNotify(aNotify) {}
    772    ~AutoStateChangeNotifier() {
    773      if (!mNotify) {
    774        return;
    775      }
    776      ElementState newState = mElement.State();
    777      if (mOldState != newState) {
    778        mElement.NotifyStateChange(mOldState ^ newState);
    779      }
    780    }
    781 
    782   private:
    783    Element& mElement;
    784    const ElementState mOldState;
    785    const bool mNotify;
    786  };
    787 
    788  // Method to add state bits.  This should be called from subclass constructors
    789  // to set up our event state correctly at construction time, and other places
    790  // where we don't want to notify a state change, or there's an
    791  // AutoStateChangeNotifier on the stack.
    792  void AddStatesSilently(ElementState aStates) { mState |= aStates; }
    793  // Method to remove state bits.  This should be called from subclass
    794  // constructors to set up our event state correctly at construction time and
    795  // other places where we don't want to notify a state change.
    796  void RemoveStatesSilently(ElementState aStates) { mState &= ~aStates; }
    797  // Methods to add state bits, potentially notifying. These will handle setting
    798  // up script blockers when they notify, so no need to do it in the callers
    799  // unless desired. States passed here must only be those in
    800  // EXTERNALLY_MANAGED_STATES.
    801  void AddStates(ElementState aStates, bool aNotify = true) {
    802    ElementState old = mState;
    803    AddStatesSilently(aStates);
    804    if (aNotify && old != mState) {
    805      NotifyStateChange(old ^ mState);
    806    }
    807  }
    808  void RemoveStates(ElementState aStates, bool aNotify = true) {
    809    ElementState old = mState;
    810    RemoveStatesSilently(aStates);
    811    if (aNotify && old != mState) {
    812      NotifyStateChange(old ^ mState);
    813    }
    814  }
    815  void SetStates(ElementState aStates, bool aSet, bool aNotify = true) {
    816    if (aSet) {
    817      AddStates(aStates, aNotify);
    818    } else {
    819      RemoveStates(aStates, aNotify);
    820    }
    821  }
    822  void ToggleStates(ElementState aStates, bool aNotify) {
    823    mState ^= aStates;
    824    if (aNotify) {
    825      NotifyStateChange(aStates);
    826    }
    827  }
    828 
    829  void UpdateEditableState(bool aNotify) override;
    830  // Makes sure that the READONLY/READWRITE flags are in sync.
    831  void UpdateReadOnlyState(bool aNotify);
    832  // Form controls and non-form controls should have different :read-only /
    833  // :read-write behavior. This is what effectively controls it.
    834  virtual bool IsReadOnlyInternal() const;
    835 
    836  /**
    837   * Normalizes an attribute name and returns it as a nodeinfo if an attribute
    838   * with that name exists. This method is intended for character case
    839   * conversion if the content object is case insensitive (e.g. HTML). Returns
    840   * the nodeinfo of the attribute with the specified name if one exists or
    841   * null otherwise.
    842   *
    843   * @param aStr the unparsed attribute string
    844   * @return the node info. May be nullptr.
    845   */
    846  already_AddRefed<mozilla::dom::NodeInfo> GetExistingAttrNameFromQName(
    847      const nsAString& aStr) const;
    848 
    849  /**
    850   * Helper for SetAttr/SetParsedAttr. This method will return true if aNotify
    851   * is true, this is a custom element, the attribute is currently set, and the
    852   * new value that is about to be set is different to the current value. As a
    853   * perf optimization the new and old values will not actually be compared if
    854   * we aren't notifying (in which case it's cheap to just return false and let
    855   * the caller go ahead and set the value).
    856   * @param aOldValue [out] Set to the old value of the attribute, but only if
    857   *   there are event listeners. If set, the type of aOldValue will be either
    858   *   nsAttrValue::eString or nsAttrValue::eAtom.
    859   * @param aModType [out] Set to AttrModType::Modification or to
    860   *   AttrModType::Addition, but only if this helper returns true
    861   * @param aOldValueSet [out] Indicates whether an old attribute value has been
    862   *   stored in aOldValue. The bool will be set to true if a value was stored.
    863   */
    864  bool MaybeCheckSameAttrVal(int32_t aNamespaceID, const nsAtom* aName,
    865                             const nsAtom* aPrefix,
    866                             const nsAttrValueOrString& aValue, bool aNotify,
    867                             nsAttrValue& aOldValue, AttrModType* aModType,
    868                             bool* aOldValueSet);
    869 
    870  /**
    871   * Notifies mutation observers if aNotify is true, there are mutation
    872   * observers, and the attribute value is changing.
    873   *
    874   * @param aNamespaceID The namespace of the attribute
    875   * @param aName The local name of the attribute
    876   * @param aPrefix The prefix of the attribute
    877   * @param aValue The value that the attribute is being changed to
    878   * @param aNotify If true, mutation listeners will be notified if they exist
    879   *   and the attribute value is changing
    880   * @param aOldValue [out] Set to the old value of the attribute, but only if
    881   *   there are event listeners. If set, the type of aOldValue will be either
    882   *   nsAttrValue::eString or nsAttrValue::eAtom.
    883   * @param aModType [out] Set to AttrModType::Modification or to
    884   *   AttrModType::Addition, but only if this helper returns true
    885   * @param aOldValueSet [out] Indicates whether an old attribute value has been
    886   *   stored in aOldValue. The bool will be set to true if a value was stored.
    887   */
    888  bool OnlyNotifySameValueSet(int32_t aNamespaceID, nsAtom* aName,
    889                              nsAtom* aPrefix,
    890                              const nsAttrValueOrString& aValue, bool aNotify,
    891                              nsAttrValue& aOldValue, AttrModType* aModType,
    892                              bool* aOldValueSet);
    893 
    894  /**
    895   * Sets the class attribute.
    896   * Assumes that we are not notifying and that the attribute hasn't been
    897   * set previously.
    898   */
    899  nsresult SetClassAttrFromParser(nsAtom* aValue);
    900 
    901  // aParsedValue receives the old value of the attribute. That's useful if
    902  // either the input or output value of aParsedValue is StoresOwnData.
    903  nsresult SetParsedAttr(int32_t aNameSpaceID, nsAtom* aName, nsAtom* aPrefix,
    904                         nsAttrValue& aParsedValue, bool aNotify);
    905  /**
    906   * Get the current value of the attribute. This returns a form that is
    907   * suitable for passing back into SetAttr.
    908   *
    909   * @param aNameSpaceID the namespace of the attr (defaults to
    910                         kNameSpaceID_None in the overload that omits this arg)
    911   * @param aName the name of the attr
    912   * @param aResult the value (may legitimately be the empty string) [OUT]
    913   * @returns true if the attribute was set (even when set to empty string)
    914   *          false when not set.
    915   * GetAttr is not inlined on purpose, to keep down codesize from all the
    916   * inlined nsAttrValue bits for C++ callers.
    917   */
    918  bool GetAttr(int32_t aNameSpaceID, const nsAtom* aName,
    919               nsAString& aResult) const;
    920  bool GetAttr(const nsAtom* aName, nsAString& aResult) const;
    921 
    922  /**
    923   * Determine if an attribute has been set (empty string or otherwise).
    924   *
    925   * @param aNameSpaceId the namespace id of the attribute (defaults to
    926                         kNameSpaceID_None in the overload that omits this arg)
    927   * @param aAttr the attribute name
    928   * @return whether an attribute exists
    929   */
    930  inline bool HasAttr(int32_t aNameSpaceID, const nsAtom* aName) const {
    931    return mAttrs.HasAttr(aNameSpaceID, aName);
    932  }
    933 
    934  bool HasAttr(const nsAtom* aAttr) const { return mAttrs.HasAttr(aAttr); }
    935 
    936  /**
    937   * Determine if an attribute has been set to a non-empty string value. If the
    938   * attribute is not set at all, this will return false.
    939   *
    940   * @param aNameSpaceId the namespace id of the attribute (defaults to
    941   *                     kNameSpaceID_None in the overload that omits this arg)
    942   * @param aAttr the attribute name
    943   */
    944  inline bool HasNonEmptyAttr(int32_t aNameSpaceID, const nsAtom* aName) const;
    945 
    946  bool HasNonEmptyAttr(const nsAtom* aAttr) const {
    947    return HasNonEmptyAttr(kNameSpaceID_None, aAttr);
    948  }
    949 
    950  /**
    951   * Test whether this Element's given attribute has the given value.  If the
    952   * attribute is not set at all, this will return false.
    953   *
    954   * @param aNameSpaceID The namespace ID of the attribute.  Must not
    955   *                     be kNameSpaceID_Unknown.
    956   * @param aName The name atom of the attribute.  Must not be null.
    957   * @param aValue The value to compare to.
    958   * @param aCaseSensitive Whether to do a case-sensitive compare on the value.
    959   */
    960  inline bool AttrValueIs(int32_t aNameSpaceID, const nsAtom* aName,
    961                          const nsAString& aValue,
    962                          nsCaseTreatment aCaseSensitive) const;
    963 
    964  /**
    965   * Test whether this Element's given attribute has the given value.  If the
    966   * attribute is not set at all, this will return false.
    967   *
    968   * @param aNameSpaceID The namespace ID of the attribute.  Must not
    969   *                     be kNameSpaceID_Unknown.
    970   * @param aName The name atom of the attribute.  Must not be null.
    971   * @param aValue The value to compare to.  Must not be null.
    972   * @param aCaseSensitive Whether to do a case-sensitive compare on the value.
    973   */
    974  bool AttrValueIs(int32_t aNameSpaceID, const nsAtom* aName,
    975                   const nsAtom* aValue, nsCaseTreatment aCaseSensitive) const;
    976 
    977  /**
    978   * Check whether this Element's given attribute has one of a given list of
    979   * values. If there is a match, we return the index in the list of the first
    980   * matching value. If there was no attribute at all, then we return
    981   * ATTR_MISSING. If there was an attribute but it didn't match, we return
    982   * ATTR_VALUE_NO_MATCH. A non-negative result always indicates a match.
    983   *
    984   * @param aNameSpaceID The namespace ID of the attribute.  Must not
    985   *                     be kNameSpaceID_Unknown.
    986   * @param aName The name atom of the attribute.  Must not be null.
    987   * @param aValues a nullptr-terminated array of pointers to atom values to
    988   * test against.
    989   * @param aCaseSensitive Whether to do a case-sensitive compare on the values.
    990   * @return ATTR_MISSING, ATTR_VALUE_NO_MATCH or the non-negative index
    991   * indicating the first value of aValues that matched
    992   */
    993  using AttrValuesArray = AttrArray::AttrValuesArray;
    994  int32_t FindAttrValueIn(int32_t aNameSpaceID, const nsAtom* aName,
    995                          AttrArray::AttrValuesArray* aValues,
    996                          nsCaseTreatment aCaseSensitive) const;
    997 
    998  /**
    999   * Set attribute values. All attribute values are assumed to have a
   1000   * canonical string representation that can be used for these
   1001   * methods. The SetAttr method is assumed to perform a translation
   1002   * of the canonical form into the underlying content specific
   1003   * form.
   1004   *
   1005   * @param aNameSpaceID the namespace of the attribute
   1006   * @param aName the name of the attribute
   1007   * @param aValue the value to set
   1008   * @param aNotify specifies how whether or not the document should be
   1009   *        notified of the attribute change.
   1010   */
   1011  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName, const nsAString& aValue,
   1012                   bool aNotify) {
   1013    return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
   1014  }
   1015  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName, nsAtom* aPrefix,
   1016                   const nsAString& aValue, bool aNotify) {
   1017    return SetAttr(aNameSpaceID, aName, aPrefix, aValue, nullptr, aNotify);
   1018  }
   1019  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName, const nsAString& aValue,
   1020                   nsIPrincipal* aTriggeringPrincipal, bool aNotify) {
   1021    return SetAttr(aNameSpaceID, aName, nullptr, aValue, aTriggeringPrincipal,
   1022                   aNotify);
   1023  }
   1024 
   1025  /**
   1026   * Set attribute values. All attribute values are assumed to have a
   1027   * canonical String representation that can be used for these
   1028   * methods. The SetAttr method is assumed to perform a translation
   1029   * of the canonical form into the underlying content specific
   1030   * form.
   1031   *
   1032   * @param aNameSpaceID the namespace of the attribute
   1033   * @param aName the name of the attribute
   1034   * @param aPrefix the prefix of the attribute
   1035   * @param aValue the value to set
   1036   * @param aMaybeScriptedPrincipal the principal of the scripted caller
   1037   * responsible for setting the attribute, or null if no scripted caller can be
   1038   *        determined. A null value here does not guarantee that there is no
   1039   *        scripted caller, but a non-null value does guarantee that a scripted
   1040   *        caller with the given principal is directly responsible for the
   1041   *        attribute change.
   1042   * @param aNotify specifies how whether or not the document should be
   1043   *        notified of the attribute change.
   1044   */
   1045  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName, nsAtom* aPrefix,
   1046                   const nsAString& aValue,
   1047                   nsIPrincipal* aMaybeScriptedPrincipal, bool aNotify);
   1048 
   1049  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName, nsAtom* aPrefix,
   1050                   nsAtom* aValue, nsIPrincipal* aMaybeScriptedPrincipal,
   1051                   bool aNotify);
   1052 
   1053  /**
   1054   * Remove an attribute so that it is no longer explicitly specified.
   1055   *
   1056   * @param aNameSpaceID the namespace id of the attribute
   1057   * @param aName the name of the attribute to unset
   1058   * @param aNotify specifies whether or not the document should be
   1059   * notified of the attribute change
   1060   */
   1061  nsresult UnsetAttr(int32_t aNameSpaceID, nsAtom* aName, bool aNotify);
   1062 
   1063  /**
   1064   * Swap an attribute value. This is a public wrapper that ensures bloom
   1065   * filter updates are performed correctly. For kNameSpaceID_None attributes,
   1066   * this will automatically update the bloom filter and propagate changes to
   1067   * parent elements.
   1068   *
   1069   * @param aLocalName the local name of the attribute
   1070   * @param aValue the value to swap (will contain old value on return)
   1071   * @param aHadValue set to true if attribute existed, false otherwise
   1072   */
   1073  nsresult SetAndSwapAttr(nsAtom* aLocalName, nsAttrValue& aValue,
   1074                          bool* aHadValue);
   1075 
   1076  /**
   1077   * Swap an attribute value. This is a public wrapper that ensures bloom
   1078   * filter updates are performed correctly. For kNameSpaceID_None attributes,
   1079   * this will automatically update the bloom filter and propagate changes to
   1080   * parent elements.
   1081   *
   1082   * @param aName the node info of the attribute
   1083   * @param aValue the value to swap (will contain old value on return)
   1084   * @param aHadValue set to true if attribute existed, false otherwise
   1085   */
   1086  nsresult SetAndSwapAttr(mozilla::dom::NodeInfo* aName, nsAttrValue& aValue,
   1087                          bool* aHadValue);
   1088 
   1089  /**
   1090   * Get the namespace / name / prefix of a given attribute.
   1091   *
   1092   * @param   aIndex the index of the attribute name
   1093   * @returns The name at the given index.
   1094   * @note    The document returned by NodeInfo()->GetDocument() (if one is
   1095   *          present) is *not* necessarily the owner document of the element.
   1096   * @note    The pointer returned by this function is only valid until the
   1097   *          next call of either GetAttrNameAt or SetAttr on the element.
   1098   * @note    This will crash if the index is invalid.
   1099   */
   1100  const nsAttrName* GetAttrNameAt(uint32_t aIndex) const {
   1101    return mAttrs.GetSafeAttrNameAt(aIndex);
   1102  }
   1103 
   1104  /**
   1105   * Same as above, but does not do out-of-bounds checks!
   1106   */
   1107  const nsAttrName* GetUnsafeAttrNameAt(uint32_t aIndex) const {
   1108    return mAttrs.AttrNameAt(aIndex);
   1109  }
   1110 
   1111  /**
   1112   * A fallible overload of GetAttrNameAt.
   1113   */
   1114  [[nodiscard]] bool GetAttrNameAt(uint32_t aIndex,
   1115                                   const nsAttrName** aResult) const {
   1116    return mAttrs.GetSafeAttrNameAt(aIndex, aResult);
   1117  }
   1118 
   1119  /**
   1120   * Gets the attribute info (name and value) for this element at a given index.
   1121   */
   1122  BorrowedAttrInfo GetAttrInfoAt(uint32_t aIndex) const {
   1123    if (aIndex >= mAttrs.AttrCount()) {
   1124      return BorrowedAttrInfo(nullptr, nullptr);
   1125    }
   1126 
   1127    return mAttrs.AttrInfoAt(aIndex);
   1128  }
   1129 
   1130  /**
   1131   * Get the number of all specified attributes.
   1132   *
   1133   * @return the number of attributes
   1134   */
   1135  uint32_t GetAttrCount() const { return mAttrs.AttrCount(); }
   1136 
   1137  /**
   1138   * Get the class list of this element (this corresponds to the value of the
   1139   * class attribute).  This may be null if there are no classes, but that's not
   1140   * guaranteed (e.g. we could have class="").
   1141   */
   1142  const nsAttrValue* GetClasses() const {
   1143    if (!MayHaveClass()) {
   1144      return nullptr;
   1145    }
   1146 
   1147    if (IsSVGElement()) {
   1148      if (const nsAttrValue* value = GetSVGAnimatedClass()) {
   1149        return value;
   1150      }
   1151    }
   1152 
   1153    return GetParsedAttr(nsGkAtoms::_class);
   1154  }
   1155 
   1156 #ifdef MOZ_DOM_LIST
   1157  virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override {
   1158    List(out, aIndent, ""_ns);
   1159  }
   1160  virtual void DumpContent(FILE* out, int32_t aIndent,
   1161                           bool aDumpAll) const override;
   1162  void List(FILE* out, int32_t aIndent, const nsCString& aPrefix) const;
   1163  void ListAttributes(FILE* out) const;
   1164 #endif
   1165 
   1166  /**
   1167   * Append to aOutDescription a string describing the element and its
   1168   * attributes.
   1169   * If aShort is true, only the id and class attributes will be listed.
   1170   */
   1171  void Describe(nsAString& aOutDescription, bool aShort = false) const;
   1172 
   1173  /*
   1174   * Attribute Mapping Helpers
   1175   */
   1176  struct MappedAttributeEntry {
   1177    const nsStaticAtom* const attribute;
   1178  };
   1179 
   1180  /**
   1181   * A common method where you can just pass in a list of maps to check
   1182   * for attribute dependence. Most implementations of
   1183   * IsAttributeMapped should use this function as a default
   1184   * handler.
   1185   */
   1186  template <size_t N>
   1187  static bool FindAttributeDependence(
   1188      const nsAtom* aAttribute, const MappedAttributeEntry* const (&aMaps)[N]) {
   1189    return FindAttributeDependence(aAttribute, aMaps, N);
   1190  }
   1191 
   1192  // https://html.spec.whatwg.org/#attr-button-command
   1193  enum class Command : uint8_t {
   1194    Invalid,
   1195    Custom,
   1196    TogglePopover,
   1197    ShowPopover,
   1198    HidePopover,
   1199    ShowModal,
   1200    RequestClose,
   1201    Toggle,
   1202    Close,
   1203    Open,
   1204  };
   1205 
   1206  virtual bool IsValidCommandAction(Command aCommand) const { return false; }
   1207 
   1208  /**
   1209   * Elements can provide their own default behaviours for "Invoke" (see
   1210   * command/commandfor attributes).
   1211   * If the action is not recognised, they can choose to ignore it and `return
   1212   * false`. If an action is recognised then they should `return true` to
   1213   * indicate to sub-classes that this has been handled and no further steps
   1214   * should be run.
   1215   */
   1216  MOZ_CAN_RUN_SCRIPT virtual bool HandleCommandInternal(Element* aSource,
   1217                                                        Command aCommand,
   1218                                                        ErrorResult& aRv) {
   1219    return false;
   1220  }
   1221 
   1222 private:
   1223  void DescribeAttribute(uint32_t index, nsAString& aOutDescription) const;
   1224 
   1225  static bool FindAttributeDependence(const nsAtom* aAttribute,
   1226                                      const MappedAttributeEntry* const aMaps[],
   1227                                      uint32_t aMapCount);
   1228 
   1229  bool HasSharedRoot(const Element* aElement) const;
   1230 
   1231  Element* GetElementByIdInDocOrSubtree(nsAtom* aID) const;
   1232 
   1233 protected:
   1234  inline bool GetAttr(const nsAtom* aName, DOMString& aResult) const {
   1235    MOZ_ASSERT(aResult.IsEmpty(), "Should have empty string coming in");
   1236    const nsAttrValue* val = mAttrs.GetAttr(aName);
   1237    if (!val) {
   1238      return false;  // DOMString comes pre-emptied.
   1239    }
   1240    val->ToString(aResult);
   1241    return true;
   1242  }
   1243 
   1244  inline bool GetAttr(int32_t aNameSpaceID, const nsAtom* aName,
   1245                      DOMString& aResult) const {
   1246    MOZ_ASSERT(aResult.IsEmpty(), "Should have empty string coming in");
   1247    const nsAttrValue* val = mAttrs.GetAttr(aName, aNameSpaceID);
   1248    if (!val) {
   1249      return false;  // DOMString comes pre-emptied.
   1250    }
   1251    val->ToString(aResult);
   1252    return true;
   1253  }
   1254 
   1255 public:
   1256  bool HasAttrs() const { return mAttrs.HasAttrs(); }
   1257 
   1258  inline bool GetAttr(const nsAString& aName, DOMString& aResult) const {
   1259    MOZ_ASSERT(aResult.IsEmpty(), "Should have empty string coming in");
   1260    const nsAttrValue* val = mAttrs.GetAttr(aName);
   1261    if (val) {
   1262      val->ToString(aResult);
   1263      return true;
   1264    }
   1265    // else DOMString comes pre-emptied.
   1266    return false;
   1267  }
   1268 
   1269  // Note, this does not notify about the removal.
   1270  void ClearAttributes() { mAttrs.Clear(); }
   1271 
   1272  void GetTagName(nsAString& aTagName) const { aTagName = NodeName(); }
   1273  void GetId(nsAString& aId) const { GetAttr(nsGkAtoms::id, aId); }
   1274  void GetId(DOMString& aId) const { GetAttr(nsGkAtoms::id, aId); }
   1275  void SetId(const nsAString& aId) {
   1276    SetAttr(kNameSpaceID_None, nsGkAtoms::id, aId, true);
   1277  }
   1278  void GetClassName(nsAString& aClassName) {
   1279    GetAttr(nsGkAtoms::_class, aClassName);
   1280  }
   1281  void GetClassName(DOMString& aClassName) {
   1282    GetAttr(nsGkAtoms::_class, aClassName);
   1283  }
   1284  void SetClassName(const nsAString& aClassName) {
   1285    SetAttr(kNameSpaceID_None, nsGkAtoms::_class, aClassName, true);
   1286  }
   1287 
   1288  nsDOMTokenList* ClassList();
   1289  nsDOMTokenList* Part();
   1290 
   1291  nsDOMAttributeMap* Attributes();
   1292 
   1293  void GetAttributeNames(nsTArray<nsString>& aResult);
   1294 
   1295  void GetAttribute(const nsAString& aName, nsAString& aReturn) {
   1296    DOMString str;
   1297    GetAttribute(aName, str);
   1298    str.ToString(aReturn);
   1299  }
   1300 
   1301  void GetAttribute(const nsAString& aName, DOMString& aReturn);
   1302  void GetAttributeNS(const nsAString& aNamespaceURI,
   1303                      const nsAString& aLocalName, nsAString& aReturn);
   1304  bool ToggleAttribute(const nsAString& aName, const Optional<bool>& aForce,
   1305                       nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError);
   1306  void SetAttribute(const nsAString& aName, const nsAString& aValue,
   1307                    nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError);
   1308  void SetAttributeNS(const nsAString& aNamespaceURI,
   1309                      const nsAString& aLocalName, const nsAString& aValue,
   1310                      nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError);
   1311  void SetAttribute(const nsAString& aName, const nsAString& aValue,
   1312                    ErrorResult& aError) {
   1313    SetAttribute(aName, aValue, nullptr, aError);
   1314  }
   1315 
   1316  MOZ_CAN_RUN_SCRIPT void SetAttribute(
   1317      const nsAString& aName,
   1318      const TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString& aValue,
   1319      nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError);
   1320  MOZ_CAN_RUN_SCRIPT void SetAttributeNS(
   1321      const nsAString& aNamespaceURI, const nsAString& aLocalName,
   1322      const TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString& aValue,
   1323      nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError);
   1324  MOZ_CAN_RUN_SCRIPT void SetAttribute(
   1325      const nsAString& aName,
   1326      const TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString& aValue,
   1327      ErrorResult& aError) {
   1328    SetAttribute(aName, aValue, nullptr, aError);
   1329  }
   1330 
   1331  /**
   1332   * This method creates a principal that subsumes this element's NodePrincipal
   1333   * and which has flags set for elevated permissions that devtools needs to
   1334   * operate on this element. The principal returned by this method is used by
   1335   * various devtools methods to permit otherwise blocked operations, without
   1336   * changing any other restrictions the NodePrincipal might have.
   1337   */
   1338  already_AddRefed<nsIPrincipal> CreateDevtoolsPrincipal();
   1339  void SetAttributeDevtools(const nsAString& aName, const nsAString& aValue,
   1340                            ErrorResult& aError);
   1341  void SetAttributeDevtoolsNS(const nsAString& aNamespaceURI,
   1342                              const nsAString& aLocalName,
   1343                              const nsAString& aValue, ErrorResult& aError);
   1344 
   1345  void RemoveAttribute(const nsAString& aName, ErrorResult& aError);
   1346  void RemoveAttributeNS(const nsAString& aNamespaceURI,
   1347                         const nsAString& aLocalName, ErrorResult& aError);
   1348  bool HasAttribute(const nsAString& aName) const {
   1349    return InternalGetAttrNameFromQName(aName) != nullptr;
   1350  }
   1351  bool HasAttributeNS(const nsAString& aNamespaceURI,
   1352                      const nsAString& aLocalName) const;
   1353  bool HasAttributes() const { return HasAttrs(); }
   1354  Element* Closest(const nsACString& aSelector, ErrorResult& aResult);
   1355  bool Matches(const nsACString& aSelector, ErrorResult& aError);
   1356  already_AddRefed<nsIHTMLCollection> GetElementsByTagName(
   1357      const nsAString& aQualifiedName);
   1358  already_AddRefed<nsIHTMLCollection> GetElementsByTagNameNS(
   1359      const nsAString& aNamespaceURI, const nsAString& aLocalName,
   1360      ErrorResult& aError);
   1361  already_AddRefed<nsIHTMLCollection> GetElementsByClassName(
   1362      const nsAString& aClassNames);
   1363 
   1364  /**
   1365   * Returns attribute associated element for the given attribute name, see
   1366   * https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#attr-associated-element
   1367   */
   1368  Element* GetAttrAssociatedElement(nsAtom* aAttr) const;
   1369  void GetAttrAssociatedElements(
   1370      nsAtom* aAttr, bool* aUseCachedValue,
   1371      Nullable<nsTArray<RefPtr<Element>>>& aElements);
   1372 
   1373  /**
   1374   * Sets an attribute element for the given attribute.
   1375   * https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#explicitly-set-attr-element
   1376   */
   1377  void ExplicitlySetAttrElement(nsAtom* aAttr, Element* aElement);
   1378  void ExplicitlySetAttrElements(
   1379      nsAtom* aAttr,
   1380      const Nullable<Sequence<OwningNonNull<Element>>>& aElements);
   1381 
   1382  void ClearExplicitlySetAttrElement(nsAtom*);
   1383  void ClearExplicitlySetAttrElements(nsAtom*);
   1384 
   1385  /**
   1386   * Gets the attribute element for the given attribute.
   1387   * https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#explicitly-set-attr-element
   1388   * Unlike GetAttrAssociatedElement, this returns the target even if it isn't
   1389   * a descendant of any of this element's shadow-including ancestors. It also
   1390   * doesn't attempt to retrieve an element using a string id set in the content
   1391   * attribute.
   1392   */
   1393  Element* GetExplicitlySetAttrElement(nsAtom* aAttr) const;
   1394 
   1395  /**
   1396   * Gets the attribute elements for the given attribute. Unlike
   1397   * GetAttrAssociatedElements, this returns an uncached array of explicitly set
   1398   * elements without checking if they are a descendant of any of this element's
   1399   * shadow-including ancestors. It also does not attempt to retrieve elements
   1400   * using the ids set in the content attribute.
   1401   */
   1402  void GetExplicitlySetAttrElements(nsAtom* aAttr,
   1403                                    nsTArray<Element*>& aElements) const;
   1404 
   1405  PseudoStyleType GetPseudoElementType() const {
   1406    nsresult rv = NS_OK;
   1407    auto raw = GetProperty(nsGkAtoms::pseudoProperty, &rv);
   1408    if (rv == NS_PROPTABLE_PROP_NOT_THERE) {
   1409      return PseudoStyleType::NotPseudo;
   1410    }
   1411    return PseudoStyleType(reinterpret_cast<uintptr_t>(raw));
   1412  }
   1413 
   1414  void SetPseudoElementType(PseudoStyleType aPseudo) {
   1415    static_assert(sizeof(PseudoStyleType) <= sizeof(uintptr_t),
   1416                  "Need to be able to store this in a void*");
   1417    MOZ_ASSERT(PseudoStyle::IsPseudoElement(aPseudo));
   1418    SetProperty(nsGkAtoms::pseudoProperty, reinterpret_cast<void*>(aPseudo));
   1419  }
   1420 
   1421  /**
   1422   * Return an array of all elements in the subtree rooted at this
   1423   * element that have grid container frames. This does not include
   1424   * pseudo-elements.
   1425   */
   1426  void GetElementsWithGrid(nsTArray<RefPtr<Element>>& aElements);
   1427 
   1428  /**
   1429   * Provide a direct way to determine if this Element has visible
   1430   * scrollbars. Flushes layout.
   1431   */
   1432  MOZ_CAN_RUN_SCRIPT bool HasVisibleScrollbars();
   1433 
   1434  /**
   1435   * Get an editor which handles user inputs when this element has focus.
   1436   * If this is a text control, return a TextEditor if it's already created and
   1437   * it's not in the design mode.
   1438   * If this is editable, return HTMLEditor which should've already been
   1439   * created.
   1440   * Otherwise, return nullptr.
   1441   */
   1442  EditorBase* GetExtantEditor() const;
   1443 
   1444 private:
   1445  /**
   1446   * Implement the algorithm specified at
   1447   * https://dom.spec.whatwg.org/#insert-adjacent for both
   1448   * |insertAdjacentElement()| and |insertAdjacentText()| APIs.
   1449   */
   1450  nsINode* InsertAdjacent(const nsAString& aWhere, nsINode* aNode,
   1451                          ErrorResult& aError);
   1452 
   1453 public:
   1454  Element* InsertAdjacentElement(const nsAString& aWhere, Element& aElement,
   1455                                 ErrorResult& aError);
   1456 
   1457  void InsertAdjacentText(const nsAString& aWhere, const nsAString& aData,
   1458                          ErrorResult& aError);
   1459 
   1460  void SetPointerCapture(int32_t aPointerId, ErrorResult& aError);
   1461  void ReleasePointerCapture(int32_t aPointerId, ErrorResult& aError);
   1462  bool HasPointerCapture(long aPointerId);
   1463  void SetCapture(bool aRetargetToElement);
   1464 
   1465  void SetCaptureAlways(bool aRetargetToElement);
   1466 
   1467  void ReleaseCapture();
   1468 
   1469  already_AddRefed<Promise> RequestFullscreen(CallerType, ErrorResult&);
   1470  void RequestPointerLock(CallerType aCallerType);
   1471  Attr* GetAttributeNode(const nsAString& aName);
   1472  MOZ_CAN_RUN_SCRIPT already_AddRefed<Attr> SetAttributeNode(
   1473      Attr& aNewAttr, nsIPrincipal* aSubjectPrincipal, ErrorResult& aError);
   1474  already_AddRefed<Attr> RemoveAttributeNode(Attr& aOldAttr,
   1475                                             ErrorResult& aError);
   1476  Attr* GetAttributeNodeNS(const nsAString& aNamespaceURI,
   1477                           const nsAString& aLocalName);
   1478  MOZ_CAN_RUN_SCRIPT already_AddRefed<Attr> SetAttributeNodeNS(
   1479      Attr& aNewAttr, nsIPrincipal* aSubjectPrincipal, ErrorResult& aError);
   1480 
   1481  MOZ_CAN_RUN_SCRIPT already_AddRefed<DOMRectList> GetClientRects();
   1482  MOZ_CAN_RUN_SCRIPT already_AddRefed<DOMRect> GetBoundingClientRect();
   1483 
   1484  enum class Loading : uint8_t {
   1485    Eager,
   1486    Lazy,
   1487  };
   1488 
   1489  Loading LoadingState() const;
   1490  void GetLoading(nsAString& aValue) const;
   1491  bool ParseLoadingAttribute(const nsAString& aValue, nsAttrValue& aResult);
   1492 
   1493  // https://html.spec.whatwg.org/#potentially-render-blocking
   1494  virtual bool IsPotentiallyRenderBlocking() { return false; }
   1495  bool BlockingContainsRender() const;
   1496 
   1497  // Shadow DOM v1
   1498  enum class ShadowRootDeclarative : bool { No, Yes };
   1499 
   1500  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   1501  already_AddRefed<ShadowRoot> AttachShadow(const ShadowRootInit& aInit,
   1502                                            ErrorResult& aError);
   1503  bool CanAttachShadowDOM() const;
   1504 
   1505  enum class DelegatesFocus : bool { No, Yes };
   1506  enum class ShadowRootClonable : bool { No, Yes };
   1507  enum class ShadowRootSerializable : bool { No, Yes };
   1508 
   1509  already_AddRefed<ShadowRoot> AttachShadowWithoutNameChecks(
   1510      ShadowRootMode aMode, DelegatesFocus = DelegatesFocus::No,
   1511      SlotAssignmentMode aSlotAssignmentMode = SlotAssignmentMode::Named,
   1512      ShadowRootClonable aClonable = ShadowRootClonable::No,
   1513      ShadowRootSerializable aSerializable = ShadowRootSerializable::No,
   1514      const nsAString& aReferenceTarget = EmptyString());
   1515 
   1516  // Attach UA Shadow Root if it is not attached.
   1517  enum class NotifyUAWidgetSetup : bool { No, Yes };
   1518  void AttachAndSetUAShadowRoot(NotifyUAWidgetSetup = NotifyUAWidgetSetup::Yes,
   1519                                DelegatesFocus = DelegatesFocus::No);
   1520 
   1521  // Dispatch an event to UAWidgetsChild, triggering construction
   1522  // or onchange callback on the existing widget.
   1523  void NotifyUAWidgetSetupOrChange();
   1524 
   1525  enum class UnattachShadowRoot {
   1526    No,
   1527    Yes,
   1528  };
   1529 
   1530  // Dispatch an event to UAWidgetsChild, triggering UA Widget destruction.
   1531  // and optionally remove the shadow root.
   1532  void NotifyUAWidgetTeardown(UnattachShadowRoot = UnattachShadowRoot::Yes);
   1533 
   1534  void UnattachShadow();
   1535 
   1536  ShadowRoot* GetShadowRootByMode() const;
   1537  void SetSlot(const nsAString& aName, ErrorResult& aError);
   1538  void GetSlot(nsAString& aName);
   1539 
   1540  ShadowRoot* GetShadowRoot() const {
   1541    const nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
   1542    return slots ? slots->mShadowRoot.get() : nullptr;
   1543  }
   1544 
   1545  const Maybe<float> GetLastRememberedBSize() const {
   1546    const nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
   1547    return slots ? slots->mLastRememberedBSize : Nothing();
   1548  }
   1549  const Maybe<float> GetLastRememberedISize() const {
   1550    const nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
   1551    return slots ? slots->mLastRememberedISize : Nothing();
   1552  }
   1553  bool HasLastRememberedBSize() const {
   1554    return GetLastRememberedBSize().isSome();
   1555  }
   1556  bool HasLastRememberedISize() const {
   1557    return GetLastRememberedISize().isSome();
   1558  }
   1559 
   1560  const Maybe<ContentRelevancy> GetContentRelevancy() const {
   1561    const auto* slots = GetExistingExtendedDOMSlots();
   1562    return slots ? slots->mContentRelevancy : Nothing();
   1563  }
   1564  void SetContentRelevancy(ContentRelevancy relevancy) {
   1565    ExtendedDOMSlots()->mContentRelevancy = Some(relevancy);
   1566  }
   1567 
   1568  const Maybe<bool> GetVisibleForContentVisibility() const {
   1569    const auto* slots = GetExistingExtendedDOMSlots();
   1570    return slots ? slots->mVisibleForContentVisibility : Nothing();
   1571  }
   1572  void SetVisibleForContentVisibility(bool visible) {
   1573    ExtendedDOMSlots()->mVisibleForContentVisibility = Some(visible);
   1574  }
   1575 
   1576  void ClearContentRelevancy() {
   1577    if (auto* slots = GetExistingExtendedDOMSlots()) {
   1578      slots->mContentRelevancy.reset();
   1579      slots->mVisibleForContentVisibility.reset();
   1580      slots->mTemporarilyVisibleForScrolledIntoViewDescendant = false;
   1581    }
   1582  }
   1583 
   1584  bool TemporarilyVisibleForScrolledIntoViewDescendant() const {
   1585    const auto* slots = GetExistingExtendedDOMSlots();
   1586    return slots && slots->mTemporarilyVisibleForScrolledIntoViewDescendant;
   1587  }
   1588 
   1589  void SetTemporarilyVisibleForScrolledIntoViewDescendant(bool aVisible) {
   1590    ExtendedDOMSlots()->mTemporarilyVisibleForScrolledIntoViewDescendant =
   1591        aVisible;
   1592  }
   1593 
   1594  // https://drafts.csswg.org/cssom-view-1/#dom-element-checkvisibility
   1595  MOZ_CAN_RUN_SCRIPT bool CheckVisibility(const CheckVisibilityOptions&);
   1596 
   1597 private:
   1598  // DO NOT USE THIS FUNCTION directly in C++. This function is supposed to be
   1599  // called from JS. Use PresShell::ScrollContentIntoView instead.
   1600  MOZ_CAN_RUN_SCRIPT void ScrollIntoView(const ScrollIntoViewOptions& aOptions);
   1601 
   1602 public:
   1603  MOZ_CAN_RUN_SCRIPT
   1604  // DO NOT USE THIS FUNCTION directly in C++. This function is supposed to be
   1605  // called from JS. Use PresShell::ScrollContentIntoView instead.
   1606  void ScrollIntoView(const BooleanOrScrollIntoViewOptions& aObject);
   1607  MOZ_CAN_RUN_SCRIPT void ScrollTo(double aXScroll, double aYScroll);
   1608  MOZ_CAN_RUN_SCRIPT void ScrollTo(const ScrollToOptions& aOptions);
   1609  MOZ_CAN_RUN_SCRIPT void ScrollBy(double aXScrollDif, double aYScrollDif);
   1610  MOZ_CAN_RUN_SCRIPT void ScrollBy(const ScrollToOptions& aOptions);
   1611  MOZ_CAN_RUN_SCRIPT double ScrollTop();
   1612  MOZ_CAN_RUN_SCRIPT void SetScrollTop(double aScrollTop);
   1613  MOZ_CAN_RUN_SCRIPT double ScrollLeft();
   1614  MOZ_CAN_RUN_SCRIPT void SetScrollLeft(double aScrollLeft);
   1615  MOZ_CAN_RUN_SCRIPT int32_t ScrollWidth();
   1616  MOZ_CAN_RUN_SCRIPT int32_t ScrollHeight();
   1617  MOZ_CAN_RUN_SCRIPT void MozScrollSnap();
   1618  MOZ_CAN_RUN_SCRIPT int32_t ClientTop() {
   1619    return CSSPixel::FromAppUnits(GetClientAreaRect().y).Rounded();
   1620  }
   1621  MOZ_CAN_RUN_SCRIPT int32_t ClientLeft() {
   1622    return CSSPixel::FromAppUnits(GetClientAreaRect().x).Rounded();
   1623  }
   1624  MOZ_CAN_RUN_SCRIPT int32_t ClientWidth() {
   1625    return CSSPixel::FromAppUnits(GetClientAreaRect().Width()).Rounded();
   1626  }
   1627  MOZ_CAN_RUN_SCRIPT int32_t ClientHeight() {
   1628    return CSSPixel::FromAppUnits(GetClientAreaRect().Height()).Rounded();
   1629  }
   1630 
   1631  MOZ_CAN_RUN_SCRIPT int32_t ScreenX();
   1632  MOZ_CAN_RUN_SCRIPT int32_t ScreenY();
   1633  MOZ_CAN_RUN_SCRIPT already_AddRefed<nsIScreen> GetScreen();
   1634 
   1635  MOZ_CAN_RUN_SCRIPT double ScrollTopMin();
   1636  MOZ_CAN_RUN_SCRIPT double ScrollTopMax();
   1637  MOZ_CAN_RUN_SCRIPT double ScrollLeftMin();
   1638  MOZ_CAN_RUN_SCRIPT double ScrollLeftMax();
   1639 
   1640  MOZ_CAN_RUN_SCRIPT double ClientHeightDouble() {
   1641    return CSSPixel::FromAppUnits(GetClientAreaRect().Height());
   1642  }
   1643 
   1644  MOZ_CAN_RUN_SCRIPT double ClientWidthDouble() {
   1645    return CSSPixel::FromAppUnits(GetClientAreaRect().Width());
   1646  }
   1647 
   1648  MOZ_CAN_RUN_SCRIPT double CurrentCSSZoom();
   1649 
   1650  Element* GetOffsetParent() {
   1651    CSSIntRect rcFrame;
   1652    return GetOffsetRect(rcFrame);
   1653  }
   1654  int32_t OffsetTop() {
   1655    CSSIntRect rcFrame;
   1656    GetOffsetRect(rcFrame);
   1657    return rcFrame.y;
   1658  }
   1659  int32_t OffsetLeft() {
   1660    CSSIntRect rcFrame;
   1661    GetOffsetRect(rcFrame);
   1662    return rcFrame.x;
   1663  }
   1664  int32_t OffsetWidth() {
   1665    CSSIntRect rcFrame;
   1666    GetOffsetRect(rcFrame);
   1667    return rcFrame.Width();
   1668  }
   1669  int32_t OffsetHeight() {
   1670    CSSIntRect rcFrame;
   1671    GetOffsetRect(rcFrame);
   1672    return rcFrame.Height();
   1673  }
   1674  /**
   1675   * Get the frame's offset information for offsetTop/Left/Width/Height.
   1676   * Returns the parent the offset is relative to.
   1677   * @note This method flushes pending notifications (FlushType::Layout).
   1678   * @param aRect the offset information [OUT]
   1679   */
   1680  Element* GetOffsetRect(CSSIntRect& aRect);
   1681 
   1682  // This function will return the block size of first line box, no matter if
   1683  // the box is 'block' or 'inline'. The return unit is pixel. If the element
   1684  // can't get a primary frame, we will return be zero.
   1685  double FirstLineBoxBSize() const;
   1686 
   1687  already_AddRefed<Flex> GetAsFlexContainer();
   1688  void GetGridFragments(nsTArray<RefPtr<Grid>>& aResult);
   1689 
   1690  bool HasGridFragments();
   1691 
   1692  already_AddRefed<DOMMatrixReadOnly> GetTransformToAncestor(
   1693      Element& aAncestor);
   1694  already_AddRefed<DOMMatrixReadOnly> GetTransformToParent();
   1695  already_AddRefed<DOMMatrixReadOnly> GetTransformToViewport();
   1696 
   1697  already_AddRefed<Animation> Animate(
   1698      JSContext* aContext, JS::Handle<JSObject*> aKeyframes,
   1699      const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
   1700      ErrorResult& aError);
   1701 
   1702  MOZ_CAN_RUN_SCRIPT
   1703  void GetAnimations(const GetAnimationsOptions& aOptions,
   1704                     nsTArray<RefPtr<Animation>>& aAnimations);
   1705 
   1706  void GetAnimationsWithoutFlush(const GetAnimationsOptions& aOptions,
   1707                                 nsTArray<RefPtr<Animation>>& aAnimations);
   1708 
   1709  void CloneAnimationsFrom(const Element& aOther);
   1710 
   1711  virtual void GetInnerHTML(nsAString& aInnerHTML, OOMReporter& aError);
   1712 
   1713  // https://html.spec.whatwg.org/#dom-parsing-and-serialization:dom-element-innerhtml
   1714  // @param aInnerHTML will always be of type `NullIsEmptyString`.
   1715  void GetInnerHTML(OwningTrustedHTMLOrNullIsEmptyString& aInnerHTML,
   1716                    OOMReporter& aError);
   1717 
   1718  // https://html.spec.whatwg.org/#dom-parsing-and-serialization:dom-element-innerhtml
   1719  //
   1720  // May only run script if aInnerHTML is a string. If this behavior changes,
   1721  // callees might need adjusting.
   1722  MOZ_CAN_RUN_SCRIPT void SetInnerHTML(
   1723      const TrustedHTMLOrNullIsEmptyString& aInnerHTML,
   1724      nsIPrincipal* aSubjectPrincipal, ErrorResult& aError);
   1725 
   1726  // Call this method only with trusted, i.e. non-attacker-controlled, strings.
   1727  virtual void SetInnerHTMLTrusted(const nsAString& aInnerHTML,
   1728                                   nsIPrincipal* aSubjectPrincipal,
   1729                                   ErrorResult& aError);
   1730 
   1731  // @param aOuterHTML will always be of type `NullIsEmptyString`.
   1732  void GetOuterHTML(OwningTrustedHTMLOrNullIsEmptyString& aOuterHTML);
   1733 
   1734  MOZ_CAN_RUN_SCRIPT void SetOuterHTML(
   1735      const TrustedHTMLOrNullIsEmptyString& aOuterHTML,
   1736      nsIPrincipal* aSubjectPrincipal, ErrorResult& aError);
   1737 
   1738  MOZ_CAN_RUN_SCRIPT void InsertAdjacentHTML(
   1739      const nsAString& aPosition,
   1740      const TrustedHTMLOrString& aTrustedHTMLOrString,
   1741      nsIPrincipal* aSubjectPrincipal, ErrorResult& aError);
   1742 
   1743  virtual void SetHTML(const nsAString& aInnerHTML,
   1744                       const SetHTMLOptions& aOptions, ErrorResult& aError);
   1745 
   1746  MOZ_CAN_RUN_SCRIPT
   1747  virtual void SetHTMLUnsafe(const TrustedHTMLOrString& aHTML,
   1748                             const SetHTMLUnsafeOptions& aOptions,
   1749                             nsIPrincipal* aSubjectPrincipal,
   1750                             ErrorResult& aError);
   1751 
   1752  void GetHTML(const GetHTMLOptions& aOptions, nsAString& aResult);
   1753 
   1754  StylePropertyMapReadOnly* ComputedStyleMap();
   1755 
   1756  //----------------------------------------
   1757 
   1758  /**
   1759   * Add a script event listener with the given event handler name
   1760   * (like onclick) and with the value as JS
   1761   * @param aEventName the event listener name
   1762   * @param aValue the JS to attach
   1763   * @param aDefer indicates if deferred execution is allowed
   1764   */
   1765  void SetEventHandler(nsAtom* aEventName, const nsAString& aValue,
   1766                       bool aDefer = true);
   1767 
   1768  /**
   1769   * Do whatever needs to be done when the mouse leaves a link
   1770   */
   1771  nsresult LeaveLink(nsPresContext* aPresContext);
   1772 
   1773  static bool ShouldBlur(nsIContent* aContent);
   1774 
   1775  /**
   1776   * Method to create and dispatch a left-click event loosely based on
   1777   * aSourceEvent. If aFullDispatch is true, the event will be dispatched
   1778   * through the full dispatching of the presshell of the aPresContext; if it's
   1779   * false the event will be dispatched only as a DOM event.
   1780   * If aPresContext is nullptr, this does nothing.
   1781   *
   1782   * @param aFlags      Extra flags for the dispatching event.  The true flags
   1783   *                    will be respected.
   1784   */
   1785  MOZ_CAN_RUN_SCRIPT
   1786  static nsresult DispatchClickEvent(nsPresContext* aPresContext,
   1787                                     WidgetInputEvent* aSourceEvent,
   1788                                     nsIContent* aTarget, bool aFullDispatch,
   1789                                     const EventFlags* aFlags,
   1790                                     nsEventStatus* aStatus);
   1791 
   1792  /**
   1793   * Method to dispatch aEvent to aTarget. If aFullDispatch is true, the event
   1794   * will be dispatched through the full dispatching of the presshell of the
   1795   * aPresContext; if it's false the event will be dispatched only as a DOM
   1796   * event.
   1797   * If aPresContext is nullptr, this does nothing.
   1798   */
   1799  using nsIContent::DispatchEvent;
   1800  MOZ_CAN_RUN_SCRIPT
   1801  static nsresult DispatchEvent(nsPresContext* aPresContext,
   1802                                WidgetEvent* aEvent, nsIContent* aTarget,
   1803                                bool aFullDispatch, nsEventStatus* aStatus);
   1804 
   1805  bool IsDisplayContents() const {
   1806    return HasServoData() && Servo_Element_IsDisplayContents(this);
   1807  }
   1808 
   1809  /*
   1810   * https://html.spec.whatwg.org/#being-rendered
   1811   *
   1812   * With a gotcha for display contents:
   1813   *   https://github.com/whatwg/html/issues/1837
   1814   */
   1815  bool IsRendered() const { return GetPrimaryFrame() || IsDisplayContents(); }
   1816 
   1817  const nsAttrValue* GetParsedAttr(const nsAtom* aAttr) const {
   1818    return mAttrs.GetAttr(aAttr);
   1819  }
   1820 
   1821  const nsAttrValue* GetParsedAttr(const nsAtom* aAttr,
   1822                                   int32_t aNameSpaceID) const {
   1823    return mAttrs.GetAttr(aAttr, aNameSpaceID);
   1824  }
   1825 
   1826  /**
   1827   * Returns the attribute map, if there is one.
   1828   *
   1829   * @return existing attribute map or nullptr.
   1830   */
   1831  nsDOMAttributeMap* GetAttributeMap() {
   1832    nsDOMSlots* slots = GetExistingDOMSlots();
   1833 
   1834    return slots ? slots->mAttributeMap.get() : nullptr;
   1835  }
   1836 
   1837  void RecompileScriptEventListeners();
   1838 
   1839  /**
   1840   * Get the attr info for the given namespace ID and attribute name.  The
   1841   * namespace ID must not be kNameSpaceID_Unknown and the name must not be
   1842   * null.  Note that this can only return info on attributes that actually
   1843   * live on this element (and is only virtual to handle XUL prototypes).  That
   1844   * is, this should only be called from methods that only care about attrs
   1845   * that effectively live in mAttrs.
   1846   */
   1847  BorrowedAttrInfo GetAttrInfo(int32_t aNamespaceID,
   1848                               const nsAtom* aName) const {
   1849    NS_ASSERTION(aName, "must have attribute name");
   1850    NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
   1851                 "must have a real namespace ID!");
   1852 
   1853    int32_t index = mAttrs.IndexOfAttr(aName, aNamespaceID);
   1854    if (index < 0) {
   1855      return BorrowedAttrInfo(nullptr, nullptr);
   1856    }
   1857 
   1858    return mAttrs.AttrInfoAt(index);
   1859  }
   1860 
   1861  /**
   1862   * Parse a string into an nsAttrValue for a CORS attribute.  This
   1863   * never fails.  The resulting value is an enumerated value whose
   1864   * GetEnumValue() returns one of the above constants.
   1865   */
   1866  static void ParseCORSValue(const nsAString& aValue, nsAttrValue& aResult);
   1867 
   1868  /**
   1869   * Return the CORS mode for a given string
   1870   */
   1871  static CORSMode StringToCORSMode(const nsAString& aValue);
   1872 
   1873  /**
   1874   * Return the CORS mode for a given nsAttrValue (which may be null,
   1875   * but if not should have been parsed via ParseCORSValue).
   1876   */
   1877  static CORSMode AttrValueToCORSMode(const nsAttrValue* aValue);
   1878 
   1879  nsINode* GetScopeChainParent() const override;
   1880 
   1881  JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
   1882 
   1883  /**
   1884   * Locate a TextEditor rooted at this content node, if there is one.
   1885   */
   1886  MOZ_CAN_RUN_SCRIPT_BOUNDARY mozilla::TextEditor* GetTextEditorInternal();
   1887 
   1888  /**
   1889   * Gets value of boolean attribute. Only works for attributes in null
   1890   * namespace.
   1891   *
   1892   * @param aAttr    name of attribute.
   1893   * @param aValue   Boolean value of attribute.
   1894   */
   1895  bool GetBoolAttr(nsAtom* aAttr) const { return HasAttr(aAttr); }
   1896 
   1897  /**
   1898   * Sets value of boolean attribute by removing attribute or setting it to
   1899   * the empty string. Only works for attributes in null namespace.
   1900   *
   1901   * @param aAttr    name of attribute.
   1902   * @param aValue   Boolean value of attribute.
   1903   */
   1904  nsresult SetBoolAttr(nsAtom* aAttr, bool aValue);
   1905 
   1906  /**
   1907   * Gets the enum value string of an attribute and using a default value if
   1908   * the attribute is missing or the string is an invalid enum value.
   1909   *
   1910   * @param aType     the name of the attribute.
   1911   * @param aDefault  the default value if the attribute is missing or invalid.
   1912   * @param aResult   string corresponding to the value [out].
   1913   */
   1914  void GetEnumAttr(nsAtom* aAttr, const char* aDefault,
   1915                   nsAString& aResult) const;
   1916 
   1917  /**
   1918   * Gets the enum value string of an attribute and using the default missing
   1919   * value if the attribute is missing or the default invalid value if the
   1920   * string is an invalid enum value.
   1921   *
   1922   * @param aType            the name of the attribute.
   1923   * @param aDefaultMissing  the default value if the attribute is missing.  If
   1924                             null and the attribute is missing, aResult will be
   1925                             set to the null DOMString; this only matters for
   1926                             cases in which we're reflecting a nullable string.
   1927   * @param aDefaultInvalid  the default value if the attribute is invalid.
   1928   * @param aResult          string corresponding to the value [out].
   1929   */
   1930  void GetEnumAttr(nsAtom* aAttr, const char* aDefaultMissing,
   1931                   const char* aDefaultInvalid, nsAString& aResult) const;
   1932 
   1933  /**
   1934   * Unset an attribute.
   1935   */
   1936  void UnsetAttr(nsAtom* aAttr, ErrorResult& aError) {
   1937    aError = UnsetAttr(kNameSpaceID_None, aAttr, true);
   1938  }
   1939 
   1940  /**
   1941   * Set an attribute in the simplest way possible.
   1942   */
   1943  void SetAttr(nsAtom* aAttr, const nsAString& aValue, ErrorResult& aError) {
   1944    aError = SetAttr(kNameSpaceID_None, aAttr, aValue, true);
   1945  }
   1946 
   1947  void SetAttr(nsAtom* aAttr, const nsAString& aValue,
   1948               nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError) {
   1949    aError =
   1950        SetAttr(kNameSpaceID_None, aAttr, aValue, aTriggeringPrincipal, true);
   1951  }
   1952 
   1953  /**
   1954   * Preallocate space in this element's attribute array for the given
   1955   * total number of attributes.
   1956   */
   1957  void TryReserveAttributeCount(uint32_t aAttributeCount);
   1958 
   1959  void SetParserHadDuplicateAttributeError() {
   1960    SetFlags(ELEMENT_PARSER_HAD_DUPLICATE_ATTR_ERROR);
   1961  }
   1962 
   1963  /**
   1964   * Set a content attribute via a reflecting nullable string IDL
   1965   * attribute (e.g. a CORS attribute).  If DOMStringIsNull(aValue),
   1966   * this will actually remove the content attribute.
   1967   */
   1968  void SetOrRemoveNullableStringAttr(nsAtom* aName, const nsAString& aValue,
   1969                                     ErrorResult& aError);
   1970 
   1971  /**
   1972   * Retrieve the ratio of font-size-inflated text font size to computed font
   1973   * size for this element. This will query the element for its primary frame,
   1974   * and then use this to get font size inflation information about the frame.
   1975   *
   1976   * @returns The font size inflation ratio (inflated font size to uninflated
   1977   *          font size) for the primary frame of this element. Returns 1.0
   1978   *          by default if font size inflation is not enabled. Returns -1
   1979   *          if the element does not have a primary frame.
   1980   *
   1981   * @note The font size inflation ratio that is returned is actually the
   1982   *       font size inflation data for the element's _primary frame_, not the
   1983   *       element itself, but for most purposes, this should be sufficient.
   1984   */
   1985  float FontSizeInflation();
   1986 
   1987  void GetImplementedPseudoElement(nsAString&) const;
   1988 
   1989  /**
   1990   * Get the pseudo element for this pseudo request (i.e. PseudoStyleType and
   1991   * its function parameter, if any).
   1992   */
   1993  Element* GetPseudoElement(const PseudoStyleRequest&) const;
   1994 
   1995  ReferrerPolicy GetReferrerPolicyAsEnum() const;
   1996  ReferrerPolicy ReferrerPolicyFromAttr(const nsAttrValue* aValue) const;
   1997 
   1998  /*
   1999   * Helpers for .dataset.  This is implemented on Element, though only some
   2000   * sorts of elements expose it to JS as a .dataset property
   2001   */
   2002  // Getter, to be called from bindings.
   2003  already_AddRefed<nsDOMStringMap> Dataset();
   2004  // Callback for destructor of dataset to ensure to null out our weak pointer
   2005  // to it.
   2006  void ClearDataset();
   2007 
   2008  // A number of methods to cast to various XUL interfaces. They return a
   2009  // pointer only if the element implements that interface.
   2010  already_AddRefed<nsIDOMXULButtonElement> AsXULButton();
   2011  already_AddRefed<nsIDOMXULContainerElement> AsXULContainer();
   2012  already_AddRefed<nsIDOMXULContainerItemElement> AsXULContainerItem();
   2013  already_AddRefed<nsIDOMXULControlElement> AsXULControl();
   2014  already_AddRefed<nsIDOMXULMenuListElement> AsXULMenuList();
   2015  already_AddRefed<nsIDOMXULMultiSelectControlElement>
   2016  AsXULMultiSelectControl();
   2017  already_AddRefed<nsIDOMXULRadioGroupElement> AsXULRadioGroup();
   2018  already_AddRefed<nsIDOMXULRelatedElement> AsXULRelated();
   2019  already_AddRefed<nsIDOMXULSelectControlElement> AsXULSelectControl();
   2020  already_AddRefed<nsIDOMXULSelectControlItemElement> AsXULSelectControlItem();
   2021  already_AddRefed<nsIBrowser> AsBrowser();
   2022  already_AddRefed<nsIAutoCompletePopup> AsAutoCompletePopup();
   2023 
   2024  /**
   2025   * Get the presentation context for this content node.
   2026   * @return the presentation context
   2027   */
   2028  enum PresContextFor { eForComposedDoc, eForUncomposedDoc };
   2029  nsPresContext* GetPresContext(PresContextFor aFor) const;
   2030 
   2031  /**
   2032   * The method focuses (or activates) element that accesskey is bound to. It is
   2033   * called when accesskey is activated.
   2034   *
   2035   * @param aKeyCausesActivation - if true then element should be activated
   2036   * @param aIsTrustedEvent - if true then event that is cause of accesskey
   2037   *                          execution is trusted.
   2038   * @return an error if the element isn't able to handle the accesskey (caller
   2039   *         would look for the next element to handle it).
   2040   *         a boolean indicates whether the focus moves to the element after
   2041   *         the element handles the accesskey.
   2042   */
   2043  MOZ_CAN_RUN_SCRIPT
   2044  virtual Result<bool, nsresult> PerformAccesskey(bool aKeyCausesActivation,
   2045                                                  bool aIsTrustedEvent) {
   2046    return Err(NS_ERROR_NOT_IMPLEMENTED);
   2047  }
   2048 
   2049 protected:
   2050  // Supported rel values for <form> and anchors.
   2051  static const DOMTokenListSupportedToken sAnchorAndFormRelValues[];
   2052 
   2053  /*
   2054   * Named-bools for use with SetAttrAndNotify to make call sites easier to
   2055   * read.
   2056   */
   2057  static const bool kNotifyDocumentObservers = true;
   2058  static const bool kDontNotifyDocumentObservers = false;
   2059  static const bool kCallAfterSetAttr = true;
   2060  static const bool kDontCallAfterSetAttr = false;
   2061 
   2062  /*
   2063   * The supported values of blocking attribute for use with nsDOMTokenList.
   2064   */
   2065  static const DOMTokenListSupportedToken sSupportedBlockingValues[];
   2066 
   2067  /**
   2068   * Common implementation for SetAttr overloads. Takes a callback to perform
   2069   * the type-specific parsing and value setting.
   2070   */
   2071  template <typename ParseFunc>
   2072  nsresult SetAttrInternal(int32_t aNamespaceID, nsAtom* aName, nsAtom* aPrefix,
   2073                           const nsAttrValueOrString& aValueForComparison,
   2074                           nsIPrincipal* aSubjectPrincipal, bool aNotify,
   2075                           ParseFunc&& aParseFn);
   2076 
   2077  /**
   2078   * Set attribute and (if needed) notify documentobservers.  This will send the
   2079   * AttributeChanged notification. Callers of this method are responsible for
   2080   * calling AttributeWillChange, since that needs to happen before the new attr
   2081   * value has been set, and in particular before it has been parsed.
   2082   *
   2083   * For the boolean parameters, consider using the named bools above to aid
   2084   * code readability.
   2085   *
   2086   * @param aNamespaceID  namespace of attribute
   2087   * @param aAttribute    local-name of attribute
   2088   * @param aPrefix       aPrefix of attribute
   2089   * @param aOldValue     The old value of the attribute to use as a fallback
   2090   *                      in the cases where the actual old value (i.e.
   2091   *                      its current value) is !StoresOwnData() --- in which
   2092   *                      case the current value is probably already useless.
   2093   *                      If the current value is StoresOwnData() (or absent),
   2094   *                      aOldValue will not be used. aOldValue will only be set
   2095   *                      in certain circumstances (there are mutation
   2096   *                      listeners, element is a custom element, attribute was
   2097   *                      not previously unset). Otherwise it will be null.
   2098   * @param aParsedValue  parsed new value of attribute. Replaced by the
   2099   *                      old value of the attribute. This old value is only
   2100   *                      useful if either it or the new value is StoresOwnData.
   2101   * @param aSubjectPrincipal
   2102   *                      the principal of the scripted caller responsible for
   2103   *                      setting the attribute, or null if no scripted caller
   2104   *                      can be determined. A null value here does not
   2105   *                      guarantee that there is no scripted caller, but a
   2106   *                      non-null value does guarantee that a scripted caller
   2107   *                      with the given principal is directly responsible for
   2108   *                      the attribute change.
   2109   * @param aModType      AttrModType::Modification or AttrModType::Addition.
   2110   * @param aNotify       should we notify document-observers?
   2111   * @param aCallAfterSetAttr should we call AfterSetAttr?
   2112   * @param aComposedDocument The current composed document of the element.
   2113   * @param aGuard        For making sure that this is called with a
   2114   *                      mozAutoDocUpdate instance, this is here.  Specify
   2115   *                      an instance of it which you created for the call.
   2116   */
   2117  nsresult SetAttrAndNotify(int32_t aNamespaceID, nsAtom* aName,
   2118                            nsAtom* aPrefix, const nsAttrValue* aOldValue,
   2119                            nsAttrValue& aParsedValue,
   2120                            nsIPrincipal* aSubjectPrincipal,
   2121                            AttrModType aModType, bool aNotify,
   2122                            bool aCallAfterSetAttr, Document* aComposedDocument,
   2123                            const mozAutoDocUpdate& aGuard);
   2124 
   2125  /**
   2126   * Convert an attribute string value to attribute type based on the type of
   2127   * attribute.  Called by SetAttr().  Note that at the moment we only do this
   2128   * for attributes in the null namespace (kNameSpaceID_None).
   2129   *
   2130   * @param aNamespaceID the namespace of the attribute to convert
   2131   * @param aAttribute the attribute to convert
   2132   * @param aValue the string value to convert
   2133   * @param aMaybeScriptedPrincipal the principal of the script setting the
   2134   *        attribute, if one can be determined, or null otherwise. As in
   2135   *        AfterSetAttr, a null value does not guarantee that the attribute was
   2136   *        not set by a scripted caller, but a non-null value guarantees that
   2137   *        the attribute was set by a scripted caller with the given principal.
   2138   * @param aResult the nsAttrValue [OUT]
   2139   * @return true if the parsing was successful, false otherwise
   2140   */
   2141  virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
   2142                              const nsAString& aValue,
   2143                              nsIPrincipal* aMaybeScriptedPrincipal,
   2144                              nsAttrValue& aResult);
   2145 
   2146  /**
   2147   * Hook that is called by Element::SetAttr to allow subclasses to
   2148   * deal with attribute sets.  This will only be called after we verify that
   2149   * we're actually doing an attr set and will be called before
   2150   * AttributeWillChange and before ParseAttribute and hence before we've set
   2151   * the new value.
   2152   *
   2153   * @param aNamespaceID the namespace of the attr being set
   2154   * @param aName the localname of the attribute being set
   2155   * @param aValue the value it's being set to represented as either a string or
   2156   *        a parsed nsAttrValue. Alternatively, if the attr is being removed it
   2157   *        will be null.
   2158   * @param aNotify Whether we plan to notify document observers.
   2159   */
   2160  virtual void BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
   2161                             const nsAttrValue* aValue, bool aNotify);
   2162 
   2163  /**
   2164   * Hook that is called by Element::SetAttr to allow subclasses to
   2165   * deal with attribute sets.  This will only be called after we have called
   2166   * SetAndSwapAttr (that is, after we have actually set the attr).  It will
   2167   * always be called under a scriptblocker.
   2168   *
   2169   * @param aNamespaceID the namespace of the attr being set
   2170   * @param aName the localname of the attribute being set
   2171   * @param aValue the value it's being set to.  If null, the attr is being
   2172   *        removed.
   2173   * @param aOldValue the value that the attribute had previously. If null,
   2174   *        the attr was not previously set. This argument may not have the
   2175   *        correct value for SVG elements, or other cases in which the
   2176   *        attribute value doesn't store its own data
   2177   * @param aMaybeScriptedPrincipal the principal of the scripted caller
   2178   *        responsible for setting the attribute, or null if no scripted caller
   2179   *        can be determined, or the attribute is being unset. A null value
   2180   *        here does not guarantee that there is no scripted caller, but a
   2181   *        non-null value does guarantee that a scripted caller with the given
   2182   *        principal is directly responsible for the attribute change.
   2183   * @param aNotify Whether we plan to notify document observers.
   2184   */
   2185  virtual void AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
   2186                            const nsAttrValue* aValue,
   2187                            const nsAttrValue* aOldValue,
   2188                            nsIPrincipal* aMaybeScriptedPrincipal,
   2189                            bool aNotify);
   2190 
   2191  /**
   2192   * This function shall be called just before the id attribute changes. It will
   2193   * be called after BeforeSetAttr. If the attribute being changed is not the id
   2194   * attribute, this function does nothing. Otherwise, it will remove the old id
   2195   * from the document's id cache.
   2196   *
   2197   * This must happen after BeforeSetAttr (rather than during) because the
   2198   * the subclasses' calls to BeforeSetAttr may notify on state changes. If they
   2199   * incorrectly determine whether the element had an id, the element may not be
   2200   * restyled properly.
   2201   *
   2202   * @param aNamespaceID the namespace of the attr being set
   2203   * @param aName the localname of the attribute being set
   2204   * @param aValue the new id value. Will be null if the id is being unset.
   2205   */
   2206  void PreIdMaybeChange(int32_t aNamespaceID, nsAtom* aName,
   2207                        const nsAttrValue* aValue);
   2208 
   2209  /**
   2210   * This function shall be called just after the id attribute changes. It will
   2211   * be called before AfterSetAttr. If the attribute being changed is not the id
   2212   * attribute, this function does nothing. Otherwise, it will add the new id to
   2213   * the document's id cache and properly set the ElementHasID flag.
   2214   *
   2215   * This must happen before AfterSetAttr (rather than during) because the
   2216   * the subclasses' calls to AfterSetAttr may notify on state changes. If they
   2217   * incorrectly determine whether the element now has an id, the element may
   2218   * not be restyled properly.
   2219   *
   2220   * @param aNamespaceID the namespace of the attr being set
   2221   * @param aName the localname of the attribute being set
   2222   * @param aValue the new id value. Will be null if the id is being unset.
   2223   */
   2224  void PostIdMaybeChange(int32_t aNamespaceID, nsAtom* aName,
   2225                         const nsAttrValue* aValue);
   2226 
   2227  /**
   2228   * Usually, setting an attribute to the value that it already has results in
   2229   * no action. However, in some cases, setting an attribute to its current
   2230   * value should have the effect of, for example, forcing a reload of
   2231   * network data. To address that, this function will be called in this
   2232   * situation to allow the handling of such a case.
   2233   *
   2234   * @param aNamespaceID the namespace of the attr being set
   2235   * @param aName the localname of the attribute being set
   2236   * @param aValue the value it's being set to represented as either a string or
   2237   *        a parsed nsAttrValue.
   2238   * @param aNotify Whether we plan to notify document observers.
   2239   */
   2240  virtual void OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
   2241                                      const nsAttrValueOrString& aValue,
   2242                                      bool aNotify);
   2243 
   2244  /**
   2245   * Hook to allow subclasses to produce a different EventListenerManager if
   2246   * needed for attachment of attribute-defined handlers
   2247   */
   2248  virtual EventListenerManager* GetEventListenerManagerForAttr(
   2249      nsAtom* aAttrName, bool* aDefer);
   2250 
   2251  /**
   2252   * Internal hook for converting an attribute name-string to nsAttrName in
   2253   * case there is such existing attribute. aNameToUse can be passed to get
   2254   * name which was used for looking for the attribute (lowercase in HTML).
   2255   */
   2256  const nsAttrName* InternalGetAttrNameFromQName(
   2257      const nsAString& aStr, nsAutoString* aNameToUse = nullptr) const;
   2258 
   2259  virtual Element* GetNameSpaceElement() override { return this; }
   2260 
   2261  Attr* GetAttributeNodeNSInternal(const nsAString& aNamespaceURI,
   2262                                   const nsAString& aLocalName);
   2263 
   2264  inline void RegisterActivityObserver();
   2265  inline void UnregisterActivityObserver();
   2266 
   2267  /**
   2268   * Add/remove this element to the documents id cache
   2269   */
   2270  void AddToIdTable(nsAtom* aId);
   2271  void RemoveFromIdTable();
   2272 
   2273  /**
   2274   * Functions to carry out event default actions for links of all types
   2275   * (HTML links, XLinks, SVG "XLinks", etc.)
   2276   */
   2277 
   2278  /**
   2279   * Check that we meet the conditions to handle a link event
   2280   * and that we are actually on a link.
   2281   *
   2282   * @param aVisitor event visitor
   2283   * @return true if we can handle the link event, false otherwise
   2284   */
   2285  bool CheckHandleEventForLinksPrecondition(EventChainVisitor& aVisitor) const;
   2286 
   2287  /**
   2288   * Handle status bar updates before they can be cancelled.
   2289   */
   2290  void GetEventTargetParentForLinks(EventChainPreVisitor& aVisitor);
   2291 
   2292  void DispatchChromeOnlyLinkClickEvent(EventChainPostVisitor& aVisitor);
   2293 
   2294  /**
   2295   * Handle default actions for link event if the event isn't consumed yet.
   2296   */
   2297  MOZ_CAN_RUN_SCRIPT
   2298  nsresult PostHandleEventForLinks(EventChainPostVisitor& aVisitor);
   2299 
   2300  mozilla::dom::FetchPriority GetFetchPriority() const;
   2301 
   2302  static void ParseFetchPriority(const nsAString& aValue, nsAttrValue& aResult);
   2303 
   2304 public:
   2305  /**
   2306   * Check if this element is a link. This matches the CSS definition of the
   2307   * :any-link pseudo-class.
   2308   */
   2309  bool IsLink() const {
   2310    return mState.HasAtLeastOneOfStates(ElementState::VISITED |
   2311                                        ElementState::UNVISITED);
   2312  }
   2313 
   2314  /**
   2315   * Get a pointer to the full href URI (fully resolved and canonicalized, since
   2316   * it's an nsIURI object) for link elements.
   2317   *
   2318   * @return A pointer to the URI or null if the element is not a link, or it
   2319   *         has no HREF attribute, or the HREF attribute is an invalid URI.
   2320   */
   2321  virtual already_AddRefed<nsIURI> GetHrefURI() const { return nullptr; }
   2322 
   2323  // Step 2. of
   2324  // <https://html.spec.whatwg.org/multipage/semantics.html#get-an-element's-target>
   2325  //
   2326  // Sanitize targets that look like they contain dangling markup.
   2327  static void SanitizeLinkOrFormTarget(nsAString& aTarget);
   2328 
   2329  /**
   2330   * <https://html.spec.whatwg.org/multipage/semantics.html#get-an-element's-target>
   2331   * (Excluding <form>)
   2332   *
   2333   * Get the target of this link element. Consumers should established that
   2334   * this element is a link (probably using IsLink) before calling this
   2335   * function (or else why call it?). This method neuters probably markup
   2336   * injection attempts.
   2337   *
   2338   * Note: for HTML this gets the value of the 'target' attribute; for XLink
   2339   * this gets the value of the xlink:_moz_target attribute, or failing that,
   2340   * the value of xlink:show, converted to a suitably equivalent named target
   2341   * (e.g. _blank).
   2342   */
   2343  void GetLinkTarget(nsAString& aTarget);
   2344 
   2345  virtual void GetLinkTargetImpl(nsAString& aTarget);
   2346 
   2347  virtual bool Translate() const;
   2348 
   2349  MOZ_CAN_RUN_SCRIPT
   2350  void FireBeforematchEvent(ErrorResult& aRv);
   2351 
   2352  void PropagateBloomFilterToParents();
   2353  void UpdateSubtreeBloomFilterForClass(const nsAttrValue* aClassValue);
   2354  void UpdateSubtreeBloomFilterForAttribute(nsAtom* aAttribute);
   2355  uint64_t GetSubtreeBloomFilter() const {
   2356    return mAttrs.GetSubtreeBloomFilter();
   2357  }
   2358 #ifdef DEBUG
   2359  void VerifySubtreeBloomFilter() const;
   2360 #endif
   2361 
   2362 protected:
   2363  enum class ReparseAttributes { No, Yes };
   2364  /**
   2365   * Copy attributes and state to another element
   2366   * @param aDest the object to copy to
   2367   */
   2368  nsresult CopyInnerTo(Element* aDest,
   2369                       ReparseAttributes = ReparseAttributes::Yes);
   2370 
   2371  /**
   2372   * Some event handler content attributes have a different name (e.g. different
   2373   * case) from the actual event name.  This function takes an event handler
   2374   * content attribute name and returns the corresponding event name, to be used
   2375   * for adding the actual event listener.
   2376   */
   2377  virtual nsAtom* GetEventNameForAttr(nsAtom* aAttr);
   2378 
   2379  /**
   2380   * Register/unregister this element to accesskey map if it supports accesskey.
   2381   */
   2382  virtual void RegUnRegAccessKey(bool aDoReg);
   2383 
   2384 private:
   2385 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
   2386  void AssertInvariantsOnNodeInfoChange();
   2387 #endif
   2388 
   2389  /**
   2390   * Slow path for GetClasses, this should only be called for SVG elements.
   2391   */
   2392  const nsAttrValue* GetSVGAnimatedClass() const;
   2393 
   2394  /**
   2395   * Get this element's client area rect in app units.
   2396   * @return the frame's client area
   2397   */
   2398  MOZ_CAN_RUN_SCRIPT nsRect GetClientAreaRect();
   2399 
   2400  /** Gets the scroll size as for the scroll{Width,Height} APIs */
   2401  MOZ_CAN_RUN_SCRIPT nsSize GetScrollSize();
   2402  /** Gets the scroll position as for the scroll{Top,Left} APIs */
   2403  MOZ_CAN_RUN_SCRIPT nsPoint GetScrollOrigin();
   2404  /** Gets the scroll range as for the scroll{Top,Left}{Min,Max} APIs */
   2405  MOZ_CAN_RUN_SCRIPT nsRect GetScrollRange();
   2406 
   2407  /**
   2408   * GetCustomInterface is somewhat like a GetInterface, but it is expected
   2409   * that the implementation is provided by a custom element or via the
   2410   * the XBL implements keyword. To use this, create a public method that
   2411   * wraps a call to GetCustomInterface.
   2412   */
   2413  template <class T>
   2414  void GetCustomInterface(nsGetterAddRefs<T> aResult);
   2415 
   2416  // Prevent people from doing pointless checks/casts on Element instances.
   2417  void IsElement() = delete;
   2418  void AsElement() = delete;
   2419 
   2420  // Data members
   2421  ElementState mState;
   2422  // Per-node data managed by Servo.
   2423  //
   2424  // There should not be data on nodes that are not in the flattened tree, or
   2425  // descendants of display: none elements.
   2426  mozilla::RustCell<ServoNodeData*> mServoData;
   2427 
   2428 protected:
   2429  // Array containing all attributes for this element
   2430  AttrArray mAttrs;
   2431 };
   2432 
   2433 inline bool Element::HasNonEmptyAttr(int32_t aNameSpaceID,
   2434                                     const nsAtom* aName) const {
   2435  MOZ_ASSERT(aNameSpaceID > kNameSpaceID_Unknown, "Must have namespace");
   2436  MOZ_ASSERT(aName, "Must have attribute name");
   2437 
   2438  const nsAttrValue* val = mAttrs.GetAttr(aName, aNameSpaceID);
   2439  return val && !val->IsEmptyString();
   2440 }
   2441 
   2442 inline bool Element::AttrValueIs(int32_t aNameSpaceID, const nsAtom* aName,
   2443                                 const nsAString& aValue,
   2444                                 nsCaseTreatment aCaseSensitive) const {
   2445  return mAttrs.AttrValueIs(aNameSpaceID, aName, aValue, aCaseSensitive);
   2446 }
   2447 
   2448 inline bool Element::AttrValueIs(int32_t aNameSpaceID, const nsAtom* aName,
   2449                                 const nsAtom* aValue,
   2450                                 nsCaseTreatment aCaseSensitive) const {
   2451  return mAttrs.AttrValueIs(aNameSpaceID, aName, aValue, aCaseSensitive);
   2452 }
   2453 
   2454 }  // namespace dom
   2455 }  // namespace mozilla
   2456 
   2457 NON_VIRTUAL_ADDREF_RELEASE(mozilla::dom::Element)
   2458 
   2459 inline mozilla::dom::Element* nsINode::AsElement() {
   2460  MOZ_ASSERT(IsElement());
   2461  return static_cast<mozilla::dom::Element*>(this);
   2462 }
   2463 
   2464 inline const mozilla::dom::Element* nsINode::AsElement() const {
   2465  MOZ_ASSERT(IsElement());
   2466  return static_cast<const mozilla::dom::Element*>(this);
   2467 }
   2468 
   2469 inline mozilla::dom::Element* nsINode::GetParentElement() const {
   2470  return mozilla::dom::Element::FromNodeOrNull(mParent);
   2471 }
   2472 
   2473 inline mozilla::dom::Element* nsINode::GetPreviousElementSibling() const {
   2474  nsIContent* previousSibling = GetPreviousSibling();
   2475  while (previousSibling) {
   2476    if (previousSibling->IsElement()) {
   2477      return previousSibling->AsElement();
   2478    }
   2479    previousSibling = previousSibling->GetPreviousSibling();
   2480  }
   2481 
   2482  return nullptr;
   2483 }
   2484 
   2485 inline mozilla::dom::ShadowRoot* nsINode::GetShadowRoot() const {
   2486  return IsElement() ? AsElement()->GetShadowRoot() : nullptr;
   2487 }
   2488 
   2489 inline mozilla::dom::Element* nsINode::GetAsElementOrParentElement() const {
   2490  return IsElement() ? const_cast<mozilla::dom::Element*>(AsElement())
   2491                     : GetParentElement();
   2492 }
   2493 
   2494 inline mozilla::dom::Element* nsINode::GetNextElementSibling() const {
   2495  nsIContent* nextSibling = GetNextSibling();
   2496  while (nextSibling) {
   2497    if (nextSibling->IsElement()) {
   2498      return nextSibling->AsElement();
   2499    }
   2500    nextSibling = nextSibling->GetNextSibling();
   2501  }
   2502 
   2503  return nullptr;
   2504 }
   2505 
   2506 /**
   2507 * Macros to implement Clone(). _elementName is the class for which to implement
   2508 * Clone.
   2509 */
   2510 #define NS_IMPL_ELEMENT_CLONE(_elementName, ...)                    \
   2511  nsresult _elementName::Clone(mozilla::dom::NodeInfo* aNodeInfo,   \
   2512                               nsINode** aResult) const {           \
   2513    *aResult = nullptr;                                             \
   2514    RefPtr<_elementName> it = new (aNodeInfo->NodeInfoManager())    \
   2515        _elementName(do_AddRef(aNodeInfo), ##__VA_ARGS__);          \
   2516    nsresult rv = const_cast<_elementName*>(this)->CopyInnerTo(it); \
   2517    if (NS_SUCCEEDED(rv)) {                                         \
   2518      it.forget(aResult);                                           \
   2519    }                                                               \
   2520    return rv;                                                      \
   2521  }
   2522 
   2523 #define NS_IMPL_ELEMENT_CLONE_WITH_INIT(_elementName, ...)           \
   2524  nsresult _elementName::Clone(mozilla::dom::NodeInfo* aNodeInfo,    \
   2525                               nsINode** aResult) const {            \
   2526    *aResult = nullptr;                                              \
   2527    RefPtr<_elementName> it = new (aNodeInfo->NodeInfoManager())     \
   2528        _elementName(do_AddRef(aNodeInfo), ##__VA_ARGS__);           \
   2529    nsresult rv = it->Init();                                        \
   2530    nsresult rv2 = const_cast<_elementName*>(this)->CopyInnerTo(it); \
   2531    if (NS_FAILED(rv2)) {                                            \
   2532      rv = rv2;                                                      \
   2533    }                                                                \
   2534    if (NS_SUCCEEDED(rv)) {                                          \
   2535      it.forget(aResult);                                            \
   2536    }                                                                \
   2537    return rv;                                                       \
   2538  }
   2539 
   2540 #define NS_IMPL_ELEMENT_CLONE_WITH_INIT_AND_PARSER(_elementName) \
   2541  NS_IMPL_ELEMENT_CLONE_WITH_INIT(_elementName, NOT_FROM_PARSER)
   2542 
   2543 #endif  // mozilla_dom_Element_h__