mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-29 12:19:54 +00:00
LibWeb: Implement FileReaderSync
interface
This interface allows the user to read File or Blob objects synchronously from inside workers.
This commit is contained in:
parent
3f71907255
commit
bbcd8bd97c
Notes:
github-actions[bot]
2025-02-28 04:50:48 +00:00
Author: https://github.com/tcl3
Commit: bbcd8bd97c
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3667
Reviewed-by: https://github.com/shannonbooth
6 changed files with 170 additions and 9 deletions
|
@ -284,6 +284,7 @@ set(SOURCES
|
||||||
FileAPI/File.cpp
|
FileAPI/File.cpp
|
||||||
FileAPI/FileList.cpp
|
FileAPI/FileList.cpp
|
||||||
FileAPI/FileReader.cpp
|
FileAPI/FileReader.cpp
|
||||||
|
FileAPI/FileReaderSync.cpp
|
||||||
Geometry/DOMMatrix.cpp
|
Geometry/DOMMatrix.cpp
|
||||||
Geometry/DOMMatrixReadOnly.cpp
|
Geometry/DOMMatrixReadOnly.cpp
|
||||||
Geometry/DOMPoint.cpp
|
Geometry/DOMPoint.cpp
|
||||||
|
|
|
@ -81,6 +81,14 @@ public:
|
||||||
void set_onloadend(WebIDL::CallbackType*);
|
void set_onloadend(WebIDL::CallbackType*);
|
||||||
WebIDL::CallbackType* onloadend();
|
WebIDL::CallbackType* onloadend();
|
||||||
|
|
||||||
|
enum class Type {
|
||||||
|
ArrayBuffer,
|
||||||
|
BinaryString,
|
||||||
|
Text,
|
||||||
|
DataURL,
|
||||||
|
};
|
||||||
|
static WebIDL::ExceptionOr<Result> blob_package_data(JS::Realm& realm, ByteBuffer, FileReader::Type type, Optional<String> const&, Optional<String> const& encoding_name = {});
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
FileReader(JS::Realm&, ByteBuffer);
|
FileReader(JS::Realm&, ByteBuffer);
|
||||||
|
|
||||||
|
@ -91,17 +99,8 @@ protected:
|
||||||
private:
|
private:
|
||||||
explicit FileReader(JS::Realm&);
|
explicit FileReader(JS::Realm&);
|
||||||
|
|
||||||
enum class Type {
|
|
||||||
ArrayBuffer,
|
|
||||||
BinaryString,
|
|
||||||
Text,
|
|
||||||
DataURL,
|
|
||||||
};
|
|
||||||
|
|
||||||
WebIDL::ExceptionOr<void> read_operation(Blob&, Type, Optional<String> const& encoding_name = {});
|
WebIDL::ExceptionOr<void> read_operation(Blob&, Type, Optional<String> const& encoding_name = {});
|
||||||
|
|
||||||
static WebIDL::ExceptionOr<Result> blob_package_data(JS::Realm& realm, ByteBuffer, FileReader::Type type, Optional<String> const&, Optional<String> const& encoding_name);
|
|
||||||
|
|
||||||
void queue_a_task(GC::Ref<GC::Function<void()>>);
|
void queue_a_task(GC::Ref<GC::Function<void()>>);
|
||||||
|
|
||||||
// Internal state to handle aborting the FileReader.
|
// Internal state to handle aborting the FileReader.
|
||||||
|
|
106
Libraries/LibWeb/FileAPI/FileReaderSync.cpp
Normal file
106
Libraries/LibWeb/FileAPI/FileReaderSync.cpp
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* 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/FileReaderSyncPrototype.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/AbstractOperations.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)
|
||||||
|
{
|
||||||
|
Base::initialize(realm);
|
||||||
|
WEB_SET_PROTOTYPE_FOR_INTERFACE(FileReaderSync);
|
||||||
|
}
|
||||||
|
|
||||||
|
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::Root<JS::ArrayBuffer>> FileReaderSync::read_as_array_buffer(Blob& blob)
|
||||||
|
{
|
||||||
|
return read_as<GC::Root<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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
41
Libraries/LibWeb/FileAPI/FileReaderSync.h
Normal file
41
Libraries/LibWeb/FileAPI/FileReaderSync.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025, Tim Ledbetter <tim.ledbetter@ladybird.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibJS/Forward.h>
|
||||||
|
#include <LibWeb/Bindings/PlatformObject.h>
|
||||||
|
#include <LibWeb/FileAPI/FileReader.h>
|
||||||
|
#include <LibWeb/Forward.h>
|
||||||
|
|
||||||
|
namespace Web::FileAPI {
|
||||||
|
|
||||||
|
// https://w3c.github.io/FileAPI/#FileReaderSync
|
||||||
|
class FileReaderSync : public Bindings::PlatformObject {
|
||||||
|
WEB_PLATFORM_OBJECT(FileReaderSync, Bindings::PlatformObject);
|
||||||
|
GC_DECLARE_ALLOCATOR(FileReaderSync);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~FileReaderSync() override;
|
||||||
|
|
||||||
|
[[nodiscard]] static GC::Ref<FileReaderSync> create(JS::Realm&);
|
||||||
|
static GC::Ref<FileReaderSync> construct_impl(JS::Realm&);
|
||||||
|
|
||||||
|
WebIDL::ExceptionOr<GC::Root<JS::ArrayBuffer>> read_as_array_buffer(Blob&);
|
||||||
|
WebIDL::ExceptionOr<String> read_as_binary_string(Blob&);
|
||||||
|
WebIDL::ExceptionOr<String> read_as_text(Blob&, Optional<String> const& encoding = {});
|
||||||
|
WebIDL::ExceptionOr<String> read_as_data_url(Blob&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit FileReaderSync(JS::Realm&);
|
||||||
|
|
||||||
|
template<typename Result>
|
||||||
|
WebIDL::ExceptionOr<Result> read_as(Blob&, FileReader::Type, Optional<String> const& encoding = {});
|
||||||
|
|
||||||
|
virtual void initialize(JS::Realm&) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
13
Libraries/LibWeb/FileAPI/FileReaderSync.idl
Normal file
13
Libraries/LibWeb/FileAPI/FileReaderSync.idl
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#import <FileAPI/Blob.idl>
|
||||||
|
|
||||||
|
// https://w3c.github.io/FileAPI/#FileReaderSync
|
||||||
|
[Exposed=(DedicatedWorker,SharedWorker)]
|
||||||
|
interface FileReaderSync {
|
||||||
|
constructor();
|
||||||
|
// Synchronously return strings
|
||||||
|
|
||||||
|
ArrayBuffer readAsArrayBuffer(Blob blob);
|
||||||
|
DOMString readAsText(Blob blob, optional DOMString encoding);
|
||||||
|
DOMString readAsBinaryString(Blob blob);
|
||||||
|
DOMString readAsDataURL(Blob blob);
|
||||||
|
};
|
|
@ -98,6 +98,7 @@ libweb_js_bindings(FileAPI/Blob)
|
||||||
libweb_js_bindings(FileAPI/File)
|
libweb_js_bindings(FileAPI/File)
|
||||||
libweb_js_bindings(FileAPI/FileList)
|
libweb_js_bindings(FileAPI/FileList)
|
||||||
libweb_js_bindings(FileAPI/FileReader)
|
libweb_js_bindings(FileAPI/FileReader)
|
||||||
|
libweb_js_bindings(FileAPI/FileReaderSync)
|
||||||
libweb_js_bindings(Geometry/DOMMatrix)
|
libweb_js_bindings(Geometry/DOMMatrix)
|
||||||
libweb_js_bindings(Geometry/DOMMatrixReadOnly)
|
libweb_js_bindings(Geometry/DOMMatrixReadOnly)
|
||||||
libweb_js_bindings(Geometry/DOMPoint)
|
libweb_js_bindings(Geometry/DOMPoint)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue