ladybird/Libraries/LibWeb/Streams/AbstractOperations.h
Timothy Flynn 26c01f0957 LibWeb: Move WritableStream AOs into their own file
The main streams AO file has gotten very large, and is a bit difficult
to navigate. In an effort to improve DX, this migrates WritableStream
AOs to their own file.
2025-04-18 06:55:40 -04:00

133 lines
6.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2023, Matthew Olsson <mattco@serenityos.org>
* Copyright (c) 2023-2025, Shannon Booth <shannon@serenityos.org>
* Copyright (c) 2023-2024, Kenneth Myhra <kennethmyhra@serenityos.org>
* Copyright (c) 2025, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibGC/Ptr.h>
#include <LibWeb/Forward.h>
#include <LibWeb/Streams/Algorithms.h>
#include <LibWeb/WebIDL/CallbackType.h>
#include <LibWeb/WebIDL/ExceptionOr.h>
namespace Web::Streams {
GC::Ref<SizeAlgorithm> extract_size_algorithm(JS::VM&, QueuingStrategy const&);
WebIDL::ExceptionOr<double> extract_high_water_mark(QueuingStrategy const&, double default_hwm);
WebIDL::ExceptionOr<GC::Ref<JS::ArrayBuffer>> transfer_array_buffer(JS::Realm& realm, JS::ArrayBuffer& buffer);
void initialize_transform_stream(TransformStream&, GC::Ref<WebIDL::Promise> start_promise, double writable_high_water_mark, GC::Ref<SizeAlgorithm> writable_size_algorithm, double readable_high_water_mark, GC::Ref<SizeAlgorithm> readable_size_algorithm);
void set_up_transform_stream_default_controller(TransformStream&, TransformStreamDefaultController&, GC::Ref<TransformAlgorithm>, GC::Ref<FlushAlgorithm>, GC::Ref<CancelAlgorithm>);
void set_up_transform_stream_default_controller_from_transformer(TransformStream&, JS::Value transformer, Transformer&);
void transform_stream_default_controller_clear_algorithms(TransformStreamDefaultController&);
WebIDL::ExceptionOr<void> transform_stream_default_controller_enqueue(TransformStreamDefaultController&, JS::Value chunk);
void transform_stream_default_controller_error(TransformStreamDefaultController&, JS::Value error);
void transform_stream_default_controller_terminate(TransformStreamDefaultController&);
GC::Ref<WebIDL::Promise> transform_stream_default_controller_perform_transform(TransformStreamDefaultController&, JS::Value chunk);
GC::Ref<WebIDL::Promise> transform_stream_default_sink_abort_algorithm(TransformStream&, JS::Value reason);
GC::Ref<WebIDL::Promise> transform_stream_default_sink_close_algorithm(TransformStream&);
GC::Ref<WebIDL::Promise> transform_stream_default_sink_write_algorithm(TransformStream&, JS::Value chunk);
GC::Ref<WebIDL::Promise> transform_stream_default_source_pull_algorithm(TransformStream&);
GC::Ref<WebIDL::Promise> transform_stream_default_source_cancel_algorithm(TransformStream&, JS::Value reason);
void transform_stream_error(TransformStream&, JS::Value error);
void transform_stream_error_writable_and_unblock_write(TransformStream&, JS::Value error);
void transform_stream_set_backpressure(TransformStream&, bool backpressure);
void transform_stream_unblock_write(TransformStream&);
bool is_non_negative_number(JS::Value);
bool can_copy_data_block_bytes_buffer(JS::ArrayBuffer const& to_buffer, u64 to_index, JS::ArrayBuffer const& from_buffer, u64 from_index, u64 count);
bool can_transfer_array_buffer(JS::ArrayBuffer const& array_buffer);
WebIDL::ExceptionOr<JS::Value> clone_as_uint8_array(JS::Realm&, WebIDL::ArrayBufferView&);
WebIDL::ExceptionOr<JS::Value> structured_clone(JS::Realm&, JS::Value value);
// https://streams.spec.whatwg.org/#value-with-size
struct ValueWithSize {
JS::Value value;
double size;
};
// https://streams.spec.whatwg.org/#dequeue-value
template<typename T>
JS::Value dequeue_value(T& container)
{
// 1. Assert: container has [[queue]] and [[queueTotalSize]] internal slots.
// 2. Assert: container.[[queue]] is not empty.
VERIFY(!container.queue().is_empty());
// 3. Let valueWithSize be container.[[queue]][0].
// 4. Remove valueWithSize from container.[[queue]].
auto value_with_size = container.queue().take_first();
// 5. Set container.[[queueTotalSize]] to container.[[queueTotalSize]] valueWithSizes size.
container.set_queue_total_size(container.queue_total_size() - value_with_size.size);
// 6. If container.[[queueTotalSize]] < 0, set container.[[queueTotalSize]] to 0. (This can occur due to rounding errors.)
if (container.queue_total_size() < 0.0)
container.set_queue_total_size(0.0);
// 7. Return valueWithSizes value.
return value_with_size.value;
}
// https://streams.spec.whatwg.org/#enqueue-value-with-size
template<typename T>
WebIDL::ExceptionOr<void> enqueue_value_with_size(T& container, JS::Value value, JS::Value size)
{
// 1. Assert: container has [[queue]] and [[queueTotalSize]] internal slots.
// 2. If ! IsNonNegativeNumber(size) is false, throw a RangeError exception.
if (!is_non_negative_number(size))
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::RangeError, "Chunk has non-positive size"sv };
// 3. If size is +∞, throw a RangeError exception.
if (size.is_positive_infinity())
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::RangeError, "Chunk has infinite size"sv };
// 4. Append a new value-with-size with value value and size size to container.[[queue]].
container.queue().append({ value, size.as_double() });
// 5. Set container.[[queueTotalSize]] to container.[[queueTotalSize]] + size.
container.set_queue_total_size(container.queue_total_size() + size.as_double());
return {};
}
// https://streams.spec.whatwg.org/#peek-queue-value
template<typename T>
JS::Value peek_queue_value(T& container)
{
// 1. Assert: container has [[queue]] and [[queueTotalSize]] internal slots.
// 2. Assert: container.[[queue]] is not empty.
VERIFY(!container.queue().is_empty());
// 3. Let valueWithSize be container.[[queue]][0].
auto& value_with_size = container.queue().first();
// 4. Return valueWithSizes value.
return value_with_size.value;
}
// https://streams.spec.whatwg.org/#reset-queue
template<typename T>
void reset_queue(T& container)
{
// 1. Assert: container has [[queue]] and [[queueTotalSize]] internal slots.
// 2. Set container.[[queue]] to a new empty list.
container.queue().clear();
// 3. Set container.[[queueTotalSize]] to 0.
container.set_queue_total_size(0);
}
}