summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/streams
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core/streams')
-rw-r--r--chromium/third_party/blink/renderer/core/streams/BUILD.gn8
-rw-r--r--chromium/third_party/blink/renderer/core/streams/README.md2
-rw-r--r--chromium/third_party/blink/renderer/core/streams/ReadableStream.js59
-rw-r--r--chromium/third_party/blink/renderer/core/streams/TransformStream.js2
-rw-r--r--chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.cc101
-rw-r--r--chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.h41
-rw-r--r--chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.idl17
-rw-r--r--chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.cc72
-rw-r--r--chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.h40
-rw-r--r--chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.idl17
-rw-r--r--chromium/third_party/blink/renderer/core/streams/miscellaneous_operations.h2
-rw-r--r--chromium/third_party/blink/renderer/core/streams/miscellaneous_operations_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/streams/queuing_strategy_common.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/streams/queuing_strategy_common.h20
-rw-r--r--chromium/third_party/blink/renderer/core/streams/queuing_strategy_init.idl10
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.h4
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.h1
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_native.cc67
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_native.h29
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc64
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_reader.cc49
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_reader.h9
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transferable_streams.cc878
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transferable_streams.h37
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transferable_streams_test.cc129
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.h2
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream_native.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream_wrapper.h2
-rw-r--r--chromium/third_party/blink/renderer/core/streams/underlying_sink_base.h2
-rw-r--r--chromium/third_party/blink/renderer/core/streams/underlying_source_base.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/streams/underlying_source_base.h9
-rw-r--r--chromium/third_party/blink/renderer/core/streams/underlying_source_base.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream.h5
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_default_writer.h3
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_native.cc65
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_native.h14
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.h6
44 files changed, 1635 insertions, 262 deletions
diff --git a/chromium/third_party/blink/renderer/core/streams/BUILD.gn b/chromium/third_party/blink/renderer/core/streams/BUILD.gn
index 24a5a0577bc..e747d5e73ac 100644
--- a/chromium/third_party/blink/renderer/core/streams/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/streams/BUILD.gn
@@ -6,12 +6,18 @@ import("//third_party/blink/renderer/core/core.gni")
blink_core_sources("streams") {
sources = [
+ "byte_length_queuing_strategy.cc",
+ "byte_length_queuing_strategy.h",
+ "count_queuing_strategy.cc",
+ "count_queuing_strategy.h",
"miscellaneous_operations.cc",
"miscellaneous_operations.h",
"promise_handler.cc",
"promise_handler.h",
"queue_with_sizes.cc",
"queue_with_sizes.h",
+ "queuing_strategy_common.cc",
+ "queuing_strategy_common.h",
"readable_stream.cc",
"readable_stream.h",
"readable_stream_default_controller.cc",
@@ -30,6 +36,8 @@ blink_core_sources("streams") {
"stream_algorithms.h",
"stream_promise_resolver.cc",
"stream_promise_resolver.h",
+ "transferable_streams.cc",
+ "transferable_streams.h",
"transform_stream.cc",
"transform_stream.h",
"transform_stream_default_controller.cc",
diff --git a/chromium/third_party/blink/renderer/core/streams/README.md b/chromium/third_party/blink/renderer/core/streams/README.md
index 68569248bdf..1b845c20ec1 100644
--- a/chromium/third_party/blink/renderer/core/streams/README.md
+++ b/chromium/third_party/blink/renderer/core/streams/README.md
@@ -26,6 +26,8 @@ feature. The following files are part of the new implementation:
writable_stream_default_writer.idl
writable_stream_native.cc
writable_stream_native.h
+ transferable_streams.cc
+ transferable_streams.h
transform_stream_default_controller.cc
transform_stream_default_controller.h
transform_stream_native.cc
diff --git a/chromium/third_party/blink/renderer/core/streams/ReadableStream.js b/chromium/third_party/blink/renderer/core/streams/ReadableStream.js
index 797fe38d9b5..b34ad33e09d 100644
--- a/chromium/third_party/blink/renderer/core/streams/ReadableStream.js
+++ b/chromium/third_party/blink/renderer/core/streams/ReadableStream.js
@@ -38,7 +38,6 @@
const internalReadableStreamSymbol = v8.createPrivateSymbol(
'internal ReadableStream in exposed ReadableStream interface');
// Remove this once C++ code has been updated to use CreateReadableStream.
- const _lockNotifyTarget = v8.createPrivateSymbol('[[lockNotifyTarget]]');
const _strategySizeAlgorithm = v8.createPrivateSymbol(
'[[strategySizeAlgorithm]]');
const _pullAlgorithm = v8.createPrivateSymbol('[[pullAlgorithm]]');
@@ -47,9 +46,6 @@
const CLOSE_REQUESTED = 0b10;
const PULLING = 0b100;
const PULL_AGAIN = 0b1000;
- // TODO(ricea): Remove this once blink::UnderlyingSourceBase no longer needs
- // it.
- const BLINK_LOCK_NOTIFICATIONS = 0b10000;
const ObjectCreate = global.Object.create;
@@ -127,10 +123,10 @@
// CreateReadableStream.
constructor(underlyingSource = {}, strategy = {},
internalArgument = undefined) {
- const enableBlinkLockNotifications =
+ const createdByUA =
internalArgument === createWithExternalControllerSentinel;
- if (!useCounted && !enableBlinkLockNotifications) {
+ if (!useCounted && !createdByUA) {
binding.countUse('ReadableStreamConstructor');
useCounted = true;
}
@@ -157,8 +153,7 @@
highWaterMark = ValidateAndNormalizeHighWaterMark(highWaterMark);
SetUpReadableStreamDefaultControllerFromUnderlyingSource(
- this, underlyingSource, highWaterMark, sizeAlgorithm,
- enableBlinkLockNotifications);
+ this, underlyingSource, highWaterMark, sizeAlgorithm);
}
}
@@ -381,11 +376,8 @@
return new ReadableStreamDefaultReader(stream);
}
- // The non-standard boolean |enableBlinkLockNotifications| argument indicates
- // whether the stream is being created from C++.
function CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm,
- highWaterMark, sizeAlgorithm,
- enableBlinkLockNotifications) {
+ highWaterMark, sizeAlgorithm) {
if (highWaterMark === undefined) {
highWaterMark = 1;
}
@@ -399,7 +391,7 @@
const controller = ObjectCreate(ReadableStreamDefaultController_prototype);
SetUpReadableStreamDefaultController(
stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm,
- highWaterMark, sizeAlgorithm, enableBlinkLockNotifications);
+ highWaterMark, sizeAlgorithm);
return stream;
}
@@ -490,11 +482,9 @@
const startAlgorithm = () => undefined;
const branch1Stream = CreateReadableStream(
- startAlgorithm, pullAlgorithm, cancel1Algorithm, undefined, undefined,
- false);
+ startAlgorithm, pullAlgorithm, cancel1Algorithm);
const branch2Stream = CreateReadableStream(
- startAlgorithm, pullAlgorithm, cancel2Algorithm, undefined, undefined,
- false);
+ startAlgorithm, pullAlgorithm, cancel2Algorithm);
const branch1controller = branch1Stream[_controller];
const branch2controller = branch2Stream[_controller];
@@ -695,17 +685,6 @@
}
function ReadableStreamReaderGenericInitialize(reader, stream) {
- // TODO(yhirano): Remove this when we don't need hasPendingActivity in
- // blink::UnderlyingSourceBase.
- const controller = stream[_controller];
- if (controller[_readableStreamDefaultControllerBits] &
- BLINK_LOCK_NOTIFICATIONS) {
- // The stream is created with an external controller (i.e. made in
- // Blink).
- const lockNotifyTarget = controller[_lockNotifyTarget];
- callFunction(lockNotifyTarget.notifyLockAcquired, lockNotifyTarget);
- }
-
reader[_ownerReadableStream] = stream;
stream[_reader] = reader;
@@ -724,17 +703,6 @@
}
function ReadableStreamReaderGenericRelease(reader) {
- // TODO(yhirano): Remove this when we don't need hasPendingActivity in
- // blink::UnderlyingSourceBase.
- const controller = reader[_ownerReadableStream][_controller];
- if (controller[_readableStreamDefaultControllerBits] &
- BLINK_LOCK_NOTIFICATIONS) {
- // The stream is created with an external controller (i.e. made in
- // Blink).
- const lockNotifyTarget = controller[_lockNotifyTarget];
- callFunction(lockNotifyTarget.notifyLockReleased, lockNotifyTarget);
- }
-
if (ReadableStreamGetState(reader[_ownerReadableStream]) ===
STATE_READABLE) {
rejectPromise(
@@ -1000,12 +968,10 @@
function SetUpReadableStreamDefaultController(
stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm,
- highWaterMark, sizeAlgorithm, enableBlinkLockNotifications) {
+ highWaterMark, sizeAlgorithm) {
controller[_controlledReadableStream] = stream;
controller[_queue] = new binding.SimpleQueue();
controller[_queueTotalSize] = 0;
- controller[_readableStreamDefaultControllerBits] =
- enableBlinkLockNotifications ? BLINK_LOCK_NOTIFICATIONS : 0b0;
controller[_strategySizeAlgorithm] = sizeAlgorithm;
controller[_strategyHWM] = highWaterMark;
controller[_pullAlgorithm] = pullAlgorithm;
@@ -1019,8 +985,7 @@
}
function SetUpReadableStreamDefaultControllerFromUnderlyingSource(
- stream, underlyingSource, highWaterMark, sizeAlgorithm,
- enableBlinkLockNotifications) {
+ stream, underlyingSource, highWaterMark, sizeAlgorithm) {
const controller = ObjectCreate(ReadableStreamDefaultController_prototype);
const startAlgorithm =
() => CallOrNoop1(underlyingSource, 'start', controller,
@@ -1029,13 +994,9 @@
underlyingSource, 'pull', 0, controller, 'underlyingSource.pull');
const cancelAlgorithm = CreateAlgorithmFromUnderlyingMethod(
underlyingSource, 'cancel', 1, 'underlyingSource.cancel');
- // TODO(ricea): Remove this once C++ API has been updated.
- if (enableBlinkLockNotifications) {
- controller[_lockNotifyTarget] = underlyingSource;
- }
SetUpReadableStreamDefaultController(
stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm,
- highWaterMark, sizeAlgorithm, enableBlinkLockNotifications);
+ highWaterMark, sizeAlgorithm);
}
//
diff --git a/chromium/third_party/blink/renderer/core/streams/TransformStream.js b/chromium/third_party/blink/renderer/core/streams/TransformStream.js
index 4b7449584a9..639be9b30f1 100644
--- a/chromium/third_party/blink/renderer/core/streams/TransformStream.js
+++ b/chromium/third_party/blink/renderer/core/streams/TransformStream.js
@@ -193,7 +193,7 @@
};
stream[_readable] = binding.CreateReadableStream(
startAlgorithm, pullAlgorithm, cancelAlgorithm, readableHighWaterMark,
- readableSizeAlgorithm, false);
+ readableSizeAlgorithm);
stream[_backpressure] = undefined;
stream[_backpressureChangePromise] = undefined;
TransformStreamSetBackpressure(stream, true);
diff --git a/chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.cc b/chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.cc
new file mode 100644
index 00000000000..aae8fb8bc29
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.cc
@@ -0,0 +1,101 @@
+// Copyright 2019 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/byte_length_queuing_strategy.h"
+
+#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/core/streams/queuing_strategy_common.h"
+#include "third_party/blink/renderer/core/streams/queuing_strategy_init.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
+#include "third_party/blink/renderer/platform/heap/visitor.h"
+
+namespace blink {
+
+namespace {
+
+class ByteLengthQueuingStrategySizeFunction final : public ScriptFunction {
+ public:
+ static v8::Local<v8::Function> CreateFunction(ScriptState* script_state) {
+ ByteLengthQueuingStrategySizeFunction* self =
+ MakeGarbageCollected<ByteLengthQueuingStrategySizeFunction>(
+ script_state);
+ return self->BindToV8Function();
+ }
+
+ explicit ByteLengthQueuingStrategySizeFunction(ScriptState* script_state)
+ : ScriptFunction(script_state) {}
+
+ private:
+ void CallRaw(const v8::FunctionCallbackInfo<v8::Value>& args) override {
+ auto* isolate = args.GetIsolate();
+ DCHECK_EQ(isolate, GetScriptState()->GetIsolate());
+ auto context = GetScriptState()->GetContext();
+ v8::Local<v8::Value> chunk;
+ if (args.Length() < 1) {
+ chunk = v8::Undefined(isolate);
+ } else {
+ chunk = args[0];
+ }
+
+ // https://streams.spec.whatwg.org/#blqs-size
+ // 1. Return ? GetV(chunk, "byteLength").
+
+ // https://tc39.es/ecma262/#sec-getv
+ // 1. Assert: IsPropertyKey(P) is true.
+ // 2. Let O be ? ToObject(V).
+ v8::Local<v8::Object> chunk_as_object;
+ if (!chunk->ToObject(context).ToLocal(&chunk_as_object)) {
+ // Should have thrown an exception, which will be caught further up the
+ // stack.
+ return;
+ }
+ // 3. Return ? O.[[Get]](P, V).
+ v8::Local<v8::Value> byte_length;
+ if (!chunk_as_object->Get(context, V8AtomicString(isolate, "byteLength"))
+ .ToLocal(&byte_length)) {
+ // Should have thrown an exception.
+ return;
+ }
+ args.GetReturnValue().Set(byte_length);
+ }
+};
+
+} // namespace
+
+ByteLengthQueuingStrategy* ByteLengthQueuingStrategy::Create(
+ ScriptState* script_state,
+ const QueuingStrategyInit* init) {
+ return MakeGarbageCollected<ByteLengthQueuingStrategy>(script_state, init);
+}
+
+ByteLengthQueuingStrategy::ByteLengthQueuingStrategy(
+ ScriptState* script_state,
+ const QueuingStrategyInit* init)
+ : high_water_mark_(script_state->GetIsolate(),
+ HighWaterMarkOrUndefined(script_state, init)) {}
+
+ByteLengthQueuingStrategy::~ByteLengthQueuingStrategy() = default;
+
+ScriptValue ByteLengthQueuingStrategy::highWaterMark(
+ ScriptState* script_state) const {
+ return ScriptValue(script_state,
+ high_water_mark_.NewLocal(script_state->GetIsolate()));
+}
+
+ScriptValue ByteLengthQueuingStrategy::size(ScriptState* script_state) const {
+ // We don't cache the result because normally this method will only be called
+ // once anyway.
+ return ScriptValue(
+ script_state,
+ ByteLengthQueuingStrategySizeFunction::CreateFunction(script_state));
+}
+
+void ByteLengthQueuingStrategy::Trace(Visitor* visitor) {
+ visitor->Trace(high_water_mark_);
+ ScriptWrappable::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.h b/chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.h
new file mode 100644
index 00000000000..c1544212c8a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.h
@@ -0,0 +1,41 @@
+// Copyright 2019 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_BYTE_LENGTH_QUEUING_STRATEGY_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_BYTE_LENGTH_QUEUING_STRATEGY_H_
+
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+class QueuingStrategyInit;
+class ScriptState;
+class ScriptValue;
+class Visitor;
+
+// https://streams.spec.whatwg.org/#blqs-class
+class ByteLengthQueuingStrategy final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static ByteLengthQueuingStrategy* Create(ScriptState*,
+ const QueuingStrategyInit*);
+
+ ByteLengthQueuingStrategy(ScriptState*, const QueuingStrategyInit*);
+ ~ByteLengthQueuingStrategy() override;
+
+ ScriptValue highWaterMark(ScriptState*) const;
+ ScriptValue size(ScriptState*) const;
+
+ void Trace(Visitor*) override;
+
+ private:
+ const TraceWrapperV8Reference<v8::Value> high_water_mark_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_BYTE_LENGTH_QUEUING_STRATEGY_H_
diff --git a/chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.idl b/chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.idl
new file mode 100644
index 00000000000..af68396eb0e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.idl
@@ -0,0 +1,17 @@
+// Copyright 2019 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.
+
+// https://streams.spec.whatwg.org/#blqs-class
+
+[
+ Exposed=(Window,Worker,Worklet),
+ RuntimeEnabled=StreamsNative,
+ ConstructorCallWith=ScriptState,
+ Constructor([PermissiveDictionaryConversion] QueuingStrategyInit init)
+] interface ByteLengthQueuingStrategy {
+ [CallWith=ScriptState] readonly attribute any highWaterMark;
+
+ // size is an accessor that returns a function.
+ [CallWith=ScriptState] readonly attribute any size;
+};
diff --git a/chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.cc b/chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.cc
new file mode 100644
index 00000000000..2b1aa3b9c24
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.cc
@@ -0,0 +1,72 @@
+// Copyright 2019 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/count_queuing_strategy.h"
+
+#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/core/streams/queuing_strategy_common.h"
+#include "third_party/blink/renderer/core/streams/queuing_strategy_init.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/heap/visitor.h"
+
+namespace blink {
+
+namespace {
+
+class CountQueuingStrategySizeFunction final : public ScriptFunction {
+ public:
+ static v8::Local<v8::Function> CreateFunction(ScriptState* script_state) {
+ CountQueuingStrategySizeFunction* self =
+ MakeGarbageCollected<CountQueuingStrategySizeFunction>(script_state);
+ return self->BindToV8Function();
+ }
+
+ explicit CountQueuingStrategySizeFunction(ScriptState* script_state)
+ : ScriptFunction(script_state) {}
+
+ private:
+ void CallRaw(const v8::FunctionCallbackInfo<v8::Value>& args) override {
+ // https://streams.spec.whatwg.org/#cqs-size
+ // 1. Return 1.
+ args.GetReturnValue().Set(
+ v8::Integer::New(GetScriptState()->GetIsolate(), 1));
+ }
+};
+
+} // namespace
+
+CountQueuingStrategy* CountQueuingStrategy::Create(
+ ScriptState* script_state,
+ const QueuingStrategyInit* init) {
+ return MakeGarbageCollected<CountQueuingStrategy>(script_state, init);
+}
+
+CountQueuingStrategy::CountQueuingStrategy(ScriptState* script_state,
+ const QueuingStrategyInit* init)
+ : high_water_mark_(script_state->GetIsolate(),
+ HighWaterMarkOrUndefined(script_state, init)) {}
+
+CountQueuingStrategy::~CountQueuingStrategy() = default;
+
+ScriptValue CountQueuingStrategy::highWaterMark(
+ ScriptState* script_state) const {
+ return ScriptValue(script_state,
+ high_water_mark_.NewLocal(script_state->GetIsolate()));
+}
+
+ScriptValue CountQueuingStrategy::size(ScriptState* script_state) const {
+ // We don't cache the result because normally this method will only be called
+ // once anyway.
+ return ScriptValue(
+ script_state,
+ CountQueuingStrategySizeFunction::CreateFunction(script_state));
+}
+
+void CountQueuingStrategy::Trace(Visitor* visitor) {
+ visitor->Trace(high_water_mark_);
+ ScriptWrappable::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.h b/chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.h
new file mode 100644
index 00000000000..246c4599d14
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.h
@@ -0,0 +1,40 @@
+// Copyright 2019 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_COUNT_QUEUING_STRATEGY_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_COUNT_QUEUING_STRATEGY_H_
+
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+class QueuingStrategyInit;
+class ScriptState;
+class ScriptValue;
+class Visitor;
+
+// https://streams.spec.whatwg.org/#blqs-class
+class CountQueuingStrategy final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static CountQueuingStrategy* Create(ScriptState*, const QueuingStrategyInit*);
+
+ CountQueuingStrategy(ScriptState*, const QueuingStrategyInit*);
+ ~CountQueuingStrategy() override;
+
+ ScriptValue highWaterMark(ScriptState*) const;
+ ScriptValue size(ScriptState*) const;
+
+ void Trace(Visitor*) override;
+
+ private:
+ const TraceWrapperV8Reference<v8::Value> high_water_mark_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_COUNT_QUEUING_STRATEGY_H_
diff --git a/chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.idl b/chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.idl
new file mode 100644
index 00000000000..02cfe7a9715
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.idl
@@ -0,0 +1,17 @@
+// Copyright 2019 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.
+
+// https://streams.spec.whatwg.org/#cqs-class
+
+[
+ Exposed=(Window,Worker,Worklet),
+ RuntimeEnabled=StreamsNative,
+ ConstructorCallWith=ScriptState,
+ Constructor([PermissiveDictionaryConversion] QueuingStrategyInit init)
+] interface CountQueuingStrategy {
+ [CallWith=ScriptState] readonly attribute any highWaterMark;
+
+ // size is an accessor that returns a function.
+ [CallWith=ScriptState] readonly attribute any size;
+};
diff --git a/chromium/third_party/blink/renderer/core/streams/miscellaneous_operations.h b/chromium/third_party/blink/renderer/core/streams/miscellaneous_operations.h
index f490157e2e2..8d715102122 100644
--- a/chromium/third_party/blink/renderer/core/streams/miscellaneous_operations.h
+++ b/chromium/third_party/blink/renderer/core/streams/miscellaneous_operations.h
@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "v8/include/v8.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/streams/miscellaneous_operations_test.cc b/chromium/third_party/blink/renderer/core/streams/miscellaneous_operations_test.cc
index c21a934ed4a..9a8e28b4895 100644
--- a/chromium/third_party/blink/renderer/core/streams/miscellaneous_operations_test.cc
+++ b/chromium/third_party/blink/renderer/core/streams/miscellaneous_operations_test.cc
@@ -97,7 +97,8 @@ v8::Local<v8::Value> CreateFromFunctionAndGetResult(
int argc = 0,
v8::Local<v8::Value> argv[] = nullptr) {
String js = String("({start: ") + function_definition + "})" + '\0';
- ScriptValue underlying_value = EvalWithPrintingError(scope, js.Utf8().data());
+ ScriptValue underlying_value =
+ EvalWithPrintingError(scope, js.Utf8().c_str());
auto underlying_object = underlying_value.V8Value().As<v8::Object>();
auto* algo = CreateAlgorithmFromUnderlyingMethod(
scope->GetScriptState(), underlying_object, "start",
diff --git a/chromium/third_party/blink/renderer/core/streams/queuing_strategy_common.cc b/chromium/third_party/blink/renderer/core/streams/queuing_strategy_common.cc
new file mode 100644
index 00000000000..4441a896a38
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/streams/queuing_strategy_common.cc
@@ -0,0 +1,23 @@
+// Copyright 2019 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/queuing_strategy_common.h"
+
+#include "third_party/blink/renderer/core/streams/queuing_strategy_init.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+
+namespace blink {
+
+v8::Local<v8::Value> HighWaterMarkOrUndefined(ScriptState* script_state,
+ const QueuingStrategyInit* init) {
+ v8::Local<v8::Value> high_water_mark;
+ if (init->hasHighWaterMark()) {
+ high_water_mark = init->highWaterMark().V8Value();
+ } else {
+ high_water_mark = v8::Undefined(script_state->GetIsolate());
+ }
+ return high_water_mark;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/queuing_strategy_common.h b/chromium/third_party/blink/renderer/core/streams/queuing_strategy_common.h
new file mode 100644
index 00000000000..d62e6a866f1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/streams/queuing_strategy_common.h
@@ -0,0 +1,20 @@
+// Copyright 2019 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_QUEUING_STRATEGY_COMMON_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_QUEUING_STRATEGY_COMMON_H_
+
+#include "v8/include/v8.h"
+
+namespace blink {
+
+class ScriptState;
+class QueuingStrategyInit;
+
+v8::Local<v8::Value> HighWaterMarkOrUndefined(ScriptState* script_state,
+ const QueuingStrategyInit* init);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_QUEUING_STRATEGY_COMMON_H_
diff --git a/chromium/third_party/blink/renderer/core/streams/queuing_strategy_init.idl b/chromium/third_party/blink/renderer/core/streams/queuing_strategy_init.idl
new file mode 100644
index 00000000000..7d5bd0c511e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/streams/queuing_strategy_init.idl
@@ -0,0 +1,10 @@
+// Copyright 2019 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.
+
+// https://streams.spec.whatwg.org/#cqs-class
+
+[PermissiveDictionaryConversion]
+dictionary QueuingStrategyInit {
+ any highWaterMark;
+};
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 8b787d62af1..e1088481c4a 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream.cc
@@ -60,11 +60,9 @@ ReadableStream* ReadableStream::CreateWithCountQueueingStrategy(
ReadableStream* ReadableStream::Deserialize(ScriptState* script_state,
MessagePort* port,
ExceptionState& exception_state) {
- // TODO(ricea): Implementation serialization for the native implementation.
if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
- exception_state.ThrowTypeError(
- "serialization disabled because StreamsNative feature is enabled");
- return nullptr;
+ return ReadableStreamNative::Deserialize(script_state, port,
+ exception_state);
}
return ReadableStreamWrapper::Deserialize(script_state, port,
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc
index b5fca428366..653cab070a3 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc
@@ -271,7 +271,6 @@ void ReadableStreamDefaultController::Trace(Visitor* visitor) {
visitor->Trace(pull_algorithm_);
visitor->Trace(queue_);
visitor->Trace(strategy_size_algorithm_);
- visitor->Trace(lock_notify_target_);
ScriptWrappable::Trace(visitor);
}
@@ -494,7 +493,6 @@ void ReadableStreamDefaultController::SetUp(
StreamAlgorithm* cancel_algorithm,
double high_water_mark,
StrategySizeAlgorithm* size_algorithm,
- bool enable_blink_lock_notifications,
ExceptionState& exception_state) {
// https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller
// 1. Assert: stream.[[readableStreamController]] is undefined.
@@ -510,10 +508,6 @@ void ReadableStreamDefaultController::SetUp(
DCHECK(controller->queue_->IsEmpty());
DCHECK_EQ(controller->queue_->TotalSize(), 0);
- // Not part of the standard.
- controller->enable_blink_lock_notifications_ =
- enable_blink_lock_notifications;
-
// 5. Set controller.[[strategySizeAlgorithm]] to sizeAlgorithm and
// controller.[[strategyHWM]] to highWaterMark.
controller->strategy_size_algorithm_ = size_algorithm;
@@ -610,7 +604,6 @@ void ReadableStreamDefaultController::SetUpFromUnderlyingSource(
v8::Local<v8::Object> underlying_source,
double high_water_mark,
StrategySizeAlgorithm* size_algorithm,
- bool enable_blink_lock_notifications,
ExceptionState& exception_state) {
// https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller-from-underlying-source
// 2. Let controller be ObjectCreate(the original value of
@@ -646,18 +639,11 @@ void ReadableStreamDefaultController::SetUpFromUnderlyingSource(
return;
}
- // TODO(ricea): Remove this once C++ API has been updated.
- if (enable_blink_lock_notifications) {
- controller->lock_notify_target_.Set(script_state->GetIsolate(),
- underlying_source);
- }
-
// 6. Perform ? SetUpReadableStreamDefaultController(stream, controller,
// startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark,
// sizeAlgorithm).
SetUp(script_state, stream, controller, start_algorithm, pull_algorithm,
- cancel_algorithm, high_water_mark, size_algorithm,
- enable_blink_lock_notifications, exception_state);
+ cancel_algorithm, high_water_mark, size_algorithm, exception_state);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.h b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.h
index 14e8becff8f..0a14d943b82 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.h
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.h
@@ -100,7 +100,6 @@ class ReadableStreamDefaultController : public ScriptWrappable {
StreamAlgorithm* cancel_algorithm,
double high_water_mark,
StrategySizeAlgorithm* size_algorithm,
- bool enable_blink_lock_notifications,
ExceptionState&);
// https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller-from-underlying-source
@@ -109,7 +108,6 @@ class ReadableStreamDefaultController : public ScriptWrappable {
v8::Local<v8::Object> underlying_source,
double high_water_mark,
StrategySizeAlgorithm* size_algorithm,
- bool enable_blink_lock_notifications,
ExceptionState&);
// Boolean flags are grouped together to reduce object size. Verbs have been
@@ -118,14 +116,12 @@ class ReadableStreamDefaultController : public ScriptWrappable {
bool will_pull_again_ = false;
bool is_pulling_ = false;
bool is_started_ = false;
- bool enable_blink_lock_notifications_ = false;
Member<StreamAlgorithm> cancel_algorithm_;
Member<ReadableStreamNative> controlled_readable_stream_;
Member<StreamAlgorithm> pull_algorithm_;
Member<QueueWithSizes> queue_;
double strategy_high_water_mark_ = 0.0;
Member<StrategySizeAlgorithm> strategy_size_algorithm_;
- TraceWrapperV8Reference<v8::Object> lock_notify_target_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.cc
index 6abdedafe86..91fe704295a 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.cc
@@ -31,8 +31,6 @@ class ReadableStreamDefaultControllerWrapper final
// (close/desiredSize/enqueue/error will become no-ops afterward.)
void NoteHasBeenCanceled() override { js_controller_.Clear(); }
- bool IsActive() const override { return !js_controller_.IsEmpty(); }
-
void Close() override {
ScriptState* script_state = script_state_;
// This will assert that the context is valid; do not call this method when
@@ -129,8 +127,6 @@ class ReadableStreamDefaultControllerNative final
void NoteHasBeenCanceled() override { controller_ = nullptr; }
- bool IsActive() const override { return controller_; }
-
void Close() override {
if (!controller_)
return;
@@ -138,6 +134,7 @@ class ReadableStreamDefaultControllerNative final
ScriptState::Scope scope(script_state_);
ReadableStreamDefaultController::Close(script_state_, controller_);
+ controller_ = nullptr;
}
double DesiredSize() const override {
@@ -173,6 +170,7 @@ class ReadableStreamDefaultControllerNative final
ReadableStreamDefaultController::Error(script_state_, controller_,
js_error);
+ controller_ = nullptr;
}
void Trace(Visitor* visitor) override {
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.h b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.h
index bfdb80447cb..7d859463d8c 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.h
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.h
@@ -33,7 +33,6 @@ class CORE_EXPORT ReadableStreamDefaultControllerInterface
// (Close/DesiredSize/Enqueue/Error will become no-ops afterward.)
virtual void NoteHasBeenCanceled() = 0;
- virtual bool IsActive() const = 0;
virtual void Close() = 0;
virtual double DesiredSize() const = 0;
virtual void Enqueue(v8::Local<v8::Value> js_chunk) const = 0;
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_native.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_native.cc
index 4567ec4b712..632ea367d68 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_native.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_native.cc
@@ -8,7 +8,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/frame/use_counter.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/promise_handler.h"
@@ -16,6 +15,7 @@
#include "third_party/blink/renderer/core/streams/readable_stream_reader.h"
#include "third_party/blink/renderer/core/streams/stream_algorithms.h"
#include "third_party/blink/renderer/core/streams/stream_promise_resolver.h"
+#include "third_party/blink/renderer/core/streams/transferable_streams.h"
#include "third_party/blink/renderer/core/streams/underlying_source_base.h"
#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
#include "third_party/blink/renderer/core/streams/writable_stream_default_writer.h"
@@ -25,18 +25,12 @@
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/visitor.h"
+#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
namespace blink {
-struct ReadableStreamNative::PipeOptions {
- PipeOptions() = default;
- bool prevent_close = false;
- bool prevent_abort = false;
- bool prevent_cancel = false;
-};
-
// PipeToEngine implements PipeTo(). All standard steps in this class come from
// https://streams.spec.whatwg.org/#readable-stream-pipe-to
//
@@ -1053,8 +1047,7 @@ ReadableStreamNative* ReadableStreamNative::Create(
// sizeAlgorithm).
ReadableStreamDefaultController::SetUp(
script_state, stream, controller, start_algorithm, pull_algorithm,
- cancel_algorithm, high_water_mark, size_algorithm, false,
- exception_state);
+ cancel_algorithm, high_water_mark, size_algorithm, exception_state);
if (exception_state.HadException()) {
return nullptr;
}
@@ -1065,14 +1058,12 @@ ReadableStreamNative* ReadableStreamNative::Create(
ReadableStreamNative::ReadableStreamNative() = default;
-// TODO(ricea): Remove |enable_blink_lock_notifications| once
-// blink::ReadableStreamOperations has been updated to use CreateReadableStream.
ReadableStreamNative::ReadableStreamNative(ScriptState* script_state,
ScriptValue raw_underlying_source,
ScriptValue raw_strategy,
- bool enable_blink_lock_notifications,
+ bool created_by_ua,
ExceptionState& exception_state) {
- if (!enable_blink_lock_notifications) {
+ if (!created_by_ua) {
// TODO(ricea): Move this to IDL once blink::ReadableStreamOperations is
// no longer using the public constructor.
UseCounter::Count(ExecutionContext::From(script_state),
@@ -1157,7 +1148,7 @@ ReadableStreamNative::ReadableStreamNative(ScriptState* script_state,
// (this, underlyingSource, highWaterMark, sizeAlgorithm).
ReadableStreamDefaultController::SetUpFromUnderlyingSource(
script_state, this, underlying_source, high_water_mark, size_algorithm,
- enable_blink_lock_notifications, exception_state);
+ exception_state);
}
ReadableStreamNative::~ReadableStreamNative() = default;
@@ -1394,7 +1385,43 @@ void ReadableStreamNative::LockAndDisturb(ScriptState* script_state,
void ReadableStreamNative::Serialize(ScriptState* script_state,
MessagePort* port,
ExceptionState& exception_state) {
- // TODO(ricea): Implement this.
+ if (IsLocked(this)) {
+ exception_state.ThrowTypeError("Cannot transfer a locked stream");
+ return;
+ }
+
+ auto* writable =
+ CreateCrossRealmTransformWritable(script_state, port, exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+
+ auto promise = PipeTo(script_state, this, writable, PipeOptions());
+ promise.MarkAsHandled();
+}
+
+ReadableStreamNative* ReadableStreamNative::Deserialize(
+ ScriptState* script_state,
+ MessagePort* port,
+ ExceptionState& exception_state) {
+ // We need to execute JavaScript to call "Then" on v8::Promises. We will not
+ // run author code.
+ v8::Isolate::AllowJavascriptExecutionScope allow_js(
+ script_state->GetIsolate());
+ auto* readable =
+ CreateCrossRealmTransformReadable(script_state, port, exception_state);
+ if (exception_state.HadException()) {
+ return nullptr;
+ }
+ return readable;
+}
+
+ScriptPromise ReadableStreamNative::PipeTo(ScriptState* script_state,
+ ReadableStreamNative* readable,
+ WritableStreamNative* destination,
+ PipeOptions pipe_options) {
+ auto* engine = MakeGarbageCollected<PipeToEngine>(script_state, pipe_options);
+ return engine->Start(readable, destination);
}
v8::Local<v8::Value> ReadableStreamNative::GetStoredError(
@@ -1409,14 +1436,6 @@ void ReadableStreamNative::Trace(Visitor* visitor) {
ReadableStream::Trace(visitor);
}
-ScriptPromise ReadableStreamNative::PipeTo(ScriptState* script_state,
- ReadableStreamNative* readable,
- WritableStreamNative* destination,
- PipeOptions pipe_options) {
- auto* engine = MakeGarbageCollected<PipeToEngine>(script_state, pipe_options);
- return engine->Start(readable, destination);
-}
-
//
// Abstract Operations Used By Controllers
//
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_native.h b/chromium/third_party/blink/renderer/core/streams/readable_stream_native.h
index b2af17d437e..ee1b87d9d9b 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_native.h
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_native.h
@@ -30,6 +30,13 @@ class WritableStreamNative;
// See https://streams.spec.whatwg.org/#rs-model for background.
class ReadableStreamNative : public ReadableStream {
public:
+ struct PipeOptions {
+ PipeOptions() = default;
+ bool prevent_close = false;
+ bool prevent_abort = false;
+ bool prevent_cancel = false;
+ };
+
enum State : uint8_t { kReadable, kClosed, kErrored };
// Implements ReadableStream::Create() when this implementation is enabled.
@@ -60,14 +67,11 @@ class ReadableStreamNative : public ReadableStream {
ReadableStreamNative();
- // TODO(ricea): Remove |enable_blink_lock_notifications| once
- // blink::ReadableStreamOperations has been updated to use
- // CreateReadableStream.
// https://streams.spec.whatwg.org/#rs-constructor
ReadableStreamNative(ScriptState*,
ScriptValue raw_underlying_source,
ScriptValue raw_strategy,
- bool enable_blink_lock_notifications,
+ bool created_by_ua,
ExceptionState&);
~ReadableStreamNative() override;
@@ -146,6 +150,10 @@ class ReadableStreamNative : public ReadableStream {
void Serialize(ScriptState*, MessagePort* port, ExceptionState&) override;
+ static ReadableStreamNative* Deserialize(ScriptState*,
+ MessagePort* port,
+ ExceptionState&);
+
bool IsBroken() const override { return false; }
//
@@ -162,6 +170,12 @@ class ReadableStreamNative : public ReadableStream {
return stream->reader_;
}
+ // https://streams.spec.whatwg.org/#readable-stream-pipe-to
+ static ScriptPromise PipeTo(ScriptState*,
+ ReadableStreamNative*,
+ WritableStreamNative*,
+ PipeOptions);
+
//
// Functions exported for use by TransformStream. Not part of the standard.
//
@@ -190,7 +204,6 @@ class ReadableStreamNative : public ReadableStream {
friend class ReadableStreamDefaultController;
friend class ReadableStreamReader;
- struct PipeOptions;
class PipeToEngine;
class ReadHandleImpl;
class TeeEngine;
@@ -204,12 +217,6 @@ class ReadableStreamNative : public ReadableStream {
bool for_author_code,
ExceptionState&);
- // https://streams.spec.whatwg.org/#readable-stream-pipe-to
- static ScriptPromise PipeTo(ScriptState*,
- ReadableStreamNative*,
- WritableStreamNative*,
- PipeOptions);
-
// https://streams.spec.whatwg.org/#readable-stream-add-read-request
static StreamPromiseResolver* AddReadRequest(ScriptState*,
ReadableStreamNative*);
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 605a1b46c80..8f77a2bfc43 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
@@ -24,6 +24,7 @@
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "v8/include/v8.h"
@@ -131,6 +132,8 @@ ScriptValue CheckedGetInternalStream(ScriptState* script_state,
}
TEST(ReadableStreamOperationsTest, IsReadableStream) {
+ ScopedStreamsNativeForTest enabled(false);
+
V8TestingScope scope;
TryCatchScope try_catch_scope(scope.GetIsolate());
EXPECT_FALSE(ReadableStreamOperations::IsReadableStream(
@@ -167,6 +170,8 @@ TEST(ReadableStreamOperationsTest, IsReadableStream) {
}
TEST(ReadableStreamOperationsTest, IsReadableStreamDefaultReaderInvalid) {
+ ScopedStreamsNativeForTest enabled(false);
+
V8TestingScope scope;
TryCatchScope try_catch_scope(scope.GetIsolate());
EXPECT_FALSE(ReadableStreamOperations::IsReadableStreamDefaultReader(
@@ -195,6 +200,8 @@ TEST(ReadableStreamOperationsTest, IsReadableStreamDefaultReaderInvalid) {
}
TEST(ReadableStreamOperationsTest, GetReader) {
+ ScopedStreamsNativeForTest enabled(false);
+
V8TestingScope scope;
TryCatchScope try_catch_scope(scope.GetIsolate());
auto* stream =
@@ -232,6 +239,8 @@ TEST(ReadableStreamOperationsTest, GetReader) {
}
TEST(ReadableStreamOperationsTest, IsDisturbed) {
+ ScopedStreamsNativeForTest enabled(false);
+
V8TestingScope scope;
TryCatchScope try_catch_scope(scope.GetIsolate());
auto* stream =
@@ -252,6 +261,8 @@ TEST(ReadableStreamOperationsTest, IsDisturbed) {
}
TEST(ReadableStreamOperationsTest, Read) {
+ ScopedStreamsNativeForTest enabled(false);
+
V8TestingScope scope;
TryCatchScope try_catch_scope(scope.GetIsolate());
ScriptValue reader =
@@ -301,6 +312,8 @@ TEST(ReadableStreamOperationsTest, Read) {
TEST(ReadableStreamOperationsTest,
CreateReadableStreamWithCustomUnderlyingSourceAndStrategy) {
+ ScopedStreamsNativeForTest enabled(false);
+
V8TestingScope scope;
TryCatchScope try_catch_scope(scope.GetIsolate());
auto* underlying_source =
@@ -367,47 +380,9 @@ TEST(ReadableStreamOperationsTest,
EXPECT_TRUE(it3->IsDone());
}
-TEST(ReadableStreamOperationsTest,
- UnderlyingSourceShouldHavePendingActivityWhenLockedAndControllerIsActive) {
- V8TestingScope scope;
- TryCatchScope try_catch_scope(scope.GetIsolate());
- auto* underlying_source =
- MakeGarbageCollected<TestUnderlyingSource>(scope.GetScriptState());
-
- ScriptValue strategy = ReadableStreamOperations::CreateCountQueuingStrategy(
- scope.GetScriptState(), 10);
- ASSERT_FALSE(strategy.IsEmpty());
-
- ScriptValue internal_stream = ReadableStreamOperations::CreateReadableStream(
- scope.GetScriptState(), underlying_source, strategy);
- ASSERT_FALSE(internal_stream.IsEmpty());
-
- CHECK(!RuntimeEnabledFeatures::StreamsNativeEnabled());
- auto* stream = ReadableStreamWrapper::CreateFromInternalStream(
- scope.GetScriptState(), internal_stream, ASSERT_NO_EXCEPTION);
- ASSERT_TRUE(stream);
-
- v8::Local<v8::Object> global = scope.GetScriptState()->GetContext()->Global();
- ASSERT_TRUE(global
- ->Set(scope.GetContext(),
- V8String(scope.GetIsolate(), "stream"),
- ToV8(stream, scope.GetScriptState()))
- .IsJust());
-
- EXPECT_FALSE(underlying_source->HasPendingActivity());
- EvalWithPrintingError(&scope, "let reader = stream.getReader();");
- EXPECT_TRUE(underlying_source->HasPendingActivity());
- EvalWithPrintingError(&scope, "reader.releaseLock();");
- EXPECT_FALSE(underlying_source->HasPendingActivity());
- EvalWithPrintingError(&scope, "reader = stream.getReader();");
- EXPECT_TRUE(underlying_source->HasPendingActivity());
- underlying_source->Enqueue(
- ScriptValue(scope.GetScriptState(), v8::Undefined(scope.GetIsolate())));
- underlying_source->Close();
- EXPECT_FALSE(underlying_source->HasPendingActivity());
-}
-
TEST(ReadableStreamOperationsTest, IsReadable) {
+ ScopedStreamsNativeForTest enabled(false);
+
V8TestingScope scope;
TryCatchScope try_catch_scope(scope.GetIsolate());
@@ -448,6 +423,8 @@ TEST(ReadableStreamOperationsTest, IsReadable) {
}
TEST(ReadableStreamOperationsTest, IsClosed) {
+ ScopedStreamsNativeForTest enabled(false);
+
V8TestingScope scope;
TryCatchScope try_catch_scope(scope.GetIsolate());
@@ -488,6 +465,8 @@ TEST(ReadableStreamOperationsTest, IsClosed) {
}
TEST(ReadableStreamOperationsTest, IsErrored) {
+ ScopedStreamsNativeForTest enabled(false);
+
V8TestingScope scope;
TryCatchScope try_catch_scope(scope.GetIsolate());
@@ -528,6 +507,8 @@ TEST(ReadableStreamOperationsTest, IsErrored) {
}
TEST(ReadableStreamOperationsTest, Tee) {
+ ScopedStreamsNativeForTest enabled(false);
+
V8TestingScope scope;
TryCatchScope try_catch_scope(scope.GetIsolate());
v8::Local<v8::Context> context = scope.GetScriptState()->GetContext();
@@ -599,7 +580,8 @@ TEST(ReadableStreamOperationsTest, Tee) {
}
TEST(ReadableStreamOperationsTest, Serialize) {
- RuntimeEnabledFeatures::SetTransferableStreamsEnabled(true);
+ ScopedStreamsNativeForTest streams_native_enabled(false);
+ ScopedTransferableStreamsForTest transferable_streams_enabled(true);
V8TestingScope scope;
TryCatchScope try_catch_scope(scope.GetIsolate());
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_reader.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_reader.cc
index 7396853b466..66b5a1a999b 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_reader.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_reader.cc
@@ -170,16 +170,6 @@ void ReadableStreamReader::GenericRelease(ScriptState* script_state,
DCHECK_EQ(reader->owner_readable_stream_->reader_, reader);
auto* isolate = script_state->GetIsolate();
- // TODO(yhirano): Remove this when we don"t need hasPendingActivity in
- // blink::UnderlyingSourceBase.
- ReadableStreamDefaultController* controller =
- reader->owner_readable_stream_->readable_stream_controller_;
- if (controller->enable_blink_lock_notifications_) {
- // The stream is created with an external controller (i.e. made in
- // Blink).
- auto lock_notify_target = controller->lock_notify_target_.NewLocal(isolate);
- CallNullaryMethod(script_state, lock_notify_target, "notifyLockReleased");
- }
// 3. If reader.[[ownerReadableStream]].[[state]] is "readable", reject
// reader.[[closedPromise]] with a TypeError exception.
@@ -237,17 +227,6 @@ void ReadableStreamReader::GenericInitialize(ScriptState* script_state,
ReadableStreamReader* reader,
ReadableStreamNative* stream) {
auto* isolate = script_state->GetIsolate();
- // TODO(yhirano): Remove this when we don't need hasPendingActivity in
- // blink::UnderlyingSourceBase.
- ReadableStreamDefaultController* controller =
- stream->readable_stream_controller_;
- if (controller->enable_blink_lock_notifications_) {
- // The stream is created with an external controller (i.e. made in
- // Blink).
- v8::Local<v8::Object> lock_notify_target =
- controller->lock_notify_target_.NewLocal(isolate);
- CallNullaryMethod(script_state, lock_notify_target, "notifyLockAcquired");
- }
// https://streams.spec.whatwg.org/#readable-stream-reader-generic-initialize
// 1. Set reader.[[forAuthorCode]] to true.
@@ -290,32 +269,4 @@ void ReadableStreamReader::GenericInitialize(ScriptState* script_state,
}
}
-void ReadableStreamReader::CallNullaryMethod(ScriptState* script_state,
- v8::Local<v8::Object> object,
- const char* method_name) {
- auto* isolate = script_state->GetIsolate();
- auto context = script_state->GetContext();
- v8::TryCatch try_catch(isolate);
- v8::Local<v8::Value> method;
- if (!object->Get(context, V8AtomicString(isolate, method_name))
- .ToLocal(&method)) {
- DLOG(WARNING) << "Ignored failed lookup of '" << method_name
- << "' in CallNullaryMethod";
- return;
- }
-
- if (!method->IsFunction()) {
- DLOG(WARNING) << "Didn't call '" << method_name
- << "' in CallNullaryMethod because it was the wrong type";
- return;
- }
-
- v8::MaybeLocal<v8::Value> result =
- method.As<v8::Function>()->Call(context, object, 0, nullptr);
- if (result.IsEmpty()) {
- DLOG(WARNING) << "Ignored failure of '" << method_name
- << "' in CallNullaryMethod";
- }
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_reader.h b/chromium/third_party/blink/renderer/core/streams/readable_stream_reader.h
index 3d5f8d3e7c5..ba10befa61e 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_reader.h
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_reader.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_READER_H_
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "v8/include/v8.h"
@@ -25,7 +26,7 @@ class Visitor;
// with the standard, ReadableStreamDefaultReader is implemented by the
// ReadableStreamReader class.
// TODO(ricea): Refactor this when implementing ReadableStreamBYOBReader.
-class ReadableStreamReader : public ScriptWrappable {
+class CORE_EXPORT ReadableStreamReader : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
@@ -81,12 +82,6 @@ class ReadableStreamReader : public ScriptWrappable {
ReadableStreamReader*,
ReadableStreamNative*);
- // Calls method |method_name| on |object|, passing no arguments, and ignoring
- // errors. Used for Blink lock notifications.
- static void CallNullaryMethod(ScriptState*,
- v8::Local<v8::Object> object,
- const char* method_name);
-
Member<StreamPromiseResolver> closed_promise_;
bool for_author_code_ = true;
Member<ReadableStreamNative> owner_readable_stream_;
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_test.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_test.cc
index 8347364aea2..2217f829919 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_test.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_test.cc
@@ -410,13 +410,7 @@ TEST_P(ReadableStreamTest, LockAndDisturb) {
}
TEST_P(ReadableStreamTest, Serialize) {
- if (GetParam()) {
- // Serialize() is not yet supported in the C++ implementation.
- return;
- }
-
ScopedTransferableStreamsForTest enabled(true);
- RuntimeEnabledFeatures::SetTransferableStreamsEnabled(true);
V8TestingScope scope;
auto* script_state = scope.GetScriptState();
diff --git a/chromium/third_party/blink/renderer/core/streams/transferable_streams.cc b/chromium/third_party/blink/renderer/core/streams/transferable_streams.cc
new file mode 100644
index 00000000000..82efecbc340
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/streams/transferable_streams.cc
@@ -0,0 +1,878 @@
+// Copyright 2019 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.
+
+// Functions for transferable streams. See design doc
+// https://docs.google.com/document/d/1_KuZzg5c3pncLJPFa8SuVm23AP4tft6mzPCL5at3I9M/edit
+
+#include "third_party/blink/renderer/core/streams/transferable_streams.h"
+
+#include "base/stl_util.h"
+#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
+#include "third_party/blink/renderer/core/events/message_event.h"
+#include "third_party/blink/renderer/core/messaging/message_port.h"
+#include "third_party/blink/renderer/core/messaging/post_message_options.h"
+#include "third_party/blink/renderer/core/streams/miscellaneous_operations.h"
+#include "third_party/blink/renderer/core/streams/promise_handler.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_default_controller.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_native.h"
+#include "third_party/blink/renderer/core/streams/stream_algorithms.h"
+#include "third_party/blink/renderer/core/streams/stream_promise_resolver.h"
+#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
+#include "third_party/blink/renderer/core/streams/writable_stream_native.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"
+#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/heap/visitor.h"
+#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "v8/include/v8.h"
+
+// See the design doc at
+// https://docs.google.com/document/d/1_KuZzg5c3pncLJPFa8SuVm23AP4tft6mzPCL5at3I9M/edit
+// for explanation of how transferable streams are constructed from the "cross
+// realm identity transform" implemented in this file.
+
+// The peer (the other end of the MessagePort) is untrusted as it may be
+// compromised. This means we have to be very careful in unpacking the messages
+// from the peer. LOG(WARNING) is used for cases where a message from the peer
+// appears to be invalid. If this appears during ordinary testing it indicates a
+// bug.
+//
+// The -vmodule=transferable_streams=3 command-line argument can be used for
+// debugging of the protocol.
+
+namespace blink {
+
+namespace {
+
+// These are the types of messages that are sent between peers.
+enum class MessageType { kPull, kCancel, kChunk, kClose, kAbort, kError };
+
+// These are the different ways an error reason can be encoded.
+enum class ErrorType { kTypeError, kJson, kDomException, kUndefined };
+
+bool IsATypeError(ScriptState* script_state, v8::Local<v8::Object> object) {
+ // There isn't a 100% reliable way to identify a TypeError.
+ return object->IsNativeError() &&
+ object->GetConstructorName()
+ ->Equals(script_state->GetContext(),
+ V8AtomicString(script_state->GetIsolate(), "TypeError"))
+ .ToChecked();
+}
+
+bool IsADOMException(v8::Isolate* isolate, v8::Local<v8::Object> object) {
+ return V8DOMException::HasInstance(object, isolate);
+}
+
+// Creates a JavaScript object with a null prototype structured like {key1:
+// value2, key2: value2}. This is used to create objects to be serialized by
+// postMessage.
+v8::Local<v8::Object> CreateKeyValueObject(v8::Isolate* isolate,
+ const char* key1,
+ v8::Local<v8::Value> value1,
+ const char* key2,
+ v8::Local<v8::Value> value2) {
+ v8::Local<v8::Name> names[] = {V8AtomicString(isolate, key1),
+ V8AtomicString(isolate, key2)};
+ v8::Local<v8::Value> values[] = {value1, value2};
+ static_assert(base::size(names) == base::size(values),
+ "names and values arrays must be the same size");
+ return v8::Object::New(isolate, v8::Null(isolate), names, values,
+ base::size(names));
+}
+
+// Unpacks an object created by CreateKeyValueObject(). |value1| and |value2|
+// are out parameters. Returns false on failure.
+bool UnpackKeyValueObject(ScriptState* script_state,
+ v8::Local<v8::Object> object,
+ const char* key1,
+ v8::Local<v8::Value>* value1,
+ const char* key2,
+ v8::Local<v8::Value>* value2) {
+ auto* isolate = script_state->GetIsolate();
+ v8::TryCatch try_catch(isolate);
+ auto context = script_state->GetContext();
+ if (!object->Get(context, V8AtomicString(isolate, key1)).ToLocal(value1)) {
+ DLOG(WARNING) << "Error reading key: '" << key1 << "'";
+ return false;
+ }
+ if (!object->Get(context, V8AtomicString(isolate, key2)).ToLocal(value2)) {
+ DLOG(WARNING) << "Error reading key: '" << key2 << "'";
+ return false;
+ }
+ return true;
+}
+
+// Send a message with type |type| and contents |value| over |port|. The type
+// will be packed as a number with key "t", and the value will be packed with
+// key "v".
+void PackAndPostMessage(ScriptState* script_state,
+ MessagePort* port,
+ MessageType type,
+ v8::Local<v8::Value> value,
+ ExceptionState& exception_state) {
+ DVLOG(3) << "PackAndPostMessage sending message type "
+ << static_cast<int>(type);
+ auto* isolate = script_state->GetIsolate();
+ v8::Local<v8::Object> packed = CreateKeyValueObject(
+ isolate, "t", v8::Number::New(isolate, static_cast<int>(type)), "v",
+ value);
+ port->postMessage(script_state, ScriptValue(script_state, packed),
+ PostMessageOptions::Create(), exception_state);
+}
+
+// Packs an error into an {e: number, s: string} object for transmission by
+// postMessage. Serializing the resulting object should never fail.
+v8::Local<v8::Object> PackErrorType(v8::Isolate* isolate,
+ ErrorType type,
+ v8::Local<v8::String> string) {
+ auto error_as_number = v8::Number::New(isolate, static_cast<int>(type));
+ return CreateKeyValueObject(isolate, "e", error_as_number, "s", string);
+}
+
+// Overload for the common case where |string| is a compile-time constant.
+v8::Local<v8::Object> PackErrorType(v8::Isolate* isolate,
+ ErrorType type,
+ const char* string) {
+ return PackErrorType(isolate, type, V8String(isolate, string));
+}
+
+// We'd like to able to transfer TypeError exceptions, but we can't, so we hack
+// around it. PackReason() is guaranteed to succeed and the object produced is
+// guaranteed to be serializable by postMessage(), however data may be lost. It
+// is not very efficient, and has fairly arbitrary semantics.
+// TODO(ricea): Replace once Errors are serializable.
+v8::Local<v8::Value> PackReason(ScriptState* script_state,
+ v8::Local<v8::Value> reason) {
+ auto* isolate = script_state->GetIsolate();
+ auto context = script_state->GetContext();
+ if (reason->IsString() || reason->IsNumber() || reason->IsBoolean()) {
+ v8::TryCatch try_catch(isolate);
+ v8::Local<v8::String> stringified;
+ if (!v8::JSON::Stringify(context, reason).ToLocal(&stringified)) {
+ return PackErrorType(isolate, ErrorType::kTypeError,
+ "Cannot transfer message");
+ }
+
+ return PackErrorType(isolate, ErrorType::kJson, stringified);
+ }
+
+ if (reason->IsNull()) {
+ return PackErrorType(isolate, ErrorType::kJson, "null");
+ }
+
+ if (reason->IsFunction() || reason->IsSymbol() || !reason->IsObject()) {
+ // Squash to undefined
+ return PackErrorType(isolate, ErrorType::kUndefined, "");
+ }
+
+ if (IsATypeError(script_state, reason.As<v8::Object>())) {
+ v8::TryCatch try_catch(isolate);
+ // "message" on TypeError is a normal property, meaning that if it
+ // is set, it is set on the object itself. We can take advantage of
+ // this to avoid executing user JavaScript in the case when the
+ // TypeError was generated internally.
+ v8::Local<v8::Value> descriptor;
+ if (!reason.As<v8::Object>()
+ ->GetOwnPropertyDescriptor(context,
+ V8AtomicString(isolate, "message"))
+ .ToLocal(&descriptor)) {
+ return PackErrorType(isolate, ErrorType::kTypeError,
+ "Cannot transfer message");
+ }
+ if (descriptor->IsUndefined()) {
+ return PackErrorType(isolate, ErrorType::kTypeError, "");
+ }
+ v8::Local<v8::Value> message;
+ CHECK(descriptor->IsObject());
+ if (!descriptor.As<v8::Object>()
+ ->Get(context, V8AtomicString(isolate, "value"))
+ .ToLocal(&message)) {
+ message = V8String(isolate, "Cannot transfer message");
+ } else if (!message->IsString()) {
+ message = V8String(isolate, "");
+ }
+ return PackErrorType(isolate, ErrorType::kTypeError,
+ message.As<v8::String>());
+ }
+
+ if (IsADOMException(isolate, reason.As<v8::Object>())) {
+ DOMException* dom_exception =
+ V8DOMException::ToImpl(reason.As<v8::Object>());
+ String message = dom_exception->message();
+ String name = dom_exception->name();
+ v8::Local<v8::Value> packed = CreateKeyValueObject(
+ isolate, "m", V8String(isolate, message), "n", V8String(isolate, name));
+ // It should be impossible for this to fail, except for out-of-memory.
+ v8::Local<v8::String> packed_string =
+ v8::JSON::Stringify(context, packed).ToLocalChecked();
+ return PackErrorType(isolate, ErrorType::kDomException, packed_string);
+ }
+
+ v8::TryCatch try_catch(isolate);
+ v8::Local<v8::Value> json;
+ if (!v8::JSON::Stringify(context, reason).ToLocal(&json)) {
+ return PackErrorType(isolate, ErrorType::kTypeError,
+ "Cannot transfer message");
+ }
+
+ return PackErrorType(isolate, ErrorType::kJson, json.As<v8::String>());
+}
+
+// Converts an object created by PackReason() back into a clone of the original
+// object, minus any data that was discarded by PackReason().
+bool UnpackReason(ScriptState* script_state,
+ v8::Local<v8::Value> packed_reason,
+ v8::Local<v8::Value>* reason) {
+ // We need to be robust against malformed input because it could come from a
+ // compromised renderer.
+ if (!packed_reason->IsObject()) {
+ DLOG(WARNING) << "packed_reason is not an object";
+ return false;
+ }
+
+ v8::Local<v8::Value> encoder_value;
+ v8::Local<v8::Value> string_value;
+ if (!UnpackKeyValueObject(script_state, packed_reason.As<v8::Object>(), "e",
+ &encoder_value, "s", &string_value)) {
+ return false;
+ }
+
+ if (!encoder_value->IsNumber()) {
+ DLOG(WARNING) << "encoder_value is not a number";
+ return false;
+ }
+
+ int encoder = encoder_value.As<v8::Number>()->Value();
+ if (!string_value->IsString()) {
+ DLOG(WARNING) << "string_value is not a string";
+ return false;
+ }
+
+ v8::Local<v8::String> string = string_value.As<v8::String>();
+ auto* isolate = script_state->GetIsolate();
+ auto context = script_state->GetContext();
+ switch (static_cast<ErrorType>(encoder)) {
+ case ErrorType::kJson: {
+ v8::TryCatch try_catch(isolate);
+ if (!v8::JSON::Parse(context, string).ToLocal(reason)) {
+ DLOG(WARNING) << "JSON Parse failed. Content: " << ToCoreString(string);
+ return false;
+ }
+ return true;
+ }
+
+ case ErrorType::kTypeError:
+ *reason = v8::Exception::TypeError(string);
+ return true;
+
+ case ErrorType::kDomException: {
+ v8::TryCatch try_catch(isolate);
+ v8::Local<v8::Value> packed_exception;
+ if (!v8::JSON::Parse(context, string).ToLocal(&packed_exception)) {
+ DLOG(WARNING) << "Packed DOMException JSON parse failed";
+ return false;
+ }
+
+ if (!packed_exception->IsObject()) {
+ DLOG(WARNING) << "Packed DOMException is not an object";
+ return false;
+ }
+
+ v8::Local<v8::Value> message;
+ v8::Local<v8::Value> name;
+ if (!UnpackKeyValueObject(script_state, packed_exception.As<v8::Object>(),
+ "m", &message, "n", &name)) {
+ DLOG(WARNING) << "Failed unpacking packed DOMException";
+ return false;
+ }
+
+ if (!message->IsString()) {
+ DLOG(WARNING) << "DOMException message is not a string";
+ return false;
+ }
+
+ if (!name->IsString()) {
+ DLOG(WARNING) << "DOMException name is not a string";
+ return false;
+ }
+
+ auto ToBlink = [](v8::Local<v8::Value> value) {
+ return ToBlinkString<String>(value.As<v8::String>(), kDoNotExternalize);
+ };
+ *reason = ToV8(DOMException::Create(ToBlink(message), ToBlink(name)),
+ script_state);
+ return true;
+ }
+
+ case ErrorType::kUndefined:
+ *reason = v8::Undefined(isolate);
+ return true;
+
+ default:
+ DLOG(WARNING) << "Invalid ErrorType: " << encoder;
+ return false;
+ }
+}
+
+// Base class for CrossRealmTransformWritable and CrossRealmTransformReadable.
+// Contains common methods that are used when handling MessagePort events.
+class CrossRealmTransformStream
+ : public GarbageCollected<CrossRealmTransformStream> {
+ public:
+ // Neither of the subclasses require finalization, so no destructor.
+
+ virtual ScriptState* GetScriptState() const = 0;
+ virtual MessagePort* GetMessagePort() const = 0;
+
+ // HandleMessage() is called by CrossRealmTransformMessageListener to handle
+ // an incoming message from the MessagePort.
+ virtual void HandleMessage(MessageType type, v8::Local<v8::Value> value) = 0;
+
+ // HandleError() is called by CrossRealmTransformErrorListener when an error
+ // event is fired on the message port. It should error the stream.
+ virtual void HandleError(v8::Local<v8::Value> error) = 0;
+
+ virtual void Trace(Visitor*) {}
+};
+
+// Handles MessageEvents from the MessagePort.
+class CrossRealmTransformMessageListener final : public NativeEventListener {
+ public:
+ explicit CrossRealmTransformMessageListener(CrossRealmTransformStream* target)
+ : target_(target) {}
+
+ void Invoke(ExecutionContext*, Event* event) override {
+ // TODO(ricea): Find a way to guarantee this cast is safe.
+ MessageEvent* message = static_cast<MessageEvent*>(event);
+ ScriptState* script_state = target_->GetScriptState();
+ // The deserializer code called by message->data() looks up the ScriptState
+ // from the current context, so we need to make sure it is set.
+ ScriptState::Scope scope(script_state);
+ v8::Local<v8::Value> data = message->data(script_state).V8Value();
+ if (!data->IsObject()) {
+ DLOG(WARNING) << "Invalid message from peer ignored (not object)";
+ return;
+ }
+
+ v8::Local<v8::Value> type;
+ v8::Local<v8::Value> value;
+ if (!UnpackKeyValueObject(script_state, data.As<v8::Object>(), "t", &type,
+ "v", &value)) {
+ DLOG(WARNING) << "Invalid message from peer ignored";
+ return;
+ }
+
+ if (!type->IsNumber()) {
+ DLOG(WARNING) << "Invalid message from peer ignored (type is not number)";
+ return;
+ }
+
+ int type_value = type.As<v8::Number>()->Value();
+ DVLOG(3) << "MessageListener saw message type " << type_value;
+ target_->HandleMessage(static_cast<MessageType>(type_value), value);
+ }
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(target_);
+ NativeEventListener::Trace(visitor);
+ }
+
+ private:
+ const Member<CrossRealmTransformStream> target_;
+};
+
+// Handles "error" events from the MessagePort.
+class CrossRealmTransformErrorListener final : public NativeEventListener {
+ public:
+ explicit CrossRealmTransformErrorListener(CrossRealmTransformStream* target)
+ : target_(target) {}
+
+ void Invoke(ExecutionContext*, Event*) override {
+ ScriptState* script_state = target_->GetScriptState();
+ const auto* error =
+ DOMException::Create("chunk could not be cloned", "DataCloneError");
+ auto* message_port = target_->GetMessagePort();
+ v8::Local<v8::Value> error_value = ToV8(error, script_state);
+ ExceptionState exception_state(script_state->GetIsolate(),
+ ExceptionState::kUnknownContext, "", "");
+
+ PackAndPostMessage(script_state, message_port, MessageType::kError,
+ PackReason(script_state, error_value), exception_state);
+ if (exception_state.HadException()) {
+ DLOG(WARNING) << "Ignoring postMessage failure in error listener";
+ exception_state.ClearException();
+ }
+
+ message_port->close();
+ target_->HandleError(error_value);
+ }
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(target_);
+ NativeEventListener::Trace(visitor);
+ }
+
+ private:
+ const Member<CrossRealmTransformStream> target_;
+};
+
+// Class for data associated with the writable side of the cross realm transform
+// stream.
+class CrossRealmTransformWritable final : public CrossRealmTransformStream {
+ public:
+ CrossRealmTransformWritable(ScriptState* script_state, MessagePort* port)
+ : script_state_(script_state),
+ message_port_(port),
+ backpressure_promise_(
+ MakeGarbageCollected<StreamPromiseResolver>(script_state)) {}
+
+ WritableStreamNative* CreateWritableStream(ExceptionState&);
+
+ ScriptState* GetScriptState() const override { return script_state_; }
+ MessagePort* GetMessagePort() const override { return message_port_; }
+ void HandleMessage(MessageType type, v8::Local<v8::Value> value) override;
+ void HandleError(v8::Local<v8::Value> error) override;
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(script_state_);
+ visitor->Trace(message_port_);
+ visitor->Trace(backpressure_promise_);
+ visitor->Trace(controller_);
+ CrossRealmTransformStream::Trace(visitor);
+ }
+
+ private:
+ class WriteAlgorithm;
+ class CloseAlgorithm;
+ class AbortAlgorithm;
+
+ const Member<ScriptState> script_state_;
+ const Member<MessagePort> message_port_;
+ Member<StreamPromiseResolver> backpressure_promise_;
+ Member<WritableStreamDefaultController> controller_;
+};
+
+class CrossRealmTransformWritable::WriteAlgorithm final
+ : public StreamAlgorithm {
+ public:
+ explicit WriteAlgorithm(CrossRealmTransformWritable* writable)
+ : writable_(writable) {}
+
+ // Sends the chunk to the readable side, possibly after waiting for
+ // backpressure.
+ v8::Local<v8::Promise> Run(ScriptState* script_state,
+ int argc,
+ v8::Local<v8::Value> argv[]) override {
+ DCHECK_EQ(argc, 1);
+ auto chunk = argv[0];
+
+ if (!writable_->backpressure_promise_) {
+ return DoWrite(script_state, chunk);
+ }
+
+ auto* isolate = script_state->GetIsolate();
+ return StreamThenPromise(
+ script_state->GetContext(),
+ writable_->backpressure_promise_->V8Promise(isolate),
+ MakeGarbageCollected<DoWriteOnResolve>(script_state, chunk, this));
+ }
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(writable_);
+ StreamAlgorithm::Trace(visitor);
+ }
+
+ private:
+ // A promise handler which calls DoWrite() when the promise resolves.
+ class DoWriteOnResolve final : public PromiseHandlerWithValue {
+ public:
+ DoWriteOnResolve(ScriptState* script_state,
+ v8::Local<v8::Value> chunk,
+ WriteAlgorithm* target)
+ : PromiseHandlerWithValue(script_state),
+ chunk_(script_state->GetIsolate(), chunk),
+ target_(target) {}
+
+ v8::Local<v8::Value> CallWithLocal(v8::Local<v8::Value>) override {
+ ScriptState* script_state = GetScriptState();
+ return target_->DoWrite(script_state,
+ chunk_.NewLocal(script_state->GetIsolate()));
+ }
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(chunk_);
+ visitor->Trace(target_);
+ PromiseHandlerWithValue::Trace(visitor);
+ }
+
+ private:
+ const TraceWrapperV8Reference<v8::Value> chunk_;
+ const Member<WriteAlgorithm> target_;
+ };
+
+ // Sends a chunk over the message port to the readable side.
+ v8::Local<v8::Promise> DoWrite(ScriptState* script_state,
+ v8::Local<v8::Value> chunk) {
+ writable_->backpressure_promise_ =
+ MakeGarbageCollected<StreamPromiseResolver>(script_state);
+ ExceptionState exception_state(script_state->GetIsolate(),
+ ExceptionState::kUnknownContext, "", "");
+ PackAndPostMessage(script_state, writable_->message_port_,
+ MessageType::kChunk, chunk, exception_state);
+ if (exception_state.HadException()) {
+ auto exception = exception_state.GetException();
+ exception_state.ClearException();
+
+ PackAndPostMessage(
+ script_state, writable_->message_port_, MessageType::kError,
+ PackReason(writable_->script_state_, exception), exception_state);
+ if (exception_state.HadException()) {
+ DLOG(WARNING) << "Disregarding exception while sending error";
+ exception_state.ClearException();
+ }
+
+ writable_->message_port_->close();
+ return PromiseReject(script_state, exception);
+ }
+
+ return PromiseResolveWithUndefined(script_state);
+ }
+
+ const Member<CrossRealmTransformWritable> writable_;
+};
+
+class CrossRealmTransformWritable::CloseAlgorithm final
+ : public StreamAlgorithm {
+ public:
+ explicit CloseAlgorithm(CrossRealmTransformWritable* writable)
+ : writable_(writable) {}
+
+ // Sends a close message to the readable side and closes the message port.
+ v8::Local<v8::Promise> Run(ScriptState* script_state,
+ int argc,
+ v8::Local<v8::Value> argv[]) override {
+ DCHECK_EQ(argc, 0);
+ ExceptionState exception_state(script_state->GetIsolate(),
+ ExceptionState::kUnknownContext, "", "");
+ PackAndPostMessage(
+ script_state, writable_->message_port_, MessageType::kClose,
+ v8::Undefined(script_state->GetIsolate()), exception_state);
+ if (exception_state.HadException()) {
+ DLOG(WARNING) << "Ignoring exception from PackAndPostMessage kClose";
+ exception_state.ClearException();
+ }
+
+ writable_->message_port_->close();
+ return PromiseResolveWithUndefined(script_state);
+ }
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(writable_);
+ StreamAlgorithm::Trace(visitor);
+ }
+
+ private:
+ const Member<CrossRealmTransformWritable> writable_;
+};
+
+class CrossRealmTransformWritable::AbortAlgorithm final
+ : public StreamAlgorithm {
+ public:
+ explicit AbortAlgorithm(CrossRealmTransformWritable* writable)
+ : writable_(writable) {}
+
+ // Sends an abort message to the readable side and closes the message port.
+ v8::Local<v8::Promise> Run(ScriptState* script_state,
+ int argc,
+ v8::Local<v8::Value> argv[]) override {
+ DCHECK_EQ(argc, 1);
+ auto reason = argv[0];
+ ExceptionState exception_state(script_state->GetIsolate(),
+ ExceptionState::kUnknownContext, "", "");
+ PackAndPostMessage(
+ script_state, writable_->message_port_, MessageType::kAbort,
+ PackReason(writable_->script_state_, reason), exception_state);
+ if (exception_state.HadException()) {
+ DLOG(WARNING) << "Ignoring exception from PackAndPostMessage kAbort";
+ exception_state.ClearException();
+ }
+ writable_->message_port_->close();
+ return PromiseResolveWithUndefined(script_state);
+ }
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(writable_);
+ StreamAlgorithm::Trace(visitor);
+ }
+
+ private:
+ const Member<CrossRealmTransformWritable> writable_;
+};
+
+WritableStreamNative* CrossRealmTransformWritable::CreateWritableStream(
+ ExceptionState& exception_state) {
+ DCHECK(!controller_) << "CreateWritableStream() can only be called once";
+
+ message_port_->setOnmessage(
+ MakeGarbageCollected<CrossRealmTransformMessageListener>(this));
+ message_port_->setOnmessageerror(
+ MakeGarbageCollected<CrossRealmTransformErrorListener>(this));
+
+ auto* stream = WritableStreamNative::Create(
+ script_state_, CreateTrivialStartAlgorithm(),
+ MakeGarbageCollected<WriteAlgorithm>(this),
+ MakeGarbageCollected<CloseAlgorithm>(this),
+ MakeGarbageCollected<AbortAlgorithm>(this), 1,
+ CreateDefaultSizeAlgorithm(), exception_state);
+
+ if (exception_state.HadException()) {
+ return nullptr;
+ }
+
+ controller_ = stream->Controller();
+ return stream;
+}
+
+void CrossRealmTransformWritable::HandleMessage(MessageType type,
+ v8::Local<v8::Value> value) {
+ switch (type) {
+ case MessageType::kPull:
+ DCHECK(backpressure_promise_);
+ backpressure_promise_->ResolveWithUndefined(script_state_);
+ backpressure_promise_ = nullptr;
+ return;
+
+ case MessageType::kCancel:
+ case MessageType::kError: {
+ v8::Local<v8::Value> reason;
+ if (!UnpackReason(script_state_, value, &reason)) {
+ DLOG(WARNING)
+ << "Invalid message from peer ignored (unable to unpack value)";
+ return;
+ }
+ WritableStreamDefaultController::ErrorIfNeeded(script_state_, controller_,
+ reason);
+ if (backpressure_promise_) {
+ backpressure_promise_->ResolveWithUndefined(script_state_);
+ backpressure_promise_ = nullptr;
+ }
+ return;
+ }
+
+ default:
+ DLOG(WARNING) << "Invalid message from peer ignored (invalid type): "
+ << static_cast<int>(type);
+ return;
+ }
+}
+
+void CrossRealmTransformWritable::HandleError(v8::Local<v8::Value> error) {
+ WritableStreamDefaultController::ErrorIfNeeded(script_state_, controller_,
+ error);
+}
+
+// Class for data associated with the readable side of the cross realm transform
+// stream.
+class CrossRealmTransformReadable final : public CrossRealmTransformStream {
+ public:
+ CrossRealmTransformReadable(ScriptState* script_state, MessagePort* port)
+ : script_state_(script_state),
+ message_port_(port),
+ backpressure_promise_(
+ MakeGarbageCollected<StreamPromiseResolver>(script_state)) {}
+
+ ReadableStreamNative* CreateReadableStream(ExceptionState&);
+
+ ScriptState* GetScriptState() const override { return script_state_; }
+ MessagePort* GetMessagePort() const override { return message_port_; }
+ void HandleMessage(MessageType type, v8::Local<v8::Value> value) override;
+ void HandleError(v8::Local<v8::Value> error) override;
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(script_state_);
+ visitor->Trace(message_port_);
+ visitor->Trace(backpressure_promise_);
+ visitor->Trace(controller_);
+ CrossRealmTransformStream::Trace(visitor);
+ }
+
+ private:
+ class PullAlgorithm;
+ class CancelAlgorithm;
+
+ const Member<ScriptState> script_state_;
+ const Member<MessagePort> message_port_;
+ Member<StreamPromiseResolver> backpressure_promise_;
+ Member<ReadableStreamDefaultController> controller_;
+ bool finished_ = false;
+};
+
+class CrossRealmTransformReadable::PullAlgorithm final
+ : public StreamAlgorithm {
+ public:
+ explicit PullAlgorithm(CrossRealmTransformReadable* readable)
+ : readable_(readable) {}
+
+ // Sends a pull message to the writable side and then waits for backpressure
+ // to clear.
+ v8::Local<v8::Promise> Run(ScriptState* script_state,
+ int argc,
+ v8::Local<v8::Value> argv[]) override {
+ DCHECK_EQ(argc, 0);
+ auto* isolate = script_state->GetIsolate();
+ ExceptionState exception_state(isolate, ExceptionState::kUnknownContext, "",
+ "");
+
+ PackAndPostMessage(
+ script_state, readable_->message_port_, MessageType::kPull,
+ v8::Undefined(script_state->GetIsolate()), exception_state);
+ if (exception_state.HadException()) {
+ DLOG(WARNING) << "Ignoring exception from PackAndPostMessage kClose";
+ exception_state.ClearException();
+ }
+
+ return readable_->backpressure_promise_->V8Promise(isolate);
+ }
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(readable_);
+ StreamAlgorithm::Trace(visitor);
+ }
+
+ private:
+ const Member<CrossRealmTransformReadable> readable_;
+};
+
+class CrossRealmTransformReadable::CancelAlgorithm final
+ : public StreamAlgorithm {
+ public:
+ explicit CancelAlgorithm(CrossRealmTransformReadable* readable)
+ : readable_(readable) {}
+
+ // Sends a cancel message to the writable side and closes the message port.
+ v8::Local<v8::Promise> Run(ScriptState* script_state,
+ int argc,
+ v8::Local<v8::Value> argv[]) override {
+ DCHECK_EQ(argc, 1);
+ auto reason = argv[0];
+ readable_->finished_ = true;
+ ExceptionState exception_state(script_state->GetIsolate(),
+ ExceptionState::kUnknownContext, "", "");
+
+ PackAndPostMessage(script_state, readable_->message_port_,
+ MessageType::kCancel, PackReason(script_state, reason),
+ exception_state);
+ if (exception_state.HadException()) {
+ DLOG(WARNING) << "Ignoring exception from PackAndPostMessage kClose";
+ exception_state.ClearException();
+ }
+
+ readable_->message_port_->close();
+ return PromiseResolveWithUndefined(script_state);
+ }
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(readable_);
+ StreamAlgorithm::Trace(visitor);
+ }
+
+ private:
+ const Member<CrossRealmTransformReadable> readable_;
+};
+
+ReadableStreamNative* CrossRealmTransformReadable::CreateReadableStream(
+ ExceptionState& exception_state) {
+ DCHECK(!controller_) << "CreateReadableStream can only be called once";
+
+ message_port_->setOnmessage(
+ MakeGarbageCollected<CrossRealmTransformMessageListener>(this));
+ message_port_->setOnmessageerror(
+ MakeGarbageCollected<CrossRealmTransformErrorListener>(this));
+
+ auto* stream = ReadableStreamNative::Create(
+ script_state_, CreateTrivialStartAlgorithm(),
+ MakeGarbageCollected<PullAlgorithm>(this),
+ MakeGarbageCollected<CancelAlgorithm>(this),
+ /* highWaterMark = */ 0, CreateDefaultSizeAlgorithm(), exception_state);
+
+ if (exception_state.HadException()) {
+ return nullptr;
+ }
+
+ controller_ = stream->GetController();
+ return stream;
+}
+
+void CrossRealmTransformReadable::HandleMessage(MessageType type,
+ v8::Local<v8::Value> value) {
+ switch (type) {
+ case MessageType::kChunk: {
+ // This can't throw because we always use the default strategy size
+ // algorithm, which doesn't throw, and always returns a valid value of
+ // 1.0.
+ ReadableStreamDefaultController::Enqueue(script_state_, controller_,
+ value, ASSERT_NO_EXCEPTION);
+
+ backpressure_promise_->ResolveWithUndefined(script_state_);
+ backpressure_promise_ =
+ MakeGarbageCollected<StreamPromiseResolver>(script_state_);
+ return;
+ }
+
+ case MessageType::kClose:
+ finished_ = true;
+ ReadableStreamDefaultController::Close(script_state_, controller_);
+ message_port_->close();
+ return;
+
+ case MessageType::kAbort:
+ case MessageType::kError: {
+ finished_ = true;
+ v8::Local<v8::Value> reason;
+ if (!UnpackReason(script_state_, value, &reason)) {
+ DLOG(WARNING)
+ << "Invalid message from peer ignored (unable to unpack value)";
+ return;
+ }
+
+ ReadableStreamDefaultController::Error(script_state_, controller_,
+ reason);
+ message_port_->close();
+ return;
+ }
+
+ default:
+ DLOG(WARNING) << "Invalid message from peer ignored (invalid type): "
+ << static_cast<int>(type);
+ return;
+ }
+}
+
+void CrossRealmTransformReadable::HandleError(v8::Local<v8::Value> error) {
+ ReadableStreamDefaultController::Error(script_state_, controller_, error);
+}
+
+} // namespace
+
+CORE_EXPORT WritableStreamNative* CreateCrossRealmTransformWritable(
+ ScriptState* script_state,
+ MessagePort* port,
+ ExceptionState& exception_state) {
+ return MakeGarbageCollected<CrossRealmTransformWritable>(script_state, port)
+ ->CreateWritableStream(exception_state);
+}
+
+CORE_EXPORT ReadableStreamNative* CreateCrossRealmTransformReadable(
+ ScriptState* script_state,
+ MessagePort* port,
+ ExceptionState& exception_state) {
+ return MakeGarbageCollected<CrossRealmTransformReadable>(script_state, port)
+ ->CreateReadableStream(exception_state);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/transferable_streams.h b/chromium/third_party/blink/renderer/core/streams/transferable_streams.h
new file mode 100644
index 00000000000..62883f1d69c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/streams/transferable_streams.h
@@ -0,0 +1,37 @@
+// Copyright 2019 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.
+
+// Functions used to build transferable streams.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFERABLE_STREAMS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFERABLE_STREAMS_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+
+namespace blink {
+
+class ExceptionState;
+class MessagePort;
+class ReadableStreamNative;
+class ScriptState;
+class WritableStreamNative;
+
+// Creates the writable side of a cross-realm identity transform stream, using
+// |port| for communication. |port| must be entangled with another MessagePort
+// which is passed to CreateCrossRealmTransformReadable().
+CORE_EXPORT WritableStreamNative* CreateCrossRealmTransformWritable(
+ ScriptState*,
+ MessagePort* port,
+ ExceptionState&);
+
+// Creates the readable side of a cross-realm identity transform stream. |port|
+// is used symmetrically with CreateCrossRealmTransformWritable().
+CORE_EXPORT ReadableStreamNative* CreateCrossRealmTransformReadable(
+ ScriptState*,
+ MessagePort* port,
+ ExceptionState&);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFERABLE_STREAMS_H_
diff --git a/chromium/third_party/blink/renderer/core/streams/transferable_streams_test.cc b/chromium/third_party/blink/renderer/core/streams/transferable_streams_test.cc
new file mode 100644
index 00000000000..3811b0541e5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/streams/transferable_streams_test.cc
@@ -0,0 +1,129 @@
+// Copyright 2019 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/transferable_streams.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_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_readable_stream_default_reader.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_writable_stream_default_writer.h"
+#include "third_party/blink/renderer/core/messaging/message_channel.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_default_reader.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_native.h"
+#include "third_party/blink/renderer/core/streams/writable_stream_default_writer.h"
+#include "third_party/blink/renderer/core/streams/writable_stream_native.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+
+namespace blink {
+
+namespace {
+
+// We only do minimal testing here. The functionality of transferable streams is
+// tested in the layout tests.
+TEST(TransferableStreamsTest, SmokeTest) {
+ V8TestingScope scope;
+
+ auto* channel =
+ MakeGarbageCollected<MessageChannel>(scope.GetExecutionContext());
+ auto* script_state = scope.GetScriptState();
+ auto* writable = CreateCrossRealmTransformWritable(
+ script_state, channel->port1(), ASSERT_NO_EXCEPTION);
+ ASSERT_TRUE(writable);
+ auto* readable = CreateCrossRealmTransformReadable(
+ script_state, channel->port2(), ASSERT_NO_EXCEPTION);
+ ASSERT_TRUE(readable);
+
+ auto* writer = V8WritableStreamDefaultWriter::ToImpl(
+ writable->getWriter(script_state, ASSERT_NO_EXCEPTION)
+ .V8Value()
+ .As<v8::Object>());
+ auto* reader = V8ReadableStreamDefaultReader::ToImpl(
+ readable->getReader(script_state, ASSERT_NO_EXCEPTION)
+ .V8Value()
+ .As<v8::Object>());
+
+ writer->write(script_state, ScriptValue::CreateNull(script_state));
+
+ class ExpectNullResponse : public ScriptFunction {
+ public:
+ static v8::Local<v8::Function> Create(ScriptState* script_state,
+ bool* got_response) {
+ auto* self =
+ MakeGarbageCollected<ExpectNullResponse>(script_state, got_response);
+ return self->BindToV8Function();
+ }
+
+ ExpectNullResponse(ScriptState* script_state, bool* got_response)
+ : ScriptFunction(script_state), got_response_(got_response) {}
+
+ private:
+ ScriptValue Call(ScriptValue value) override {
+ *got_response_ = true;
+ if (!value.IsObject()) {
+ ADD_FAILURE() << "iterator must be an object";
+ return ScriptValue();
+ }
+ bool done = false;
+ auto* script_state = GetScriptState();
+ auto chunk_maybe =
+ V8UnpackIteratorResult(script_state,
+ value.V8Value()
+ ->ToObject(script_state->GetContext())
+ .ToLocalChecked(),
+ &done);
+ EXPECT_FALSE(done);
+ v8::Local<v8::Value> chunk;
+ if (!chunk_maybe.ToLocal(&chunk)) {
+ ADD_FAILURE() << "V8UnpackIteratorResult failed";
+ return ScriptValue();
+ }
+ EXPECT_TRUE(chunk->IsNull());
+ return ScriptValue();
+ }
+
+ bool* got_response_;
+ };
+
+ // TODO(ricea): This is copy-and-pasted from transform_stream_test.cc. Put it
+ // in a shared location.
+ class ExpectNotReached : public ScriptFunction {
+ public:
+ static v8::Local<v8::Function> Create(ScriptState* script_state) {
+ auto* self = MakeGarbageCollected<ExpectNotReached>(script_state);
+ return self->BindToV8Function();
+ }
+
+ explicit ExpectNotReached(ScriptState* script_state)
+ : ScriptFunction(script_state) {}
+
+ private:
+ ScriptValue Call(ScriptValue) override {
+ ADD_FAILURE() << "ExpectNotReached was reached";
+ return ScriptValue();
+ }
+ };
+
+ bool got_response = false;
+ reader->read(script_state)
+ .Then(ExpectNullResponse::Create(script_state, &got_response),
+ ExpectNotReached::Create(script_state));
+
+ // Need to run the event loop to pass messages through the MessagePort.
+ test::RunPendingTasks();
+
+ // Resolve promises.
+ v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
+
+ EXPECT_TRUE(got_response);
+}
+
+} // namespace
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.h b/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.h
index 3ce613810ae..d87de7fea31 100644
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.h
+++ b/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "v8/include/v8.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream_native.cc b/chromium/third_party/blink/renderer/core/streams/transform_stream_native.cc
index 79040dae29f..825cece3098 100644
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream_native.cc
+++ b/chromium/third_party/blink/renderer/core/streams/transform_stream_native.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/core/streams/transform_stream_native.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/streams/miscellaneous_operations.h"
#include "third_party/blink/renderer/core/streams/promise_handler.h"
#include "third_party/blink/renderer/core/streams/readable_stream_default_controller.h"
@@ -22,7 +21,8 @@
#include "third_party/blink/renderer/platform/bindings/to_v8.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "third_party/blink/renderer/platform/heap/visitor.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream_wrapper.h b/chromium/third_party/blink/renderer/core/streams/transform_stream_wrapper.h
index 022a175c8be..f0668dffaad 100644
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream_wrapper.h
+++ b/chromium/third_party/blink/renderer/core/streams/transform_stream_wrapper.h
@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/platform/heap/member.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "v8/include/v8.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/streams/underlying_sink_base.h b/chromium/third_party/blink/renderer/core/streams/underlying_sink_base.h
index 515b64cd552..9dd9e0bf5ee 100644
--- a/chromium/third_party/blink/renderer/core/streams/underlying_sink_base.h
+++ b/chromium/third_party/blink/renderer/core/streams/underlying_sink_base.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_UNDERLYING_SINK_BASE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_UNDERLYING_SINK_BASE_H_
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/streams/writable_stream_default_controller_interface.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -12,7 +13,6 @@
namespace blink {
-class ScriptPromise;
class ScriptValue;
class ScriptState;
diff --git a/chromium/third_party/blink/renderer/core/streams/underlying_source_base.cc b/chromium/third_party/blink/renderer/core/streams/underlying_source_base.cc
index 6e4ccc9f619..9efc0fe8ad5 100644
--- a/chromium/third_party/blink/renderer/core/streams/underlying_source_base.cc
+++ b/chromium/third_party/blink/renderer/core/streams/underlying_source_base.cc
@@ -47,22 +47,6 @@ ScriptValue UnderlyingSourceBase::type(ScriptState* script_state) const {
return ScriptValue(script_state, v8::Undefined(script_state->GetIsolate()));
}
-void UnderlyingSourceBase::notifyLockAcquired() {
- is_stream_locked_ = true;
-}
-
-void UnderlyingSourceBase::notifyLockReleased() {
- is_stream_locked_ = false;
-}
-
-bool UnderlyingSourceBase::HasPendingActivity() const {
- // This will return false within a finite time period _assuming_ that
- // consumers use the controller to close or error the stream.
- // Browser-created readable streams should always close or error within a
- // finite time period, due to timeouts etc.
- return controller_ && controller_->IsActive() && is_stream_locked_;
-}
-
void UnderlyingSourceBase::ContextDestroyed(ExecutionContext*) {
if (controller_) {
controller_->NoteHasBeenCanceled();
diff --git a/chromium/third_party/blink/renderer/core/streams/underlying_source_base.h b/chromium/third_party/blink/renderer/core/streams/underlying_source_base.h
index 55abd8e3dfb..664f30e87d5 100644
--- a/chromium/third_party/blink/renderer/core/streams/underlying_source_base.h
+++ b/chromium/third_party/blink/renderer/core/streams/underlying_source_base.h
@@ -22,7 +22,6 @@ class ReadableStreamDefaultControllerInterface;
class CORE_EXPORT UnderlyingSourceBase
: public ScriptWrappable,
- public ActiveScriptWrappable<UnderlyingSourceBase>,
public ContextLifecycleObserver {
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(UnderlyingSourceBase);
@@ -41,13 +40,8 @@ class CORE_EXPORT UnderlyingSourceBase
ScriptValue type(ScriptState*) const;
- void notifyLockAcquired();
- void notifyLockReleased();
-
- // ScriptWrappable
- bool HasPendingActivity() const override;
-
// ContextLifecycleObserver
+ // TODO(ricea): Is this still useful?
void ContextDestroyed(ExecutionContext*) override;
protected:
@@ -60,7 +54,6 @@ class CORE_EXPORT UnderlyingSourceBase
private:
Member<ReadableStreamDefaultControllerInterface> controller_;
- bool is_stream_locked_ = false;
};
} // 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 d943658bcc2..bdf11311634 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
@@ -8,7 +8,6 @@
// automatically for use in initializing a ReadableStream.
[
- ActiveScriptWrappable,
NoInterfaceObject
]
interface UnderlyingSourceBase {
@@ -18,7 +17,4 @@ interface UnderlyingSourceBase {
// This only exists to prevent Object.prototype.type being accessed.
[CallWith=ScriptState] readonly attribute any type;
-
- void notifyLockAcquired();
- void notifyLockReleased();
};
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 da3db6e90c5..f0817bf8400 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream.cc
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream.cc
@@ -53,11 +53,27 @@ WritableStream* WritableStream::Create(ScriptState* script_state,
return stream;
}
+WritableStream* WritableStream::CreateWithCountQueueingStrategy(
+ ScriptState* script_state,
+ UnderlyingSinkBase* underlying_sink,
+ size_t high_water_mark) {
+ if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
+ return WritableStreamNative::CreateWithCountQueueingStrategy(
+ script_state, underlying_sink, high_water_mark);
+ }
+
+ return WritableStreamWrapper::CreateWithCountQueueingStrategy(
+ script_state, underlying_sink, high_water_mark);
+}
+
// static
WritableStream* WritableStream::Deserialize(ScriptState* script_state,
MessagePort* port,
ExceptionState& exception_state) {
- // TODO(ricea): Switch on Blink feature.
+ if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
+ return WritableStreamNative::Deserialize(script_state, port,
+ exception_state);
+ }
return WritableStreamWrapper::Deserialize(script_state, port,
exception_state);
}
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 2d57e2195b9..cbc4f61654b 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream.h
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream.h
@@ -15,6 +15,7 @@
namespace blink {
class MessagePort;
+class UnderlyingSinkBase;
// This is an implementation of the corresponding IDL interface.
class CORE_EXPORT WritableStream : public ScriptWrappable {
@@ -31,6 +32,10 @@ class CORE_EXPORT WritableStream : public ScriptWrappable {
ScriptValue underlying_sink,
ScriptValue strategy,
ExceptionState&);
+ static WritableStream* CreateWithCountQueueingStrategy(
+ ScriptState*,
+ UnderlyingSinkBase*,
+ size_t high_water_mark);
// IDL defined functions
virtual bool locked(ScriptState*, ExceptionState&) const = 0;
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_default_writer.h b/chromium/third_party/blink/renderer/core/streams/writable_stream_default_writer.h
index 1bb5bea8112..fbe239eac20 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_default_writer.h
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_default_writer.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_WRITABLE_STREAM_DEFAULT_WRITER_H_
#include "base/optional.h"
+#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "v8/include/v8.h"
@@ -21,7 +22,7 @@ class WritableStream;
class WritableStreamNative;
// https://streams.spec.whatwg.org/#default-writer-class
-class WritableStreamDefaultWriter final : public ScriptWrappable {
+class CORE_EXPORT WritableStreamDefaultWriter final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_native.cc b/chromium/third_party/blink/renderer/core/streams/writable_stream_native.cc
index 262a9833c1b..4c8477811ac 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_native.cc
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_native.cc
@@ -7,7 +7,11 @@
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/streams/miscellaneous_operations.h"
#include "third_party/blink/renderer/core/streams/promise_handler.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_native.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_operations.h"
#include "third_party/blink/renderer/core/streams/stream_promise_resolver.h"
+#include "third_party/blink/renderer/core/streams/transferable_streams.h"
+#include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
#include "third_party/blink/renderer/core/streams/writable_stream_default_writer.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -215,6 +219,67 @@ WritableStreamNative* WritableStreamNative::Create(
return stream;
}
+// static
+WritableStreamNative* WritableStreamNative::CreateWithCountQueueingStrategy(
+ ScriptState* script_state,
+ UnderlyingSinkBase* underlying_sink,
+ size_t high_water_mark) {
+ // TODO(crbug.com/902633): This method of constructing a WritableStream
+ // introduces unnecessary trips through the V8. Perhaps we should implement
+ // algorithms based on an UnderlyingSinkBase, or C++ stream implementations
+ // should provide the algorithms directly.
+ ScriptValue strategy = ReadableStreamOperations::CreateCountQueuingStrategy(
+ script_state, high_water_mark);
+ if (strategy.IsEmpty())
+ return nullptr;
+
+ auto underlying_sink_value = ScriptValue::From(script_state, underlying_sink);
+
+ ExceptionState exception_state(script_state->GetIsolate(),
+ ExceptionState::kConstructionContext,
+ "WritableStream");
+ auto* stream = MakeGarbageCollected<WritableStreamNative>(
+ script_state, underlying_sink_value, strategy, exception_state);
+ if (exception_state.HadException())
+ return nullptr;
+ return stream;
+}
+
+void WritableStreamNative::Serialize(ScriptState* script_state,
+ MessagePort* port,
+ ExceptionState& exception_state) {
+ if (IsLocked(this)) {
+ exception_state.ThrowTypeError("Cannot transfer a locked stream");
+ return;
+ }
+
+ auto* readable =
+ CreateCrossRealmTransformReadable(script_state, port, exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+
+ auto promise = ReadableStreamNative::PipeTo(
+ script_state, readable, this, ReadableStreamNative::PipeOptions());
+ promise.MarkAsHandled();
+}
+
+WritableStreamNative* WritableStreamNative::Deserialize(
+ ScriptState* script_state,
+ MessagePort* port,
+ ExceptionState& exception_state) {
+ // We need to execute JavaScript to call "Then" on v8::Promises. We will not
+ // run author code.
+ v8::Isolate::AllowJavascriptExecutionScope allow_js(
+ script_state->GetIsolate());
+ auto* writable =
+ CreateCrossRealmTransformWritable(script_state, port, exception_state);
+ if (exception_state.HadException()) {
+ return nullptr;
+ }
+ return writable;
+}
+
WritableStreamDefaultWriter* WritableStreamNative::AcquireDefaultWriter(
ScriptState* script_state,
WritableStreamNative* stream,
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_native.h b/chromium/third_party/blink/renderer/core/streams/writable_stream_native.h
index 64f80fc2fdd..e37cac9a68c 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_native.h
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_native.h
@@ -20,6 +20,7 @@ class StrategySizeAlgorithm;
class StreamAlgorithm;
class StreamPromiseResolver;
class StreamStartAlgorithm;
+class UnderlyingSinkBase;
class WritableStreamDefaultController;
class WritableStreamDefaultWriter;
@@ -44,6 +45,11 @@ class CORE_EXPORT WritableStreamNative : public WritableStream {
StrategySizeAlgorithm* size_algorithm,
ExceptionState&);
+ static WritableStreamNative* CreateWithCountQueueingStrategy(
+ ScriptState*,
+ UnderlyingSinkBase*,
+ size_t high_water_mark);
+
// Used by Create().
WritableStreamNative();
@@ -83,9 +89,11 @@ class CORE_EXPORT WritableStreamNative : public WritableStream {
return stream->writer_;
}
- void Serialize(ScriptState*, MessagePort*, ExceptionState&) override {
- // TODO(ricea): Implement this.
- }
+ void Serialize(ScriptState*, MessagePort*, ExceptionState&) override;
+
+ static WritableStreamNative* Deserialize(ScriptState*,
+ MessagePort*,
+ ExceptionState&);
//
// Methods used by ReadableStreamNative::PipeTo
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_test.cc b/chromium/third_party/blink/renderer/core/streams/writable_stream_test.cc
index 5401cc714fc..e87946d1063 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_test.cc
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_test.cc
@@ -60,12 +60,6 @@ TEST_P(WritableStreamTest, GetWriter) {
}
TEST_P(WritableStreamTest, Serialize) {
- // Disable the test when StreamsNative is enabled as WritableStreamNative
- // doesn't support serialization yet.
- // TODO(ricea): Re-enable this test when serialization is supported.
- if (GetParam())
- return;
-
ScopedTransferableStreamsForTest enable_transferable_streams(true);
V8TestingScope scope;
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
index 277aa68d67a..6e6ffcd7ab3 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.cc
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.cc
@@ -7,6 +7,8 @@
#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/readable_stream_operations.h"
+#include "third_party/blink/renderer/core/streams/underlying_sink_base.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"
@@ -46,6 +48,27 @@ WritableStreamWrapper* WritableStreamWrapper::CreateFromInternalStream(
return stream;
}
+WritableStreamWrapper* WritableStreamWrapper::CreateWithCountQueueingStrategy(
+ ScriptState* script_state,
+ UnderlyingSinkBase* underlying_sink,
+ size_t high_water_mark) {
+ ScriptValue strategy = ReadableStreamOperations::CreateCountQueuingStrategy(
+ script_state, high_water_mark);
+ if (strategy.IsEmpty())
+ return nullptr;
+
+ auto underlying_sink_value = ScriptValue::From(script_state, underlying_sink);
+ auto* stream = MakeGarbageCollected<WritableStreamWrapper>();
+
+ ExceptionState exception_state(script_state->GetIsolate(),
+ ExceptionState::kConstructionContext,
+ "WritableStream");
+ stream->Init(script_state, underlying_sink_value, strategy, exception_state);
+ if (exception_state.HadException())
+ return nullptr;
+ return stream;
+}
+
bool WritableStreamWrapper::InitInternal(
ScriptState* script_state,
v8::Local<v8::Object> internal_stream) {
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
index 4a24ad85ae6..658c6d10225 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.h
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.h
@@ -16,6 +16,7 @@
namespace blink {
class MessagePort;
+class WritableStreamWrapper;
// This is an implementation of the WritableStream interface that delegates to
// the V8 Extras implementation.
@@ -46,6 +47,11 @@ class CORE_EXPORT WritableStreamWrapper final : public WritableStream {
v8::Local<v8::Object> internal_stream,
ExceptionState&);
+ static WritableStreamWrapper* CreateWithCountQueueingStrategy(
+ ScriptState*,
+ UnderlyingSinkBase*,
+ size_t high_water_mark);
+
void Trace(Visitor* visitor) override;
// IDL defined functions