diff --git a/Userland/Libraries/LibWeb/SVG/SVGTextPathElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGTextPathElement.cpp index 3686fb8eb5..3817044957 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGTextPathElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGTextPathElement.cpp @@ -33,6 +33,12 @@ void SVGTextPathElement::initialize(JS::Realm& realm) set_prototype(&Bindings::ensure_web_prototype(realm, "SVGTextPathElement"_fly_string)); } +void SVGTextPathElement::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + SVGURIReferenceMixin::visit_edges(visitor); +} + JS::GCPtr SVGTextPathElement::create_layout_node(NonnullRefPtr style) { return heap().allocate_without_realm(document(), *this, move(style)); diff --git a/Userland/Libraries/LibWeb/SVG/SVGTextPathElement.h b/Userland/Libraries/LibWeb/SVG/SVGTextPathElement.h index e635034f91..cd03760ff0 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGTextPathElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGTextPathElement.h @@ -8,11 +8,14 @@ #include #include +#include namespace Web::SVG { // https://svgwg.org/svg2-draft/text.html#TextPathElement -class SVGTextPathElement : public SVGTextContentElement { +class SVGTextPathElement + : public SVGTextContentElement + , public SVGURIReferenceMixin { WEB_PLATFORM_OBJECT(SVGTextPathElement, SVGTextContentElement); JS_DECLARE_ALLOCATOR(SVGTextPathElement); @@ -25,6 +28,7 @@ protected: SVGTextPathElement(DOM::Document&, DOM::QualifiedName); virtual void initialize(JS::Realm&) override; + virtual void visit_edges(Cell::Visitor&) override; }; } diff --git a/Userland/Libraries/LibWeb/SVG/SVGURIReference.h b/Userland/Libraries/LibWeb/SVG/SVGURIReference.h new file mode 100644 index 0000000000..46658367d8 --- /dev/null +++ b/Userland/Libraries/LibWeb/SVG/SVGURIReference.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023, Luke Wilde + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Web::SVG { + +enum class SupportsXLinkHref { + No, + Yes, +}; + +// https://svgwg.org/svg2-draft/types.html#InterfaceSVGURIReference +template +class SVGURIReferenceMixin { +public: + virtual ~SVGURIReferenceMixin() = default; + + JS::NonnullGCPtr href() + { + // The href IDL attribute represents the value of the ‘href’ attribute, and, on elements that are defined to support + // it, the deprecated ‘xlink:href’ attribute. On getting href, an SVGAnimatedString object is returned that: + // - reflects the ‘href’ attribute, and + // - if the element is defined to support the deprecated ‘xlink:href’ attribute, additionally reflects that + // deprecated attribute. + if (!m_href_animated_string) { + auto* this_svg_element = dynamic_cast(this); + VERIFY(this_svg_element); + m_href_animated_string = SVGAnimatedString::create(this_svg_element->realm(), *this_svg_element, AttributeNames::href, supports_xlink_href == SupportsXLinkHref::Yes ? Optional { AttributeNames::xlink_href } : OptionalNone {}); + } + return *m_href_animated_string; + } + +protected: + void visit_edges(JS::Cell::Visitor& visitor) + { + visitor.visit(m_href_animated_string); + } + +private: + JS::GCPtr m_href_animated_string; +}; + +} diff --git a/Userland/Libraries/LibWeb/SVG/SVGURIReference.idl b/Userland/Libraries/LibWeb/SVG/SVGURIReference.idl index 8046b91382..5365d6fcd4 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGURIReference.idl +++ b/Userland/Libraries/LibWeb/SVG/SVGURIReference.idl @@ -1,3 +1,6 @@ +#import + +// https://svgwg.org/svg2-draft/types.html#InterfaceSVGURIReference interface mixin SVGURIReference { - // FIXME: [SameObject] readonly attribute SVGAnimatedString href; + [SameObject] readonly attribute SVGAnimatedString href; };