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/. */
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.
13 #ifndef FragmentOrElement_h___
14 #define FragmentOrElement_h___
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 "nsCycleCollectionParticipant.h" // NS_DECL_CYCLE_*
22 #include "nsIContent.h" // base class
23 #include "nsAtomHashKeys.h"
24 #include "nsIHTMLCollection.h"
25 #include "nsIWeakReferenceUtils.h"
27 class ContentUnbinder
;
29 class nsLabelsNodeList
;
30 class nsDOMAttributeMap
;
33 class nsICSSDeclaration
;
34 class nsDOMCSSAttributeDeclaration
;
39 class DeclarationBlock
;
40 enum class ContentRelevancyReason
;
41 using ContentRelevancy
= EnumSet
<ContentRelevancyReason
, uint8_t>;
42 class ElementAnimationData
;
44 struct CustomElementData
;
48 } // namespace mozilla
51 * Tearoff to use for nodes to implement nsISupportsWeakReference
53 class nsNodeSupportsWeakRefTearoff final
: public nsISupportsWeakReference
{
55 explicit nsNodeSupportsWeakRefTearoff(nsINode
* aNode
) : mNode(aNode
) {}
58 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
60 // nsISupportsWeakReference
61 NS_DECL_NSISUPPORTSWEAKREFERENCE
63 NS_DECL_CYCLE_COLLECTION_CLASS(nsNodeSupportsWeakRefTearoff
)
66 ~nsNodeSupportsWeakRefTearoff() = default;
68 nsCOMPtr
<nsINode
> mNode
;
72 * A generic base class for DOM elements and document fragments,
73 * implementing many nsIContent, nsINode and Element methods.
75 namespace mozilla::dom
{
77 class DOMIntersectionObserver
;
80 class FragmentOrElement
: public nsIContent
{
82 explicit FragmentOrElement(
83 already_AddRefed
<mozilla::dom::NodeInfo
>& aNodeInfo
);
84 explicit FragmentOrElement(
85 already_AddRefed
<mozilla::dom::NodeInfo
>&& aNodeInfo
);
87 // We want to avoid the overhead of extra function calls for
88 // refcounting when we're not doing refcount logging, so we can't
89 // NS_DECL_ISUPPORTS_INHERITED.
90 NS_IMETHOD
QueryInterface(REFNSIID aIID
, void** aInstancePtr
) override
;
91 NS_INLINE_DECL_REFCOUNTING_INHERITED(FragmentOrElement
, nsIContent
);
93 NS_DECL_ADDSIZEOFEXCLUDINGTHIS
95 // nsINode interface methods
96 virtual void GetTextContentInternal(nsAString
& aTextContent
,
97 mozilla::OOMReporter
& aError
) override
;
98 virtual void SetTextContentInternal(const nsAString
& aTextContent
,
99 nsIPrincipal
* aSubjectPrincipal
,
100 mozilla::ErrorResult
& aError
) override
;
102 // nsIContent interface methods
103 const nsTextFragment
* GetText() override
;
104 uint32_t TextLength() const override
;
105 bool TextIsOnlyWhitespace() override
;
106 bool ThreadSafeTextIsOnlyWhitespace() const override
;
108 void DestroyContent() override
;
109 void SaveSubtreeState() override
;
111 nsIHTMLCollection
* Children();
112 uint32_t ChildElementCount() {
113 if (!HasChildren()) {
116 return Children()->Length();
119 RadioGroupContainer
& OwnedRadioGroupContainer() {
120 auto* slots
= ExtendedDOMSlots();
121 if (!slots
->mRadioGroupContainer
) {
122 slots
->mRadioGroupContainer
= MakeUnique
<RadioGroupContainer
>();
124 return *slots
->mRadioGroupContainer
;
129 * If there are listeners for DOMNodeInserted event, fires the event on all
132 static void FireNodeInserted(Document
* aDoc
, nsINode
* aParent
,
133 const nsTArray
<nsCOMPtr
<nsIContent
>>& aNodes
);
135 NS_DECL_CYCLE_COLLECTION_SKIPPABLE_WRAPPERCACHE_CLASS_INHERITED(
136 FragmentOrElement
, nsIContent
)
138 static void ClearContentUnbinder();
139 static bool CanSkip(nsINode
* aNode
, bool aRemovingAllowed
);
140 static bool CanSkipInCC(nsINode
* aNode
);
141 static bool CanSkipThis(nsINode
* aNode
);
142 static void RemoveBlackMarkedNode(nsINode
* aNode
);
143 static void MarkNodeChildren(nsINode
* aNode
);
144 static void InitCCCallbacks();
147 * Is the HTML local name a void element?
149 static bool IsHTMLVoid(nsAtom
* aLocalName
);
152 virtual ~FragmentOrElement();
155 * Dummy CopyInnerTo so that we can use the same macros for
156 * Elements and DocumentFragments.
158 nsresult
CopyInnerTo(FragmentOrElement
* aDest
) { return NS_OK
; }
162 * There are a set of DOM- and scripting-specific instance variables
163 * that may only be instantiated when a content object is accessed
164 * through the DOM. Rather than burn actual slots in the content
165 * objects for each of these instance variables, we put them off
166 * in a side structure that's only allocated when the content is
167 * accessed through the DOM.
170 class nsExtendedDOMSlots
: public nsIContent::nsExtendedContentSlots
{
172 nsExtendedDOMSlots();
173 ~nsExtendedDOMSlots();
175 void TraverseExtendedSlots(nsCycleCollectionTraversalCallback
&) final
;
176 void UnlinkExtendedSlots(nsIContent
&) final
;
178 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf
) const final
;
181 * SMIL Overridde style rules (for SMIL animation of CSS properties)
182 * @see Element::GetSMILOverrideStyle
184 RefPtr
<nsDOMCSSAttributeDeclaration
> mSMILOverrideStyle
;
187 * Holds any SMIL override style declaration for this element.
189 RefPtr
<DeclarationBlock
> mSMILOverrideStyleDeclaration
;
192 * The controllers of the XUL Element.
194 nsCOMPtr
<nsIControllers
> mControllers
;
197 * An object implementing the .labels property for this element.
199 RefPtr
<nsLabelsNodeList
> mLabelsList
;
202 * ShadowRoot bound to the element.
204 RefPtr
<ShadowRoot
> mShadowRoot
;
207 * Web components custom element data.
209 UniquePtr
<CustomElementData
> mCustomElementData
;
212 * Web animations data.
214 UniquePtr
<ElementAnimationData
> mAnimations
;
217 * PopoverData for the element.
219 UniquePtr
<PopoverData
> mPopoverData
;
222 * CustomStates for the element.
224 nsTArray
<RefPtr
<nsAtom
>> mCustomStates
;
227 * RadioGroupContainer for radio buttons grouped under this disconnected
230 UniquePtr
<RadioGroupContainer
> mRadioGroupContainer
;
233 * Last remembered size (in CSS pixels) for the element.
234 * @see {@link https://drafts.csswg.org/css-sizing-4/#last-remembered}
236 Maybe
<float> mLastRememberedBSize
;
237 Maybe
<float> mLastRememberedISize
;
240 * Whether the content of this element is relevant for the purposes
241 * of `content-visibility: auto.
242 * Reflects 'relevant to the user' concept, see
243 * https://drafts.csswg.org/css-contain/#relevant-to-the-user.
245 Maybe
<ContentRelevancy
> mContentRelevancy
;
248 * Whether the content of this element is considered visible for
249 * the purposes of `content-visibility: auto.
250 * Reflects 'proximity to the viewport' concept, see
251 * https://drafts.csswg.org/css-contain/#proximity-to-the-viewport.
253 Maybe
<bool> mVisibleForContentVisibility
;
256 * Whether content-visibility: auto is temporarily visible for
257 * the purposes of the descendant of scrollIntoView.
259 bool mTemporarilyVisibleForScrolledIntoViewDescendant
= false;
262 * The .dataset attribute.
263 * @see nsGenericHTMLElement::GetDataset
265 nsDOMStringMap
* MOZ_UNSAFE_REF("ClearDataSet clears it") mDataset
= nullptr;
267 /** An object implementing the .part property for this element. */
268 RefPtr
<nsDOMTokenList
> mPart
;
271 * Explicitly set attr-element, see
272 * https://html.spec.whatwg.org/#explicitly-set-attr-element
274 nsTHashMap
<RefPtr
<nsAtom
>, nsWeakPtr
> mExplicitlySetAttrElementMap
;
276 * Explicitly set attr-elements, see
277 * https://html.spec.whatwg.org/#explicitly-set-attr-elements
279 * The first member of the pair are the explicitly set attr-elements. The
280 * second member is the cached attr-associated elements.
283 nsTHashMap
<RefPtr
<nsAtom
>, std::pair
<Maybe
<nsTArray
<nsWeakPtr
>>,
284 Maybe
<nsTArray
<RefPtr
<Element
>>>>>
288 class nsDOMSlots
: public nsIContent::nsContentSlots
{
293 void Traverse(nsCycleCollectionTraversalCallback
&) final
;
294 void Unlink(nsINode
&) final
;
296 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const;
299 * The .style attribute (an interface that forwards to the actual
301 * @see nsGenericHTMLElement::GetStyle
303 nsCOMPtr
<nsICSSDeclaration
> mStyle
;
306 * @see Element::Attributes
308 RefPtr
<nsDOMAttributeMap
> mAttributeMap
;
311 * An object implementing the .children property for this element.
313 RefPtr
<nsContentList
> mChildrenList
;
316 * An object implementing the .classList property for this element.
318 RefPtr
<nsDOMTokenList
> mClassList
;
322 * In case ExtendedDOMSlots is needed before normal DOMSlots, an instance of
323 * FatSlots class, which combines those two slot types, is created.
324 * This way we can avoid extra allocation for ExtendedDOMSlots.
325 * FatSlots is useful for example when creating Custom Elements.
327 class FatSlots final
: public nsDOMSlots
, public nsExtendedDOMSlots
{
329 FatSlots() : nsDOMSlots(), nsExtendedDOMSlots() {
330 MOZ_COUNT_CTOR(FatSlots
);
331 SetExtendedContentSlots(this, false);
334 ~FatSlots() final
{ MOZ_COUNT_DTOR(FatSlots
); }
338 void GetMarkup(bool aIncludeSelf
, nsAString
& aMarkup
);
339 void SetInnerHTMLInternal(const nsAString
& aInnerHTML
, ErrorResult
& aError
);
341 // Override from nsINode
342 nsIContent::nsContentSlots
* CreateSlots() override
{
343 return new nsDOMSlots();
346 nsIContent::nsExtendedContentSlots
* CreateExtendedSlots() final
{
347 return new nsExtendedDOMSlots();
350 nsDOMSlots
* DOMSlots() { return static_cast<nsDOMSlots
*>(Slots()); }
352 nsDOMSlots
* GetExistingDOMSlots() const {
353 return static_cast<nsDOMSlots
*>(GetExistingSlots());
356 nsExtendedDOMSlots
* ExtendedDOMSlots() {
357 nsContentSlots
* slots
= GetExistingContentSlots();
359 FatSlots
* fatSlots
= new FatSlots();
364 if (!slots
->GetExtendedContentSlots()) {
365 slots
->SetExtendedContentSlots(CreateExtendedSlots(), true);
368 return static_cast<nsExtendedDOMSlots
*>(slots
->GetExtendedContentSlots());
371 const nsExtendedDOMSlots
* GetExistingExtendedDOMSlots() const {
372 return static_cast<const nsExtendedDOMSlots
*>(
373 GetExistingExtendedContentSlots());
376 nsExtendedDOMSlots
* GetExistingExtendedDOMSlots() {
377 return static_cast<nsExtendedDOMSlots
*>(GetExistingExtendedContentSlots());
380 friend class ::ContentUnbinder
;
383 } // namespace mozilla::dom
385 #define NS_ELEMENT_INTERFACE_TABLE_TO_MAP_SEGUE \
386 if (NS_SUCCEEDED(rv)) return rv; \
388 rv = FragmentOrElement::QueryInterface(aIID, aInstancePtr); \
389 NS_INTERFACE_TABLE_TO_MAP_SEGUE
391 #endif /* FragmentOrElement_h___ */