From 66dec1bf5491b2ffdc39b74fa64979574bd15069 Mon Sep 17 00:00:00 2001 From: Matthew Olsson Date: Tue, 28 Mar 2023 18:58:41 -0700 Subject: [PATCH] LibWeb: Add UnderlyingSource struct for ReadableStream constructor --- Userland/Libraries/LibWeb/CMakeLists.txt | 1 + Userland/Libraries/LibWeb/Forward.h | 1 + .../LibWeb/Streams/UnderlyingSource.cpp | 59 +++++++++++++++++++ .../LibWeb/Streams/UnderlyingSource.h | 31 ++++++++++ 4 files changed, 92 insertions(+) create mode 100644 Userland/Libraries/LibWeb/Streams/UnderlyingSource.cpp create mode 100644 Userland/Libraries/LibWeb/Streams/UnderlyingSource.h diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index fe7450e723..a66c0eb03b 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -459,6 +459,7 @@ set(SOURCES Streams/ReadableStreamDefaultController.cpp Streams/ReadableStreamDefaultReader.cpp Streams/ReadableStreamGenericReader.cpp + Streams/UnderlyingSource.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 f7e8a948c3..28f4d2ed68 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -422,6 +422,7 @@ class ReadableStreamDefaultController; class ReadableStreamDefaultReader; class ReadableStreamGenericReaderMixin; class ReadRequest; +struct UnderlyingSource; } namespace Web::SVG { diff --git a/Userland/Libraries/LibWeb/Streams/UnderlyingSource.cpp b/Userland/Libraries/LibWeb/Streams/UnderlyingSource.cpp new file mode 100644 index 0000000000..7ea43d3e44 --- /dev/null +++ b/Userland/Libraries/LibWeb/Streams/UnderlyingSource.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023, Matthew Olsson + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +namespace Web::Streams { + +// Non-standard function to aid in converting a user-provided function into a WebIDL::Callback. This is essentially +// what the Bindings generator would do at compile time, but at runtime instead. +static JS::ThrowCompletionOr> property_to_callback(JS::VM& vm, JS::Value value, JS::PropertyKey const& property_key) +{ + auto property = TRY(value.get(vm, property_key)); + + if (property.is_undefined()) + return JS::Handle {}; + + if (!property.is_function()) + return vm.throw_completion(JS::ErrorType::NotAFunction, TRY_OR_THROW_OOM(vm, property.to_string_without_side_effects())); + + return vm.heap().allocate_without_realm(property.as_object(), HTML::incumbent_settings_object()); +} + +JS::ThrowCompletionOr UnderlyingSource::from_value(JS::VM& vm, JS::Value value) +{ + if (!value.is_object()) + return UnderlyingSource {}; + + auto& object = value.as_object(); + + UnderlyingSource underlying_source { + .start = TRY(property_to_callback(vm, value, "start")), + .pull = TRY(property_to_callback(vm, value, "pull")), + .cancel = TRY(property_to_callback(vm, value, "cancel")), + .type = {}, + .auto_allocate_chunk_size = {}, + }; + + if (TRY(object.has_property("type"))) { + auto type_value = TRY(TRY(object.get("type")).to_string(object.vm())); + if (type_value == "bytes"sv) { + underlying_source.type = ReadableStreamType::Bytes; + } else { + return vm.throw_completion(DeprecatedString::formatted("Unknown stream type '{}'", type_value)); + } + } + + if (TRY(object.has_property("autoAllocateChunkSize"))) + underlying_source.auto_allocate_chunk_size = TRY(TRY(object.get("autoAllocateChunkSize")).to_bigint_int64(object.vm())); + + return underlying_source; +} + +} diff --git a/Userland/Libraries/LibWeb/Streams/UnderlyingSource.h b/Userland/Libraries/LibWeb/Streams/UnderlyingSource.h new file mode 100644 index 0000000000..08daab383a --- /dev/null +++ b/Userland/Libraries/LibWeb/Streams/UnderlyingSource.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023, Matthew Olsson + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace Web::Streams { + +enum class ReadableStreamType { + Bytes +}; + +struct UnderlyingSource { + JS::Handle start; + JS::Handle pull; + JS::Handle cancel; + Optional type; + Optional auto_allocate_chunk_size; + + static JS::ThrowCompletionOr from_value(JS::VM&, JS::Value); +}; + +}