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