/src/serenity/Userland/Libraries/LibWeb/HTML/HTMLSlotElement.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2020, the SerenityOS developers. |
3 | | * Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org> |
4 | | * |
5 | | * SPDX-License-Identifier: BSD-2-Clause |
6 | | */ |
7 | | |
8 | | #include <LibWeb/Bindings/HTMLSlotElementPrototype.h> |
9 | | #include <LibWeb/Bindings/Intrinsics.h> |
10 | | #include <LibWeb/DOM/Element.h> |
11 | | #include <LibWeb/DOM/Text.h> |
12 | | #include <LibWeb/HTML/HTMLSlotElement.h> |
13 | | |
14 | | namespace Web::HTML { |
15 | | |
16 | | JS_DEFINE_ALLOCATOR(HTMLSlotElement); |
17 | | |
18 | | HTMLSlotElement::HTMLSlotElement(DOM::Document& document, DOM::QualifiedName qualified_name) |
19 | 0 | : HTMLElement(document, move(qualified_name)) |
20 | 0 | { |
21 | 0 | } |
22 | | |
23 | 0 | HTMLSlotElement::~HTMLSlotElement() = default; |
24 | | |
25 | | void HTMLSlotElement::initialize(JS::Realm& realm) |
26 | 0 | { |
27 | 0 | Base::initialize(realm); |
28 | 0 | WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLSlotElement); |
29 | 0 | } |
30 | | |
31 | | void HTMLSlotElement::visit_edges(JS::Cell::Visitor& visitor) |
32 | 0 | { |
33 | 0 | Base::visit_edges(visitor); |
34 | 0 | Slot::visit_edges(visitor); |
35 | |
|
36 | 0 | for (auto const& node : m_manually_assigned_nodes) |
37 | 0 | node.visit([&](auto const& slottable) { visitor.visit(slottable); });Unexecuted instantiation: HTMLSlotElement.cpp:auto Web::HTML::HTMLSlotElement::visit_edges(JS::Cell::Visitor&)::$_0::operator()<JS::NonnullGCPtr<Web::DOM::Element> >(JS::NonnullGCPtr<Web::DOM::Element> const&) const Unexecuted instantiation: HTMLSlotElement.cpp:auto Web::HTML::HTMLSlotElement::visit_edges(JS::Cell::Visitor&)::$_0::operator()<JS::NonnullGCPtr<Web::DOM::Text> >(JS::NonnullGCPtr<Web::DOM::Text> const&) const |
38 | 0 | } |
39 | | |
40 | | // https://html.spec.whatwg.org/multipage/scripting.html#dom-slot-assignednodes |
41 | | Vector<JS::Handle<DOM::Node>> HTMLSlotElement::assigned_nodes(AssignedNodesOptions options) const |
42 | 0 | { |
43 | | // 1. If options["flatten"] is false, then return this's assigned nodes. |
44 | 0 | if (!options.flatten) { |
45 | 0 | Vector<JS::Handle<DOM::Node>> assigned_nodes; |
46 | 0 | assigned_nodes.ensure_capacity(assigned_nodes_internal().size()); |
47 | |
|
48 | 0 | for (auto const& node : assigned_nodes_internal()) { |
49 | 0 | node.visit([&](auto const& node) { |
50 | 0 | assigned_nodes.unchecked_append(*node); |
51 | 0 | }); Unexecuted instantiation: HTMLSlotElement.cpp:auto Web::HTML::HTMLSlotElement::assigned_nodes(Web::HTML::AssignedNodesOptions) const::$_0::operator()<JS::NonnullGCPtr<Web::DOM::Element> >(JS::NonnullGCPtr<Web::DOM::Element> const&) const Unexecuted instantiation: HTMLSlotElement.cpp:auto Web::HTML::HTMLSlotElement::assigned_nodes(Web::HTML::AssignedNodesOptions) const::$_0::operator()<JS::NonnullGCPtr<Web::DOM::Text> >(JS::NonnullGCPtr<Web::DOM::Text> const&) const |
52 | 0 | } |
53 | |
|
54 | 0 | return assigned_nodes; |
55 | 0 | } |
56 | | |
57 | | // FIXME: 2. Return the result of finding flattened slottables with this. |
58 | 0 | return {}; |
59 | 0 | } |
60 | | |
61 | | // https://html.spec.whatwg.org/multipage/scripting.html#dom-slot-assignedelements |
62 | | Vector<JS::Handle<DOM::Element>> HTMLSlotElement::assigned_elements(AssignedNodesOptions options) const |
63 | 0 | { |
64 | | // 1. If options["flatten"] is false, then return this's assigned nodes, filtered to contain only Element nodes. |
65 | 0 | if (!options.flatten) { |
66 | 0 | Vector<JS::Handle<DOM::Element>> assigned_nodes; |
67 | |
|
68 | 0 | for (auto const& node : assigned_nodes_internal()) { |
69 | 0 | if (auto const* element = node.get_pointer<JS::NonnullGCPtr<DOM::Element>>()) |
70 | 0 | assigned_nodes.append(*element); |
71 | 0 | } |
72 | |
|
73 | 0 | return assigned_nodes; |
74 | 0 | } |
75 | | |
76 | | // FIXME: 2. Return the result of finding flattened slottables with this, filtered to contain only Element nodes. |
77 | 0 | return {}; |
78 | 0 | } |
79 | | |
80 | | // https://html.spec.whatwg.org/multipage/scripting.html#dom-slot-assign |
81 | | void HTMLSlotElement::assign(Vector<SlottableHandle> nodes) |
82 | 0 | { |
83 | | // 1. For each node of this's manually assigned nodes, set node's manual slot assignment to null. |
84 | 0 | for (auto& node : m_manually_assigned_nodes) { |
85 | 0 | node.visit([&](auto& node) { |
86 | 0 | node->set_manual_slot_assignment(nullptr); |
87 | 0 | }); Unexecuted instantiation: HTMLSlotElement.cpp:auto Web::HTML::HTMLSlotElement::assign(AK::Vector<AK::Variant<JS::Handle<Web::DOM::Element>, JS::Handle<Web::DOM::Text> >, 0ul>)::$_0::operator()<JS::NonnullGCPtr<Web::DOM::Element> >(JS::NonnullGCPtr<Web::DOM::Element>&) const Unexecuted instantiation: HTMLSlotElement.cpp:auto Web::HTML::HTMLSlotElement::assign(AK::Vector<AK::Variant<JS::Handle<Web::DOM::Element>, JS::Handle<Web::DOM::Text> >, 0ul>)::$_0::operator()<JS::NonnullGCPtr<Web::DOM::Text> >(JS::NonnullGCPtr<Web::DOM::Text>&) const |
88 | 0 | } |
89 | | |
90 | | // 2. Let nodesSet be a new ordered set. |
91 | 0 | Vector<DOM::Slottable> nodes_set; |
92 | | |
93 | | // 3. For each node of nodes: |
94 | 0 | for (auto& node_handle : nodes) { |
95 | 0 | auto& node = node_handle.visit([](auto& node) -> DOM::SlottableMixin& { return *node; });Unexecuted instantiation: HTMLSlotElement.cpp:Web::DOM::SlottableMixin& Web::HTML::HTMLSlotElement::assign(AK::Vector<AK::Variant<JS::Handle<Web::DOM::Element>, JS::Handle<Web::DOM::Text> >, 0ul>)::$_1::operator()<JS::Handle<Web::DOM::Element> >(JS::Handle<Web::DOM::Element>&) const Unexecuted instantiation: HTMLSlotElement.cpp:Web::DOM::SlottableMixin& Web::HTML::HTMLSlotElement::assign(AK::Vector<AK::Variant<JS::Handle<Web::DOM::Element>, JS::Handle<Web::DOM::Text> >, 0ul>)::$_1::operator()<JS::Handle<Web::DOM::Text> >(JS::Handle<Web::DOM::Text>&) const |
96 | 0 | auto slottable = node_handle.visit([](auto& node) { return node->as_slottable(); });Unexecuted instantiation: HTMLSlotElement.cpp:auto Web::HTML::HTMLSlotElement::assign(AK::Vector<AK::Variant<JS::Handle<Web::DOM::Element>, JS::Handle<Web::DOM::Text> >, 0ul>)::$_2::operator()<JS::Handle<Web::DOM::Element> >(JS::Handle<Web::DOM::Element>&) const Unexecuted instantiation: HTMLSlotElement.cpp:auto Web::HTML::HTMLSlotElement::assign(AK::Vector<AK::Variant<JS::Handle<Web::DOM::Element>, JS::Handle<Web::DOM::Text> >, 0ul>)::$_2::operator()<JS::Handle<Web::DOM::Text> >(JS::Handle<Web::DOM::Text>&) const |
97 | | |
98 | | // 1. If node's manual slot assignment refers to a slot, then remove node from that slot's manually assigned nodes. |
99 | 0 | if (node.manual_slot_assignment() != nullptr) { |
100 | 0 | m_manually_assigned_nodes.remove_all_matching([&](auto const& manually_assigned_node) { |
101 | 0 | return slottable == manually_assigned_node; |
102 | 0 | }); |
103 | 0 | } |
104 | | |
105 | | // 2. Set node's manual slot assignment to this. |
106 | 0 | node.set_manual_slot_assignment(this); |
107 | | |
108 | | // 3. Append node to nodesSet. |
109 | 0 | nodes_set.append(slottable); |
110 | 0 | } |
111 | | |
112 | | // 4. Set this's manually assigned nodes to nodesSet. |
113 | 0 | m_manually_assigned_nodes = move(nodes_set); |
114 | | |
115 | | // 5. Run assign slottables for a tree for this's root. |
116 | 0 | assign_slottables_for_a_tree(root()); |
117 | 0 | } |
118 | | |
119 | | // https://dom.spec.whatwg.org/#ref-for-concept-element-attributes-change-ext |
120 | | void HTMLSlotElement::attribute_change_steps(FlyString const& local_name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_) |
121 | 0 | { |
122 | 0 | Base::attribute_change_steps(local_name, old_value, value, namespace_); |
123 | | |
124 | | // 1. If element is a slot, localName is name, and namespace is null, then: |
125 | 0 | if (local_name == AttributeNames::name && !namespace_.has_value()) { |
126 | | // 1. If value is oldValue, then return. |
127 | 0 | if (value == old_value) |
128 | 0 | return; |
129 | | |
130 | | // 2. If value is null and oldValue is the empty string, then return. |
131 | 0 | if (!value.has_value() && old_value == String {}) |
132 | 0 | return; |
133 | | |
134 | | // 3. If value is the empty string and oldValue is null, then return. |
135 | 0 | if (value == String {} && !old_value.has_value()) |
136 | 0 | return; |
137 | | |
138 | | // 4. If value is null or the empty string, then set element’s name to the empty string. |
139 | 0 | if (!value.has_value()) |
140 | 0 | set_slot_name({}); |
141 | | // 5. Otherwise, set element’s name to value. |
142 | 0 | else |
143 | 0 | set_slot_name(*value); |
144 | | |
145 | | // 6. Run assign slottables for a tree with element’s root. |
146 | 0 | DOM::assign_slottables_for_a_tree(root()); |
147 | 0 | } |
148 | 0 | } |
149 | | |
150 | | } |