Files
ladybird/Libraries/LibWeb/FileAPI/FileReaderSync.cpp
Shannon Booth fd44da6829 LibWeb/Bindings: Emit one bindings header and cpp per IDL
Previously, the LibWeb bindings generator would output multiple per
interface files like Prototype/Constructor/Namespace/GlobalMixin
depending on the contents of that IDL file.

This complicates the build system as it means that it does not know
what files will be generated without knowledge of the contents of that
IDL file.

Instead, for each IDL file only generate a single Bindings/<IDLFile>.h
and Bindings/<IDLFile>.cpp.
2026-04-21 07:36:13 +02:00

107 lines
3.8 KiB
C++
Raw Permalink 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) 2025, Tim Ledbetter <tim.ledbetter@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/ArrayBuffer.h>
#include <LibJS/Runtime/Realm.h>
#include <LibJS/Runtime/TypedArray.h>
#include <LibWeb/Bindings/FileReaderSync.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/FileAPI/Blob.h>
#include <LibWeb/FileAPI/FileReaderSync.h>
#include <LibWeb/HTML/EventLoop/EventLoop.h>
#include <LibWeb/Streams/ReadableStream.h>
#include <LibWeb/Streams/ReadableStreamDefaultReader.h>
#include <LibWeb/WebIDL/ExceptionOr.h>
namespace Web::FileAPI {
GC_DEFINE_ALLOCATOR(FileReaderSync);
FileReaderSync::~FileReaderSync() = default;
FileReaderSync::FileReaderSync(JS::Realm& realm)
: PlatformObject(realm)
{
}
void FileReaderSync::initialize(JS::Realm& realm)
{
WEB_SET_PROTOTYPE_FOR_INTERFACE(FileReaderSync);
Base::initialize(realm);
}
GC::Ref<FileReaderSync> FileReaderSync::create(JS::Realm& realm)
{
return realm.create<FileReaderSync>(realm);
}
GC::Ref<FileReaderSync> FileReaderSync::construct_impl(JS::Realm& realm)
{
return FileReaderSync::create(realm);
}
// https://w3c.github.io/FileAPI/#dfn-readAsArrayBufferSync
WebIDL::ExceptionOr<GC::Ref<JS::ArrayBuffer>> FileReaderSync::read_as_array_buffer(Blob& blob)
{
return read_as<GC::Ref<JS::ArrayBuffer>>(blob, FileReader::Type::ArrayBuffer);
}
// https://w3c.github.io/FileAPI/#dfn-readAsBinaryStringSync
WebIDL::ExceptionOr<String> FileReaderSync::read_as_binary_string(Blob& blob)
{
return read_as<String>(blob, FileReader::Type::BinaryString);
}
// https://w3c.github.io/FileAPI/#dfn-readAsTextSync
WebIDL::ExceptionOr<String> FileReaderSync::read_as_text(Blob& blob, Optional<String> const& encoding)
{
return read_as<String>(blob, FileReader::Type::Text, encoding);
}
// https://w3c.github.io/FileAPI/#dfn-readAsDataURLSync
WebIDL::ExceptionOr<String> FileReaderSync::read_as_data_url(Blob& blob)
{
return read_as<String>(blob, FileReader::Type::DataURL);
}
template<typename Result>
WebIDL::ExceptionOr<Result> FileReaderSync::read_as(Blob& blob, FileReader::Type type, Optional<String> const& encoding)
{
// 1. Let stream be the result of calling get stream on blob.
auto stream = blob.get_stream();
// 2. Let reader be the result of getting a reader from stream.
auto reader = TRY(stream->get_a_reader());
// 3. Let promise be the result of reading all bytes from stream with reader.
auto promise_capability = reader->read_all_bytes_deprecated();
// FIXME: Try harder to not reach into promise's [[Promise]] slot
auto promise = GC::Ref { as<JS::Promise>(*promise_capability->promise()) };
// 4. Wait for promise to be fulfilled or rejected.
// FIXME: Create spec issue to use WebIDL react to promise steps here instead of this custom logic
HTML::main_thread_event_loop().spin_until(GC::create_function(heap(), [promise]() {
return promise->state() == JS::Promise::State::Fulfilled || promise->state() == JS::Promise::State::Rejected;
}));
// 5. If promise fulfilled with a byte sequence bytes:
auto result = promise->result();
auto* array_buffer = result.extract_pointer<JS::ArrayBuffer>();
if (promise->state() == JS::Promise::State::Fulfilled && array_buffer) {
// AD-HOC: This diverges from the spec as wrritten, where the type argument is specified explicitly for each caller.
// 1. Return the result of package data given bytes, type, blobs type, and encoding.
auto result = TRY(FileReader::blob_package_data(realm(), array_buffer->buffer(), type, blob.type(), encoding));
return result.get<Result>();
}
// 6. Throw promises rejection reason.
VERIFY(promise->state() == JS::Promise::State::Rejected);
return JS::throw_completion(result);
}
}