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/. */
7 #include "mozilla/dom/StaticRange.h"
8 #include "mozilla/dom/StaticRangeBinding.h"
9 #include "nsContentUtils.h"
12 namespace mozilla::dom
{
14 template already_AddRefed
<StaticRange
> StaticRange::Create(
15 const RangeBoundary
& aStartBoundary
, const RangeBoundary
& aEndBoundary
,
17 template already_AddRefed
<StaticRange
> StaticRange::Create(
18 const RangeBoundary
& aStartBoundary
, const RawRangeBoundary
& aEndBoundary
,
20 template already_AddRefed
<StaticRange
> StaticRange::Create(
21 const RawRangeBoundary
& aStartBoundary
, const RangeBoundary
& aEndBoundary
,
23 template already_AddRefed
<StaticRange
> StaticRange::Create(
24 const RawRangeBoundary
& aStartBoundary
,
25 const RawRangeBoundary
& aEndBoundary
, ErrorResult
& aRv
);
26 template nsresult
StaticRange::SetStartAndEnd(
27 const RangeBoundary
& aStartBoundary
, const RangeBoundary
& aEndBoundary
);
28 template nsresult
StaticRange::SetStartAndEnd(
29 const RangeBoundary
& aStartBoundary
, const RawRangeBoundary
& aEndBoundary
);
30 template nsresult
StaticRange::SetStartAndEnd(
31 const RawRangeBoundary
& aStartBoundary
, const RangeBoundary
& aEndBoundary
);
32 template nsresult
StaticRange::SetStartAndEnd(
33 const RawRangeBoundary
& aStartBoundary
,
34 const RawRangeBoundary
& aEndBoundary
);
35 template void StaticRange::DoSetRange(const RangeBoundary
& aStartBoundary
,
36 const RangeBoundary
& aEndBoundary
,
38 template void StaticRange::DoSetRange(const RangeBoundary
& aStartBoundary
,
39 const RawRangeBoundary
& aEndBoundary
,
41 template void StaticRange::DoSetRange(const RawRangeBoundary
& aStartBoundary
,
42 const RangeBoundary
& aEndBoundary
,
44 template void StaticRange::DoSetRange(const RawRangeBoundary
& aStartBoundary
,
45 const RawRangeBoundary
& aEndBoundary
,
48 nsTArray
<RefPtr
<StaticRange
>>* StaticRange::sCachedRanges
= nullptr;
50 NS_IMPL_CYCLE_COLLECTING_ADDREF(StaticRange
)
51 NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_INTERRUPTABLE_LAST_RELEASE(
52 StaticRange
, DoSetRange(RawRangeBoundary(), RawRangeBoundary(), nullptr),
53 AbstractRange::MaybeCacheToReuse(*this))
55 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(StaticRange
)
56 NS_INTERFACE_MAP_END_INHERITING(AbstractRange
)
58 NS_IMPL_CYCLE_COLLECTION_CLASS(StaticRange
)
60 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(StaticRange
, AbstractRange
)
61 NS_IMPL_CYCLE_COLLECTION_UNLINK(mStart
)
62 NS_IMPL_CYCLE_COLLECTION_UNLINK(mEnd
)
63 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
65 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(StaticRange
, AbstractRange
)
66 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
68 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(StaticRange
, AbstractRange
)
69 NS_IMPL_CYCLE_COLLECTION_TRACE_END
72 already_AddRefed
<StaticRange
> StaticRange::Create(nsINode
* aNode
) {
74 if (!sCachedRanges
|| sCachedRanges
->IsEmpty()) {
75 return do_AddRef(new StaticRange(aNode
));
77 RefPtr
<StaticRange
> staticRange
= sCachedRanges
->PopLastElement().forget();
78 staticRange
->Init(aNode
);
79 return staticRange
.forget();
83 template <typename SPT
, typename SRT
, typename EPT
, typename ERT
>
84 already_AddRefed
<StaticRange
> StaticRange::Create(
85 const RangeBoundaryBase
<SPT
, SRT
>& aStartBoundary
,
86 const RangeBoundaryBase
<EPT
, ERT
>& aEndBoundary
, ErrorResult
& aRv
) {
87 RefPtr
<StaticRange
> staticRange
=
88 StaticRange::Create(aStartBoundary
.Container());
89 staticRange
->DoSetRange(aStartBoundary
, aEndBoundary
, nullptr);
91 return staticRange
.forget();
94 StaticRange::~StaticRange() {
95 DoSetRange(RawRangeBoundary(), RawRangeBoundary(), nullptr);
98 bool StaticRange::IsValid() const {
99 if (!mStart
.IsSetAndValid() || !mEnd
.IsSetAndValid()) {
103 const Maybe
<int32_t> pointOrder
= nsContentUtils::ComparePoints(mStart
, mEnd
);
104 return pointOrder
.isSome() && *pointOrder
<= 0;
107 template <typename SPT
, typename SRT
, typename EPT
, typename ERT
>
108 void StaticRange::DoSetRange(const RangeBoundaryBase
<SPT
, SRT
>& aStartBoundary
,
109 const RangeBoundaryBase
<EPT
, ERT
>& aEndBoundary
,
110 nsINode
* aRootNode
) {
111 bool checkCommonAncestor
=
112 IsInAnySelection() && (mStart
.Container() != aStartBoundary
.Container() ||
113 mEnd
.Container() != aEndBoundary
.Container());
114 mStart
.CopyFrom(aStartBoundary
, RangeBoundaryIsMutationObserved::No
);
115 mEnd
.CopyFrom(aEndBoundary
, RangeBoundaryIsMutationObserved::No
);
116 MOZ_ASSERT(mStart
.IsSet() == mEnd
.IsSet());
117 mIsPositioned
= mStart
.IsSet() && mEnd
.IsSet();
119 if (checkCommonAncestor
) {
120 UpdateCommonAncestorIfNecessary();
125 already_AddRefed
<StaticRange
> StaticRange::Constructor(
126 const GlobalObject
& global
, const StaticRangeInit
& init
, ErrorResult
& aRv
) {
127 if (init
.mStartContainer
->NodeType() == nsINode::DOCUMENT_TYPE_NODE
||
128 init
.mStartContainer
->NodeType() == nsINode::ATTRIBUTE_NODE
||
129 init
.mEndContainer
->NodeType() == nsINode::DOCUMENT_TYPE_NODE
||
130 init
.mEndContainer
->NodeType() == nsINode::ATTRIBUTE_NODE
) {
131 aRv
.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR
);
135 return Create(init
.mStartContainer
, init
.mStartOffset
, init
.mEndContainer
,
136 init
.mEndOffset
, aRv
);
139 JSObject
* StaticRange::WrapObject(JSContext
* aCx
,
140 JS::Handle
<JSObject
*> aGivenProto
) {
141 return StaticRange_Binding::Wrap(aCx
, this, aGivenProto
);
144 } // namespace mozilla::dom