From 9650a5ff33aae04ba3663a1bcf74c8b7edd331b5 Mon Sep 17 00:00:00 2001 From: Jamie Mansfield Date: Fri, 23 Aug 2024 00:36:22 +0100 Subject: [PATCH] LibWeb/FileAPI: Update Blob.slice for spec changes --- Userland/Libraries/LibWeb/FileAPI/Blob.cpp | 71 ++++++++++++++-------- Userland/Libraries/LibWeb/FileAPI/Blob.h | 2 + 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/Userland/Libraries/LibWeb/FileAPI/Blob.cpp b/Userland/Libraries/LibWeb/FileAPI/Blob.cpp index 8597b7f8418..92439c2ba98 100644 --- a/Userland/Libraries/LibWeb/FileAPI/Blob.cpp +++ b/Userland/Libraries/LibWeb/FileAPI/Blob.cpp @@ -221,66 +221,85 @@ WebIDL::ExceptionOr> Blob::construct_impl(JS::Realm& real // https://w3c.github.io/FileAPI/#dfn-slice WebIDL::ExceptionOr> Blob::slice(Optional start, Optional end, Optional const& content_type) +{ + // 1. Let sliceStart, sliceEnd, and sliceContentType be null. + // 2. If start is given, set sliceStart to start. + // 3. If end is given, set sliceEnd to end. + // 3. If contentType is given, set sliceContentType to contentType. + // 4. Return the result of slice blob given this, sliceStart, sliceEnd, and sliceContentType. + return slice_blob(start, end, content_type); +} + +// https://w3c.github.io/FileAPI/#slice-blob +WebIDL::ExceptionOr> Blob::slice_blob(Optional start, Optional end, Optional const& content_type) { auto& vm = realm().vm(); - // 1. The optional start parameter is a value for the start point of a slice() call, and must be treated as a byte-order position, with the zeroth position representing the first byte. - // User agents must process slice() with start normalized according to the following: + // 1. Let originalSize be blob’s size. + auto original_size = size(); + + // 2. The start parameter, if non-null, is a value for the start point of a slice blob call, and must be treated as a byte-order position, + // with the zeroth position representing the first byte. User agents must normalize start according to the following: i64 relative_start; if (!start.has_value()) { - // a. If the optional start parameter is not used as a parameter when making this call, let relativeStart be 0. + // a. If start is null, let relativeStart be 0. relative_start = 0; } else { auto start_value = start.value(); - // b. If start is negative, let relativeStart be max((size + start), 0). + + // b. If start is negative, let relativeStart be max((originalSize + start), 0). if (start_value < 0) { - relative_start = max((size() + start_value), 0); + relative_start = max((static_cast(original_size) + start_value), 0); } - // c. Else, let relativeStart be min(start, size). + // c. Otherwise, let relativeStart be min(start, originalSize). else { - relative_start = min(start_value, size()); + relative_start = min(start_value, original_size); } } - // 2. The optional end parameter is a value for the end point of a slice() call. User agents must process slice() with end normalized according to the following: + // 3. The end parameter, if non-null. is a value for the end point of a slice blob call. User agents must normalize end according to the following: i64 relative_end; if (!end.has_value()) { - // a. If the optional end parameter is not used as a parameter when making this call, let relativeEnd be size. - relative_end = size(); + // a. If end is null, let relativeEnd be originalSize. + relative_end = original_size; } else { auto end_value = end.value(); - // b. If end is negative, let relativeEnd be max((size + end), 0). + + // b. If end is negative, let relativeEnd be max((originalSize + end), 0). if (end_value < 0) { - relative_end = max((size() + end_value), 0); + relative_end = max((static_cast(original_size) + end_value), 0); } - // c Else, let relativeEnd be min(end, size). + // c. Otherwise, let relativeEnd be min(end, originalSize). else { - relative_end = min(end_value, size()); + relative_end = min(end_value, original_size); } } - // 3. The optional contentType parameter is used to set the ASCII-encoded string in lower case representing the media type of the Blob. - // User agents must process the slice() with contentType normalized according to the following: + // 4. The contentType parameter, if non-null, is used to set the ASCII-encoded string in lower case representing the media type of the Blob. + // User agents must normalize contentType according to the following: String relative_content_type; if (!content_type.has_value()) { - // a. If the contentType parameter is not provided, let relativeContentType be set to the empty string. - relative_content_type = String {}; + // a. If contentType is null, let relativeContentType be set to the empty string. + relative_content_type = {}; } else { - // b. Else let relativeContentType be set to contentType and run the substeps below: + // b. Otherwise, let relativeContentType be set to contentType and run the substeps below: - // 1. If relativeContentType contains any characters outside the range of U+0020 to U+007E, then set relativeContentType to the empty string and return from these substeps. - // NOTE: contentType is set to empty string at declaration. - if (is_basic_latin(content_type.value())) { - // 2. Convert every character in relativeContentType to ASCII lowercase. + // 1. If relativeContentType contains any characters outside the range of U+0020 to U+007E, then set relativeContentType to the empty string + // and return from these substeps: + if (!is_basic_latin(content_type.value())) { + relative_content_type = {}; + } + // 2. Convert every character in relativeContentType to ASCII lowercase. + else { relative_content_type = TRY_OR_THROW_OOM(vm, Infra::to_ascii_lowercase(content_type.value())); } } - // 4. Let span be max((relativeEnd - relativeStart), 0). + // 5. Let span be max((relativeEnd - relativeStart), 0). auto span = max((relative_end - relative_start), 0); - // 5. Return a new Blob object S with the following characteristics: - // a. S refers to span consecutive bytes from this, beginning with the byte at byte-order position relativeStart. + // 6. Return a new Blob object S with the following characteristics: + // a. S refers to span consecutive bytes from blob’s associated byte sequence, beginning with the byte at byte-order position relativeStart. // b. S.size = span. // c. S.type = relativeContentType. auto byte_buffer = TRY_OR_THROW_OOM(vm, m_byte_buffer.slice(relative_start, span)); diff --git a/Userland/Libraries/LibWeb/FileAPI/Blob.h b/Userland/Libraries/LibWeb/FileAPI/Blob.h index 4974eb16040..7746ea185c9 100644 --- a/Userland/Libraries/LibWeb/FileAPI/Blob.h +++ b/Userland/Libraries/LibWeb/FileAPI/Blob.h @@ -67,6 +67,8 @@ protected: virtual void initialize(JS::Realm&) override; + WebIDL::ExceptionOr> slice_blob(Optional start = {}, Optional end = {}, Optional const& content_type = {}); + ByteBuffer m_byte_buffer {}; String m_type {};