Commit 18def511 authored by Adam Rice's avatar Adam Rice Committed by Commit Bot

Return ScriptPromise from TransformStreamTransformer

Previously the Transform() and Flush() methods of
TransformStreamTransformer returned void. This meant that there was no
way for them to wait for asynchronous work to finish.

Change the function signatures to return ScriptPromise. Transform() or
Flush() won't be called again until the returned promise is settled.

Returning v8::Local<v8::Promise> would have been slightly more
efficient, but ScriptPromise was used for consistency with
UnderlyingSinkBase and UnderlyingSourceBase.

Add tests that Transform() and Flush() promises are actually waited for.

BUG=962837

Change-Id: I2e79c6a79a457fd021eee17eca4f1502c3aa521f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1865735Reviewed-by: default avatarYutaka Hirano <yhirano@chromium.org>
Commit-Queue: Adam Rice <ricea@chromium.org>
Cr-Commit-Position: refs/heads/master@{#709861}
parent 9d5550ff
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/streams/transform_stream_native.h" #include "third_party/blink/renderer/core/streams/transform_stream_native.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/web_feature.h" #include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/streams/miscellaneous_operations.h" #include "third_party/blink/renderer/core/streams/miscellaneous_operations.h"
...@@ -66,11 +67,12 @@ class TransformStreamNative::FlushAlgorithm final : public StreamAlgorithm { ...@@ -66,11 +67,12 @@ class TransformStreamNative::FlushAlgorithm final : public StreamAlgorithm {
ExceptionState exception_state(script_state->GetIsolate(), ExceptionState exception_state(script_state->GetIsolate(),
ExceptionState::kUnknownContext, "", ""); ExceptionState::kUnknownContext, "", "");
ControllerInterface controller_interface(script_state, controller_); ControllerInterface controller_interface(script_state, controller_);
ScriptPromise promise;
{ {
// This is needed because the realm of the transformer can be different // This is needed because the realm of the transformer can be different
// from the realm of the transform stream. // from the realm of the transform stream.
ScriptState::Scope scope(transformer_->GetScriptState()); ScriptState::Scope scope(transformer_->GetScriptState());
transformer_->Flush(&controller_interface, exception_state); promise = transformer_->Flush(&controller_interface, exception_state);
} }
if (exception_state.HadException()) { if (exception_state.HadException()) {
auto exception = exception_state.GetException(); auto exception = exception_state.GetException();
...@@ -78,7 +80,7 @@ class TransformStreamNative::FlushAlgorithm final : public StreamAlgorithm { ...@@ -78,7 +80,7 @@ class TransformStreamNative::FlushAlgorithm final : public StreamAlgorithm {
return PromiseReject(script_state, exception); return PromiseReject(script_state, exception);
} }
return PromiseResolveWithUndefined(script_state); return promise.V8Value().As<v8::Promise>();
} }
// SetController() must be called before Run() is. // SetController() must be called before Run() is.
...@@ -112,11 +114,13 @@ class TransformStreamNative::TransformAlgorithm final : public StreamAlgorithm { ...@@ -112,11 +114,13 @@ class TransformStreamNative::TransformAlgorithm final : public StreamAlgorithm {
ExceptionState exception_state(script_state->GetIsolate(), ExceptionState exception_state(script_state->GetIsolate(),
ExceptionState::kUnknownContext, "", ""); ExceptionState::kUnknownContext, "", "");
ControllerInterface controller_interface(script_state, controller_); ControllerInterface controller_interface(script_state, controller_);
ScriptPromise promise;
{ {
// This is needed because the realm of the transformer can be different // This is needed because the realm of the transformer can be different
// from the realm of the transform stream. // from the realm of the transform stream.
ScriptState::Scope scope(transformer_->GetScriptState()); ScriptState::Scope scope(transformer_->GetScriptState());
transformer_->Transform(argv[0], &controller_interface, exception_state); promise = transformer_->Transform(argv[0], &controller_interface,
exception_state);
} }
if (exception_state.HadException()) { if (exception_state.HadException()) {
auto exception = exception_state.GetException(); auto exception = exception_state.GetException();
...@@ -124,7 +128,7 @@ class TransformStreamNative::TransformAlgorithm final : public StreamAlgorithm { ...@@ -124,7 +128,7 @@ class TransformStreamNative::TransformAlgorithm final : public StreamAlgorithm {
return PromiseReject(script_state, exception); return PromiseReject(script_state, exception);
} }
return PromiseResolveWithUndefined(script_state); return promise.V8Value().As<v8::Promise>();
} }
// SetController() must be called before Run() is. // SetController() must be called before Run() is.
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/bindings/core/v8/script_function.h" #include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h" #include "third_party/blink/renderer/bindings/core/v8/script_value.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"
...@@ -29,8 +31,11 @@ ...@@ -29,8 +31,11 @@
namespace blink { namespace blink {
namespace { namespace {
using ::testing::_; using ::testing::_;
using ::testing::ByMove;
using ::testing::Mock; using ::testing::Mock;
using ::testing::Return;
class TransformStreamTest : public ::testing::Test { class TransformStreamTest : public ::testing::Test {
public: public:
...@@ -68,19 +73,33 @@ class TransformStreamTest : public ::testing::Test { ...@@ -68,19 +73,33 @@ class TransformStreamTest : public ::testing::Test {
Persistent<TransformStream> stream_; Persistent<TransformStream> stream_;
}; };
class IdentityTransformer final : public TransformStreamTransformer { // A convenient base class to make tests shorter. Subclasses need not implement
// both Transform() and Flush(), and can override the void versions to avoid the
// need to create a promise to return. Not appropriate for use in production.
class TestTransformer : public TransformStreamTransformer {
public: public:
explicit IdentityTransformer(ScriptState* script_state) explicit TestTransformer(ScriptState* script_state)
: script_state_(script_state) {} : script_state_(script_state) {}
void Transform(v8::Local<v8::Value> chunk, virtual void TransformVoid(v8::Local<v8::Value>,
TransformStreamDefaultControllerInterface* controller, TransformStreamDefaultControllerInterface*,
ExceptionState& exception_state) override { ExceptionState&) {}
controller->Enqueue(chunk, exception_state);
ScriptPromise Transform(v8::Local<v8::Value> chunk,
TransformStreamDefaultControllerInterface* controller,
ExceptionState& exception_state) override {
TransformVoid(chunk, controller, exception_state);
return ScriptPromise::CastUndefined(script_state_);
} }
void Flush(TransformStreamDefaultControllerInterface* controller, virtual void FlushVoid(TransformStreamDefaultControllerInterface*,
ExceptionState& exception_state) override {} ExceptionState&) {}
ScriptPromise Flush(TransformStreamDefaultControllerInterface* controller,
ExceptionState& exception_state) override {
FlushVoid(controller, exception_state);
return ScriptPromise::CastUndefined(script_state_);
}
ScriptState* GetScriptState() override { return script_state_; } ScriptState* GetScriptState() override { return script_state_; }
...@@ -93,18 +112,30 @@ class IdentityTransformer final : public TransformStreamTransformer { ...@@ -93,18 +112,30 @@ class IdentityTransformer final : public TransformStreamTransformer {
const Member<ScriptState> script_state_; const Member<ScriptState> script_state_;
}; };
class IdentityTransformer final : public TestTransformer {
public:
explicit IdentityTransformer(ScriptState* script_state)
: TestTransformer(script_state) {}
void TransformVoid(v8::Local<v8::Value> chunk,
TransformStreamDefaultControllerInterface* controller,
ExceptionState& exception_state) override {
controller->Enqueue(chunk, exception_state);
}
};
class MockTransformStreamTransformer : public TransformStreamTransformer { class MockTransformStreamTransformer : public TransformStreamTransformer {
public: public:
explicit MockTransformStreamTransformer(ScriptState* script_state) explicit MockTransformStreamTransformer(ScriptState* script_state)
: script_state_(script_state) {} : script_state_(script_state) {}
MOCK_METHOD3(Transform, MOCK_METHOD3(Transform,
void(v8::Local<v8::Value> chunk, ScriptPromise(v8::Local<v8::Value> chunk,
TransformStreamDefaultControllerInterface*, TransformStreamDefaultControllerInterface*,
ExceptionState&)); ExceptionState&));
MOCK_METHOD2(Flush, MOCK_METHOD2(Flush,
void(TransformStreamDefaultControllerInterface*, ScriptPromise(TransformStreamDefaultControllerInterface*,
ExceptionState&)); ExceptionState&));
ScriptState* GetScriptState() override { return script_state_; } ScriptState* GetScriptState() override { return script_state_; }
...@@ -144,7 +175,9 @@ TEST_F(TransformStreamTest, TransformIsCalled) { ...@@ -144,7 +175,9 @@ TEST_F(TransformStreamTest, TransformIsCalled) {
v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate()); v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
CopyReadableAndWritableToGlobal(scope); CopyReadableAndWritableToGlobal(scope);
EXPECT_CALL(*mock, Transform(_, _, _)); EXPECT_CALL(*mock, Transform(_, _, _))
.WillOnce(
Return(ByMove(ScriptPromise::CastUndefined(scope.GetScriptState()))));
// The initial read is needed to relieve backpressure. // The initial read is needed to relieve backpressure.
EvalWithPrintingError(&scope, EvalWithPrintingError(&scope,
...@@ -165,7 +198,9 @@ TEST_F(TransformStreamTest, FlushIsCalled) { ...@@ -165,7 +198,9 @@ TEST_F(TransformStreamTest, FlushIsCalled) {
v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate()); v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
CopyReadableAndWritableToGlobal(scope); CopyReadableAndWritableToGlobal(scope);
EXPECT_CALL(*mock, Flush(_, _)); EXPECT_CALL(*mock, Flush(_, _))
.WillOnce(
Return(ByMove(ScriptPromise::CastUndefined(scope.GetScriptState()))));
EvalWithPrintingError(&scope, EvalWithPrintingError(&scope,
"const writer = writable.getWriter();\n" "const writer = writable.getWriter();\n"
...@@ -237,27 +272,17 @@ TEST_F(TransformStreamTest, EnqueueFromTransform) { ...@@ -237,27 +272,17 @@ TEST_F(TransformStreamTest, EnqueueFromTransform) {
} }
TEST_F(TransformStreamTest, EnqueueFromFlush) { TEST_F(TransformStreamTest, EnqueueFromFlush) {
class EnqueueFromFlushTransformer : public TransformStreamTransformer { class EnqueueFromFlushTransformer final : public TestTransformer {
public: public:
explicit EnqueueFromFlushTransformer(ScriptState* script_state) explicit EnqueueFromFlushTransformer(ScriptState* script_state)
: script_state_(script_state) {} : TestTransformer(script_state) {}
void Transform(v8::Local<v8::Value>,
TransformStreamDefaultControllerInterface*,
ExceptionState&) override {}
void Flush(TransformStreamDefaultControllerInterface* controller,
ExceptionState& exception_state) override {
controller->Enqueue(ToV8("a", script_state_), exception_state);
}
ScriptState* GetScriptState() override { return script_state_; }
void Trace(Visitor* visitor) override {
visitor->Trace(script_state_);
TransformStreamTransformer::Trace(visitor);
}
private: void FlushVoid(TransformStreamDefaultControllerInterface* controller,
const Member<ScriptState> script_state_; ExceptionState& exception_state) override {
controller->Enqueue(ToV8("a", GetScriptState()), exception_state);
}
}; };
V8TestingScope scope; V8TestingScope scope;
auto* script_state = scope.GetScriptState(); auto* script_state = scope.GetScriptState();
Init(MakeGarbageCollected<EnqueueFromFlushTransformer>(script_state), Init(MakeGarbageCollected<EnqueueFromFlushTransformer>(script_state),
...@@ -280,27 +305,18 @@ TEST_F(TransformStreamTest, EnqueueFromFlush) { ...@@ -280,27 +305,18 @@ TEST_F(TransformStreamTest, EnqueueFromFlush) {
TEST_F(TransformStreamTest, ThrowFromTransform) { TEST_F(TransformStreamTest, ThrowFromTransform) {
static constexpr char kMessage[] = "errorInTransform"; static constexpr char kMessage[] = "errorInTransform";
class ThrowFromTransformTransformer : public TransformStreamTransformer { class ThrowFromTransformTransformer final : public TestTransformer {
public: public:
explicit ThrowFromTransformTransformer(ScriptState* script_state) explicit ThrowFromTransformTransformer(ScriptState* script_state)
: script_state_(script_state) {} : TestTransformer(script_state) {}
void Transform(v8::Local<v8::Value>,
TransformStreamDefaultControllerInterface*,
ExceptionState& exception_state) override {
exception_state.ThrowTypeError(kMessage);
}
void Flush(TransformStreamDefaultControllerInterface*,
ExceptionState&) override {}
ScriptState* GetScriptState() override { return script_state_; } void TransformVoid(v8::Local<v8::Value>,
void Trace(Visitor* visitor) override { TransformStreamDefaultControllerInterface*,
visitor->Trace(script_state_); ExceptionState& exception_state) override {
TransformStreamTransformer::Trace(visitor); exception_state.ThrowTypeError(kMessage);
} }
private:
const Member<ScriptState> script_state_;
}; };
V8TestingScope scope; V8TestingScope scope;
auto* script_state = scope.GetScriptState(); auto* script_state = scope.GetScriptState();
Init(MakeGarbageCollected<ThrowFromTransformTransformer>( Init(MakeGarbageCollected<ThrowFromTransformTransformer>(
...@@ -331,25 +347,15 @@ TEST_F(TransformStreamTest, ThrowFromTransform) { ...@@ -331,25 +347,15 @@ TEST_F(TransformStreamTest, ThrowFromTransform) {
TEST_F(TransformStreamTest, ThrowFromFlush) { TEST_F(TransformStreamTest, ThrowFromFlush) {
static constexpr char kMessage[] = "errorInFlush"; static constexpr char kMessage[] = "errorInFlush";
class ThrowFromFlushTransformer : public TransformStreamTransformer { class ThrowFromFlushTransformer final : public TestTransformer {
public: public:
explicit ThrowFromFlushTransformer(ScriptState* script_state) explicit ThrowFromFlushTransformer(ScriptState* script_state)
: script_state_(script_state) {} : TestTransformer(script_state) {}
void Transform(v8::Local<v8::Value>,
TransformStreamDefaultControllerInterface*, void FlushVoid(TransformStreamDefaultControllerInterface*,
ExceptionState&) override {} ExceptionState& exception_state) override {
void Flush(TransformStreamDefaultControllerInterface*,
ExceptionState& exception_state) override {
exception_state.ThrowTypeError(kMessage); exception_state.ThrowTypeError(kMessage);
} }
ScriptState* GetScriptState() override { return script_state_; }
void Trace(Visitor* visitor) override {
visitor->Trace(script_state_);
TransformStreamTransformer::Trace(visitor);
}
private:
const Member<ScriptState> script_state_;
}; };
V8TestingScope scope; V8TestingScope scope;
auto* script_state = scope.GetScriptState(); auto* script_state = scope.GetScriptState();
...@@ -389,5 +395,126 @@ TEST_F(TransformStreamTest, CreateFromReadableWritablePair) { ...@@ -389,5 +395,126 @@ TEST_F(TransformStreamTest, CreateFromReadableWritablePair) {
EXPECT_EQ(writable, transform.Writable()); EXPECT_EQ(writable, transform.Writable());
} }
TEST_F(TransformStreamTest, WaitInTransform) {
class WaitInTransformTransformer final : public TestTransformer {
public:
explicit WaitInTransformTransformer(ScriptState* script_state)
: TestTransformer(script_state),
transform_promise_resolver_(
MakeGarbageCollected<ScriptPromiseResolver>(script_state)) {}
ScriptPromise Transform(v8::Local<v8::Value>,
TransformStreamDefaultControllerInterface*,
ExceptionState&) override {
return transform_promise_resolver_->Promise();
}
void FlushVoid(TransformStreamDefaultControllerInterface*,
ExceptionState&) override {
flush_called_ = true;
}
void ResolvePromise() { transform_promise_resolver_->Resolve(); }
bool FlushCalled() const { return flush_called_; }
void Trace(Visitor* visitor) override {
visitor->Trace(transform_promise_resolver_);
TestTransformer::Trace(visitor);
}
private:
const Member<ScriptPromiseResolver> transform_promise_resolver_;
bool flush_called_ = false;
};
V8TestingScope scope;
auto* script_state = scope.GetScriptState();
auto* transformer =
MakeGarbageCollected<WaitInTransformTransformer>(script_state);
Init(transformer, script_state, ASSERT_NO_EXCEPTION);
CopyReadableAndWritableToGlobal(scope);
ScriptValue promise =
EvalWithPrintingError(&scope,
"const writer = writable.getWriter();\n"
"const promise = writer.write('a');\n"
"writer.close();\n"
"promise;\n");
// Need to read to relieve backpressure.
Stream()
->Readable()
->GetReadHandle(script_state, ASSERT_NO_EXCEPTION)
->Read(script_state);
ScriptPromiseTester write_tester(script_state,
ScriptPromise::Cast(script_state, promise));
// Give Transform() the opportunity to be called.
v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
EXPECT_FALSE(write_tester.IsFulfilled());
EXPECT_FALSE(transformer->FlushCalled());
transformer->ResolvePromise();
write_tester.WaitUntilSettled();
EXPECT_TRUE(write_tester.IsFulfilled());
EXPECT_TRUE(transformer->FlushCalled());
}
TEST_F(TransformStreamTest, WaitInFlush) {
class WaitInFlushTransformer final : public TestTransformer {
public:
explicit WaitInFlushTransformer(ScriptState* script_state)
: TestTransformer(script_state),
flush_promise_resolver_(
MakeGarbageCollected<ScriptPromiseResolver>(script_state)) {}
ScriptPromise Flush(TransformStreamDefaultControllerInterface*,
ExceptionState&) override {
return flush_promise_resolver_->Promise();
}
void ResolvePromise() { flush_promise_resolver_->Resolve(); }
void Trace(Visitor* visitor) override {
visitor->Trace(flush_promise_resolver_);
TestTransformer::Trace(visitor);
}
private:
const Member<ScriptPromiseResolver> flush_promise_resolver_;
};
V8TestingScope scope;
auto* script_state = scope.GetScriptState();
auto* transformer =
MakeGarbageCollected<WaitInFlushTransformer>(script_state);
Init(transformer, script_state, ASSERT_NO_EXCEPTION);
CopyReadableAndWritableToGlobal(scope);
ScriptValue promise =
EvalWithPrintingError(&scope,
"const writer = writable.getWriter();\n"
"writer.close();\n");
// Need to read to relieve backpressure.
Stream()
->Readable()
->GetReadHandle(script_state, ASSERT_NO_EXCEPTION)
->Read(script_state);
ScriptPromiseTester close_tester(script_state,
ScriptPromise::Cast(script_state, promise));
// Give Flush() the opportunity to be called.
v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
EXPECT_FALSE(close_tester.IsFulfilled());
transformer->ResolvePromise();
close_tester.WaitUntilSettled();
EXPECT_TRUE(close_tester.IsFulfilled());
}
} // namespace } // namespace
} // namespace blink } // namespace blink
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
namespace blink { namespace blink {
class ExceptionState; class ExceptionState;
class ScriptPromise;
class ScriptState; class ScriptState;
class TransformStreamDefaultControllerInterface; class TransformStreamDefaultControllerInterface;
class Visitor; class Visitor;
...@@ -33,11 +34,11 @@ class CORE_EXPORT TransformStreamTransformer ...@@ -33,11 +34,11 @@ class CORE_EXPORT TransformStreamTransformer
TransformStreamTransformer() = default; TransformStreamTransformer() = default;
virtual ~TransformStreamTransformer() = default; virtual ~TransformStreamTransformer() = default;
virtual void Transform(v8::Local<v8::Value> chunk, virtual ScriptPromise Transform(v8::Local<v8::Value> chunk,
TransformStreamDefaultControllerInterface*, TransformStreamDefaultControllerInterface*,
ExceptionState&) = 0; ExceptionState&) = 0;
virtual void Flush(TransformStreamDefaultControllerInterface*, virtual ScriptPromise Flush(TransformStreamDefaultControllerInterface*,
ExceptionState&) = 0; ExceptionState&) = 0;
// Returns the ScriptState associated with this Transformer. // Returns the ScriptState associated with this Transformer.
virtual ScriptState* GetScriptState() = 0; virtual ScriptState* GetScriptState() = 0;
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#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/array_buffer_or_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.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"
...@@ -50,7 +51,7 @@ DeflateTransformer::~DeflateTransformer() { ...@@ -50,7 +51,7 @@ DeflateTransformer::~DeflateTransformer() {
} }
} }
void DeflateTransformer::Transform( ScriptPromise DeflateTransformer::Transform(
v8::Local<v8::Value> chunk, v8::Local<v8::Value> chunk,
TransformStreamDefaultControllerInterface* controller, TransformStreamDefaultControllerInterface* controller,
ExceptionState& exception_state) { ExceptionState& exception_state) {
...@@ -59,29 +60,33 @@ void DeflateTransformer::Transform( ...@@ -59,29 +60,33 @@ void DeflateTransformer::Transform(
script_state_->GetIsolate(), chunk, buffer_source, script_state_->GetIsolate(), chunk, buffer_source,
UnionTypeConversionMode::kNotNullable, exception_state); UnionTypeConversionMode::kNotNullable, exception_state);
if (exception_state.HadException()) { if (exception_state.HadException()) {
return; return ScriptPromise();
} }
if (buffer_source.IsArrayBufferView()) { if (buffer_source.IsArrayBufferView()) {
const auto* view = buffer_source.GetAsArrayBufferView().View(); const auto* view = buffer_source.GetAsArrayBufferView().View();
const uint8_t* start = static_cast<const uint8_t*>(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();
Deflate(start, length, IsFinished(false), controller, exception_state); Deflate(start, length, IsFinished(false), controller, exception_state);
return; return ScriptPromise::CastUndefined(script_state_);
} }
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 uint8_t*>(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();
Deflate(start, length, IsFinished(false), controller, exception_state); Deflate(start, length, IsFinished(false), controller, exception_state);
return ScriptPromise::CastUndefined(script_state_);
} }
void DeflateTransformer::Flush( ScriptPromise DeflateTransformer::Flush(
TransformStreamDefaultControllerInterface* controller, TransformStreamDefaultControllerInterface* controller,
ExceptionState& exception_state) { ExceptionState& exception_state) {
Deflate(nullptr, 0u, IsFinished(true), controller, exception_state); Deflate(nullptr, 0u, IsFinished(true), controller, exception_state);
was_flush_called_ = true; was_flush_called_ = true;
deflateEnd(&stream_); deflateEnd(&stream_);
out_buffer_.clear(); out_buffer_.clear();
return ScriptPromise::CastUndefined(script_state_);
} }
void DeflateTransformer::Deflate( void DeflateTransformer::Deflate(
......
...@@ -21,12 +21,12 @@ class DeflateTransformer final : public TransformStreamTransformer { ...@@ -21,12 +21,12 @@ class DeflateTransformer final : public TransformStreamTransformer {
DeflateTransformer(ScriptState*, Format, int level); DeflateTransformer(ScriptState*, Format, int level);
~DeflateTransformer() override; ~DeflateTransformer() override;
void Transform(v8::Local<v8::Value> chunk, ScriptPromise Transform(v8::Local<v8::Value> chunk,
TransformStreamDefaultControllerInterface*, TransformStreamDefaultControllerInterface*,
ExceptionState&) override; ExceptionState&) override;
void Flush(TransformStreamDefaultControllerInterface*, ScriptPromise Flush(TransformStreamDefaultControllerInterface*,
ExceptionState&) override; ExceptionState&) override;
ScriptState* GetScriptState() override { return script_state_; } ScriptState* GetScriptState() override { return script_state_; }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#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/array_buffer_or_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.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"
...@@ -41,7 +42,7 @@ InflateTransformer::~InflateTransformer() { ...@@ -41,7 +42,7 @@ InflateTransformer::~InflateTransformer() {
} }
} }
void InflateTransformer::Transform( ScriptPromise InflateTransformer::Transform(
v8::Local<v8::Value> chunk, v8::Local<v8::Value> chunk,
TransformStreamDefaultControllerInterface* controller, TransformStreamDefaultControllerInterface* controller,
ExceptionState& exception_state) { ExceptionState& exception_state) {
...@@ -51,23 +52,25 @@ void InflateTransformer::Transform( ...@@ -51,23 +52,25 @@ void InflateTransformer::Transform(
script_state_->GetIsolate(), chunk, buffer_source, script_state_->GetIsolate(), chunk, buffer_source,
UnionTypeConversionMode::kNotNullable, exception_state); UnionTypeConversionMode::kNotNullable, exception_state);
if (exception_state.HadException()) { if (exception_state.HadException()) {
return; return ScriptPromise();
} }
if (buffer_source.IsArrayBufferView()) { if (buffer_source.IsArrayBufferView()) {
const auto* view = buffer_source.GetAsArrayBufferView().View(); const auto* view = buffer_source.GetAsArrayBufferView().View();
const uint8_t* start = static_cast<const uint8_t*>(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 ScriptPromise::CastUndefined(script_state_);
} }
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 uint8_t*>(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);
return ScriptPromise::CastUndefined(script_state_);
} }
void InflateTransformer::Flush( ScriptPromise InflateTransformer::Flush(
TransformStreamDefaultControllerInterface* controller, TransformStreamDefaultControllerInterface* controller,
ExceptionState& exception_state) { ExceptionState& exception_state) {
DCHECK(!was_flush_called_); DCHECK(!was_flush_called_);
...@@ -75,6 +78,8 @@ void InflateTransformer::Flush( ...@@ -75,6 +78,8 @@ void InflateTransformer::Flush(
inflateEnd(&stream_); inflateEnd(&stream_);
was_flush_called_ = true; was_flush_called_ = true;
out_buffer_.clear(); out_buffer_.clear();
return ScriptPromise::CastUndefined(script_state_);
} }
void InflateTransformer::Inflate( void InflateTransformer::Inflate(
......
...@@ -17,12 +17,12 @@ class InflateTransformer final : public TransformStreamTransformer { ...@@ -17,12 +17,12 @@ class InflateTransformer final : public TransformStreamTransformer {
InflateTransformer(ScriptState*, Format format); InflateTransformer(ScriptState*, Format format);
~InflateTransformer() override; ~InflateTransformer() override;
void Transform(v8::Local<v8::Value> chunk, ScriptPromise Transform(v8::Local<v8::Value> chunk,
TransformStreamDefaultControllerInterface*, TransformStreamDefaultControllerInterface*,
ExceptionState&) override; ExceptionState&) override;
void Flush(TransformStreamDefaultControllerInterface*, ScriptPromise Flush(TransformStreamDefaultControllerInterface*,
ExceptionState&) override; ExceptionState&) override;
ScriptState* GetScriptState() override { return script_state_; } ScriptState* GetScriptState() override { return script_state_; }
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <utility> #include <utility>
#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h" #include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.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/core/streams/transform_stream_default_controller_interface.h" #include "third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.h"
#include "third_party/blink/renderer/core/streams/transform_stream_transformer.h" #include "third_party/blink/renderer/core/streams/transform_stream_transformer.h"
...@@ -38,15 +39,15 @@ class TextDecoderStream::Transformer final : public TransformStreamTransformer { ...@@ -38,15 +39,15 @@ class TextDecoderStream::Transformer final : public TransformStreamTransformer {
// Implements the type conversion part of the "decode and enqueue a chunk" // Implements the type conversion part of the "decode and enqueue a chunk"
// algorithm. // algorithm.
void Transform(v8::Local<v8::Value> chunk, ScriptPromise Transform(v8::Local<v8::Value> chunk,
TransformStreamDefaultControllerInterface* controller, TransformStreamDefaultControllerInterface* controller,
ExceptionState& exception_state) override { ExceptionState& exception_state) override {
ArrayBufferOrArrayBufferView bufferSource; ArrayBufferOrArrayBufferView bufferSource;
V8ArrayBufferOrArrayBufferView::ToImpl( V8ArrayBufferOrArrayBufferView::ToImpl(
script_state_->GetIsolate(), chunk, bufferSource, script_state_->GetIsolate(), chunk, bufferSource,
UnionTypeConversionMode::kNotNullable, exception_state); UnionTypeConversionMode::kNotNullable, exception_state);
if (exception_state.HadException()) if (exception_state.HadException())
return; return ScriptPromise();
// This implements the "get a copy of the bytes held by the buffer source" // This implements the "get a copy of the bytes held by the buffer source"
// algorithm (https://heycam.github.io/webidl/#dfn-get-buffer-source-copy). // algorithm (https://heycam.github.io/webidl/#dfn-get-buffer-source-copy).
...@@ -56,7 +57,7 @@ class TextDecoderStream::Transformer final : public TransformStreamTransformer { ...@@ -56,7 +57,7 @@ class TextDecoderStream::Transformer final : public TransformStreamTransformer {
uint32_t length = view->byteLength(); uint32_t length = view->byteLength();
DecodeAndEnqueue(start, length, WTF::FlushBehavior::kDoNotFlush, DecodeAndEnqueue(start, length, WTF::FlushBehavior::kDoNotFlush,
controller, exception_state); controller, exception_state);
return; return ScriptPromise::CastUndefined(script_state_);
} }
DCHECK(bufferSource.IsArrayBuffer()); DCHECK(bufferSource.IsArrayBuffer());
const auto* array_buffer = bufferSource.GetAsArrayBuffer(); const auto* array_buffer = bufferSource.GetAsArrayBuffer();
...@@ -64,13 +65,17 @@ class TextDecoderStream::Transformer final : public TransformStreamTransformer { ...@@ -64,13 +65,17 @@ class TextDecoderStream::Transformer final : public TransformStreamTransformer {
uint32_t length = array_buffer->ByteLength(); uint32_t length = array_buffer->ByteLength();
DecodeAndEnqueue(start, length, WTF::FlushBehavior::kDoNotFlush, controller, DecodeAndEnqueue(start, length, WTF::FlushBehavior::kDoNotFlush, controller,
exception_state); exception_state);
return ScriptPromise::CastUndefined(script_state_);
} }
// Implements the "encode and flush" algorithm. // Implements the "encode and flush" algorithm.
void Flush(TransformStreamDefaultControllerInterface* controller, ScriptPromise Flush(TransformStreamDefaultControllerInterface* controller,
ExceptionState& exception_state) override { ExceptionState& exception_state) override {
DecodeAndEnqueue(nullptr, 0u, WTF::FlushBehavior::kDataEOF, controller, DecodeAndEnqueue(nullptr, 0u, WTF::FlushBehavior::kDataEOF, controller,
exception_state); exception_state);
return ScriptPromise::CastUndefined(script_state_);
} }
ScriptState* GetScriptState() override { return script_state_; } ScriptState* GetScriptState() override { return script_state_; }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/optional.h" #include "base/optional.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_string_resource.h" #include "third_party/blink/renderer/bindings/core/v8/v8_string_resource.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"
#include "third_party/blink/renderer/core/streams/transform_stream_transformer.h" #include "third_party/blink/renderer/core/streams/transform_stream_transformer.h"
...@@ -34,15 +35,15 @@ class TextEncoderStream::Transformer final : public TransformStreamTransformer { ...@@ -34,15 +35,15 @@ class TextEncoderStream::Transformer final : public TransformStreamTransformer {
// Implements the "encode and enqueue a chunk" algorithm. For efficiency, only // Implements the "encode and enqueue a chunk" algorithm. For efficiency, only
// the characters at the end of chunks are special-cased. // the characters at the end of chunks are special-cased.
void Transform(v8::Local<v8::Value> chunk, ScriptPromise Transform(v8::Local<v8::Value> chunk,
TransformStreamDefaultControllerInterface* controller, TransformStreamDefaultControllerInterface* controller,
ExceptionState& exception_state) override { ExceptionState& exception_state) override {
V8StringResource<> input_resource = chunk; V8StringResource<> input_resource = chunk;
if (!input_resource.Prepare(script_state_->GetIsolate(), exception_state)) if (!input_resource.Prepare(script_state_->GetIsolate(), exception_state))
return; return ScriptPromise();
const String input = input_resource; const String input = input_resource;
if (input.IsEmpty()) if (input.IsEmpty())
return; return ScriptPromise::CastUndefined(script_state_);
const base::Optional<UChar> high_surrogate = pending_high_surrogate_; const base::Optional<UChar> high_surrogate = pending_high_surrogate_;
pending_high_surrogate_ = base::nullopt; pending_high_surrogate_ = base::nullopt;
...@@ -60,19 +61,21 @@ class TextEncoderStream::Transformer final : public TransformStreamTransformer { ...@@ -60,19 +61,21 @@ class TextEncoderStream::Transformer final : public TransformStreamTransformer {
bool have_output = bool have_output =
Encode16BitString(input, high_surrogate, &prefix, &result); Encode16BitString(input, high_surrogate, &prefix, &result);
if (!have_output) if (!have_output)
return; return ScriptPromise::CastUndefined(script_state_);
} }
DOMUint8Array* array = DOMUint8Array* array =
CreateDOMUint8ArrayFromTwoStdStringsConcatenated(prefix, result); CreateDOMUint8ArrayFromTwoStdStringsConcatenated(prefix, result);
controller->Enqueue(ToV8(array, script_state_), exception_state); controller->Enqueue(ToV8(array, script_state_), exception_state);
return ScriptPromise::CastUndefined(script_state_);
} }
// Implements the "encode and flush" algorithm. // Implements the "encode and flush" algorithm.
void Flush(TransformStreamDefaultControllerInterface* controller, ScriptPromise Flush(TransformStreamDefaultControllerInterface* controller,
ExceptionState& exception_state) override { ExceptionState& exception_state) override {
if (!pending_high_surrogate_.has_value()) if (!pending_high_surrogate_.has_value())
return; return ScriptPromise::CastUndefined(script_state_);
const std::string replacement_character = ReplacementCharacterInUtf8(); const std::string replacement_character = ReplacementCharacterInUtf8();
const uint8_t* u8buffer = const uint8_t* u8buffer =
...@@ -82,6 +85,8 @@ class TextEncoderStream::Transformer final : public TransformStreamTransformer { ...@@ -82,6 +85,8 @@ class TextEncoderStream::Transformer final : public TransformStreamTransformer {
replacement_character.length())), replacement_character.length())),
script_state_), script_state_),
exception_state); exception_state);
return ScriptPromise::CastUndefined(script_state_);
} }
ScriptState* GetScriptState() override { return script_state_; } ScriptState* GetScriptState() override { return script_state_; }
......
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