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  * A unique per-element set of attributes that is used as an
9  * nsIStyleRule; used to implement presentational attributes.
10  */
11 
12 #ifndef nsMappedAttributes_h___
13 #define nsMappedAttributes_h___
14 
15 #include "AttrArray.h"
16 #include "nsMappedAttributeElement.h"
17 #include "mozilla/Attributes.h"
18 #include "mozilla/ServoBindingTypes.h"
19 #include "mozilla/MemoryReporting.h"
20 
21 class nsAtom;
22 class nsHTMLStyleSheet;
23 
24 class nsMappedAttributes final {
25   using InternalAttr = AttrArray::InternalAttr;
26 
27  public:
28   nsMappedAttributes(nsHTMLStyleSheet* aSheet,
29                      nsMapRuleToAttributesFunc aMapRuleFunc);
30 
31   // Do not return null.
32   void* operator new(size_t size, uint32_t aAttrCount = 1) noexcept(true);
33   nsMappedAttributes* Clone(bool aWillAddAttr);
34 
35   NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(nsMappedAttributes, LastRelease())
36 
37   void SetAndSwapAttr(nsAtom* aAttrName, nsAttrValue& aValue,
38                       bool* aValueWasSet);
39   const nsAttrValue* GetAttr(const nsAtom* aAttrName) const;
40   const nsAttrValue* GetAttr(const nsAString& aAttrName) const;
41 
Count()42   uint32_t Count() const { return mAttrCount; }
43 
44   bool Equals(const nsMappedAttributes* aAttributes) const;
45   PLDHashNumber HashValue() const;
46 
DropStyleSheetReference()47   void DropStyleSheetReference() { mSheet = nullptr; }
48   void SetStyleSheet(nsHTMLStyleSheet* aSheet);
GetStyleSheet()49   nsHTMLStyleSheet* GetStyleSheet() { return mSheet; }
50 
SetRuleMapper(nsMapRuleToAttributesFunc aRuleMapper)51   void SetRuleMapper(nsMapRuleToAttributesFunc aRuleMapper) {
52     mRuleMapper = aRuleMapper;
53   }
54 
Attrs()55   auto Attrs() const {
56     return mozilla::Span<const InternalAttr>{mBuffer, mAttrCount};
57   }
Attrs()58   auto Attrs() { return mozilla::Span<InternalAttr>{mBuffer, mAttrCount}; }
NameAt(uint32_t aPos)59   const nsAttrName* NameAt(uint32_t aPos) const {
60     NS_ASSERTION(aPos < mAttrCount, "out-of-bounds");
61     return &Attrs()[aPos].mName;
62   }
AttrAt(uint32_t aPos)63   const nsAttrValue* AttrAt(uint32_t aPos) const {
64     NS_ASSERTION(aPos < mAttrCount, "out-of-bounds");
65     return &Attrs()[aPos].mValue;
66   }
67   // Remove the attr at position aPos.  The value of the attr is placed in
68   // aValue; any value that was already in aValue is destroyed.
69   void RemoveAttrAt(uint32_t aPos, nsAttrValue& aValue);
70   const nsAttrName* GetExistingAttrNameFromQName(const nsAString& aName) const;
71   int32_t IndexOfAttr(const nsAtom* aLocalName) const;
72 
73   // Apply the contained mapper to the contained set of servo rules,
74   // unless the servo rules have already been initialized.
75   void LazilyResolveServoDeclaration(mozilla::dom::Document* aDocument);
76 
77   // Obtain the contained servo declaration block
78   // May return null if called before the inner block
79   // has been (lazily) resolved
GetServoStyle()80   const RefPtr<RawServoDeclarationBlock>& GetServoStyle() const {
81     return mServoStyle;
82   }
83 
ClearServoStyle()84   void ClearServoStyle() {
85     MOZ_ASSERT(NS_IsMainThread());
86     mServoStyle = nullptr;
87   }
88 
89   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
90 
91   static void Shutdown();
92 
93  private:
94   void LastRelease();
95 
96   nsMappedAttributes(const nsMappedAttributes& aCopy);
97   ~nsMappedAttributes();
98 
99   uint16_t mAttrCount;
100 #ifdef DEBUG
101   uint16_t mBufferSize;
102 #endif
103   nsHTMLStyleSheet* mSheet;  // weak
104   nsMapRuleToAttributesFunc mRuleMapper;
105   RefPtr<RawServoDeclarationBlock> mServoStyle;
106   InternalAttr mBuffer[0];
107 
108   static bool sShuttingDown;
109 
110   // We're caching some memory to avoid trashing the allocator.
111   // The memory stored at index N can hold N attribute values.
112   static nsTArray<void*>* sCachedMappedAttributeAllocations;
113 };
114 
115 #endif /* nsMappedAttributes_h___ */
116