From 9b3da5a142d96229376e62002c33e1fad111c099 Mon Sep 17 00:00:00 2001 From: Kenneth Myhra Date: Fri, 15 Jul 2022 21:54:02 +0200 Subject: [PATCH] LibWeb: Move extract_body() towards spec compliance --- Userland/Libraries/LibWeb/FileAPI/Blob.h | 2 + .../Libraries/LibWeb/XHR/XMLHttpRequest.cpp | 55 ++++++++++++++----- .../Libraries/LibWeb/XHR/XMLHttpRequest.h | 5 -- 3 files changed, 43 insertions(+), 19 deletions(-) diff --git a/Userland/Libraries/LibWeb/FileAPI/Blob.h b/Userland/Libraries/LibWeb/FileAPI/Blob.h index 2b2a645406..0035f243f5 100644 --- a/Userland/Libraries/LibWeb/FileAPI/Blob.h +++ b/Userland/Libraries/LibWeb/FileAPI/Blob.h @@ -54,6 +54,8 @@ private: ByteBuffer m_byte_buffer {}; String m_type {}; + + friend class XHR::XMLHttpRequest; }; } diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp index ca92d34dd8..adb8d7d202 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -311,19 +312,43 @@ Optional XMLHttpRequest::extract_mime_type(Fetch::HeaderLis } // https://fetch.spec.whatwg.org/#concept-bodyinit-extract -static XMLHttpRequest::BodyWithType extract_body(XMLHttpRequestBodyInit const& body) +// FIXME: The parameter 'body_init' should be 'typedef (ReadableStream or XMLHttpRequestBodyInit) BodyInit'. For now we just let it be 'XMLHttpRequestBodyInit'. +static Fetch::BodyWithType extract_body(XMLHttpRequestBodyInit const& body_init) { - XMLHttpRequest::BodyWithType body_with_type {}; - body.visit( + // FIXME: 1. Let stream be object if object is a ReadableStream object. Otherwise, let stream be a new ReadableStream, and set up stream. + Fetch::Body::ReadableStreamDummy stream {}; + // FIXME: 2. Let action be null. + // 3. Let source be null. + Fetch::Body::SourceType source {}; + // 4. Let length be null. + Optional length {}; + // 5. Let type be null. + Optional type {}; + + // 6. Switch on object. + // FIXME: Still need to support Blob, BufferSource and FormData + body_init.visit( [&](NonnullRefPtr const& url_search_params) { - body_with_type.body = url_search_params->to_string().to_byte_buffer(); - body_with_type.type = "application/x-www-form-urlencoded;charset=UTF-8"; + // 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 = MUST(ByteBuffer::copy("application/x-www-form-urlencoded;charset=UTF-8"sv.bytes())); }, - [&](String const& string) { - body_with_type.body = string.to_byte_buffer(); - body_with_type.type = "text/plain;charset=UTF-8"; + [&](String const& scalar_value_string) { + // 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 = MUST(ByteBuffer::copy("text/plain;charset=UTF-8"sv.bytes())); }); - return body_with_type; + + // FIXME: 7. If source is a byte sequence, then set action to a step that returns source and length to source’s length. + // FIXME: 8. If action is non-null, then run these steps in in parallel: + + // 9. Let body be a body whose stream is stream, source is source, and length is length. + auto body = Fetch::Body { move(stream), move(source), move(length) }; + // 10. Return (body, type). + return { .body = move(body), .type = move(type) }; } // https://xhr.spec.whatwg.org/#dom-xmlhttprequest-setrequestheader @@ -465,7 +490,7 @@ DOM::ExceptionOr XMLHttpRequest::send(Optional bod if (m_method.is_one_of("GET"sv, "HEAD"sv)) body = {}; - auto body_with_type = body.has_value() ? extract_body(body.value()) : XMLHttpRequest::BodyWithType {}; + auto body_with_type = body.has_value() ? extract_body(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); @@ -486,10 +511,12 @@ DOM::ExceptionOr XMLHttpRequest::send(Optional bod auto request = LoadRequest::create_for_url_on_page(request_url, m_window->page()); request.set_method(m_method); - if (!body_with_type.body.is_empty()) { - request.set_body(body_with_type.body); - if (!body_with_type.type.is_empty()) - request.set_header("Content-Type", body_with_type.type); + if (body_with_type.has_value()) { + body_with_type->body.source().visit( + [&](ByteBuffer const& buffer) { request.set_body(buffer); }, + [](auto&) {}); + if (body_with_type->type.has_value()) + request.set_header("Content-Type", String { body_with_type->type->span() }); } for (auto& it : m_request_headers) request.set_header(it.key, it.value); diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h index 6aa8585630..83309d2a00 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h @@ -38,11 +38,6 @@ public: Done = 4, }; - struct BodyWithType { - ByteBuffer body; - String type; - }; - using WrapperType = Bindings::XMLHttpRequestWrapper; static NonnullRefPtr create(HTML::Window& window)