AbortFollower.h (3305B)
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 #ifndef mozilla_dom_AbortFollower_h 8 #define mozilla_dom_AbortFollower_h 9 10 #include "jsapi.h" 11 #include "mozilla/WeakPtr.h" 12 #include "nsISupportsImpl.h" 13 #include "nsTObserverArray.h" 14 15 namespace mozilla::dom { 16 17 enum class SignalAborted { No, Yes }; 18 19 class AbortSignal; 20 class AbortSignalImpl; 21 22 // This class must be implemented by objects who want to follow an 23 // AbortSignalImpl. 24 class AbortFollower : public nsISupports { 25 public: 26 virtual void RunAbortAlgorithm() = 0; 27 28 // This adds strong reference to this follower on the signal, which means 29 // you'll need to call Unfollow() to prevent your object from living 30 // needlessly longer. 31 void Follow(AbortSignalImpl* aSignal); 32 33 // Explicitly call this to let garbage collection happen sooner when the 34 // follower finished its work and cannot be aborted anymore. 35 void Unfollow(); 36 37 bool IsFollowing() const; 38 39 AbortSignalImpl* Signal() const { return mFollowingSignal; } 40 41 protected: 42 virtual ~AbortFollower(); 43 44 friend class AbortSignalImpl; 45 46 WeakPtr<AbortSignalImpl> mFollowingSignal; 47 }; 48 49 /* 50 * TODO(krosylight): The only consumer of this is Fetch. It would be nice to 51 * merge this back to AbortSignal as it's quite a duplication right now. 52 * 53 * AbortSignalImpl is a minimal implementation without an associated global 54 * and without event dispatching, those are added in AbortSignal. 55 * See Bug 1478101 56 */ 57 class AbortSignalImpl : public nsISupports, public SupportsWeakPtr { 58 public: 59 explicit AbortSignalImpl(SignalAborted aAborted, 60 JS::Handle<JS::Value> aReason); 61 62 bool Aborted() const; 63 64 // Web IDL Layer 65 void GetReason(JSContext* aCx, JS::MutableHandle<JS::Value> aReason); 66 // Helper for other DOM code 67 JS::Value RawReason() const; 68 69 void SignalAbort(JS::Handle<JS::Value> aReason); 70 71 protected: 72 // Subclasses of this class must call these Traverse and Unlink functions 73 // during corresponding cycle collection operations. 74 static void Traverse(AbortSignalImpl* aSignal, 75 nsCycleCollectionTraversalCallback& cb); 76 77 static void Unlink(AbortSignalImpl* aSignal); 78 79 virtual ~AbortSignalImpl() { UnlinkFollowers(); } 80 81 virtual void SignalAbortWithDependents(); 82 83 virtual void RunAbortSteps(); 84 85 void SetAborted(JS::Handle<JS::Value> aReason); 86 87 JS::Heap<JS::Value> mReason; 88 89 private: 90 friend class AbortFollower; 91 92 void MaybeAssignAbortError(JSContext* aCx); 93 94 void UnlinkFollowers(); 95 96 // TODO(krosylight): We should rename all names around the term "Follow". See 97 // bug 1873648. 98 // 99 // |AbortFollower::Follow| adds to this array, and 100 // |AbortFollower::Unfollow| (also called by the destructor) will remove 101 // from this array. Finally, calling |SignalAbort()| will (after running all 102 // abort algorithms) empty this and make all contained followers |Unfollow()|. 103 nsTObserverArray<RefPtr<AbortFollower>> mFollowers; 104 105 SignalAborted mAborted; 106 }; 107 108 } // namespace mozilla::dom 109 110 #endif // mozilla_dom_AbortFollower_h