tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

DOMSVGLengthList.h (7272B)


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