Bug 1665252 - remove allowpaymentrequest attribute from HTMLIFrameElement r=dom-worke...
[gecko.git] / dom / base / nsMappedAttributes.cpp
blob4771d2cdce3a55dc27343994424e91423e57cb88
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/. */
7 /*
8 * A unique per-element set of attributes that is used as an
9 * nsIStyleRule; used to implement presentational attributes.
12 #include "nsMappedAttributes.h"
13 #include "mozilla/Assertions.h"
14 #include "nsHTMLStyleSheet.h"
15 #include "mozilla/DeclarationBlock.h"
16 #include "mozilla/HashFunctions.h"
17 #include "mozilla/MappedDeclarations.h"
18 #include "mozilla/MemoryReporting.h"
20 using namespace mozilla;
22 bool nsMappedAttributes::sShuttingDown = false;
23 nsTArray<void*>* nsMappedAttributes::sCachedMappedAttributeAllocations =
24 nullptr;
26 void nsMappedAttributes::Shutdown() {
27 sShuttingDown = true;
28 if (sCachedMappedAttributeAllocations) {
29 for (uint32_t i = 0; i < sCachedMappedAttributeAllocations->Length(); ++i) {
30 void* cachedValue = (*sCachedMappedAttributeAllocations)[i];
31 ::operator delete(cachedValue);
35 delete sCachedMappedAttributeAllocations;
36 sCachedMappedAttributeAllocations = nullptr;
39 nsMappedAttributes::nsMappedAttributes(nsHTMLStyleSheet* aSheet,
40 nsMapRuleToAttributesFunc aMapRuleFunc)
41 : mAttrCount(0),
42 mSheet(aSheet),
43 mRuleMapper(aMapRuleFunc),
44 mServoStyle(nullptr) {
45 MOZ_ASSERT(mRefCnt == 0); // Ensure caching works as expected.
48 nsMappedAttributes::nsMappedAttributes(const nsMappedAttributes& aCopy)
49 : mAttrCount(aCopy.mAttrCount),
50 mSheet(aCopy.mSheet),
51 mRuleMapper(aCopy.mRuleMapper),
52 // This is only called by ::Clone, which is used to create independent
53 // nsMappedAttributes objects which should not share a DeclarationBlock
54 mServoStyle(nullptr) {
55 MOZ_ASSERT(mBufferSize >= aCopy.mAttrCount, "can't fit attributes");
56 MOZ_ASSERT(mRefCnt == 0); // Ensure caching works as expected.
58 uint32_t i;
59 for (i = 0; i < mAttrCount; ++i) {
60 new (&Attrs()[i]) InternalAttr(aCopy.Attrs()[i]);
64 nsMappedAttributes::~nsMappedAttributes() {
65 if (mSheet) {
66 mSheet->DropMappedAttributes(this);
69 uint32_t i;
70 for (i = 0; i < mAttrCount; ++i) {
71 Attrs()[i].~InternalAttr();
75 nsMappedAttributes* nsMappedAttributes::Clone(bool aWillAddAttr) {
76 uint32_t extra = aWillAddAttr ? 1 : 0;
78 // This will call the overridden operator new
79 return new (mAttrCount + extra) nsMappedAttributes(*this);
82 void* nsMappedAttributes::operator new(size_t aSize,
83 uint32_t aAttrCount) noexcept(true) {
84 size_t size = aSize + aAttrCount * sizeof(InternalAttr);
86 // aSize will include the mAttrs buffer so subtract that.
87 // We don't want to under-allocate, however, so do not subtract
88 // if we have zero attributes. The zero attribute case only happens
89 // for <body>'s mapped attributes
90 if (aAttrCount != 0) {
91 size -= sizeof(void* [1]);
94 if (sCachedMappedAttributeAllocations) {
95 void* cached = sCachedMappedAttributeAllocations->SafeElementAt(aAttrCount);
96 if (cached) {
97 (*sCachedMappedAttributeAllocations)[aAttrCount] = nullptr;
98 return cached;
102 void* newAttrs = ::operator new(size);
104 #ifdef DEBUG
105 static_cast<nsMappedAttributes*>(newAttrs)->mBufferSize = aAttrCount;
106 #endif
107 return newAttrs;
110 void nsMappedAttributes::LastRelease() {
111 if (!sShuttingDown) {
112 if (!sCachedMappedAttributeAllocations) {
113 sCachedMappedAttributeAllocations = new nsTArray<void*>();
116 // Ensure the cache array is at least mAttrCount + 1 long and
117 // that each item is either null or pointing to a cached item.
118 // The size of the array is capped because mapped attributes are defined
119 // statically in element implementations.
120 sCachedMappedAttributeAllocations->SetCapacity(mAttrCount + 1);
121 for (uint32_t i = sCachedMappedAttributeAllocations->Length();
122 i < (uint32_t(mAttrCount) + 1); ++i) {
123 sCachedMappedAttributeAllocations->AppendElement(nullptr);
126 if (!(*sCachedMappedAttributeAllocations)[mAttrCount]) {
127 void* memoryToCache = this;
128 this->~nsMappedAttributes();
129 (*sCachedMappedAttributeAllocations)[mAttrCount] = memoryToCache;
130 return;
134 delete this;
137 void nsMappedAttributes::SetAndSwapAttr(nsAtom* aAttrName, nsAttrValue& aValue,
138 bool* aValueWasSet) {
139 MOZ_ASSERT(aAttrName, "null name");
140 *aValueWasSet = false;
141 uint32_t i;
142 for (i = 0; i < mAttrCount && !Attrs()[i].mName.IsSmaller(aAttrName); ++i) {
143 if (Attrs()[i].mName.Equals(aAttrName)) {
144 Attrs()[i].mValue.SwapValueWith(aValue);
145 *aValueWasSet = true;
146 return;
150 MOZ_ASSERT(mBufferSize >= mAttrCount + 1, "can't fit attributes");
152 if (mAttrCount != i) {
153 memmove(&Attrs()[i + 1], &Attrs()[i],
154 (mAttrCount - i) * sizeof(InternalAttr));
157 new (&Attrs()[i].mName) nsAttrName(aAttrName);
158 new (&Attrs()[i].mValue) nsAttrValue();
159 Attrs()[i].mValue.SwapValueWith(aValue);
160 ++mAttrCount;
163 const nsAttrValue* nsMappedAttributes::GetAttr(const nsAtom* aAttrName) const {
164 MOZ_ASSERT(aAttrName, "null name");
166 for (uint32_t i = 0; i < mAttrCount; ++i) {
167 if (Attrs()[i].mName.Equals(aAttrName)) {
168 return &Attrs()[i].mValue;
172 return nullptr;
175 const nsAttrValue* nsMappedAttributes::GetAttr(
176 const nsAString& aAttrName) const {
177 for (uint32_t i = 0; i < mAttrCount; ++i) {
178 if (Attrs()[i].mName.Atom()->Equals(aAttrName)) {
179 return &Attrs()[i].mValue;
183 return nullptr;
186 bool nsMappedAttributes::Equals(const nsMappedAttributes* aOther) const {
187 if (this == aOther) {
188 return true;
191 if (mRuleMapper != aOther->mRuleMapper || mAttrCount != aOther->mAttrCount) {
192 return false;
195 uint32_t i;
196 for (i = 0; i < mAttrCount; ++i) {
197 if (!Attrs()[i].mName.Equals(aOther->Attrs()[i].mName) ||
198 !Attrs()[i].mValue.Equals(aOther->Attrs()[i].mValue)) {
199 return false;
203 return true;
206 PLDHashNumber nsMappedAttributes::HashValue() const {
207 PLDHashNumber hash = HashGeneric(mRuleMapper);
209 uint32_t i;
210 for (i = 0; i < mAttrCount; ++i) {
211 hash = AddToHash(hash, Attrs()[i].mName.HashValue(),
212 Attrs()[i].mValue.HashValue());
215 return hash;
218 void nsMappedAttributes::SetStyleSheet(nsHTMLStyleSheet* aSheet) {
219 MOZ_ASSERT(!mSheet,
220 "Should either drop the sheet reference manually, "
221 "or drop the mapped attributes");
222 mSheet = aSheet; // not ref counted
225 void nsMappedAttributes::RemoveAttrAt(uint32_t aPos, nsAttrValue& aValue) {
226 Attrs()[aPos].mValue.SwapValueWith(aValue);
227 Attrs()[aPos].~InternalAttr();
228 memmove(&Attrs()[aPos], &Attrs()[aPos + 1],
229 (mAttrCount - aPos - 1) * sizeof(InternalAttr));
230 mAttrCount--;
233 const nsAttrName* nsMappedAttributes::GetExistingAttrNameFromQName(
234 const nsAString& aName) const {
235 uint32_t i;
236 for (i = 0; i < mAttrCount; ++i) {
237 if (Attrs()[i].mName.IsAtom()) {
238 if (Attrs()[i].mName.Atom()->Equals(aName)) {
239 return &Attrs()[i].mName;
241 } else {
242 if (Attrs()[i].mName.NodeInfo()->QualifiedNameEquals(aName)) {
243 return &Attrs()[i].mName;
248 return nullptr;
251 int32_t nsMappedAttributes::IndexOfAttr(const nsAtom* aLocalName) const {
252 uint32_t i;
253 for (i = 0; i < mAttrCount; ++i) {
254 if (Attrs()[i].mName.Equals(aLocalName)) {
255 return i;
259 return -1;
262 size_t nsMappedAttributes::SizeOfIncludingThis(
263 MallocSizeOf aMallocSizeOf) const {
264 MOZ_ASSERT(mBufferSize >= mAttrCount, "can't fit attributes");
266 size_t n = aMallocSizeOf(this);
267 for (uint16_t i = 0; i < mAttrCount; ++i) {
268 n += Attrs()[i].mValue.SizeOfExcludingThis(aMallocSizeOf);
270 return n;
273 void nsMappedAttributes::LazilyResolveServoDeclaration(dom::Document* aDoc) {
274 MOZ_ASSERT(!mServoStyle,
275 "LazilyResolveServoDeclaration should not be called if "
276 "mServoStyle is already set");
277 if (mRuleMapper) {
278 MappedDeclarations declarations(
279 aDoc, Servo_DeclarationBlock_CreateEmpty().Consume());
280 (*mRuleMapper)(this, declarations);
281 mServoStyle = declarations.TakeDeclarationBlock();