From 87654f5b513165c9faf8863d3a9332aa2da7c0ac Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Wed, 21 Sep 2022 23:27:13 +0100 Subject: [PATCH] LibWeb: Start fleshing out the ReadableStream interface This is so we can just assume it exists in Fetch APIs (while still skipping functionality that relies on a full implementation, of course). --- .../LibWeb/Bindings/WindowObjectHelper.h | 3 + Userland/Libraries/LibWeb/CMakeLists.txt | 2 + Userland/Libraries/LibWeb/Forward.h | 12 ++-- .../LibWeb/Streams/AbstractOperations.cpp | 23 ++++++ .../LibWeb/Streams/AbstractOperations.h | 15 ++++ .../LibWeb/Streams/ReadableStream.cpp | 71 +++++++++++++++++++ .../Libraries/LibWeb/Streams/ReadableStream.h | 71 +++++++++++++++++++ .../LibWeb/Streams/ReadableStream.idl | 5 ++ Userland/Libraries/LibWeb/idl_files.cmake | 1 + 9 files changed, 199 insertions(+), 4 deletions(-) create mode 100644 Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp create mode 100644 Userland/Libraries/LibWeb/Streams/AbstractOperations.h create mode 100644 Userland/Libraries/LibWeb/Streams/ReadableStream.cpp create mode 100644 Userland/Libraries/LibWeb/Streams/ReadableStream.h create mode 100644 Userland/Libraries/LibWeb/Streams/ReadableStream.idl diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h b/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h index 2eb176c02d..9944790de6 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h +++ b/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h @@ -301,6 +301,8 @@ #include #include #include +#include +#include #include #include #include @@ -543,6 +545,7 @@ ADD_WINDOW_OBJECT_INTERFACE(ProgressEvent) \ ADD_WINDOW_OBJECT_INTERFACE(PromiseRejectionEvent) \ ADD_WINDOW_OBJECT_INTERFACE(Range) \ + ADD_WINDOW_OBJECT_INTERFACE(ReadableStream) \ ADD_WINDOW_OBJECT_INTERFACE(ResizeObserver) \ ADD_WINDOW_OBJECT_INTERFACE(Screen) \ ADD_WINDOW_OBJECT_INTERFACE(Selection) \ diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 47983f1cde..d8356938fa 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -364,6 +364,8 @@ set(SOURCES Platform/TimerSerenity.cpp RequestIdleCallback/IdleDeadline.cpp ResizeObserver/ResizeObserver.cpp + Streams/AbstractOperations.cpp + Streams/ReadableStream.cpp SVG/AttributeNames.cpp SVG/AttributeParser.cpp SVG/SVGAnimatedLength.cpp diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index ead5a73949..94fde4f6cd 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -366,6 +366,14 @@ namespace Web::ResizeObserver { class ResizeObserver; } +namespace Web::Selection { +class Selection; +} + +namespace Web::Streams { +class ReadableStream; +} + namespace Web::SVG { class SVGAnimatedLength; class SVGCircleElement; @@ -384,10 +392,6 @@ class SVGRectElement; class SVGSVGElement; } -namespace Web::Selection { -class Selection; -} - namespace Web::WebSockets { class WebSocket; } diff --git a/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp b/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp new file mode 100644 index 0000000000..ac1045b707 --- /dev/null +++ b/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022, Linus Groh + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +namespace Web::Streams { + +// https://streams.spec.whatwg.org/#is-readable-stream-locked +bool is_readable_stream_locked(ReadableStream const& stream) +{ + // 1. If stream.[[reader]] is undefined, return false. + if (stream.reader() == nullptr) + return false; + + // 2. Return true. + return true; +} + +} diff --git a/Userland/Libraries/LibWeb/Streams/AbstractOperations.h b/Userland/Libraries/LibWeb/Streams/AbstractOperations.h new file mode 100644 index 0000000000..0ffb117183 --- /dev/null +++ b/Userland/Libraries/LibWeb/Streams/AbstractOperations.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2022, Linus Groh + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Web::Streams { + +bool is_readable_stream_locked(ReadableStream const&); + +} diff --git a/Userland/Libraries/LibWeb/Streams/ReadableStream.cpp b/Userland/Libraries/LibWeb/Streams/ReadableStream.cpp new file mode 100644 index 0000000000..e035a96b3e --- /dev/null +++ b/Userland/Libraries/LibWeb/Streams/ReadableStream.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022, Linus Groh + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +namespace Web::Streams { + +// https://streams.spec.whatwg.org/#rs-constructor +DOM::ExceptionOr> ReadableStream::create_with_global_object(HTML::Window& window) +{ + auto* readable_stream = window.heap().allocate(window.realm(), window); + + return JS::NonnullGCPtr { *readable_stream }; +} + +ReadableStream::ReadableStream(HTML::Window& window) + : PlatformObject(window.realm()) +{ + set_prototype(&window.cached_web_prototype("ReadableStream")); +} + +ReadableStream::~ReadableStream() = default; + +void ReadableStream::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_controller); + visitor.visit(m_reader); + visitor.visit(m_stored_error); +} + +// https://streams.spec.whatwg.org/#readablestream-locked +bool ReadableStream::is_readable() const +{ + // A ReadableStream stream is readable if stream.[[state]] is "readable". + return m_state == State::Readable; +} + +// https://streams.spec.whatwg.org/#readablestream-closed +bool ReadableStream::is_closed() const +{ + // A ReadableStream stream is closed if stream.[[state]] is "closed". + return m_state == State::Closed; +} + +// https://streams.spec.whatwg.org/#readablestream-errored +bool ReadableStream::is_errored() const +{ + // A ReadableStream stream is errored if stream.[[state]] is "errored". + return m_state == State::Errored; +} +// https://streams.spec.whatwg.org/#readablestream-locked +bool ReadableStream::is_locked() const +{ + // A ReadableStream stream is locked if ! IsReadableStreamLocked(stream) returns true. + return is_readable_stream_locked(*this); +} + +// https://streams.spec.whatwg.org/#is-readable-stream-disturbed +bool ReadableStream::is_disturbed() const +{ + // A ReadableStream stream is disturbed if stream.[[disturbed]] is true. + return m_disturbed; +} + +} diff --git a/Userland/Libraries/LibWeb/Streams/ReadableStream.h b/Userland/Libraries/LibWeb/Streams/ReadableStream.h new file mode 100644 index 0000000000..7a60125e89 --- /dev/null +++ b/Userland/Libraries/LibWeb/Streams/ReadableStream.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022, Linus Groh + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +namespace Web::Streams { + +// https://streams.spec.whatwg.org/#readablestream +class ReadableStream final : public Bindings::PlatformObject { + WEB_PLATFORM_OBJECT(Request, Bindings::PlatformObject); + +public: + enum class State { + Readable, + Closed, + Errored, + }; + + static DOM::ExceptionOr> create_with_global_object(HTML::Window&); + + virtual ~ReadableStream() override; + + JS::GCPtr controller() const { return m_controller; } + JS::GCPtr reader() const { return m_reader; } + JS::Value stored_error() const { return m_stored_error; } + + bool is_readable() const; + bool is_closed() const; + bool is_errored() const; + bool is_locked() const; + bool is_disturbed() const; + +private: + explicit ReadableStream(HTML::Window&); + + virtual void visit_edges(Cell::Visitor&) override; + + // https://streams.spec.whatwg.org/#readablestream-controller + // A ReadableStreamDefaultController or ReadableByteStreamController created with the ability to control the state and queue of this stream + JS::GCPtr m_controller; + + // https://streams.spec.whatwg.org/#readablestream-detached + // A boolean flag set to true when the stream is transferred + bool m_detached { false }; + + // https://streams.spec.whatwg.org/#readablestream-disturbed + // A boolean flag set to true when the stream has been read from or canceled + bool m_disturbed { false }; + + // 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 + JS::GCPtr 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" + State m_state { State::Readable }; + + // https://streams.spec.whatwg.org/#readablestream-storederror + // A value indicating how the stream failed, to be given as a failure reason or exception when trying to operate on an errored stream + JS::Value m_stored_error { JS::js_undefined() }; +}; + +} diff --git a/Userland/Libraries/LibWeb/Streams/ReadableStream.idl b/Userland/Libraries/LibWeb/Streams/ReadableStream.idl new file mode 100644 index 0000000000..fbe51a1825 --- /dev/null +++ b/Userland/Libraries/LibWeb/Streams/ReadableStream.idl @@ -0,0 +1,5 @@ +// Dummy definition so we can use ReadableStream as a type in Fetch. + +// https://streams.spec.whatwg.org/#readablestream +interface ReadableStream { +}; diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index cf3a00541f..3239d265e3 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -159,6 +159,7 @@ libweb_js_bindings(IntersectionObserver/IntersectionObserver) libweb_js_bindings(NavigationTiming/PerformanceTiming) libweb_js_bindings(RequestIdleCallback/IdleDeadline) libweb_js_bindings(ResizeObserver/ResizeObserver) +libweb_js_bindings(Streams/ReadableStream) libweb_js_bindings(SVG/SVGAnimatedLength) libweb_js_bindings(SVG/SVGClipPathElement) libweb_js_bindings(SVG/SVGDefsElement)