/src/serenity/Userland/Libraries/LibWeb/Streams/ReadableByteStreamController.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2023, Matthew Olsson <mattco@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #pragma once |
8 | | |
9 | | #include <AK/Optional.h> |
10 | | #include <AK/SinglyLinkedList.h> |
11 | | #include <LibWeb/Bindings/PlatformObject.h> |
12 | | #include <LibWeb/Streams/AbstractOperations.h> |
13 | | |
14 | | namespace Web::Streams { |
15 | | |
16 | | enum class ReaderType { |
17 | | Default, |
18 | | Byob, |
19 | | None, |
20 | | }; |
21 | | |
22 | | // https://streams.spec.whatwg.org/#pull-into-descriptor |
23 | | struct PullIntoDescriptor { |
24 | | // https://streams.spec.whatwg.org/#pull-into-descriptor-buffer |
25 | | // An ArrayBuffer |
26 | | JS::NonnullGCPtr<JS::ArrayBuffer> buffer; |
27 | | |
28 | | // https://streams.spec.whatwg.org/#pull-into-descriptor-buffer-byte-length |
29 | | // A positive integer representing the initial byte length of buffer |
30 | | u64 buffer_byte_length; |
31 | | |
32 | | // https://streams.spec.whatwg.org/#pull-into-descriptor-byte-offset |
33 | | // A nonnegative integer byte offset into the buffer where the underlying byte source will start writing |
34 | | u64 byte_offset; |
35 | | |
36 | | // https://streams.spec.whatwg.org/#pull-into-descriptor-byte-length |
37 | | // A positive integer number of bytes which can be written into the buffer |
38 | | u64 byte_length; |
39 | | |
40 | | // https://streams.spec.whatwg.org/#pull-into-descriptor-bytes-filled |
41 | | // A nonnegative integer number of bytes that have been written into the buffer so far |
42 | | u64 bytes_filled; |
43 | | |
44 | | // https://streams.spec.whatwg.org/#pull-into-descriptor-minimum-fill |
45 | | // A positive integer representing the minimum number of bytes that must be written into the buffer before the associated read() request may be fulfilled. By default, this equals the element size. |
46 | | u64 minimum_fill; |
47 | | |
48 | | // https://streams.spec.whatwg.org/#pull-into-descriptor-element-size |
49 | | // A positive integer representing the number of bytes that can be written into the buffer at a time, using views of the type described by the view constructor |
50 | | u64 element_size; |
51 | | |
52 | | // https://streams.spec.whatwg.org/#pull-into-descriptor-view-constructor |
53 | | // A typed array constructor or %DataView%, which will be used for constructing a view with which to write into the buffer |
54 | | JS::NonnullGCPtr<JS::NativeFunction> view_constructor; |
55 | | |
56 | | // https://streams.spec.whatwg.org/#pull-into-descriptor-reader-type |
57 | | // Either "default" or "byob", indicating what type of readable stream reader initiated this request, or "none" if the initiating reader was released |
58 | | ReaderType reader_type; |
59 | | }; |
60 | | |
61 | | // https://streams.spec.whatwg.org/#readable-byte-stream-queue-entry |
62 | | struct ReadableByteStreamQueueEntry { |
63 | | // https://streams.spec.whatwg.org/#readable-byte-stream-queue-entry-buffer |
64 | | // An ArrayBuffer, which will be a transferred version of the one originally supplied by the underlying byte source |
65 | | JS::NonnullGCPtr<JS::ArrayBuffer> buffer; |
66 | | |
67 | | // https://streams.spec.whatwg.org/#readable-byte-stream-queue-entry-byte-offset |
68 | | // A nonnegative integer number giving the byte offset derived from the view originally supplied by the underlying byte source |
69 | | u64 byte_offset; |
70 | | |
71 | | // https://streams.spec.whatwg.org/#readable-byte-stream-queue-entry-byte-length |
72 | | // A nonnegative integer number giving the byte length derived from the view originally supplied by the underlying byte source |
73 | | u64 byte_length; |
74 | | }; |
75 | | |
76 | | // https://streams.spec.whatwg.org/#readablebytestreamcontroller |
77 | | class ReadableByteStreamController : public Bindings::PlatformObject { |
78 | | WEB_PLATFORM_OBJECT(ReadableByteStreamController, Bindings::PlatformObject); |
79 | | JS_DECLARE_ALLOCATOR(ReadableByteStreamController); |
80 | | |
81 | | public: |
82 | 0 | virtual ~ReadableByteStreamController() override = default; |
83 | | |
84 | | // IDL getter, returns current [[byobRequest]] (if any), and otherwise the [[byobRequest]] for the next pending pull into request |
85 | | JS::GCPtr<ReadableStreamBYOBRequest> byob_request(); |
86 | | |
87 | 0 | void set_byob_request(JS::GCPtr<ReadableStreamBYOBRequest> request) { m_byob_request = request; } |
88 | | |
89 | | // Raw [[byobRequest]] slot |
90 | 0 | JS::GCPtr<ReadableStreamBYOBRequest const> raw_byob_request() const { return m_byob_request; } |
91 | 0 | JS::GCPtr<ReadableStreamBYOBRequest> raw_byob_request() { return m_byob_request; } |
92 | | |
93 | | Optional<double> desired_size() const; |
94 | | WebIDL::ExceptionOr<void> close(); |
95 | | void error(JS::Value error); |
96 | | WebIDL::ExceptionOr<void> enqueue(JS::Handle<WebIDL::ArrayBufferView>&); |
97 | | |
98 | 0 | Optional<u64> const& auto_allocate_chunk_size() { return m_auto_allocate_chunk_size; } |
99 | 0 | void set_auto_allocate_chunk_size(Optional<u64> value) { m_auto_allocate_chunk_size = value; } |
100 | | |
101 | 0 | JS::GCPtr<CancelAlgorithm> cancel_algorithm() { return m_cancel_algorithm; } |
102 | 0 | void set_cancel_algorithm(JS::GCPtr<CancelAlgorithm> value) { m_cancel_algorithm = value; } |
103 | | |
104 | 0 | bool close_requested() const { return m_close_requested; } |
105 | 0 | void set_close_requested(bool value) { m_close_requested = value; } |
106 | | |
107 | 0 | bool pull_again() const { return m_pull_again; } |
108 | 0 | void set_pull_again(bool value) { m_pull_again = value; } |
109 | | |
110 | 0 | JS::GCPtr<PullAlgorithm> pull_algorithm() { return m_pull_algorithm; } |
111 | 0 | void set_pull_algorithm(JS::GCPtr<PullAlgorithm> value) { m_pull_algorithm = value; } |
112 | | |
113 | 0 | bool pulling() const { return m_pulling; } |
114 | 0 | void set_pulling(bool value) { m_pulling = value; } |
115 | | |
116 | 0 | SinglyLinkedList<PullIntoDescriptor>& pending_pull_intos() { return m_pending_pull_intos; } |
117 | 0 | SinglyLinkedList<PullIntoDescriptor> const& pending_pull_intos() const { return m_pending_pull_intos; } |
118 | | |
119 | 0 | SinglyLinkedList<ReadableByteStreamQueueEntry>& queue() { return m_queue; } |
120 | | |
121 | 0 | double queue_total_size() const { return m_queue_total_size; } |
122 | 0 | void set_queue_total_size(double size) { m_queue_total_size = size; } |
123 | | |
124 | 0 | bool started() const { return m_started; } |
125 | 0 | void set_started(bool value) { m_started = value; } |
126 | | |
127 | 0 | double strategy_hwm() const { return m_strategy_hwm; } |
128 | 0 | void set_strategy_hwm(double value) { m_strategy_hwm = value; } |
129 | | |
130 | 0 | JS::GCPtr<ReadableStream const> stream() const { return m_stream; } |
131 | 0 | JS::GCPtr<ReadableStream> stream() { return m_stream; } |
132 | 0 | void set_stream(JS::GCPtr<ReadableStream> stream) { m_stream = stream; } |
133 | | |
134 | | JS::NonnullGCPtr<WebIDL::Promise> cancel_steps(JS::Value reason); |
135 | | void pull_steps(JS::NonnullGCPtr<ReadRequest>); |
136 | | void release_steps(); |
137 | | |
138 | | private: |
139 | | explicit ReadableByteStreamController(JS::Realm&); |
140 | | |
141 | | virtual void visit_edges(Cell::Visitor&) override; |
142 | | |
143 | | virtual void initialize(JS::Realm&) override; |
144 | | |
145 | | // https://streams.spec.whatwg.org/#readablebytestreamcontroller-autoallocatechunksize |
146 | | // A positive integer, when the automatic buffer allocation feature is enabled. In that case, this value specifies the size of buffer to allocate. It is undefined otherwise. |
147 | | Optional<u64> m_auto_allocate_chunk_size; |
148 | | |
149 | | // https://streams.spec.whatwg.org/#readablebytestreamcontroller-byobrequest |
150 | | // A ReadableStreamBYOBRequest instance representing the current BYOB pull request, or null if there are no pending requests |
151 | | JS::GCPtr<ReadableStreamBYOBRequest> m_byob_request; |
152 | | |
153 | | // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-cancelalgorithm |
154 | | // A promise-returning algorithm, taking one argument (the cancel reason), which communicates a requested cancelation to the underlying source |
155 | | JS::GCPtr<CancelAlgorithm> m_cancel_algorithm; |
156 | | |
157 | | // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-closerequested |
158 | | // A boolean flag indicating whether the stream has been closed by its underlying source, but still has chunks in its internal queue that have not yet been read |
159 | | bool m_close_requested { false }; |
160 | | |
161 | | // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-pullagain |
162 | | // A boolean flag set to true if the stream’s mechanisms requested a call to the underlying source's pull algorithm to pull more data, but the pull could not yet be done since a previous call is still executing |
163 | | bool m_pull_again { false }; |
164 | | |
165 | | // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-pullalgorithm |
166 | | // A promise-returning algorithm that pulls data from the underlying source |
167 | | JS::GCPtr<PullAlgorithm> m_pull_algorithm; |
168 | | |
169 | | // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-pulling |
170 | | // A boolean flag set to true while the underlying source's pull algorithm is executing and the returned promise has not yet fulfilled, used to prevent reentrant calls |
171 | | bool m_pulling { false }; |
172 | | |
173 | | // https://streams.spec.whatwg.org/#readablebytestreamcontroller-pendingpullintos |
174 | | // A list of pull-into descriptors |
175 | | SinglyLinkedList<PullIntoDescriptor> m_pending_pull_intos; |
176 | | |
177 | | // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-queue |
178 | | // A list representing the stream’s internal queue of chunks |
179 | | SinglyLinkedList<ReadableByteStreamQueueEntry> m_queue; |
180 | | |
181 | | // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-queuetotalsize |
182 | | // The total size of all the chunks stored in [[queue]] |
183 | | double m_queue_total_size { 0 }; |
184 | | |
185 | | // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-started |
186 | | // A boolean flag indicating whether the underlying source has finished starting |
187 | | bool m_started { false }; |
188 | | |
189 | | // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-strategyhwm |
190 | | // A number supplied to the constructor as part of the stream’s queuing strategy, indicating the point at which the stream will apply backpressure to its underlying source |
191 | | double m_strategy_hwm { 0 }; |
192 | | |
193 | | // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-stream |
194 | | // The ReadableStream instance controlled |
195 | | JS::GCPtr<ReadableStream> m_stream; |
196 | | }; |
197 | | |
198 | | } |