FragmentOrElement.h (12223B)
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 as well as nsDocumentFragment. This 9 * provides an implementation of nsINode, implements nsIContent, provides 10 * utility methods for subclasses, and so forth. 11 */ 12 13 #ifndef FragmentOrElement_h___ 14 #define FragmentOrElement_h___ 15 16 #include "mozilla/Attributes.h" 17 #include "mozilla/EnumSet.h" 18 #include "mozilla/MemoryReporting.h" 19 #include "mozilla/UniquePtr.h" 20 #include "mozilla/dom/RadioGroupContainer.h" 21 #include "nsAtomHashKeys.h" 22 #include "nsCycleCollectionParticipant.h" // NS_DECL_CYCLE_* 23 #include "nsIContent.h" // base class 24 #include "nsIHTMLCollection.h" 25 #include "nsIWeakReferenceUtils.h" 26 27 class ContentUnbinder; 28 class nsContentList; 29 class nsLabelsNodeList; 30 class nsDOMAttributeMap; 31 class nsDOMTokenList; 32 class nsIControllers; 33 class nsDOMCSSAttributeDeclaration; 34 class nsDOMCSSDeclaration; 35 class nsDOMStringMap; 36 class nsIURI; 37 38 namespace mozilla { 39 class DeclarationBlock; 40 enum class ContentRelevancyReason; 41 using ContentRelevancy = EnumSet<ContentRelevancyReason, uint8_t>; 42 class ElementAnimationData; 43 namespace dom { 44 struct CustomElementData; 45 class Element; 46 class PopoverData; 47 class StylePropertyMap; 48 class StylePropertyMapReadOnly; 49 } // namespace dom 50 } // namespace mozilla 51 52 /** 53 * Tearoff to use for nodes to implement nsISupportsWeakReference 54 */ 55 class nsNodeSupportsWeakRefTearoff final : public nsISupportsWeakReference { 56 public: 57 explicit nsNodeSupportsWeakRefTearoff(nsINode* aNode) : mNode(aNode) {} 58 59 // nsISupports 60 NS_DECL_CYCLE_COLLECTING_ISUPPORTS_FINAL 61 62 // nsISupportsWeakReference 63 NS_DECL_NSISUPPORTSWEAKREFERENCE 64 65 NS_DECL_CYCLE_COLLECTION_CLASS(nsNodeSupportsWeakRefTearoff) 66 67 private: 68 ~nsNodeSupportsWeakRefTearoff() = default; 69 70 nsCOMPtr<nsINode> mNode; 71 }; 72 73 /** 74 * A generic base class for DOM elements and document fragments, 75 * implementing many nsIContent, nsINode and Element methods. 76 */ 77 namespace mozilla::dom { 78 79 class DOMIntersectionObserver; 80 class ShadowRoot; 81 82 class FragmentOrElement : public nsIContent { 83 public: 84 explicit FragmentOrElement( 85 already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo); 86 explicit FragmentOrElement( 87 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo); 88 89 // We want to avoid the overhead of extra function calls for 90 // refcounting when we're not doing refcount logging, so we can't 91 // NS_DECL_ISUPPORTS_INHERITED. 92 NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override; 93 NS_INLINE_DECL_REFCOUNTING_INHERITED(FragmentOrElement, nsIContent); 94 95 NS_DECL_ADDSIZEOFEXCLUDINGTHIS 96 97 // nsINode interface methods 98 virtual void GetTextContentInternal(nsAString& aTextContent, 99 mozilla::OOMReporter& aError) override; 100 virtual void SetTextContentInternal( 101 const nsAString& aTextContent, nsIPrincipal* aSubjectPrincipal, 102 mozilla::ErrorResult& aError, 103 MutationEffectOnScript aMutationEffectOnScript) override; 104 105 // nsIContent interface methods 106 const CharacterDataBuffer* GetCharacterDataBuffer() const override; 107 uint32_t TextLength() const override; 108 bool TextIsOnlyWhitespace() override; 109 bool ThreadSafeTextIsOnlyWhitespace() const override; 110 111 void DestroyContent() override; 112 void SaveSubtreeState() override; 113 114 nsIHTMLCollection* Children(); 115 uint32_t ChildElementCount() { 116 if (!HasChildren()) { 117 return 0; 118 } 119 return Children()->Length(); 120 } 121 122 RadioGroupContainer& OwnedRadioGroupContainer() { 123 auto* slots = ExtendedDOMSlots(); 124 if (!slots->mRadioGroupContainer) { 125 slots->mRadioGroupContainer = MakeUnique<RadioGroupContainer>(); 126 } 127 return *slots->mRadioGroupContainer; 128 } 129 130 public: 131 NS_DECL_CYCLE_COLLECTION_SKIPPABLE_WRAPPERCACHE_CLASS_INHERITED( 132 FragmentOrElement, nsIContent) 133 134 static void ClearContentUnbinder(); 135 static bool CanSkip(nsINode* aNode, bool aRemovingAllowed); 136 static bool CanSkipInCC(nsINode* aNode); 137 static bool CanSkipThis(nsINode* aNode); 138 static void RemoveBlackMarkedNode(nsINode* aNode); 139 static void MarkNodeChildren(nsINode* aNode); 140 static void InitCCCallbacks(); 141 142 /** 143 * Is the HTML local name a void element? 144 */ 145 static bool IsHTMLVoid(const nsAtom* aLocalName); 146 147 protected: 148 virtual ~FragmentOrElement(); 149 150 /** 151 * Dummy CopyInnerTo so that we can use the same macros for 152 * Elements and DocumentFragments. 153 */ 154 nsresult CopyInnerTo(FragmentOrElement* aDest) { return NS_OK; } 155 156 public: 157 /** 158 * There are a set of DOM- and scripting-specific instance variables 159 * that may only be instantiated when a content object is accessed 160 * through the DOM. Rather than burn actual slots in the content 161 * objects for each of these instance variables, we put them off 162 * in a side structure that's only allocated when the content is 163 * accessed through the DOM. 164 */ 165 166 class nsExtendedDOMSlots : public nsIContent::nsExtendedContentSlots { 167 public: 168 nsExtendedDOMSlots(); 169 ~nsExtendedDOMSlots(); 170 171 void TraverseExtendedSlots(nsCycleCollectionTraversalCallback&) final; 172 void UnlinkExtendedSlots(nsIContent&) final; 173 174 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const final; 175 176 /** 177 * SMIL Overridde style rules (for SMIL animation of CSS properties) 178 * @see Element::GetSMILOverrideStyle 179 */ 180 RefPtr<nsDOMCSSAttributeDeclaration> mSMILOverrideStyle; 181 182 /** 183 * Holds any SMIL override style declaration for this element. 184 */ 185 RefPtr<DeclarationBlock> mSMILOverrideStyleDeclaration; 186 187 /** 188 * The controllers of the XUL Element. 189 */ 190 nsCOMPtr<nsIControllers> mControllers; 191 192 /** 193 * An object implementing the .labels property for this element. 194 */ 195 RefPtr<nsLabelsNodeList> mLabelsList; 196 197 /** 198 * ShadowRoot bound to the element. 199 */ 200 RefPtr<ShadowRoot> mShadowRoot; 201 202 /** 203 * Web components custom element data. 204 */ 205 UniquePtr<CustomElementData> mCustomElementData; 206 207 /** 208 * Web animations data. 209 */ 210 UniquePtr<ElementAnimationData> mAnimations; 211 212 /** 213 * PopoverData for the element. 214 */ 215 UniquePtr<PopoverData> mPopoverData; 216 217 /** 218 * The association to a popover that this element was the source 219 * showing a popover, e.g. the source in `el.showPopover({source})`. 220 */ 221 nsWeakPtr mAssociatedPopover; 222 223 /** 224 * CustomStates for the element. 225 */ 226 nsTArray<RefPtr<nsAtom>> mCustomStates; 227 228 /** 229 * RadioGroupContainer for radio buttons grouped under this disconnected 230 * element. 231 */ 232 UniquePtr<RadioGroupContainer> mRadioGroupContainer; 233 234 /** 235 * Last remembered size (in CSS pixels) for the element. 236 * @see {@link https://drafts.csswg.org/css-sizing-4/#last-remembered} 237 */ 238 Maybe<float> mLastRememberedBSize; 239 Maybe<float> mLastRememberedISize; 240 241 /** 242 * Whether the content of this element is relevant for the purposes 243 * of `content-visibility: auto. 244 * Reflects 'relevant to the user' concept, see 245 * https://drafts.csswg.org/css-contain/#relevant-to-the-user. 246 */ 247 Maybe<ContentRelevancy> mContentRelevancy; 248 249 /** 250 * Whether the content of this element is considered visible for 251 * the purposes of `content-visibility: auto. 252 * Reflects 'proximity to the viewport' concept, see 253 * https://drafts.csswg.org/css-contain/#proximity-to-the-viewport. 254 */ 255 Maybe<bool> mVisibleForContentVisibility; 256 257 /** 258 * Whether content-visibility: auto is temporarily visible for 259 * the purposes of the descendant of scrollIntoView. 260 */ 261 bool mTemporarilyVisibleForScrolledIntoViewDescendant = false; 262 263 /** 264 * The .dataset attribute. 265 * @see nsGenericHTMLElement::GetDataset 266 */ 267 nsDOMStringMap* MOZ_UNSAFE_REF("ClearDataSet clears it") mDataset = nullptr; 268 269 /** An object implementing the .part property for this element. */ 270 RefPtr<nsDOMTokenList> mPart; 271 272 /** 273 * Explicitly set attr-element, see 274 * https://html.spec.whatwg.org/#explicitly-set-attr-element 275 */ 276 nsTHashMap<RefPtr<nsAtom>, nsWeakPtr> mExplicitlySetAttrElementMap; 277 /** 278 * Explicitly set attr-elements, see 279 * https://html.spec.whatwg.org/#explicitly-set-attr-elements 280 * 281 * The first member of the pair are the explicitly set attr-elements. The 282 * second member is the cached attr-associated elements. 283 */ 284 285 nsTHashMap<RefPtr<nsAtom>, std::pair<Maybe<nsTArray<nsWeakPtr>>, 286 Maybe<nsTArray<RefPtr<Element>>>>> 287 mAttrElementsMap; 288 }; 289 290 class nsDOMSlots : public nsIContent::nsContentSlots { 291 public: 292 nsDOMSlots(); 293 ~nsDOMSlots(); 294 295 void Traverse(nsCycleCollectionTraversalCallback&) final; 296 void Unlink(nsINode&) final; 297 298 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 299 300 /** 301 * The .style attribute (an interface that forwards to the actual 302 * style rules) 303 * @see nsGenericHTMLElement::GetStyle 304 */ 305 nsCOMPtr<nsDOMCSSDeclaration> mStyle; 306 307 /** 308 * @see Element::Attributes 309 */ 310 RefPtr<nsDOMAttributeMap> mAttributeMap; 311 312 /** 313 * An object implementing the .children property for this element. 314 */ 315 RefPtr<nsContentList> mChildrenList; 316 317 /** 318 * An object implementing the .classList property for this element. 319 */ 320 RefPtr<nsDOMTokenList> mClassList; 321 322 /** 323 * An object implementing the .computedStyleMap() method for this element. 324 */ 325 RefPtr<StylePropertyMapReadOnly> mComputedStyleMap; 326 327 /** 328 * An object implementing the .attributeStyleMap property for this element. 329 */ 330 RefPtr<StylePropertyMap> mAttributeStyleMap; 331 }; 332 333 /** 334 * In case ExtendedDOMSlots is needed before normal DOMSlots, an instance of 335 * FatSlots class, which combines those two slot types, is created. 336 * This way we can avoid extra allocation for ExtendedDOMSlots. 337 * FatSlots is useful for example when creating Custom Elements. 338 */ 339 class FatSlots final : public nsDOMSlots, public nsExtendedDOMSlots { 340 public: 341 FatSlots() : nsDOMSlots(), nsExtendedDOMSlots() { 342 MOZ_COUNT_CTOR(FatSlots); 343 SetExtendedContentSlots(this, false); 344 } 345 346 ~FatSlots() final { MOZ_COUNT_DTOR(FatSlots); } 347 }; 348 349 protected: 350 void GetMarkup(bool aIncludeSelf, nsAString& aMarkup); 351 void SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult& aError); 352 353 // Override from nsINode 354 nsIContent::nsContentSlots* CreateSlots() override { 355 return new nsDOMSlots(); 356 } 357 358 nsIContent::nsExtendedContentSlots* CreateExtendedSlots() final { 359 return new nsExtendedDOMSlots(); 360 } 361 362 nsDOMSlots* DOMSlots() { return static_cast<nsDOMSlots*>(Slots()); } 363 364 nsDOMSlots* GetExistingDOMSlots() const { 365 return static_cast<nsDOMSlots*>(GetExistingSlots()); 366 } 367 368 nsExtendedDOMSlots* ExtendedDOMSlots() { 369 nsContentSlots* slots = GetExistingContentSlots(); 370 if (!slots) { 371 FatSlots* fatSlots = new FatSlots(); 372 mSlots = fatSlots; 373 return fatSlots; 374 } 375 376 if (!slots->GetExtendedContentSlots()) { 377 slots->SetExtendedContentSlots(CreateExtendedSlots(), true); 378 } 379 380 return static_cast<nsExtendedDOMSlots*>(slots->GetExtendedContentSlots()); 381 } 382 383 const nsExtendedDOMSlots* GetExistingExtendedDOMSlots() const { 384 return static_cast<const nsExtendedDOMSlots*>( 385 GetExistingExtendedContentSlots()); 386 } 387 388 nsExtendedDOMSlots* GetExistingExtendedDOMSlots() { 389 return static_cast<nsExtendedDOMSlots*>(GetExistingExtendedContentSlots()); 390 } 391 392 friend class ::ContentUnbinder; 393 }; 394 395 } // namespace mozilla::dom 396 397 #define NS_ELEMENT_INTERFACE_TABLE_TO_MAP_SEGUE \ 398 if (NS_SUCCEEDED(rv)) return rv; \ 399 \ 400 rv = FragmentOrElement::QueryInterface(aIID, aInstancePtr); \ 401 NS_INTERFACE_TABLE_TO_MAP_SEGUE 402 403 #endif /* FragmentOrElement_h___ */