Bug 1892041 - Part 1: Update test262 features. r=spidermonkey-reviewers,dminor
[gecko.git] / dom / base / Highlight.cpp
blobcd0efccce58c9a27f426de0372d5c282d5d75d40
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
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 "Highlight.h"
8 #include "HighlightRegistry.h"
9 #include "mozilla/StaticAnalysisFunctions.h"
10 #include "mozilla/dom/HighlightBinding.h"
12 #include "mozilla/AlreadyAddRefed.h"
13 #include "mozilla/ErrorResult.h"
14 #include "mozilla/RefPtr.h"
16 #include "AbstractRange.h"
17 #include "Document.h"
18 #include "PresShell.h"
19 #include "Selection.h"
21 #include "nsFrameSelection.h"
22 #include "nsPIDOMWindow.h"
24 namespace mozilla::dom {
26 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Highlight, mRanges, mWindow)
28 NS_IMPL_CYCLE_COLLECTING_ADDREF(Highlight)
29 NS_IMPL_CYCLE_COLLECTING_RELEASE(Highlight)
31 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Highlight)
32 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
33 NS_INTERFACE_MAP_ENTRY(nsISupports)
34 NS_INTERFACE_MAP_END
36 Highlight::Highlight(
37 const Sequence<OwningNonNull<AbstractRange>>& aInitialRanges,
38 nsPIDOMWindowInner* aWindow, ErrorResult& aRv)
39 : mWindow(aWindow) {
40 for (RefPtr<AbstractRange> range : aInitialRanges) {
41 Add(*range, aRv);
42 if (aRv.Failed()) {
43 return;
48 already_AddRefed<Highlight> Highlight::Constructor(
49 const GlobalObject& aGlobal,
50 const Sequence<OwningNonNull<AbstractRange>>& aInitialRanges,
51 ErrorResult& aRv) {
52 MOZ_ASSERT(NS_IsMainThread());
53 nsCOMPtr<nsPIDOMWindowInner> window =
54 do_QueryInterface(aGlobal.GetAsSupports());
55 if (!window) {
56 aRv.ThrowUnknownError(
57 "There is no window associated to "
58 "this highlight object!");
59 return nullptr;
62 RefPtr<Highlight> highlight = new Highlight(aInitialRanges, window, aRv);
63 return aRv.Failed() ? nullptr : highlight.forget();
66 void Highlight::AddToHighlightRegistry(HighlightRegistry& aHighlightRegistry,
67 nsAtom& aHighlightName) {
68 mHighlightRegistries.LookupOrInsert(&aHighlightRegistry)
69 .Insert(&aHighlightName);
72 void Highlight::RemoveFromHighlightRegistry(
73 HighlightRegistry& aHighlightRegistry, nsAtom& aHighlightName) {
74 if (auto entry = mHighlightRegistries.Lookup(&aHighlightRegistry)) {
75 auto& highlightNames = entry.Data();
76 highlightNames.Remove(&aHighlightName);
77 if (highlightNames.IsEmpty()) {
78 entry.Remove();
83 already_AddRefed<Selection> Highlight::CreateHighlightSelection(
84 nsAtom* aHighlightName, nsFrameSelection* aFrameSelection) {
85 MOZ_ASSERT(aFrameSelection);
86 MOZ_ASSERT(aFrameSelection->GetPresShell());
87 RefPtr<Selection> selection =
88 MakeRefPtr<Selection>(SelectionType::eHighlight, aFrameSelection);
89 selection->SetHighlightSelectionData({aHighlightName, this});
90 AutoFrameSelectionBatcher selectionBatcher(__FUNCTION__);
91 for (const RefPtr<AbstractRange>& range : mRanges) {
92 if (range->GetComposedDocOfContainers() ==
93 aFrameSelection->GetPresShell()->GetDocument()) {
94 // since this is run in a context guarded by a selection batcher,
95 // no strong reference is needed to keep `range` alive.
96 selection->AddHighlightRangeAndSelectFramesAndNotifyListeners(
97 MOZ_KnownLive(*range));
100 return selection.forget();
103 void Highlight::Add(AbstractRange& aRange, ErrorResult& aRv) {
104 Highlight_Binding::SetlikeHelpers::Add(this, aRange, aRv);
105 if (aRv.Failed()) {
106 return;
108 if (!mRanges.Contains(&aRange)) {
109 mRanges.AppendElement(&aRange);
110 AutoFrameSelectionBatcher selectionBatcher(__FUNCTION__,
111 mHighlightRegistries.Count());
112 for (const RefPtr<HighlightRegistry>& registry :
113 mHighlightRegistries.Keys()) {
114 auto frameSelection = registry->GetFrameSelection();
115 selectionBatcher.AddFrameSelection(frameSelection);
116 // since this is run in a context guarded by a selection batcher,
117 // no strong reference is needed to keep `registry` alive.
118 MOZ_KnownLive(registry)->MaybeAddRangeToHighlightSelection(aRange, *this);
119 if (aRv.Failed()) {
120 return;
126 void Highlight::Clear(ErrorResult& aRv) {
127 Highlight_Binding::SetlikeHelpers::Clear(this, aRv);
128 if (!aRv.Failed()) {
129 mRanges.Clear();
130 AutoFrameSelectionBatcher selectionBatcher(__FUNCTION__,
131 mHighlightRegistries.Count());
133 for (const RefPtr<HighlightRegistry>& registry :
134 mHighlightRegistries.Keys()) {
135 auto frameSelection = registry->GetFrameSelection();
136 selectionBatcher.AddFrameSelection(frameSelection);
137 // since this is run in a context guarded by a selection batcher,
138 // no strong reference is needed to keep `registry` alive.
139 MOZ_KnownLive(registry)->RemoveHighlightSelection(*this);
144 bool Highlight::Delete(AbstractRange& aRange, ErrorResult& aRv) {
145 if (Highlight_Binding::SetlikeHelpers::Delete(this, aRange, aRv)) {
146 mRanges.RemoveElement(&aRange);
147 AutoFrameSelectionBatcher selectionBatcher(__FUNCTION__,
148 mHighlightRegistries.Count());
150 for (const RefPtr<HighlightRegistry>& registry :
151 mHighlightRegistries.Keys()) {
152 auto frameSelection = registry->GetFrameSelection();
153 selectionBatcher.AddFrameSelection(frameSelection);
154 // since this is run in a context guarded by a selection batcher,
155 // no strong reference is needed to keep `registry` alive.
156 MOZ_KnownLive(registry)->MaybeRemoveRangeFromHighlightSelection(aRange,
157 *this);
159 return true;
161 return false;
164 JSObject* Highlight::WrapObject(JSContext* aCx,
165 JS::Handle<JSObject*> aGivenProto) {
166 return Highlight_Binding::Wrap(aCx, this, aGivenProto);
169 } // namespace mozilla::dom