diff options
author | Matthew Olsson <matthewcolsson@gmail.com> | 2023-04-09 01:26:48 -0700 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-04-27 07:57:53 +0200 |
commit | b57b3c54cca6027e88959ead40399622c3359766 (patch) | |
tree | 53e670e8f3c432848096cd9872e12191ce1b82fb /Userland/Libraries | |
parent | e8ad57108264b2bcc3a0ffeaf255d04866dd42e4 (diff) | |
download | serenity-b57b3c54cca6027e88959ead40399622c3359766.zip |
LibWeb: Add ReadableStreamBYOBReader to ReadableStreamReader type
Diffstat (limited to 'Userland/Libraries')
7 files changed, 58 insertions, 53 deletions
diff --git a/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp b/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp index 8483578c25..ffc12344e9 100644 --- a/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp +++ b/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp @@ -12,6 +12,7 @@ #include <LibWeb/Streams/AbstractOperations.h> #include <LibWeb/Streams/ReadableByteStreamController.h> #include <LibWeb/Streams/ReadableStream.h> +#include <LibWeb/Streams/ReadableStreamBYOBReader.h> #include <LibWeb/Streams/ReadableStreamBYOBRequest.h> #include <LibWeb/Streams/ReadableStreamDefaultController.h> #include <LibWeb/Streams/ReadableStreamDefaultReader.h> @@ -46,7 +47,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<ReadableStreamDefaultReader>> acquire_reada bool is_readable_stream_locked(ReadableStream const& stream) { // 1. If stream.[[reader]] is undefined, return false. - if (!stream.reader()) + if (!stream.reader().has_value()) return false; // 2. Return true. @@ -75,13 +76,18 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> readable_stream_cancel(Re // 5. Let reader be stream.[[reader]]. auto reader = stream.reader(); - // FIXME: // 6. If reader is not undefined and reader implements ReadableStreamBYOBReader, - // 1. Let readIntoRequests be reader.[[readIntoRequests]]. - // 2. Set reader.[[readIntoRequests]] to an empty list. - // 3. For each readIntoRequest of readIntoRequests, - // 1. Perform readIntoRequest’s close steps, given undefined. - (void)reader; + if (reader.has_value() && reader->has<JS::NonnullGCPtr<ReadableStreamBYOBReader>>()) { + // 1. Let readIntoRequests be reader.[[readIntoRequests]]. + // 2. Set reader.[[readIntoRequests]] to an empty list. + auto read_into_requests = move(reader->get<JS::NonnullGCPtr<ReadableStreamBYOBReader>>()->read_into_requests()); + + // 3. For each readIntoRequest of readIntoRequests, + for (auto& read_into_request : read_into_requests) { + // 1. Perform readIntoRequest’s close steps, given undefined. + read_into_request->on_close(JS::js_undefined()); + } + } // 7. Let sourceCancelPromise be ! stream.[[controller]].[[CancelSteps]](reason). auto source_cancel_promise = TRY(stream.controller()->visit([&](auto const& controller) { @@ -103,14 +109,14 @@ void readable_stream_fulfill_read_request(ReadableStream& stream, JS::Value chun VERIFY(readable_stream_has_default_reader(stream)); // 2. Let reader be stream.[[reader]]. - auto& reader = *stream.reader(); + auto reader = stream.reader()->get<JS::NonnullGCPtr<ReadableStreamDefaultReader>>(); // 3. Assert: reader.[[readRequests]] is not empty. - VERIFY(!reader.read_requests().is_empty()); + VERIFY(!reader->read_requests().is_empty()); // 4. Let readRequest be reader.[[readRequests]][0]. // 5. Remove readRequest from reader.[[readRequests]]. - auto read_request = reader.read_requests().take_first(); + auto read_request = reader->read_requests().take_first(); // 6. If done is true, perform readRequest’s close steps. if (done) { @@ -129,7 +135,7 @@ size_t readable_stream_get_num_read_requests(ReadableStream& stream) VERIFY(readable_stream_has_default_reader(stream)); // 2. Return stream.[[reader]].[[readRequests]]'s size. - return stream.reader()->read_requests().size(); + return stream.reader()->get<JS::NonnullGCPtr<ReadableStreamDefaultReader>>()->read_requests().size(); } // https://streams.spec.whatwg.org/#readable-stream-has-default-reader @@ -139,11 +145,11 @@ bool readable_stream_has_default_reader(ReadableStream& stream) auto reader = stream.reader(); // 2. If reader is undefined, return false. - if (!reader) + if (!reader.has_value()) return false; // 3. If reader implements ReadableStreamDefaultReader, return true. - if (reader->is_default_reader()) + if (reader->has<JS::NonnullGCPtr<ReadableStreamDefaultReader>>()) return true; // 4. Return false. @@ -165,17 +171,19 @@ void readable_stream_close(ReadableStream& stream) auto reader = stream.reader(); // 4. If reader is undefined, return. - if (!reader) + if (!reader.has_value()) return; // 5. Resolve reader.[[closedPromise]] with undefined. - WebIDL::resolve_promise(realm, *reader->closed_promise_capability()); + WebIDL::resolve_promise(realm, *reader->visit([](auto& reader) { + return reader->closed_promise_capability(); + })); // 6. If reader implements ReadableStreamDefaultReader, - if (reader->is_default_reader()) { + if (reader->has<JS::NonnullGCPtr<ReadableStreamDefaultReader>>()) { // 1. Let readRequests be reader.[[readRequests]]. // 2. Set reader.[[readRequests]] to an empty list. - auto read_requests = move(reader->read_requests()); + auto read_requests = move(reader->get<JS::NonnullGCPtr<ReadableStreamDefaultReader>>()->read_requests()); // 3. For each readRequest of readRequests, for (auto& read_request : read_requests) { @@ -203,19 +211,21 @@ void readable_stream_error(ReadableStream& stream, JS::Value error) auto reader = stream.reader(); // 5. If reader is undefined, return. - if (!reader) + if (!reader.has_value()) return; + auto closed_promise_capability = reader->visit([](auto& reader) { return reader->closed_promise_capability(); }); + // 6. Reject reader.[[closedPromise]] with e. - WebIDL::reject_promise(realm, *reader->closed_promise_capability(), error); + WebIDL::reject_promise(realm, *closed_promise_capability, error); // 7. Set reader.[[closedPromise]].[[PromiseIsHandled]] to true. - WebIDL::mark_promise_as_handled(*reader->closed_promise_capability()); + WebIDL::mark_promise_as_handled(*closed_promise_capability); // 8. If reader implements ReadableStreamDefaultReader, - if (reader->is_default_reader()) { + if (reader->has<JS::NonnullGCPtr<ReadableStreamDefaultReader>>()) { // 1. Perform ! ReadableStreamDefaultReaderErrorReadRequests(reader, e). - readable_stream_default_reader_error_read_requests(*reader, error); + readable_stream_default_reader_error_read_requests(*reader->get<JS::NonnullGCPtr<ReadableStreamDefaultReader>>(), error); } // 9. Otherwise, else { @@ -230,15 +240,14 @@ void readable_stream_error(ReadableStream& stream, JS::Value error) // https://streams.spec.whatwg.org/#readable-stream-add-read-request void readable_stream_add_read_request(ReadableStream& stream, ReadRequest const& read_request) { - // FIXME: Check implementation type // 1. Assert: stream.[[reader]] implements ReadableStreamDefaultReader. - VERIFY(stream.reader()); + VERIFY(stream.reader().has_value() && stream.reader()->has<JS::NonnullGCPtr<ReadableStreamDefaultReader>>()); // 2. Assert: stream.[[state]] is "readable". VERIFY(stream.state() == ReadableStream::State::Readable); // 3. Append readRequest to stream.[[reader]].[[readRequests]]. - stream.reader()->read_requests().append(read_request); + stream.reader()->get<JS::NonnullGCPtr<ReadableStreamDefaultReader>>()->read_requests().append(read_request); } // https://streams.spec.whatwg.org/#readable-stream-reader-generic-cancel @@ -255,30 +264,27 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> readable_stream_reader_ge } // https://streams.spec.whatwg.org/#readable-stream-reader-generic-initialize -void readable_stream_reader_generic_initialize(ReadableStreamGenericReaderMixin& reader, ReadableStream& stream) +void readable_stream_reader_generic_initialize(ReadableStreamReader reader, ReadableStream& stream) { auto& realm = stream.realm(); // 1. Set reader.[[stream]] to stream. - reader.set_stream(stream); + reader.visit([&](auto& reader) { reader->set_stream(stream); }); // 2. Set stream.[[reader]] to reader. - if (reader.is_default_reader()) { - stream.set_reader(static_cast<ReadableStreamDefaultReader&>(reader)); - } else { - // FIXME: Handle other descendents of ReadableStreamGenericReaderMixin (i.e. BYOBReader) - TODO(); - } + stream.set_reader(reader); // 3. If stream.[[state]] is "readable", if (stream.state() == ReadableStream::State::Readable) { // 1. Set reader.[[closedPromise]] to a new promise. - reader.set_closed_promise_capability(WebIDL::create_promise(realm)); + reader.visit([&](auto& reader) { reader->set_closed_promise_capability(WebIDL::create_promise(realm)); }); } // 4. Otherwise, if stream.[[state]] is "closed", else if (stream.state() == ReadableStream::State::Closed) { // 1. Set reader.[[closedPromise]] to a promise resolved with undefined. - reader.set_closed_promise_capability(WebIDL::create_resolved_promise(realm, JS::js_undefined())); + reader.visit([&](auto& reader) { + reader->set_closed_promise_capability(WebIDL::create_resolved_promise(realm, JS::js_undefined())); + }); } // 5. Otherwise, else { @@ -286,10 +292,11 @@ void readable_stream_reader_generic_initialize(ReadableStreamGenericReaderMixin& VERIFY(stream.state() == ReadableStream::State::Errored); // 2. Set reader.[[closedPromise]] to a promise rejected with stream.[[storedError]]. - reader.set_closed_promise_capability(WebIDL::create_rejected_promise(realm, stream.stored_error())); - // 3. Set reader.[[closedPromise]].[[PromiseIsHandled]] to true. - WebIDL::mark_promise_as_handled(*reader.closed_promise_capability()); + reader.visit([&](auto& reader) { + reader->set_closed_promise_capability(WebIDL::create_rejected_promise(realm, stream.stored_error())); + WebIDL::mark_promise_as_handled(*reader->closed_promise_capability()); + }); } } @@ -303,7 +310,7 @@ WebIDL::ExceptionOr<void> readable_stream_reader_generic_release(ReadableStreamG VERIFY(stream); // 3. Assert: stream.[[reader]] is reader. - VERIFY(stream->reader().ptr() == &reader); + VERIFY(stream->reader()->visit([](auto& reader) -> ReadableStreamGenericReaderMixin* { return reader.ptr(); }) == &reader); auto& realm = stream->realm(); @@ -406,7 +413,7 @@ WebIDL::ExceptionOr<void> set_up_readable_stream_default_reader(ReadableStreamDe // 2. Perform ! ReadableStreamReaderGenericInitialize(reader, stream). // 3. Set reader.[[readRequests]] to a new empty list. - readable_stream_reader_generic_initialize(reader, stream); + readable_stream_reader_generic_initialize(ReadableStreamReader { reader }, stream); return {}; } diff --git a/Userland/Libraries/LibWeb/Streams/AbstractOperations.h b/Userland/Libraries/LibWeb/Streams/AbstractOperations.h index 918832038c..f8abb03434 100644 --- a/Userland/Libraries/LibWeb/Streams/AbstractOperations.h +++ b/Userland/Libraries/LibWeb/Streams/AbstractOperations.h @@ -9,6 +9,7 @@ #include <LibJS/Heap/GCPtr.h> #include <LibWeb/Forward.h> +#include <LibWeb/Streams/ReadableStream.h> #include <LibWeb/WebIDL/CallbackType.h> #include <LibWeb/WebIDL/ExceptionOr.h> #include <LibWeb/WebIDL/Promise.h> @@ -35,7 +36,7 @@ size_t readable_stream_get_num_read_requests(ReadableStream&); bool readable_stream_has_default_reader(ReadableStream&); WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> readable_stream_reader_generic_cancel(ReadableStreamGenericReaderMixin&, JS::Value reason); -void readable_stream_reader_generic_initialize(ReadableStreamGenericReaderMixin&, ReadableStream&); +void readable_stream_reader_generic_initialize(ReadableStreamReader, ReadableStream&); WebIDL::ExceptionOr<void> readable_stream_reader_generic_release(ReadableStreamGenericReaderMixin&); void readable_stream_default_reader_error_read_requests(ReadableStreamDefaultReader&, JS::Value error); diff --git a/Userland/Libraries/LibWeb/Streams/ReadableStream.cpp b/Userland/Libraries/LibWeb/Streams/ReadableStream.cpp index de150649c6..c747f6f03f 100644 --- a/Userland/Libraries/LibWeb/Streams/ReadableStream.cpp +++ b/Userland/Libraries/LibWeb/Streams/ReadableStream.cpp @@ -9,6 +9,7 @@ #include <LibWeb/Streams/AbstractOperations.h> #include <LibWeb/Streams/ReadableByteStreamController.h> #include <LibWeb/Streams/ReadableStream.h> +#include <LibWeb/Streams/ReadableStreamBYOBReader.h> #include <LibWeb/Streams/ReadableStreamDefaultController.h> #include <LibWeb/Streams/ReadableStreamDefaultReader.h> #include <LibWeb/Streams/UnderlyingSource.h> @@ -111,7 +112,8 @@ void ReadableStream::visit_edges(Cell::Visitor& visitor) if (m_controller.has_value()) m_controller->visit([&](auto& controller) { visitor.visit(controller); }); visitor.visit(m_stored_error); - visitor.visit(m_reader); + if (m_reader.has_value()) + m_reader->visit([&](auto& reader) { visitor.visit(reader); }); } // https://streams.spec.whatwg.org/#readablestream-locked diff --git a/Userland/Libraries/LibWeb/Streams/ReadableStream.h b/Userland/Libraries/LibWeb/Streams/ReadableStream.h index 8ee92c1c4e..e9acd15b2f 100644 --- a/Userland/Libraries/LibWeb/Streams/ReadableStream.h +++ b/Userland/Libraries/LibWeb/Streams/ReadableStream.h @@ -13,9 +13,8 @@ namespace Web::Streams { -// FIXME: Variant<DefaultReader, ByteStreamReader> // https://streams.spec.whatwg.org/#typedefdef-readablestreamreader -using ReadableStreamReader = JS::GCPtr<ReadableStreamDefaultReader>; +using ReadableStreamReader = Variant<JS::NonnullGCPtr<ReadableStreamDefaultReader>, JS::NonnullGCPtr<ReadableStreamBYOBReader>>; // https://streams.spec.whatwg.org/#typedefdef-readablestreamcontroller using ReadableStreamController = Variant<JS::NonnullGCPtr<ReadableStreamDefaultController>, JS::NonnullGCPtr<ReadableByteStreamController>>; @@ -45,8 +44,8 @@ public: JS::Value stored_error() const { return m_stored_error; } void set_stored_error(JS::Value value) { m_stored_error = value; } - ReadableStreamReader reader() const { return m_reader; } - void set_reader(ReadableStreamReader value) { m_reader = value; } + Optional<ReadableStreamReader> const& reader() const { return m_reader; } + void set_reader(Optional<ReadableStreamReader> value) { m_reader = move(value); } bool is_disturbed() const; void set_disturbed(bool value) { m_disturbed = value; } @@ -79,7 +78,7 @@ private: // https://streams.spec.whatwg.org/#readablestream-reader // A ReadableStreamDefaultReader or ReadableStreamBYOBReader instance, if the stream is locked to a reader, or undefined if it is not - ReadableStreamReader m_reader; + Optional<ReadableStreamReader> m_reader; // https://streams.spec.whatwg.org/#readablestream-state // A string containing the stream’s current state, used internally; one of "readable", "closed", or "errored" diff --git a/Userland/Libraries/LibWeb/Streams/ReadableStream.idl b/Userland/Libraries/LibWeb/Streams/ReadableStream.idl index c189da14e3..c38656e29b 100644 --- a/Userland/Libraries/LibWeb/Streams/ReadableStream.idl +++ b/Userland/Libraries/LibWeb/Streams/ReadableStream.idl @@ -1,3 +1,4 @@ +#import <Streams/ReadableStreamBYOBReader.idl> #import <Streams/ReadableStreamDefaultReader.idl> // https://streams.spec.whatwg.org/#readablestream @@ -13,5 +14,4 @@ interface ReadableStream { ReadableStreamReader getReader(); }; -// FIXME: typedef (ReadableStreamDefaultReader or ReadableStreamBYOBReader) ReadableStreamReader; -typedef ReadableStreamDefaultReader ReadableStreamReader; +typedef (ReadableStreamDefaultReader or ReadableStreamBYOBReader) ReadableStreamReader; diff --git a/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultReader.h b/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultReader.h index c67bab2541..fffde74cf7 100644 --- a/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultReader.h +++ b/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultReader.h @@ -45,8 +45,6 @@ public: SinglyLinkedList<NonnullRefPtr<ReadRequest>>& read_requests() { return m_read_requests; } - virtual bool is_default_reader() const override { return true; } - private: explicit ReadableStreamDefaultReader(JS::Realm&); diff --git a/Userland/Libraries/LibWeb/Streams/ReadableStreamGenericReader.h b/Userland/Libraries/LibWeb/Streams/ReadableStreamGenericReader.h index bfca9f5ceb..dbeb691ddb 100644 --- a/Userland/Libraries/LibWeb/Streams/ReadableStreamGenericReader.h +++ b/Userland/Libraries/LibWeb/Streams/ReadableStreamGenericReader.h @@ -29,8 +29,6 @@ public: JS::GCPtr<WebIDL::Promise> closed_promise_capability() { return m_closed_promise; } void set_closed_promise_capability(JS::GCPtr<WebIDL::Promise> promise) { m_closed_promise = promise; } - virtual bool is_default_reader() const { return false; } - protected: explicit ReadableStreamGenericReaderMixin(JS::Realm&); |