summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/streams
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-13 16:23:34 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-14 10:37:21 +0000
commit38a9a29f4f9436cace7f0e7abf9c586057df8a4e (patch)
treec4e8c458dc595bc0ddb435708fa2229edfd00bd4 /chromium/third_party/blink/renderer/core/streams
parente684a3455bcc29a6e3e66a004e352dea4e1141e7 (diff)
downloadqtwebengine-chromium-38a9a29f4f9436cace7f0e7abf9c586057df8a4e.tar.gz
BASELINE: Update Chromium to 73.0.3683.37
Change-Id: I08c9af2948b645f671e5d933aca1f7a90ea372f2 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/core/streams')
-rw-r--r--chromium/third_party/blink/renderer/core/streams/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/streams/CommonOperations.js15
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream.cc116
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream.h11
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream_test.cc50
-rw-r--r--chromium/third_party/blink/renderer/core/streams/underlying_source_base.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream.cc210
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream.h57
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.cc230
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.h88
12 files changed, 514 insertions, 347 deletions
diff --git a/chromium/third_party/blink/renderer/core/streams/BUILD.gn b/chromium/third_party/blink/renderer/core/streams/BUILD.gn
index 4ddb512fda8..1e82808c34a 100644
--- a/chromium/third_party/blink/renderer/core/streams/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/streams/BUILD.gn
@@ -22,5 +22,7 @@ blink_core_sources("streams") {
"underlying_source_base.h",
"writable_stream.cc",
"writable_stream.h",
+ "writable_stream_wrapper.cc",
+ "writable_stream_wrapper.h",
]
}
diff --git a/chromium/third_party/blink/renderer/core/streams/CommonOperations.js b/chromium/third_party/blink/renderer/core/streams/CommonOperations.js
index 266850799a4..9423a115435 100644
--- a/chromium/third_party/blink/renderer/core/streams/CommonOperations.js
+++ b/chromium/third_party/blink/renderer/core/streams/CommonOperations.js
@@ -310,7 +310,7 @@
function isATypeError(object) {
// There doesn't appear to be a 100% reliable way to identify a TypeError
// from JS.
- return getPrototypeOf(object) === TypeError_prototype;
+ return object !== null && getPrototypeOf(object) === TypeError_prototype;
}
function isADOMException(object) {
@@ -329,6 +329,7 @@
switch (typeof reason) {
case 'string':
case 'number':
+ case 'boolean':
return {encoder: 'json', string: JSON_stringify(reason)};
case 'object':
@@ -477,20 +478,17 @@
const {type, value} = callFunction(binding.MessageEvent_data_get, evt);
// assert(type === kChunk || type === kClose || type === kAbort ||
// type=kError);
+ if (finished) {
+ return;
+ }
switch (type) {
case kChunk:
- if (finished) {
- return;
- }
binding.ReadableStreamDefaultControllerEnqueue(controller, value);
resolvePromise(backpressurePromise);
backpressurePromise = v8.createPromise();
break;
case kClose:
- if (finished) {
- return;
- }
finished = true;
binding.ReadableStreamDefaultControllerClose(controller);
callFunction(binding.MessagePort_close, port);
@@ -498,9 +496,6 @@
case kAbort:
case kError:
- if (finished) {
- return;
- }
finished = true;
binding.ReadableStreamDefaultControllerError(
controller, unpackReason(value));
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream.cc
index f71fefdabc0..1d4e81ad22e 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_writable_stream.h"
#include "third_party/blink/renderer/core/streams/readable_stream_operations.h"
#include "third_party/blink/renderer/core/streams/retain_wrapper_during_construction.h"
+#include "third_party/blink/renderer/core/streams/writable_stream_wrapper.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
@@ -240,6 +241,7 @@ ScriptValue ReadableStream::pipeThrough(ScriptState* script_state,
exception_state);
}
+// https://streams.spec.whatwg.org/#rs-pipe-through
ScriptValue ReadableStream::pipeThrough(ScriptState* script_state,
ScriptValue transform_stream,
ScriptValue options,
@@ -247,57 +249,100 @@ ScriptValue ReadableStream::pipeThrough(ScriptState* script_state,
v8::Local<v8::Value> pair_value = transform_stream.V8Value();
v8::Local<v8::Context> context = script_state->GetContext();
- constexpr char kWritableIsUndefined[] =
- "Failed to execute 'pipeThrough' on 'ReadableStream': "
- "parameter 1's 'writable' property is undefined.";
- constexpr char kReadableIsUndefined[] =
- "Failed to execute 'pipeThrough' on 'ReadableStream': "
- "parameter 1's 'readable' property is undefined.";
+ constexpr char kWritableIsNotWritableStream[] =
+ "parameter 1's 'writable' property is not a WritableStream.";
+ constexpr char kReadableIsNotReadableStream[] =
+ "parameter 1's 'readable' property is not a ReadableStream.";
+ constexpr char kWritableIsLocked[] = "parameter 1's 'writable' is locked.";
v8::Local<v8::Object> pair;
if (!pair_value->ToObject(context).ToLocal(&pair)) {
- exception_state.ThrowTypeError(kWritableIsUndefined);
+ exception_state.ThrowTypeError(kWritableIsNotWritableStream);
return ScriptValue();
}
- v8::TryCatch block(script_state->GetIsolate());
+ v8::Isolate* isolate = script_state->GetIsolate();
v8::Local<v8::Value> writable, readable;
- if (!pair->Get(context, V8String(script_state->GetIsolate(), "writable"))
- .ToLocal(&writable)) {
- exception_state.RethrowV8Exception(block.Exception());
+ {
+ v8::TryCatch block(isolate);
+ if (!pair->Get(context, V8String(isolate, "writable")).ToLocal(&writable)) {
+ exception_state.RethrowV8Exception(block.Exception());
+ return ScriptValue();
+ }
+ DCHECK(!block.HasCaught());
+
+ if (!pair->Get(context, V8String(isolate, "readable")).ToLocal(&readable)) {
+ exception_state.RethrowV8Exception(block.Exception());
+ return ScriptValue();
+ }
+ DCHECK(!block.HasCaught());
+ }
+
+ // 2. If ! IsWritableStream(_writable_) is *false*, throw a *TypeError*
+ // exception.
+ WritableStream* dom_writable =
+ V8WritableStream::ToImplWithTypeCheck(isolate, writable);
+ if (!dom_writable) {
+ exception_state.ThrowTypeError(kWritableIsNotWritableStream);
return ScriptValue();
}
- DCHECK(!block.HasCaught());
- if (writable->IsUndefined()) {
- exception_state.ThrowTypeError(kWritableIsUndefined);
+ // 3. If ! IsReadableStream(_readable_) is *false*, throw a *TypeError*
+ // exception.
+ if (!V8ReadableStream::HasInstance(readable, isolate)) {
+ exception_state.ThrowTypeError(kReadableIsNotReadableStream);
return ScriptValue();
}
- if (!pair->Get(context, V8String(script_state->GetIsolate(), "readable"))
- .ToLocal(&readable)) {
- exception_state.RethrowV8Exception(block.Exception());
+ // TODO(ricea): When aborting pipes is supported, implement step 5:
+ // 5. If _signal_ is not *undefined*, and _signal_ is not an instance of the
+ // `AbortSignal` interface, throw a *TypeError* exception.
+
+ // 6. If ! IsReadableStreamLocked(*this*) is *true*, throw a *TypeError*
+ // exception.
+ if (IsLocked(script_state, exception_state).value_or(false)) {
+ exception_state.ThrowTypeError("Cannot pipe a locked stream");
+ return ScriptValue();
+ }
+ if (exception_state.HadException()) {
return ScriptValue();
}
- DCHECK(!block.HasCaught());
- if (readable->IsUndefined()) {
- exception_state.ThrowTypeError(kReadableIsUndefined);
+ // 7. If ! IsWritableStreamLocked(_writable_) is *true*, throw a *TypeError*
+ // exception.
+ if (dom_writable->IsLocked(script_state, exception_state).value_or(false)) {
+ exception_state.ThrowTypeError(kWritableIsLocked);
return ScriptValue();
}
+ if (exception_state.HadException()) {
+ return ScriptValue();
+ }
+
+ // This cast is safe because the following code will only be run when the
+ // native version of WritableStream is not in use.
+ // TODO(ricea): Add a CHECK() for the feature flag here.
+ WritableStreamWrapper* writable_wrapper =
+ static_cast<WritableStreamWrapper*>(dom_writable);
+
+ // 8. Let _promise_ be ! ReadableStreamPipeTo(*this*, _writable_,
+ // _preventClose_, _preventAbort_, _preventCancel_,
+ // _signal_).
- ScriptPromise promise =
- pipeTo(script_state, ScriptValue(script_state, writable), options,
- exception_state);
- if (!exception_state.HadException()) {
- // set promise.[[PromiseIsHandled]] to true.
- // We don't have a primitive to do this, so let's attach a catch handler.
- //
- // ScriptPromise::Then(f, g) is a confusing interface, it is actually
- // |promise.then(f).catch(g)|.
- promise.Then(v8::Local<v8::Function>(),
- NoopFunction::CreateFunction(script_state));
+ // TODO(ricea): Maybe change the parameters to
+ // ReadableStreamOperations::PipeTo to match ReadableStreamPipeTo() in the
+ // standard?
+ ScriptPromise promise = ReadableStreamOperations::PipeTo(
+ script_state, GetInternalStream(script_state),
+ writable_wrapper->GetInternalStream(script_state), options,
+ exception_state);
+ if (exception_state.HadException()) {
+ return ScriptValue();
}
+
+ // 9. Set _promise_.[[PromiseIsHandled]] to *true*.
+ promise.MarkAsHandled();
+
+ // 10. Return _readable_.
return ScriptValue(script_state, readable);
}
@@ -336,9 +381,16 @@ ScriptPromise ReadableStream::pipeTo(ScriptState* script_state,
if (exception_state.HadException())
return ScriptPromise();
+ // This cast is safe because the following code will only be run when the
+ // native version of WritableStream is not in use.
+ // TODO(ricea): Add a CHECK() for the feature flag here.
+ WritableStreamWrapper* destination_wrapper =
+ static_cast<WritableStreamWrapper*>(destination);
+
return ReadableStreamOperations::PipeTo(
script_state, GetInternalStream(script_state),
- destination->GetInternalStream(script_state), options, exception_state);
+ destination_wrapper->GetInternalStream(script_state), options,
+ exception_state);
}
ScriptValue ReadableStream::tee(ScriptState* script_state,
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc
index 8ad8e81b3b4..840c87f185b 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc
@@ -34,14 +34,15 @@ class ReadableStreamOperationsTestNotReached : public ScriptFunction {
public:
static v8::Local<v8::Function> CreateFunction(ScriptState* script_state) {
ReadableStreamOperationsTestNotReached* self =
- new ReadableStreamOperationsTestNotReached(script_state);
+ MakeGarbageCollected<ReadableStreamOperationsTestNotReached>(
+ script_state);
return self->BindToV8Function();
}
- private:
explicit ReadableStreamOperationsTestNotReached(ScriptState* script_state)
: ScriptFunction(script_state) {}
+ private:
ScriptValue Call(ScriptValue) override;
};
@@ -67,7 +68,8 @@ class Iteration final : public GarbageCollectedFinalized<Iteration> {
is_valid_ = false;
return;
}
- value_ = ToCoreString(value->ToString(v.GetScriptState()->GetIsolate()));
+ value_ = ToCoreString(
+ value->ToString(v.GetScriptState()->GetContext()).ToLocalChecked());
}
bool IsSet() const { return is_set_; }
@@ -88,19 +90,20 @@ class ReaderFunction : public ScriptFunction {
public:
static v8::Local<v8::Function> CreateFunction(ScriptState* script_state,
Iteration* iteration) {
- ReaderFunction* self = new ReaderFunction(script_state, iteration);
+ ReaderFunction* self =
+ MakeGarbageCollected<ReaderFunction>(script_state, iteration);
return self->BindToV8Function();
}
+ ReaderFunction(ScriptState* script_state, Iteration* iteration)
+ : ScriptFunction(script_state), iteration_(iteration) {}
+
void Trace(blink::Visitor* visitor) override {
visitor->Trace(iteration_);
ScriptFunction::Trace(visitor);
}
private:
- ReaderFunction(ScriptState* script_state, Iteration* iteration)
- : ScriptFunction(script_state), iteration_(iteration) {}
-
ScriptValue Call(ScriptValue value) override {
iteration_->Set(value);
return value;
@@ -244,8 +247,8 @@ TEST(ReadableStreamOperationsTest, Read) {
scope.GetScriptState(), reader, ASSERT_NO_EXCEPTION)
.value_or(false));
- Iteration* it1 = new Iteration();
- Iteration* it2 = new Iteration();
+ Iteration* it1 = MakeGarbageCollected<Iteration>();
+ Iteration* it2 = MakeGarbageCollected<Iteration>();
ReadableStreamOperations::DefaultReaderRead(scope.GetScriptState(), reader)
.Then(ReaderFunction::CreateFunction(scope.GetScriptState(), it1),
ReadableStreamOperationsTestNotReached::CreateFunction(
@@ -283,7 +286,8 @@ TEST(ReadableStreamOperationsTest,
CreateReadableStreamWithCustomUnderlyingSourceAndStrategy) {
V8TestingScope scope;
TryCatchScope try_catch_scope(scope.GetIsolate());
- auto* underlying_source = new TestUnderlyingSource(scope.GetScriptState());
+ auto* underlying_source =
+ MakeGarbageCollected<TestUnderlyingSource>(scope.GetScriptState());
ScriptValue strategy = ReadableStreamOperations::CreateCountQueuingStrategy(
scope.GetScriptState(), 10);
@@ -306,9 +310,9 @@ TEST(ReadableStreamOperationsTest,
ASSERT_NO_EXCEPTION);
ASSERT_FALSE(reader.IsEmpty());
- Iteration* it1 = new Iteration();
- Iteration* it2 = new Iteration();
- Iteration* it3 = new Iteration();
+ Iteration* it1 = MakeGarbageCollected<Iteration>();
+ Iteration* it2 = MakeGarbageCollected<Iteration>();
+ Iteration* it3 = MakeGarbageCollected<Iteration>();
ReadableStreamOperations::DefaultReaderRead(scope.GetScriptState(), reader)
.Then(ReaderFunction::CreateFunction(scope.GetScriptState(), it1),
ReadableStreamOperationsTestNotReached::CreateFunction(
@@ -350,7 +354,8 @@ TEST(ReadableStreamOperationsTest,
UnderlyingSourceShouldHavePendingActivityWhenLockedAndControllerIsActive) {
V8TestingScope scope;
TryCatchScope try_catch_scope(scope.GetIsolate());
- auto* underlying_source = new TestUnderlyingSource(scope.GetScriptState());
+ auto* underlying_source =
+ MakeGarbageCollected<TestUnderlyingSource>(scope.GetScriptState());
ScriptValue strategy = ReadableStreamOperations::CreateCountQueuingStrategy(
scope.GetScriptState(), 10);
@@ -545,8 +550,8 @@ TEST(ReadableStreamOperationsTest, Tee) {
ASSERT_FALSE(reader1.IsEmpty());
ASSERT_FALSE(reader2.IsEmpty());
- Iteration* it1 = new Iteration();
- Iteration* it2 = new Iteration();
+ Iteration* it1 = MakeGarbageCollected<Iteration>();
+ Iteration* it2 = MakeGarbageCollected<Iteration>();
ReadableStreamOperations::DefaultReaderRead(scope.GetScriptState(), reader1)
.Then(ReaderFunction::CreateFunction(scope.GetScriptState(), it1),
ReadableStreamOperationsTestNotReached::CreateFunction(
@@ -600,7 +605,7 @@ TEST(ReadableStreamOperationsTest, Serialize) {
ScriptValue reader = ReadableStreamOperations::GetReader(
scope.GetScriptState(), transferred, ASSERT_NO_EXCEPTION);
ASSERT_FALSE(reader.IsEmpty());
- Iteration* it = new Iteration();
+ Iteration* it = MakeGarbageCollected<Iteration>();
ReadableStreamOperations::DefaultReaderRead(scope.GetScriptState(), reader)
.Then(ReaderFunction::CreateFunction(scope.GetScriptState(), it),
ReadableStreamOperationsTestNotReached::CreateFunction(
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream.cc b/chromium/third_party/blink/renderer/core/streams/transform_stream.cc
index 066821136b1..77f74ea721d 100644
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream.cc
+++ b/chromium/third_party/blink/renderer/core/streams/transform_stream.cc
@@ -12,7 +12,7 @@
#include "third_party/blink/renderer/core/streams/readable_stream.h"
#include "third_party/blink/renderer/core/streams/transform_stream_default_controller.h"
#include "third_party/blink/renderer/core/streams/transform_stream_transformer.h"
-#include "third_party/blink/renderer/core/streams/writable_stream.h"
+#include "third_party/blink/renderer/core/streams/writable_stream_wrapper.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
@@ -30,16 +30,11 @@ class TransformStream::Algorithm : public ScriptFunction {
static v8::Local<v8::Function> Create(TransformStreamTransformer* transformer,
ScriptState* script_state,
ExceptionState& exception_state) {
- auto* algorithm = new T(transformer, script_state, exception_state);
+ auto* algorithm =
+ MakeGarbageCollected<T>(transformer, script_state, exception_state);
return algorithm->BindToV8Function();
}
- void Trace(Visitor* visitor) override {
- visitor->Trace(transformer_);
- ScriptFunction::Trace(visitor);
- }
-
- protected:
Algorithm(TransformStreamTransformer* transformer,
ScriptState* script_state,
ExceptionState& exception_state)
@@ -48,6 +43,12 @@ class TransformStream::Algorithm : public ScriptFunction {
interface_name_(exception_state.InterfaceName()),
property_name_(exception_state.PropertyName()) {}
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(transformer_);
+ ScriptFunction::Trace(visitor);
+ }
+
+ protected:
// AlgorithmScope holds the stack-allocated objects used by the CallRaw()
// methods for FlushAlgorithm and TransformAlgorithm.
class AlgorithmScope {
@@ -122,6 +123,9 @@ class TransformStream::TransformAlgorithm : public TransformStream::Algorithm {
};
TransformStream::TransformStream() = default;
+TransformStream::TransformStream(ReadableStream* readable,
+ WritableStream* writable)
+ : readable_(readable), writable_(writable) {}
TransformStream::~TransformStream() = default;
@@ -174,8 +178,10 @@ TransformStream* TransformStream::Create(ScriptState* script_state,
}
}
DCHECK(stream->IsObject());
- ts->InitInternal(script_state, stream.As<v8::Object>(), exception_state);
- return ts->stream_.IsEmpty() ? nullptr : ts;
+ if (!ts->InitInternal(script_state, stream.As<v8::Object>(), exception_state))
+ return nullptr;
+
+ return ts;
}
void TransformStream::Init(TransformStreamTransformer* transformer,
@@ -202,13 +208,12 @@ void TransformStream::Init(TransformStreamTransformer* transformer,
}
void TransformStream::Trace(Visitor* visitor) {
- visitor->Trace(stream_);
visitor->Trace(readable_);
visitor->Trace(writable_);
ScriptWrappable::Trace(visitor);
}
-void TransformStream::InitInternal(ScriptState* script_state,
+bool TransformStream::InitInternal(ScriptState* script_state,
v8::Local<v8::Object> stream,
ExceptionState& exception_state) {
v8::Local<v8::Value> readable, writable;
@@ -218,13 +223,13 @@ void TransformStream::InitInternal(ScriptState* script_state,
args)
.ToLocal(&readable)) {
exception_state.RethrowV8Exception(block.Exception());
- return;
+ return false;
}
if (!V8ScriptRunner::CallExtra(script_state, "getTransformStreamWritable",
args)
.ToLocal(&writable)) {
exception_state.RethrowV8Exception(block.Exception());
- return;
+ return false;
}
DCHECK(readable->IsObject());
@@ -232,16 +237,16 @@ void TransformStream::InitInternal(ScriptState* script_state,
script_state, readable.As<v8::Object>(), exception_state);
if (!readable_)
- return;
+ return false;
DCHECK(writable->IsObject());
- writable_ = WritableStream::CreateFromInternalStream(
+ writable_ = WritableStreamWrapper::CreateFromInternalStream(
script_state, writable.As<v8::Object>(), exception_state);
if (!writable_)
- return;
+ return false;
- stream_.Set(script_state->GetIsolate(), stream);
+ return true;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream.h b/chromium/third_party/blink/renderer/core/streams/transform_stream.h
index 45149039855..602a383c707 100644
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream.h
+++ b/chromium/third_party/blink/renderer/core/streams/transform_stream.h
@@ -29,7 +29,8 @@ class WritableStream;
// defined in C++. Provides access to the readable and writable streams.
//
// On-heap references to this class must always be via a TraceWrapperMember, and
-// must always have an ancestor in the V8 heap, or |stream_| will be lost.
+// must always have an ancestor in the V8 heap, or the internal JavaScript
+// objects owned by |readable_| and |writable_| will be lost.
//
// To ensure that the JS TransformStream is always referenced, this class uses
// two-stage construction. After calling the constructor, store the reference
@@ -40,6 +41,11 @@ class CORE_EXPORT TransformStream final : public ScriptWrappable {
public:
TransformStream();
+
+ // This constructor produces a TransformStream from an existing {readable,
+ // writable} pair. It cannot fail and does not require calling Init().
+ TransformStream(ReadableStream*, WritableStream*);
+
~TransformStream() override;
// |Create| functions internally call Init().
@@ -76,11 +82,10 @@ class CORE_EXPORT TransformStream final : public ScriptWrappable {
class FlushAlgorithm;
class TransformAlgorithm;
- void InitInternal(ScriptState*,
+ bool InitInternal(ScriptState*,
v8::Local<v8::Object> stream,
ExceptionState&);
- TraceWrapperV8Reference<v8::Value> stream_;
TraceWrapperMember<ReadableStream> readable_;
TraceWrapperMember<WritableStream> writable_;
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream_test.cc b/chromium/third_party/blink/renderer/core/streams/transform_stream_test.cc
index 26d78b97e3b..abeaa2f815b 100644
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream_test.cc
+++ b/chromium/third_party/blink/renderer/core/streams/transform_stream_test.cc
@@ -45,7 +45,7 @@ class TransformStreamTest : public ::testing::Test {
void Init(TransformStreamTransformer* transformer,
ScriptState* script_state,
ExceptionState& exception_state) {
- holder_ = new Holder(script_state);
+ holder_ = MakeGarbageCollected<Holder>(script_state);
holder_->Stream()->Init(transformer, script_state, exception_state);
}
@@ -135,13 +135,15 @@ class MockTransformStreamTransformer : public TransformStreamTransformer {
// If this doesn't work then nothing else will.
TEST_F(TransformStreamTest, Construct) {
V8TestingScope scope;
- Init(new IdentityTransformer(), scope.GetScriptState(), ASSERT_NO_EXCEPTION);
+ Init(MakeGarbageCollected<IdentityTransformer>(), scope.GetScriptState(),
+ ASSERT_NO_EXCEPTION);
EXPECT_TRUE(Stream());
}
TEST_F(TransformStreamTest, Accessors) {
V8TestingScope scope;
- Init(new IdentityTransformer(), scope.GetScriptState(), ASSERT_NO_EXCEPTION);
+ Init(MakeGarbageCollected<IdentityTransformer>(), scope.GetScriptState(),
+ ASSERT_NO_EXCEPTION);
ReadableStream* readable = Stream()->Readable();
WritableStream* writable = Stream()->Writable();
EXPECT_TRUE(readable);
@@ -150,7 +152,7 @@ TEST_F(TransformStreamTest, Accessors) {
TEST_F(TransformStreamTest, TransformIsCalled) {
V8TestingScope scope;
- auto* mock = new ::testing::StrictMock<MockTransformStreamTransformer>();
+ auto* mock = MakeGarbageCollected<MockTransformStreamTransformer>();
Init(mock, scope.GetScriptState(), ASSERT_NO_EXCEPTION);
// Need to run microtasks so the startAlgorithm promise resolves.
v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
@@ -170,7 +172,7 @@ TEST_F(TransformStreamTest, TransformIsCalled) {
TEST_F(TransformStreamTest, FlushIsCalled) {
V8TestingScope scope;
- auto* mock = new ::testing::StrictMock<MockTransformStreamTransformer>();
+ auto* mock = MakeGarbageCollected<MockTransformStreamTransformer>();
Init(mock, scope.GetScriptState(), ASSERT_NO_EXCEPTION);
// Need to run microtasks so the startAlgorithm promise resolves.
v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
@@ -189,14 +191,14 @@ TEST_F(TransformStreamTest, FlushIsCalled) {
class ExpectNotReached : public ScriptFunction {
public:
static v8::Local<v8::Function> Create(ScriptState* script_state) {
- auto* self = new ExpectNotReached(script_state);
+ auto* self = MakeGarbageCollected<ExpectNotReached>(script_state);
return self->BindToV8Function();
}
- private:
explicit ExpectNotReached(ScriptState* script_state)
: ScriptFunction(script_state) {}
+ private:
ScriptValue Call(ScriptValue) override {
ADD_FAILURE() << "ExpectNotReached was reached";
return ScriptValue();
@@ -210,16 +212,17 @@ class ExpectChunkIsString : public ScriptFunction {
static v8::Local<v8::Function> Create(ScriptState* script_state,
const String& expected,
bool* called) {
- auto* self = new ExpectChunkIsString(script_state, expected, called);
+ auto* self = MakeGarbageCollected<ExpectChunkIsString>(script_state,
+ expected, called);
return self->BindToV8Function();
}
- private:
ExpectChunkIsString(ScriptState* script_state,
const String& expected,
bool* called)
: ScriptFunction(script_state), expected_(expected), called_(called) {}
+ private:
ScriptValue Call(ScriptValue value) override {
*called_ = true;
if (!value.IsObject()) {
@@ -248,16 +251,17 @@ class ExpectTypeError : public ScriptFunction {
static v8::Local<v8::Function> Create(ScriptState* script_state,
const String& message,
bool* called) {
- auto* self = new ExpectTypeError(script_state, message, called);
+ auto* self =
+ MakeGarbageCollected<ExpectTypeError>(script_state, message, called);
return self->BindToV8Function();
}
- private:
ExpectTypeError(ScriptState* script_state,
const String& message,
bool* called)
: ScriptFunction(script_state), message_(message), called_(called) {}
+ private:
ScriptValue Call(ScriptValue value) override {
*called_ = true;
EXPECT_TRUE(IsTypeError(GetScriptState(), value, message_));
@@ -298,7 +302,8 @@ class ExpectTypeError : public ScriptFunction {
TEST_F(TransformStreamTest, EnqueueFromTransform) {
V8TestingScope scope;
auto* script_state = scope.GetScriptState();
- Init(new IdentityTransformer(), script_state, ASSERT_NO_EXCEPTION);
+ Init(MakeGarbageCollected<IdentityTransformer>(), script_state,
+ ASSERT_NO_EXCEPTION);
CopyReadableAndWritableToGlobal(scope);
@@ -337,8 +342,8 @@ TEST_F(TransformStreamTest, EnqueueFromFlush) {
};
V8TestingScope scope;
auto* script_state = scope.GetScriptState();
- Init(new EnqueueFromFlushTransformer(scope.GetContext()->Global(),
- scope.GetIsolate()),
+ Init(MakeGarbageCollected<EnqueueFromFlushTransformer>(
+ scope.GetContext()->Global(), scope.GetIsolate()),
script_state, ASSERT_NO_EXCEPTION);
CopyReadableAndWritableToGlobal(scope);
@@ -370,7 +375,8 @@ TEST_F(TransformStreamTest, ThrowFromTransform) {
};
V8TestingScope scope;
auto* script_state = scope.GetScriptState();
- Init(new ThrowFromTransformTransformer(), script_state, ASSERT_NO_EXCEPTION);
+ Init(MakeGarbageCollected<ThrowFromTransformTransformer>(), script_state,
+ ASSERT_NO_EXCEPTION);
CopyReadableAndWritableToGlobal(scope);
@@ -410,7 +416,8 @@ TEST_F(TransformStreamTest, ThrowFromFlush) {
};
V8TestingScope scope;
auto* script_state = scope.GetScriptState();
- Init(new ThrowFromFlushTransformer(), script_state, ASSERT_NO_EXCEPTION);
+ Init(MakeGarbageCollected<ThrowFromFlushTransformer>(), script_state,
+ ASSERT_NO_EXCEPTION);
CopyReadableAndWritableToGlobal(scope);
@@ -436,5 +443,16 @@ TEST_F(TransformStreamTest, ThrowFromFlush) {
EXPECT_TRUE(writableTypeErrorThrown);
}
+TEST_F(TransformStreamTest, CreateFromReadableWritablePair) {
+ V8TestingScope scope;
+ ReadableStream* readable =
+ ReadableStream::Create(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
+ WritableStream* writable =
+ WritableStream::Create(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
+ TransformStream transform(readable, writable);
+ EXPECT_EQ(readable, transform.Readable());
+ EXPECT_EQ(writable, transform.Writable());
+}
+
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/underlying_source_base.idl b/chromium/third_party/blink/renderer/core/streams/underlying_source_base.idl
index 8e61f0aac31..d943658bcc2 100644
--- a/chromium/third_party/blink/renderer/core/streams/underlying_source_base.idl
+++ b/chromium/third_party/blink/renderer/core/streams/underlying_source_base.idl
@@ -14,7 +14,7 @@
interface UnderlyingSourceBase {
[CallWith=ScriptState, ImplementedAs=startWrapper] Promise<void> start(any stream);
[CallWith=ScriptState] Promise<void> pull();
- [CallWith=ScriptState, ImplementedAs=cancelWrapper] Promise<void> cancel([Default=Undefined] optional any reason);
+ [CallWith=ScriptState, ImplementedAs=cancelWrapper] Promise<void> cancel([DefaultValue=Undefined] optional any reason);
// This only exists to prevent Object.prototype.type being accessed.
[CallWith=ScriptState] readonly attribute any type;
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream.cc b/chromium/third_party/blink/renderer/core/streams/writable_stream.cc
index 26ea2b2dd08..292fda8738c 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream.cc
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream.cc
@@ -8,32 +8,13 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_writable_stream.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/core/streams/retain_wrapper_during_construction.h"
+#include "third_party/blink/renderer/core/streams/writable_stream_wrapper.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
-void WritableStream::Init(ScriptState* script_state,
- ScriptValue underlying_sink,
- ScriptValue strategy,
- ExceptionState& exception_state) {
- v8::Local<v8::Object> internal_stream;
- v8::TryCatch block(script_state->GetIsolate());
-
- if (!CreateInternalStream(script_state, underlying_sink.V8Value(),
- strategy.V8Value())
- .ToLocal(&internal_stream)) {
- exception_state.RethrowV8Exception(block.Exception());
- return;
- }
-
- if (!InitInternal(script_state, internal_stream)) {
- exception_state.RethrowV8Exception(block.Exception());
- return;
- }
-}
-
WritableStream* WritableStream::Create(ScriptState* script_state,
ExceptionState& exception_state) {
return Create(
@@ -56,7 +37,8 @@ WritableStream* WritableStream::Create(ScriptState* script_state,
ScriptValue underlying_sink,
ScriptValue strategy,
ExceptionState& exception_state) {
- auto* stream = MakeGarbageCollected<WritableStream>();
+ // TODO(ricea): Switch on Blink feature.
+ auto* stream = MakeGarbageCollected<WritableStreamWrapper>();
stream->Init(script_state, underlying_sink, strategy, exception_state);
if (exception_state.HadException())
return nullptr;
@@ -64,193 +46,13 @@ WritableStream* WritableStream::Create(ScriptState* script_state,
return stream;
}
-WritableStream* WritableStream::CreateFromInternalStream(
- ScriptState* script_state,
- v8::Local<v8::Object> internal_stream,
- ExceptionState& exception_state) {
- v8::TryCatch block(script_state->GetIsolate());
- auto* stream = MakeGarbageCollected<WritableStream>();
- if (!stream->InitInternal(script_state, internal_stream)) {
- exception_state.RethrowV8Exception(block.Exception());
- return nullptr;
- }
- return stream;
-}
-
-bool WritableStream::InitInternal(ScriptState* script_state,
- v8::Local<v8::Object> internal_stream) {
- v8::Isolate* isolate = script_state->GetIsolate();
-
-#if DCHECK_IS_ON()
- v8::Local<v8::Value> args[] = {internal_stream};
- v8::Local<v8::Value> result_value;
-
- if (!V8ScriptRunner::CallExtra(script_state, "IsWritableStream", args)
- .ToLocal(&result_value)) {
- DLOG(FATAL) << "Failing to call IsWritableStream for DCHECK.";
- return false;
- }
- DCHECK(result_value->BooleanValue(isolate));
-#endif // DCHECK_IS_ON()
-
- internal_stream_.Set(isolate, internal_stream);
-
- v8::Local<v8::Value> wrapper = ToV8(this, script_state);
- if (wrapper.IsEmpty())
- return false;
-
- v8::Local<v8::Context> context = script_state->GetContext();
- v8::Local<v8::Object> bindings =
- context->GetExtrasBindingObject().As<v8::Object>();
- v8::Local<v8::Value> symbol_value;
- if (!bindings->Get(context, V8String(isolate, "internalWritableStreamSymbol"))
- .ToLocal(&symbol_value)) {
- return false;
- }
-
- if (wrapper.As<v8::Object>()
- ->Set(context, symbol_value.As<v8::Symbol>(),
- internal_stream_.NewLocal(isolate))
- .IsNothing()) {
- return false;
- }
-
- return RetainWrapperDuringConstruction(this, script_state);
-}
-
-v8::MaybeLocal<v8::Object> WritableStream::CreateInternalStream(
- ScriptState* script_state,
- v8::Local<v8::Value> underlying_sink,
- v8::Local<v8::Value> strategy) {
- v8::Local<v8::Value> args[] = {underlying_sink, strategy};
- v8::Local<v8::Value> stream;
-
- if (!V8ScriptRunner::CallExtra(script_state, "createWritableStream", args)
- .ToLocal(&stream)) {
- return v8::MaybeLocal<v8::Object>();
- }
-
- DCHECK(stream->IsObject());
- return v8::MaybeLocal<v8::Object>(stream.As<v8::Object>());
-}
-
-void WritableStream::Trace(Visitor* visitor) {
- visitor->Trace(internal_stream_);
- ScriptWrappable::Trace(visitor);
-}
-
-bool WritableStream::locked(ScriptState* script_state,
- ExceptionState& exception_state) const {
- auto result = IsLocked(script_state, exception_state);
-
- return !result || *result;
-}
-
-ScriptPromise WritableStream::abort(ScriptState* script_state,
- ExceptionState& exception_state) {
- return abort(
- script_state,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
- exception_state);
-}
-
-ScriptPromise WritableStream::abort(ScriptState* script_state,
- ScriptValue reason,
- ExceptionState& exception_state) {
- if (locked(script_state, exception_state) &&
- !exception_state.HadException()) {
- exception_state.ThrowTypeError("Cannot abort a locked stream");
- }
-
- v8::Local<v8::Value> args[] = {
- internal_stream_.NewLocal(script_state->GetIsolate()), reason.V8Value()};
- v8::TryCatch block(script_state->GetIsolate());
- v8::Local<v8::Value> result;
-
- if (!V8ScriptRunner::CallExtra(script_state, "WritableStreamAbort", args)
- .ToLocal(&result)) {
- exception_state.RethrowV8Exception(block.Exception());
- return ScriptPromise();
- }
- return ScriptPromise(script_state, result);
-}
-
-ScriptValue WritableStream::getWriter(ScriptState* script_state,
- ExceptionState& exception_state) {
- v8::TryCatch block(script_state->GetIsolate());
- v8::Local<v8::Value> args[] = {
- internal_stream_.NewLocal(script_state->GetIsolate())};
- v8::Local<v8::Value> result;
-
- if (!V8ScriptRunner::CallExtra(script_state,
- "AcquireWritableStreamDefaultWriter", args)
- .ToLocal(&result)) {
- exception_state.RethrowV8Exception(block.Exception());
- return ScriptValue();
- }
- return ScriptValue(script_state, result);
-}
-
-base::Optional<bool> WritableStream::IsLocked(
- ScriptState* script_state,
- ExceptionState& exception_state) const {
- v8::TryCatch block(script_state->GetIsolate());
- v8::Local<v8::Value> args[] = {
- internal_stream_.NewLocal(script_state->GetIsolate())};
- v8::Local<v8::Value> result_value;
-
- if (!V8ScriptRunner::CallExtra(script_state, "IsWritableStreamLocked", args)
- .ToLocal(&result_value)) {
- exception_state.RethrowV8Exception(block.Exception());
- return base::nullopt;
- }
- return result_value->BooleanValue(script_state->GetIsolate());
-}
-
-void WritableStream::Serialize(ScriptState* script_state,
- MessagePort* port,
- ExceptionState& exception_state) {
- DCHECK(port);
- DCHECK(RuntimeEnabledFeatures::TransferableStreamsEnabled());
- v8::TryCatch block(script_state->GetIsolate());
- v8::Local<v8::Value> port_v8_value = ToV8(port, script_state);
- DCHECK(!port_v8_value.IsEmpty());
- v8::Local<v8::Value> args[] = {ToV8(this, script_state), port_v8_value};
- V8ScriptRunner::CallExtra(script_state, "WritableStreamSerialize", args);
- if (block.HasCaught()) {
- exception_state.RethrowV8Exception(block.Exception());
- }
-}
-
// static
WritableStream* WritableStream::Deserialize(ScriptState* script_state,
MessagePort* port,
ExceptionState& exception_state) {
- // We need to execute V8 Extras JavaScript to create the new WritableStream.
- // We will not run author code.
- auto* isolate = script_state->GetIsolate();
- v8::Isolate::AllowJavascriptExecutionScope allow_js(isolate);
- DCHECK(port);
- DCHECK(RuntimeEnabledFeatures::TransferableStreamsEnabled());
- v8::TryCatch block(isolate);
- v8::Local<v8::Value> port_v8 = ToV8(port, script_state);
- DCHECK(!port_v8.IsEmpty());
- v8::Local<v8::Value> args[] = {port_v8};
- ScriptValue internal_stream(
- script_state, V8ScriptRunner::CallExtra(
- script_state, "WritableStreamDeserialize", args));
- if (block.HasCaught()) {
- exception_state.RethrowV8Exception(block.Exception());
- return nullptr;
- }
- DCHECK(!internal_stream.IsEmpty());
- return CreateFromInternalStream(script_state, internal_stream,
- exception_state);
-}
-
-ScriptValue WritableStream::GetInternalStream(ScriptState* script_state) const {
- return ScriptValue(script_state,
- internal_stream_.NewLocal(script_state->GetIsolate()));
+ // TODO(ricea): Switch on Blink feature.
+ return WritableStreamWrapper::Deserialize(script_state, port,
+ exception_state);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream.h b/chromium/third_party/blink/renderer/core/streams/writable_stream.h
index c2326c72673..0520505622b 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream.h
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream.h
@@ -22,19 +22,8 @@ class CORE_EXPORT WritableStream : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- // Call one of Init functions before using the instance.
- WritableStream() = default;
- ~WritableStream() override = default;
-
- // If an error happens, |exception_state.HadException()| will be true, and
- // |this| will not be usable after that.
- void Init(ScriptState*,
- ScriptValue underlying_sink,
- ScriptValue strategy,
- ExceptionState& exception_state);
-
- // Create* functions call Init* internally and return null when an error
- // happens.
+ // Create function selects an implementation of WritableStream to use at
+ // runtime.
static WritableStream* Create(ScriptState*, ExceptionState&);
static WritableStream* Create(ScriptState*,
ScriptValue underlying_sink,
@@ -43,33 +32,21 @@ class CORE_EXPORT WritableStream : public ScriptWrappable {
ScriptValue underlying_sink,
ScriptValue strategy,
ExceptionState&);
- static WritableStream* CreateFromInternalStream(
- ScriptState* script_state,
- ScriptValue internal_stream,
- ExceptionState& exception_state) {
- DCHECK(internal_stream.IsObject());
- return CreateFromInternalStream(script_state,
- internal_stream.V8Value().As<v8::Object>(),
- exception_state);
- }
- static WritableStream* CreateFromInternalStream(
- ScriptState*,
- v8::Local<v8::Object> internal_stream,
- ExceptionState&);
-
- void Trace(Visitor* visitor) override;
// IDL defined functions
- bool locked(ScriptState*, ExceptionState&) const;
- ScriptPromise abort(ScriptState*, ExceptionState&);
- ScriptPromise abort(ScriptState*, ScriptValue reason, ExceptionState&);
- ScriptValue getWriter(ScriptState*, ExceptionState&);
+ virtual bool locked(ScriptState*, ExceptionState&) const = 0;
+ virtual ScriptPromise abort(ScriptState*, ExceptionState&) = 0;
+ virtual ScriptPromise abort(ScriptState*,
+ ScriptValue reason,
+ ExceptionState&) = 0;
+ virtual ScriptValue getWriter(ScriptState*, ExceptionState&) = 0;
- base::Optional<bool> IsLocked(ScriptState*, ExceptionState&) const;
+ virtual base::Optional<bool> IsLocked(ScriptState*,
+ ExceptionState&) const = 0;
// Serialize this stream to |port|. The stream will be locked by this
// operation.
- void Serialize(ScriptState*, MessagePort* port, ExceptionState&);
+ virtual void Serialize(ScriptState*, MessagePort* port, ExceptionState&) = 0;
// Given a |port| which is entangled with a MessagePort that was previously
// passed to Serialize(), returns a new WritableStream which behaves like it
@@ -77,18 +54,6 @@ class CORE_EXPORT WritableStream : public ScriptWrappable {
static WritableStream* Deserialize(ScriptState*,
MessagePort* port,
ExceptionState&);
-
- ScriptValue GetInternalStream(ScriptState*) const;
-
- private:
- bool InitInternal(ScriptState*, v8::Local<v8::Object> internal_stream);
-
- static v8::MaybeLocal<v8::Object> CreateInternalStream(
- ScriptState* script_state,
- v8::Local<v8::Value> underlying_sink,
- v8::Local<v8::Value> strategy);
-
- TraceWrapperV8Reference<v8::Object> internal_stream_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.cc b/chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.cc
new file mode 100644
index 00000000000..e8c7bd1d3d2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.cc
@@ -0,0 +1,230 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/streams/writable_stream_wrapper.h"
+
+#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_writable_stream.h"
+#include "third_party/blink/renderer/core/messaging/message_port.h"
+#include "third_party/blink/renderer/core/streams/retain_wrapper_during_construction.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+
+namespace blink {
+
+void WritableStreamWrapper::Init(ScriptState* script_state,
+ ScriptValue underlying_sink,
+ ScriptValue strategy,
+ ExceptionState& exception_state) {
+ v8::Local<v8::Object> internal_stream;
+ v8::TryCatch block(script_state->GetIsolate());
+
+ if (!CreateInternalStream(script_state, underlying_sink.V8Value(),
+ strategy.V8Value())
+ .ToLocal(&internal_stream)) {
+ exception_state.RethrowV8Exception(block.Exception());
+ return;
+ }
+
+ if (!InitInternal(script_state, internal_stream)) {
+ exception_state.RethrowV8Exception(block.Exception());
+ return;
+ }
+}
+
+WritableStreamWrapper* WritableStreamWrapper::CreateFromInternalStream(
+ ScriptState* script_state,
+ v8::Local<v8::Object> internal_stream,
+ ExceptionState& exception_state) {
+ v8::TryCatch block(script_state->GetIsolate());
+ auto* stream = MakeGarbageCollected<WritableStreamWrapper>();
+ if (!stream->InitInternal(script_state, internal_stream)) {
+ exception_state.RethrowV8Exception(block.Exception());
+ return nullptr;
+ }
+ return stream;
+}
+
+bool WritableStreamWrapper::InitInternal(
+ ScriptState* script_state,
+ v8::Local<v8::Object> internal_stream) {
+ v8::Isolate* isolate = script_state->GetIsolate();
+
+#if DCHECK_IS_ON()
+ v8::Local<v8::Value> args[] = {internal_stream};
+ v8::Local<v8::Value> result_value;
+
+ if (!V8ScriptRunner::CallExtra(script_state, "IsWritableStream", args)
+ .ToLocal(&result_value)) {
+ DLOG(FATAL) << "Failing to call IsWritableStream for DCHECK.";
+ return false;
+ }
+ DCHECK(result_value->BooleanValue(isolate));
+#endif // DCHECK_IS_ON()
+
+ internal_stream_.Set(isolate, internal_stream);
+
+ v8::Local<v8::Value> wrapper = ToV8(this, script_state);
+ if (wrapper.IsEmpty())
+ return false;
+
+ v8::Local<v8::Context> context = script_state->GetContext();
+ v8::Local<v8::Object> bindings =
+ context->GetExtrasBindingObject().As<v8::Object>();
+ v8::Local<v8::Value> symbol_value;
+ if (!bindings->Get(context, V8String(isolate, "internalWritableStreamSymbol"))
+ .ToLocal(&symbol_value)) {
+ return false;
+ }
+
+ if (wrapper.As<v8::Object>()
+ ->Set(context, symbol_value.As<v8::Symbol>(),
+ internal_stream_.NewLocal(isolate))
+ .IsNothing()) {
+ return false;
+ }
+
+ return RetainWrapperDuringConstruction(this, script_state);
+}
+
+v8::MaybeLocal<v8::Object> WritableStreamWrapper::CreateInternalStream(
+ ScriptState* script_state,
+ v8::Local<v8::Value> underlying_sink,
+ v8::Local<v8::Value> strategy) {
+ v8::Local<v8::Value> args[] = {underlying_sink, strategy};
+ v8::Local<v8::Value> stream;
+
+ if (!V8ScriptRunner::CallExtra(script_state, "createWritableStream", args)
+ .ToLocal(&stream)) {
+ return v8::MaybeLocal<v8::Object>();
+ }
+
+ DCHECK(stream->IsObject());
+ return v8::MaybeLocal<v8::Object>(stream.As<v8::Object>());
+}
+
+void WritableStreamWrapper::Trace(Visitor* visitor) {
+ visitor->Trace(internal_stream_);
+ ScriptWrappable::Trace(visitor);
+}
+
+bool WritableStreamWrapper::locked(ScriptState* script_state,
+ ExceptionState& exception_state) const {
+ auto result = IsLocked(script_state, exception_state);
+
+ return !result || *result;
+}
+
+ScriptPromise WritableStreamWrapper::abort(ScriptState* script_state,
+ ExceptionState& exception_state) {
+ return abort(
+ script_state,
+ ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
+ exception_state);
+}
+
+ScriptPromise WritableStreamWrapper::abort(ScriptState* script_state,
+ ScriptValue reason,
+ ExceptionState& exception_state) {
+ if (locked(script_state, exception_state) &&
+ !exception_state.HadException()) {
+ exception_state.ThrowTypeError("Cannot abort a locked stream");
+ }
+
+ v8::Local<v8::Value> args[] = {
+ internal_stream_.NewLocal(script_state->GetIsolate()), reason.V8Value()};
+ v8::TryCatch block(script_state->GetIsolate());
+ v8::Local<v8::Value> result;
+
+ if (!V8ScriptRunner::CallExtra(script_state, "WritableStreamAbort", args)
+ .ToLocal(&result)) {
+ exception_state.RethrowV8Exception(block.Exception());
+ return ScriptPromise();
+ }
+ return ScriptPromise(script_state, result);
+}
+
+ScriptValue WritableStreamWrapper::getWriter(ScriptState* script_state,
+ ExceptionState& exception_state) {
+ v8::TryCatch block(script_state->GetIsolate());
+ v8::Local<v8::Value> args[] = {
+ internal_stream_.NewLocal(script_state->GetIsolate())};
+ v8::Local<v8::Value> result;
+
+ if (!V8ScriptRunner::CallExtra(script_state,
+ "AcquireWritableStreamDefaultWriter", args)
+ .ToLocal(&result)) {
+ exception_state.RethrowV8Exception(block.Exception());
+ return ScriptValue();
+ }
+ return ScriptValue(script_state, result);
+}
+
+base::Optional<bool> WritableStreamWrapper::IsLocked(
+ ScriptState* script_state,
+ ExceptionState& exception_state) const {
+ v8::TryCatch block(script_state->GetIsolate());
+ v8::Local<v8::Value> args[] = {
+ internal_stream_.NewLocal(script_state->GetIsolate())};
+ v8::Local<v8::Value> result_value;
+
+ if (!V8ScriptRunner::CallExtra(script_state, "IsWritableStreamLocked", args)
+ .ToLocal(&result_value)) {
+ exception_state.RethrowV8Exception(block.Exception());
+ return base::nullopt;
+ }
+ return result_value->BooleanValue(script_state->GetIsolate());
+}
+
+void WritableStreamWrapper::Serialize(ScriptState* script_state,
+ MessagePort* port,
+ ExceptionState& exception_state) {
+ DCHECK(port);
+ DCHECK(RuntimeEnabledFeatures::TransferableStreamsEnabled());
+ v8::TryCatch block(script_state->GetIsolate());
+ v8::Local<v8::Value> port_v8_value = ToV8(port, script_state);
+ DCHECK(!port_v8_value.IsEmpty());
+ v8::Local<v8::Value> args[] = {GetInternalStream(script_state).V8Value(),
+ port_v8_value};
+ V8ScriptRunner::CallExtra(script_state, "WritableStreamSerialize", args);
+ if (block.HasCaught()) {
+ exception_state.RethrowV8Exception(block.Exception());
+ }
+}
+
+// static
+WritableStreamWrapper* WritableStreamWrapper::Deserialize(
+ ScriptState* script_state,
+ MessagePort* port,
+ ExceptionState& exception_state) {
+ // We need to execute V8 Extras JavaScript to create the new WritableStream.
+ // We will not run author code.
+ auto* isolate = script_state->GetIsolate();
+ v8::Isolate::AllowJavascriptExecutionScope allow_js(isolate);
+ DCHECK(port);
+ DCHECK(RuntimeEnabledFeatures::TransferableStreamsEnabled());
+ v8::TryCatch block(isolate);
+ v8::Local<v8::Value> port_v8 = ToV8(port, script_state);
+ DCHECK(!port_v8.IsEmpty());
+ v8::Local<v8::Value> args[] = {port_v8};
+ ScriptValue internal_stream(
+ script_state, V8ScriptRunner::CallExtra(
+ script_state, "WritableStreamDeserialize", args));
+ if (block.HasCaught()) {
+ exception_state.RethrowV8Exception(block.Exception());
+ return nullptr;
+ }
+ DCHECK(!internal_stream.IsEmpty());
+ return CreateFromInternalStream(script_state, internal_stream,
+ exception_state);
+}
+
+ScriptValue WritableStreamWrapper::GetInternalStream(
+ ScriptState* script_state) const {
+ return ScriptValue(script_state,
+ internal_stream_.NewLocal(script_state->GetIsolate()));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.h b/chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.h
new file mode 100644
index 00000000000..81f2e96a380
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.h
@@ -0,0 +1,88 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_WRITABLE_STREAM_WRAPPER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_WRITABLE_STREAM_WRAPPER_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/core/streams/writable_stream.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+class MessagePort;
+
+// This is an implementation of the WritableStream interface that delegates to
+// the V8 Extras implementation. Use TraceWrapperMember to hold a reference to
+// an instance of this class.
+class CORE_EXPORT WritableStreamWrapper final : public WritableStream {
+ public:
+ // Call one of Init functions before using the instance.
+ WritableStreamWrapper() = default;
+ ~WritableStreamWrapper() override = default;
+
+ // If an error happens, |exception_state.HadException()| will be true, and
+ // |this| will not be usable after that.
+ void Init(ScriptState*,
+ ScriptValue underlying_sink,
+ ScriptValue strategy,
+ ExceptionState& exception_state);
+
+ static WritableStreamWrapper* CreateFromInternalStream(
+ ScriptState* script_state,
+ ScriptValue internal_stream,
+ ExceptionState& exception_state) {
+ DCHECK(internal_stream.IsObject());
+ return CreateFromInternalStream(script_state,
+ internal_stream.V8Value().As<v8::Object>(),
+ exception_state);
+ }
+ static WritableStreamWrapper* CreateFromInternalStream(
+ ScriptState*,
+ v8::Local<v8::Object> internal_stream,
+ ExceptionState&);
+
+ void Trace(Visitor* visitor) override;
+
+ // IDL defined functions
+ bool locked(ScriptState*, ExceptionState&) const override;
+ ScriptPromise abort(ScriptState*, ExceptionState&) override;
+ ScriptPromise abort(ScriptState*,
+ ScriptValue reason,
+ ExceptionState&) override;
+ ScriptValue getWriter(ScriptState*, ExceptionState&) override;
+
+ base::Optional<bool> IsLocked(ScriptState*, ExceptionState&) const override;
+
+ // Serialize this stream to |port|. The stream will be locked by this
+ // operation.
+ void Serialize(ScriptState*, MessagePort* port, ExceptionState&) override;
+
+ // Given a |port| which is entangled with a MessagePort that was previously
+ // passed to Serialize(), returns a new WritableStreamWrapper which behaves
+ // like it was the original.
+ static WritableStreamWrapper* Deserialize(ScriptState*,
+ MessagePort* port,
+ ExceptionState&);
+
+ ScriptValue GetInternalStream(ScriptState*) const;
+
+ private:
+ bool InitInternal(ScriptState*, v8::Local<v8::Object> internal_stream);
+
+ static v8::MaybeLocal<v8::Object> CreateInternalStream(
+ ScriptState* script_state,
+ v8::Local<v8::Value> underlying_sink,
+ v8::Local<v8::Value> strategy);
+
+ TraceWrapperV8Reference<v8::Object> internal_stream_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_WRITABLE_STREAM_WRAPPER_H_