Coverage Report

Created: 2025-03-04 07:22

/src/serenity/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
3
 * Copyright (c) 2024, Jelle Raaijmakers <jelle@gmta.nl>
4
 *
5
 * SPDX-License-Identifier: BSD-2-Clause
6
 */
7
8
#pragma once
9
10
#include <AK/String.h>
11
#include <AK/WeakPtr.h>
12
#include <LibWeb/Bindings/HTMLFormElementPrototype.h>
13
#include <LibWeb/Forward.h>
14
#include <LibWeb/WebIDL/Types.h>
15
16
namespace Web::HTML {
17
18
// Form-associated elements should invoke this macro to inject overridden FormAssociatedElement and HTMLElement
19
// methods as needed. If your class wished to override an HTMLElement method that is overridden here, use the
20
// following methods instead:
21
//
22
//    HTMLElement::inserted() -> Use form_associated_element_was_inserted()
23
//    HTMLElement::removed_from() -> Use form_associated_element_was_removed()
24
//
25
#define FORM_ASSOCIATED_ELEMENT(ElementBaseClass, ElementClass)                                                                      \
26
private:                                                                                                                             \
27
    virtual HTMLElement& form_associated_element_to_html_element() override                                                          \
28
0
    {                                                                                                                                \
29
0
        static_assert(IsBaseOf<HTMLElement, ElementClass>);                                                                          \
30
0
        return *this;                                                                                                                \
31
0
    }                                                                                                                                \
Unexecuted instantiation: Web::HTML::HTMLImageElement::form_associated_element_to_html_element()
Unexecuted instantiation: Web::HTML::HTMLButtonElement::form_associated_element_to_html_element()
Unexecuted instantiation: Web::HTML::HTMLFieldSetElement::form_associated_element_to_html_element()
Unexecuted instantiation: Web::HTML::HTMLInputElement::form_associated_element_to_html_element()
Unexecuted instantiation: Web::HTML::HTMLSelectElement::form_associated_element_to_html_element()
Unexecuted instantiation: Web::HTML::HTMLTextAreaElement::form_associated_element_to_html_element()
Unexecuted instantiation: Web::HTML::HTMLObjectElement::form_associated_element_to_html_element()
Unexecuted instantiation: Web::HTML::HTMLOutputElement::form_associated_element_to_html_element()
32
                                                                                                                                     \
33
    virtual void inserted() override                                                                                                 \
34
0
    {                                                                                                                                \
35
0
        ElementBaseClass::inserted();                                                                                                \
36
0
        form_node_was_inserted();                                                                                                    \
37
0
        form_associated_element_was_inserted();                                                                                      \
38
0
    }                                                                                                                                \
Unexecuted instantiation: Web::HTML::HTMLImageElement::inserted()
Unexecuted instantiation: Web::HTML::HTMLButtonElement::inserted()
Unexecuted instantiation: Web::HTML::HTMLFieldSetElement::inserted()
Unexecuted instantiation: Web::HTML::HTMLInputElement::inserted()
Unexecuted instantiation: Web::HTML::HTMLSelectElement::inserted()
Unexecuted instantiation: Web::HTML::HTMLTextAreaElement::inserted()
Unexecuted instantiation: Web::HTML::HTMLObjectElement::inserted()
Unexecuted instantiation: Web::HTML::HTMLOutputElement::inserted()
39
                                                                                                                                     \
40
    virtual void removed_from(DOM::Node* node) override                                                                              \
41
0
    {                                                                                                                                \
42
0
        ElementBaseClass::removed_from(node);                                                                                        \
43
0
        form_node_was_removed();                                                                                                     \
44
0
        form_associated_element_was_removed(node);                                                                                   \
45
0
    }                                                                                                                                \
Unexecuted instantiation: Web::HTML::HTMLImageElement::removed_from(Web::DOM::Node*)
Unexecuted instantiation: Web::HTML::HTMLButtonElement::removed_from(Web::DOM::Node*)
Unexecuted instantiation: Web::HTML::HTMLFieldSetElement::removed_from(Web::DOM::Node*)
Unexecuted instantiation: Web::HTML::HTMLInputElement::removed_from(Web::DOM::Node*)
Unexecuted instantiation: Web::HTML::HTMLSelectElement::removed_from(Web::DOM::Node*)
Unexecuted instantiation: Web::HTML::HTMLTextAreaElement::removed_from(Web::DOM::Node*)
Unexecuted instantiation: Web::HTML::HTMLObjectElement::removed_from(Web::DOM::Node*)
Unexecuted instantiation: Web::HTML::HTMLOutputElement::removed_from(Web::DOM::Node*)
46
                                                                                                                                     \
47
    virtual void attribute_changed(FlyString const& name, Optional<String> const& old_value, Optional<String> const& value) override \
48
0
    {                                                                                                                                \
49
0
        ElementBaseClass::attribute_changed(name, old_value, value);                                                                 \
50
0
        form_node_attribute_changed(name, value);                                                                                    \
51
0
        form_associated_element_attribute_changed(name, value);                                                                      \
52
0
    }
Unexecuted instantiation: Web::HTML::HTMLImageElement::attribute_changed(AK::FlyString const&, AK::Optional<AK::String> const&, AK::Optional<AK::String> const&)
Unexecuted instantiation: Web::HTML::HTMLButtonElement::attribute_changed(AK::FlyString const&, AK::Optional<AK::String> const&, AK::Optional<AK::String> const&)
Unexecuted instantiation: Web::HTML::HTMLFieldSetElement::attribute_changed(AK::FlyString const&, AK::Optional<AK::String> const&, AK::Optional<AK::String> const&)
Unexecuted instantiation: Web::HTML::HTMLInputElement::attribute_changed(AK::FlyString const&, AK::Optional<AK::String> const&, AK::Optional<AK::String> const&)
Unexecuted instantiation: Web::HTML::HTMLSelectElement::attribute_changed(AK::FlyString const&, AK::Optional<AK::String> const&, AK::Optional<AK::String> const&)
Unexecuted instantiation: Web::HTML::HTMLTextAreaElement::attribute_changed(AK::FlyString const&, AK::Optional<AK::String> const&, AK::Optional<AK::String> const&)
Unexecuted instantiation: Web::HTML::HTMLObjectElement::attribute_changed(AK::FlyString const&, AK::Optional<AK::String> const&, AK::Optional<AK::String> const&)
Unexecuted instantiation: Web::HTML::HTMLOutputElement::attribute_changed(AK::FlyString const&, AK::Optional<AK::String> const&, AK::Optional<AK::String> const&)
53
54
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#selection-direction
55
enum class SelectionDirection {
56
    Forward,
57
    Backward,
58
    None,
59
};
60
61
class FormAssociatedElement {
62
public:
63
0
    HTMLFormElement* form() { return m_form; }
64
0
    HTMLFormElement const* form() const { return m_form; }
65
66
    void set_form(HTMLFormElement*);
67
68
    void element_id_changed(Badge<DOM::Document>);
69
    void element_with_id_was_added_or_removed(Badge<DOM::Document>);
70
71
    bool enabled() const;
72
73
    void set_parser_inserted(Badge<HTMLParser>);
74
75
    // https://html.spec.whatwg.org/multipage/forms.html#category-listed
76
0
    virtual bool is_listed() const { return false; }
77
78
    // https://html.spec.whatwg.org/multipage/forms.html#category-submit
79
0
    virtual bool is_submittable() const { return false; }
80
81
    // https://html.spec.whatwg.org/multipage/forms.html#category-reset
82
0
    virtual bool is_resettable() const { return false; }
83
84
    // https://html.spec.whatwg.org/multipage/forms.html#category-autocapitalize
85
0
    virtual bool is_auto_capitalize_inheriting() const { return false; }
86
87
    // https://html.spec.whatwg.org/multipage/forms.html#concept-button
88
0
    virtual bool is_button() const { return false; }
89
90
    // https://html.spec.whatwg.org/multipage/forms.html#concept-submit-button
91
0
    virtual bool is_submit_button() const { return false; }
92
93
0
    virtual String value() const { return String {}; }
94
95
    virtual HTMLElement& form_associated_element_to_html_element() = 0;
96
0
    HTMLElement const& form_associated_element_to_html_element() const { return const_cast<FormAssociatedElement&>(*this).form_associated_element_to_html_element(); }
97
98
    // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-form-reset-control
99
0
    virtual void reset_algorithm() {};
100
101
    virtual void clear_algorithm();
102
103
    String form_action() const;
104
    WebIDL::ExceptionOr<void> set_form_action(String const&);
105
106
protected:
107
0
    FormAssociatedElement() = default;
108
0
    virtual ~FormAssociatedElement() = default;
109
110
0
    virtual void form_associated_element_was_inserted() { }
111
0
    virtual void form_associated_element_was_removed(DOM::Node*) { }
112
0
    virtual void form_associated_element_attribute_changed(FlyString const&, Optional<String> const&) { }
113
114
    void form_node_was_inserted();
115
    void form_node_was_removed();
116
    void form_node_attribute_changed(FlyString const&, Optional<String> const&);
117
118
private:
119
    void reset_form_owner();
120
121
    WeakPtr<HTMLFormElement> m_form;
122
123
    // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#parser-inserted-flag
124
    bool m_parser_inserted { false };
125
};
126
127
enum class SelectionSource {
128
    UI,
129
    DOM,
130
};
131
132
class FormAssociatedTextControlElement : public FormAssociatedElement {
133
public:
134
    // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-textarea/input-relevant-value
135
    virtual String relevant_value() = 0;
136
    virtual WebIDL::ExceptionOr<void> set_relevant_value(String const&) = 0;
137
138
    virtual void set_dirty_value_flag(bool flag) = 0;
139
140
    // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-select
141
    WebIDL::ExceptionOr<void> select();
142
143
    // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-selectionstart
144
    Optional<WebIDL::UnsignedLong> selection_start() const;
145
    WebIDL::ExceptionOr<void> set_selection_start(Optional<WebIDL::UnsignedLong> const&);
146
147
    // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-selectionend
148
    Optional<WebIDL::UnsignedLong> selection_end() const;
149
    WebIDL::ExceptionOr<void> set_selection_end(Optional<WebIDL::UnsignedLong> const&);
150
151
    // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-selectiondirection
152
    Optional<String> selection_direction() const;
153
    void set_selection_direction(Optional<String> direction);
154
    WebIDL::ExceptionOr<void> set_selection_direction_binding(Optional<String> direction);
155
0
    SelectionDirection selection_direction_state() const { return m_selection_direction; }
156
157
    // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-setrangetext
158
    WebIDL::ExceptionOr<void> set_range_text(String const& replacement);
159
    WebIDL::ExceptionOr<void> set_range_text(String const& replacement, WebIDL::UnsignedLong start, WebIDL::UnsignedLong end, Bindings::SelectionMode = Bindings::SelectionMode::Preserve);
160
161
    // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-setselectionrange
162
    void set_the_selection_range(Optional<WebIDL::UnsignedLong> start, Optional<WebIDL::UnsignedLong> end, SelectionDirection direction = SelectionDirection::None, SelectionSource source = SelectionSource::DOM);
163
164
    // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-setselectionrange
165
    WebIDL::ExceptionOr<void> set_selection_range(Optional<WebIDL::UnsignedLong> start, Optional<WebIDL::UnsignedLong> end, Optional<String> direction);
166
167
protected:
168
    // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-textarea/input-relevant-value
169
    void relevant_value_was_changed(JS::GCPtr<DOM::Text>);
170
171
0
    virtual void selection_was_changed([[maybe_unused]] size_t selection_start, [[maybe_unused]] size_t selection_end) { }
172
173
private:
174
    // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-textarea/input-selection
175
    WebIDL::UnsignedLong m_selection_start { 0 };
176
    WebIDL::UnsignedLong m_selection_end { 0 };
177
    SelectionDirection m_selection_direction { SelectionDirection::None };
178
};
179
180
}