Bug 1728955: part 8) Refactor `DisplayErrCode` in Windows' `nsClipboard`. r=masayuki
[gecko.git] / dom / abort / AbortSignal.cpp
blob40ded23571d3966ff084306ecfc6b5dbcebc3176
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 "AbortSignal.h"
9 #include "mozilla/dom/Event.h"
10 #include "mozilla/dom/EventBinding.h"
11 #include "mozilla/dom/AbortSignalBinding.h"
12 #include "mozilla/RefPtr.h"
14 namespace mozilla::dom {
16 // AbortSignalImpl
17 // ----------------------------------------------------------------------------
19 AbortSignalImpl::AbortSignalImpl(bool aAborted) : mAborted(aAborted) {}
21 bool AbortSignalImpl::Aborted() const { return mAborted; }
23 // https://dom.spec.whatwg.org/#abortsignal-signal-abort steps 1-4
24 void AbortSignalImpl::SignalAbort() {
25 // Step 1.
26 if (mAborted) {
27 return;
30 // Step 2.
31 mAborted = true;
33 // Step 3.
34 // When there are multiple followers, the follower removal algorithm
35 // https://dom.spec.whatwg.org/#abortsignal-remove could be invoked in an
36 // earlier algorithm to remove a later algorithm, so |mFollowers| must be a
37 // |nsTObserverArray| to defend against mutation.
38 for (RefPtr<AbortFollower> follower : mFollowers.ForwardRange()) {
39 MOZ_ASSERT(follower->mFollowingSignal == this);
40 follower->RunAbortAlgorithm();
43 // Step 4.
44 // Clear follower->signal links, then clear signal->follower links.
45 for (AbortFollower* follower : mFollowers.ForwardRange()) {
46 follower->mFollowingSignal = nullptr;
48 mFollowers.Clear();
51 /* static */ void AbortSignalImpl::Traverse(
52 AbortSignalImpl* aSignal, nsCycleCollectionTraversalCallback& cb) {
53 // To be filled in shortly.
56 // AbortSignal
57 // ----------------------------------------------------------------------------
59 NS_IMPL_CYCLE_COLLECTION_CLASS(AbortSignal)
61 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(AbortSignal,
62 DOMEventTargetHelper)
63 AbortSignalImpl::Traverse(static_cast<AbortSignalImpl*>(tmp), cb);
64 AbortFollower::Traverse(static_cast<AbortFollower*>(tmp), cb);
65 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
67 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(AbortSignal,
68 DOMEventTargetHelper)
69 AbortSignalImpl::Unlink(static_cast<AbortSignalImpl*>(tmp));
70 AbortFollower::Unlink(static_cast<AbortFollower*>(tmp));
71 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
73 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AbortSignal)
74 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
76 NS_IMPL_ADDREF_INHERITED(AbortSignal, DOMEventTargetHelper)
77 NS_IMPL_RELEASE_INHERITED(AbortSignal, DOMEventTargetHelper)
79 AbortSignal::AbortSignal(nsIGlobalObject* aGlobalObject, bool aAborted)
80 : DOMEventTargetHelper(aGlobalObject), AbortSignalImpl(aAborted) {}
82 JSObject* AbortSignal::WrapObject(JSContext* aCx,
83 JS::Handle<JSObject*> aGivenProto) {
84 return AbortSignal_Binding::Wrap(aCx, this, aGivenProto);
87 already_AddRefed<AbortSignal> AbortSignal::Abort(GlobalObject& aGlobal) {
88 nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
89 RefPtr<AbortSignal> abortSignal = new AbortSignal(global, true);
90 return abortSignal.forget();
93 // https://dom.spec.whatwg.org/#abortsignal-signal-abort
94 void AbortSignal::SignalAbort() {
95 // Steps 1-4.
96 AbortSignalImpl::SignalAbort();
98 // Step 5.
99 EventInit init;
100 init.mBubbles = false;
101 init.mCancelable = false;
103 RefPtr<Event> event = Event::Constructor(this, u"abort"_ns, init);
104 event->SetTrusted(true);
106 DispatchEvent(*event);
109 // AbortFollower
110 // ----------------------------------------------------------------------------
112 AbortFollower::~AbortFollower() { Unfollow(); }
114 // https://dom.spec.whatwg.org/#abortsignal-add
115 void AbortFollower::Follow(AbortSignalImpl* aSignal) {
116 // Step 1.
117 if (aSignal->mAborted) {
118 return;
121 MOZ_DIAGNOSTIC_ASSERT(aSignal);
123 Unfollow();
125 // Step 2.
126 mFollowingSignal = aSignal;
127 MOZ_ASSERT(!aSignal->mFollowers.Contains(this));
128 aSignal->mFollowers.AppendElement(this);
131 // https://dom.spec.whatwg.org/#abortsignal-remove
132 void AbortFollower::Unfollow() {
133 if (mFollowingSignal) {
134 // |Unfollow| is called by cycle-collection unlink code that runs in no
135 // guaranteed order. So we can't, symmetric with |Follow| above, assert
136 // that |this| will be found in |mFollowingSignal->mFollowers|.
137 mFollowingSignal->mFollowers.RemoveElement(this);
138 mFollowingSignal = nullptr;
142 bool AbortFollower::IsFollowing() const { return !!mFollowingSignal; }
144 /* static */ void AbortFollower::Traverse(
145 AbortFollower* aFollower, nsCycleCollectionTraversalCallback& cb) {
146 ImplCycleCollectionTraverse(cb, aFollower->mFollowingSignal,
147 "mFollowingSignal", 0);
150 } // namespace mozilla::dom