From 29112f736514bbbdf674b808dec17ab34ce6d5b9 Mon Sep 17 00:00:00 2001 From: Kenneth Myhra Date: Fri, 17 May 2024 22:11:15 +0200 Subject: [PATCH] LibWeb: Integrate Streams in XHR::send() --- .../Libraries/LibWeb/XHR/XMLHttpRequest.cpp | 60 +++++++++++-------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp index e7c78bf17dc..76c90095a1d 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp @@ -3,7 +3,7 @@ * Copyright (c) 2021-2023, Linus Groh * Copyright (c) 2022-2023, Luke Wilde * Copyright (c) 2022, Ali Mohammad Pur - * Copyright (c) 2022-2023, Kenneth Myhra + * Copyright (c) 2022-2024, Kenneth Myhra * * SPDX-License-Identifier: BSD-2-Clause */ @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -813,34 +814,45 @@ WebIDL::ExceptionOr XMLHttpRequest::send(Optionalrealm(), EventNames::readystatechange)); + + // 5. Fire a progress event named progress at this with this’s received bytes’s length and length. + fire_progress_event(*this, EventNames::progress, m_received_bytes.size(), length.get()); + }); // 11. Let processEndOfBody be this step: run handle response end-of-body for this. + auto process_end_of_body = JS::create_heap_function(heap(), [this]() { + // NOTE: This cannot throw, as `handle_response_end_of_body` only throws in a synchronous context. + // FIXME: However, we can receive allocation failures, but we can't propagate them anywhere currently. + handle_response_end_of_body().release_value_but_fixme_should_propagate_errors(); + }); // 12. Let processBodyError be these steps: - // 1. Set this’s response to a network error. - // 2. Run handle errors for this. + auto process_body_error = JS::create_heap_function(heap(), [this](JS::Value) { + auto& vm = this->vm(); + // 1. Set this’s response to a network error. + m_response = Fetch::Infrastructure::Response::network_error(vm, "A network error occurred processing body."sv); + // 2. Run handle errors for this. + // NOTE: This cannot throw, as `handle_errors` only throws in a synchronous context. + // FIXME: However, we can receive allocation failures, but we can't propagate them anywhere currently. + handle_errors().release_value_but_fixme_should_propagate_errors(); + }); // 13. Incrementally read this’s response’s body, given processBodyChunk, processEndOfBody, processBodyError, and this’s relevant global object. - }; - - // FIXME: Remove this once we implement the Streams standard. See above. - // NOTE: `this` is kept alive by FetchAlgorithms using JS::SafeFunction. - auto process_response_consume_body = [this](JS::NonnullGCPtr, Variant null_or_failure_or_bytes) { - // NOTE: `response` is not used here as `process_response` is called before `process_response_consume_body` and thus `m_response` is already set up. - if (null_or_failure_or_bytes.has()) { - // NOTE: We are not in a context where we can throw if this fails due to OOM. - m_received_bytes.append(null_or_failure_or_bytes.get()); - } - - // NOTE: This cannot throw, as `handle_response_end_of_body` only throws in a synchronous context. - // FIXME: However, we can receive allocation failures, but we can't propagate them anywhere currently. - handle_response_end_of_body().release_value_but_fixme_should_propagate_errors(); + auto global_object = JS::NonnullGCPtr { HTML::relevant_global_object(*this) }; + response->body()->incrementally_read(process_body_chunks, process_end_of_body, process_body_error, global_object); }; // 10. Set this’s fetch controller to the result of fetching req with processRequestBodyChunkLength set to processRequestBodyChunkLength, processRequestEndOfBody set to processRequestEndOfBody, and processResponse set to processResponse. @@ -854,7 +866,7 @@ WebIDL::ExceptionOr XMLHttpRequest::send(Optional