From 0459795b05ce723bd0d7fabd9090424908051e84 Mon Sep 17 00:00:00 2001 From: Johan Dahlin Date: Thu, 12 Sep 2024 14:06:12 +0200 Subject: [PATCH] LibCompress: Add ZlibDecompressor.decompress_all --- .../Text/expected/all-window-properties.txt | 2 +- Userland/Libraries/LibCompress/Zlib.cpp | 16 +++++++++ Userland/Libraries/LibCompress/Zlib.h | 3 +- .../LibWeb/Compression/CompressionStream.cpp | 35 ++++++++++++------- .../Compression/DecompressionStream.cpp | 35 ++++++++++++------- 5 files changed, 65 insertions(+), 26 deletions(-) diff --git a/Tests/LibWeb/Text/expected/all-window-properties.txt b/Tests/LibWeb/Text/expected/all-window-properties.txt index 8c09febb7563..97fe913fcd10 100644 --- a/Tests/LibWeb/Text/expected/all-window-properties.txt +++ b/Tests/LibWeb/Text/expected/all-window-properties.txt @@ -63,7 +63,6 @@ Crypto CryptoKey CustomElementRegistry CustomEvent -DecompressionStream DOMException DOMImplementation DOMMatrix @@ -83,6 +82,7 @@ DataTransferItem DataTransferItemList DataView Date +DecompressionStream DisposableStack Document DocumentFragment diff --git a/Userland/Libraries/LibCompress/Zlib.cpp b/Userland/Libraries/LibCompress/Zlib.cpp index 6978eae94c00..17d0c3c51ee7 100644 --- a/Userland/Libraries/LibCompress/Zlib.cpp +++ b/Userland/Libraries/LibCompress/Zlib.cpp @@ -171,4 +171,20 @@ ErrorOr ZlibCompressor::compress_all(ReadonlyBytes bytes, ZlibCompre return buffer; } +ErrorOr ZlibDecompressor::decompress_all(ReadonlyBytes bytes) +{ + // Even though the content encoding is "deflate", it's actually deflate with the zlib wrapper. + // https://tools.ietf.org/html/rfc7230#section-4.2.2 + auto memory_stream = TRY(try_make(bytes)); + auto zlib_decompressor = ZlibDecompressor::create(move(memory_stream)); + if (zlib_decompressor.is_error()) { + // From the RFC: + // "Note: Some non-conformant implementations send the "deflate" + // compressed data without the zlib wrapper." + return DeflateDecompressor::decompress_all(bytes); + } else { + return zlib_decompressor.value()->read_until_eof(); + } +} + } diff --git a/Userland/Libraries/LibCompress/Zlib.h b/Userland/Libraries/LibCompress/Zlib.h index 478ead7f24ed..20228c455df2 100644 --- a/Userland/Libraries/LibCompress/Zlib.h +++ b/Userland/Libraries/LibCompress/Zlib.h @@ -54,6 +54,8 @@ class ZlibDecompressor : public Stream { virtual bool is_open() const override; virtual void close() override; + static ErrorOr decompress_all(ReadonlyBytes); + private: ZlibDecompressor(ZlibHeader, NonnullOwnPtr); @@ -72,7 +74,6 @@ class ZlibCompressor : public Stream { virtual bool is_open() const override; virtual void close() override; ErrorOr finish(); - static ErrorOr compress_all(ReadonlyBytes bytes, ZlibCompressionLevel = ZlibCompressionLevel::Default); private: diff --git a/Userland/Libraries/LibWeb/Compression/CompressionStream.cpp b/Userland/Libraries/LibWeb/Compression/CompressionStream.cpp index 0d0ee6ea5542..682a1055b47e 100644 --- a/Userland/Libraries/LibWeb/Compression/CompressionStream.cpp +++ b/Userland/Libraries/LibWeb/Compression/CompressionStream.cpp @@ -26,7 +26,28 @@ JS_DEFINE_ALLOCATOR(CompressionStream); WebIDL::ExceptionOr> CompressionStream::construct_impl(JS::Realm& realm, Bindings::CompressionFormat format) { - return realm.heap().allocate(realm, realm, format); + auto stream = realm.heap().allocate(realm, realm, format); + + auto& vm = realm.vm(); + auto* env = vm.variable_environment(); + if (env) { + // FIXME: Make this private to the web execution context + auto& global_object = realm.global_object(); + auto constructor_value_or_error = global_object.get("CompressionStream_constructor"); + auto constructor_value = TRY(constructor_value_or_error); + if (constructor_value.is_empty() || constructor_value.is_undefined()) { + return WebIDL::SimpleException { + WebIDL::SimpleExceptionType::TypeError, + "CompressionStream constructor not found"sv + }; + } + + auto& func = static_cast(constructor_value.as_function()); + JS::MarkedVector arguments_list { vm.heap() }; + arguments_list.append(JS::PrimitiveString::create(vm, Bindings::idl_enum_to_string(format))); + TRY(func.internal_call(stream->m_this_value, move(arguments_list))); + } + return stream; } WebIDL::ExceptionOr> CompressionStream::compress(JS::VM& vm, Bindings::CompressionFormat format, JS::Handle buffer_source) @@ -63,7 +84,7 @@ WebIDL::ExceptionOr> CompressionStream::compres static JS::GCPtr import_js_script(JS::Realm& realm) { auto& vm = realm.vm(); - auto file = MUST(Core::File::open("Userland/Libraries/LibWeb/Compression/CompressionStream.js"sv, Core::File::OpenMode::Read)); + auto file = MUST(Core::File::open("/Users/johandahlin/dev/ladybird/Userland/Libraries/LibWeb/Compression/CompressionStream.js"sv, Core::File::OpenMode::Read)); auto file_contents = MUST(file->read_until_eof()); auto source = StringView { file_contents }; @@ -78,16 +99,6 @@ CompressionStream::CompressionStream(JS::Realm& realm, Bindings::CompressionForm , m_js_script(import_js_script(realm)) , m_this_value(JS::Object::create(realm, realm.intrinsics().object_prototype())) { - auto& vm = realm.vm(); - auto* env = vm.variable_environment(); - if (env) { - // FIXME: Make this private to the web execution context - auto constructor_value = MUST(env->get_binding_value(vm, "CompressionStream_constructor", true)); - auto& func = static_cast(constructor_value.as_function()); - JS::MarkedVector arguments_list { vm.heap() }; - arguments_list.append(JS::PrimitiveString::create(vm, Bindings::idl_enum_to_string(format))); - MUST(func.internal_call(m_this_value, move(arguments_list))); - } } CompressionStream::~CompressionStream() = default; diff --git a/Userland/Libraries/LibWeb/Compression/DecompressionStream.cpp b/Userland/Libraries/LibWeb/Compression/DecompressionStream.cpp index 722d35ba2ac4..d93e29604ab4 100644 --- a/Userland/Libraries/LibWeb/Compression/DecompressionStream.cpp +++ b/Userland/Libraries/LibWeb/Compression/DecompressionStream.cpp @@ -26,7 +26,28 @@ JS_DEFINE_ALLOCATOR(DecompressionStream); WebIDL::ExceptionOr> DecompressionStream::construct_impl(JS::Realm& realm, Bindings::CompressionFormat format) { - return realm.heap().allocate(realm, realm, format); + auto stream = realm.heap().allocate(realm, realm, format); + + auto& vm = realm.vm(); + auto* env = vm.variable_environment(); + if (env) { + // FIXME: Make this private to the web execution context + auto& global_object = realm.global_object(); + auto constructor_value_or_error = global_object.get("DecompressionStream_constructor"); + auto constructor_value = TRY(constructor_value_or_error); + if (constructor_value.is_empty() || constructor_value.is_undefined()) { + return WebIDL::SimpleException { + WebIDL::SimpleExceptionType::TypeError, + "DecompressionStream constructor not found"sv + }; + } + + auto& func = static_cast(constructor_value.as_function()); + JS::MarkedVector arguments_list { vm.heap() }; + arguments_list.append(JS::PrimitiveString::create(vm, Bindings::idl_enum_to_string(format))); + TRY(func.internal_call(stream->m_this_value, move(arguments_list))); + } + return stream; } WebIDL::ExceptionOr> DecompressionStream::decompress(JS::VM& vm, Bindings::CompressionFormat format, JS::Handle buffer_source) @@ -65,7 +86,7 @@ WebIDL::ExceptionOr> DecompressionStream::decom static JS::GCPtr import_js_script(JS::Realm& realm) { auto& vm = realm.vm(); - auto file = MUST(Core::File::open("Userland/Libraries/LibWeb/Compression/DecompressionStream.js"sv, Core::File::OpenMode::Read)); + auto file = MUST(Core::File::open("/Users/johandahlin/dev/ladybird/Userland/Libraries/LibWeb/Compression/DecompressionStream.js"sv, Core::File::OpenMode::Read)); auto file_contents = MUST(file->read_until_eof()); auto source = StringView { file_contents }; @@ -80,16 +101,6 @@ DecompressionStream::DecompressionStream(JS::Realm& realm, Bindings::Compression , m_js_script(import_js_script(realm)) , m_this_value(JS::Object::create(realm, realm.intrinsics().object_prototype())) { - auto& vm = realm.vm(); - auto* env = vm.variable_environment(); - if (env) { - // FIXME: Make this private to the web execution context - auto constructor_value = MUST(env->get_binding_value(vm, "DecompressionStream_constructor", true)); - auto& func = static_cast(constructor_value.as_function()); - JS::MarkedVector arguments_list { vm.heap() }; - arguments_list.append(JS::PrimitiveString::create(vm, Bindings::idl_enum_to_string(format))); - MUST(func.internal_call(m_this_value, move(arguments_list))); - } } DecompressionStream::~DecompressionStream() = default;