Bug 1936278 - Prevent search mode chiclet from being dismissed when clicking in page...
[gecko.git] / dom / svg / DOMSVGStringList.cpp
blob4f5c72ea176b633d57751eeff5c92126ed6a9345
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 #include "DOMSVGStringList.h"
9 #include "mozAutoDocUpdate.h"
10 #include "mozilla/dom/SVGStringListBinding.h"
11 #include "mozilla/dom/SVGTests.h"
12 #include "nsCOMPtr.h"
13 #include "nsError.h"
14 #include "nsQueryObject.h"
15 #include "SVGAttrTearoffTable.h"
16 #include <algorithm>
18 // See the architecture comment in this file's header.
20 namespace mozilla::dom {
22 static inline SVGAttrTearoffTable<SVGStringList, DOMSVGStringList>&
23 SVGStringListTearoffTable() {
24 static SVGAttrTearoffTable<SVGStringList, DOMSVGStringList>
25 sSVGStringListTearoffTable;
26 return sSVGStringListTearoffTable;
29 NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGStringList)
31 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGStringList)
32 // No unlinking of mElement, we'd need to null out the value pointer (the
33 // object it points to is held by the element) and null-check it everywhere.
34 tmp->RemoveFromTearoffTable();
35 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
36 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
37 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGStringList)
38 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElement)
39 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
40 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGStringList)
41 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
42 NS_IMPL_CYCLE_COLLECTION_TRACE_END
44 NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGStringList)
45 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGStringList)
47 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGStringList)
48 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
49 NS_INTERFACE_MAP_ENTRY(nsISupports)
50 NS_INTERFACE_MAP_END
52 //----------------------------------------------------------------------
53 // Helper class: AutoChangeStringListNotifier
54 // Stack-based helper class to pair calls to WillChangeStringListList and
55 // DidChangeStringListList.
56 class MOZ_RAII AutoChangeStringListNotifier : public mozAutoDocUpdate {
57 public:
58 explicit AutoChangeStringListNotifier(DOMSVGStringList* aStringList)
59 : mozAutoDocUpdate(aStringList->mElement->GetComposedDoc(), true),
60 mStringList(aStringList) {
61 MOZ_ASSERT(mStringList, "Expecting non-null stringList");
62 mEmptyOrOldValue = mStringList->mElement->WillChangeStringList(
63 mStringList->mIsConditionalProcessingAttribute, mStringList->mAttrEnum,
64 *this);
67 ~AutoChangeStringListNotifier() {
68 mStringList->mElement->DidChangeStringList(
69 mStringList->mIsConditionalProcessingAttribute, mStringList->mAttrEnum,
70 mEmptyOrOldValue, *this);
73 private:
74 DOMSVGStringList* const mStringList;
75 nsAttrValue mEmptyOrOldValue;
78 /* static */
79 already_AddRefed<DOMSVGStringList> DOMSVGStringList::GetDOMWrapper(
80 SVGStringList* aList, SVGElement* aElement,
81 bool aIsConditionalProcessingAttribute, uint8_t aAttrEnum) {
82 RefPtr<DOMSVGStringList> wrapper =
83 SVGStringListTearoffTable().GetTearoff(aList);
84 if (!wrapper) {
85 wrapper = new DOMSVGStringList(aElement, aIsConditionalProcessingAttribute,
86 aAttrEnum);
87 SVGStringListTearoffTable().AddTearoff(aList, wrapper);
89 return wrapper.forget();
92 void DOMSVGStringList::RemoveFromTearoffTable() {
93 // Script no longer has any references to us.
94 SVGStringListTearoffTable().RemoveTearoff(&InternalList());
97 DOMSVGStringList::~DOMSVGStringList() { RemoveFromTearoffTable(); }
99 /* virtual */
100 JSObject* DOMSVGStringList::WrapObject(JSContext* aCx,
101 JS::Handle<JSObject*> aGivenProto) {
102 return SVGStringList_Binding::Wrap(aCx, this, aGivenProto);
105 // ----------------------------------------------------------------------------
106 // SVGStringList implementation:
108 uint32_t DOMSVGStringList::NumberOfItems() const {
109 return InternalList().Length();
112 uint32_t DOMSVGStringList::Length() const { return NumberOfItems(); }
114 void DOMSVGStringList::Clear() {
115 if (InternalList().IsExplicitlySet()) {
116 AutoChangeStringListNotifier notifier(this);
117 InternalList().Clear();
121 void DOMSVGStringList::Initialize(const nsAString& aNewItem, nsAString& aRetval,
122 ErrorResult& aRv) {
123 if (InternalList().IsExplicitlySet()) {
124 InternalList().Clear();
126 InsertItemBefore(aNewItem, 0, aRetval, aRv);
129 void DOMSVGStringList::GetItem(uint32_t aIndex, nsAString& aRetval,
130 ErrorResult& aRv) {
131 bool found;
132 IndexedGetter(aIndex, found, aRetval);
133 if (!found) {
134 aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
138 void DOMSVGStringList::IndexedGetter(uint32_t aIndex, bool& aFound,
139 nsAString& aRetval) {
140 aFound = aIndex < InternalList().Length();
141 if (aFound) {
142 aRetval = InternalList()[aIndex];
146 void DOMSVGStringList::InsertItemBefore(const nsAString& aNewItem,
147 uint32_t aIndex, nsAString& aRetval,
148 ErrorResult& aRv) {
149 if (aNewItem.IsEmpty()) {
150 aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
151 return;
153 aIndex = std::min(aIndex, InternalList().Length());
155 // Ensure we have enough memory so we can avoid complex error handling below:
156 if (!InternalList().SetCapacity(InternalList().Length() + 1)) {
157 aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
158 return;
161 AutoChangeStringListNotifier notifier(this);
162 InternalList().InsertItem(aIndex, aNewItem);
163 aRetval = aNewItem;
166 void DOMSVGStringList::ReplaceItem(const nsAString& aNewItem, uint32_t aIndex,
167 nsAString& aRetval, ErrorResult& aRv) {
168 if (aNewItem.IsEmpty()) {
169 aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
170 return;
172 if (aIndex >= InternalList().Length()) {
173 aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
174 return;
177 aRetval = InternalList()[aIndex];
178 AutoChangeStringListNotifier notifier(this);
179 InternalList().ReplaceItem(aIndex, aNewItem);
182 void DOMSVGStringList::RemoveItem(uint32_t aIndex, nsAString& aRetval,
183 ErrorResult& aRv) {
184 if (aIndex >= InternalList().Length()) {
185 aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
186 return;
189 AutoChangeStringListNotifier notifier(this);
190 InternalList().RemoveItem(aIndex);
193 void DOMSVGStringList::AppendItem(const nsAString& aNewItem, nsAString& aRetval,
194 ErrorResult& aRv) {
195 InsertItemBefore(aNewItem, InternalList().Length(), aRetval, aRv);
198 SVGStringList& DOMSVGStringList::InternalList() const {
199 if (mIsConditionalProcessingAttribute) {
200 nsCOMPtr<dom::SVGTests> tests = do_QueryObject(mElement);
201 return tests->mStringListAttributes[mAttrEnum];
203 return mElement->GetStringListInfo().mValues[mAttrEnum];
206 } // namespace mozilla::dom