mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-26 01:35:08 +02:00
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.
107 lines
3.8 KiB
C++
107 lines
3.8 KiB
C++
/*
|
||
* 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, blob’s type, and encoding.
|
||
auto result = TRY(FileReader::blob_package_data(realm(), array_buffer->buffer(), type, blob.type(), encoding));
|
||
return result.get<Result>();
|
||
}
|
||
|
||
// 6. Throw promise’s rejection reason.
|
||
VERIFY(promise->state() == JS::Promise::State::Rejected);
|
||
return JS::throw_completion(result);
|
||
}
|
||
|
||
}
|