From a0211344570c1a9d7f3096e8d227e590fdd42d8a Mon Sep 17 00:00:00 2001 From: Kenneth Myhra Date: Wed, 3 Sep 2025 18:13:57 +0200 Subject: [PATCH] LibWeb/FileAPI: Make sure to always run the constructor steps for Blob Previously we did not execute the constructor steps if we constructed a Blob from a ByteBuffer and a String. Though we only construct a Blob from ByteBuffer and String internally we still need to run these steps. By creating the new type 'BlobPartsOrByteBuffer' we can consolidate those two approaches to creating a Blob into our already existing constructor steps. --- Libraries/LibWeb/FileAPI/Blob.cpp | 26 ++++++++++++++++++-------- Libraries/LibWeb/FileAPI/Blob.h | 8 +++++--- Libraries/LibWeb/FileAPI/File.cpp | 4 ++-- Libraries/LibWeb/FileAPI/File.h | 4 ++-- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/Libraries/LibWeb/FileAPI/Blob.cpp b/Libraries/LibWeb/FileAPI/Blob.cpp index 93de7567c3a..aa933795bf4 100644 --- a/Libraries/LibWeb/FileAPI/Blob.cpp +++ b/Libraries/LibWeb/FileAPI/Blob.cpp @@ -30,7 +30,11 @@ GC_DEFINE_ALLOCATOR(Blob); GC::Ref Blob::create(JS::Realm& realm, ByteBuffer byte_buffer, String type) { - return realm.create(realm, move(byte_buffer), move(type)); + BlobPropertyBag options = { + .type = move(type), + .endings = Bindings::EndingType::Transparent + }; + return create(realm, move(byte_buffer), move(options)); } // https://w3c.github.io/FileAPI/#convert-line-endings-to-native @@ -81,7 +85,7 @@ ErrorOr convert_line_endings_to_native(StringView string) } // https://w3c.github.io/FileAPI/#process-blob-parts -ErrorOr process_blob_parts(Vector const& blob_parts, Optional const& options) +ErrorOr process_blob_parts(BlobParts const& blob_parts, Optional const& options) { // 1. Let bytes be an empty sequence of bytes. ByteBuffer bytes {}; @@ -182,16 +186,22 @@ WebIDL::ExceptionOr Blob::deserialization_steps(HTML::TransferDataDecoder& } // https://w3c.github.io/FileAPI/#ref-for-dom-blob-blob -GC::Ref Blob::create(JS::Realm& realm, Optional> const& blob_parts, Optional const& options) +GC::Ref Blob::create(JS::Realm& realm, Optional const& blob_parts_or_byte_buffer, Optional const& options) { // 1. If invoked with zero parameters, return a new Blob object consisting of 0 bytes, with size set to 0, and with type set to the empty string. - if (!blob_parts.has_value() && !options.has_value()) + if (!blob_parts_or_byte_buffer.has_value() && !options.has_value()) return realm.create(realm); ByteBuffer byte_buffer {}; // 2. Let bytes be the result of processing blob parts given blobParts and options. - if (blob_parts.has_value()) { - byte_buffer = MUST(process_blob_parts(blob_parts.value(), options)); + if (blob_parts_or_byte_buffer.has_value()) { + byte_buffer = blob_parts_or_byte_buffer->visit( + [&](BlobParts const& blob_parts) { + return MUST(process_blob_parts(blob_parts, options)); + }, + [](ByteBuffer const& byte_buffer) { + return byte_buffer; + }); } auto type = String {}; @@ -214,9 +224,9 @@ GC::Ref Blob::create(JS::Realm& realm, Optional> const& b return realm.create(realm, move(byte_buffer), move(type)); } -WebIDL::ExceptionOr> Blob::construct_impl(JS::Realm& realm, Optional> const& blob_parts, Optional const& options) +WebIDL::ExceptionOr> Blob::construct_impl(JS::Realm& realm, Optional const& blob_parts, Optional const& options) { - return Blob::create(realm, blob_parts, options); + return create(realm, blob_parts.has_value() ? blob_parts.value() : Optional {}, options); } // https://w3c.github.io/FileAPI/#dfn-slice diff --git a/Libraries/LibWeb/FileAPI/Blob.h b/Libraries/LibWeb/FileAPI/Blob.h index cbe09f56a35..63617e8426f 100644 --- a/Libraries/LibWeb/FileAPI/Blob.h +++ b/Libraries/LibWeb/FileAPI/Blob.h @@ -18,6 +18,8 @@ namespace Web::FileAPI { using BlobPart = Variant, GC::Root, String>; +using BlobParts = Vector; +using BlobPartsOrByteBuffer = Variant; struct BlobPropertyBag { String type = String {}; @@ -25,7 +27,7 @@ struct BlobPropertyBag { }; [[nodiscard]] ErrorOr convert_line_endings_to_native(StringView string); -[[nodiscard]] ErrorOr process_blob_parts(Vector const& blob_parts, Optional const& options = {}); +[[nodiscard]] ErrorOr process_blob_parts(BlobParts const& blob_parts, Optional const& options = {}); [[nodiscard]] bool is_basic_latin(StringView view); class WEB_API Blob @@ -38,8 +40,8 @@ public: virtual ~Blob() override; [[nodiscard]] static GC::Ref create(JS::Realm&, ByteBuffer, String type); - [[nodiscard]] static GC::Ref create(JS::Realm&, Optional> const& blob_parts = {}, Optional const& options = {}); - static WebIDL::ExceptionOr> construct_impl(JS::Realm&, Optional> const& blob_parts = {}, Optional const& options = {}); + [[nodiscard]] static GC::Ref create(JS::Realm&, Optional const& blob_parts_or_byte_buffer = {}, Optional const& options = {}); + static WebIDL::ExceptionOr> construct_impl(JS::Realm&, Optional const& blob_parts = {}, Optional const& options = {}); // https://w3c.github.io/FileAPI/#dfn-size u64 size() const { return m_byte_buffer.size(); } diff --git a/Libraries/LibWeb/FileAPI/File.cpp b/Libraries/LibWeb/FileAPI/File.cpp index 46d065bb6a3..9f08c5fa2f2 100644 --- a/Libraries/LibWeb/FileAPI/File.cpp +++ b/Libraries/LibWeb/FileAPI/File.cpp @@ -43,7 +43,7 @@ GC::Ref File::create(JS::Realm& realm) } // https://w3c.github.io/FileAPI/#ref-for-dom-file-file -WebIDL::ExceptionOr> File::create(JS::Realm& realm, Vector const& file_bits, String const& file_name, Optional const& options) +WebIDL::ExceptionOr> File::create(JS::Realm& realm, BlobParts const& file_bits, String const& file_name, Optional const& options) { auto& vm = realm.vm(); @@ -83,7 +83,7 @@ WebIDL::ExceptionOr> File::create(JS::Realm& realm, Vector(realm, move(bytes), move(name), move(type), last_modified); } -WebIDL::ExceptionOr> File::construct_impl(JS::Realm& realm, Vector const& file_bits, String const& file_name, Optional const& options) +WebIDL::ExceptionOr> File::construct_impl(JS::Realm& realm, BlobParts const& file_bits, String const& file_name, Optional const& options) { return create(realm, file_bits, file_name, options); } diff --git a/Libraries/LibWeb/FileAPI/File.h b/Libraries/LibWeb/FileAPI/File.h index d778dd68488..ddfddea23aa 100644 --- a/Libraries/LibWeb/FileAPI/File.h +++ b/Libraries/LibWeb/FileAPI/File.h @@ -20,8 +20,8 @@ class File : public Blob { public: static GC::Ref create(JS::Realm& realm); - static WebIDL::ExceptionOr> create(JS::Realm&, Vector const& file_bits, String const& file_name, Optional const& options = {}); - static WebIDL::ExceptionOr> construct_impl(JS::Realm&, Vector const& file_bits, String const& file_name, Optional const& options = {}); + static WebIDL::ExceptionOr> create(JS::Realm&, BlobParts const& file_bits, String const& file_name, Optional const& options = {}); + static WebIDL::ExceptionOr> construct_impl(JS::Realm&, BlobParts const& file_bits, String const& file_name, Optional const& options = {}); virtual ~File() override;