ReadableStream.h (11464B)
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_ReadableStream_h 8 #define mozilla_dom_ReadableStream_h 9 10 #include "js/TypeDecls.h" 11 #include "js/Value.h" 12 #include "mozilla/Attributes.h" 13 #include "mozilla/ErrorResult.h" 14 #include "mozilla/dom/BindingDeclarations.h" 15 #include "mozilla/dom/IterableIterator.h" 16 #include "mozilla/dom/QueuingStrategyBinding.h" 17 #include "mozilla/dom/ReadableStreamControllerBase.h" 18 #include "mozilla/dom/ReadableStreamDefaultController.h" 19 #include "mozilla/dom/UnderlyingSourceCallbackHelpers.h" 20 #include "nsCycleCollectionParticipant.h" 21 #include "nsWrapperCache.h" 22 23 namespace mozilla::dom { 24 25 class Promise; 26 class ReadableStreamBYOBRequest; 27 class ReadableStreamDefaultReader; 28 class ReadableStreamGenericReader; 29 struct ReadableStreamGetReaderOptions; 30 struct ReadableStreamIteratorOptions; 31 struct ReadIntoRequest; 32 class WritableStream; 33 struct ReadableWritablePair; 34 struct StreamPipeOptions; 35 36 using ReadableStreamReader = 37 ReadableStreamDefaultReaderOrReadableStreamBYOBReader; 38 using OwningReadableStreamReader = 39 OwningReadableStreamDefaultReaderOrReadableStreamBYOBReader; 40 class NativeUnderlyingSource; 41 class BodyStreamHolder; 42 class UniqueMessagePortId; 43 class MessagePort; 44 45 class ReadableStream : public nsISupports, public nsWrapperCache { 46 public: 47 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 48 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ReadableStream) 49 50 friend class WritableStream; 51 52 protected: 53 virtual ~ReadableStream(); 54 55 nsCOMPtr<nsIGlobalObject> mGlobal; 56 57 // If one extends ReadableStream with another cycle collectable class, 58 // calling HoldJSObjects and DropJSObjects should happen using 'this' of 59 // that extending class. And in that case Explicit should be passed to the 60 // constructor of ReadableStream so that it doesn't make those calls. 61 // See also https://bugzilla.mozilla.org/show_bug.cgi?id=1801214. 62 enum class HoldDropJSObjectsCaller { Implicit, Explicit }; 63 64 explicit ReadableStream(const GlobalObject& aGlobal, 65 HoldDropJSObjectsCaller aHoldDropCaller); 66 explicit ReadableStream(nsIGlobalObject* aGlobal, 67 HoldDropJSObjectsCaller aHoldDropCaller); 68 69 public: 70 // Abstract algorithms 71 MOZ_CAN_RUN_SCRIPT static already_AddRefed<ReadableStream> CreateAbstract( 72 JSContext* aCx, nsIGlobalObject* aGlobal, 73 UnderlyingSourceAlgorithmsBase* aAlgorithms, 74 mozilla::Maybe<double> aHighWaterMark, 75 QueuingStrategySize* aSizeAlgorithm, ErrorResult& aRv); 76 MOZ_CAN_RUN_SCRIPT static already_AddRefed<ReadableStream> CreateByteAbstract( 77 JSContext* aCx, nsIGlobalObject* aGlobal, 78 UnderlyingSourceAlgorithmsBase* aAlgorithms, ErrorResult& aRv); 79 80 // Slot Getter/Setters: 81 MOZ_KNOWN_LIVE ReadableStreamControllerBase* Controller() { 82 return mController; 83 } 84 ReadableStreamDefaultController* DefaultController() { 85 MOZ_ASSERT(mController && mController->IsDefault()); 86 return mController->AsDefault(); 87 } 88 void SetController(ReadableStreamControllerBase& aController) { 89 MOZ_ASSERT(!mController); 90 mController = &aController; 91 } 92 93 bool Disturbed() const { return mDisturbed; } 94 void SetDisturbed(bool aDisturbed) { mDisturbed = aDisturbed; } 95 96 ReadableStreamGenericReader* GetReader() { return mReader; } 97 void SetReader(ReadableStreamGenericReader* aReader); 98 99 ReadableStreamDefaultReader* GetDefaultReader(); 100 101 enum class ReaderState { Readable, Closed, Errored }; 102 103 ReaderState State() const { return mState; } 104 void SetState(const ReaderState& aState) { mState = aState; } 105 106 JS::Value StoredError() const { return mStoredError; } 107 void SetStoredError(JS::Handle<JS::Value> aStoredError) { 108 mStoredError = aStoredError; 109 } 110 111 nsIInputStream* MaybeGetInputStreamIfUnread() { 112 MOZ_ASSERT(!Disturbed()); 113 if (UnderlyingSourceAlgorithmsBase* algorithms = 114 Controller()->GetAlgorithms()) { 115 return algorithms->MaybeGetInputStreamIfUnread(); 116 } 117 return nullptr; 118 } 119 120 // [Transferable] 121 // https://html.spec.whatwg.org/multipage/structured-data.html#transfer-steps 122 MOZ_CAN_RUN_SCRIPT bool Transfer(JSContext* aCx, 123 UniqueMessagePortId& aPortId); 124 MOZ_CAN_RUN_SCRIPT static already_AddRefed<ReadableStream> 125 ReceiveTransferImpl(JSContext* aCx, nsIGlobalObject* aGlobal, 126 MessagePort& aPort); 127 // https://html.spec.whatwg.org/multipage/structured-data.html#transfer-receiving-steps 128 MOZ_CAN_RUN_SCRIPT static bool ReceiveTransfer( 129 JSContext* aCx, nsIGlobalObject* aGlobal, MessagePort& aPort, 130 JS::MutableHandle<JSObject*> aReturnObject); 131 132 // Public functions to implement other specs 133 // https://streams.spec.whatwg.org/#other-specs-rs 134 135 // https://streams.spec.whatwg.org/#readablestream-set-up 136 static already_AddRefed<ReadableStream> CreateNative( 137 JSContext* aCx, nsIGlobalObject* aGlobal, 138 UnderlyingSourceAlgorithmsWrapper& aAlgorithms, 139 mozilla::Maybe<double> aHighWaterMark, 140 QueuingStrategySize* aSizeAlgorithm, ErrorResult& aRv); 141 142 // https://streams.spec.whatwg.org/#readablestream-set-up-with-byte-reading-support 143 144 protected: 145 // Sets up the ReadableStream with byte reading support. Intended for 146 // subclasses. 147 void SetUpByteNative(JSContext* aCx, 148 UnderlyingSourceAlgorithmsWrapper& aAlgorithms, 149 mozilla::Maybe<double> aHighWaterMark, ErrorResult& aRv); 150 151 public: 152 // Creates and sets up a ReadableStream with byte reading support. Use 153 // SetUpByteNative for this purpose in subclasses. 154 static already_AddRefed<ReadableStream> CreateByteNative( 155 JSContext* aCx, nsIGlobalObject* aGlobal, 156 UnderlyingSourceAlgorithmsWrapper& aAlgorithms, 157 mozilla::Maybe<double> aHighWaterMark, ErrorResult& aRv); 158 159 // The following algorithms must only be used on ReadableStream instances 160 // initialized via the above set up or set up with byte reading support 161 // algorithms (not, e.g., on web-developer-created instances): 162 163 // https://streams.spec.whatwg.org/#readablestream-close 164 MOZ_CAN_RUN_SCRIPT void CloseNative(JSContext* aCx, ErrorResult& aRv); 165 166 // https://streams.spec.whatwg.org/#readablestream-error 167 void ErrorNative(JSContext* aCx, JS::Handle<JS::Value> aError, 168 ErrorResult& aRv); 169 170 // https://streams.spec.whatwg.org/#readablestream-enqueue 171 MOZ_CAN_RUN_SCRIPT void EnqueueNative(JSContext* aCx, 172 JS::Handle<JS::Value> aChunk, 173 ErrorResult& aRv); 174 175 // https://streams.spec.whatwg.org/#readablestream-current-byob-request-view 176 void GetCurrentBYOBRequestView(JSContext* aCx, 177 JS::MutableHandle<JSObject*> aView, 178 ErrorResult& aRv); 179 180 // The following algorithms can be used on arbitrary ReadableStream instances, 181 // including ones that are created by web developers. They can all fail in 182 // various operation-specific ways, and these failures should be handled by 183 // the calling specification. 184 185 // https://streams.spec.whatwg.org/#readablestream-get-a-reader 186 already_AddRefed<mozilla::dom::ReadableStreamDefaultReader> GetReader( 187 ErrorResult& aRv); 188 189 // IDL layer functions 190 191 nsIGlobalObject* GetParentObject() const { return mGlobal; } 192 193 JSObject* WrapObject(JSContext* aCx, 194 JS::Handle<JSObject*> aGivenProto) override; 195 196 // IDL methods 197 198 // TODO: Use MOZ_CAN_RUN_SCRIPT when IDL constructors can use it (bug 1749042) 199 MOZ_CAN_RUN_SCRIPT_BOUNDARY static already_AddRefed<ReadableStream> 200 Constructor(const GlobalObject& aGlobal, 201 const Optional<JS::Handle<JSObject*>>& aUnderlyingSource, 202 const QueuingStrategy& aStrategy, ErrorResult& aRv); 203 204 MOZ_CAN_RUN_SCRIPT static already_AddRefed<ReadableStream> From( 205 const GlobalObject& aGlobal, JS::Handle<JS::Value> asyncIterable, 206 ErrorResult& aRv); 207 208 bool Locked() const; 209 210 MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> Cancel( 211 JSContext* cx, JS::Handle<JS::Value> aReason, ErrorResult& aRv); 212 213 void GetReader(const ReadableStreamGetReaderOptions& aOptions, 214 OwningReadableStreamReader& resultReader, ErrorResult& aRv); 215 216 MOZ_CAN_RUN_SCRIPT already_AddRefed<ReadableStream> PipeThrough( 217 const ReadableWritablePair& aTransform, const StreamPipeOptions& aOptions, 218 ErrorResult& aRv); 219 220 MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> PipeTo( 221 WritableStream& aDestination, const StreamPipeOptions& aOptions, 222 ErrorResult& aRv); 223 224 MOZ_CAN_RUN_SCRIPT void Tee(JSContext* aCx, 225 nsTArray<RefPtr<ReadableStream>>& aResult, 226 ErrorResult& aRv); 227 228 struct IteratorData { 229 void Traverse(nsCycleCollectionTraversalCallback& cb); 230 void Unlink(); 231 232 RefPtr<ReadableStreamDefaultReader> mReader; 233 bool mPreventCancel; 234 }; 235 236 using Iterator = AsyncIterableIterator<ReadableStream>; 237 238 void InitAsyncIteratorData(IteratorData& aData, Iterator::IteratorType aType, 239 const ReadableStreamIteratorOptions& aOptions, 240 ErrorResult& aRv); 241 MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> GetNextIterationResult( 242 Iterator* aIterator, ErrorResult& aRv); 243 MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> IteratorReturn( 244 JSContext* aCx, Iterator* aIterator, JS::Handle<JS::Value> aValue, 245 ErrorResult& aRv); 246 247 // Internal Slots: 248 private: 249 RefPtr<ReadableStreamControllerBase> mController; 250 bool mDisturbed = false; 251 RefPtr<ReadableStreamGenericReader> mReader; 252 ReaderState mState = ReaderState::Readable; 253 JS::Heap<JS::Value> mStoredError; 254 255 HoldDropJSObjectsCaller mHoldDropCaller; 256 }; 257 258 namespace streams_abstract { 259 260 bool IsReadableStreamLocked(ReadableStream* aStream); 261 262 double ReadableStreamGetNumReadRequests(ReadableStream* aStream); 263 264 void ReadableStreamError(JSContext* aCx, ReadableStream* aStream, 265 JS::Handle<JS::Value> aValue, ErrorResult& aRv); 266 267 MOZ_CAN_RUN_SCRIPT void ReadableStreamClose(JSContext* aCx, 268 ReadableStream* aStream, 269 ErrorResult& aRv); 270 271 MOZ_CAN_RUN_SCRIPT void ReadableStreamFulfillReadRequest( 272 JSContext* aCx, ReadableStream* aStream, JS::Handle<JS::Value> aChunk, 273 bool done, ErrorResult& aRv); 274 275 void ReadableStreamAddReadRequest(ReadableStream* aStream, 276 ReadRequest* aReadRequest); 277 void ReadableStreamAddReadIntoRequest(ReadableStream* aStream, 278 ReadIntoRequest* aReadIntoRequest); 279 280 MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> ReadableStreamCancel( 281 JSContext* aCx, ReadableStream* aStream, JS::Handle<JS::Value> aError, 282 ErrorResult& aRv); 283 284 already_AddRefed<ReadableStreamDefaultReader> 285 AcquireReadableStreamDefaultReader(ReadableStream* aStream, ErrorResult& aRv); 286 287 bool ReadableStreamHasBYOBReader(ReadableStream* aStream); 288 bool ReadableStreamHasDefaultReader(ReadableStream* aStream); 289 290 } // namespace streams_abstract 291 292 } // namespace mozilla::dom 293 294 #endif // mozilla_dom_ReadableStream_h