tor-browser

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

StaticRange.cpp (6552B)


      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 "mozilla/dom/StaticRange.h"
      8 
      9 #include "mozilla/dom/StaticRangeBinding.h"
     10 #include "nsContentUtils.h"
     11 #include "nsINode.h"
     12 
     13 namespace mozilla::dom {
     14 
     15 template already_AddRefed<StaticRange> StaticRange::Create(
     16    const RangeBoundary& aStartBoundary, const RangeBoundary& aEndBoundary,
     17    ErrorResult& aRv);
     18 template already_AddRefed<StaticRange> StaticRange::Create(
     19    const RangeBoundary& aStartBoundary, const RawRangeBoundary& aEndBoundary,
     20    ErrorResult& aRv);
     21 template already_AddRefed<StaticRange> StaticRange::Create(
     22    const RawRangeBoundary& aStartBoundary, const RangeBoundary& aEndBoundary,
     23    ErrorResult& aRv);
     24 template already_AddRefed<StaticRange> StaticRange::Create(
     25    const RawRangeBoundary& aStartBoundary,
     26    const RawRangeBoundary& aEndBoundary, ErrorResult& aRv);
     27 template nsresult StaticRange::SetStartAndEnd(
     28    const RangeBoundary& aStartBoundary, const RangeBoundary& aEndBoundary);
     29 template nsresult StaticRange::SetStartAndEnd(
     30    const RangeBoundary& aStartBoundary, const RawRangeBoundary& aEndBoundary);
     31 template nsresult StaticRange::SetStartAndEnd(
     32    const RawRangeBoundary& aStartBoundary, const RangeBoundary& aEndBoundary);
     33 template nsresult StaticRange::SetStartAndEnd(
     34    const RawRangeBoundary& aStartBoundary,
     35    const RawRangeBoundary& aEndBoundary);
     36 template void StaticRange::DoSetRange(const RangeBoundary& aStartBoundary,
     37                                      const RangeBoundary& aEndBoundary,
     38                                      nsINode* aRootNode);
     39 template void StaticRange::DoSetRange(const RangeBoundary& aStartBoundary,
     40                                      const RawRangeBoundary& aEndBoundary,
     41                                      nsINode* aRootNode);
     42 template void StaticRange::DoSetRange(const RawRangeBoundary& aStartBoundary,
     43                                      const RangeBoundary& aEndBoundary,
     44                                      nsINode* aRootNode);
     45 template void StaticRange::DoSetRange(const RawRangeBoundary& aStartBoundary,
     46                                      const RawRangeBoundary& aEndBoundary,
     47                                      nsINode* aRootNode);
     48 
     49 nsTArray<RefPtr<StaticRange>>* StaticRange::sCachedRanges = nullptr;
     50 
     51 NS_IMPL_CYCLE_COLLECTING_ADDREF(StaticRange)
     52 NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_INTERRUPTABLE_LAST_RELEASE(
     53    StaticRange, DoSetRange(RawRangeBoundary(), RawRangeBoundary(), nullptr),
     54    AbstractRange::MaybeCacheToReuse(*this))
     55 
     56 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(StaticRange)
     57 NS_INTERFACE_MAP_END_INHERITING(AbstractRange)
     58 
     59 NS_IMPL_CYCLE_COLLECTION_CLASS(StaticRange)
     60 
     61 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(StaticRange, AbstractRange)
     62  NS_IMPL_CYCLE_COLLECTION_UNLINK(mStart)
     63  NS_IMPL_CYCLE_COLLECTION_UNLINK(mEnd)
     64 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     65 
     66 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(StaticRange, AbstractRange)
     67 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     68 
     69 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(StaticRange, AbstractRange)
     70 NS_IMPL_CYCLE_COLLECTION_TRACE_END
     71 
     72 // static
     73 already_AddRefed<StaticRange> StaticRange::Create(nsINode* aNode) {
     74  MOZ_ASSERT(aNode);
     75  if (!sCachedRanges || sCachedRanges->IsEmpty()) {
     76    return do_AddRef(
     77        new StaticRange(aNode, RangeBoundaryIsMutationObserved::No));
     78  }
     79  RefPtr<StaticRange> staticRange = sCachedRanges->PopLastElement().forget();
     80  staticRange->Init(aNode);
     81  return staticRange.forget();
     82 }
     83 
     84 // static
     85 template <typename SPT, typename SRT, typename EPT, typename ERT>
     86 already_AddRefed<StaticRange> StaticRange::Create(
     87    const RangeBoundaryBase<SPT, SRT>& aStartBoundary,
     88    const RangeBoundaryBase<EPT, ERT>& aEndBoundary, ErrorResult& aRv) {
     89  RefPtr<StaticRange> staticRange =
     90      StaticRange::Create(aStartBoundary.GetContainer());
     91  staticRange->DoSetRange(aStartBoundary, aEndBoundary, nullptr);
     92 
     93  return staticRange.forget();
     94 }
     95 
     96 StaticRange::~StaticRange() {
     97  DoSetRange(RawRangeBoundary(mStart.GetTreeKind()),
     98             RawRangeBoundary(mEnd.GetTreeKind()), nullptr);
     99 }
    100 
    101 bool StaticRange::IsValid() const {
    102  if (!mStart.IsSetAndValid() || !mEnd.IsSetAndValid()) {
    103    return false;
    104  }
    105 
    106  MOZ_ASSERT(mAreStartAndEndInSameTree ==
    107             (RangeUtils::ComputeRootNode(mStart.GetContainer()) ==
    108              RangeUtils::ComputeRootNode(mEnd.GetContainer())));
    109  if (!mAreStartAndEndInSameTree) {
    110    return false;
    111  }
    112 
    113  const Maybe<int32_t> pointOrder = nsContentUtils::ComparePoints(mStart, mEnd);
    114  return pointOrder.isSome() && *pointOrder <= 0;
    115 }
    116 
    117 template <typename SPT, typename SRT, typename EPT, typename ERT>
    118 void StaticRange::DoSetRange(const RangeBoundaryBase<SPT, SRT>& aStartBoundary,
    119                             const RangeBoundaryBase<EPT, ERT>& aEndBoundary,
    120                             nsINode* aRootNode) {
    121  bool checkCommonAncestor =
    122      IsInAnySelection() &&
    123      (mStart.GetContainer() != aStartBoundary.GetContainer() ||
    124       mEnd.GetContainer() != aEndBoundary.GetContainer());
    125  mStart.CopyFrom(aStartBoundary, mIsMutationObserved);
    126  mEnd.CopyFrom(aEndBoundary, mIsMutationObserved);
    127  MOZ_ASSERT(mStart.IsSet() == mEnd.IsSet());
    128  mIsPositioned = mStart.IsSet() && mEnd.IsSet();
    129 
    130  if (checkCommonAncestor) {
    131    UpdateCommonAncestorIfNecessary();
    132  }
    133 
    134  mAreStartAndEndInSameTree =
    135      RangeUtils::ComputeRootNode(mStart.GetContainer()) ==
    136      RangeUtils::ComputeRootNode(mEnd.GetContainer());
    137 }
    138 
    139 /* static */
    140 already_AddRefed<StaticRange> StaticRange::Constructor(
    141    const GlobalObject& global, const StaticRangeInit& init, ErrorResult& aRv) {
    142  if (init.mStartContainer->NodeType() == nsINode::DOCUMENT_TYPE_NODE ||
    143      init.mStartContainer->NodeType() == nsINode::ATTRIBUTE_NODE ||
    144      init.mEndContainer->NodeType() == nsINode::DOCUMENT_TYPE_NODE ||
    145      init.mEndContainer->NodeType() == nsINode::ATTRIBUTE_NODE) {
    146    aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
    147    return nullptr;
    148  }
    149 
    150  return Create(init.mStartContainer, init.mStartOffset, init.mEndContainer,
    151                init.mEndOffset, aRv);
    152 }
    153 
    154 JSObject* StaticRange::WrapObject(JSContext* aCx,
    155                                  JS::Handle<JSObject*> aGivenProto) {
    156  return StaticRange_Binding::Wrap(aCx, this, aGivenProto);
    157 }
    158 
    159 }  // namespace mozilla::dom