/src/mozilla-central/dom/svg/DOMSVGNumberList.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 | | #ifndef MOZILLA_DOMSVGNUMBERLIST_H__ |
8 | | #define MOZILLA_DOMSVGNUMBERLIST_H__ |
9 | | |
10 | | #include "DOMSVGAnimatedNumberList.h" |
11 | | #include "nsCycleCollectionParticipant.h" |
12 | | #include "nsDebug.h" |
13 | | #include "nsTArray.h" |
14 | | #include "SVGNumberList.h" |
15 | | #include "mozilla/Attributes.h" |
16 | | #include "mozilla/ErrorResult.h" |
17 | | |
18 | | class nsSVGElement; |
19 | | |
20 | | namespace mozilla { |
21 | | |
22 | | class DOMSVGNumber; |
23 | | |
24 | | /** |
25 | | * Class DOMSVGNumberList |
26 | | * |
27 | | * This class is used to create the DOM tearoff objects that wrap internal |
28 | | * SVGNumberList objects. |
29 | | * |
30 | | * See the architecture comment in DOMSVGAnimatedNumberList.h. |
31 | | * |
32 | | * This class is strongly intertwined with DOMSVGAnimatedNumberList and |
33 | | * DOMSVGNumber. We are a friend of DOMSVGAnimatedNumberList, and are |
34 | | * responsible for nulling out our DOMSVGAnimatedNumberList's pointer to us |
35 | | * when we die, essentially making its pointer to us a weak pointer. Similarly, |
36 | | * our DOMSVGNumber items are friends of us and responsible for nulling out our |
37 | | * pointers to them. |
38 | | * |
39 | | * Our DOM items are created lazily on demand as and when script requests them. |
40 | | */ |
41 | | class DOMSVGNumberList final : public nsISupports, |
42 | | public nsWrapperCache |
43 | | { |
44 | | friend class AutoChangeNumberListNotifier; |
45 | | friend class DOMSVGNumber; |
46 | | |
47 | 0 | ~DOMSVGNumberList() { |
48 | 0 | // Our mAList's weak ref to us must be nulled out when we die. If GC has |
49 | 0 | // unlinked us using the cycle collector code, then that has already |
50 | 0 | // happened, and mAList is null. |
51 | 0 | if (mAList) { |
52 | 0 | ( IsAnimValList() ? mAList->mAnimVal : mAList->mBaseVal ) = nullptr; |
53 | 0 | } |
54 | 0 | } |
55 | | |
56 | | public: |
57 | | NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
58 | | NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGNumberList) |
59 | | |
60 | | DOMSVGNumberList(DOMSVGAnimatedNumberList *aAList, |
61 | | const SVGNumberList &aInternalList) |
62 | | : mAList(aAList) |
63 | 0 | { |
64 | 0 | // aInternalList must be passed in explicitly because we can't use |
65 | 0 | // InternalList() here. (Because it depends on IsAnimValList, which depends |
66 | 0 | // on this object having been assigned to aAList's mBaseVal or mAnimVal, |
67 | 0 | // which hasn't happened yet.) |
68 | 0 |
|
69 | 0 | InternalListLengthWillChange(aInternalList.Length()); // Sync mItems |
70 | 0 | } |
71 | | |
72 | | virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override; |
73 | | |
74 | | nsISupports* GetParentObject() |
75 | 0 | { |
76 | 0 | return static_cast<nsIContent*>(Element()); |
77 | 0 | } |
78 | | |
79 | | /** |
80 | | * This will normally be the same as InternalList().Length(), except if we've |
81 | | * hit OOM in which case our length will be zero. |
82 | | */ |
83 | 0 | uint32_t LengthNoFlush() const { |
84 | 0 | MOZ_ASSERT(mItems.Length() == 0 || |
85 | 0 | mItems.Length() == InternalList().Length(), |
86 | 0 | "DOM wrapper's list length is out of sync"); |
87 | 0 | return mItems.Length(); |
88 | 0 | } |
89 | | |
90 | | /// Called to notify us to synchronize our length and detach excess items. |
91 | | void InternalListLengthWillChange(uint32_t aNewLength); |
92 | | |
93 | | /** |
94 | | * Returns true if our attribute is animating (in which case our animVal is |
95 | | * not simply a mirror of our baseVal). |
96 | | */ |
97 | 0 | bool IsAnimating() const { |
98 | 0 | return mAList->IsAnimating(); |
99 | 0 | } |
100 | | /** |
101 | | * Returns true if there is an animated list mirroring the base list. |
102 | | */ |
103 | 0 | bool AnimListMirrorsBaseList() const { |
104 | 0 | return mAList->mAnimVal && !mAList->IsAnimating(); |
105 | 0 | } |
106 | | |
107 | | uint32_t NumberOfItems() const |
108 | 0 | { |
109 | 0 | if (IsAnimValList()) { |
110 | 0 | Element()->FlushAnimations(); |
111 | 0 | } |
112 | 0 | return LengthNoFlush(); |
113 | 0 | } |
114 | | void Clear(ErrorResult& error); |
115 | | already_AddRefed<DOMSVGNumber> Initialize(DOMSVGNumber& newItem, |
116 | | ErrorResult& error); |
117 | | already_AddRefed<DOMSVGNumber> GetItem(uint32_t index, ErrorResult& error); |
118 | | already_AddRefed<DOMSVGNumber> IndexedGetter(uint32_t index, bool& found, |
119 | | ErrorResult& error); |
120 | | already_AddRefed<DOMSVGNumber> InsertItemBefore(DOMSVGNumber& newItem, |
121 | | uint32_t index, ErrorResult& error); |
122 | | already_AddRefed<DOMSVGNumber> ReplaceItem(DOMSVGNumber& newItem, uint32_t index, |
123 | | ErrorResult& error); |
124 | | already_AddRefed<DOMSVGNumber> RemoveItem(uint32_t index, |
125 | | ErrorResult& error); |
126 | | already_AddRefed<DOMSVGNumber> AppendItem(DOMSVGNumber& newItem, |
127 | | ErrorResult& error) |
128 | 0 | { |
129 | 0 | return InsertItemBefore(newItem, LengthNoFlush(), error); |
130 | 0 | } |
131 | | uint32_t Length() const |
132 | 0 | { |
133 | 0 | return NumberOfItems(); |
134 | 0 | } |
135 | | |
136 | | private: |
137 | | |
138 | 0 | nsSVGElement* Element() const { |
139 | 0 | return mAList->mElement; |
140 | 0 | } |
141 | | |
142 | 0 | uint8_t AttrEnum() const { |
143 | 0 | return mAList->mAttrEnum; |
144 | 0 | } |
145 | | |
146 | | /// Used to determine if this list is the baseVal or animVal list. |
147 | 0 | bool IsAnimValList() const { |
148 | 0 | MOZ_ASSERT(this == mAList->mBaseVal || this == mAList->mAnimVal, |
149 | 0 | "Calling IsAnimValList() too early?!"); |
150 | 0 | return this == mAList->mAnimVal; |
151 | 0 | } |
152 | | |
153 | | /** |
154 | | * Get a reference to this object's corresponding internal SVGNumberList. |
155 | | * |
156 | | * To simplify the code we just have this one method for obtaining both |
157 | | * baseVal and animVal internal lists. This means that animVal lists don't |
158 | | * get const protection, but our setter methods guard against changing |
159 | | * animVal lists. |
160 | | */ |
161 | | SVGNumberList& InternalList() const; |
162 | | |
163 | | /// Returns the DOMSVGNumber at aIndex, creating it if necessary. |
164 | | already_AddRefed<DOMSVGNumber> GetItemAt(uint32_t aIndex); |
165 | | |
166 | | void MaybeInsertNullInAnimValListAt(uint32_t aIndex); |
167 | | void MaybeRemoveItemFromAnimValListAt(uint32_t aIndex); |
168 | | |
169 | | // Weak refs to our DOMSVGNumber items. The items are friends and take care |
170 | | // of clearing our pointer to them when they die. |
171 | | FallibleTArray<DOMSVGNumber*> mItems; |
172 | | |
173 | | RefPtr<DOMSVGAnimatedNumberList> mAList; |
174 | | }; |
175 | | |
176 | | } // namespace mozilla |
177 | | |
178 | | #endif // MOZILLA_DOMSVGNUMBERLIST_H__ |