LibWeb/DOM: Implement 'find flattened slottables'

Returning a Vector of Slottable is not very nice here, but this
matches find_slottable (which this calls), and as far as I can
tell this is technically 'safe' at the moment in the way in
which it is / will be called.

It's also not great that like find_slottable it takes a non-const
ref, but changing that causes a bunch of other fallout.
This commit is contained in:
Shannon Booth 2025-05-03 16:34:50 +12:00 committed by Shannon Booth
commit 2d6b11c8cb
Notes: github-actions[bot] 2025-05-19 11:27:20 +00:00
2 changed files with 50 additions and 0 deletions

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
* Copyright (c) 2025, Shannon Booth <shannon@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -154,6 +155,54 @@ Vector<Slottable> find_slottables(GC::Ref<HTML::HTMLSlotElement> slot)
return result;
}
// https://dom.spec.whatwg.org/#find-flattened-slotables
Vector<Slottable> find_flattened_slottables(GC::Ref<HTML::HTMLSlotElement> slot)
{
// 1. Let result be « ».
Vector<Slottable> result;
// 2. If slots root is not a shadow root, then return result.
if (!slot->root().is_shadow_root())
return result;
// 3. Let slottables be the result of finding slottables given slot.
auto slottables = find_slottables(slot);
// 4. If slottables is the empty list, then append each slottable child of slot, in tree order, to slottables.
if (slottables.is_empty()) {
slot->for_each_child([&](auto& node) {
if (!node.is_slottable())
return IterationDecision::Continue;
slottables.append(node.as_slottable());
return IterationDecision::Continue;
});
}
// 5. For each node of slottables:
for (auto& node : slottables) {
// 1. If node is a slot whose root is a shadow root:
// 1. Let temporaryResult be the result of finding flattened slottables given node.
// 2. Append each slottable in temporaryResult, in order, to result.
// 2. Otherwise, append node to result.
auto* maybe_slot = node.get_pointer<GC::Ref<DOM::Element>>();
if (!maybe_slot) {
result.append(node);
continue;
}
if (auto* slot = as_if<HTML::HTMLSlotElement>(maybe_slot->ptr()); slot && slot->root().is_shadow_root()) {
auto temporary_result = find_flattened_slottables(*slot);
result.extend(temporary_result);
} else {
result.append(node);
}
}
// 6. Return result.
return result;
}
// https://dom.spec.whatwg.org/#assign-slotables
void assign_slottables(GC::Ref<HTML::HTMLSlotElement> slot)
{

View file

@ -57,6 +57,7 @@ bool is_an_assigned_slottable(GC::Ref<Node>);
GC::Ptr<HTML::HTMLSlotElement> find_a_slot(Slottable const&, OpenFlag = OpenFlag::Unset);
Vector<Slottable> find_slottables(GC::Ref<HTML::HTMLSlotElement>);
Vector<Slottable> find_flattened_slottables(GC::Ref<HTML::HTMLSlotElement>);
void assign_slottables(GC::Ref<HTML::HTMLSlotElement>);
void assign_slottables_for_a_tree(GC::Ref<Node>);
void assign_a_slot(Slottable const&);