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__