Procházet zdrojové kódy

LibWeb: Implement SVGUseElement#href

Required by Ruffle.
https://github.com/ruffle-rs/ruffle/blob/b196c8d1bcc2d691c61d8d78b17b5fd60e0234b8/web/packages/core/src/shadow-template.ts#L601-L602
Luke Wilde před 1 rokem
rodič
revize
54972e3ceb

+ 114 - 0
Tests/LibWeb/Text/expected/SVG/svg-href.txt

@@ -0,0 +1,114 @@
+           ---------------
+use - no-xlink-href
+---------------
+element.href instanceof SVGAnimatedString -> true
+element.href === element.href -> true
+element.href.baseVal -> 
+element.href.animVal -> 
+element.href.baseVal === element.href.animVal -> true
+element.getAttribute("xlink:href") -> null
+element.getAttribute("href") -> null
+setting baseVal...
+done, new values:
+element.href.baseVal -> testSet
+element.href.animVal -> testSet
+element.href.baseVal === element.href.animVal -> true
+element.getAttribute("xlink:href") -> null
+element.getAttribute("href") -> testSet
+animVal should be readonly:
+TypeError: Cannot set property 'animVal' of [object SVGAnimatedString]
+---------------
+use - explicit-xlink-href
+---------------
+element.href instanceof SVGAnimatedString -> true
+element.href === element.href -> true
+element.href.baseVal -> test1
+element.href.animVal -> test1
+element.href.baseVal === element.href.animVal -> true
+element.getAttribute("xlink:href") -> test1
+element.getAttribute("href") -> null
+setting baseVal...
+done, new values:
+element.href.baseVal -> testSet
+element.href.animVal -> testSet
+element.href.baseVal === element.href.animVal -> true
+element.getAttribute("xlink:href") -> testSet
+element.getAttribute("href") -> null
+animVal should be readonly:
+TypeError: Cannot set property 'animVal' of [object SVGAnimatedString]
+---------------
+use - implicit-xlink-href
+---------------
+element.href instanceof SVGAnimatedString -> true
+element.href === element.href -> true
+element.href.baseVal -> test2
+element.href.animVal -> test2
+element.href.baseVal === element.href.animVal -> true
+element.getAttribute("xlink:href") -> null
+element.getAttribute("href") -> test2
+setting baseVal...
+done, new values:
+element.href.baseVal -> testSet
+element.href.animVal -> testSet
+element.href.baseVal === element.href.animVal -> true
+element.getAttribute("xlink:href") -> null
+element.getAttribute("href") -> testSet
+animVal should be readonly:
+TypeError: Cannot set property 'animVal' of [object SVGAnimatedString]
+---------------
+textPath - no-xlink-href
+---------------
+element.href instanceof SVGAnimatedString -> true
+element.href === element.href -> true
+element.href.baseVal -> 
+element.href.animVal -> 
+element.href.baseVal === element.href.animVal -> true
+element.getAttribute("xlink:href") -> null
+element.getAttribute("href") -> null
+setting baseVal...
+done, new values:
+element.href.baseVal -> testSet
+element.href.animVal -> testSet
+element.href.baseVal === element.href.animVal -> true
+element.getAttribute("xlink:href") -> null
+element.getAttribute("href") -> testSet
+animVal should be readonly:
+TypeError: Cannot set property 'animVal' of [object SVGAnimatedString]
+---------------
+textPath - explicit-xlink-href
+---------------
+element.href instanceof SVGAnimatedString -> true
+element.href === element.href -> true
+element.href.baseVal -> test1
+element.href.animVal -> test1
+element.href.baseVal === element.href.animVal -> true
+element.getAttribute("xlink:href") -> test1
+element.getAttribute("href") -> null
+setting baseVal...
+done, new values:
+element.href.baseVal -> testSet
+element.href.animVal -> testSet
+element.href.baseVal === element.href.animVal -> true
+element.getAttribute("xlink:href") -> testSet
+element.getAttribute("href") -> null
+animVal should be readonly:
+TypeError: Cannot set property 'animVal' of [object SVGAnimatedString]
+---------------
+textPath - implicit-xlink-href
+---------------
+element.href instanceof SVGAnimatedString -> true
+element.href === element.href -> true
+element.href.baseVal -> test2
+element.href.animVal -> test2
+element.href.baseVal === element.href.animVal -> true
+element.getAttribute("xlink:href") -> null
+element.getAttribute("href") -> test2
+setting baseVal...
+done, new values:
+element.href.baseVal -> testSet
+element.href.animVal -> testSet
+element.href.baseVal === element.href.animVal -> true
+element.getAttribute("xlink:href") -> null
+element.getAttribute("href") -> testSet
+animVal should be readonly:
+TypeError: Cannot set property 'animVal' of [object SVGAnimatedString]

+ 57 - 0
Tests/LibWeb/Text/input/SVG/svg-href.html

