Bug 1303025 - Accept null for body param in constructor of Response. r=bkelly
authorXidorn Quan <me@upsuper.org>
Sat, 13 Jan 2018 14:20:50 +1100
changeset 453873 62f5c4a3682381134b607d359824b7605ec15156
parent 453872 10ea246d416b35cc9a7457553ef2f5c8419a5cd1
child 453874 857bda1e6d53c19b3f9b7de23070d64ab5a84c3e
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbkelly
bugs1303025
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1303025 - Accept null for body param in constructor of Response. r=bkelly MozReview-Commit-ID: LeEFcQzPJlv
dom/fetch/Response.cpp
dom/fetch/Response.h
dom/webidl/Response.webidl
testing/web-platform/tests/fetch/api/response/response-init-002.html
--- a/dom/fetch/Response.cpp
+++ b/dom/fetch/Response.cpp
@@ -135,17 +135,17 @@ Response::Redirect(const GlobalObject& a
     return nullptr;
   }
 
   if (aStatus != 301 && aStatus != 302 && aStatus != 303 && aStatus != 307 && aStatus != 308) {
     aRv.ThrowRangeError<MSG_INVALID_REDIRECT_STATUSCODE_ERROR>();
     return nullptr;
   }
 
-  Optional<fetch::ResponseBodyInit> body;
+  Optional<Nullable<fetch::ResponseBodyInit>> body;
   ResponseInit init;
   init.mStatus = aStatus;
   RefPtr<Response> r = Response::Constructor(aGlobal, body, init, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
   r->GetInternalHeaders()->Set(NS_LITERAL_CSTRING("Location"),
@@ -156,17 +156,17 @@ Response::Redirect(const GlobalObject& a
   r->GetInternalHeaders()->SetGuard(HeadersGuardEnum::Immutable, aRv);
   MOZ_ASSERT(!aRv.Failed());
 
   return r.forget();
 }
 
 /*static*/ already_AddRefed<Response>
 Response::Constructor(const GlobalObject& aGlobal,
-                      const Optional<fetch::ResponseBodyInit>& aBody,
+                      const Optional<Nullable<fetch::ResponseBodyInit>>& aBody,
                       const ResponseInit& aInit, ErrorResult& aRv)
 {
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
 
   if (aInit.mStatus < 200 || aInit.mStatus > 599) {
     aRv.ThrowRangeError<MSG_INVALID_RESPONSE_STATUSCODE_ERROR>();
     return nullptr;
   }
@@ -222,29 +222,29 @@ Response::Constructor(const GlobalObject
     }
 
     internalResponse->Headers()->Fill(*headers->GetInternalHeaders(), aRv);
     if (NS_WARN_IF(aRv.Failed())) {
       return nullptr;
     }
   }
 
-  if (aBody.WasPassed()) {
+  if (aBody.WasPassed() && !aBody.Value().IsNull()) {
     if (aInit.mStatus == 204 || aInit.mStatus == 205 || aInit.mStatus == 304) {
       aRv.ThrowTypeError<MSG_RESPONSE_NULL_STATUS_WITH_BODY>();
       return nullptr;
     }
 
     nsCString contentTypeWithCharset;
     nsCOMPtr<nsIInputStream> bodyStream;
     int64_t bodySize = InternalResponse::UNKNOWN_BODY_SIZE;
 
-    if (aBody.Value().IsReadableStream()) {
-      const ReadableStream& readableStream =
-        aBody.Value().GetAsReadableStream();
+    const fetch::ResponseBodyInit& body = aBody.Value().Value();
+    if (body.IsReadableStream()) {
+      const ReadableStream& readableStream = body.GetAsReadableStream();
 
       JS::Rooted<JSObject*> readableStreamObj(aGlobal.Context(),
                                               readableStream.Obj());
 
       if (JS::ReadableStreamIsDisturbed(readableStreamObj) ||
           JS::ReadableStreamIsLocked(readableStreamObj) ||
           !JS::ReadableStreamIsReadable(readableStreamObj)) {
         aRv.ThrowTypeError<MSG_FETCH_BODY_CONSUMED_ERROR>();
@@ -283,17 +283,17 @@ Response::Constructor(const GlobalObject
                                         getter_AddRefs(r->mFetchStreamReader),
                                         getter_AddRefs(bodyStream));
         if (NS_WARN_IF(aRv.Failed())) {
           return nullptr;
         }
       }
     } else {
       uint64_t size = 0;
-      aRv = ExtractByteStreamFromBody(aBody.Value(),
+      aRv = ExtractByteStreamFromBody(body,
                                       getter_AddRefs(bodyStream),
                                       contentTypeWithCharset,
                                       size);
       if (NS_WARN_IF(aRv.Failed())) {
         return nullptr;
       }
 
       bodySize = size;
--- a/dom/fetch/Response.h
+++ b/dom/fetch/Response.h
@@ -115,17 +115,17 @@ public:
   static already_AddRefed<Response>
   Error(const GlobalObject& aGlobal);
 
   static already_AddRefed<Response>
   Redirect(const GlobalObject& aGlobal, const nsAString& aUrl, uint16_t aStatus, ErrorResult& aRv);
 
   static already_AddRefed<Response>
   Constructor(const GlobalObject& aGlobal,
-              const Optional<fetch::ResponseBodyInit>& aBody,
+              const Optional<Nullable<fetch::ResponseBodyInit>>& aBody,
               const ResponseInit& aInit, ErrorResult& rv);
 
   nsIGlobalObject* GetParentObject() const
   {
     return mOwner;
   }
 
   already_AddRefed<Response>
--- a/dom/webidl/Response.webidl
+++ b/dom/webidl/Response.webidl
@@ -4,17 +4,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  * The origin of this IDL file is
  * https://fetch.spec.whatwg.org/#response-class
  */
 
 // This should be Constructor(optional BodyInit... but BodyInit doesn't include
 // ReadableStream yet because we don't want to expose Streams API to Request.
-[Constructor(optional (Blob or BufferSource or FormData or URLSearchParams or ReadableStream or USVString) body, optional ResponseInit init),
+[Constructor(optional (Blob or BufferSource or FormData or URLSearchParams or ReadableStream or USVString)? body, optional ResponseInit init),
  Exposed=(Window,Worker)]
 interface Response {
   [NewObject] static Response error();
   [Throws,
    NewObject] static Response redirect(USVString url, optional unsigned short status = 302);
 
   readonly attribute ResponseType type;
 
--- a/testing/web-platform/tests/fetch/api/response/response-init-002.html
+++ b/testing/web-platform/tests/fetch/api/response/response-init-002.html
@@ -60,11 +60,16 @@
 
       promise_test(function(test) {
         var response = new Response("This is my fork", {"headers" : [["Content-Type", ""]]});
         return response.blob().then(function(blob) {
           assert_equals(blob.type, "", "Blob type should be the empty string");
         });
       }, "Testing empty Response Content-Type header");
 
+      test(function() {
+        var response = new Response(null, {status: 204});
+        assert_equals(response.body, null);
+      }, "Testing null Response body");
+
     </script>
   </body>
 </html>