TeeState.h (5513B)
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/. */ 6 7 #ifndef mozilla_dom_TeeState_h 8 #define mozilla_dom_TeeState_h 9 10 #include "mozilla/HoldDropJSObjects.h" 11 #include "mozilla/dom/Promise.h" 12 #include "mozilla/dom/ReadableStream.h" 13 #include "mozilla/dom/ReadableStreamDefaultReader.h" 14 #include "nsISupports.h" 15 16 namespace mozilla::dom { 17 18 class ReadableStreamDefaultTeeSourceAlgorithms; 19 20 enum class TeeBranch : bool { 21 Branch1, 22 Branch2, 23 }; 24 25 inline TeeBranch OtherTeeBranch(TeeBranch aBranch) { 26 if (aBranch == TeeBranch::Branch1) { 27 return TeeBranch::Branch2; 28 } 29 return TeeBranch::Branch1; 30 } 31 32 // A closure capturing the free variables in the ReadableStreamTee family of 33 // algorithms. 34 // https://streams.spec.whatwg.org/#abstract-opdef-readablestreamdefaulttee 35 // https://streams.spec.whatwg.org/#abstract-opdef-readablebytestreamtee 36 struct TeeState : public nsISupports { 37 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 38 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TeeState) 39 40 static already_AddRefed<TeeState> Create(ReadableStream* aStream, 41 bool aCloneForBranch2, 42 ErrorResult& aRv); 43 44 ReadableStream* GetStream() const { return mStream; } 45 void SetStream(ReadableStream* aStream) { mStream = aStream; } 46 47 ReadableStreamGenericReader* GetReader() const { return mReader; } 48 void SetReader(ReadableStreamGenericReader* aReader) { mReader = aReader; } 49 50 ReadableStreamDefaultReader* GetDefaultReader() const { 51 return mReader->AsDefault(); 52 } 53 54 bool ReadAgain() const { return mReadAgain; } 55 void SetReadAgain(bool aReadAgain) { mReadAgain = aReadAgain; } 56 57 // ReadableByteStreamTee uses ReadAgainForBranch{1,2}; 58 bool ReadAgainForBranch1() const { return ReadAgain(); } 59 void SetReadAgainForBranch1(bool aReadAgainForBranch1) { 60 SetReadAgain(aReadAgainForBranch1); 61 } 62 63 bool ReadAgainForBranch2() const { return mReadAgainForBranch2; } 64 void SetReadAgainForBranch2(bool aReadAgainForBranch2) { 65 mReadAgainForBranch2 = aReadAgainForBranch2; 66 } 67 68 bool Reading() const { return mReading; } 69 void SetReading(bool aReading) { mReading = aReading; } 70 71 bool Canceled1() const { return mCanceled1; } 72 void SetCanceled1(bool aCanceled1) { mCanceled1 = aCanceled1; } 73 74 bool Canceled2() const { return mCanceled2; } 75 void SetCanceled2(bool aCanceled2) { mCanceled2 = aCanceled2; } 76 77 void SetCanceled(TeeBranch aBranch, bool aCanceled) { 78 aBranch == TeeBranch::Branch1 ? SetCanceled1(aCanceled) 79 : SetCanceled2(aCanceled); 80 } 81 bool Canceled(TeeBranch aBranch) { 82 return aBranch == TeeBranch::Branch1 ? Canceled1() : Canceled2(); 83 } 84 85 JS::Value Reason1() const { return mReason1; } 86 void SetReason1(JS::Handle<JS::Value> aReason1) { mReason1 = aReason1; } 87 88 JS::Value Reason2() const { return mReason2; } 89 void SetReason2(JS::Handle<JS::Value> aReason2) { mReason2 = aReason2; } 90 91 void SetReason(TeeBranch aBranch, JS::Handle<JS::Value> aReason) { 92 aBranch == TeeBranch::Branch1 ? SetReason1(aReason) : SetReason2(aReason); 93 } 94 95 ReadableStream* Branch1() const { return mBranch1; } 96 void SetBranch1(already_AddRefed<ReadableStream> aBranch1) { 97 mBranch1 = aBranch1; 98 } 99 100 ReadableStream* Branch2() const { return mBranch2; } 101 void SetBranch2(already_AddRefed<ReadableStream> aBranch2) { 102 mBranch2 = aBranch2; 103 } 104 105 Promise* CancelPromise() const { return mCancelPromise; } 106 void SetCancelPromise(Promise* aCancelPromise) { 107 mCancelPromise = aCancelPromise; 108 } 109 110 bool CloneForBranch2() const { return mCloneForBranch2; } 111 void setCloneForBranch2(bool aCloneForBranch2) { 112 mCloneForBranch2 = aCloneForBranch2; 113 } 114 115 // Some code is better served by using an enum into various internal slots to 116 // avoid duplication: Here we provide alternative accessors for that case. 117 ReadableStream* Branch(TeeBranch aBranch) const { 118 return aBranch == TeeBranch::Branch1 ? Branch1() : Branch2(); 119 } 120 121 void SetReadAgainForBranch(TeeBranch aBranch, bool aValue) { 122 if (aBranch == TeeBranch::Branch1) { 123 SetReadAgainForBranch1(aValue); 124 return; 125 } 126 SetReadAgainForBranch2(aValue); 127 } 128 129 MOZ_CAN_RUN_SCRIPT void PullCallback(JSContext* aCx, nsIGlobalObject* aGlobal, 130 ErrorResult& aRv); 131 132 private: 133 TeeState(ReadableStream* aStream, bool aCloneForBranch2); 134 135 // Implicit: 136 RefPtr<ReadableStream> mStream; 137 138 // Step 3. (Step Numbering is based on ReadableStreamDefaultTee) 139 RefPtr<ReadableStreamGenericReader> mReader; 140 141 // Step 4. 142 bool mReading = false; 143 144 // Step 5. 145 // (Aliased to readAgainForBranch1, for the purpose of ReadableByteStreamTee) 146 bool mReadAgain = false; 147 148 // ReadableByteStreamTee 149 bool mReadAgainForBranch2 = false; 150 151 // Step 6. 152 bool mCanceled1 = false; 153 154 // Step 7. 155 bool mCanceled2 = false; 156 157 // Step 8. 158 JS::Heap<JS::Value> mReason1; 159 160 // Step 9. 161 JS::Heap<JS::Value> mReason2; 162 163 // Step 10. 164 RefPtr<ReadableStream> mBranch1; 165 166 // Step 11. 167 RefPtr<ReadableStream> mBranch2; 168 169 // Step 12. 170 RefPtr<Promise> mCancelPromise; 171 172 // Implicit: 173 bool mCloneForBranch2 = false; 174 175 virtual ~TeeState() { mozilla::DropJSObjects(this); } 176 }; 177 178 } // namespace mozilla::dom 179 #endif