@@ -0,0 +1,57 @@
+<script src="../include.js"></script>
+<svg xmlns="http://www.w3.org/2000/svg" id="svg-element">
+    <use class="no-xlink-href"></use>
+    <use class="explicit-xlink-href" xlink:href="test1"></use>
+    <use class="implicit-xlink-href" href="test2"></use>
+    <text class="ignore">
+        <textPath class="no-xlink-href"></textPath>
+        <textPath class="explicit-xlink-href" xlink:href="test1"></textPath>
+        <textPath class="implicit-xlink-href" href="test2"></textPath>
+    </text>
+</svg>
+<script>
+    function dumpAttribute(element) {
+        "use strict";
+        println("---------------");
+        println(`${element.tagName} - ${element.getAttribute("class")}`);
+        println("---------------");
+        println(`element.href instanceof SVGAnimatedString -> ${element.href instanceof SVGAnimatedString}`);
+        println(`element.href === element.href -> ${element.href === element.href}`);
+        println(`element.href.baseVal -> ${element.href.baseVal}`);
+        println(`element.href.animVal -> ${element.href.animVal}`);
+        println(`element.href.baseVal === element.href.animVal -> ${element.href.baseVal === element.href.animVal}`);
+        println(`element.getAttribute("xlink:href") -> ${element.getAttribute("xlink:href")}`);
+        println(`element.getAttribute("href") -> ${element.getAttribute("href")}`);
+        println("setting baseVal...");
+        element.href.baseVal = "testSet";
+        println("done, new values:");
+        println(`element.href.baseVal -> ${element.href.baseVal}`);
+        println(`element.href.animVal -> ${element.href.animVal}`);
+        println(`element.href.baseVal === element.href.animVal -> ${element.href.baseVal === element.href.animVal}`);
+        println(`element.getAttribute("xlink:href") -> ${element.getAttribute("xlink:href")}`);
+        println(`element.getAttribute("href") -> ${element.getAttribute("href")}`);
+        println("animVal should be readonly:")
+        try {
+            element.href.animVal = "invalid";
+        } catch (e) {
+            println(`${e.name}: ${e.message}`);
+        }
+    }
+
+    function dumpTree(element) {
+        for (const child of Array.from(element.children))
+        {
+            if (child.getAttribute("class") !== "ignore")
+            {
+                dumpAttribute(child);
+            }
+
+            dumpTree(child);
+        }
+    }
+
+    test(() => {
+        const svgElement = document.getElementById("svg-element");
+        dumpTree(svgElement);
+    });
+</script>

+ 1 - 0
Userland/Libraries/LibWeb/SVG/SVGUseElement.cpp

@@ -44,6 +44,7 @@ void SVGUseElement::initialize(JS::Realm& realm)
 void SVGUseElement::visit_edges(Cell::Visitor& visitor)
 void SVGUseElement::visit_edges(Cell::Visitor& visitor)
 {
 {
     Base::visit_edges(visitor);
     Base::visit_edges(visitor);
+    SVGURIReferenceMixin::visit_edges(visitor);
     visitor.visit(m_document_observer);
     visitor.visit(m_document_observer);
 }
 }
 
 

+ 4 - 1
Userland/Libraries/LibWeb/SVG/SVGUseElement.h

@@ -11,10 +11,13 @@
 #include <LibWeb/DOM/DocumentObserver.h>
 #include <LibWeb/DOM/DocumentObserver.h>
 #include <LibWeb/SVG/SVGAnimatedLength.h>
 #include <LibWeb/SVG/SVGAnimatedLength.h>
 #include <LibWeb/SVG/SVGGraphicsElement.h>
 #include <LibWeb/SVG/SVGGraphicsElement.h>
+#include <LibWeb/SVG/SVGURIReference.h>
 
 
 namespace Web::SVG {
 namespace Web::SVG {
 
 
-class SVGUseElement final : public SVGGraphicsElement {
+class SVGUseElement final
+    : public SVGGraphicsElement
+    , public SVGURIReferenceMixin<SupportsXLinkHref::Yes> {
     WEB_PLATFORM_OBJECT(SVGUseElement, SVGGraphicsElement);
     WEB_PLATFORM_OBJECT(SVGUseElement, SVGGraphicsElement);
     JS_DECLARE_ALLOCATOR(SVGUseElement);
     JS_DECLARE_ALLOCATOR(SVGUseElement);
 
 

+ 2 - 1
Userland/Libraries/LibWeb/SVG/SVGUseElement.idl

@@ -1,6 +1,7 @@
 #import <SVG/SVGAnimatedLength.idl>
 #import <SVG/SVGAnimatedLength.idl>
 #import <SVG/SVGElement.idl>
 #import <SVG/SVGElement.idl>
 #import <SVG/SVGGraphicsElement.idl>
 #import <SVG/SVGGraphicsElement.idl>
+#import <SVG/SVGURIReference.idl>
 
 
 // https://svgwg.org/svg2-draft/struct.html#InterfaceSVGUseElement
 // https://svgwg.org/svg2-draft/struct.html#InterfaceSVGUseElement
 [Exposed=Window]
 [Exposed=Window]
@@ -13,4 +14,4 @@ interface SVGUseElement : SVGGraphicsElement {
   [SameObject] readonly attribute SVGElement? animatedInstanceRoot;
   [SameObject] readonly attribute SVGElement? animatedInstanceRoot;
 };
 };
 
 
-// FIXME: SVGUseElement includes SVGURIReference;
+SVGUseElement includes SVGURIReference;