Bug 1500879 - Fetch should not consume Request/Response with null-body, r=asuth

The fetch spec treats null bodies specially.  Their Body cannot become
disturbed or locked and a fresh empty ReadableStream is returned whenever an
attempt is made to consume the body.  We currently fail a number of WPT tests
in this area because we do mark the body consumed as exposed via bodyUsed.
This commit is contained in:
Andrea Marchesini
2018-11-06 14:48:07 +01:00
parent b0eb9e53e3
commit f43567d65d
13 changed files with 227 additions and 86 deletions

View File

@@ -40,6 +40,7 @@
#include "mozilla/Telemetry.h"
#include "BodyExtractor.h"
#include "EmptyBody.h"
#include "FetchObserver.h"
#include "InternalRequest.h"
#include "InternalResponse.h"
@@ -1242,6 +1243,29 @@ FetchBody<Derived>::ConsumeBody(JSContext* aCx, FetchConsumeType aType,
return nullptr;
}
// Null bodies are a special-case in the fetch spec. The Body mix-in can only
// be "disturbed" or "locked" if its associated "body" is non-null.
// Additionally, the Body min-in's "consume body" algorithm explicitly creates
// a fresh empty ReadableStream object in step 2. This means that `bodyUsed`
// will never return true for a null body.
//
// To this end, we create a fresh (empty) body every time a request is made
// and consume its body here, without marking this FetchBody consumed via
// SetBodyUsed.
nsCOMPtr<nsIInputStream> bodyStream;
DerivedClass()->GetBody(getter_AddRefs(bodyStream));
if (!bodyStream) {
RefPtr<EmptyBody> emptyBody =
EmptyBody::Create(DerivedClass()->GetParentObject(),
DerivedClass()->GetPrincipalInfo().get(),
signalImpl, mMimeType, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
return emptyBody->ConsumeBody(aCx, aType, aRv);
}
SetBodyUsed(aCx, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
@@ -1251,7 +1275,7 @@ FetchBody<Derived>::ConsumeBody(JSContext* aCx, FetchConsumeType aType,
RefPtr<Promise> promise =
FetchBodyConsumer<Derived>::Create(global, mMainThreadEventTarget, this,
signalImpl, aType, aRv);
bodyStream, signalImpl, aType, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
@@ -1269,6 +1293,11 @@ already_AddRefed<Promise>
FetchBody<Response>::ConsumeBody(JSContext* aCx, FetchConsumeType aType,
ErrorResult& aRv);
template
already_AddRefed<Promise>
FetchBody<EmptyBody>::ConsumeBody(JSContext* aCx, FetchConsumeType aType,
ErrorResult& aRv);
template <class Derived>
void
FetchBody<Derived>::SetMimeType()
@@ -1297,6 +1326,13 @@ template
void
FetchBody<Response>::SetMimeType();
template <class Derived>
void
FetchBody<Derived>::OverrideMimeType(const nsACString& aMimeType)
{
mMimeType = aMimeType;
}
template <class Derived>
const nsACString&
FetchBody<Derived>::BodyBlobURISpec() const
@@ -1312,6 +1348,10 @@ template
const nsACString&
FetchBody<Response>::BodyBlobURISpec() const;
template
const nsACString&
FetchBody<EmptyBody>::BodyBlobURISpec() const;
template <class Derived>
const nsAString&
FetchBody<Derived>::BodyLocalPath() const
@@ -1327,6 +1367,10 @@ template
const nsAString&
FetchBody<Response>::BodyLocalPath() const;
template
const nsAString&
FetchBody<EmptyBody>::BodyLocalPath() const;
template <class Derived>
void
FetchBody<Derived>::SetReadableStreamBody(JSContext* aCx, JSObject* aBody)