Commit b4462270 authored by Adam Rice's avatar Adam Rice Committed by Commit Bot

[ReadableStream] Remove ExceptionState& from two methods

ReadableStream::LockAndDisturb() can no longer throw now that the V8
Extras implementation has been removed. Remove the ExceptionState&
argument. Also remove the ScriptState::Scope from the method which is
not needed.

ReadableStream::GetReaderNotForAuthorCode() is never called on a
locked stream, so it cannot throw. Remove the ExceptionState&
argument.

In order to ensure that ReadableStream::GetReaderNotForAuthorCode() is
not called on a locked stream, check in
BodyStreamBuffer::ExtractBody() whether the stream is locked or
disturbed and throw an exception. This is only done when
FetchUploadStreaing is enabled. This actually improves our alignment
with the Fetch Standard and improves our test pass rate.

Many fetch-related methods no longer need an
ExceptionState& argument either, so remove those unneeded arguments too.

Bug: 1010794

Change-Id: I6c84f8bff006c696edca13b7a46fcbc10c142201
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2217830
Commit-Queue: Adam Rice <ricea@chromium.org>
Reviewed-by: default avatarPeter Beverloo <peter@chromium.org>
Reviewed-by: default avatarYoichi Osato <yoichio@chromium.org>
Reviewed-by: default avatarDan Sanders <sandersd@chromium.org>
Reviewed-by: default avatarMatt Falkenhagen <falken@chromium.org>
Reviewed-by: default avatarYutaka Hirano <yhirano@chromium.org>
Cr-Commit-Position: refs/heads/master@{#790089}
parent 55d4d3cd
...@@ -168,11 +168,10 @@ BodyStreamBuffer::BodyStreamBuffer(ScriptState* script_state, ...@@ -168,11 +168,10 @@ BodyStreamBuffer::BodyStreamBuffer(ScriptState* script_state,
} }
scoped_refptr<BlobDataHandle> BodyStreamBuffer::DrainAsBlobDataHandle( scoped_refptr<BlobDataHandle> BodyStreamBuffer::DrainAsBlobDataHandle(
BytesConsumer::BlobSizePolicy policy, BytesConsumer::BlobSizePolicy policy) {
ExceptionState& exception_state) {
DCHECK(!IsStreamLocked()); DCHECK(!IsStreamLocked());
DCHECK(!IsStreamDisturbed()); DCHECK(!IsStreamDisturbed());
if (IsStreamClosed() || IsStreamErrored()) if (IsStreamClosed() || IsStreamErrored() || stream_broken_)
return nullptr; return nullptr;
if (made_from_readable_stream_) if (made_from_readable_stream_)
...@@ -181,19 +180,16 @@ scoped_refptr<BlobDataHandle> BodyStreamBuffer::DrainAsBlobDataHandle( ...@@ -181,19 +180,16 @@ scoped_refptr<BlobDataHandle> BodyStreamBuffer::DrainAsBlobDataHandle(
scoped_refptr<BlobDataHandle> blob_data_handle = scoped_refptr<BlobDataHandle> blob_data_handle =
consumer_->DrainAsBlobDataHandle(policy); consumer_->DrainAsBlobDataHandle(policy);
if (blob_data_handle) { if (blob_data_handle) {
CloseAndLockAndDisturb(exception_state); CloseAndLockAndDisturb();
if (exception_state.HadException())
return nullptr;
return blob_data_handle; return blob_data_handle;
} }
return nullptr; return nullptr;
} }
scoped_refptr<EncodedFormData> BodyStreamBuffer::DrainAsFormData( scoped_refptr<EncodedFormData> BodyStreamBuffer::DrainAsFormData() {
ExceptionState& exception_state) {
DCHECK(!IsStreamLocked()); DCHECK(!IsStreamLocked());
DCHECK(!IsStreamDisturbed()); DCHECK(!IsStreamDisturbed());
if (IsStreamClosed() || IsStreamErrored()) if (IsStreamClosed() || IsStreamErrored() || stream_broken_)
return nullptr; return nullptr;
if (made_from_readable_stream_) if (made_from_readable_stream_)
...@@ -201,9 +197,7 @@ scoped_refptr<EncodedFormData> BodyStreamBuffer::DrainAsFormData( ...@@ -201,9 +197,7 @@ scoped_refptr<EncodedFormData> BodyStreamBuffer::DrainAsFormData(
scoped_refptr<EncodedFormData> form_data = consumer_->DrainAsFormData(); scoped_refptr<EncodedFormData> form_data = consumer_->DrainAsFormData();
if (form_data) { if (form_data) {
CloseAndLockAndDisturb(exception_state); CloseAndLockAndDisturb();
if (exception_state.HadException())
return nullptr;
return form_data; return form_data;
} }
return nullptr; return nullptr;
...@@ -212,13 +206,10 @@ scoped_refptr<EncodedFormData> BodyStreamBuffer::DrainAsFormData( ...@@ -212,13 +206,10 @@ scoped_refptr<EncodedFormData> BodyStreamBuffer::DrainAsFormData(
void BodyStreamBuffer::DrainAsChunkedDataPipeGetter( void BodyStreamBuffer::DrainAsChunkedDataPipeGetter(
ScriptState* script_state, ScriptState* script_state,
mojo::PendingReceiver<network::mojom::blink::ChunkedDataPipeGetter> mojo::PendingReceiver<network::mojom::blink::ChunkedDataPipeGetter>
pending_receiver, pending_receiver) {
ExceptionState& exception_state) {
DCHECK(!IsStreamLocked()); DCHECK(!IsStreamLocked());
auto* consumer = MakeGarbageCollected<ReadableStreamBytesConsumer>( auto* consumer =
script_state, stream_, exception_state); MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream_);
if (exception_state.HadException())
return;
stream_uploader_ = MakeGarbageCollected<BytesUploader>( stream_uploader_ = MakeGarbageCollected<BytesUploader>(
consumer, std::move(pending_receiver), consumer, std::move(pending_receiver),
ExecutionContext::From(script_state) ExecutionContext::From(script_state)
...@@ -368,13 +359,8 @@ bool BodyStreamBuffer::IsStreamDisturbed() const { ...@@ -368,13 +359,8 @@ bool BodyStreamBuffer::IsStreamDisturbed() const {
return stream_->IsDisturbed(); return stream_->IsDisturbed();
} }
void BodyStreamBuffer::CloseAndLockAndDisturb(ExceptionState& exception_state) { void BodyStreamBuffer::CloseAndLockAndDisturb() {
if (stream_broken_) { DCHECK(!stream_broken_);
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
"Body stream has suffered a fatal error and cannot be disturbed");
return;
}
if (IsStreamReadable()) { if (IsStreamReadable()) {
// Note that the stream cannot be "draining", because it doesn't have // Note that the stream cannot be "draining", because it doesn't have
...@@ -382,7 +368,7 @@ void BodyStreamBuffer::CloseAndLockAndDisturb(ExceptionState& exception_state) { ...@@ -382,7 +368,7 @@ void BodyStreamBuffer::CloseAndLockAndDisturb(ExceptionState& exception_state) {
Close(); Close();
} }
stream_->LockAndDisturb(script_state_, exception_state); stream_->LockAndDisturb(script_state_);
} }
bool BodyStreamBuffer::IsAborted() { bool BodyStreamBuffer::IsAborted() {
...@@ -524,14 +510,10 @@ BytesConsumer* BodyStreamBuffer::ReleaseHandle( ...@@ -524,14 +510,10 @@ BytesConsumer* BodyStreamBuffer::ReleaseHandle(
side_data_blob_.reset(); side_data_blob_.reset();
if (made_from_readable_stream_) { if (made_from_readable_stream_) {
DCHECK(script_state_->ContextIsValid());
ScriptState::Scope scope(script_state_); ScriptState::Scope scope(script_state_);
auto* consumer = MakeGarbageCollected<ReadableStreamBytesConsumer>( return MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state_,
script_state_, stream_, exception_state); stream_);
if (exception_state.HadException()) {
stream_broken_ = true;
return nullptr;
}
return consumer;
} }
// We need to call these before calling CloseAndLockAndDisturb. // We need to call these before calling CloseAndLockAndDisturb.
const bool is_closed = IsStreamClosed(); const bool is_closed = IsStreamClosed();
...@@ -539,9 +521,7 @@ BytesConsumer* BodyStreamBuffer::ReleaseHandle( ...@@ -539,9 +521,7 @@ BytesConsumer* BodyStreamBuffer::ReleaseHandle(
BytesConsumer* consumer = consumer_.Release(); BytesConsumer* consumer = consumer_.Release();
CloseAndLockAndDisturb(exception_state); CloseAndLockAndDisturb();
if (exception_state.HadException())
return nullptr;
if (is_closed) { if (is_closed) {
// Note that the stream cannot be "draining", because it doesn't have // Note that the stream cannot be "draining", because it doesn't have
......
...@@ -61,13 +61,11 @@ class CORE_EXPORT BodyStreamBuffer final : public UnderlyingSourceBase, ...@@ -61,13 +61,11 @@ class CORE_EXPORT BodyStreamBuffer final : public UnderlyingSourceBase,
// Callable only when neither locked nor disturbed. // Callable only when neither locked nor disturbed.
scoped_refptr<BlobDataHandle> DrainAsBlobDataHandle( scoped_refptr<BlobDataHandle> DrainAsBlobDataHandle(
BytesConsumer::BlobSizePolicy, BytesConsumer::BlobSizePolicy);
ExceptionState&); scoped_refptr<EncodedFormData> DrainAsFormData();
scoped_refptr<EncodedFormData> DrainAsFormData(ExceptionState&);
void DrainAsChunkedDataPipeGetter( void DrainAsChunkedDataPipeGetter(
ScriptState*, ScriptState*,
mojo::PendingReceiver<network::mojom::blink::ChunkedDataPipeGetter>, mojo::PendingReceiver<network::mojom::blink::ChunkedDataPipeGetter>);
ExceptionState&);
void StartLoading(FetchDataLoader*, void StartLoading(FetchDataLoader*,
FetchDataLoader::Client* /* client */, FetchDataLoader::Client* /* client */,
ExceptionState&); ExceptionState&);
...@@ -88,7 +86,11 @@ class CORE_EXPORT BodyStreamBuffer final : public UnderlyingSourceBase, ...@@ -88,7 +86,11 @@ class CORE_EXPORT BodyStreamBuffer final : public UnderlyingSourceBase,
bool IsStreamErrored() const; bool IsStreamErrored() const;
bool IsStreamLocked() const; bool IsStreamLocked() const;
bool IsStreamDisturbed() const; bool IsStreamDisturbed() const;
void CloseAndLockAndDisturb(ExceptionState&);
// Closes the stream if necessary, and then locks and disturbs it. Should not
// be called if |stream_broken_| is true.
void CloseAndLockAndDisturb();
ScriptState* GetScriptState() { return script_state_; } ScriptState* GetScriptState() { return script_state_; }
bool IsAborted(); bool IsAborted();
......
...@@ -244,8 +244,7 @@ TEST_F(BodyStreamBufferTest, DrainAsBlobDataHandle) { ...@@ -244,8 +244,7 @@ TEST_F(BodyStreamBufferTest, DrainAsBlobDataHandle) {
EXPECT_EQ(side_data_blob, buffer->GetSideDataBlobForTest()); EXPECT_EQ(side_data_blob, buffer->GetSideDataBlobForTest());
scoped_refptr<BlobDataHandle> output_blob_data_handle = scoped_refptr<BlobDataHandle> output_blob_data_handle =
buffer->DrainAsBlobDataHandle( buffer->DrainAsBlobDataHandle(
BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize, BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize);
ASSERT_NO_EXCEPTION);
EXPECT_TRUE(buffer->IsStreamLocked()); EXPECT_TRUE(buffer->IsStreamLocked());
EXPECT_TRUE(buffer->IsStreamDisturbed()); EXPECT_TRUE(buffer->IsStreamDisturbed());
...@@ -270,8 +269,7 @@ TEST_F(BodyStreamBufferTest, DrainAsBlobDataHandleReturnsNull) { ...@@ -270,8 +269,7 @@ TEST_F(BodyStreamBufferTest, DrainAsBlobDataHandleReturnsNull) {
EXPECT_EQ(side_data_blob, buffer->GetSideDataBlobForTest()); EXPECT_EQ(side_data_blob, buffer->GetSideDataBlobForTest());
EXPECT_FALSE(buffer->DrainAsBlobDataHandle( EXPECT_FALSE(buffer->DrainAsBlobDataHandle(
BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize, BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize));
ASSERT_NO_EXCEPTION));
EXPECT_FALSE(buffer->IsStreamLocked()); EXPECT_FALSE(buffer->IsStreamLocked());
EXPECT_FALSE(buffer->IsStreamDisturbed()); EXPECT_FALSE(buffer->IsStreamDisturbed());
...@@ -295,8 +293,7 @@ TEST_F(BodyStreamBufferTest, ...@@ -295,8 +293,7 @@ TEST_F(BodyStreamBufferTest,
EXPECT_TRUE(buffer->IsStreamReadable()); EXPECT_TRUE(buffer->IsStreamReadable());
EXPECT_FALSE(buffer->DrainAsBlobDataHandle( EXPECT_FALSE(buffer->DrainAsBlobDataHandle(
BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize, BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize));
exception_state));
EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_FALSE(buffer->HasPendingActivity());
EXPECT_FALSE(buffer->IsStreamLocked()); EXPECT_FALSE(buffer->IsStreamLocked());
...@@ -323,8 +320,7 @@ TEST_F(BodyStreamBufferTest, DrainAsFormData) { ...@@ -323,8 +320,7 @@ TEST_F(BodyStreamBufferTest, DrainAsFormData) {
EXPECT_FALSE(buffer->IsStreamDisturbed()); EXPECT_FALSE(buffer->IsStreamDisturbed());
EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_FALSE(buffer->HasPendingActivity());
EXPECT_EQ(side_data_blob, buffer->GetSideDataBlobForTest()); EXPECT_EQ(side_data_blob, buffer->GetSideDataBlobForTest());
scoped_refptr<EncodedFormData> output_form_data = scoped_refptr<EncodedFormData> output_form_data = buffer->DrainAsFormData();
buffer->DrainAsFormData(ASSERT_NO_EXCEPTION);
EXPECT_TRUE(buffer->IsStreamLocked()); EXPECT_TRUE(buffer->IsStreamLocked());
EXPECT_TRUE(buffer->IsStreamDisturbed()); EXPECT_TRUE(buffer->IsStreamDisturbed());
...@@ -349,7 +345,7 @@ TEST_F(BodyStreamBufferTest, DrainAsFormDataReturnsNull) { ...@@ -349,7 +345,7 @@ TEST_F(BodyStreamBufferTest, DrainAsFormDataReturnsNull) {
EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_FALSE(buffer->HasPendingActivity());
EXPECT_EQ(side_data_blob, buffer->GetSideDataBlobForTest()); EXPECT_EQ(side_data_blob, buffer->GetSideDataBlobForTest());
EXPECT_FALSE(buffer->DrainAsFormData(ASSERT_NO_EXCEPTION)); EXPECT_FALSE(buffer->DrainAsFormData());
EXPECT_FALSE(buffer->IsStreamLocked()); EXPECT_FALSE(buffer->IsStreamLocked());
EXPECT_FALSE(buffer->IsStreamDisturbed()); EXPECT_FALSE(buffer->IsStreamDisturbed());
...@@ -371,7 +367,7 @@ TEST_F(BodyStreamBufferTest, ...@@ -371,7 +367,7 @@ TEST_F(BodyStreamBufferTest,
EXPECT_FALSE(buffer->IsStreamDisturbed()); EXPECT_FALSE(buffer->IsStreamDisturbed());
EXPECT_TRUE(buffer->IsStreamReadable()); EXPECT_TRUE(buffer->IsStreamReadable());
EXPECT_FALSE(buffer->DrainAsFormData(exception_state)); EXPECT_FALSE(buffer->DrainAsFormData());
EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_FALSE(buffer->HasPendingActivity());
EXPECT_FALSE(buffer->IsStreamLocked()); EXPECT_FALSE(buffer->IsStreamLocked());
......
...@@ -113,7 +113,7 @@ class FetchManager::Loader final ...@@ -113,7 +113,7 @@ class FetchManager::Loader final
void DidFail(const ResourceError&) override; void DidFail(const ResourceError&) override;
void DidFailRedirectCheck() override; void DidFailRedirectCheck() override;
void Start(ExceptionState&); void Start();
void Dispose(); void Dispose();
void Abort(); void Abort();
...@@ -226,9 +226,9 @@ class FetchManager::Loader final ...@@ -226,9 +226,9 @@ class FetchManager::Loader final
}; };
private: private:
void PerformSchemeFetch(ExceptionState&); void PerformSchemeFetch();
void PerformNetworkError(const String& message); void PerformNetworkError(const String& message);
void PerformHTTPFetch(ExceptionState&); void PerformHTTPFetch();
void PerformDataFetch(); void PerformDataFetch();
// If |dom_exception| is provided, throws the specified DOMException instead // If |dom_exception| is provided, throws the specified DOMException instead
// of the usual "Failed to fetch" TypeError. // of the usual "Failed to fetch" TypeError.
...@@ -527,7 +527,7 @@ void FetchManager::Loader::DidFailRedirectCheck() { ...@@ -527,7 +527,7 @@ void FetchManager::Loader::DidFailRedirectCheck() {
Failed(String(), nullptr); Failed(String(), nullptr);
} }
void FetchManager::Loader::Start(ExceptionState& exception_state) { void FetchManager::Loader::Start() {
// "1. If |request|'s url contains a Known HSTS Host, modify it per the // "1. If |request|'s url contains a Known HSTS Host, modify it per the
// requirements of the 'URI [sic] Loading and Port Mapping' chapter of HTTP // requirements of the 'URI [sic] Loading and Port Mapping' chapter of HTTP
// Strict Transport Security." // Strict Transport Security."
...@@ -573,7 +573,7 @@ void FetchManager::Loader::Start(ExceptionState& exception_state) { ...@@ -573,7 +573,7 @@ void FetchManager::Loader::Start(ExceptionState& exception_state) {
fetch_request_data_->IsolatedWorldOrigin()->CanReadContent(url)) || fetch_request_data_->IsolatedWorldOrigin()->CanReadContent(url)) ||
fetch_request_data_->Mode() == network::mojom::RequestMode::kNavigate) { fetch_request_data_->Mode() == network::mojom::RequestMode::kNavigate) {
// "The result of performing a scheme fetch using request." // "The result of performing a scheme fetch using request."
PerformSchemeFetch(exception_state); PerformSchemeFetch();
return; return;
} }
...@@ -603,7 +603,7 @@ void FetchManager::Loader::Start(ExceptionState& exception_state) { ...@@ -603,7 +603,7 @@ void FetchManager::Loader::Start(ExceptionState& exception_state) {
// "Set |request|'s response tainting to |opaque|." // "Set |request|'s response tainting to |opaque|."
fetch_request_data_->SetResponseTainting(FetchRequestData::kOpaqueTainting); fetch_request_data_->SetResponseTainting(FetchRequestData::kOpaqueTainting);
// "The result of performing a scheme fetch using |request|." // "The result of performing a scheme fetch using |request|."
PerformSchemeFetch(exception_state); PerformSchemeFetch();
return; return;
} }
...@@ -624,7 +624,7 @@ void FetchManager::Loader::Start(ExceptionState& exception_state) { ...@@ -624,7 +624,7 @@ void FetchManager::Loader::Start(ExceptionState& exception_state) {
// "The result of performing an HTTP fetch using |request| with the // "The result of performing an HTTP fetch using |request| with the
// |CORS flag| set." // |CORS flag| set."
PerformHTTPFetch(exception_state); PerformHTTPFetch();
} }
void FetchManager::Loader::Dispose() { void FetchManager::Loader::Dispose() {
...@@ -660,16 +660,14 @@ void FetchManager::Loader::Abort() { ...@@ -660,16 +660,14 @@ void FetchManager::Loader::Abort() {
NotifyFinished(); NotifyFinished();
} }
void FetchManager::Loader::PerformSchemeFetch(ExceptionState& exception_state) { void FetchManager::Loader::PerformSchemeFetch() {
// "To perform a scheme fetch using |request|, switch on |request|'s url's // "To perform a scheme fetch using |request|, switch on |request|'s url's
// scheme, and run the associated steps:" // scheme, and run the associated steps:"
if (SchemeRegistry::ShouldTreatURLSchemeAsSupportingFetchAPI( if (SchemeRegistry::ShouldTreatURLSchemeAsSupportingFetchAPI(
fetch_request_data_->Url().Protocol()) || fetch_request_data_->Url().Protocol()) ||
fetch_request_data_->Url().ProtocolIs("blob")) { fetch_request_data_->Url().ProtocolIs("blob")) {
// "Return the result of performing an HTTP fetch using |request|." // "Return the result of performing an HTTP fetch using |request|."
PerformHTTPFetch(exception_state); PerformHTTPFetch();
if (exception_state.HadException())
return;
} else if (fetch_request_data_->Url().ProtocolIsData()) { } else if (fetch_request_data_->Url().ProtocolIsData()) {
PerformDataFetch(); PerformDataFetch();
} else { } else {
...@@ -685,7 +683,7 @@ void FetchManager::Loader::PerformNetworkError(const String& message) { ...@@ -685,7 +683,7 @@ void FetchManager::Loader::PerformNetworkError(const String& message) {
Failed(message, nullptr); Failed(message, nullptr);
} }
void FetchManager::Loader::PerformHTTPFetch(ExceptionState& exception_state) { void FetchManager::Loader::PerformHTTPFetch() {
// CORS preflight fetch procedure is implemented inside ThreadableLoader. // CORS preflight fetch procedure is implemented inside ThreadableLoader.
// "1. Let |HTTPRequest| be a copy of |request|, except that |HTTPRequest|'s // "1. Let |HTTPRequest| be a copy of |request|, except that |HTTPRequest|'s
...@@ -732,10 +730,7 @@ void FetchManager::Loader::PerformHTTPFetch(ExceptionState& exception_state) { ...@@ -732,10 +730,7 @@ void FetchManager::Loader::PerformHTTPFetch(ExceptionState& exception_state) {
fetch_request_data_->Method() != http_names::kHEAD) { fetch_request_data_->Method() != http_names::kHEAD) {
if (fetch_request_data_->Buffer()) { if (fetch_request_data_->Buffer()) {
scoped_refptr<EncodedFormData> form_data = scoped_refptr<EncodedFormData> form_data =
fetch_request_data_->Buffer()->DrainAsFormData(exception_state); fetch_request_data_->Buffer()->DrainAsFormData();
if (exception_state.HadException())
return;
if (form_data) { if (form_data) {
request.SetHttpBody(form_data); request.SetHttpBody(form_data);
} else if (RuntimeEnabledFeatures::OutOfBlinkCorsEnabled() && } else if (RuntimeEnabledFeatures::OutOfBlinkCorsEnabled() &&
...@@ -743,13 +738,12 @@ void FetchManager::Loader::PerformHTTPFetch(ExceptionState& exception_state) { ...@@ -743,13 +738,12 @@ void FetchManager::Loader::PerformHTTPFetch(ExceptionState& exception_state) {
execution_context_)) { execution_context_)) {
UseCounter::Count(execution_context_, UseCounter::Count(execution_context_,
WebFeature::kFetchUploadStreaming); WebFeature::kFetchUploadStreaming);
DCHECK(!fetch_request_data_->Buffer()->IsStreamLocked());
mojo::PendingRemote<network::mojom::blink::ChunkedDataPipeGetter> mojo::PendingRemote<network::mojom::blink::ChunkedDataPipeGetter>
pending_remote; pending_remote;
fetch_request_data_->Buffer()->DrainAsChunkedDataPipeGetter( fetch_request_data_->Buffer()->DrainAsChunkedDataPipeGetter(
resolver_->GetScriptState(), resolver_->GetScriptState(),
pending_remote.InitWithNewPipeAndPassReceiver(), exception_state); pending_remote.InitWithNewPipeAndPassReceiver());
if (exception_state.HadException())
return;
request.MutableBody().SetStreamBody(std::move(pending_remote)); request.MutableBody().SetStreamBody(std::move(pending_remote));
request.SetAllowHTTP1ForStreamingUpload( request.SetAllowHTTP1ForStreamingUpload(
fetch_request_data_->AllowHTTP1ForStreamingUpload()); fetch_request_data_->AllowHTTP1ForStreamingUpload());
...@@ -881,28 +875,26 @@ ScriptPromise FetchManager::Fetch(ScriptState* script_state, ...@@ -881,28 +875,26 @@ ScriptPromise FetchManager::Fetch(ScriptState* script_state,
FetchRequestData* request, FetchRequestData* request,
AbortSignal* signal, AbortSignal* signal,
ExceptionState& exception_state) { ExceptionState& exception_state) {
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
DCHECK(signal); DCHECK(signal);
if (signal->aborted()) { if (signal->aborted()) {
resolver->Reject( exception_state.ThrowDOMException(DOMExceptionCode::kAbortError,
MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError)); "The user aborted a request.");
return promise; return ScriptPromise();
} }
request->SetContext(mojom::RequestContextType::FETCH); request->SetContext(mojom::RequestContextType::FETCH);
request->SetDestination(network::mojom::RequestDestination::kEmpty); request->SetDestination(network::mojom::RequestDestination::kEmpty);
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
auto* loader = auto* loader =
MakeGarbageCollected<Loader>(GetExecutionContext(), this, resolver, MakeGarbageCollected<Loader>(GetExecutionContext(), this, resolver,
request, &script_state->World(), signal); request, &script_state->World(), signal);
loaders_.insert(loader); loaders_.insert(loader);
signal->AddAlgorithm(WTF::Bind(&Loader::Abort, WrapWeakPersistent(loader))); signal->AddAlgorithm(WTF::Bind(&Loader::Abort, WrapWeakPersistent(loader)));
// TODO(ricea): Reject the Response body with AbortError, not TypeError. // TODO(ricea): Reject the Response body with AbortError, not TypeError.
loader->Start(exception_state); loader->Start();
if (exception_state.HadException())
return ScriptPromise();
return promise; return promise;
} }
......
...@@ -234,16 +234,13 @@ FetchRequestData* FetchRequestData::Clone(ScriptState* script_state, ...@@ -234,16 +234,13 @@ FetchRequestData* FetchRequestData::Clone(ScriptState* script_state,
return request; return request;
} }
FetchRequestData* FetchRequestData::Pass(ScriptState* script_state, FetchRequestData* FetchRequestData::Pass(ScriptState* script_state) {
ExceptionState& exception_state) {
FetchRequestData* request = FetchRequestData::CloneExceptBody(); FetchRequestData* request = FetchRequestData::CloneExceptBody();
if (buffer_) { if (buffer_) {
request->buffer_ = buffer_; request->buffer_ = buffer_;
buffer_ = BodyStreamBuffer::Create( buffer_ = BodyStreamBuffer::Create(
script_state, BytesConsumer::CreateClosed(), nullptr /* AbortSignal */); script_state, BytesConsumer::CreateClosed(), nullptr /* AbortSignal */);
buffer_->CloseAndLockAndDisturb(exception_state); buffer_->CloseAndLockAndDisturb();
if (exception_state.HadException())
return nullptr;
} }
request->url_loader_factory_ = std::move(url_loader_factory_); request->url_loader_factory_ = std::move(url_loader_factory_);
return request; return request;
......
...@@ -43,7 +43,7 @@ class CORE_EXPORT FetchRequestData final ...@@ -43,7 +43,7 @@ class CORE_EXPORT FetchRequestData final
mojom::blink::FetchAPIRequestPtr, mojom::blink::FetchAPIRequestPtr,
ForServiceWorkerFetchEvent); ForServiceWorkerFetchEvent);
FetchRequestData* Clone(ScriptState*, ExceptionState&); FetchRequestData* Clone(ScriptState*, ExceptionState&);
FetchRequestData* Pass(ScriptState*, ExceptionState&); FetchRequestData* Pass(ScriptState*);
explicit FetchRequestData(ExecutionContext* execution_context); explicit FetchRequestData(ExecutionContext* execution_context);
~FetchRequestData(); ~FetchRequestData();
......
...@@ -75,11 +75,8 @@ class GlobalFetchImpl final : public GarbageCollected<GlobalFetchImpl<T>>, ...@@ -75,11 +75,8 @@ class GlobalFetchImpl final : public GarbageCollected<GlobalFetchImpl<T>>,
return ScriptPromise(); return ScriptPromise();
probe::WillSendXMLHttpOrFetchNetworkRequest(execution_context, r->url()); probe::WillSendXMLHttpOrFetchNetworkRequest(execution_context, r->url());
FetchRequestData* request_data = FetchRequestData* request_data = r->PassRequestData(script_state);
r->PassRequestData(script_state, exception_state);
MeasureFetchProperties(execution_context, request_data); MeasureFetchProperties(execution_context, request_data);
if (exception_state.HadException())
return ScriptPromise();
auto promise = fetch_manager_->Fetch(script_state, request_data, auto promise = fetch_manager_->Fetch(script_state, request_data,
r->signal(), exception_state); r->signal(), exception_state);
if (exception_state.HadException()) if (exception_state.HadException())
......
...@@ -95,9 +95,8 @@ class ReadableStreamBytesConsumer::OnRejected final : public ScriptFunction { ...@@ -95,9 +95,8 @@ class ReadableStreamBytesConsumer::OnRejected final : public ScriptFunction {
ReadableStreamBytesConsumer::ReadableStreamBytesConsumer( ReadableStreamBytesConsumer::ReadableStreamBytesConsumer(
ScriptState* script_state, ScriptState* script_state,
ReadableStream* stream, ReadableStream* stream)
ExceptionState& exception_state) : reader_(stream->GetReaderNotForAuthorCode(script_state)),
: reader_(stream->GetReaderNotForAuthorCode(script_state, exception_state)),
script_state_(script_state) {} script_state_(script_state) {}
ReadableStreamBytesConsumer::~ReadableStreamBytesConsumer() {} ReadableStreamBytesConsumer::~ReadableStreamBytesConsumer() {}
......
...@@ -22,10 +22,10 @@ class ScriptState; ...@@ -22,10 +22,10 @@ class ScriptState;
// This class is a BytesConsumer pulling bytes from a ReadableStream. // This class is a BytesConsumer pulling bytes from a ReadableStream.
// The stream will be immediately locked by the consumer and will never be // The stream will be immediately locked by the consumer and will never be
// released. // released. The stream must not be locked before this object is created.
class CORE_EXPORT ReadableStreamBytesConsumer final : public BytesConsumer { class CORE_EXPORT ReadableStreamBytesConsumer final : public BytesConsumer {
public: public:
ReadableStreamBytesConsumer(ScriptState*, ReadableStream*, ExceptionState&); ReadableStreamBytesConsumer(ScriptState*, ReadableStream*);
~ReadableStreamBytesConsumer() override; ~ReadableStreamBytesConsumer() override;
Result BeginRead(const char** buffer, size_t* available) override; Result BeginRead(const char** buffer, size_t* available) override;
......
...@@ -52,8 +52,7 @@ TEST(ReadableStreamBytesConsumerTest, Create) { ...@@ -52,8 +52,7 @@ TEST(ReadableStreamBytesConsumerTest, Create) {
ASSERT_FALSE(exception_state.HadException()); ASSERT_FALSE(exception_state.HadException());
Persistent<BytesConsumer> consumer = Persistent<BytesConsumer> consumer =
MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream, MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream);
ASSERT_NO_EXCEPTION);
EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState()); EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
} }
...@@ -69,8 +68,7 @@ TEST(ReadableStreamBytesConsumerTest, EmptyStream) { ...@@ -69,8 +68,7 @@ TEST(ReadableStreamBytesConsumerTest, EmptyStream) {
underlying_source->Close(); underlying_source->Close();
Persistent<BytesConsumer> consumer = Persistent<BytesConsumer> consumer =
MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream, MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream);
ASSERT_NO_EXCEPTION);
Persistent<MockClient> client = MakeGarbageCollected<MockClient>(); Persistent<MockClient> client = MakeGarbageCollected<MockClient>();
consumer->SetClient(client); consumer->SetClient(client);
...@@ -109,8 +107,7 @@ TEST(ReadableStreamBytesConsumerTest, ErroredStream) { ...@@ -109,8 +107,7 @@ TEST(ReadableStreamBytesConsumerTest, ErroredStream) {
script_state->GetIsolate(), v8::Undefined(script_state->GetIsolate()))); script_state->GetIsolate(), v8::Undefined(script_state->GetIsolate())));
Persistent<BytesConsumer> consumer = Persistent<BytesConsumer> consumer =
MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream, MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream);
ASSERT_NO_EXCEPTION);
Persistent<MockClient> client = MakeGarbageCollected<MockClient>(); Persistent<MockClient> client = MakeGarbageCollected<MockClient>();
consumer->SetClient(client); consumer->SetClient(client);
Checkpoint checkpoint; Checkpoint checkpoint;
...@@ -166,8 +163,7 @@ TEST(ReadableStreamBytesConsumerTest, TwoPhaseRead) { ...@@ -166,8 +163,7 @@ TEST(ReadableStreamBytesConsumerTest, TwoPhaseRead) {
} }
Persistent<BytesConsumer> consumer = Persistent<BytesConsumer> consumer =
MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream, MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream);
ASSERT_NO_EXCEPTION);
Persistent<MockClient> client = MakeGarbageCollected<MockClient>(); Persistent<MockClient> client = MakeGarbageCollected<MockClient>();
consumer->SetClient(client); consumer->SetClient(client);
Checkpoint checkpoint; Checkpoint checkpoint;
...@@ -258,8 +254,7 @@ TEST(ReadableStreamBytesConsumerTest, EnqueueUndefined) { ...@@ -258,8 +254,7 @@ TEST(ReadableStreamBytesConsumerTest, EnqueueUndefined) {
underlying_source->Close(); underlying_source->Close();
Persistent<BytesConsumer> consumer = Persistent<BytesConsumer> consumer =
MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream, MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream);
ASSERT_NO_EXCEPTION);
Persistent<MockClient> client = MakeGarbageCollected<MockClient>(); Persistent<MockClient> client = MakeGarbageCollected<MockClient>();
consumer->SetClient(client); consumer->SetClient(client);
Checkpoint checkpoint; Checkpoint checkpoint;
...@@ -298,8 +293,7 @@ TEST(ReadableStreamBytesConsumerTest, EnqueueNull) { ...@@ -298,8 +293,7 @@ TEST(ReadableStreamBytesConsumerTest, EnqueueNull) {
underlying_source->Close(); underlying_source->Close();
Persistent<BytesConsumer> consumer = Persistent<BytesConsumer> consumer =
MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream, MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream);
ASSERT_NO_EXCEPTION);
Persistent<MockClient> client = MakeGarbageCollected<MockClient>(); Persistent<MockClient> client = MakeGarbageCollected<MockClient>();
consumer->SetClient(client); consumer->SetClient(client);
Checkpoint checkpoint; Checkpoint checkpoint;
...@@ -339,8 +333,7 @@ TEST(ReadableStreamBytesConsumerTest, EnqueueString) { ...@@ -339,8 +333,7 @@ TEST(ReadableStreamBytesConsumerTest, EnqueueString) {
underlying_source->Close(); underlying_source->Close();
Persistent<BytesConsumer> consumer = Persistent<BytesConsumer> consumer =
MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream, MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream);
ASSERT_NO_EXCEPTION);
Persistent<MockClient> client = MakeGarbageCollected<MockClient>(); Persistent<MockClient> client = MakeGarbageCollected<MockClient>();
consumer->SetClient(client); consumer->SetClient(client);
Checkpoint checkpoint; Checkpoint checkpoint;
......
...@@ -183,6 +183,20 @@ static BodyStreamBuffer* ExtractBody(ScriptState* script_state, ...@@ -183,6 +183,20 @@ static BodyStreamBuffer* ExtractBody(ScriptState* script_state,
V8ReadableStream::HasInstance(body, isolate)) { V8ReadableStream::HasInstance(body, isolate)) {
ReadableStream* readable_stream = ReadableStream* readable_stream =
V8ReadableStream::ToImpl(body.As<v8::Object>()); V8ReadableStream::ToImpl(body.As<v8::Object>());
// This is implemented in Request::CreateRequestWithRequestOrString():
// "If the |keepalive| flag is set, then throw a TypeError."
// "If |object| is disturbed or locked, then throw a TypeError."
if (readable_stream->IsDisturbed()) {
exception_state.ThrowTypeError(
"The provided ReadableStream is disturbed");
return nullptr;
}
if (readable_stream->IsLocked()) {
exception_state.ThrowTypeError("The provided ReadableStream is locked");
return nullptr;
}
// "Set |stream| to |object|."
return_buffer = return_buffer =
MakeGarbageCollected<BodyStreamBuffer>(script_state, readable_stream); MakeGarbageCollected<BodyStreamBuffer>(script_state, readable_stream);
} else { } else {
...@@ -688,9 +702,7 @@ Request* Request::CreateRequestWithRequestOrString( ...@@ -688,9 +702,7 @@ Request* Request::CreateRequestWithRequestOrString(
input_request->request_->SetBuffer(dummy_stream); input_request->request_->SetBuffer(dummy_stream);
// "Let |reader| be the result of getting reader from |dummyStream|." // "Let |reader| be the result of getting reader from |dummyStream|."
// "Read all bytes from |dummyStream| with |reader|." // "Read all bytes from |dummyStream| with |reader|."
input_request->BodyBuffer()->CloseAndLockAndDisturb(exception_state); input_request->BodyBuffer()->CloseAndLockAndDisturb();
if (exception_state.HadException())
return nullptr;
} }
// "Return |r|." // "Return |r|."
...@@ -931,12 +943,9 @@ Request* Request::clone(ScriptState* script_state, ...@@ -931,12 +943,9 @@ Request* Request::clone(ScriptState* script_state,
return MakeGarbageCollected<Request>(script_state, request, headers, signal); return MakeGarbageCollected<Request>(script_state, request, headers, signal);
} }
FetchRequestData* Request::PassRequestData(ScriptState* script_state, FetchRequestData* Request::PassRequestData(ScriptState* script_state) {
ExceptionState& exception_state) {
DCHECK(!IsBodyUsed()); DCHECK(!IsBodyUsed());
FetchRequestData* data = request_->Pass(script_state, exception_state); FetchRequestData* data = request_->Pass(script_state);
if (exception_state.HadException())
return nullptr;
// |data|'s buffer('s js wrapper) has no retainer, but it's OK because // |data|'s buffer('s js wrapper) has no retainer, but it's OK because
// the only caller is the fetch function and it uses the body buffer // the only caller is the fetch function and it uses the body buffer
// immediately. // immediately.
......
...@@ -93,7 +93,7 @@ class CORE_EXPORT Request final : public ScriptWrappable, ...@@ -93,7 +93,7 @@ class CORE_EXPORT Request final : public ScriptWrappable,
return Body::HasPendingActivity(); return Body::HasPendingActivity();
} }
FetchRequestData* PassRequestData(ScriptState*, ExceptionState&); FetchRequestData* PassRequestData(ScriptState*);
mojom::blink::FetchAPIRequestPtr CreateFetchAPIRequest() const; mojom::blink::FetchAPIRequestPtr CreateFetchAPIRequest() const;
bool HasBody() const; bool HasBody() const;
BodyStreamBuffer* BodyBuffer() override { return request_->Buffer(); } BodyStreamBuffer* BodyBuffer() override { return request_->Buffer(); }
......
...@@ -1581,19 +1581,13 @@ void ReadableStream::Tee(ScriptState* script_state, ...@@ -1581,19 +1581,13 @@ void ReadableStream::Tee(ScriptState* script_state,
*branch2 = engine->Branch2(); *branch2 = engine->Branch2();
} }
void ReadableStream::LockAndDisturb(ScriptState* script_state, void ReadableStream::LockAndDisturb(ScriptState* script_state) {
ExceptionState& exception_state) {
ScriptState::Scope scope(script_state);
if (reader_) { if (reader_) {
return; return;
} }
ReadableStreamReader* reader = ReadableStreamReader* reader = GetReaderNotForAuthorCode(script_state);
AcquireDefaultReader(script_state, this, false, exception_state); DCHECK(reader);
if (!reader) {
return;
}
is_disturbed_ = true; is_disturbed_ = true;
} }
...@@ -1633,8 +1627,11 @@ ReadableStream* ReadableStream::Deserialize(ScriptState* script_state, ...@@ -1633,8 +1627,11 @@ ReadableStream* ReadableStream::Deserialize(ScriptState* script_state,
} }
ReadableStreamDefaultReader* ReadableStream::GetReaderNotForAuthorCode( ReadableStreamDefaultReader* ReadableStream::GetReaderNotForAuthorCode(
ScriptState* script_state, ScriptState* script_state) {
ExceptionState& exception_state) { DCHECK(!IsLocked(this));
// Since the stream is not locked, AcquireDefaultReader cannot fail.
NonThrowableExceptionState exception_state(__FILE__, __LINE__);
return AcquireDefaultReader(script_state, this, false, exception_state); return AcquireDefaultReader(script_state, this, false, exception_state);
} }
......
...@@ -153,7 +153,7 @@ class CORE_EXPORT ReadableStream : public ScriptWrappable { ...@@ -153,7 +153,7 @@ class CORE_EXPORT ReadableStream : public ScriptWrappable {
bool IsErrored() const { return IsErrored(this); } bool IsErrored() const { return IsErrored(this); }
void LockAndDisturb(ScriptState*, ExceptionState&); void LockAndDisturb(ScriptState*);
void Serialize(ScriptState*, MessagePort* port, ExceptionState&); void Serialize(ScriptState*, MessagePort* port, ExceptionState&);
...@@ -164,9 +164,9 @@ class CORE_EXPORT ReadableStream : public ScriptWrappable { ...@@ -164,9 +164,9 @@ class CORE_EXPORT ReadableStream : public ScriptWrappable {
// Returns a reader that doesn't have the |for_author_code_| flag set. This is // Returns a reader that doesn't have the |for_author_code_| flag set. This is
// used in contexts where reads should not be interceptable by user code. This // used in contexts where reads should not be interceptable by user code. This
// corresponds to calling AcquireReadableStreamDefaultReader(stream, false) in // corresponds to calling AcquireReadableStreamDefaultReader(stream, false) in
// specification language. // specification language. The caller must ensure that the stream is not
ReadableStreamDefaultReader* GetReaderNotForAuthorCode(ScriptState*, // locked.
ExceptionState&); ReadableStreamDefaultReader* GetReaderNotForAuthorCode(ScriptState*);
// //
// Readable stream abstract operations // Readable stream abstract operations
......
...@@ -336,7 +336,6 @@ TEST_F(ReadableStreamTest, Error) { ...@@ -336,7 +336,6 @@ TEST_F(ReadableStreamTest, Error) {
TEST_F(ReadableStreamTest, LockAndDisturb) { TEST_F(ReadableStreamTest, LockAndDisturb) {
V8TestingScope scope; V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState(); ScriptState* script_state = scope.GetScriptState();
ExceptionState& exception_state = scope.GetExceptionState();
auto* underlying_source = auto* underlying_source =
MakeGarbageCollected<TestUnderlyingSource>(script_state); MakeGarbageCollected<TestUnderlyingSource>(script_state);
...@@ -348,8 +347,7 @@ TEST_F(ReadableStreamTest, LockAndDisturb) { ...@@ -348,8 +347,7 @@ TEST_F(ReadableStreamTest, LockAndDisturb) {
EXPECT_FALSE(stream->IsLocked()); EXPECT_FALSE(stream->IsLocked());
EXPECT_FALSE(stream->IsDisturbed()); EXPECT_FALSE(stream->IsDisturbed());
stream->LockAndDisturb(script_state, exception_state); stream->LockAndDisturb(script_state);
ASSERT_FALSE(exception_state.HadException());
EXPECT_TRUE(stream->IsLocked()); EXPECT_TRUE(stream->IsLocked());
EXPECT_TRUE(stream->IsDisturbed()); EXPECT_TRUE(stream->IsDisturbed());
......
...@@ -143,10 +143,7 @@ scoped_refptr<BlobDataHandle> ExtractBlobHandle( ...@@ -143,10 +143,7 @@ scoped_refptr<BlobDataHandle> ExtractBlobHandle(
return nullptr; return nullptr;
auto blob_handle = buffer->DrainAsBlobDataHandle( auto blob_handle = buffer->DrainAsBlobDataHandle(
BytesConsumer::BlobSizePolicy::kDisallowBlobWithInvalidSize, BytesConsumer::BlobSizePolicy::kDisallowBlobWithInvalidSize);
exception_state);
if (exception_state.HadException())
return nullptr;
return blob_handle; return blob_handle;
} }
......
...@@ -327,12 +327,8 @@ void FetchRespondWithObserver::OnResponseFulfilled( ...@@ -327,12 +327,8 @@ void FetchRespondWithObserver::OnResponseFulfilled(
scoped_refptr<BlobDataHandle> blob_data_handle = scoped_refptr<BlobDataHandle> blob_data_handle =
buffer->DrainAsBlobDataHandle( buffer->DrainAsBlobDataHandle(
BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize, BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize);
exception_state);
if (exception_state.HadException()) {
OnResponseRejected(ServiceWorkerResponseError::kResponseBodyBroken);
return;
}
if (blob_data_handle) { if (blob_data_handle) {
// Handle the blob response body. // Handle the blob response body.
fetch_api_response->blob = blob_data_handle; fetch_api_response->blob = blob_data_handle;
......
...@@ -75,10 +75,14 @@ ImageDecoderExternal::ImageDecoderExternal(ScriptState* script_state, ...@@ -75,10 +75,14 @@ ImageDecoderExternal::ImageDecoderExternal(ScriptState* script_state,
prefer_animation_ = init->preferAnimation(); prefer_animation_ = init->preferAnimation();
if (init->data().IsReadableStream()) { if (init->data().IsReadableStream()) {
consumer_ = MakeGarbageCollected<ReadableStreamBytesConsumer>( if (init->data().GetAsReadableStream()->IsLocked()) {
script_state, init->data().GetAsReadableStream(), exception_state); exception_state.ThrowTypeError(
if (exception_state.HadException()) "ImageDecoder can only accept readable streams that are not yet "
"locked to a reader");
return; return;
}
consumer_ = MakeGarbageCollected<ReadableStreamBytesConsumer>(
script_state, init->data().GetAsReadableStream());
stream_buffer_ = WTF::SharedBuffer::Create(); stream_buffer_ = WTF::SharedBuffer::Create();
CreateImageDecoder(); CreateImageDecoder();
......
This is a testharness.js-based test. This is a testharness.js-based test.
PASS Constructing a Request with a stream holds the original object. PASS Constructing a Request with a stream holds the original object.
FAIL Constructing a Request with a stream on which getReader() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw PASS Constructing a Request with a stream on which getReader() is called
FAIL Constructing a Request with a stream on which read() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw PASS Constructing a Request with a stream on which read() is called
FAIL Constructing a Request with a stream on which read() and releaseLock() are called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw PASS Constructing a Request with a stream on which read() and releaseLock() are called
FAIL Constructing a Request with a Request on which body.getReader() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw FAIL Constructing a Request with a Request on which body.getReader() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw
FAIL Constructing a Request with a Request on which body.getReader().read() is called promise_test: Unhandled rejection with value: object "TypeError: Failed to construct 'Request': Cannot construct a Request with a Request object that has already been used." FAIL Constructing a Request with a Request on which body.getReader().read() is called promise_test: Unhandled rejection with value: object "TypeError: Failed to construct 'Request': Cannot construct a Request with a Request object that has already been used."
FAIL Constructing a Request with a Request on which read() and releaseLock() are called promise_test: Unhandled rejection with value: object "TypeError: Failed to construct 'Request': Cannot construct a Request with a Request object that has already been used." FAIL Constructing a Request with a Request on which read() and releaseLock() are called promise_test: Unhandled rejection with value: object "TypeError: Failed to construct 'Request': Cannot construct a Request with a Request object that has already been used."
......
This is a testharness.js-based test. This is a testharness.js-based test.
PASS Constructing a Request with a stream holds the original object. PASS Constructing a Request with a stream holds the original object.
FAIL Constructing a Request with a stream on which getReader() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw PASS Constructing a Request with a stream on which getReader() is called
FAIL Constructing a Request with a stream on which read() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw PASS Constructing a Request with a stream on which read() is called
FAIL Constructing a Request with a stream on which read() and releaseLock() are called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw PASS Constructing a Request with a stream on which read() and releaseLock() are called
FAIL Constructing a Request with a Request on which body.getReader() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw FAIL Constructing a Request with a Request on which body.getReader() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw
FAIL Constructing a Request with a Request on which body.getReader().read() is called promise_test: Unhandled rejection with value: object "TypeError: Failed to construct 'Request': Cannot construct a Request with a Request object that has already been used." FAIL Constructing a Request with a Request on which body.getReader().read() is called promise_test: Unhandled rejection with value: object "TypeError: Failed to construct 'Request': Cannot construct a Request with a Request object that has already been used."
FAIL Constructing a Request with a Request on which read() and releaseLock() are called promise_test: Unhandled rejection with value: object "TypeError: Failed to construct 'Request': Cannot construct a Request with a Request object that has already been used." FAIL Constructing a Request with a Request on which read() and releaseLock() are called promise_test: Unhandled rejection with value: object "TypeError: Failed to construct 'Request': Cannot construct a Request with a Request object that has already been used."
......
This is a testharness.js-based test. This is a testharness.js-based test.
PASS Constructing a Request with a stream holds the original object. PASS Constructing a Request with a stream holds the original object.
FAIL Constructing a Request with a stream on which getReader() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw PASS Constructing a Request with a stream on which getReader() is called
FAIL Constructing a Request with a stream on which read() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw PASS Constructing a Request with a stream on which read() is called
FAIL Constructing a Request with a stream on which read() and releaseLock() are called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw PASS Constructing a Request with a stream on which read() and releaseLock() are called
FAIL Constructing a Request with a Request on which body.getReader() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw FAIL Constructing a Request with a Request on which body.getReader() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw
FAIL Constructing a Request with a Request on which body.getReader().read() is called promise_test: Unhandled rejection with value: object "TypeError: Failed to construct 'Request': Cannot construct a Request with a Request object that has already been used." FAIL Constructing a Request with a Request on which body.getReader().read() is called promise_test: Unhandled rejection with value: object "TypeError: Failed to construct 'Request': Cannot construct a Request with a Request object that has already been used."
FAIL Constructing a Request with a Request on which read() and releaseLock() are called promise_test: Unhandled rejection with value: object "TypeError: Failed to construct 'Request': Cannot construct a Request with a Request object that has already been used." FAIL Constructing a Request with a Request on which read() and releaseLock() are called promise_test: Unhandled rejection with value: object "TypeError: Failed to construct 'Request': Cannot construct a Request with a Request object that has already been used."
......
This is a testharness.js-based test. This is a testharness.js-based test.
PASS Constructing a Request with a stream holds the original object. PASS Constructing a Request with a stream holds the original object.
FAIL Constructing a Request with a stream on which getReader() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw PASS Constructing a Request with a stream on which getReader() is called
FAIL Constructing a Request with a stream on which read() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw PASS Constructing a Request with a stream on which read() is called
FAIL Constructing a Request with a stream on which read() and releaseLock() are called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw PASS Constructing a Request with a stream on which read() and releaseLock() are called
FAIL Constructing a Request with a Request on which body.getReader() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw FAIL Constructing a Request with a Request on which body.getReader() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw
FAIL Constructing a Request with a Request on which body.getReader().read() is called promise_test: Unhandled rejection with value: object "TypeError: Failed to construct 'Request': Cannot construct a Request with a Request object that has already been used." FAIL Constructing a Request with a Request on which body.getReader().read() is called promise_test: Unhandled rejection with value: object "TypeError: Failed to construct 'Request': Cannot construct a Request with a Request object that has already been used."
FAIL Constructing a Request with a Request on which read() and releaseLock() are called promise_test: Unhandled rejection with value: object "TypeError: Failed to construct 'Request': Cannot construct a Request with a Request object that has already been used." FAIL Constructing a Request with a Request on which read() and releaseLock() are called promise_test: Unhandled rejection with value: object "TypeError: Failed to construct 'Request': Cannot construct a Request with a Request object that has already been used."
......
This is a testharness.js-based test.
FAIL Constructing a Request with a stream on which getReader() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw
FAIL Constructing a Request with a stream on which read() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw
FAIL Constructing a Request with a stream on which read() and releaseLock() are called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw
FAIL Constructing a Request with a Request on which body.getReader() is called promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'getReader' of undefined"
FAIL Constructing a Request with a Request on which body.getReader().read() is called promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'getReader' of undefined"
FAIL Constructing a Request with a Request on which read() and releaseLock() are called promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'getReader' of undefined"
Harness: the test ran to completion.
This is a testharness.js-based test.
FAIL Constructing a Request with a stream on which getReader() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw
FAIL Constructing a Request with a stream on which read() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw
FAIL Constructing a Request with a stream on which read() and releaseLock() are called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw
FAIL Constructing a Request with a Request on which body.getReader() is called promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'getReader' of undefined"
FAIL Constructing a Request with a Request on which body.getReader().read() is called promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'getReader' of undefined"
FAIL Constructing a Request with a Request on which read() and releaseLock() are called promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'getReader' of undefined"
Harness: the test ran to completion.
This is a testharness.js-based test.
FAIL Constructing a Request with a stream on which getReader() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw
FAIL Constructing a Request with a stream on which read() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw
FAIL Constructing a Request with a stream on which read() and releaseLock() are called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw
FAIL Constructing a Request with a Request on which body.getReader() is called promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'getReader' of undefined"
FAIL Constructing a Request with a Request on which body.getReader().read() is called promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'getReader' of undefined"
FAIL Constructing a Request with a Request on which read() and releaseLock() are called promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'getReader' of undefined"
Harness: the test ran to completion.
This is a testharness.js-based test.
FAIL Constructing a Request with a stream on which getReader() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw
FAIL Constructing a Request with a stream on which read() is called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw
FAIL Constructing a Request with a stream on which read() and releaseLock() are called assert_throws_js: new Request() function "() => new Request(input, init)" did not throw
FAIL Constructing a Request with a Request on which body.getReader() is called promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'getReader' of undefined"
FAIL Constructing a Request with a Request on which body.getReader().read() is called promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'getReader' of undefined"
FAIL Constructing a Request with a Request on which read() and releaseLock() are called promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'getReader' of undefined"
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