/src/serenity/Userland/Libraries/LibWeb/Fetch/Infrastructure/IncrementalReadLoopReadRequest.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2024, Kenneth Myhra <kennethmyhra@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #include <LibJS/Runtime/TypedArray.h> |
8 | | #include <LibWeb/Bindings/HostDefined.h> |
9 | | #include <LibWeb/Fetch/Infrastructure/IncrementalReadLoopReadRequest.h> |
10 | | #include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h> |
11 | | |
12 | | namespace Web::Fetch::Infrastructure { |
13 | | |
14 | | JS_DEFINE_ALLOCATOR(IncrementalReadLoopReadRequest); |
15 | | |
16 | | void IncrementalReadLoopReadRequest::on_chunk(JS::Value chunk) |
17 | 0 | { |
18 | 0 | auto& realm = m_reader->realm(); |
19 | | // 1. Let continueAlgorithm be null. |
20 | 0 | JS::GCPtr<JS::HeapFunction<void()>> continue_algorithm; |
21 | | |
22 | | // 2. If chunk is not a Uint8Array object, then set continueAlgorithm to this step: run processBodyError given a TypeError. |
23 | 0 | if (!chunk.is_object() || !is<JS::Uint8Array>(chunk.as_object())) { |
24 | 0 | continue_algorithm = JS::create_heap_function(realm.heap(), [&realm, process_body_error = m_process_body_error] { |
25 | 0 | process_body_error->function()(JS::TypeError::create(realm, "Chunk data is not Uint8Array"sv)); |
26 | 0 | }); |
27 | 0 | } |
28 | | // 3. Otherwise: |
29 | 0 | else { |
30 | | // 1. Let bytes be a copy of chunk. |
31 | | // NOTE: Implementations are strongly encouraged to use an implementation strategy that avoids this copy where possible. |
32 | 0 | auto& uint8_array = static_cast<JS::Uint8Array&>(chunk.as_object()); |
33 | 0 | auto bytes = MUST(ByteBuffer::copy(uint8_array.data())); |
34 | | // 2. Set continueAlgorithm to these steps: |
35 | 0 | continue_algorithm = JS::create_heap_function(realm.heap(), [bytes = move(bytes), body = m_body, reader = m_reader, task_destination = m_task_destination, process_body_chunk = m_process_body_chunk, process_end_of_body = m_process_end_of_body, process_body_error = m_process_body_error] { |
36 | 0 | HTML::TemporaryExecutionContext execution_context { Bindings::host_defined_environment_settings_object(reader->realm()), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes }; |
37 | | // 1. Run processBodyChunk given bytes. |
38 | 0 | process_body_chunk->function()(move(bytes)); |
39 | | |
40 | | // 2. Perform the incrementally-read loop given reader, taskDestination, processBodyChunk, processEndOfBody, and processBodyError. |
41 | 0 | body->incrementally_read_loop(reader, task_destination, process_body_chunk, process_end_of_body, process_body_error); |
42 | 0 | }); |
43 | 0 | } |
44 | | |
45 | | // 4. Queue a fetch task given continueAlgorithm and taskDestination. |
46 | 0 | Fetch::Infrastructure::queue_fetch_task(m_task_destination, *continue_algorithm); |
47 | 0 | } |
48 | | |
49 | | void IncrementalReadLoopReadRequest::on_close() |
50 | 0 | { |
51 | | // 1. Queue a fetch task given processEndOfBody and taskDestination. |
52 | 0 | Fetch::Infrastructure::queue_fetch_task(m_task_destination, JS::create_heap_function(m_reader->heap(), [this] { |
53 | 0 | m_process_end_of_body->function()(); |
54 | 0 | })); |
55 | 0 | } |
56 | | |
57 | | void IncrementalReadLoopReadRequest::on_error(JS::Value error) |
58 | 0 | { |
59 | | // 1. Queue a fetch task to run processBodyError given e, with taskDestination. |
60 | 0 | Fetch::Infrastructure::queue_fetch_task(m_task_destination, JS::create_heap_function(m_reader->heap(), [this, error = move(error)] { |
61 | 0 | m_process_body_error->function()(error); |
62 | 0 | })); |
63 | 0 | } |
64 | | |
65 | | IncrementalReadLoopReadRequest::IncrementalReadLoopReadRequest(JS::NonnullGCPtr<Body> body, JS::NonnullGCPtr<Streams::ReadableStreamDefaultReader> reader, JS::NonnullGCPtr<JS::Object> task_destination, Body::ProcessBodyChunkCallback process_body_chunk, Body::ProcessEndOfBodyCallback process_end_of_body, Body::ProcessBodyErrorCallback process_body_error) |
66 | 0 | : m_body(body) |
67 | 0 | , m_reader(reader) |
68 | 0 | , m_task_destination(task_destination) |
69 | 0 | , m_process_body_chunk(process_body_chunk) |
70 | 0 | , m_process_end_of_body(process_end_of_body) |
71 | 0 | , m_process_body_error(process_body_error) |
72 | 0 | { |
73 | 0 | } |
74 | | |
75 | | void IncrementalReadLoopReadRequest::visit_edges(Visitor& visitor) |
76 | 0 | { |
77 | 0 | Base::visit_edges(visitor); |
78 | 0 | visitor.visit(m_body); |
79 | 0 | visitor.visit(m_reader); |
80 | 0 | visitor.visit(m_task_destination); |
81 | 0 | visitor.visit(m_process_body_chunk); |
82 | 0 | visitor.visit(m_process_end_of_body); |
83 | 0 | visitor.visit(m_process_body_error); |
84 | 0 | } |
85 | | |
86 | | } |