LibWeb/FileAPI: Update Blob.slice for spec changes

This commit is contained in:
Jamie Mansfield 2024-08-23 00:36:22 +01:00 committed by Tim Ledbetter
parent 181ece4d9c
commit 9650a5ff33
Notes: github-actions[bot] 2024-08-23 11:09:18 +00:00
2 changed files with 47 additions and 26 deletions

View file

@ -221,66 +221,85 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Blob>> Blob::construct_impl(JS::Realm& real
// https://w3c.github.io/FileAPI/#dfn-slice
WebIDL::ExceptionOr<JS::NonnullGCPtr<Blob>> Blob::slice(Optional<i64> start, Optional<i64> end, Optional<String> 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<JS::NonnullGCPtr<Blob>> Blob::slice_blob(Optional<i64> start, Optional<i64> end, Optional<String> 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 blobs 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<i64>(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<i64>(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 blobs 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));

View file

@ -67,6 +67,8 @@ protected:
virtual void initialize(JS::Realm&) override;
WebIDL::ExceptionOr<JS::NonnullGCPtr<Blob>> slice_blob(Optional<i64> start = {}, Optional<i64> end = {}, Optional<String> const& content_type = {});
ByteBuffer m_byte_buffer {};
String m_type {};