Bug 1769952 - Fix running raptor on a Win10-64 VM r=sparky
[gecko.git] / dom / streams / ReadableByteStreamController.h
blob4529f51f93ee0a937f00e2151fd4bcaf3eb719d9
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/. */
7 #ifndef mozilla_dom_ReadableByteStreamController_h
8 #define mozilla_dom_ReadableByteStreamController_h
10 #include <cstddef>
11 #include "UnderlyingSourceCallbackHelpers.h"
12 #include "js/RootingAPI.h"
13 #include "js/TypeDecls.h"
14 #include "mozilla/Attributes.h"
15 #include "mozilla/ErrorResult.h"
16 #include "mozilla/dom/BindingDeclarations.h"
17 #include "mozilla/dom/QueuingStrategyBinding.h"
18 #include "mozilla/dom/QueueWithSizes.h"
19 #include "mozilla/dom/ReadableStream.h"
20 #include "mozilla/dom/ReadRequest.h"
21 #include "mozilla/dom/ReadableStreamBYOBRequest.h"
22 #include "mozilla/dom/ReadableStreamController.h"
23 #include "mozilla/dom/TypedArray.h"
24 #include "nsCycleCollectionParticipant.h"
25 #include "nsWrapperCache.h"
26 #include "mozilla/dom/Nullable.h"
27 #include "nsTArray.h"
28 #include "nsISupportsImpl.h"
30 namespace mozilla::dom {
32 // https://streams.spec.whatwg.org/#pull-into-descriptor-reader-type
33 // Indicates what type of readable stream reader initiated this request,
34 // or None if the initiating reader was released.
35 enum ReaderType { Default, BYOB, None };
37 struct PullIntoDescriptor;
38 struct ReadableByteStreamQueueEntry;
39 struct ReadIntoRequest;
41 class ReadableByteStreamController final : public ReadableStreamController,
42 public nsWrapperCache {
43 public:
44 NS_DECL_ISUPPORTS_INHERITED
45 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
46 ReadableByteStreamController, ReadableStreamController)
48 public:
49 explicit ReadableByteStreamController(nsIGlobalObject* aGlobal);
51 protected:
52 ~ReadableByteStreamController() override;
54 public:
55 bool IsDefault() override { return false; }
56 bool IsByte() override { return true; }
57 ReadableStreamDefaultController* AsDefault() override { return nullptr; }
58 ReadableByteStreamController* AsByte() override { return this; }
60 JSObject* WrapObject(JSContext* aCx,
61 JS::Handle<JSObject*> aGivenProto) override;
63 already_AddRefed<ReadableStreamBYOBRequest> GetByobRequest(JSContext* aCx,
64 ErrorResult& aRv);
66 Nullable<double> GetDesiredSize() const;
68 MOZ_CAN_RUN_SCRIPT void Close(JSContext* aCx, ErrorResult& aRv);
70 MOZ_CAN_RUN_SCRIPT void Enqueue(JSContext* aCx, const ArrayBufferView& aChunk,
71 ErrorResult& aRv);
73 void Error(JSContext* aCx, JS::Handle<JS::Value> aErrorValue,
74 ErrorResult& aRv);
76 MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> CancelSteps(
77 JSContext* aCx, JS::Handle<JS::Value> aReason, ErrorResult& aRv) override;
78 MOZ_CAN_RUN_SCRIPT void PullSteps(JSContext* aCx, ReadRequest* aReadRequest,
79 ErrorResult& aRv) override;
80 void ReleaseSteps() override;
82 // Internal Slot Accessors
83 Maybe<uint64_t> AutoAllocateChunkSize() { return mAutoAllocateChunkSize; }
84 void SetAutoAllocateChunkSize(Maybe<uint64_t>& aSize) {
85 mAutoAllocateChunkSize = aSize;
88 ReadableStreamBYOBRequest* GetByobRequest() const { return mByobRequest; }
89 void SetByobRequest(ReadableStreamBYOBRequest* aByobRequest) {
90 mByobRequest = aByobRequest;
93 LinkedList<RefPtr<PullIntoDescriptor>>& PendingPullIntos() {
94 return mPendingPullIntos;
96 void ClearPendingPullIntos();
98 ReadableStream* Stream() const { return mStream; }
99 void SetStream(ReadableStream* aStream) { mStream = aStream; }
101 double QueueTotalSize() const { return mQueueTotalSize; }
102 void SetQueueTotalSize(double aQueueTotalSize) {
103 mQueueTotalSize = aQueueTotalSize;
105 void AddToQueueTotalSize(double aLength) { mQueueTotalSize += aLength; }
107 double StrategyHWM() const { return mStrategyHWM; }
108 void SetStrategyHWM(double aStrategyHWM) { mStrategyHWM = aStrategyHWM; }
110 bool CloseRequested() const { return mCloseRequested; }
111 void SetCloseRequested(bool aCloseRequested) {
112 mCloseRequested = aCloseRequested;
115 UnderlyingSourceAlgorithmsBase* GetAlgorithms() { return mAlgorithms; }
116 void SetAlgorithms(UnderlyingSourceAlgorithmsBase* aAlgorithms) {
117 mAlgorithms = aAlgorithms;
120 LinkedList<RefPtr<ReadableByteStreamQueueEntry>>& Queue() { return mQueue; }
121 void ClearQueue();
123 bool Started() const { return mStarted; }
124 void SetStarted(bool aStarted) { mStarted = aStarted; }
126 bool Pulling() const { return mPulling; }
127 void SetPulling(bool aPulling) { mPulling = aPulling; }
129 bool PullAgain() const { return mPullAgain; }
130 void SetPullAgain(bool aPullAgain) { mPullAgain = aPullAgain; }
132 private:
133 // A boolean flag indicating whether the stream has been closed by its
134 // underlying byte source, but still has chunks in its internal queue that
135 // have not yet been read
136 bool mCloseRequested = false;
138 // A boolean flag set to true if the stream’s mechanisms requested a call
139 // to the underlying byte source's pull algorithm to pull more data, but the
140 // pull could not yet be done since a previous call is still executing
141 bool mPullAgain = false;
143 // A boolean flag indicating whether the underlying byte source has finished
144 // starting
145 bool mStarted = false;
147 // A boolean flag set to true while the underlying byte source's pull
148 // algorithm is executing and the returned promise has not yet fulfilled,
149 // used to prevent reentrant calls
150 bool mPulling = false;
152 // A positive integer, when the automatic buffer allocation feature is
153 // enabled. In that case, this value specifies the size of buffer to allocate.
154 // It is undefined otherwise.
155 Maybe<uint64_t> mAutoAllocateChunkSize;
157 // A ReadableStreamBYOBRequest instance representing the current BYOB pull
158 // request, or null if there are no pending requests
159 RefPtr<ReadableStreamBYOBRequest> mByobRequest;
161 // The algorithms for the underlying byte source
162 RefPtr<UnderlyingSourceAlgorithmsBase> mAlgorithms;
164 // A list of pull-into descriptors
165 LinkedList<RefPtr<PullIntoDescriptor>> mPendingPullIntos;
167 // A list of readable byte stream queue entries representing the stream’s
168 // internal queue of chunks
170 // This is theoretically supposed to be a QueueWithSizes, but it is
171 // mostly not actually manipulated or used like QueueWithSizes, so instead we
172 // use a LinkedList.
173 LinkedList<RefPtr<ReadableByteStreamQueueEntry>> mQueue;
175 // The total size, in bytes, of all the chunks stored in [[queue]] (see § 8.1
176 // Queue-with-sizes)
177 double mQueueTotalSize = 0.0;
179 // A number supplied to the constructor as part of the stream’s queuing
180 // strategy, indicating the point at which the stream will apply backpressure
181 // to its underlying byte source
182 double mStrategyHWM = 0.0;
184 RefPtr<ReadableStream> mStream;
187 // https://streams.spec.whatwg.org/#readable-byte-stream-queue-entry
188 // Important: These list elements need to be traced by the owning structure.
189 struct ReadableByteStreamQueueEntry
190 : LinkedListElement<RefPtr<ReadableByteStreamQueueEntry>> {
191 NS_INLINE_DECL_REFCOUNTING(mozilla::dom::ReadableByteStreamQueueEntry)
193 friend class ReadableByteStreamController::cycleCollection;
195 ReadableByteStreamQueueEntry(JS::Handle<JSObject*> aBuffer,
196 size_t aByteOffset, size_t aByteLength)
197 : LinkedListElement<RefPtr<ReadableByteStreamQueueEntry>>(),
198 mBuffer(aBuffer),
199 mByteOffset(aByteOffset),
200 mByteLength(aByteLength) {}
202 JSObject* Buffer() const { return mBuffer; }
203 void SetBuffer(JS::Handle<JSObject*> aBuffer) { mBuffer = aBuffer; }
205 size_t ByteOffset() const { return mByteOffset; }
206 void SetByteOffset(size_t aByteOffset) { mByteOffset = aByteOffset; }
208 size_t ByteLength() const { return mByteLength; }
209 void SetByteLength(size_t aByteLength) { mByteLength = aByteLength; }
211 void ClearBuffer() { mBuffer = nullptr; }
213 private:
214 // An ArrayBuffer, which will be a transferred version of the one originally
215 // supplied by the underlying byte source.
217 // This is traced by the list owner (see ReadableByteStreamController's
218 // tracing code).
219 JS::Heap<JSObject*> mBuffer;
221 // A nonnegative integer number giving the byte offset derived from the view
222 // originally supplied by the underlying byte source
223 size_t mByteOffset = 0;
225 // A nonnegative integer number giving the byte length derived from the view
226 // originally supplied by the underlying byte source
227 size_t mByteLength = 0;
229 ~ReadableByteStreamQueueEntry() = default;
232 // Important: These list elments need to be traced by the owning structure.
233 struct PullIntoDescriptor final
234 : LinkedListElement<RefPtr<PullIntoDescriptor>> {
235 NS_INLINE_DECL_REFCOUNTING(mozilla::dom::PullIntoDescriptor)
237 enum Constructor {
238 DataView,
239 #define DEFINE_TYPED_CONSTRUCTOR_ENUM_NAMES(ExternalT, NativeT, Name) Name,
240 JS_FOR_EACH_TYPED_ARRAY(DEFINE_TYPED_CONSTRUCTOR_ENUM_NAMES)
241 #undef DEFINE_TYPED_CONSTRUCTOR_ENUM_NAMES
244 static Constructor constructorFromScalar(JS::Scalar::Type type) {
245 switch (type) {
246 #define REMAP_PULL_INTO_DESCRIPTOR_TYPE(ExternalT, NativeT, Name) \
247 case JS::Scalar::Name: \
248 return Constructor::Name;
249 JS_FOR_EACH_TYPED_ARRAY(REMAP_PULL_INTO_DESCRIPTOR_TYPE)
250 #undef REMAP
252 case JS::Scalar::Int64:
253 case JS::Scalar::Simd128:
254 case JS::Scalar::MaxTypedArrayViewType:
255 break;
257 MOZ_CRASH("Unexpected Scalar::Type");
260 friend class ReadableByteStreamController::cycleCollection;
262 PullIntoDescriptor(JS::Handle<JSObject*> aBuffer, uint64_t aBufferByteLength,
263 uint64_t aByteOffset, uint64_t aByteLength,
264 uint64_t aBytesFilled, uint64_t aElementSize,
265 Constructor aViewConstructor, ReaderType aReaderType)
266 : LinkedListElement<RefPtr<PullIntoDescriptor>>(),
267 mBuffer(aBuffer),
268 mBufferByteLength(aBufferByteLength),
269 mByteOffset(aByteOffset),
270 mByteLength(aByteLength),
271 mBytesFilled(aBytesFilled),
272 mElementSize(aElementSize),
273 mViewConstructor(aViewConstructor),
274 mReaderType(aReaderType) {}
276 JSObject* Buffer() const { return mBuffer; }
277 void SetBuffer(JS::Handle<JSObject*> aBuffer) { mBuffer = aBuffer; }
279 uint64_t BufferByteLength() const { return mBufferByteLength; }
280 void SetBufferByteLength(const uint64_t aBufferByteLength) {
281 mBufferByteLength = aBufferByteLength;
284 uint64_t ByteOffset() const { return mByteOffset; }
285 void SetByteOffset(const uint64_t aByteOffset) { mByteOffset = aByteOffset; }
287 uint64_t ByteLength() const { return mByteLength; }
288 void SetByteLength(const uint64_t aByteLength) { mByteLength = aByteLength; }
290 uint64_t BytesFilled() const { return mBytesFilled; }
291 void SetBytesFilled(const uint64_t aBytesFilled) {
292 mBytesFilled = aBytesFilled;
295 uint64_t ElementSize() const { return mElementSize; }
296 void SetElementSize(const uint64_t aElementSize) {
297 mElementSize = aElementSize;
300 Constructor ViewConstructor() const { return mViewConstructor; }
302 // Note: Named GetReaderType to avoid name conflict with type.
303 ReaderType GetReaderType() const { return mReaderType; }
304 void SetReaderType(const ReaderType aReaderType) {
305 mReaderType = aReaderType;
308 void ClearBuffer() { mBuffer = nullptr; }
310 private:
311 // This is traced by the list owner (see ReadableByteStreamController's
312 // tracing code).
313 JS::Heap<JSObject*> mBuffer;
314 uint64_t mBufferByteLength = 0;
315 uint64_t mByteOffset = 0;
316 uint64_t mByteLength = 0;
317 uint64_t mBytesFilled = 0;
318 uint64_t mElementSize = 0;
319 Constructor mViewConstructor;
320 ReaderType mReaderType;
322 ~PullIntoDescriptor() = default;
325 MOZ_CAN_RUN_SCRIPT void ReadableByteStreamControllerRespond(
326 JSContext* aCx, ReadableByteStreamController* aController,
327 uint64_t aBytesWritten, ErrorResult& aRv);
329 MOZ_CAN_RUN_SCRIPT void ReadableByteStreamControllerRespondInternal(
330 JSContext* aCx, ReadableByteStreamController* aController,
331 uint64_t aBytesWritten, ErrorResult& aRv);
333 MOZ_CAN_RUN_SCRIPT void ReadableByteStreamControllerRespondWithNewView(
334 JSContext* aCx, ReadableByteStreamController* aController,
335 JS::Handle<JSObject*> aView, ErrorResult& aRv);
337 MOZ_CAN_RUN_SCRIPT void ReadableByteStreamControllerPullInto(
338 JSContext* aCx, ReadableByteStreamController* aController,
339 JS::Handle<JSObject*> aView, ReadIntoRequest* aReadIntoRequest,
340 ErrorResult& aRv);
342 void ReadableByteStreamControllerError(
343 ReadableByteStreamController* aController, JS::Handle<JS::Value> aValue,
344 ErrorResult& aRv);
346 MOZ_CAN_RUN_SCRIPT void ReadableByteStreamControllerEnqueue(
347 JSContext* aCx, ReadableByteStreamController* aController,
348 JS::Handle<JSObject*> aChunk, ErrorResult& aRv);
350 already_AddRefed<ReadableStreamBYOBRequest>
351 ReadableByteStreamControllerGetBYOBRequest(
352 JSContext* aCx, ReadableByteStreamController* aController,
353 ErrorResult& aRv);
355 MOZ_CAN_RUN_SCRIPT void ReadableByteStreamControllerClose(
356 JSContext* aCx, ReadableByteStreamController* aController,
357 ErrorResult& aRv);
359 MOZ_CAN_RUN_SCRIPT void SetUpReadableByteStreamController(
360 JSContext* aCx, ReadableStream* aStream,
361 ReadableByteStreamController* aController,
362 UnderlyingSourceAlgorithmsBase* aAlgorithms, double aHighWaterMark,
363 Maybe<uint64_t> aAutoAllocateChunkSize, ErrorResult& aRv);
365 MOZ_CAN_RUN_SCRIPT void ReadableByteStreamControllerCallPullIfNeeded(
366 JSContext* aCx, ReadableByteStreamController* aController,
367 ErrorResult& aRv);
369 MOZ_CAN_RUN_SCRIPT void SetUpReadableByteStreamControllerFromUnderlyingSource(
370 JSContext* aCx, ReadableStream* aStream,
371 JS::Handle<JSObject*> aUnderlyingSource,
372 UnderlyingSource& aUnderlyingSourceDict, double aHighWaterMark,
373 ErrorResult& aRv);
375 void ReadableByteStreamControllerClearAlgorithms(
376 ReadableByteStreamController* aController);
378 } // namespace mozilla::dom
380 #endif