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 "AbortSignal.h"
8
9 #include "mozilla/dom/Event.h"
10 #include "mozilla/dom/AbortSignalBinding.h"
11
12 namespace mozilla {
13 namespace dom {
14
15 // AbortSignalImpl
16 // ----------------------------------------------------------------------------
17
AbortSignalImpl(bool aAborted)18 AbortSignalImpl::AbortSignalImpl(bool aAborted) : mAborted(aAborted) {}
19
Aborted() const20 bool AbortSignalImpl::Aborted() const { return mAborted; }
21
Abort()22 void AbortSignalImpl::Abort() {
23 if (mAborted) {
24 return;
25 }
26
27 mAborted = true;
28
29 // Let's inform the followers.
30 nsTObserverArray<AbortFollower*>::ForwardIterator iter(mFollowers);
31 while (iter.HasMore()) {
32 RefPtr<AbortFollower> follower = iter.GetNext();
33 follower->Abort();
34 }
35 }
36
AddFollower(AbortFollower * aFollower)37 void AbortSignalImpl::AddFollower(AbortFollower* aFollower) {
38 MOZ_DIAGNOSTIC_ASSERT(aFollower);
39 if (!mFollowers.Contains(aFollower)) {
40 mFollowers.AppendElement(aFollower);
41 }
42 }
43
RemoveFollower(AbortFollower * aFollower)44 void AbortSignalImpl::RemoveFollower(AbortFollower* aFollower) {
45 MOZ_DIAGNOSTIC_ASSERT(aFollower);
46 mFollowers.RemoveElement(aFollower);
47 }
48
49 // AbortSignal
50 // ----------------------------------------------------------------------------
51
52 NS_IMPL_CYCLE_COLLECTION_CLASS(AbortSignal)
53
54 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(AbortSignal,
55 DOMEventTargetHelper)
56 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFollowingSignal)
57 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
58
59 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(AbortSignal,
60 DOMEventTargetHelper)
61 tmp->Unfollow();
62 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
63
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AbortSignal)64 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AbortSignal)
65 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
66
67 NS_IMPL_ADDREF_INHERITED(AbortSignal, DOMEventTargetHelper)
68 NS_IMPL_RELEASE_INHERITED(AbortSignal, DOMEventTargetHelper)
69
70 AbortSignal::AbortSignal(nsIGlobalObject* aGlobalObject, bool aAborted)
71 : DOMEventTargetHelper(aGlobalObject), AbortSignalImpl(aAborted) {}
72
WrapObject(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)73 JSObject* AbortSignal::WrapObject(JSContext* aCx,
74 JS::Handle<JSObject*> aGivenProto) {
75 return AbortSignal_Binding::Wrap(aCx, this, aGivenProto);
76 }
77
Abort()78 void AbortSignal::Abort() {
79 AbortSignalImpl::Abort();
80
81 EventInit init;
82 init.mBubbles = false;
83 init.mCancelable = false;
84
85 RefPtr<Event> event =
86 Event::Constructor(this, NS_LITERAL_STRING("abort"), init);
87 event->SetTrusted(true);
88
89 DispatchEvent(*event);
90 }
91
92 // AbortFollower
93 // ----------------------------------------------------------------------------
94
~AbortFollower()95 AbortFollower::~AbortFollower() { Unfollow(); }
96
Follow(AbortSignalImpl * aSignal)97 void AbortFollower::Follow(AbortSignalImpl* aSignal) {
98 MOZ_DIAGNOSTIC_ASSERT(aSignal);
99
100 Unfollow();
101
102 mFollowingSignal = aSignal;
103 aSignal->AddFollower(this);
104 }
105
Unfollow()106 void AbortFollower::Unfollow() {
107 if (mFollowingSignal) {
108 mFollowingSignal->RemoveFollower(this);
109 mFollowingSignal = nullptr;
110 }
111 }
112
IsFollowing() const113 bool AbortFollower::IsFollowing() const { return !!mFollowingSignal; }
114
115 } // namespace dom
116 } // namespace mozilla
117