diff --git a/Meta/gn/secondary/Userland/Libraries/LibWeb/HTML/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibWeb/HTML/BUILD.gn index 4ac1270c7ab..b8d0f7c28a3 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibWeb/HTML/BUILD.gn +++ b/Meta/gn/secondary/Userland/Libraries/LibWeb/HTML/BUILD.gn @@ -100,6 +100,7 @@ source_set("HTML") { "HTMLOptGroupElement.cpp", "HTMLOptionElement.cpp", "HTMLOptionsCollection.cpp", + "HTMLOrSVGElement.cpp", "HTMLOutputElement.cpp", "HTMLParagraphElement.cpp", "HTMLParamElement.cpp", diff --git a/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni b/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni index f624914d688..d0045eab078 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni +++ b/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni @@ -187,6 +187,7 @@ standard_idl_files = [ "//Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.idl", "//Userland/Libraries/LibWeb/HTML/HTMLOptionElement.idl", "//Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.idl", + "//Userland/Libraries/LibWeb/HTML/HTMLOrSVGElement.idl", "//Userland/Libraries/LibWeb/HTML/HTMLOutputElement.idl", "//Userland/Libraries/LibWeb/HTML/HTMLParagraphElement.idl", "//Userland/Libraries/LibWeb/HTML/HTMLParamElement.idl", diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 50cea491f96..b8e9bdcc044 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -369,6 +369,7 @@ set(SOURCES HTML/HTMLOptGroupElement.cpp HTML/HTMLOptionElement.cpp HTML/HTMLOptionsCollection.cpp + HTML/HTMLOrSVGElement.cpp HTML/HTMLOutputElement.cpp HTML/HTMLParagraphElement.cpp HTML/HTMLParamElement.cpp diff --git a/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp index f42a308a12d..791c1cf5889 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp @@ -66,18 +66,11 @@ void HTMLElement::initialize(JS::Realm& realm) void HTMLElement::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); - visitor.visit(m_dataset); + HTMLOrSVGElement::visit_edges(visitor); visitor.visit(m_labels); visitor.visit(m_attached_internals); } -JS::NonnullGCPtr HTMLElement::dataset() -{ - if (!m_dataset) - m_dataset = DOMStringMap::create(*this); - return *m_dataset; -} - // https://html.spec.whatwg.org/multipage/dom.html#dom-dir StringView HTMLElement::dir() const { @@ -591,28 +584,6 @@ void HTMLElement::attribute_changed(FlyString const& name, Optional cons #undef __ENUMERATE } -// https://html.spec.whatwg.org/multipage/interaction.html#dom-focus -void HTMLElement::focus() -{ - // 1. If the element is marked as locked for focus, then return. - if (m_locked_for_focus) - return; - - // 2. Mark the element as locked for focus. - m_locked_for_focus = true; - - // 3. Run the focusing steps for the element. - run_focusing_steps(this); - - // FIXME: 4. If the value of the preventScroll dictionary member of options is false, - // then scroll the element into view with scroll behavior "auto", - // block flow direction position set to an implementation-defined value, - // and inline base direction position set to an implementation-defined value. - - // 5. Unmark the element as locked for focus. - m_locked_for_focus = false; -} - // https://html.spec.whatwg.org/multipage/webappapis.html#fire-a-synthetic-pointer-event bool HTMLElement::fire_a_synthetic_pointer_event(FlyString const& type, DOM::Element& target, bool not_trusted) { @@ -685,15 +656,6 @@ void HTMLElement::click() m_click_in_progress = false; } -// https://html.spec.whatwg.org/multipage/interaction.html#dom-blur -void HTMLElement::blur() -{ - // The blur() method, when invoked, should run the unfocusing steps for the element on which the method was called. - run_unfocusing_steps(this); - - // User agents may selectively or uniformly ignore calls to this method for usability reasons. -} - Optional HTMLElement::default_role() const { // https://www.w3.org/TR/html-aria/#el-address diff --git a/Userland/Libraries/LibWeb/HTML/HTMLElement.h b/Userland/Libraries/LibWeb/HTML/HTMLElement.h index bf21a04565a..ccb22ffe064 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLElement.h @@ -9,6 +9,7 @@ #include #include #include +#include #include namespace Web::HTML { @@ -21,7 +22,8 @@ namespace Web::HTML { class HTMLElement : public DOM::Element - , public HTML::GlobalEventHandlers { + , public HTML::GlobalEventHandlers + , public HTML::HTMLOrSVGElement { WEB_PLATFORM_OBJECT(HTMLElement, DOM::Element); JS_DECLARE_ALLOCATOR(HTMLElement); @@ -53,14 +55,8 @@ public: bool cannot_navigate() const; - [[nodiscard]] JS::NonnullGCPtr dataset(); - - void focus(); - void click(); - void blur(); - [[nodiscard]] String access_key_label() const; bool fire_a_synthetic_pointer_event(FlyString const& type, DOM::Element& target, bool not_trusted); @@ -100,8 +96,6 @@ private: [[nodiscard]] String get_the_text_steps(); void append_rendered_text_fragment(StringView input); - JS::GCPtr m_dataset; - JS::GCPtr m_labels; // https://html.spec.whatwg.org/multipage/custom-elements.html#attached-internals @@ -114,9 +108,6 @@ private: }; ContentEditableState m_content_editable_state { ContentEditableState::Inherit }; - // https://html.spec.whatwg.org/multipage/interaction.html#locked-for-focus - bool m_locked_for_focus { false }; - // https://html.spec.whatwg.org/multipage/interaction.html#click-in-progress-flag bool m_click_in_progress { false }; }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLElement.idl b/Userland/Libraries/LibWeb/HTML/HTMLElement.idl index ea85f44ee09..d3805b9d52b 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLElement.idl +++ b/Userland/Libraries/LibWeb/HTML/HTMLElement.idl @@ -1,6 +1,7 @@ #import #import #import +#import #import #import @@ -59,16 +60,4 @@ interface mixin ElementContentEditable { [FIXME, CEReactions] attribute DOMString inputMode; }; -// https://html.spec.whatwg.org/#htmlorsvgelement -interface mixin HTMLOrSVGElement { - [SameObject] readonly attribute DOMStringMap dataset; - [FIXME] attribute DOMString nonce; // intentionally no [CEReactions] - - [CEReactions, Reflect] attribute boolean autofocus; - [CEReactions] attribute long tabIndex; - // FIXME: Support the optional FocusOptions parameter. - undefined focus(); - undefined blur(); -}; - HTMLElement includes ElementCSSInlineStyle; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOrSVGElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLOrSVGElement.cpp new file mode 100644 index 00000000000..0072ce790c3 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/HTMLOrSVGElement.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2024, Jelle Raaijmakers + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +namespace Web::HTML { + +// https://html.spec.whatwg.org/multipage/dom.html#dom-dataset-dev +template +JS::NonnullGCPtr HTMLOrSVGElement::dataset() +{ + if (!m_dataset) + m_dataset = DOMStringMap::create(*static_cast(this)); + return *m_dataset; +} + +// https://html.spec.whatwg.org/multipage/interaction.html#dom-focus +template +void HTMLOrSVGElement::focus() +{ + // FIXME: below are the focus(options) steps, also implement focus() + + // 1. If the element is marked as locked for focus, then return. + if (m_locked_for_focus) + return; + + // 2. Mark the element as locked for focus. + m_locked_for_focus = true; + + // 3. Run the focusing steps for the element. + run_focusing_steps(static_cast(this)); + + // FIXME: 4. If the value of the preventScroll dictionary member of options is false, + // then scroll the element into view with scroll behavior "auto", + // block flow direction position set to an implementation-defined value, + // and inline base direction position set to an implementation-defined value. + + // 5. Unmark the element as locked for focus. + m_locked_for_focus = false; +} + +// https://html.spec.whatwg.org/multipage/interaction.html#dom-blur +template +void HTMLOrSVGElement::blur() +{ + // The blur() method, when invoked, should run the unfocusing steps for the element on which the method was called. + run_unfocusing_steps(static_cast(this)); + + // User agents may selectively or uniformly ignore calls to this method for usability reasons. +} + +template +void HTMLOrSVGElement::visit_edges(JS::Cell::Visitor& visitor) +{ + visitor.visit(m_dataset); +} + +template class HTMLOrSVGElement; +template class HTMLOrSVGElement; +template class HTMLOrSVGElement; + +} diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOrSVGElement.h b/Userland/Libraries/LibWeb/HTML/HTMLOrSVGElement.h new file mode 100644 index 00000000000..9080ac78433 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/HTMLOrSVGElement.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024, Jelle Raaijmakers + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Web::HTML { + +template +class HTMLOrSVGElement { +public: + [[nodiscard]] JS::NonnullGCPtr dataset(); + + void focus(); + void blur(); + +protected: + void visit_edges(JS::Cell::Visitor&); + + // https://html.spec.whatwg.org/multipage/dom.html#dom-dataset-dev + JS::GCPtr m_dataset; + + // https://html.spec.whatwg.org/multipage/interaction.html#locked-for-focus + bool m_locked_for_focus { false }; +}; + +} diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOrSVGElement.idl b/Userland/Libraries/LibWeb/HTML/HTMLOrSVGElement.idl new file mode 100644 index 00000000000..ed719ceef04 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/HTMLOrSVGElement.idl @@ -0,0 +1,11 @@ +// https://html.spec.whatwg.org/#htmlorsvgelement +interface mixin HTMLOrSVGElement { + [SameObject] readonly attribute DOMStringMap dataset; + [FIXME] attribute DOMString nonce; // intentionally no [CEReactions] + + [CEReactions, Reflect] attribute boolean autofocus; + [CEReactions] attribute long tabIndex; + // FIXME: Support the optional FocusOptions parameter. + undefined focus(); + undefined blur(); +}; diff --git a/Userland/Libraries/LibWeb/MathML/MathMLElement.cpp b/Userland/Libraries/LibWeb/MathML/MathMLElement.cpp index 39b0b3eac5b..400c805d011 100644 --- a/Userland/Libraries/LibWeb/MathML/MathMLElement.cpp +++ b/Userland/Libraries/LibWeb/MathML/MathMLElement.cpp @@ -26,13 +26,6 @@ void MathMLElement::initialize(JS::Realm& realm) WEB_SET_PROTOTYPE_FOR_INTERFACE(MathMLElement); } -JS::NonnullGCPtr MathMLElement::dataset() -{ - if (!m_dataset) - m_dataset = HTML::DOMStringMap::create(*this); - return *m_dataset; -} - Optional MathMLElement::default_role() const { // https://www.w3.org/TR/html-aria/#el-math @@ -41,20 +34,10 @@ Optional MathMLElement::default_role() const return {}; } -void MathMLElement::focus() -{ - dbgln("(STUBBED) MathMLElement::focus()"); -} - -void MathMLElement::blur() -{ - dbgln("(STUBBED) MathMLElement::blur()"); -} - void MathMLElement::visit_edges(JS::Cell::Visitor& visitor) { Base::visit_edges(visitor); - visitor.visit(m_dataset); + HTMLOrSVGElement::visit_edges(visitor); } } diff --git a/Userland/Libraries/LibWeb/MathML/MathMLElement.h b/Userland/Libraries/LibWeb/MathML/MathMLElement.h index 9e2fda8e52e..d1bdfcdc99e 100644 --- a/Userland/Libraries/LibWeb/MathML/MathMLElement.h +++ b/Userland/Libraries/LibWeb/MathML/MathMLElement.h @@ -7,26 +7,22 @@ #pragma once #include -#include #include +#include namespace Web::MathML { class MathMLElement : public DOM::Element - , public HTML::GlobalEventHandlers { + , public HTML::GlobalEventHandlers + , public HTML::HTMLOrSVGElement { WEB_PLATFORM_OBJECT(MathMLElement, DOM::Element); JS_DECLARE_ALLOCATOR(MathMLElement); public: virtual ~MathMLElement() override; - [[nodiscard]] JS::NonnullGCPtr dataset(); - virtual Optional default_role() const override; - void focus(); - void blur(); - protected: virtual JS::GCPtr global_event_handlers_to_event_target(FlyString const&) override { return *this; } @@ -36,8 +32,6 @@ private: virtual void visit_edges(Visitor&) override; virtual void initialize(JS::Realm&) override; - - JS::GCPtr m_dataset; }; } diff --git a/Userland/Libraries/LibWeb/MathML/MathMLElement.idl b/Userland/Libraries/LibWeb/MathML/MathMLElement.idl index d279678796d..087b989d6dc 100644 --- a/Userland/Libraries/LibWeb/MathML/MathMLElement.idl +++ b/Userland/Libraries/LibWeb/MathML/MathMLElement.idl @@ -7,7 +7,7 @@ [Exposed=Window] interface MathMLElement : Element { }; MathMLElement includes GlobalEventHandlers; -MathMLElement includes HTMLOrSVGElement; // FIXME: We technically use HTMLOrForeignElement which is a rename of HTMLOrSVGElement, when that change is upstreamed we should update here +MathMLElement includes HTMLOrSVGElement; // FIXME: The spec calls for HTMLOrForeignElement which is a rename of HTMLOrSVGElement, when that change is upstreamed we should update here // https://drafts.csswg.org/cssom/#dom-elementcssinlinestyle-style MathMLElement includes ElementCSSInlineStyle; diff --git a/Userland/Libraries/LibWeb/SVG/SVGElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGElement.cpp index 4b66d7eb010..134d577b44b 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGElement.cpp @@ -32,17 +32,10 @@ void SVGElement::initialize(JS::Realm& realm) void SVGElement::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); - visitor.visit(m_dataset); + HTMLOrSVGElement::visit_edges(visitor); visitor.visit(m_class_name_animated_string); } -JS::NonnullGCPtr SVGElement::dataset() -{ - if (!m_dataset) - m_dataset = HTML::DOMStringMap::create(*this); - return *m_dataset; -} - void SVGElement::attribute_changed(FlyString const& name, Optional const& old_value, Optional const& value) { Base::attribute_changed(name, old_value, value); @@ -106,16 +99,6 @@ void SVGElement::remove_from_use_element_that_reference_this() }); } -void SVGElement::focus() -{ - dbgln("(STUBBED) SVGElement::focus()"); -} - -void SVGElement::blur() -{ - dbgln("(STUBBED) SVGElement::blur()"); -} - // https://svgwg.org/svg2-draft/types.html#__svg__SVGElement__classNames JS::NonnullGCPtr SVGElement::class_name() { diff --git a/Userland/Libraries/LibWeb/SVG/SVGElement.h b/Userland/Libraries/LibWeb/SVG/SVGElement.h index 26b7177423d..d5c74050109 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGElement.h @@ -8,13 +8,15 @@ #include #include +#include #include namespace Web::SVG { class SVGElement : public DOM::Element - , public HTML::GlobalEventHandlers { + , public HTML::GlobalEventHandlers + , public HTML::HTMLOrSVGElement { WEB_PLATFORM_OBJECT(SVGElement, DOM::Element); public: @@ -26,11 +28,6 @@ public: virtual void inserted() override; virtual void removed_from(Node*) override; - [[nodiscard]] JS::NonnullGCPtr dataset(); - - void focus(); - void blur(); - JS::NonnullGCPtr class_name(); JS::GCPtr owner_svg_element(); @@ -43,8 +40,6 @@ protected: void update_use_elements_that_reference_this(); void remove_from_use_element_that_reference_this(); - JS::GCPtr m_dataset; - JS::NonnullGCPtr svg_animated_length_for_property(CSS::PropertyID) const; private: