mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
LibWeb: Integrate Streams in XHR::send()
This commit is contained in:
parent
76418f3ffa
commit
29112f7365
Notes:
sideshowbarker
2024-07-17 09:37:30 +09:00
Author: https://github.com/kennethmyhra Commit: https://github.com/SerenityOS/serenity/commit/29112f7365 Pull-request: https://github.com/SerenityOS/serenity/pull/24132 Reviewed-by: https://github.com/shannonbooth Reviewed-by: https://github.com/trflynn89
1 changed files with 36 additions and 24 deletions
|
@ -3,7 +3,7 @@
|
||||||
* Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
|
* Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
|
||||||
* Copyright (c) 2022-2023, Luke Wilde <lukew@serenityos.org>
|
* Copyright (c) 2022-2023, Luke Wilde <lukew@serenityos.org>
|
||||||
* Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
|
* Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
|
||||||
* Copyright (c) 2022-2023, Kenneth Myhra <kennethmyhra@serenityos.org>
|
* Copyright (c) 2022-2024, Kenneth Myhra <kennethmyhra@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -38,6 +38,7 @@
|
||||||
#include <LibWeb/HTML/Origin.h>
|
#include <LibWeb/HTML/Origin.h>
|
||||||
#include <LibWeb/HTML/Parser/HTMLEncodingDetection.h>
|
#include <LibWeb/HTML/Parser/HTMLEncodingDetection.h>
|
||||||
#include <LibWeb/HTML/Parser/HTMLParser.h>
|
#include <LibWeb/HTML/Parser/HTMLParser.h>
|
||||||
|
#include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
|
||||||
#include <LibWeb/HTML/Window.h>
|
#include <LibWeb/HTML/Window.h>
|
||||||
#include <LibWeb/Infra/ByteSequences.h>
|
#include <LibWeb/Infra/ByteSequences.h>
|
||||||
#include <LibWeb/Infra/JSON.h>
|
#include <LibWeb/Infra/JSON.h>
|
||||||
|
@ -813,34 +814,45 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
|
||||||
// FIXME: We can't implement these steps yet, as we don't fully implement the Streams standard.
|
// FIXME: We can't implement these steps yet, as we don't fully implement the Streams standard.
|
||||||
|
|
||||||
// 10. Let processBodyChunk given bytes be these steps:
|
// 10. Let processBodyChunk given bytes be these steps:
|
||||||
// 1. Append bytes to this’s received bytes.
|
auto process_body_chunks = JS::create_heap_function(heap(), [this, length](ByteBuffer byte_buffer) {
|
||||||
// 2. If not roughly 50ms have passed since these steps were last invoked, then return.
|
// 1. Append bytes to this’s received bytes.
|
||||||
// 3. If this’s state is headers received, then set this’s state to loading.
|
m_received_bytes.append(byte_buffer);
|
||||||
// 4. Fire an event named readystatechange at this.
|
|
||||||
// Spec Note: Web compatibility is the reason readystatechange fires more often than this’s state changes.
|
// FIXME: 2. If not roughly 50ms have passed since these steps were last invoked, then return.
|
||||||
// 5. Fire a progress event named progress at this with this’s received bytes’s length and length.
|
|
||||||
|
// 3. If this’s state is headers received, then set this’s state to loading.
|
||||||
|
if (m_state == State::HeadersReceived)
|
||||||
|
m_state = State::Loading;
|
||||||
|
|
||||||
|
// 4. Fire an event named readystatechange at this.
|
||||||
|
// Spec Note: Web compatibility is the reason readystatechange fires more often than this’s state changes.
|
||||||
|
dispatch_event(*DOM::Event::create(this->realm(), 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<u64>());
|
||||||
|
});
|
||||||
|
|
||||||
// 11. Let processEndOfBody be this step: run handle response end-of-body for this.
|
// 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:
|
// 12. Let processBodyError be these steps:
|
||||||
// 1. Set this’s response to a network error.
|
auto process_body_error = JS::create_heap_function(heap(), [this](JS::Value) {
|
||||||
// 2. Run handle errors for this.
|
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.
|
// 13. Incrementally read this’s response’s body, given processBodyChunk, processEndOfBody, processBodyError, and this’s relevant global object.
|
||||||
};
|
auto global_object = JS::NonnullGCPtr<JS::Object> { HTML::relevant_global_object(*this) };
|
||||||
|
response->body()->incrementally_read(process_body_chunks, process_end_of_body, process_body_error, 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<Fetch::Infrastructure::Response>, Variant<Empty, Fetch::Infrastructure::FetchAlgorithms::ConsumeBodyFailureTag, ByteBuffer> 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<ByteBuffer>()) {
|
|
||||||
// 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<ByteBuffer>());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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.
|
// 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<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
|
||||||
.process_early_hints_response = {},
|
.process_early_hints_response = {},
|
||||||
.process_response = move(process_response),
|
.process_response = move(process_response),
|
||||||
.process_response_end_of_body = {},
|
.process_response_end_of_body = {},
|
||||||
.process_response_consume_body = move(process_response_consume_body), // FIXME: Set this to null once we implement the Streams standard. See above.
|
.process_response_consume_body = {},
|
||||||
})));
|
})));
|
||||||
|
|
||||||
// 11. Let now be the present time.
|
// 11. Let now be the present time.
|
||||||
|
|
Loading…
Reference in a new issue