Commit 119b15f3 authored by Adam Rice's avatar Adam Rice Committed by Commit Bot

Make blink::ReadableStream a pure interface

Move ReadableStream to ReadableStreamWrapper. Make ReadableStream be an
interface which can have multiple implementations. Make
ReadableStreamWrapper implement the ReadableStream interface, and be
delegated to by the ReadableStream static methods.

Deprecate ReadableStreamOperations as it won't work with the new
implementation.

BUG=902633

Change-Id: Idcc8ae62e787e5696698f13229d19c91ca7a7e74
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1494394Reviewed-by: default avatarYutaka Hirano <yhirano@chromium.org>
Commit-Queue: Adam Rice <ricea@chromium.org>
Cr-Commit-Position: refs/heads/master@{#637651}
parent b3d1fcce
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_readable_stream.h" #include "third_party/blink/renderer/bindings/core/v8/v8_readable_stream.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h" #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/streams/readable_stream.h" #include "third_party/blink/renderer/core/streams/readable_stream_wrapper.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_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/bindings/v8_binding.h"
...@@ -30,7 +30,9 @@ void V8ReadableStream::ConstructorCustom( ...@@ -30,7 +30,9 @@ void V8ReadableStream::ConstructorCustom(
ScriptValue strategy = ScriptValue(ScriptState::Current(info.GetIsolate()), ScriptValue strategy = ScriptValue(ScriptState::Current(info.GetIsolate()),
v8::Undefined(info.GetIsolate())); v8::Undefined(info.GetIsolate()));
int num_args = info.Length(); int num_args = info.Length();
auto* impl = MakeGarbageCollected<ReadableStream>(); // TODO(ricea): Switch implementation based on StreamsNative feature flag
// here.
auto* impl = MakeGarbageCollected<ReadableStreamWrapper>();
v8::Local<v8::Object> wrapper = info.Holder(); v8::Local<v8::Object> wrapper = info.Holder();
wrapper = impl->AssociateWithWrapper( wrapper = impl->AssociateWithWrapper(
info.GetIsolate(), V8ReadableStream::GetWrapperTypeInfo(), wrapper); info.GetIsolate(), V8ReadableStream::GetWrapperTypeInfo(), wrapper);
......
...@@ -349,7 +349,7 @@ void BodyStreamBuffer::CloseAndLockAndDisturb(ExceptionState& exception_state) { ...@@ -349,7 +349,7 @@ void BodyStreamBuffer::CloseAndLockAndDisturb(ExceptionState& exception_state) {
return; return;
} }
if (stream_->IsInternalStreamMissing()) { if (stream_->IsBroken()) {
stream_broken_ = true; stream_broken_ = true;
exception_state.ThrowDOMException( exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError, DOMExceptionCode::kInvalidStateError,
......
...@@ -19,6 +19,8 @@ blink_core_sources("streams") { ...@@ -19,6 +19,8 @@ blink_core_sources("streams") {
"readable_stream_default_reader.h", "readable_stream_default_reader.h",
"readable_stream_operations.cc", "readable_stream_operations.cc",
"readable_stream_operations.h", "readable_stream_operations.h",
"readable_stream_wrapper.cc",
"readable_stream_wrapper.h",
"retain_wrapper_during_construction.cc", "retain_wrapper_during_construction.cc",
"retain_wrapper_during_construction.h", "retain_wrapper_during_construction.h",
"stream_algorithms.h", "stream_algorithms.h",
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include "base/optional.h" #include "base/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h" #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.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" #include "v8/include/v8.h"
namespace blink { namespace blink {
...@@ -25,22 +24,8 @@ class CORE_EXPORT ReadableStream : public ScriptWrappable { ...@@ -25,22 +24,8 @@ class CORE_EXPORT ReadableStream : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO(); DEFINE_WRAPPERTYPEINFO();
public: public:
// Call one of Init functions before using the instance. // Create* functions create an appropriate subclass depending on which
ReadableStream() = default; // implementation is selected by blink features.
~ReadableStream() override = default;
// If an error happens, |exception_state.HadException()| will be true, and
// |this| will not be usable after that.
void Init(ScriptState*,
ScriptValue underlying_source,
ScriptValue strategy,
ExceptionState& exception_state);
void InitWithInternalStream(ScriptState*,
v8::Local<v8::Object> object,
ExceptionState& exception_state);
// Create* functions call Init* internally and returns null when an error
// happens.
static ReadableStream* Create(ScriptState*, ExceptionState&); static ReadableStream* Create(ScriptState*, ExceptionState&);
static ReadableStream* Create(ScriptState*, static ReadableStream* Create(ScriptState*,
ScriptValue underlying_source, ScriptValue underlying_source,
...@@ -49,12 +34,7 @@ class CORE_EXPORT ReadableStream : public ScriptWrappable { ...@@ -49,12 +34,7 @@ class CORE_EXPORT ReadableStream : public ScriptWrappable {
ScriptValue underlying_source, ScriptValue underlying_source,
ScriptValue strategy, ScriptValue strategy,
ExceptionState&); ExceptionState&);
static ReadableStream* CreateFromInternalStream(ScriptState*,
v8::Local<v8::Object> object,
ExceptionState&);
static ReadableStream* CreateFromInternalStream(ScriptState*,
ScriptValue object,
ExceptionState&);
// This function doesn't take ExceptionState because the caller cannot have // This function doesn't take ExceptionState because the caller cannot have
// one. Returns null when an error happens. // one. Returns null when an error happens.
static ReadableStream* CreateWithCountQueueingStrategy( static ReadableStream* CreateWithCountQueueingStrategy(
...@@ -62,45 +42,54 @@ class CORE_EXPORT ReadableStream : public ScriptWrappable { ...@@ -62,45 +42,54 @@ class CORE_EXPORT ReadableStream : public ScriptWrappable {
UnderlyingSourceBase* underlying_source, UnderlyingSourceBase* underlying_source,
size_t high_water_mark); size_t high_water_mark);
void Trace(Visitor* visitor) override;
// IDL defined functions // IDL defined functions
bool locked(ScriptState*, ExceptionState&) const; virtual bool locked(ScriptState*, ExceptionState&) const = 0;
ScriptPromise cancel(ScriptState*, ExceptionState&); virtual ScriptPromise cancel(ScriptState*, ExceptionState&) = 0;
ScriptPromise cancel(ScriptState*, ScriptValue reason, ExceptionState&); virtual ScriptPromise cancel(ScriptState*,
ScriptValue getReader(ScriptState*, ExceptionState&); ScriptValue reason,
ScriptValue getReader(ScriptState*, ScriptValue options, ExceptionState&); ExceptionState&) = 0;
ScriptValue pipeThrough(ScriptState*, virtual ScriptValue getReader(ScriptState*, ExceptionState&) = 0;
virtual ScriptValue getReader(ScriptState*,
ScriptValue options,
ExceptionState&) = 0;
virtual ScriptValue pipeThrough(ScriptState*,
ScriptValue transform_stream, ScriptValue transform_stream,
ExceptionState&); ExceptionState&) = 0;
ScriptValue pipeThrough(ScriptState*, virtual ScriptValue pipeThrough(ScriptState*,
ScriptValue transform_stream, ScriptValue transform_stream,
ScriptValue options, ScriptValue options,
ExceptionState&); ExceptionState&) = 0;
ScriptPromise pipeTo(ScriptState*, ScriptValue destination, ExceptionState&); virtual ScriptPromise pipeTo(ScriptState*,
ScriptPromise pipeTo(ScriptState*, ScriptValue destination,
ExceptionState&) = 0;
virtual ScriptPromise pipeTo(ScriptState*,
ScriptValue destination, ScriptValue destination,
ScriptValue options, ScriptValue options,
ExceptionState&); ExceptionState&) = 0;
ScriptValue tee(ScriptState*, ExceptionState&); virtual ScriptValue tee(ScriptState*, ExceptionState&) = 0;
void Tee(ScriptState*, virtual void Tee(ScriptState*,
ReadableStream** branch1, ReadableStream** branch1,
ReadableStream** branch2, ReadableStream** branch2,
ExceptionState&); ExceptionState&) = 0;
base::Optional<bool> IsLocked(ScriptState*, ExceptionState&) const; virtual base::Optional<bool> IsLocked(ScriptState*,
base::Optional<bool> IsDisturbed(ScriptState*, ExceptionState&) const; ExceptionState&) const = 0;
base::Optional<bool> IsReadable(ScriptState*, ExceptionState&) const; virtual base::Optional<bool> IsDisturbed(ScriptState*,
base::Optional<bool> IsClosed(ScriptState*, ExceptionState&) const; ExceptionState&) const = 0;
base::Optional<bool> IsErrored(ScriptState*, ExceptionState&) const; virtual base::Optional<bool> IsReadable(ScriptState*,
ExceptionState&) const = 0;
virtual base::Optional<bool> IsClosed(ScriptState*,
ExceptionState&) const = 0;
virtual base::Optional<bool> IsErrored(ScriptState*,
ExceptionState&) const = 0;
// Makes this stream locked and disturbed. // Makes this stream locked and disturbed.
void LockAndDisturb(ScriptState*, ExceptionState&); virtual void LockAndDisturb(ScriptState*, ExceptionState&) = 0;
// Serialize this stream to |port|. The stream will be locked by this // Serialize this stream to |port|. The stream will be locked by this
// operation. // operation.
void Serialize(ScriptState*, MessagePort* port, ExceptionState&); virtual void Serialize(ScriptState*, MessagePort* port, ExceptionState&) = 0;
// Given a |port| which is entangled with a MessagePort that was previously // Given a |port| which is entangled with a MessagePort that was previously
// passed to Serialize(), returns a new ReadableStream which behaves like it // passed to Serialize(), returns a new ReadableStream which behaves like it
...@@ -109,18 +98,12 @@ class CORE_EXPORT ReadableStream : public ScriptWrappable { ...@@ -109,18 +98,12 @@ class CORE_EXPORT ReadableStream : public ScriptWrappable {
MessagePort* port, MessagePort* port,
ExceptionState&); ExceptionState&);
ScriptValue GetInternalStream(ScriptState* script_state) const;
// In some cases we are known to fail to trace the stream correctly. In such // In some cases we are known to fail to trace the stream correctly. In such
// cases |object_| will be silently gone. This function is for detecting the // cases internal references will be silently lost. This function is for
// issue. Use this function at places where an actual crash happens. Do not // detecting the issue. Use this function at places where an actual crash
// use this function to write "just in case" code. // happens. Do not use this function to write "just in case" code.
bool IsInternalStreamMissing() const { return object_.IsEmpty(); } // TODO(ricea): Remove this after switching to the new implementation.
virtual bool IsBroken() const = 0;
private:
class NoopFunction;
TraceWrapperV8Reference<v8::Object> object_;
}; };
} // namespace blink } // namespace blink
......
...@@ -19,6 +19,11 @@ class ScriptState; ...@@ -19,6 +19,11 @@ class ScriptState;
// This class has various methods for ReadableStream[Reader] implemented with // This class has various methods for ReadableStream[Reader] implemented with
// V8 Extras. // V8 Extras.
//
// DEPRECATED: None of these functions work correctly with the new C++
// implementation of ReadableStream. Use the ReadableStream API directly
// instead.
//
// All methods should be called in an appropriate V8 context. All ScriptValue // All methods should be called in an appropriate V8 context. All ScriptValue
// arguments must not be empty. // arguments must not be empty.
// //
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "third_party/blink/renderer/core/messaging/message_channel.h" #include "third_party/blink/renderer/core/messaging/message_channel.h"
#include "third_party/blink/renderer/core/streams/readable_stream.h" #include "third_party/blink/renderer/core/streams/readable_stream.h"
#include "third_party/blink/renderer/core/streams/readable_stream_default_controller_wrapper.h" #include "third_party/blink/renderer/core/streams/readable_stream_default_controller_wrapper.h"
#include "third_party/blink/renderer/core/streams/readable_stream_wrapper.h"
#include "third_party/blink/renderer/core/streams/test_underlying_source.h" #include "third_party/blink/renderer/core/streams/test_underlying_source.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h"
...@@ -112,6 +113,23 @@ class ReaderFunction : public ScriptFunction { ...@@ -112,6 +113,23 @@ class ReaderFunction : public ScriptFunction {
Member<Iteration> iteration_; Member<Iteration> iteration_;
}; };
// Returns the internal V8 Extras implementation of a ReadableStream object.
// Requires StreamsNative feature to be off.
ScriptValue CheckedGetInternalStream(ScriptState* script_state,
ReadableStream* readable_stream) {
CHECK(!RuntimeEnabledFeatures::StreamsNativeEnabled());
ReadableStreamWrapper* readable_stream_wrapper =
static_cast<ReadableStreamWrapper*>(readable_stream);
return readable_stream_wrapper->GetInternalStream(script_state);
}
ScriptValue CheckedGetInternalStream(ScriptState* script_state,
ScriptValue stream) {
ReadableStream* readable_stream =
V8ReadableStream::ToImpl(stream.V8Value().As<v8::Object>());
return CheckedGetInternalStream(script_state, readable_stream);
}
TEST(ReadableStreamOperationsTest, IsReadableStream) { TEST(ReadableStreamOperationsTest, IsReadableStream) {
V8TestingScope scope; V8TestingScope scope;
TryCatchScope try_catch_scope(scope.GetIsolate()); TryCatchScope try_catch_scope(scope.GetIsolate());
...@@ -141,8 +159,7 @@ TEST(ReadableStreamOperationsTest, IsReadableStream) { ...@@ -141,8 +159,7 @@ TEST(ReadableStreamOperationsTest, IsReadableStream) {
scope.GetIsolate())); scope.GetIsolate()));
ScriptValue internal_stream = ScriptValue internal_stream =
V8ReadableStream::ToImpl(stream.V8Value().As<v8::Object>()) CheckedGetInternalStream(scope.GetScriptState(), stream);
->GetInternalStream(scope.GetScriptState());
ASSERT_FALSE(internal_stream.IsEmpty()); ASSERT_FALSE(internal_stream.IsEmpty());
EXPECT_TRUE(ReadableStreamOperations::IsReadableStream( EXPECT_TRUE(ReadableStreamOperations::IsReadableStream(
scope.GetScriptState(), internal_stream, ASSERT_NO_EXCEPTION) scope.GetScriptState(), internal_stream, ASSERT_NO_EXCEPTION)
...@@ -185,7 +202,7 @@ TEST(ReadableStreamOperationsTest, GetReader) { ...@@ -185,7 +202,7 @@ TEST(ReadableStreamOperationsTest, GetReader) {
ASSERT_TRUE(stream); ASSERT_TRUE(stream);
ScriptValue internal_stream = ScriptValue internal_stream =
stream->GetInternalStream(scope.GetScriptState()); CheckedGetInternalStream(scope.GetScriptState(), stream);
ASSERT_FALSE(internal_stream.IsEmpty()); ASSERT_FALSE(internal_stream.IsEmpty());
EXPECT_EQ(ReadableStreamOperations::IsLocked( EXPECT_EQ(ReadableStreamOperations::IsLocked(
...@@ -222,7 +239,7 @@ TEST(ReadableStreamOperationsTest, IsDisturbed) { ...@@ -222,7 +239,7 @@ TEST(ReadableStreamOperationsTest, IsDisturbed) {
ASSERT_TRUE(stream); ASSERT_TRUE(stream);
ScriptValue internal_stream = ScriptValue internal_stream =
stream->GetInternalStream(scope.GetScriptState()); CheckedGetInternalStream(scope.GetScriptState(), stream);
EXPECT_EQ(ReadableStreamOperations::IsDisturbed( EXPECT_EQ(ReadableStreamOperations::IsDisturbed(
scope.GetScriptState(), internal_stream, ASSERT_NO_EXCEPTION), scope.GetScriptState(), internal_stream, ASSERT_NO_EXCEPTION),
base::make_optional(false)); base::make_optional(false));
...@@ -365,7 +382,8 @@ TEST(ReadableStreamOperationsTest, ...@@ -365,7 +382,8 @@ TEST(ReadableStreamOperationsTest,
scope.GetScriptState(), underlying_source, strategy); scope.GetScriptState(), underlying_source, strategy);
ASSERT_FALSE(internal_stream.IsEmpty()); ASSERT_FALSE(internal_stream.IsEmpty());
auto* stream = ReadableStream::CreateFromInternalStream( CHECK(!RuntimeEnabledFeatures::StreamsNativeEnabled());
auto* stream = ReadableStreamWrapper::CreateFromInternalStream(
scope.GetScriptState(), internal_stream, ASSERT_NO_EXCEPTION); scope.GetScriptState(), internal_stream, ASSERT_NO_EXCEPTION);
ASSERT_TRUE(stream); ASSERT_TRUE(stream);
...@@ -414,17 +432,17 @@ TEST(ReadableStreamOperationsTest, IsReadable) { ...@@ -414,17 +432,17 @@ TEST(ReadableStreamOperationsTest, IsReadable) {
EXPECT_EQ(ReadableStreamOperations::IsReadable( EXPECT_EQ(ReadableStreamOperations::IsReadable(
scope.GetScriptState(), scope.GetScriptState(),
readable->GetInternalStream(scope.GetScriptState()), CheckedGetInternalStream(scope.GetScriptState(), readable),
ASSERT_NO_EXCEPTION), ASSERT_NO_EXCEPTION),
base::make_optional(true)); base::make_optional(true));
EXPECT_EQ(ReadableStreamOperations::IsReadable( EXPECT_EQ(ReadableStreamOperations::IsReadable(
scope.GetScriptState(), scope.GetScriptState(),
closed->GetInternalStream(scope.GetScriptState()), CheckedGetInternalStream(scope.GetScriptState(), closed),
ASSERT_NO_EXCEPTION), ASSERT_NO_EXCEPTION),
base::make_optional(false)); base::make_optional(false));
EXPECT_EQ(ReadableStreamOperations::IsReadable( EXPECT_EQ(ReadableStreamOperations::IsReadable(
scope.GetScriptState(), scope.GetScriptState(),
errored->GetInternalStream(scope.GetScriptState()), CheckedGetInternalStream(scope.GetScriptState(), errored),
ASSERT_NO_EXCEPTION), ASSERT_NO_EXCEPTION),
base::make_optional(false)); base::make_optional(false));
} }
...@@ -454,17 +472,17 @@ TEST(ReadableStreamOperationsTest, IsClosed) { ...@@ -454,17 +472,17 @@ TEST(ReadableStreamOperationsTest, IsClosed) {
EXPECT_EQ(ReadableStreamOperations::IsClosed( EXPECT_EQ(ReadableStreamOperations::IsClosed(
scope.GetScriptState(), scope.GetScriptState(),
readable->GetInternalStream(scope.GetScriptState()), CheckedGetInternalStream(scope.GetScriptState(), readable),
ASSERT_NO_EXCEPTION), ASSERT_NO_EXCEPTION),
base::make_optional(false)); base::make_optional(false));
EXPECT_EQ(ReadableStreamOperations::IsClosed( EXPECT_EQ(ReadableStreamOperations::IsClosed(
scope.GetScriptState(), scope.GetScriptState(),
closed->GetInternalStream(scope.GetScriptState()), CheckedGetInternalStream(scope.GetScriptState(), closed),
ASSERT_NO_EXCEPTION), ASSERT_NO_EXCEPTION),
base::make_optional(true)); base::make_optional(true));
EXPECT_EQ(ReadableStreamOperations::IsClosed( EXPECT_EQ(ReadableStreamOperations::IsClosed(
scope.GetScriptState(), scope.GetScriptState(),
errored->GetInternalStream(scope.GetScriptState()), CheckedGetInternalStream(scope.GetScriptState(), errored),
ASSERT_NO_EXCEPTION), ASSERT_NO_EXCEPTION),
base::make_optional(false)); base::make_optional(false));
} }
...@@ -494,17 +512,17 @@ TEST(ReadableStreamOperationsTest, IsErrored) { ...@@ -494,17 +512,17 @@ TEST(ReadableStreamOperationsTest, IsErrored) {
EXPECT_EQ(ReadableStreamOperations::IsErrored( EXPECT_EQ(ReadableStreamOperations::IsErrored(
scope.GetScriptState(), scope.GetScriptState(),
readable->GetInternalStream(scope.GetScriptState()), CheckedGetInternalStream(scope.GetScriptState(), readable),
ASSERT_NO_EXCEPTION), ASSERT_NO_EXCEPTION),
base::make_optional(false)); base::make_optional(false));
EXPECT_EQ(ReadableStreamOperations::IsErrored( EXPECT_EQ(ReadableStreamOperations::IsErrored(
scope.GetScriptState(), scope.GetScriptState(),
closed->GetInternalStream(scope.GetScriptState()), CheckedGetInternalStream(scope.GetScriptState(), closed),
ASSERT_NO_EXCEPTION), ASSERT_NO_EXCEPTION),
base::make_optional(false)); base::make_optional(false));
EXPECT_EQ(ReadableStreamOperations::IsErrored( EXPECT_EQ(ReadableStreamOperations::IsErrored(
scope.GetScriptState(), scope.GetScriptState(),
errored->GetInternalStream(scope.GetScriptState()), CheckedGetInternalStream(scope.GetScriptState(), errored),
ASSERT_NO_EXCEPTION), ASSERT_NO_EXCEPTION),
base::make_optional(true)); base::make_optional(true));
} }
...@@ -521,7 +539,8 @@ TEST(ReadableStreamOperationsTest, Tee) { ...@@ -521,7 +539,8 @@ TEST(ReadableStreamOperationsTest, Tee) {
ASSERT_TRUE(stream); ASSERT_TRUE(stream);
ScriptValue result = ReadableStreamOperations::Tee( ScriptValue result = ReadableStreamOperations::Tee(
scope.GetScriptState(), stream->GetInternalStream(scope.GetScriptState()), scope.GetScriptState(),
CheckedGetInternalStream(scope.GetScriptState(), stream),
exception_state); exception_state);
ASSERT_FALSE(result.IsEmpty()); ASSERT_FALSE(result.IsEmpty());
ASSERT_TRUE(result.IsObject()); ASSERT_TRUE(result.IsObject());
...@@ -593,7 +612,7 @@ TEST(ReadableStreamOperationsTest, Serialize) { ...@@ -593,7 +612,7 @@ TEST(ReadableStreamOperationsTest, Serialize) {
source->Enqueue(ScriptValue(scope.GetScriptState(), source->Enqueue(ScriptValue(scope.GetScriptState(),
V8String(scope.GetIsolate(), "hello"))); V8String(scope.GetIsolate(), "hello")));
ScriptValue internal_stream = ScriptValue internal_stream =
stream->GetInternalStream(scope.GetScriptState()); CheckedGetInternalStream(scope.GetScriptState(), stream);
MessageChannel* channel = MessageChannel::Create(scope.GetExecutionContext()); MessageChannel* channel = MessageChannel::Create(scope.GetExecutionContext());
ReadableStreamOperations::Serialize(scope.GetScriptState(), internal_stream, ReadableStreamOperations::Serialize(scope.GetScriptState(), internal_stream,
channel->port1(), ASSERT_NO_EXCEPTION); channel->port1(), ASSERT_NO_EXCEPTION);
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_WRAPPER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_WRAPPER_H_
#include "base/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/streams/readable_stream.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "v8/include/v8.h"
namespace blink {
// This is an implementation of the corresponding IDL interface.
// Use TraceWrapperMember to hold a reference to an instance of this class.
class CORE_EXPORT ReadableStreamWrapper : public ReadableStream {
public:
// Call one of Init functions before using the instance.
ReadableStreamWrapper() = default;
~ReadableStreamWrapper() override = default;
// If an error happens, |exception_state.HadException()| will be true, and
// |this| will not be usable after that.
void Init(ScriptState*,
ScriptValue underlying_source,
ScriptValue strategy,
ExceptionState& exception_state);
void InitWithInternalStream(ScriptState*,
v8::Local<v8::Object> object,
ExceptionState& exception_state);
// Create* functions call Init* internally and returns null when an error
// happens.
static ReadableStreamWrapper* Create(ScriptState*,
ScriptValue underlying_source,
ScriptValue strategy,
ExceptionState&);
static ReadableStreamWrapper* CreateFromInternalStream(
ScriptState*,
v8::Local<v8::Object> object,
ExceptionState&);
static ReadableStreamWrapper* CreateFromInternalStream(ScriptState*,
ScriptValue object,
ExceptionState&);
// This function doesn't take ExceptionState because the caller cannot have
// one. Returns null when an error happens.
static ReadableStreamWrapper* CreateWithCountQueueingStrategy(
ScriptState*,
UnderlyingSourceBase* underlying_source,
size_t high_water_mark);
void Trace(Visitor* visitor) override;
// IDL defined functions
bool locked(ScriptState*, ExceptionState&) const override;
ScriptPromise cancel(ScriptState*, ExceptionState&) override;
ScriptPromise cancel(ScriptState*,
ScriptValue reason,
ExceptionState&) override;
ScriptValue getReader(ScriptState*, ExceptionState&) override;
ScriptValue getReader(ScriptState*,
ScriptValue options,
ExceptionState&) override;
ScriptValue pipeThrough(ScriptState*,
ScriptValue transform_stream,
ExceptionState&) override;
ScriptValue pipeThrough(ScriptState*,
ScriptValue transform_stream,
ScriptValue options,
ExceptionState&) override;
ScriptPromise pipeTo(ScriptState*,
ScriptValue destination,
ExceptionState&) override;
ScriptPromise pipeTo(ScriptState*,
ScriptValue destination,
ScriptValue options,
ExceptionState&) override;
ScriptValue tee(ScriptState*, ExceptionState&) override;
void Tee(ScriptState*,
ReadableStream** branch1,
ReadableStream** branch2,
ExceptionState&) override;
base::Optional<bool> IsLocked(ScriptState*, ExceptionState&) const override;
base::Optional<bool> IsDisturbed(ScriptState*,
ExceptionState&) const override;
base::Optional<bool> IsReadable(ScriptState*, ExceptionState&) const override;
base::Optional<bool> IsClosed(ScriptState*, ExceptionState&) const override;
base::Optional<bool> IsErrored(ScriptState*, ExceptionState&) const override;
// Makes this stream locked and disturbed.
void LockAndDisturb(ScriptState*, ExceptionState&) override;
// Serialize this stream to |port|. The stream will be locked by this
// operation.
void Serialize(ScriptState*, MessagePort* port, ExceptionState&) override;
// Given a |port| which is entangled with a MessagePort that was previously
// passed to Serialize(), returns a new ReadableStreamWrapper which behaves
// like it was the original.
static ReadableStreamWrapper* Deserialize(ScriptState*,
MessagePort* port,
ExceptionState&);
ScriptValue GetInternalStream(ScriptState* script_state) const;
// In some cases we are known to fail to trace the stream correctly. In such
// cases |object_| will be silently gone. This function is for detecting the
// issue. Use this function at places where an actual crash happens. Do not
// use this function to write "just in case" code.
bool IsBroken() const override { return object_.IsEmpty(); }
private:
TraceWrapperV8Reference<v8::Object> object_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_WRAPPER_H_
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_value.h" #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h" #include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
#include "third_party/blink/renderer/core/streams/readable_stream.h" #include "third_party/blink/renderer/core/streams/readable_stream.h"
#include "third_party/blink/renderer/core/streams/readable_stream_wrapper.h"
#include "third_party/blink/renderer/core/streams/transform_stream_default_controller.h" #include "third_party/blink/renderer/core/streams/transform_stream_default_controller.h"
#include "third_party/blink/renderer/core/streams/transform_stream_transformer.h" #include "third_party/blink/renderer/core/streams/transform_stream_transformer.h"
#include "third_party/blink/renderer/core/streams/writable_stream_wrapper.h" #include "third_party/blink/renderer/core/streams/writable_stream_wrapper.h"
...@@ -233,7 +234,7 @@ bool TransformStream::InitInternal(ScriptState* script_state, ...@@ -233,7 +234,7 @@ bool TransformStream::InitInternal(ScriptState* script_state,
} }
DCHECK(readable->IsObject()); DCHECK(readable->IsObject());
readable_ = ReadableStream::CreateFromInternalStream( readable_ = ReadableStreamWrapper::CreateFromInternalStream(
script_state, readable.As<v8::Object>(), exception_state); script_state, readable.As<v8::Object>(), exception_state);
if (!readable_) if (!readable_)
......
...@@ -5705,6 +5705,7 @@ crbug.com/902633 virtual/streams-native/http/tests/streams/chromium/touching-glo ...@@ -5705,6 +5705,7 @@ crbug.com/902633 virtual/streams-native/http/tests/streams/chromium/touching-glo
### virtual/streams-native/http/tests/streams/transferable/ ### virtual/streams-native/http/tests/streams/transferable/
crbug.com/902633 virtual/streams-native/http/tests/streams/transferable/writable-stream.html [ Timeout ] crbug.com/902633 virtual/streams-native/http/tests/streams/transferable/writable-stream.html [ Timeout ]
crbug.com/902633 virtual/streams-native/http/tests/streams/transferable/window.html [ Timeout ]
# Sheriff 2018-12-27 # Sheriff 2018-12-27
crbug.com/917970 [ Mac10.13 Retina ] virtual/mouseevent_fractional/fast/events/popup-blocking-timers5.html [ Pass Failure ] crbug.com/917970 [ Mac10.13 Retina ] virtual/mouseevent_fractional/fast/events/popup-blocking-timers5.html [ Pass Failure ]
......
This is a testharness.js-based test.
FAIL sending one chunk through a transferred stream should work promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL sending ten chunks through a transferred stream should work promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL sending ten chunks one at a time should work promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL sending ten chunks on demand should work promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
PASS transferring a stream should relieve backpressure
FAIL transferring a stream should add one chunk to the queue size promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL the extra queue from transferring is counted in chunks promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL cancel should be propagated to the original promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL cancel should abort a pending read() promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL stream cancel should not wait for underlying source cancel promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL serialization should not happen until the value is read promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL transferring a non-serializable chunk should error both sides promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL errors should be passed through promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL race between cancel() and error() should leave sides in different states promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL race between cancel() and close() should be benign promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL race between cancel() and enqueue() should be benign promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
Harness: the test ran to completion.
This is a testharness.js-based test.
FAIL reason with a simple value of 'hi' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL reason with a simple value of ' \r
' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL reason with a simple value of '7' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL reason with a simple value of '3' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL reason with a simple value of 'undefined' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL reason with a simple value of 'null' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL reason with a simple value of 'true' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL reason with a simple value of 'false' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL reason with a type of 'symbol' should be squished to undefined promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL reason with a type of 'function' should be squished to undefined promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL number with a value of 'NaN' should be squished to null promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL number with a value of 'Infinity' should be squished to null promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL objects that can be completely expressed in JSON should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL objects that cannot be expressed in JSON should result in a TypeError promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL the type and message of a TypeError should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL other attributes of a TypeError should not be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL a TypeError message should not be preserved if it is not a string promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL a TypeError message should not be preserved if it is a getter promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL a TypeError message should not be preserved if it is inherited promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL DOMException errors should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
FAIL RangeErrors should not be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
Harness: the test ran to completion.
This is a testharness.js-based test.
PASS service-worker
FAIL serviceWorker.controller.postMessage should be able to transfer a ReadableStream promise_test: Unhandled rejection with value: "BAD: TypeError: Cannot read property 'constructor' of null"
FAIL postMessage in a service worker should be able to transfer ReadableStream promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'constructor' of null"
Harness: the test ran to completion.
This is a testharness.js-based test.
FAIL worker.postMessage should be able to transfer a ReadableStream promise_test: Unhandled rejection with value: "BAD: TypeError: Cannot read property 'constructor' of null"
FAIL postMessage in a worker should be able to transfer a ReadableStream promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'constructor' of null"
Harness: the test ran to completion.
This is a testharness.js-based test. This is a testharness.js-based test.
PASS window.postMessage should be able to transfer a TransformStream FAIL window.postMessage should be able to transfer a TransformStream Cannot read property 'constructor' of null
PASS a TransformStream with a locked writable should not be transferable PASS a TransformStream with a locked writable should not be transferable
PASS a TransformStream with a locked readable should not be transferable PASS a TransformStream with a locked readable should not be transferable
PASS a TransformStream with both sides locked should not be transferable PASS a TransformStream with both sides locked should not be transferable
FAIL piping through transferred transforms should work Failed to execute 'pipeThrough' on 'ReadableStream': pipeThrough disabled because StreamsNative feature is enabled FAIL piping through transferred transforms should work Cannot read property 'source' of null
Harness: the test ran to completion. Harness: the test ran to completion.
CONSOLE ERROR: line 2: Uncaught TypeError: Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope': Value at index 0 is an untransferable 'null' value.
CONSOLE ERROR: line 2: Uncaught TypeError: Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope': Value at index 0 is an untransferable 'null' value.
This is a testharness.js-based test.
FAIL worker.postMessage should be able to transfer a ReadableStream promise_test: Unhandled rejection with value: "BAD: TypeError: Cannot read property 'constructor' of null"
FAIL postMessage in a worker should be able to transfer a ReadableStream promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'constructor' of null"
FAIL terminating a worker should not error the stream promise_test: Unhandled rejection with value: "error in worker"
Harness: the test ran to completion.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment