Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/base/AttrArray.h
Line
Count
Source (jump to first uncovered line)
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
 * Storage of the attributes of a DOM node.
9
 */
10
11
#ifndef AttrArray_h___
12
#define AttrArray_h___
13
14
#include "mozilla/Attributes.h"
15
#include "mozilla/MemoryReporting.h"
16
#include "mozilla/UniquePtr.h"
17
#include "mozilla/Span.h"
18
#include "mozilla/dom/BorrowedAttrInfo.h"
19
20
#include "nscore.h"
21
#include "nsAttrName.h"
22
#include "nsAttrValue.h"
23
#include "nsCaseTreatment.h"
24
25
class nsINode;
26
class nsIContent;
27
class nsMappedAttributes;
28
class nsHTMLStyleSheet;
29
class nsRuleWalker;
30
class nsMappedAttributeElement;
31
32
class AttrArray
33
{
34
  typedef mozilla::dom::BorrowedAttrInfo BorrowedAttrInfo;
35
public:
36
0
  AttrArray() = default;
37
0
  ~AttrArray() = default;
38
39
  bool HasAttrs() const
40
0
  {
41
0
    return NonMappedAttrCount() || MappedAttrCount();
42
0
  }
43
44
  uint32_t AttrCount() const
45
0
  {
46
0
    return NonMappedAttrCount() + MappedAttrCount();
47
0
  }
48
49
  const nsAttrValue* GetAttr(nsAtom* aLocalName,
50
                             int32_t aNamespaceID = kNameSpaceID_None) const;
51
  // As above but using a string attr name and always using
52
  // kNameSpaceID_None.  This is always case-sensitive.
53
  const nsAttrValue* GetAttr(const nsAString& aName) const;
54
  // Get an nsAttrValue by qualified name.  Can optionally do
55
  // ASCII-case-insensitive name matching.
56
  const nsAttrValue* GetAttr(const nsAString& aName,
57
                             nsCaseTreatment aCaseSensitive) const;
58
  const nsAttrValue* AttrAt(uint32_t aPos) const;
59
  // SetAndSwapAttr swaps the current attribute value with aValue.
60
  // If the attribute was unset, an empty value will be swapped into aValue
61
  // and aHadValue will be set to false. Otherwise, aHadValue will be set to
62
  // true.
63
  nsresult SetAndSwapAttr(nsAtom* aLocalName, nsAttrValue& aValue,
64
                          bool* aHadValue);
65
  nsresult SetAndSwapAttr(mozilla::dom::NodeInfo* aName, nsAttrValue& aValue,
66
                          bool* aHadValue);
67
68
  // Remove the attr at position aPos.  The value of the attr is placed in
69
  // aValue; any value that was already in aValue is destroyed.
70
  nsresult RemoveAttrAt(uint32_t aPos, nsAttrValue& aValue);
71
72
  // Returns attribute name at given position, *not* out-of-bounds safe
73
  const nsAttrName* AttrNameAt(uint32_t aPos) const;
74
75
  // Returns the attribute info at a given position, *not* out-of-bounds safe
76
  BorrowedAttrInfo AttrInfoAt(uint32_t aPos) const;
77
78
  // Returns attribute name at given position or null if aPos is out-of-bounds
79
  const nsAttrName* GetSafeAttrNameAt(uint32_t aPos) const;
80
81
  const nsAttrName* GetExistingAttrNameFromQName(const nsAString& aName) const;
82
  int32_t IndexOfAttr(nsAtom* aLocalName, int32_t aNamespaceID = kNameSpaceID_None) const;
83
84
  // SetAndSwapMappedAttr swaps the current attribute value with aValue.
85
  // If the attribute was unset, an empty value will be swapped into aValue
86
  // and aHadValue will be set to false. Otherwise, aHadValue will be set to
87
  // true.
88
  nsresult SetAndSwapMappedAttr(nsAtom* aLocalName, nsAttrValue& aValue,
89
                                nsMappedAttributeElement* aContent,
90
                                nsHTMLStyleSheet* aSheet,
91
                                bool* aHadValue);
92
0
  nsresult SetMappedAttrStyleSheet(nsHTMLStyleSheet* aSheet) {
93
0
    if (!mImpl || !mImpl->mMappedAttrs) {
94
0
      return NS_OK;
95
0
    }
96
0
    return DoSetMappedAttrStyleSheet(aSheet);
97
0
  }
98
99
  // Update the rule mapping function on our mapped attributes, if we have any.
100
  // We take a nsMappedAttributeElement, not a nsMapRuleToAttributesFunc,
101
  // because the latter is defined in a header we can't include here.
102
  nsresult UpdateMappedAttrRuleMapper(nsMappedAttributeElement& aElement)
103
0
  {
104
0
    if (!mImpl || !mImpl->mMappedAttrs) {
105
0
      return NS_OK;
106
0
    }
107
0
    return DoUpdateMappedAttrRuleMapper(aElement);
108
0
  }
109
110
  void Compact();
111
112
  size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
113
  bool HasMappedAttrs() const
114
0
  {
115
0
    return MappedAttrCount();
116
0
  }
117
  const nsMappedAttributes* GetMapped() const;
118
119
  // Force this to have mapped attributes, even if those attributes are empty.
120
  nsresult ForceMapped(nsMappedAttributeElement* aContent, nsIDocument* aDocument);
121
122
  // Clear the servo declaration block on the mapped attributes, if any
123
  // Will assert off main thread
124
  void ClearMappedServoStyle();
125
126
  // Increases capacity (if necessary) to have enough space to accomodate the
127
  // unmapped attributes of |aOther|.
128
  nsresult EnsureCapacityToClone(const AttrArray& aOther);
129
130
  struct InternalAttr
131
  {
132
    nsAttrName mName;
133
    nsAttrValue mValue;
134
  };
135
136
private:
137
  AttrArray(const AttrArray& aOther) = delete;
138
  AttrArray& operator=(const AttrArray& aOther) = delete;
139
140
  uint32_t NonMappedAttrCount() const
141
0
  {
142
0
    return mImpl ? mImpl->mAttrCount : 0;
143
0
  }
144
145
  uint32_t MappedAttrCount() const
146
0
  {
147
0
    return mImpl && mImpl->mMappedAttrs ? DoGetMappedAttrCount() : 0;
148
0
  }
149
150
  uint32_t DoGetMappedAttrCount() const;
151
152
  // Returns a non-null zero-refcount object.
153
  nsMappedAttributes*
154
  GetModifiableMapped(nsMappedAttributeElement* aContent,
155
                      nsHTMLStyleSheet* aSheet,
156
                      bool aWillAddAttr,
157
                      int32_t aAttrCount = 1);
158
  nsresult MakeMappedUnique(nsMappedAttributes* aAttributes);
159
160
  bool GrowBy(uint32_t aGrowSize);
161
162
  // Tries to create an attribute, growing the buffer if needed, with the given
163
  // name and value.
164
  //
165
  // The value is moved from the argument.
166
  //
167
  // `Name` can be anything you construct a `nsAttrName` with (either an atom or
168
  // a NodeInfo pointer).
169
  template<typename Name>
170
  nsresult AddNewAttribute(Name*, nsAttrValue&);
171
172
  /**
173
   * Guts of SetMappedAttrStyleSheet for the rare case when we have mapped attrs
174
   */
175
  nsresult DoSetMappedAttrStyleSheet(nsHTMLStyleSheet* aSheet);
176
177
  /**
178
   * Guts of UpdateMappedAttrRuleMapper for the case  when we have mapped attrs.
179
   */
180
  nsresult DoUpdateMappedAttrRuleMapper(nsMappedAttributeElement& aElement);
181
182
#ifdef _MSC_VER
183
// Disable MSVC warning 'nonstandard extension used: zero-sized array in struct/union'
184
#pragma warning(push)
185
#pragma warning(disable:4200)
186
#endif
187
  class Impl
188
  {
189
  public:
190
191
    constexpr static size_t AllocationSizeForAttributes(uint32_t aAttrCount)
192
0
    {
193
0
      return sizeof(Impl) + aAttrCount * sizeof(InternalAttr);
194
0
    }
195
196
    mozilla::Span<const InternalAttr> NonMappedAttrs() const
197
0
    {
198
0
      return mozilla::MakeSpan(static_cast<const InternalAttr*>(mBuffer), mAttrCount);
199
0
    }
200
201
    mozilla::Span<InternalAttr> NonMappedAttrs()
202
0
    {
203
0
      return mozilla::MakeSpan(static_cast<InternalAttr*>(mBuffer), mAttrCount);
204
0
    }
205
206
    Impl(const Impl&) = delete;
207
    Impl(Impl&&) = delete;
208
    ~Impl();
209
210
    uint32_t mAttrCount;
211
    uint32_t mCapacity; // In number of InternalAttrs
212
213
    // Manually refcounted.
214
    nsMappedAttributes* mMappedAttrs;
215
216
    // Allocated in the same buffer as `Impl`.
217
    InternalAttr mBuffer[0];
218
  };
219
#ifdef _MSC_VER
220
#pragma warning(pop)
221
#endif
222
223
224
  mozilla::Span<InternalAttr> NonMappedAttrs()
225
0
  {
226
0
    return mImpl ? mImpl->NonMappedAttrs() : mozilla::Span<InternalAttr>();
227
0
  }
228
229
  mozilla::Span<const InternalAttr> NonMappedAttrs() const
230
0
  {
231
0
    return mImpl ? mImpl->NonMappedAttrs() : mozilla::Span<const InternalAttr>();
232
0
  }
233
234
  mozilla::UniquePtr<Impl> mImpl;
235
};
236
237
#endif