From d140a415fd192a9fb32339bf24f675eb13369b0a Mon Sep 17 00:00:00 2001 From: Tomasz Andrzejak Date: Mon, 25 Nov 2024 13:01:02 +0100 Subject: [PATCH] Implement Request#blob and Response#blob methods --- builtins/web/blob.cpp | 5 +++-- builtins/web/fetch/request-response.cpp | 15 +++++++++++++++ builtins/web/fetch/request-response.h | 1 + .../fetch/api/body/cloned-any.js.json | 2 +- .../api/request/request-consume-empty.any.js.json | 2 +- .../fetch/api/request/request-consume.any.js.json | 12 ++++++------ .../fetch/api/request/request-headers.any.js.json | 2 +- .../api/request/request-structure.any.js.json | 4 ++-- .../response/response-consume-empty.any.js.json | 2 +- .../response-error-from-stream.any.js.json | 4 ++-- .../response-stream-bad-chunk.any.js.json | 2 +- .../response-stream-disturbed-1.any.js.json | 6 +++--- .../response-stream-disturbed-2.any.js.json | 6 +++--- .../response-stream-disturbed-3.any.js.json | 6 +++--- .../response-stream-disturbed-4.any.js.json | 6 +++--- 15 files changed, 46 insertions(+), 29 deletions(-) diff --git a/builtins/web/blob.cpp b/builtins/web/blob.cpp index 42015f4b..56d4cc34 100644 --- a/builtins/web/blob.cpp +++ b/builtins/web/blob.cpp @@ -2,17 +2,18 @@ #include "builtin.h" #include "encode.h" #include "extension-api.h" -#include "js/HashTable.h" -#include "mozilla/UniquePtr.h" #include "rust-encoding.h" #include "streams/native-stream-source.h" +#include "mozilla/UniquePtr.h" #include "js/ArrayBuffer.h" #include "js/Conversions.h" #include "js/experimental/TypedData.h" +#include "js/HashTable.h" #include "js/Stream.h" #include "js/TypeDecls.h" #include "js/Value.h" +#include "js/Vector.h" #include diff --git a/builtins/web/fetch/request-response.cpp b/builtins/web/fetch/request-response.cpp index ee30bdf7..cb862dc8 100644 --- a/builtins/web/fetch/request-response.cpp +++ b/builtins/web/fetch/request-response.cpp @@ -1,5 +1,6 @@ #include "request-response.h" +#include "../blob.h" #include "../streams/native-stream-source.h" #include "../streams/transform-stream.h" #include "../url.h" @@ -8,6 +9,7 @@ #include "extension-api.h" #include "fetch_event.h" #include "host_api.h" +#include "js/String.h" #include "picosha2.h" #include "js/Array.h" @@ -546,6 +548,17 @@ bool RequestOrResponse::parse_body(JSContext *cx, JS::HandleObject self, JS::Uni } static_cast(buf.release()); result.setObject(*array_buffer); + } else if constexpr (result_type == RequestOrResponse::BodyReadResult::Blob) { + auto bytes = reinterpret_cast(buf.get()); + auto data = std::make_unique>(bytes, bytes + len); + JS::RootedObject blob(cx, blob::Blob::create(cx, std::move(data), JS_GetEmptyString(cx))); + + if (!blob) { + return RejectPromiseWithPendingError(cx, result_promise); + } + + // We can drop `buf` as the data has been now copied over to blob + result.setObject(*blob); } else { JS::RootedString text(cx, JS_NewStringCopyUTF8N(cx, JS::UTF8Chars(buf.get(), len))); if (!text) { @@ -1313,6 +1326,7 @@ const JSPropertySpec Request::static_properties[] = { const JSFunctionSpec Request::methods[] = { JS_FN("arrayBuffer", Request::bodyAll, 0, JSPROP_ENUMERATE), + JS_FN("blob", Request::bodyAll, 0, JSPROP_ENUMERATE), JS_FN("json", Request::bodyAll, 0, JSPROP_ENUMERATE), JS_FN("text", Request::bodyAll, 0, JSPROP_ENUMERATE), JS_FN("clone", Request::clone, 0, JSPROP_ENUMERATE), @@ -2304,6 +2318,7 @@ const JSPropertySpec Response::static_properties[] = { const JSFunctionSpec Response::methods[] = { JS_FN("arrayBuffer", bodyAll, 0, JSPROP_ENUMERATE), + JS_FN("blob", bodyAll, 0, JSPROP_ENUMERATE), JS_FN("json", bodyAll, 0, JSPROP_ENUMERATE), JS_FN("text", bodyAll, 0, JSPROP_ENUMERATE), JS_FS_END, diff --git a/builtins/web/fetch/request-response.h b/builtins/web/fetch/request-response.h index b963ca25..0f216f3a 100644 --- a/builtins/web/fetch/request-response.h +++ b/builtins/web/fetch/request-response.h @@ -74,6 +74,7 @@ class RequestOrResponse final { enum class BodyReadResult { ArrayBuffer, + Blob, JSON, Text, }; diff --git a/tests/wpt-harness/expectations/fetch/api/body/cloned-any.js.json b/tests/wpt-harness/expectations/fetch/api/body/cloned-any.js.json index 2a5fcc1a..a8a9143d 100644 --- a/tests/wpt-harness/expectations/fetch/api/body/cloned-any.js.json +++ b/tests/wpt-harness/expectations/fetch/api/body/cloned-any.js.json @@ -12,6 +12,6 @@ "status": "PASS" }, "Blob is cloned": { - "status": "FAIL" + "status": "PASS" } } \ No newline at end of file diff --git a/tests/wpt-harness/expectations/fetch/api/request/request-consume-empty.any.js.json b/tests/wpt-harness/expectations/fetch/api/request/request-consume-empty.any.js.json index f62ab9cb..b3ae1320 100644 --- a/tests/wpt-harness/expectations/fetch/api/request/request-consume-empty.any.js.json +++ b/tests/wpt-harness/expectations/fetch/api/request/request-consume-empty.any.js.json @@ -3,7 +3,7 @@ "status": "PASS" }, "Consume request's body as blob": { - "status": "FAIL" + "status": "PASS" }, "Consume request's body as arrayBuffer": { "status": "PASS" diff --git a/tests/wpt-harness/expectations/fetch/api/request/request-consume.any.js.json b/tests/wpt-harness/expectations/fetch/api/request/request-consume.any.js.json index 29eb926e..91334852 100644 --- a/tests/wpt-harness/expectations/fetch/api/request/request-consume.any.js.json +++ b/tests/wpt-harness/expectations/fetch/api/request/request-consume.any.js.json @@ -3,7 +3,7 @@ "status": "PASS" }, "Consume String request's body as blob": { - "status": "FAIL" + "status": "PASS" }, "Consume String request's body as arrayBuffer": { "status": "PASS" @@ -18,7 +18,7 @@ "status": "PASS" }, "Consume ArrayBuffer request's body as blob": { - "status": "FAIL" + "status": "PASS" }, "Consume ArrayBuffer request's body as arrayBuffer": { "status": "PASS" @@ -33,7 +33,7 @@ "status": "PASS" }, "Consume Uint8Array request's body as blob": { - "status": "FAIL" + "status": "PASS" }, "Consume Uint8Array request's body as arrayBuffer": { "status": "PASS" @@ -48,7 +48,7 @@ "status": "PASS" }, "Consume Int8Array request's body as blob": { - "status": "FAIL" + "status": "PASS" }, "Consume Int8Array request's body as arrayBuffer": { "status": "PASS" @@ -63,7 +63,7 @@ "status": "PASS" }, "Consume Float32Array request's body as blob": { - "status": "FAIL" + "status": "PASS" }, "Consume Float32Array request's body as arrayBuffer": { "status": "PASS" @@ -78,7 +78,7 @@ "status": "PASS" }, "Consume DataView request's body as blob": { - "status": "FAIL" + "status": "PASS" }, "Consume DataView request's body as arrayBuffer": { "status": "PASS" diff --git a/tests/wpt-harness/expectations/fetch/api/request/request-headers.any.js.json b/tests/wpt-harness/expectations/fetch/api/request/request-headers.any.js.json index 98c21422..9aef7b26 100644 --- a/tests/wpt-harness/expectations/fetch/api/request/request-headers.any.js.json +++ b/tests/wpt-harness/expectations/fetch/api/request/request-headers.any.js.json @@ -177,7 +177,7 @@ "status": "PASS" }, "Testing empty Request Content-Type header": { - "status": "FAIL" + "status": "PASS" }, "Test that Request.headers has the [SameObject] extended attribute": { "status": "PASS" diff --git a/tests/wpt-harness/expectations/fetch/api/request/request-structure.any.js.json b/tests/wpt-harness/expectations/fetch/api/request/request-structure.any.js.json index be010b84..c01e04b2 100644 --- a/tests/wpt-harness/expectations/fetch/api/request/request-structure.any.js.json +++ b/tests/wpt-harness/expectations/fetch/api/request/request-structure.any.js.json @@ -6,7 +6,7 @@ "status": "PASS" }, "Request has blob method": { - "status": "FAIL" + "status": "PASS" }, "Request has formData method": { "status": "FAIL" @@ -71,4 +71,4 @@ "Request does not expose blocking attribute": { "status": "PASS" } -} +} \ No newline at end of file diff --git a/tests/wpt-harness/expectations/fetch/api/response/response-consume-empty.any.js.json b/tests/wpt-harness/expectations/fetch/api/response/response-consume-empty.any.js.json index 26ee5254..439c0529 100644 --- a/tests/wpt-harness/expectations/fetch/api/response/response-consume-empty.any.js.json +++ b/tests/wpt-harness/expectations/fetch/api/response/response-consume-empty.any.js.json @@ -3,7 +3,7 @@ "status": "PASS" }, "Consume response's body as blob": { - "status": "FAIL" + "status": "PASS" }, "Consume response's body as arrayBuffer": { "status": "PASS" diff --git a/tests/wpt-harness/expectations/fetch/api/response/response-error-from-stream.any.js.json b/tests/wpt-harness/expectations/fetch/api/response/response-error-from-stream.any.js.json index 14ffc379..9c67f745 100644 --- a/tests/wpt-harness/expectations/fetch/api/response/response-error-from-stream.any.js.json +++ b/tests/wpt-harness/expectations/fetch/api/response/response-error-from-stream.any.js.json @@ -9,7 +9,7 @@ "status": "PASS" }, "ReadableStream start() Error propagates to Response.blob() Promise": { - "status": "FAIL" + "status": "PASS" }, "ReadableStream start() Error propagates to Response.bytes() Promise": { "status": "FAIL" @@ -27,7 +27,7 @@ "status": "PASS" }, "ReadableStream pull() Error propagates to Response.blob() Promise": { - "status": "FAIL" + "status": "PASS" }, "ReadableStream pull() Error propagates to Response.bytes() Promise": { "status": "FAIL" diff --git a/tests/wpt-harness/expectations/fetch/api/response/response-stream-bad-chunk.any.js.json b/tests/wpt-harness/expectations/fetch/api/response/response-stream-bad-chunk.any.js.json index 78654577..6e4cd277 100644 --- a/tests/wpt-harness/expectations/fetch/api/response/response-stream-bad-chunk.any.js.json +++ b/tests/wpt-harness/expectations/fetch/api/response/response-stream-bad-chunk.any.js.json @@ -3,7 +3,7 @@ "status": "PASS" }, "ReadableStream with non-Uint8Array chunk passed to Response.blob() causes TypeError": { - "status": "FAIL" + "status": "PASS" }, "ReadableStream with non-Uint8Array chunk passed to Response.bytes() causes TypeError": { "status": "FAIL" diff --git a/tests/wpt-harness/expectations/fetch/api/response/response-stream-disturbed-1.any.js.json b/tests/wpt-harness/expectations/fetch/api/response/response-stream-disturbed-1.any.js.json index 3dad7f0b..e3fb83ca 100644 --- a/tests/wpt-harness/expectations/fetch/api/response/response-stream-disturbed-1.any.js.json +++ b/tests/wpt-harness/expectations/fetch/api/response/response-stream-disturbed-1.any.js.json @@ -1,6 +1,6 @@ { "Getting blob after getting the Response body - not disturbed, not locked (body source: fetch)": { - "status": "FAIL" + "status": "PASS" }, "Getting text after getting the Response body - not disturbed, not locked (body source: fetch)": { "status": "PASS" @@ -12,7 +12,7 @@ "status": "PASS" }, "Getting blob after getting the Response body - not disturbed, not locked (body source: stream)": { - "status": "FAIL" + "status": "PASS" }, "Getting text after getting the Response body - not disturbed, not locked (body source: stream)": { "status": "PASS" @@ -24,7 +24,7 @@ "status": "PASS" }, "Getting blob after getting the Response body - not disturbed, not locked (body source: string)": { - "status": "FAIL" + "status": "PASS" }, "Getting text after getting the Response body - not disturbed, not locked (body source: string)": { "status": "PASS" diff --git a/tests/wpt-harness/expectations/fetch/api/response/response-stream-disturbed-2.any.js.json b/tests/wpt-harness/expectations/fetch/api/response/response-stream-disturbed-2.any.js.json index d81b359d..590e3c31 100644 --- a/tests/wpt-harness/expectations/fetch/api/response/response-stream-disturbed-2.any.js.json +++ b/tests/wpt-harness/expectations/fetch/api/response/response-stream-disturbed-2.any.js.json @@ -1,6 +1,6 @@ { "Getting blob after getting a locked Response body (body source: fetch)": { - "status": "FAIL" + "status": "PASS" }, "Getting text after getting a locked Response body (body source: fetch)": { "status": "PASS" @@ -12,7 +12,7 @@ "status": "PASS" }, "Getting blob after getting a locked Response body (body source: stream)": { - "status": "FAIL" + "status": "PASS" }, "Getting text after getting a locked Response body (body source: stream)": { "status": "PASS" @@ -24,7 +24,7 @@ "status": "PASS" }, "Getting blob after getting a locked Response body (body source: string)": { - "status": "FAIL" + "status": "PASS" }, "Getting text after getting a locked Response body (body source: string)": { "status": "PASS" diff --git a/tests/wpt-harness/expectations/fetch/api/response/response-stream-disturbed-3.any.js.json b/tests/wpt-harness/expectations/fetch/api/response/response-stream-disturbed-3.any.js.json index b306c09e..9e7c0598 100644 --- a/tests/wpt-harness/expectations/fetch/api/response/response-stream-disturbed-3.any.js.json +++ b/tests/wpt-harness/expectations/fetch/api/response/response-stream-disturbed-3.any.js.json @@ -1,6 +1,6 @@ { "Getting blob after reading the Response body (body source: fetch)": { - "status": "FAIL" + "status": "PASS" }, "Getting text after reading the Response body (body source: fetch)": { "status": "PASS" @@ -12,7 +12,7 @@ "status": "PASS" }, "Getting blob after reading the Response body (body source: stream)": { - "status": "FAIL" + "status": "PASS" }, "Getting text after reading the Response body (body source: stream)": { "status": "PASS" @@ -24,7 +24,7 @@ "status": "PASS" }, "Getting blob after reading the Response body (body source: string)": { - "status": "FAIL" + "status": "PASS" }, "Getting text after reading the Response body (body source: string)": { "status": "PASS" diff --git a/tests/wpt-harness/expectations/fetch/api/response/response-stream-disturbed-4.any.js.json b/tests/wpt-harness/expectations/fetch/api/response/response-stream-disturbed-4.any.js.json index 4b94a293..f0a89799 100644 --- a/tests/wpt-harness/expectations/fetch/api/response/response-stream-disturbed-4.any.js.json +++ b/tests/wpt-harness/expectations/fetch/api/response/response-stream-disturbed-4.any.js.json @@ -1,6 +1,6 @@ { "Getting blob after cancelling the Response body (body source: fetch)": { - "status": "FAIL" + "status": "PASS" }, "Getting text after cancelling the Response body (body source: fetch)": { "status": "PASS" @@ -12,7 +12,7 @@ "status": "PASS" }, "Getting blob after cancelling the Response body (body source: stream)": { - "status": "FAIL" + "status": "PASS" }, "Getting text after cancelling the Response body (body source: stream)": { "status": "PASS" @@ -24,7 +24,7 @@ "status": "PASS" }, "Getting blob after cancelling the Response body (body source: string)": { - "status": "FAIL" + "status": "PASS" }, "Getting text after cancelling the Response body (body source: string)": { "status": "PASS"