From 54a987ad45a306dde24554373831b4350fc7f3af Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Thu, 22 Sep 2022 17:30:54 +0100 Subject: [PATCH] LibWeb: Update extract_body() to use BodyInit --- Userland/Libraries/LibWeb/Fetch/BodyInit.cpp | 41 +++++++++++++------ Userland/Libraries/LibWeb/Fetch/BodyInit.h | 2 +- .../Libraries/LibWeb/XHR/XMLHttpRequest.cpp | 2 +- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/Userland/Libraries/LibWeb/Fetch/BodyInit.cpp b/Userland/Libraries/LibWeb/Fetch/BodyInit.cpp index 20eda60e52a..3014369415d 100644 --- a/Userland/Libraries/LibWeb/Fetch/BodyInit.cpp +++ b/Userland/Libraries/LibWeb/Fetch/BodyInit.cpp @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -14,13 +15,18 @@ namespace Web::Fetch { // https://fetch.spec.whatwg.org/#concept-bodyinit-extract -// FIXME: The parameter 'body_init' should be 'typedef (ReadableStream or XMLHttpRequestBodyInit) BodyInit'. For now we just let it be 'XMLHttpRequestBodyInit'. -ErrorOr extract_body(JS::Realm& realm, XMLHttpRequestBodyInit const& body_init) +DOM::ExceptionOr extract_body(JS::Realm& realm, BodyInit const& object, bool keepalive) { auto& window = verify_cast(realm.global_object()); - // FIXME: 1. Let stream be object if object is a ReadableStream object. Otherwise, let stream be a new ReadableStream, and set up stream. - auto* stream = realm.heap().allocate(realm, window); + // 1. Let stream be object if object is a ReadableStream object. Otherwise, let stream be a new ReadableStream, and set up stream. + Streams::ReadableStream* stream; + if (auto const* handle = object.get_pointer>()) { + stream = const_cast(handle->cell()); + } else { + stream = realm.heap().allocate(realm, window); + } + // FIXME: 2. Let action be null. // 3. Let source be null. Infrastructure::Body::SourceType source {}; @@ -31,8 +37,8 @@ ErrorOr extract_body(JS::Realm& realm, XMLHttpRequ // 6. Switch on object. // FIXME: Still need to support BufferSource and FormData - TRY(body_init.visit( - [&](JS::Handle const& blob) -> ErrorOr { + TRY(object.visit( + [&](JS::Handle const& blob) -> DOM::ExceptionOr { // FIXME: Set action to this step: read object. // Set source to object. source = blob; @@ -43,24 +49,35 @@ ErrorOr extract_body(JS::Realm& realm, XMLHttpRequ type = blob->type().to_byte_buffer(); return {}; }, - [&](JS::Handle const& buffer_source) -> ErrorOr { + [&](JS::Handle const& buffer_source) -> DOM::ExceptionOr { // Set source to a copy of the bytes held by object. - source = TRY(Bindings::IDL::get_buffer_source_copy(*buffer_source.cell())); + source = TRY_OR_RETURN_OOM(window, Bindings::IDL::get_buffer_source_copy(*buffer_source.cell())); return {}; }, - [&](JS::Handle const& url_search_params) -> ErrorOr { + [&](JS::Handle const& url_search_params) -> DOM::ExceptionOr { // Set source to the result of running the application/x-www-form-urlencoded serializer with object’s list. source = url_search_params->to_string().to_byte_buffer(); // Set type to `application/x-www-form-urlencoded;charset=UTF-8`. - type = TRY(ByteBuffer::copy("application/x-www-form-urlencoded;charset=UTF-8"sv.bytes())); + type = TRY_OR_RETURN_OOM(window, ByteBuffer::copy("application/x-www-form-urlencoded;charset=UTF-8"sv.bytes())); return {}; }, - [&](String const& scalar_value_string) -> ErrorOr { + [&](String const& scalar_value_string) -> DOM::ExceptionOr { // NOTE: AK::String is always UTF-8. // Set source to the UTF-8 encoding of object. source = scalar_value_string.to_byte_buffer(); // Set type to `text/plain;charset=UTF-8`. - type = TRY(ByteBuffer::copy("text/plain;charset=UTF-8"sv.bytes())); + type = TRY_OR_RETURN_OOM(window, ByteBuffer::copy("text/plain;charset=UTF-8"sv.bytes())); + return {}; + }, + [&](JS::Handle const& stream) -> DOM::ExceptionOr { + // If keepalive is true, then throw a TypeError. + if (keepalive) + return DOM::SimpleException { DOM::SimpleExceptionType::TypeError, "Cannot extract body from stream when keepalive is set" }; + + // If object is disturbed or locked, then throw a TypeError. + if (stream->is_disturbed() || stream->is_locked()) + return DOM::SimpleException { DOM::SimpleExceptionType::TypeError, "Cannot extract body from disturbed or locked stream" }; + return {}; })); diff --git a/Userland/Libraries/LibWeb/Fetch/BodyInit.h b/Userland/Libraries/LibWeb/Fetch/BodyInit.h index cd2be228577..f60d3ade2ed 100644 --- a/Userland/Libraries/LibWeb/Fetch/BodyInit.h +++ b/Userland/Libraries/LibWeb/Fetch/BodyInit.h @@ -19,6 +19,6 @@ using XMLHttpRequestBodyInit = Variant, JS::Handle, JS::Handle, JS::Handle, JS::Handle, String>; -ErrorOr extract_body(JS::Realm&, XMLHttpRequestBodyInit const&); +DOM::ExceptionOr extract_body(JS::Realm&, BodyInit const&, bool keepalive = false); } diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp index 31cd8da00e0..3cffd94dc36 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp @@ -410,7 +410,7 @@ DOM::ExceptionOr XMLHttpRequest::send(Optional {}; + auto body_with_type = body.has_value() ? TRY(Fetch::extract_body(realm, body.value())) : Optional {}; AK::URL request_url = m_window->associated_document().parse_url(m_url.to_string()); dbgln("XHR send from {} to {}", m_window->associated_document().url(), request_url);