DOMSVGAnimatedNumberList.cpp (4643B)
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 #include "DOMSVGAnimatedNumberList.h" 8 9 #include "DOMSVGNumberList.h" 10 #include "SVGAnimatedNumberList.h" 11 #include "SVGAttrTearoffTable.h" 12 #include "mozilla/RefPtr.h" 13 #include "mozilla/dom/SVGAnimatedNumberListBinding.h" 14 #include "mozilla/dom/SVGElement.h" 15 16 // See the architecture comment in this file's header. 17 18 namespace mozilla::dom { 19 20 static inline SVGAttrTearoffTable<SVGAnimatedNumberList, 21 DOMSVGAnimatedNumberList>& 22 SVGAnimatedNumberListTearoffTable() { 23 static SVGAttrTearoffTable<SVGAnimatedNumberList, DOMSVGAnimatedNumberList> 24 sSVGAnimatedNumberListTearoffTable; 25 return sSVGAnimatedNumberListTearoffTable; 26 } 27 28 NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(DOMSVGAnimatedNumberList, 29 mElement) 30 31 JSObject* DOMSVGAnimatedNumberList::WrapObject( 32 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { 33 return mozilla::dom::SVGAnimatedNumberList_Binding::Wrap(aCx, this, 34 aGivenProto); 35 } 36 37 already_AddRefed<DOMSVGNumberList> DOMSVGAnimatedNumberList::BaseVal() { 38 if (!mBaseVal) { 39 mBaseVal = new DOMSVGNumberList(this, InternalAList().GetBaseValue()); 40 } 41 RefPtr<DOMSVGNumberList> baseVal = mBaseVal; 42 return baseVal.forget(); 43 } 44 45 already_AddRefed<DOMSVGNumberList> DOMSVGAnimatedNumberList::AnimVal() { 46 if (!mAnimVal) { 47 mAnimVal = new DOMSVGNumberList(this, InternalAList().GetAnimValue()); 48 } 49 RefPtr<DOMSVGNumberList> animVal = mAnimVal; 50 return animVal.forget(); 51 } 52 53 /* static */ 54 already_AddRefed<DOMSVGAnimatedNumberList> 55 DOMSVGAnimatedNumberList::GetDOMWrapper(SVGAnimatedNumberList* aList, 56 dom::SVGElement* aElement, 57 uint8_t aAttrEnum) { 58 RefPtr<DOMSVGAnimatedNumberList> wrapper = 59 SVGAnimatedNumberListTearoffTable().GetTearoff(aList); 60 if (!wrapper) { 61 wrapper = new DOMSVGAnimatedNumberList(aElement, aAttrEnum); 62 SVGAnimatedNumberListTearoffTable().AddTearoff(aList, wrapper); 63 } 64 return wrapper.forget(); 65 } 66 67 /* static */ 68 DOMSVGAnimatedNumberList* DOMSVGAnimatedNumberList::GetDOMWrapperIfExists( 69 SVGAnimatedNumberList* aList) { 70 return SVGAnimatedNumberListTearoffTable().GetTearoff(aList); 71 } 72 73 DOMSVGAnimatedNumberList::~DOMSVGAnimatedNumberList() { 74 // Script no longer has any references to us, to our base/animVal objects, or 75 // to any of their list items. 76 SVGAnimatedNumberListTearoffTable().RemoveTearoff(&InternalAList()); 77 } 78 79 void DOMSVGAnimatedNumberList::InternalBaseValListWillChangeTo( 80 const SVGNumberList& aNewValue) { 81 // When the number of items in our internal counterpart's baseVal changes, 82 // we MUST keep our baseVal in sync. If we don't, script will either see a 83 // list that is too short and be unable to access indexes that should be 84 // valid, or else, MUCH WORSE, script will see a list that is too long and be 85 // able to access "items" at indexes that are out of bounds (read/write to 86 // bad memory)!! 87 88 RefPtr<DOMSVGAnimatedNumberList> kungFuDeathGrip; 89 if (mBaseVal) { 90 if (aNewValue.Length() < mBaseVal->LengthNoFlush()) { 91 // InternalListLengthWillChange might clear last reference to |this|. 92 // Retain a temporary reference to keep from dying before returning. 93 kungFuDeathGrip = this; 94 } 95 mBaseVal->InternalListLengthWillChange(aNewValue.Length()); 96 } 97 98 // If our attribute is not animating, then our animVal mirrors our baseVal 99 // and we must sync its length too. (If our attribute is animating, then the 100 // SMIL engine takes care of calling InternalAnimValListWillChangeTo() if 101 // necessary.) 102 103 if (!IsAnimating()) { 104 InternalAnimValListWillChangeTo(aNewValue); 105 } 106 } 107 108 void DOMSVGAnimatedNumberList::InternalAnimValListWillChangeTo( 109 const SVGNumberList& aNewValue) { 110 if (mAnimVal) { 111 mAnimVal->InternalListLengthWillChange(aNewValue.Length()); 112 } 113 } 114 115 bool DOMSVGAnimatedNumberList::IsAnimating() const { 116 return InternalAList().IsAnimating(); 117 } 118 119 SVGAnimatedNumberList& DOMSVGAnimatedNumberList::InternalAList() { 120 return *mElement->GetAnimatedNumberList(mAttrEnum); 121 } 122 123 const SVGAnimatedNumberList& DOMSVGAnimatedNumberList::InternalAList() const { 124 return *mElement->GetAnimatedNumberList(mAttrEnum); 125 } 126 127 } // namespace mozilla::dom