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