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