diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index f8fafab1fc..e4356918ab 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -175,6 +175,7 @@ set(SOURCES DOM/RadioNodeList.cpp DOM/Range.cpp DOM/ShadowRoot.cpp + DOM/Slottable.cpp DOM/StaticNodeList.cpp DOM/StaticRange.cpp DOM/StyleElementUtils.cpp diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp index d24d2ea932..5334e4afaa 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.cpp +++ b/Userland/Libraries/LibWeb/DOM/Element.cpp @@ -86,6 +86,8 @@ void Element::initialize(JS::Realm& realm) void Element::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); + SlottableMixin::visit_edges(visitor); + visitor.visit(m_attributes.ptr()); visitor.visit(m_inline_style.ptr()); visitor.visit(m_class_list.ptr()); diff --git a/Userland/Libraries/LibWeb/DOM/Element.h b/Userland/Libraries/LibWeb/DOM/Element.h index 385ed16472..fabd955248 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.h +++ b/Userland/Libraries/LibWeb/DOM/Element.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -66,6 +67,7 @@ class Element : public ParentNode , public ChildNode , public NonDocumentTypeChildNode + , public SlottableMixin , public ARIA::ARIAMixin { WEB_PLATFORM_OBJECT(Element, ParentNode); diff --git a/Userland/Libraries/LibWeb/DOM/Element.idl b/Userland/Libraries/LibWeb/DOM/Element.idl index 827c9e0f68..37fee09368 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.idl +++ b/Userland/Libraries/LibWeb/DOM/Element.idl @@ -8,8 +8,10 @@ #import #import #import +#import #import #import +#import #import enum ScrollLogicalPosition { "start", "center", "end", "nearest" }; @@ -99,3 +101,4 @@ Element includes ChildNode; Element includes InnerHTML; // https://www.w3.org/TR/wai-aria-1.2/#idl_element Element includes ARIAMixin; +Element includes Slottable; diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp index a63c41db8f..9656e0249e 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.cpp +++ b/Userland/Libraries/LibWeb/DOM/Node.cpp @@ -930,6 +930,15 @@ Element* Node::parent_or_shadow_host_element() return nullptr; } +Slottable Node::as_slottable() +{ + VERIFY(is_slottable()); + + if (is_element()) + return JS::NonnullGCPtr { static_cast(*this) }; + return JS::NonnullGCPtr { static_cast(*this) }; +} + JS::NonnullGCPtr Node::child_nodes() { if (!m_child_nodes) { diff --git a/Userland/Libraries/LibWeb/DOM/Node.h b/Userland/Libraries/LibWeb/DOM/Node.h index f5103f2afc..45499ca9b2 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.h +++ b/Userland/Libraries/LibWeb/DOM/Node.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -266,6 +267,8 @@ public: template IterationDecision for_each_shadow_including_descendant(Callback); + Slottable as_slottable(); + Node* parent() { return m_parent.ptr(); } Node const* parent() const { return m_parent.ptr(); } diff --git a/Userland/Libraries/LibWeb/DOM/Slottable.cpp b/Userland/Libraries/LibWeb/DOM/Slottable.cpp new file mode 100644 index 0000000000..50a97dd6f9 --- /dev/null +++ b/Userland/Libraries/LibWeb/DOM/Slottable.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace Web::DOM { + +SlottableMixin::~SlottableMixin() = default; + +void SlottableMixin::visit_edges(JS::Cell::Visitor& visitor) +{ + visitor.visit(m_assigned_slot); + visitor.visit(m_manual_slot_assignment); +} + +// https://dom.spec.whatwg.org/#dom-slotable-assignedslot +JS::GCPtr SlottableMixin::assigned_slot() +{ + // FIXME: The assignedSlot getter steps are to return the result of find a slot given this and with the open flag set. + return nullptr; +} + +} diff --git a/Userland/Libraries/LibWeb/DOM/Slottable.h b/Userland/Libraries/LibWeb/DOM/Slottable.h new file mode 100644 index 0000000000..f9a877b4f7 --- /dev/null +++ b/Userland/Libraries/LibWeb/DOM/Slottable.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace Web::DOM { + +// https://dom.spec.whatwg.org/#concept-slotable +using Slottable = Variant, JS::NonnullGCPtr>; + +// https://dom.spec.whatwg.org/#mixin-slotable +class SlottableMixin { +public: + virtual ~SlottableMixin(); + + String const& slottable_name() const { return m_name; } // Not called `name` to distinguish from `Element::name`. + void set_slottable_name(String name) { m_name = move(name); } + + JS::GCPtr assigned_slot(); + + JS::GCPtr assigned_slot_internal() const { return m_assigned_slot; } + void set_assigned_slot(JS::GCPtr assigned_slot) { m_assigned_slot = assigned_slot; } + + JS::GCPtr manual_slot_assignment() { return m_manual_slot_assignment; } + void set_manual_slot_assignment(JS::GCPtr manual_slot_assignment) { m_manual_slot_assignment = manual_slot_assignment; } + +protected: + void visit_edges(JS::Cell::Visitor&); + +private: + // https://dom.spec.whatwg.org/#slotable-name + String m_name; + + // https://dom.spec.whatwg.org/#slotable-assigned-slot + JS::GCPtr m_assigned_slot; + + // https://dom.spec.whatwg.org/#slottable-manual-slot-assignment + JS::GCPtr m_manual_slot_assignment; +}; + +} diff --git a/Userland/Libraries/LibWeb/DOM/Slottable.idl b/Userland/Libraries/LibWeb/DOM/Slottable.idl new file mode 100644 index 0000000000..6793e6bbc4 --- /dev/null +++ b/Userland/Libraries/LibWeb/DOM/Slottable.idl @@ -0,0 +1,4 @@ +// https://dom.spec.whatwg.org/#mixin-slotable +interface mixin Slottable { + readonly attribute HTMLSlotElement? assignedSlot; +}; diff --git a/Userland/Libraries/LibWeb/DOM/Text.cpp b/Userland/Libraries/LibWeb/DOM/Text.cpp index c5a53367c4..58440dee59 100644 --- a/Userland/Libraries/LibWeb/DOM/Text.cpp +++ b/Userland/Libraries/LibWeb/DOM/Text.cpp @@ -32,6 +32,8 @@ void Text::initialize(JS::Realm& realm) void Text::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); + SlottableMixin::visit_edges(visitor); + visitor.visit(dynamic_cast(m_owner.ptr())); } diff --git a/Userland/Libraries/LibWeb/DOM/Text.h b/Userland/Libraries/LibWeb/DOM/Text.h index c803c5fc1c..6e401ff065 100644 --- a/Userland/Libraries/LibWeb/DOM/Text.h +++ b/Userland/Libraries/LibWeb/DOM/Text.h @@ -10,6 +10,7 @@ #include #include #include +#include namespace Web::DOM { @@ -19,7 +20,9 @@ public: virtual void did_edit_text_node(Badge) = 0; }; -class Text : public CharacterData { +class Text + : public CharacterData + , public SlottableMixin { WEB_PLATFORM_OBJECT(Text, CharacterData); public: diff --git a/Userland/Libraries/LibWeb/DOM/Text.idl b/Userland/Libraries/LibWeb/DOM/Text.idl index 4093e6fdac..6a2df9579b 100644 --- a/Userland/Libraries/LibWeb/DOM/Text.idl +++ b/Userland/Libraries/LibWeb/DOM/Text.idl @@ -1,4 +1,6 @@ #import +#import +#import // https://dom.spec.whatwg.org/#text [Exposed=Window] @@ -8,3 +10,5 @@ interface Text : CharacterData { [NewObject] Text splitText(unsigned long offset); }; + +Text includes Slottable;