diff --git a/Libraries/LibWeb/Compression/CompressionStream.cpp b/Libraries/LibWeb/Compression/CompressionStream.cpp index a18224c36c6..c6d12fb809e 100644 --- a/Libraries/LibWeb/Compression/CompressionStream.cpp +++ b/Libraries/LibWeb/Compression/CompressionStream.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2024, Tim Flynn + * Copyright (c) 2025, Altomani Gianluca * * SPDX-License-Identifier: BSD-2-Clause */ @@ -113,21 +114,22 @@ WebIDL::ExceptionOr CompressionStream::compress_and_enqueue_chunk(JS::Valu return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Chunk is not a BufferSource type"sv }; // 2. Let buffer be the result of compressing chunk with cs's format and context. - auto buffer = [&]() -> ErrorOr { + auto maybe_buffer = [&]() -> ErrorOr { if (auto buffer = WebIDL::underlying_buffer_source(chunk.as_object())) return compress(buffer->buffer(), Finish::No); return ByteBuffer {}; }(); + if (maybe_buffer.is_error()) + return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("Unable to compress chunk: {}", maybe_buffer.error())) }; - if (buffer.is_error()) - return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("Unable to compress chunk: {}", buffer.error())) }; + auto buffer = maybe_buffer.release_value(); // 3. If buffer is empty, return. - if (buffer.value().is_empty()) + if (buffer.is_empty()) return {}; // 4. Split buffer into one or more non-empty pieces and convert them into Uint8Arrays. - auto array_buffer = JS::ArrayBuffer::create(realm, buffer.release_value()); + auto array_buffer = JS::ArrayBuffer::create(realm, move(buffer)); auto array = JS::Uint8Array::create(realm, array_buffer->byte_length(), *array_buffer); // 5. For each Uint8Array array, enqueue array in cs's transform. @@ -141,17 +143,18 @@ WebIDL::ExceptionOr CompressionStream::compress_flush_and_enqueue() auto& realm = this->realm(); // 1. Let buffer be the result of compressing an empty input with cs's format and context, with the finish flag. - auto buffer = compress({}, Finish::Yes); + auto maybe_buffer = compress({}, Finish::Yes); + if (maybe_buffer.is_error()) + return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("Unable to compress flush: {}", maybe_buffer.error())) }; - if (buffer.is_error()) - return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("Unable to compress flush: {}", buffer.error())) }; + auto buffer = maybe_buffer.release_value(); // 2. If buffer is empty, return. - if (buffer.value().is_empty()) + if (buffer.is_empty()) return {}; // 3. Split buffer into one or more non-empty pieces and convert them into Uint8Arrays. - auto array_buffer = JS::ArrayBuffer::create(realm, buffer.release_value()); + auto array_buffer = JS::ArrayBuffer::create(realm, move(buffer)); auto array = JS::Uint8Array::create(realm, array_buffer->byte_length(), *array_buffer); // 4. For each Uint8Array array, enqueue array in cs's transform. diff --git a/Libraries/LibWeb/Compression/DecompressionStream.cpp b/Libraries/LibWeb/Compression/DecompressionStream.cpp index 8739417afac..bc68d40c761 100644 --- a/Libraries/LibWeb/Compression/DecompressionStream.cpp +++ b/Libraries/LibWeb/Compression/DecompressionStream.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2024, Tim Flynn + * Copyright (c) 2025, Altomani Gianluca * * SPDX-License-Identifier: BSD-2-Clause */ @@ -115,21 +116,30 @@ WebIDL::ExceptionOr DecompressionStream::decompress_and_enqueue_chunk(JS:: // 2. Let buffer be the result of decompressing chunk with ds's format and context. If this results in an error, // then throw a TypeError. - auto buffer = [&]() -> ErrorOr { - if (auto buffer = WebIDL::underlying_buffer_source(chunk.as_object())) - return decompress(buffer->buffer()); - return ByteBuffer {}; - }(); + auto maybe_buffer = [&]() -> ErrorOr { + auto chunk_buffer = WebIDL::underlying_buffer_source(chunk.as_object()); + if (!chunk_buffer) + return ByteBuffer {}; - if (buffer.is_error()) - return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("Unable to decompress chunk: {}", buffer.error())) }; + TRY(m_input_stream->write_until_depleted(chunk_buffer->buffer())); + + auto decompressed = TRY(ByteBuffer::create_uninitialized(4096)); + auto size = TRY(m_decompressor.visit([&](auto const& decompressor) -> ErrorOr { + return TRY(decompressor->read_some(decompressed.bytes())).size(); + })); + return decompressed.slice(0, size); + }(); + if (maybe_buffer.is_error()) + return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("Unable to decompress chunk: {}", maybe_buffer.error())) }; + + auto buffer = maybe_buffer.release_value(); // 3. If buffer is empty, return. - if (buffer.value().is_empty()) + if (buffer.is_empty()) return {}; // 4. Split buffer into one or more non-empty pieces and convert them into Uint8Arrays. - auto array_buffer = JS::ArrayBuffer::create(realm, buffer.release_value()); + auto array_buffer = JS::ArrayBuffer::create(realm, move(buffer)); auto array = JS::Uint8Array::create(realm, array_buffer->byte_length(), *array_buffer); // 5. For each Uint8Array array, enqueue array in ds's transform. @@ -143,19 +153,24 @@ WebIDL::ExceptionOr DecompressionStream::decompress_flush_and_enqueue() auto& realm = this->realm(); // 1. Let buffer be the result of decompressing an empty input with ds's format and context, with the finish flag. - auto buffer = decompress({}); + auto maybe_buffer = m_decompressor.visit([&](auto const& decompressor) -> ErrorOr { + return TRY(decompressor->read_until_eof()); + }); + if (maybe_buffer.is_error()) + return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("Unable to compress flush: {}", maybe_buffer.error())) }; - if (buffer.is_error()) - return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("Unable to compress flush: {}", buffer.error())) }; + auto buffer = maybe_buffer.release_value(); - // FIXME: 2. If the end of the compressed input has not been reached, then throw a TypeError. + // 2. If the end of the compressed input has not been reached, then throw a TypeError. + if (m_decompressor.visit([](auto const& decompressor) { return !decompressor->is_eof(); })) + return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "End of compressed input has not been reached"sv }; // 3. If buffer is empty, return. - if (buffer.value().is_empty()) + if (buffer.is_empty()) return {}; // 4. Split buffer into one or more non-empty pieces and convert them into Uint8Arrays. - auto array_buffer = JS::ArrayBuffer::create(realm, buffer.release_value()); + auto array_buffer = JS::ArrayBuffer::create(realm, move(buffer)); auto array = JS::Uint8Array::create(realm, array_buffer->byte_length(), *array_buffer); // 5. For each Uint8Array array, enqueue array in ds's transform. @@ -163,13 +178,4 @@ WebIDL::ExceptionOr DecompressionStream::decompress_flush_and_enqueue() return {}; } -ErrorOr DecompressionStream::decompress(ReadonlyBytes bytes) -{ - TRY(m_input_stream->write_until_depleted(bytes)); - - return TRY(m_decompressor.visit([&](auto const& decompressor) { - return decompressor->read_until_eof(); - })); -} - } diff --git a/Libraries/LibWeb/Compression/DecompressionStream.h b/Libraries/LibWeb/Compression/DecompressionStream.h index 88ec91ae723..b02074f0cb5 100644 --- a/Libraries/LibWeb/Compression/DecompressionStream.h +++ b/Libraries/LibWeb/Compression/DecompressionStream.h @@ -44,8 +44,6 @@ private: WebIDL::ExceptionOr decompress_and_enqueue_chunk(JS::Value); WebIDL::ExceptionOr decompress_flush_and_enqueue(); - ErrorOr decompress(ReadonlyBytes); - Decompressor m_decompressor; NonnullOwnPtr m_input_stream; }; diff --git a/Tests/LibWeb/Text/expected/wpt-import/compression/decompression-split-chunk.tentative.any.txt b/Tests/LibWeb/Text/expected/wpt-import/compression/decompression-split-chunk.tentative.any.txt index eb7282ce1e1..a30d1b99ee6 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/compression/decompression-split-chunk.tentative.any.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/compression/decompression-split-chunk.tentative.any.txt @@ -1,50 +1,50 @@ -Harness status: Error +Harness status: OK Found 45 tests -45 Fail -Fail decompressing splitted chunk into pieces of size 1 should work in deflate -Fail decompressing splitted chunk into pieces of size 1 should work in gzip -Fail decompressing splitted chunk into pieces of size 1 should work in deflate-raw -Fail decompressing splitted chunk into pieces of size 2 should work in deflate -Fail decompressing splitted chunk into pieces of size 2 should work in gzip -Fail decompressing splitted chunk into pieces of size 2 should work in deflate-raw -Fail decompressing splitted chunk into pieces of size 3 should work in deflate -Fail decompressing splitted chunk into pieces of size 3 should work in gzip -Fail decompressing splitted chunk into pieces of size 3 should work in deflate-raw -Fail decompressing splitted chunk into pieces of size 4 should work in deflate -Fail decompressing splitted chunk into pieces of size 4 should work in gzip -Fail decompressing splitted chunk into pieces of size 4 should work in deflate-raw -Fail decompressing splitted chunk into pieces of size 5 should work in deflate -Fail decompressing splitted chunk into pieces of size 5 should work in gzip -Fail decompressing splitted chunk into pieces of size 5 should work in deflate-raw -Fail decompressing splitted chunk into pieces of size 6 should work in deflate -Fail decompressing splitted chunk into pieces of size 6 should work in gzip -Fail decompressing splitted chunk into pieces of size 6 should work in deflate-raw -Fail decompressing splitted chunk into pieces of size 7 should work in deflate -Fail decompressing splitted chunk into pieces of size 7 should work in gzip -Fail decompressing splitted chunk into pieces of size 7 should work in deflate-raw -Fail decompressing splitted chunk into pieces of size 8 should work in deflate -Fail decompressing splitted chunk into pieces of size 8 should work in gzip -Fail decompressing splitted chunk into pieces of size 8 should work in deflate-raw -Fail decompressing splitted chunk into pieces of size 9 should work in deflate -Fail decompressing splitted chunk into pieces of size 9 should work in gzip -Fail decompressing splitted chunk into pieces of size 9 should work in deflate-raw -Fail decompressing splitted chunk into pieces of size 10 should work in deflate -Fail decompressing splitted chunk into pieces of size 10 should work in gzip -Fail decompressing splitted chunk into pieces of size 10 should work in deflate-raw -Fail decompressing splitted chunk into pieces of size 11 should work in deflate -Fail decompressing splitted chunk into pieces of size 11 should work in gzip -Fail decompressing splitted chunk into pieces of size 11 should work in deflate-raw -Fail decompressing splitted chunk into pieces of size 12 should work in deflate -Fail decompressing splitted chunk into pieces of size 12 should work in gzip -Fail decompressing splitted chunk into pieces of size 12 should work in deflate-raw -Fail decompressing splitted chunk into pieces of size 13 should work in deflate -Fail decompressing splitted chunk into pieces of size 13 should work in gzip -Fail decompressing splitted chunk into pieces of size 13 should work in deflate-raw -Fail decompressing splitted chunk into pieces of size 14 should work in deflate -Fail decompressing splitted chunk into pieces of size 14 should work in gzip -Fail decompressing splitted chunk into pieces of size 14 should work in deflate-raw -Fail decompressing splitted chunk into pieces of size 15 should work in deflate -Fail decompressing splitted chunk into pieces of size 15 should work in gzip -Fail decompressing splitted chunk into pieces of size 15 should work in deflate-raw \ No newline at end of file +45 Pass +Pass decompressing splitted chunk into pieces of size 1 should work in deflate +Pass decompressing splitted chunk into pieces of size 1 should work in gzip +Pass decompressing splitted chunk into pieces of size 1 should work in deflate-raw +Pass decompressing splitted chunk into pieces of size 2 should work in deflate +Pass decompressing splitted chunk into pieces of size 2 should work in gzip +Pass decompressing splitted chunk into pieces of size 2 should work in deflate-raw +Pass decompressing splitted chunk into pieces of size 3 should work in deflate +Pass decompressing splitted chunk into pieces of size 3 should work in gzip +Pass decompressing splitted chunk into pieces of size 3 should work in deflate-raw +Pass decompressing splitted chunk into pieces of size 4 should work in deflate +Pass decompressing splitted chunk into pieces of size 4 should work in gzip +Pass decompressing splitted chunk into pieces of size 4 should work in deflate-raw +Pass decompressing splitted chunk into pieces of size 5 should work in deflate +Pass decompressing splitted chunk into pieces of size 5 should work in gzip +Pass decompressing splitted chunk into pieces of size 5 should work in deflate-raw +Pass decompressing splitted chunk into pieces of size 6 should work in deflate +Pass decompressing splitted chunk into pieces of size 6 should work in gzip +Pass decompressing splitted chunk into pieces of size 6 should work in deflate-raw +Pass decompressing splitted chunk into pieces of size 7 should work in deflate +Pass decompressing splitted chunk into pieces of size 7 should work in gzip +Pass decompressing splitted chunk into pieces of size 7 should work in deflate-raw +Pass decompressing splitted chunk into pieces of size 8 should work in deflate +Pass decompressing splitted chunk into pieces of size 8 should work in gzip +Pass decompressing splitted chunk into pieces of size 8 should work in deflate-raw +Pass decompressing splitted chunk into pieces of size 9 should work in deflate +Pass decompressing splitted chunk into pieces of size 9 should work in gzip +Pass decompressing splitted chunk into pieces of size 9 should work in deflate-raw +Pass decompressing splitted chunk into pieces of size 10 should work in deflate +Pass decompressing splitted chunk into pieces of size 10 should work in gzip +Pass decompressing splitted chunk into pieces of size 10 should work in deflate-raw +Pass decompressing splitted chunk into pieces of size 11 should work in deflate +Pass decompressing splitted chunk into pieces of size 11 should work in gzip +Pass decompressing splitted chunk into pieces of size 11 should work in deflate-raw +Pass decompressing splitted chunk into pieces of size 12 should work in deflate +Pass decompressing splitted chunk into pieces of size 12 should work in gzip +Pass decompressing splitted chunk into pieces of size 12 should work in deflate-raw +Pass decompressing splitted chunk into pieces of size 13 should work in deflate +Pass decompressing splitted chunk into pieces of size 13 should work in gzip +Pass decompressing splitted chunk into pieces of size 13 should work in deflate-raw +Pass decompressing splitted chunk into pieces of size 14 should work in deflate +Pass decompressing splitted chunk into pieces of size 14 should work in gzip +Pass decompressing splitted chunk into pieces of size 14 should work in deflate-raw +Pass decompressing splitted chunk into pieces of size 15 should work in deflate +Pass decompressing splitted chunk into pieces of size 15 should work in gzip +Pass decompressing splitted chunk into pieces of size 15 should work in deflate-raw \ No newline at end of file