StaticRange.h (5958B)
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_dom_StaticRange_h 8 #define mozilla_dom_StaticRange_h 9 10 #include "mozilla/RangeBoundary.h" 11 #include "mozilla/RangeUtils.h" 12 #include "mozilla/dom/AbstractRange.h" 13 #include "mozilla/dom/StaticRangeBinding.h" 14 #include "nsTArray.h" 15 #include "nsWrapperCache.h" 16 17 namespace mozilla { 18 class ErrorResult; 19 20 namespace dom { 21 22 class StaticRange : public AbstractRange { 23 public: 24 StaticRange() = delete; 25 explicit StaticRange(const StaticRange& aOther) = delete; 26 27 static already_AddRefed<StaticRange> Constructor(const GlobalObject& global, 28 const StaticRangeInit& init, 29 ErrorResult& aRv); 30 31 /** 32 * The following Create() returns `nsRange` instance which is initialized 33 * only with aNode. The result is never positioned. 34 */ 35 static already_AddRefed<StaticRange> Create(nsINode* aNode); 36 37 /** 38 * Create() may return `StaticRange` instance which is initialized with 39 * given range or points. If it fails initializing new range with the 40 * arguments, returns `nullptr`. `ErrorResult` is set to an error only 41 * when this returns `nullptr`. The error code indicates the reason why 42 * it couldn't initialize the instance. 43 */ 44 static already_AddRefed<StaticRange> Create( 45 const AbstractRange* aAbstractRange, ErrorResult& aRv) { 46 MOZ_ASSERT(aAbstractRange); 47 return StaticRange::Create(aAbstractRange->StartRef(), 48 aAbstractRange->EndRef(), aRv); 49 } 50 static already_AddRefed<StaticRange> Create(nsINode* aStartContainer, 51 uint32_t aStartOffset, 52 nsINode* aEndContainer, 53 uint32_t aEndOffset, 54 ErrorResult& aRv) { 55 return StaticRange::Create( 56 RawRangeBoundary(aStartContainer, aStartOffset, 57 RangeBoundaryIsMutationObserved::No), 58 RawRangeBoundary(aEndContainer, aEndOffset, 59 RangeBoundaryIsMutationObserved::No), 60 aRv); 61 } 62 template <typename SPT, typename SRT, typename EPT, typename ERT> 63 static already_AddRefed<StaticRange> Create( 64 const RangeBoundaryBase<SPT, SRT>& aStartBoundary, 65 const RangeBoundaryBase<EPT, ERT>& aEndBoundary, ErrorResult& aRv); 66 67 /** 68 * Returns true if the range is valid. 69 * 70 * @see https://dom.spec.whatwg.org/#staticrange-valid 71 */ 72 bool IsValid() const; 73 74 private: 75 // Whether the start and end points are in the same tree. 76 // They could be in different trees, i.e, cross shadow boundaries. 77 bool mAreStartAndEndInSameTree = false; 78 79 // Whether mutation is observed. 80 RangeBoundaryIsMutationObserved mIsMutationObserved; 81 82 protected: 83 explicit StaticRange(nsINode* aNode, 84 RangeBoundaryIsMutationObserved aIsMutationObserved, 85 TreeKind aBoundaryTreeKind = TreeKind::DOM) 86 : AbstractRange(aNode, /* aIsDynamicRange = */ false, aBoundaryTreeKind), 87 mIsMutationObserved(aIsMutationObserved) {} 88 virtual ~StaticRange(); 89 90 public: 91 NS_DECL_ISUPPORTS_INHERITED 92 NS_IMETHODIMP_(void) DeleteCycleCollectable(void) override; 93 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(StaticRange, 94 AbstractRange) 95 96 JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) final; 97 98 /** 99 * SetStartAndEnd() works similar to call both SetStart() and SetEnd(). 100 * Different from calls them separately, this does nothing if either 101 * the start point or the end point is invalid point. 102 * If the specified start point is after the end point, the range will be 103 * collapsed at the end point. Similarly, if they are in different root, 104 * the range will be collapsed at the end point. 105 */ 106 nsresult SetStartAndEnd(nsINode* aStartContainer, uint32_t aStartOffset, 107 nsINode* aEndContainer, uint32_t aEndOffset) { 108 return SetStartAndEnd(RawRangeBoundary(aStartContainer, aStartOffset), 109 RawRangeBoundary(aEndContainer, aEndOffset)); 110 } 111 template <typename SPT, typename SRT, typename EPT, typename ERT> 112 nsresult SetStartAndEnd(const RangeBoundaryBase<SPT, SRT>& aStartBoundary, 113 const RangeBoundaryBase<EPT, ERT>& aEndBoundary) { 114 return AbstractRange::SetStartAndEndInternal(aStartBoundary, aEndBoundary, 115 this); 116 } 117 118 protected: 119 /** 120 * DoSetRange() is called when `AbstractRange::SetStartAndEndInternal()` sets 121 * mStart and mEnd. 122 * 123 * @param aStartBoundary Computed start point. This must equals or be before 124 * aEndBoundary in the DOM tree order. 125 * @param aEndBoundary Computed end point. 126 * @param aRootNode The root node. 127 */ 128 template <typename SPT, typename SRT, typename EPT, typename ERT> 129 void DoSetRange(const RangeBoundaryBase<SPT, SRT>& aStartBoundary, 130 const RangeBoundaryBase<EPT, ERT>& aEndBoundary, 131 nsINode* aRootNode); 132 133 static nsTArray<RefPtr<StaticRange>>* sCachedRanges; 134 135 friend class AbstractRange; 136 }; 137 138 inline StaticRange* AbstractRange::AsStaticRange() { 139 MOZ_ASSERT(IsStaticRange()); 140 return static_cast<StaticRange*>(this); 141 } 142 inline const StaticRange* AbstractRange::AsStaticRange() const { 143 MOZ_ASSERT(IsStaticRange()); 144 return static_cast<const StaticRange*>(this); 145 } 146 147 } // namespace dom 148 } // namespace mozilla 149 150 #endif // #ifndef mozilla_dom_StaticRange_h