Commit 42bda3eb authored by Canon Mukai's avatar Canon Mukai Committed by Commit Bot

Align CompressionStream and DecompressionStream

There were some differences between CompressionStream and
DecompressionStream. So I aligned them.
Also, I made CompressionStream accept BufferSource.

Bug: 999091
Change-Id: Iaf6c3e54804a10ef22d05c5f4da0d5ae07d0e765
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1847605
Commit-Queue: Canon Mukai <canonmukai@google.com>
Reviewed-by: default avatarAdam Rice <ricea@chromium.org>
Reviewed-by: default avatarYutaka Hirano <yhirano@chromium.org>
Cr-Commit-Position: refs/heads/master@{#704610}
parent f4d4c687
...@@ -16,8 +16,6 @@ CompressionStream* CompressionStream::Create(ScriptState* script_state, ...@@ -16,8 +16,6 @@ CompressionStream* CompressionStream::Create(ScriptState* script_state,
exception_state); exception_state);
} }
CompressionStream::~CompressionStream() = default;
ReadableStream* CompressionStream::readable() const { ReadableStream* CompressionStream::readable() const {
return transform_->Readable(); return transform_->Readable();
} }
...@@ -35,12 +33,11 @@ CompressionStream::CompressionStream(ScriptState* script_state, ...@@ -35,12 +33,11 @@ CompressionStream::CompressionStream(ScriptState* script_state,
const AtomicString& format, const AtomicString& format,
ExceptionState& exception_state) ExceptionState& exception_state)
: transform_(MakeGarbageCollected<TransformStream>()) { : transform_(MakeGarbageCollected<TransformStream>()) {
DeflateTransformer::Format deflate_format; DeflateTransformer::Format deflate_format =
DeflateTransformer::Format::kDeflate;
if (format == "gzip") { if (format == "gzip") {
deflate_format = DeflateTransformer::Format::Gzip; deflate_format = DeflateTransformer::Format::kGzip;
} else if (format == "deflate") { } else if (format != "deflate") {
deflate_format = DeflateTransformer::Format::Deflate;
} else {
exception_state.ThrowTypeError("Unsupported format"); exception_state.ThrowTypeError("Unsupported format");
return; return;
} }
......
...@@ -19,7 +19,6 @@ class CompressionStream final : public ScriptWrappable { ...@@ -19,7 +19,6 @@ class CompressionStream final : public ScriptWrappable {
const AtomicString&, const AtomicString&,
ExceptionState&); ExceptionState&);
CompressionStream(ScriptState*, const AtomicString&, ExceptionState&); CompressionStream(ScriptState*, const AtomicString&, ExceptionState&);
~CompressionStream() override;
ReadableStream* readable() const; ReadableStream* readable() const;
WritableStream* writable() const; WritableStream* writable() const;
......
...@@ -29,17 +29,17 @@ DecompressionStream::DecompressionStream(ScriptState* script_state, ...@@ -29,17 +29,17 @@ DecompressionStream::DecompressionStream(ScriptState* script_state,
const AtomicString& format, const AtomicString& format,
ExceptionState& exception_state) ExceptionState& exception_state)
: transform_(MakeGarbageCollected<TransformStream>()) { : transform_(MakeGarbageCollected<TransformStream>()) {
InflateTransformer::Algorithm algorithm = InflateTransformer::Format deflate_format =
InflateTransformer::Algorithm::kDeflate; InflateTransformer::Format::kDeflate;
if (format == "gzip") { if (format == "gzip") {
algorithm = InflateTransformer::Algorithm::kGzip; deflate_format = InflateTransformer::Format::kGzip;
} else if (format != "deflate") { } else if (format != "deflate") {
exception_state.ThrowTypeError("Unsupported format"); exception_state.ThrowTypeError("Unsupported format");
return; return;
} }
transform_->Init( transform_->Init(
MakeGarbageCollected<InflateTransformer>(script_state, algorithm), MakeGarbageCollected<InflateTransformer>(script_state, deflate_format),
script_state, exception_state); script_state, exception_state);
} }
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_array.h" #include "third_party/blink/renderer/bindings/core/v8/v8_uint8_array.h"
#include "third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.h" #include "third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.h"
...@@ -15,7 +16,6 @@ ...@@ -15,7 +16,6 @@
#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h" #include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/to_v8.h" #include "third_party/blink/renderer/platform/bindings/to_v8.h"
#include "v8/include/v8.h" #include "v8/include/v8.h"
namespace blink { namespace blink {
...@@ -23,23 +23,27 @@ namespace blink { ...@@ -23,23 +23,27 @@ namespace blink {
DeflateTransformer::DeflateTransformer(ScriptState* script_state, DeflateTransformer::DeflateTransformer(ScriptState* script_state,
Format format, Format format,
int level) int level)
: script_state_(script_state), : script_state_(script_state), out_buffer_(kBufferSize) {
// TODO(arenevier): same as PODArena default chunk size. Is that
// reasonable? Or should we use a variable size buffer?
buffer_(16384) {
DCHECK(level >= 1 && level <= 9); DCHECK(level >= 1 && level <= 9);
int window_bits = 15;
if (format == Format::Gzip) {
window_bits += 16;
}
memset(&stream_, 0, sizeof(z_stream)); memset(&stream_, 0, sizeof(z_stream));
int err = deflateInit2(&stream_, level, Z_DEFLATED, window_bits, 8, constexpr int kWindowBits = 15;
constexpr int kUseGzip = 16;
int err;
switch (format) {
case Format::kDeflate:
err = deflateInit2(&stream_, level, Z_DEFLATED, kWindowBits, 8,
Z_DEFAULT_STRATEGY);
break;
case Format::kGzip:
err = deflateInit2(&stream_, level, Z_DEFLATED, kWindowBits + kUseGzip, 8,
Z_DEFAULT_STRATEGY); Z_DEFAULT_STRATEGY);
break;
}
DCHECK_EQ(Z_OK, err); DCHECK_EQ(Z_OK, err);
} }
DeflateTransformer::~DeflateTransformer() { DeflateTransformer::~DeflateTransformer() {
if (!is_stream_freed_) { if (!was_flush_called_) {
deflateEnd(&stream_); deflateEnd(&stream_);
} }
} }
...@@ -48,54 +52,56 @@ void DeflateTransformer::Transform( ...@@ -48,54 +52,56 @@ void DeflateTransformer::Transform(
v8::Local<v8::Value> chunk, v8::Local<v8::Value> chunk,
TransformStreamDefaultControllerInterface* controller, TransformStreamDefaultControllerInterface* controller,
ExceptionState& exception_state) { ExceptionState& exception_state) {
NotShared<DOMUint8Array> chunk_data = ToNotShared<NotShared<DOMUint8Array>>( ArrayBufferOrArrayBufferView buffer_source;
script_state_->GetIsolate(), chunk, exception_state); V8ArrayBufferOrArrayBufferView::ToImpl(
script_state_->GetIsolate(), chunk, buffer_source,
UnionTypeConversionMode::kNotNullable, exception_state);
if (exception_state.HadException()) { if (exception_state.HadException()) {
return; return;
} }
if (!chunk_data) { if (buffer_source.IsArrayBufferView()) {
exception_state.ThrowTypeError("chunk is not of type Uint8Array."); const auto* view = buffer_source.GetAsArrayBufferView().View();
const uint8_t* start = static_cast<const uint8_t*>(view->BaseAddress());
wtf_size_t length = view->byteLength();
Deflate(start, length, IsFinished(false), controller, exception_state);
return; return;
} }
DCHECK(buffer_source.IsArrayBuffer());
if (chunk_data.View()->length() == 0) { const auto* array_buffer = buffer_source.GetAsArrayBuffer();
return; const uint8_t* start = static_cast<const uint8_t*>(array_buffer->Data());
} wtf_size_t length = array_buffer->ByteLength();
Deflate(start, length, IsFinished(false), controller, exception_state);
Deflate(chunk_data.View(), false, controller, exception_state);
} }
void DeflateTransformer::Flush( void DeflateTransformer::Flush(
TransformStreamDefaultControllerInterface* controller, TransformStreamDefaultControllerInterface* controller,
ExceptionState& exception_state) { ExceptionState& exception_state) {
Deflate(nullptr, true, controller, exception_state); Deflate(nullptr, 0u, IsFinished(true), controller, exception_state);
is_stream_freed_ = true; was_flush_called_ = true;
deflateEnd(&stream_); deflateEnd(&stream_);
} }
void DeflateTransformer::Deflate( void DeflateTransformer::Deflate(
const DOMUint8Array* data, const uint8_t* start,
bool finished, wtf_size_t length,
IsFinished finished,
TransformStreamDefaultControllerInterface* controller, TransformStreamDefaultControllerInterface* controller,
ExceptionState& exception_state) { ExceptionState& exception_state) {
if (data) { stream_.avail_in = length;
stream_.avail_in = data->length(); // Zlib treats this pointer as const, so this cast is safe.
stream_.next_in = data->DataMaybeShared(); stream_.next_in = const_cast<uint8_t*>(start);
} else {
stream_.avail_in = 0;
stream_.next_in = nullptr;
}
do { do {
stream_.avail_out = buffer_.size(); stream_.avail_out = out_buffer_.size();
stream_.next_out = buffer_.data(); stream_.next_out = out_buffer_.data();
int err = deflate(&stream_, finished ? Z_FINISH : Z_NO_FLUSH); int err = deflate(&stream_, finished ? Z_FINISH : Z_NO_FLUSH);
DCHECK((finished && err == Z_STREAM_END) || (err == Z_OK)); DCHECK((finished && err == Z_STREAM_END) || err == Z_OK ||
err == Z_BUF_ERROR);
wtf_size_t bytes = buffer_.size() - stream_.avail_out; wtf_size_t bytes = out_buffer_.size() - stream_.avail_out;
if (bytes) { if (bytes) {
controller->Enqueue( controller->Enqueue(
ToV8(DOMUint8Array::Create(buffer_.data(), bytes), script_state_), ToV8(DOMUint8Array::Create(out_buffer_.data(), bytes), script_state_),
exception_state); exception_state);
if (exception_state.HadException()) { if (exception_state.HadException()) {
return; return;
......
...@@ -5,17 +5,18 @@ ...@@ -5,17 +5,18 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_DEFLATE_TRANSFORMER_H_ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_DEFLATE_TRANSFORMER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_DEFLATE_TRANSFORMER_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_DEFLATE_TRANSFORMER_H_
#include "base/util/type_safety/strong_alias.h"
#include "third_party/blink/renderer/core/streams/transform_stream_transformer.h" #include "third_party/blink/renderer/core/streams/transform_stream_transformer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h" #include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
#include "third_party/blink/renderer/platform/wtf/vector.h" #include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/zlib/zlib.h" #include "third_party/zlib/zlib.h"
namespace blink { namespace blink {
class DeflateTransformer final : public TransformStreamTransformer { class DeflateTransformer final : public TransformStreamTransformer {
public: public:
enum class Format { Gzip, Deflate }; enum class Format { kGzip, kDeflate };
DeflateTransformer(ScriptState*, Format, int level); DeflateTransformer(ScriptState*, Format, int level);
~DeflateTransformer() override; ~DeflateTransformer() override;
...@@ -32,18 +33,24 @@ class DeflateTransformer final : public TransformStreamTransformer { ...@@ -32,18 +33,24 @@ class DeflateTransformer final : public TransformStreamTransformer {
void Trace(Visitor*) override; void Trace(Visitor*) override;
private: private:
void Deflate(const DOMUint8Array* data, using IsFinished = util::StrongAlias<class IsFinishedTag, bool>;
bool finished,
void Deflate(const uint8_t*,
wtf_size_t,
IsFinished,
TransformStreamDefaultControllerInterface*, TransformStreamDefaultControllerInterface*,
ExceptionState&); ExceptionState&);
Member<ScriptState> script_state_; Member<ScriptState> script_state_;
Vector<uint8_t> buffer_; Vector<uint8_t> out_buffer_;
z_stream stream_; z_stream stream_;
bool is_stream_freed_ = false; bool was_flush_called_ = false;
// This buffer size has been experimentally verified to be optimal.
static constexpr wtf_size_t kBufferSize = 16384;
DISALLOW_COPY_AND_ASSIGN(DeflateTransformer); DISALLOW_COPY_AND_ASSIGN(DeflateTransformer);
}; };
......
...@@ -16,18 +16,17 @@ ...@@ -16,18 +16,17 @@
namespace blink { namespace blink {
InflateTransformer::InflateTransformer(ScriptState* script_state, InflateTransformer::InflateTransformer(ScriptState* script_state, Format format)
Algorithm algorithm)
: script_state_(script_state), out_buffer_(kBufferSize) { : script_state_(script_state), out_buffer_(kBufferSize) {
memset(&stream_, 0, sizeof(z_stream)); memset(&stream_, 0, sizeof(z_stream));
int err;
constexpr int kWindowBits = 15; constexpr int kWindowBits = 15;
constexpr int kUseGzip = 16; constexpr int kUseGzip = 16;
switch (algorithm) { int err;
case Algorithm::kDeflate: switch (format) {
case Format::kDeflate:
err = inflateInit2(&stream_, kWindowBits); err = inflateInit2(&stream_, kWindowBits);
break; break;
case Algorithm::kGzip: case Format::kGzip:
err = inflateInit2(&stream_, kWindowBits + kUseGzip); err = inflateInit2(&stream_, kWindowBits + kUseGzip);
break; break;
} }
...@@ -54,14 +53,14 @@ void InflateTransformer::Transform( ...@@ -54,14 +53,14 @@ void InflateTransformer::Transform(
} }
if (buffer_source.IsArrayBufferView()) { if (buffer_source.IsArrayBufferView()) {
const auto* view = buffer_source.GetAsArrayBufferView().View(); const auto* view = buffer_source.GetAsArrayBufferView().View();
const Bytef* start = static_cast<const Bytef*>(view->BaseAddress()); const uint8_t* start = static_cast<const uint8_t*>(view->BaseAddress());
wtf_size_t length = view->byteLength(); wtf_size_t length = view->byteLength();
Inflate(start, length, IsFinished(false), controller, exception_state); Inflate(start, length, IsFinished(false), controller, exception_state);
return; return;
} }
DCHECK(buffer_source.IsArrayBuffer()); DCHECK(buffer_source.IsArrayBuffer());
const auto* array_buffer = buffer_source.GetAsArrayBuffer(); const auto* array_buffer = buffer_source.GetAsArrayBuffer();
const uint8_t* start = static_cast<const Bytef*>(array_buffer->Data()); const uint8_t* start = static_cast<const uint8_t*>(array_buffer->Data());
wtf_size_t length = array_buffer->ByteLength(); wtf_size_t length = array_buffer->ByteLength();
Inflate(start, length, IsFinished(false), controller, exception_state); Inflate(start, length, IsFinished(false), controller, exception_state);
} }
...@@ -76,18 +75,17 @@ void InflateTransformer::Flush( ...@@ -76,18 +75,17 @@ void InflateTransformer::Flush(
} }
void InflateTransformer::Inflate( void InflateTransformer::Inflate(
const Bytef* start, const uint8_t* start,
wtf_size_t length, wtf_size_t length,
IsFinished finished, IsFinished finished,
TransformStreamDefaultControllerInterface* controller, TransformStreamDefaultControllerInterface* controller,
ExceptionState& exception_state) { ExceptionState& exception_state) {
unsigned int out_buffer_size = static_cast<unsigned int>(kBufferSize);
stream_.avail_in = length; stream_.avail_in = length;
// Zlib treats this pointer as const, so this cast is safe. // Zlib treats this pointer as const, so this cast is safe.
stream_.next_in = const_cast<Bytef*>(start); stream_.next_in = const_cast<uint8_t*>(start);
do { do {
stream_.avail_out = out_buffer_size; stream_.avail_out = out_buffer_.size();
stream_.next_out = out_buffer_.data(); stream_.next_out = out_buffer_.data();
int err = inflate(&stream_, finished ? Z_FINISH : Z_NO_FLUSH); int err = inflate(&stream_, finished ? Z_FINISH : Z_NO_FLUSH);
if (err != Z_OK && err != Z_STREAM_END && err != Z_BUF_ERROR) { if (err != Z_OK && err != Z_STREAM_END && err != Z_BUF_ERROR) {
...@@ -95,7 +93,7 @@ void InflateTransformer::Inflate( ...@@ -95,7 +93,7 @@ void InflateTransformer::Inflate(
return; return;
} }
wtf_size_t bytes = out_buffer_size - stream_.avail_out; wtf_size_t bytes = out_buffer_.size() - stream_.avail_out;
if (bytes) { if (bytes) {
controller->Enqueue( controller->Enqueue(
ToV8(DOMUint8Array::Create(out_buffer_.data(), bytes), script_state_), ToV8(DOMUint8Array::Create(out_buffer_.data(), bytes), script_state_),
......
...@@ -12,9 +12,9 @@ namespace blink { ...@@ -12,9 +12,9 @@ namespace blink {
class InflateTransformer final : public TransformStreamTransformer { class InflateTransformer final : public TransformStreamTransformer {
public: public:
enum class Algorithm { kDeflate, kGzip }; enum class Format { kDeflate, kGzip };
InflateTransformer(ScriptState*, Algorithm algorithm); InflateTransformer(ScriptState*, Format format);
~InflateTransformer() override; ~InflateTransformer() override;
void Transform(v8::Local<v8::Value> chunk, void Transform(v8::Local<v8::Value> chunk,
...@@ -31,7 +31,7 @@ class InflateTransformer final : public TransformStreamTransformer { ...@@ -31,7 +31,7 @@ class InflateTransformer final : public TransformStreamTransformer {
private: private:
using IsFinished = util::StrongAlias<class IsFinishedTag, bool>; using IsFinished = util::StrongAlias<class IsFinishedTag, bool>;
void Inflate(const Bytef*, void Inflate(const uint8_t*,
wtf_size_t, wtf_size_t,
IsFinished, IsFinished,
TransformStreamDefaultControllerInterface*, TransformStreamDefaultControllerInterface*,
...@@ -41,10 +41,11 @@ class InflateTransformer final : public TransformStreamTransformer { ...@@ -41,10 +41,11 @@ class InflateTransformer final : public TransformStreamTransformer {
z_stream stream_; z_stream stream_;
Vector<Bytef> out_buffer_; Vector<uint8_t> out_buffer_;
bool was_flush_called_ = false; bool was_flush_called_ = false;
// This buffer size has been experimentally verified to be optimal.
static constexpr wtf_size_t kBufferSize = 65536; static constexpr wtf_size_t kBufferSize = 65536;
DISALLOW_COPY_AND_ASSIGN(InflateTransformer); DISALLOW_COPY_AND_ASSIGN(InflateTransformer);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment