Coverage Report

Created: 2025-03-04 07:22

/src/serenity/Userland/Libraries/LibWeb/Streams/ReadableStream.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
3
 * Copyright (c) 2024, Kenneth Myhra <kennethmyhra@serenityos.org>
4
 *
5
 * SPDX-License-Identifier: BSD-2-Clause
6
 */
7
8
#pragma once
9
10
#include <AK/Forward.h>
11
#include <LibJS/Forward.h>
12
#include <LibWeb/Bindings/PlatformObject.h>
13
#include <LibWeb/Bindings/ReadableStreamPrototype.h>
14
#include <LibWeb/Forward.h>
15
#include <LibWeb/Streams/QueuingStrategy.h>
16
17
namespace Web::Streams {
18
19
// https://streams.spec.whatwg.org/#typedefdef-readablestreamreader
20
using ReadableStreamReader = Variant<JS::NonnullGCPtr<ReadableStreamDefaultReader>, JS::NonnullGCPtr<ReadableStreamBYOBReader>>;
21
22
// https://streams.spec.whatwg.org/#typedefdef-readablestreamcontroller
23
using ReadableStreamController = Variant<JS::NonnullGCPtr<ReadableStreamDefaultController>, JS::NonnullGCPtr<ReadableByteStreamController>>;
24
25
// https://streams.spec.whatwg.org/#dictdef-readablestreamgetreaderoptions
26
struct ReadableStreamGetReaderOptions {
27
    Optional<Bindings::ReadableStreamReaderMode> mode;
28
};
29
30
struct ReadableWritablePair {
31
    JS::GCPtr<ReadableStream> readable;
32
    JS::GCPtr<WritableStream> writable;
33
};
34
35
struct StreamPipeOptions {
36
    bool prevent_close { false };
37
    bool prevent_abort { false };
38
    bool prevent_cancel { false };
39
    JS::GCPtr<DOM::AbortSignal> signal;
40
};
41
42
struct ReadableStreamPair {
43
    // Define a couple container-like methods so this type may be used as the return type of the IDL `tee` implementation.
44
0
    size_t size() const { return 2; }
45
46
    JS::NonnullGCPtr<ReadableStream>& at(size_t index)
47
0
    {
48
0
        if (index == 0)
49
0
            return first;
50
0
        if (index == 1)
51
0
            return second;
52
0
        VERIFY_NOT_REACHED();
53
0
    }
54
55
    JS::NonnullGCPtr<ReadableStream> first;
56
    JS::NonnullGCPtr<ReadableStream> second;
57
};
58
59
// https://streams.spec.whatwg.org/#readablestream
60
class ReadableStream final : public Bindings::PlatformObject {
61
    WEB_PLATFORM_OBJECT(ReadableStream, Bindings::PlatformObject);
62
    JS_DECLARE_ALLOCATOR(ReadableStream);
63
64
public:
65
    enum class State {
66
        Readable,
67
        Closed,
68
        Errored,
69
    };
70
71
    static WebIDL::ExceptionOr<JS::NonnullGCPtr<ReadableStream>> construct_impl(JS::Realm&, Optional<JS::Handle<JS::Object>> const& underlying_source, QueuingStrategy const& = {});
72
73
    static WebIDL::ExceptionOr<JS::NonnullGCPtr<ReadableStream>> from(JS::VM& vm, JS::Value async_iterable);
74
75
    virtual ~ReadableStream() override;
76
77
    bool locked() const;
78
    JS::NonnullGCPtr<JS::Object> cancel(JS::Value reason);
79
    WebIDL::ExceptionOr<ReadableStreamReader> get_reader(ReadableStreamGetReaderOptions const& = {});
80
    WebIDL::ExceptionOr<JS::NonnullGCPtr<ReadableStream>> pipe_through(ReadableWritablePair transform, StreamPipeOptions const& = {});
81
    JS::NonnullGCPtr<JS::Object> pipe_to(WritableStream& destination, StreamPipeOptions const& = {});
82
    WebIDL::ExceptionOr<ReadableStreamPair> tee();
83
84
    void close();
85
    void error(JS::Value);
86
87
0
    Optional<ReadableStreamController>& controller() { return m_controller; }
88
0
    void set_controller(Optional<ReadableStreamController> value) { m_controller = move(value); }
89
90
0
    JS::Value stored_error() const { return m_stored_error; }
91
0
    void set_stored_error(JS::Value value) { m_stored_error = value; }
92
93
0
    Optional<ReadableStreamReader> const& reader() const { return m_reader; }
94
0
    void set_reader(Optional<ReadableStreamReader> value) { m_reader = move(value); }
95
96
    bool is_disturbed() const;
97
0
    void set_disturbed(bool value) { m_disturbed = value; }
98
99
    bool is_readable() const;
100
    bool is_closed() const;
101
    bool is_errored() const;
102
    bool is_locked() const;
103
104
0
    State state() const { return m_state; }
105
0
    void set_state(State value) { m_state = value; }
106
107
private:
108
    explicit ReadableStream(JS::Realm&);
109
110
    virtual void initialize(JS::Realm&) override;
111
    virtual void visit_edges(Cell::Visitor&) override;
112
113
    // https://streams.spec.whatwg.org/#readablestream-controller
114
    // A ReadableStreamDefaultController or ReadableByteStreamController created with the ability to control the state and queue of this stream
115
    Optional<ReadableStreamController> m_controller;
116
117
    // https://streams.spec.whatwg.org/#readablestream-detached
118
    // A boolean flag set to true when the stream is transferred
119
    bool m_detached { false };
120
121
    // https://streams.spec.whatwg.org/#readablestream-disturbed
122
    // A boolean flag set to true when the stream has been read from or canceled
123
    bool m_disturbed { false };
124
125
    // https://streams.spec.whatwg.org/#readablestream-reader
126
    // A ReadableStreamDefaultReader or ReadableStreamBYOBReader instance, if the stream is locked to a reader, or undefined if it is not
127
    Optional<ReadableStreamReader> m_reader;
128
129
    // https://streams.spec.whatwg.org/#readablestream-state
130
    // A string containing the stream’s current state, used internally; one of "readable", "closed", or "errored"
131
    State m_state { State::Readable };
132
133
    // https://streams.spec.whatwg.org/#readablestream-storederror
134
    // A value indicating how the stream failed, to be given as a failure reason or exception when trying to operate on an errored stream
135
    JS::Value m_stored_error { JS::js_undefined() };
136
};
137
138
}