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 #ifndef DOM_SVG_DOMSVGNUMBERLIST_H_
8 #define DOM_SVG_DOMSVGNUMBERLIST_H_
10 #include "DOMSVGAnimatedNumberList.h"
11 #include "mozAutoDocUpdate.h"
12 #include "nsCycleCollectionParticipant.h"
15 #include "SVGNumberList.h"
16 #include "mozilla/Attributes.h"
17 #include "mozilla/RefPtr.h"
26 //----------------------------------------------------------------------
27 // Helper class: AutoChangeNumberListNotifier
28 // Stack-based helper class to pair calls to WillChangeNumberList and
29 // DidChangeNumberList. Used by DOMSVGNumber and DOMSVGNumberList.
31 class MOZ_RAII AutoChangeNumberListNotifier
: public mozAutoDocUpdate
{
33 explicit AutoChangeNumberListNotifier(T
* aValue
)
34 : mozAutoDocUpdate(aValue
->Element()->GetComposedDoc(), true),
36 MOZ_ASSERT(mValue
, "Expecting non-null value");
38 mValue
->Element()->WillChangeNumberList(mValue
->AttrEnum(), *this);
41 ~AutoChangeNumberListNotifier() {
42 mValue
->Element()->DidChangeNumberList(mValue
->AttrEnum(), mEmptyOrOldValue
,
44 if (mValue
->IsAnimating()) {
45 mValue
->Element()->AnimationNeedsResample();
51 nsAttrValue mEmptyOrOldValue
;
55 * Class DOMSVGNumberList
57 * This class is used to create the DOM tearoff objects that wrap internal
58 * SVGNumberList objects.
60 * See the architecture comment in DOMSVGAnimatedNumberList.h.
62 * This class is strongly intertwined with DOMSVGAnimatedNumberList and
63 * DOMSVGNumber. We are a friend of DOMSVGAnimatedNumberList, and are
64 * responsible for nulling out our DOMSVGAnimatedNumberList's pointer to us
65 * when we die, essentially making its pointer to us a weak pointer. Similarly,
66 * our DOMSVGNumber items are friends of us and responsible for nulling out our
69 * Our DOM items are created lazily on demand as and when script requests them.
71 class DOMSVGNumberList final
: public nsISupports
, public nsWrapperCache
{
73 friend class AutoChangeNumberListNotifier
;
74 friend class DOMSVGNumber
;
77 // Our mAList's weak ref to us must be nulled out when we die. If GC has
78 // unlinked us using the cycle collector code, then that has already
79 // happened, and mAList is null.
81 (IsAnimValList() ? mAList
->mAnimVal
: mAList
->mBaseVal
) = nullptr;
86 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
87 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGNumberList
)
89 DOMSVGNumberList(DOMSVGAnimatedNumberList
* aAList
,
90 const SVGNumberList
& aInternalList
)
92 // aInternalList must be passed in explicitly because we can't use
93 // InternalList() here. (Because it depends on IsAnimValList, which depends
94 // on this object having been assigned to aAList's mBaseVal or mAnimVal,
95 // which hasn't happened yet.)
97 InternalListLengthWillChange(aInternalList
.Length()); // Sync mItems
100 virtual JSObject
* WrapObject(JSContext
* cx
,
101 JS::Handle
<JSObject
*> aGivenProto
) override
;
103 nsISupports
* GetParentObject() { return static_cast<nsIContent
*>(Element()); }
106 * This will normally be the same as InternalList().Length(), except if we've
107 * hit OOM in which case our length will be zero.
109 uint32_t LengthNoFlush() const {
111 mItems
.Length() == 0 || mItems
.Length() == InternalList().Length(),
112 "DOM wrapper's list length is out of sync");
113 return mItems
.Length();
116 /// Called to notify us to synchronize our length and detach excess items.
117 void InternalListLengthWillChange(uint32_t aNewLength
);
120 * Returns true if our attribute is animating (in which case our animVal is
121 * not simply a mirror of our baseVal).
123 bool IsAnimating() const { return mAList
->IsAnimating(); }
125 * Returns true if there is an animated list mirroring the base list.
127 bool AnimListMirrorsBaseList() const {
128 return mAList
->mAnimVal
&& !mAList
->IsAnimating();
131 uint32_t NumberOfItems() const {
132 if (IsAnimValList()) {
133 Element()->FlushAnimations();
135 return LengthNoFlush();
137 void Clear(ErrorResult
& error
);
138 already_AddRefed
<DOMSVGNumber
> Initialize(DOMSVGNumber
& aItem
,
140 already_AddRefed
<DOMSVGNumber
> GetItem(uint32_t index
, ErrorResult
& error
);
141 already_AddRefed
<DOMSVGNumber
> IndexedGetter(uint32_t index
, bool& found
,
143 already_AddRefed
<DOMSVGNumber
> InsertItemBefore(DOMSVGNumber
& aItem
,
146 already_AddRefed
<DOMSVGNumber
> ReplaceItem(DOMSVGNumber
& aItem
,
149 already_AddRefed
<DOMSVGNumber
> RemoveItem(uint32_t index
, ErrorResult
& error
);
150 already_AddRefed
<DOMSVGNumber
> AppendItem(DOMSVGNumber
& newItem
,
151 ErrorResult
& error
) {
152 return InsertItemBefore(newItem
, LengthNoFlush(), error
);
154 uint32_t Length() const { return NumberOfItems(); }
157 dom::SVGElement
* Element() const { return mAList
->mElement
; }
159 uint8_t AttrEnum() const { return mAList
->mAttrEnum
; }
161 /// Used to determine if this list is the baseVal or animVal list.
162 bool IsAnimValList() const {
163 MOZ_ASSERT(this == mAList
->mBaseVal
|| this == mAList
->mAnimVal
,
164 "Calling IsAnimValList() too early?!");
165 return this == mAList
->mAnimVal
;
169 * Get a reference to this object's corresponding internal SVGNumberList.
171 * To simplify the code we just have this one method for obtaining both
172 * baseVal and animVal internal lists. This means that animVal lists don't
173 * get const protection, but our setter methods guard against changing
176 SVGNumberList
& InternalList() const;
178 /// Returns the DOMSVGNumber at aIndex, creating it if necessary.
179 already_AddRefed
<DOMSVGNumber
> GetItemAt(uint32_t aIndex
);
181 void MaybeInsertNullInAnimValListAt(uint32_t aIndex
);
182 void MaybeRemoveItemFromAnimValListAt(uint32_t aIndex
);
184 // Weak refs to our DOMSVGNumber items. The items are friends and take care
185 // of clearing our pointer to them when they die.
186 FallibleTArray
<DOMSVGNumber
*> mItems
;
188 RefPtr
<DOMSVGAnimatedNumberList
> mAList
;
192 } // namespace mozilla
194 #endif // DOM_SVG_DOMSVGNUMBERLIST_H_