Coverage Report

Created: 2025-03-04 07:22

/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
}