Coverage Report

Created: 2026-05-16 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibWeb/HTML/LazyLoadingElement.h
Line
Count
Source
1
/*
2
 * Copyright (c) 2018-2023, Andreas Kling <kling@serenityos.org>
3
 * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
4
 *
5
 * SPDX-License-Identifier: BSD-2-Clause
6
 */
7
8
#pragma once
9
10
#include <LibWeb/Forward.h>
11
#include <LibWeb/HTML/AttributeNames.h>
12
13
namespace Web::HTML {
14
15
// Lazy-loaded elements should invoke this macro to inject overridden LazyLoadingElement methods.
16
#define LAZY_LOADING_ELEMENT(ElementClass)                                                                     \
17
private:                                                                                                       \
18
    virtual JS::GCPtr<JS::HeapFunction<void()>> take_lazy_load_resumption_steps(Badge<DOM::Document>) override \
19
0
    {                                                                                                          \
20
0
        return take_lazy_load_resumption_steps_internal();                                                     \
21
0
    }                                                                                                          \
Unexecuted instantiation: Web::HTML::HTMLImageElement::take_lazy_load_resumption_steps(AK::Badge<Web::DOM::Document>)
Unexecuted instantiation: Web::HTML::HTMLIFrameElement::take_lazy_load_resumption_steps(AK::Badge<Web::DOM::Document>)
22
                                                                                                               \
23
0
    virtual bool is_lazy_loading() const override { return true; }
Unexecuted instantiation: Web::HTML::HTMLImageElement::is_lazy_loading() const
Unexecuted instantiation: Web::HTML::HTMLIFrameElement::is_lazy_loading() const
24
25
enum class LazyLoading {
26
    Lazy,
27
    Eager,
28
};
29
30
template<typename T>
31
class LazyLoadingElement {
32
public:
33
    // https://html.spec.whatwg.org/multipage/urls-and-fetching.html#lazy-loading-attributes
34
    [[nodiscard]] LazyLoading lazy_loading_attribute() const
35
0
    {
36
0
        auto& element = static_cast<T const&>(*this);
37
38
0
        auto value = element.attribute(HTML::AttributeNames::loading);
39
0
        if (value.has_value() && value->equals_ignoring_ascii_case("lazy"sv))
40
0
            return LazyLoading::Lazy;
41
0
        return LazyLoading::Eager;
42
0
    }
Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLIFrameElement>::lazy_loading_attribute() const
Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLImageElement>::lazy_loading_attribute() const
43
44
    // https://html.spec.whatwg.org/multipage/urls-and-fetching.html#will-lazy-load-element-steps
45
    [[nodiscard]] bool will_lazy_load_element() const
46
0
    {
47
0
        auto& element = static_cast<T const&>(*this);
48
49
        // 1. If scripting is disabled for element, then return false.
50
        // Spec Note: This is an anti-tracking measure, because if a user agent supported lazy loading when scripting is
51
        //            disabled, it would still be possible for a site to track a user's approximate scroll position throughout
52
        //            a session, by strategically placing images in a page's markup such that a server can track how many
53
        //            images are requested and when.
54
0
        if (element.is_scripting_disabled())
55
0
            return false;
56
57
        // 2. If element's lazy loading attribute is in the Lazy state, then return true.
58
        // 3. Return false.
59
0
        return lazy_loading_attribute() == LazyLoading::Lazy;
60
0
    }
Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLIFrameElement>::will_lazy_load_element() const
Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLImageElement>::will_lazy_load_element() const
61
62
    void set_lazy_load_resumption_steps(Function<void()> steps)
63
0
    {
64
0
        auto& element = static_cast<T&>(*this);
65
66
0
        m_lazy_load_resumption_steps = JS::create_heap_function(element.vm().heap(), move(steps));
67
0
    }
Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLIFrameElement>::set_lazy_load_resumption_steps(AK::Function<void ()>)
Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLImageElement>::set_lazy_load_resumption_steps(AK::Function<void ()>)
68
69
    void visit_lazy_loading_element(JS::Cell::Visitor& visitor)
70
0
    {
71
0
        visitor.visit(m_lazy_load_resumption_steps);
72
0
    }
Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLIFrameElement>::visit_lazy_loading_element(JS::Cell::Visitor&)
Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLImageElement>::visit_lazy_loading_element(JS::Cell::Visitor&)
73
74
protected:
75
0
    LazyLoadingElement() = default;
Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLIFrameElement>::LazyLoadingElement()
Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLImageElement>::LazyLoadingElement()
76
0
    virtual ~LazyLoadingElement() = default;
Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLIFrameElement>::~LazyLoadingElement()
Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLImageElement>::~LazyLoadingElement()
77
78
    JS::GCPtr<JS::HeapFunction<void()>> take_lazy_load_resumption_steps_internal()
79
0
    {
80
0
        auto lazy_load_resumption_steps = m_lazy_load_resumption_steps;
81
0
        m_lazy_load_resumption_steps = nullptr;
82
0
        return lazy_load_resumption_steps;
83
0
    }
Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLImageElement>::take_lazy_load_resumption_steps_internal()
Unexecuted instantiation: Web::HTML::LazyLoadingElement<Web::HTML::HTMLIFrameElement>::take_lazy_load_resumption_steps_internal()
84
85
private:
86
    // https://html.spec.whatwg.org/multipage/urls-and-fetching.html#lazy-load-resumption-steps
87
    // Each img and iframe element has associated lazy load resumption steps, initially null.
88
    JS::GCPtr<JS::HeapFunction<void()>> m_lazy_load_resumption_steps;
89
};
90
91
}