Coverage Report

Created: 2025-09-05 06:52

/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
}