Allow href attribute without xlink on SVG elements
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 8 Aug 2018 00:55:51 +0000 (00:55 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 8 Aug 2018 00:55:51 +0000 (00:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=153854

Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2018-08-07
Reviewed by Dean Jackson.

Source/WebCore:

SVG 2 has moved the href attribute from xlink namespace to svg namespace.
Instead of using xlink:href, svg:href should be used or simply use href
if the svg namespace is defined.

See https://www.w3.org/TR/SVG2/linking.html#XLinkRefAttrs.

For backward compatibility, xlink:href will be treated as an alias to href
till it is acceptable to completely remove the support for the deprecated
xlink:href.

Tests: svg/custom/href-svg-namespace-animate.svg
       svg/custom/href-svg-namespace-dynamic.svg
       svg/custom/href-svg-namespace-elements.html
       svg/custom/href-svg-namespace-expected.svg
       svg/custom/href-svg-namespace-static.svg

* dom/Element.cpp:
(WebCore::Element::absoluteLinkURL const):
* dom/Element.h:
(WebCore::Element::getAttribute const): This new template function with
template pack parameter QualifiedNames is added to return the first none
empty attribute value given a set of attributes' names. This should be
useful for deprecated attributes. When we decide to remove the support
for the deprecated attribute, all we need is to remove it as a parameter
to getAttribute(). In this case, the none template function will be called.
* dom/VisitedLinkState.cpp:
(WebCore::linkAttribute):
* html/parser/XSSAuditor.cpp:
(WebCore::XSSAuditor::filterScriptToken):
* svg/SVGAElement.cpp:
(WebCore::SVGAElement::isURLAttribute const):
* svg/SVGAltGlyphElement.cpp:
(WebCore::SVGAltGlyphElement::hasValidGlyphElements const):
* svg/SVGCursorElement.cpp:
* svg/SVGDocumentExtensions.cpp:
(WebCore::SVGDocumentExtensions::rebuildElements):
(WebCore::SVGDocumentExtensions::rebuildAllElementReferencesForTarget):
* svg/SVGElement.cpp:
(WebCore::SVGElement::animatableAttributeForName):
* svg/SVGFEImageElement.cpp:
* svg/SVGFilterElement.cpp:
* svg/SVGFontFaceUriElement.cpp:
(WebCore::SVGFontFaceUriElement::srcValue const):
(WebCore::SVGFontFaceUriElement::parseAttribute):
(WebCore::SVGFontFaceUriElement::loadFont):
* svg/SVGForeignObjectElement.cpp:
* svg/SVGGlyphRefElement.cpp:
(WebCore::SVGGlyphRefElement::hasValidGlyphElement const):
* svg/SVGGradientElement.cpp:
* svg/SVGImageElement.cpp:
(WebCore::SVGImageElement::imageSourceURL const):
* svg/SVGMPathElement.cpp:
* svg/SVGPatternElement.cpp:
* svg/SVGScriptElement.h:
* svg/SVGTRefElement.cpp:
* svg/SVGTextPathElement.cpp:
* svg/SVGURIReference.cpp:
(WebCore::SVGURIReference::registerAttributes):
(WebCore::SVGURIReference::parseAttribute):
* svg/SVGUseElement.cpp:
(WebCore::SVGUseElement::expandUseElementsInShadowTree const):
* svg/animation/SVGSMILElement.cpp:
(WebCore::SVGSMILElement::isSupportedAttribute):
(WebCore::SVGSMILElement::svgAttributeChanged):
* svg/svgattrs.in:

LayoutTests:

* fast/selectors/any-link-basics-2-expected.txt:
* fast/selectors/any-link-basics-2.html:
Re-baseline this test because it was assuming the bare href should not
work for the SVG <a> element.
* svg/custom/href-svg-namespace-animate-expected.svg: Added.
* svg/custom/href-svg-namespace-animate.svg: Added.
* svg/custom/href-svg-namespace-dynamic-expected.svg: Added.
* svg/custom/href-svg-namespace-dynamic.svg: Added.
* svg/custom/href-svg-namespace-elements-expected.txt: Added.
* svg/custom/href-svg-namespace-elements.html: Added.
* svg/custom/href-svg-namespace-static-expected.svg: Added.
* svg/custom/href-svg-namespace.static-svg: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@234683 268f45cc-cd09-0410-ab3c-d52691b4dbfc

37 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/selectors/any-link-basics-2-expected.txt
LayoutTests/fast/selectors/any-link-basics-2.html
LayoutTests/svg/custom/href-svg-namespace-animate-expected.svg [new file with mode: 0644]
LayoutTests/svg/custom/href-svg-namespace-animate.svg [new file with mode: 0644]
LayoutTests/svg/custom/href-svg-namespace-dynamic-expected.svg [new file with mode: 0644]
LayoutTests/svg/custom/href-svg-namespace-dynamic.svg [new file with mode: 0644]
LayoutTests/svg/custom/href-svg-namespace-elements-expected.txt [new file with mode: 0644]
LayoutTests/svg/custom/href-svg-namespace-elements.html [new file with mode: 0644]
LayoutTests/svg/custom/href-svg-namespace-static-expected.svg [new file with mode: 0644]
LayoutTests/svg/custom/href-svg-namespace-static.svg [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/Element.cpp
Source/WebCore/dom/Element.h
Source/WebCore/dom/VisitedLinkState.cpp
Source/WebCore/html/parser/XSSAuditor.cpp
Source/WebCore/svg/SVGAElement.cpp
Source/WebCore/svg/SVGAltGlyphElement.cpp
Source/WebCore/svg/SVGCursorElement.cpp
Source/WebCore/svg/SVGDocumentExtensions.cpp
Source/WebCore/svg/SVGElement.cpp
Source/WebCore/svg/SVGFEImageElement.cpp
Source/WebCore/svg/SVGFilterElement.cpp
Source/WebCore/svg/SVGFontFaceUriElement.cpp
Source/WebCore/svg/SVGForeignObjectElement.cpp
Source/WebCore/svg/SVGGlyphRefElement.cpp
Source/WebCore/svg/SVGGradientElement.cpp
Source/WebCore/svg/SVGImageElement.cpp
Source/WebCore/svg/SVGMPathElement.cpp
Source/WebCore/svg/SVGPatternElement.cpp
Source/WebCore/svg/SVGScriptElement.h
Source/WebCore/svg/SVGTRefElement.cpp
Source/WebCore/svg/SVGTextPathElement.cpp
Source/WebCore/svg/SVGURIReference.cpp
Source/WebCore/svg/SVGUseElement.cpp
Source/WebCore/svg/animation/SVGSMILElement.cpp
Source/WebCore/svg/svgattrs.in

index 657fab8..6f49d69 100644 (file)
@@ -1,3 +1,23 @@
+2018-08-07  Said Abou-Hallawa  <sabouhallawa@apple.com>
+
+        Allow href attribute without xlink on SVG elements
+        https://bugs.webkit.org/show_bug.cgi?id=153854
+
+        Reviewed by Dean Jackson.
+
+        * fast/selectors/any-link-basics-2-expected.txt:
+        * fast/selectors/any-link-basics-2.html:
+        Re-baseline this test because it was assuming the bare href should not 
+        work for the SVG <a> element.
+        * svg/custom/href-svg-namespace-animate-expected.svg: Added.
+        * svg/custom/href-svg-namespace-animate.svg: Added.
+        * svg/custom/href-svg-namespace-dynamic-expected.svg: Added.
+        * svg/custom/href-svg-namespace-dynamic.svg: Added.
+        * svg/custom/href-svg-namespace-elements-expected.txt: Added.
+        * svg/custom/href-svg-namespace-elements.html: Added.
+        * svg/custom/href-svg-namespace-static-expected.svg: Added.
+        * svg/custom/href-svg-namespace.static-svg: Added.
+
 2018-08-07  Ryosuke Niwa  <rniwa@webkit.org>
 
         document.open and document.write must throw while the HTML parser is synchronously constructing a custom element
index 132af57..d855f73 100644 (file)
@@ -3,7 +3,7 @@ Test the basic matching of the :any-link selector.
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS document.querySelectorAll(":any-link").length is 21
+PASS document.querySelectorAll(":any-link").length is 25
 PASS document.querySelectorAll(":any-link")[0] is document.getElementById("target-tag-2")
 PASS document.querySelectorAll(":any-link")[1] is document.getElementById("target-tag-3")
 PASS document.querySelectorAll(":any-link")[2] is document.getElementById("target-tag-4")
@@ -21,10 +21,14 @@ PASS document.querySelectorAll(":any-link")[13] is document.getElementById("targ
 PASS document.querySelectorAll(":any-link")[14] is document.getElementById("target-tag-23")
 PASS document.querySelectorAll(":any-link")[15] is document.getElementById("target-tag-24")
 PASS document.querySelectorAll(":any-link")[16] is document.getElementById("target-tag-25")
-PASS document.querySelectorAll(":any-link")[17] is document.getElementById("target-tag-31")
-PASS document.querySelectorAll(":any-link")[18] is document.getElementById("target-tag-32")
-PASS document.querySelectorAll(":any-link")[19] is document.getElementById("target-tag-33")
-PASS document.querySelectorAll(":any-link")[20] is document.getElementById("target-tag-34")
+PASS document.querySelectorAll(":any-link")[17] is document.getElementById("target-tag-27")
+PASS document.querySelectorAll(":any-link")[18] is document.getElementById("target-tag-28")
+PASS document.querySelectorAll(":any-link")[19] is document.getElementById("target-tag-29")
+PASS document.querySelectorAll(":any-link")[20] is document.getElementById("target-tag-30")
+PASS document.querySelectorAll(":any-link")[21] is document.getElementById("target-tag-31")
+PASS document.querySelectorAll(":any-link")[22] is document.getElementById("target-tag-32")
+PASS document.querySelectorAll(":any-link")[23] is document.getElementById("target-tag-33")
+PASS document.querySelectorAll(":any-link")[24] is document.getElementById("target-tag-34")
 PASS getComputedStyle(document.getElementById("target-tag-1")).backgroundColor is "rgb(255, 255, 255)"
 PASS getComputedStyle(document.getElementById("target-tag-2")).backgroundColor is "rgb(1, 2, 3)"
 PASS getComputedStyle(document.getElementById("target-tag-3")).backgroundColor is "rgb(1, 2, 3)"
@@ -51,10 +55,10 @@ PASS getComputedStyle(document.getElementById("target-tag-23")).backgroundColor
 PASS getComputedStyle(document.getElementById("target-tag-24")).backgroundColor is "rgb(1, 2, 3)"
 PASS getComputedStyle(document.getElementById("target-tag-25")).backgroundColor is "rgb(1, 2, 3)"
 PASS getComputedStyle(document.getElementById("target-tag-26")).backgroundColor is "rgb(255, 255, 255)"
-PASS getComputedStyle(document.getElementById("target-tag-27")).backgroundColor is "rgb(255, 255, 255)"
-PASS getComputedStyle(document.getElementById("target-tag-28")).backgroundColor is "rgb(255, 255, 255)"
-PASS getComputedStyle(document.getElementById("target-tag-29")).backgroundColor is "rgb(255, 255, 255)"
-PASS getComputedStyle(document.getElementById("target-tag-30")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("target-tag-27")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("target-tag-28")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("target-tag-29")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("target-tag-30")).backgroundColor is "rgb(1, 2, 3)"
 PASS getComputedStyle(document.getElementById("target-tag-31")).backgroundColor is "rgb(1, 2, 3)"
 PASS getComputedStyle(document.getElementById("target-tag-32")).backgroundColor is "rgb(1, 2, 3)"
 PASS getComputedStyle(document.getElementById("target-tag-33")).backgroundColor is "rgb(1, 2, 3)"
index 0436b29..6ae652d 100644 (file)
@@ -76,8 +76,6 @@
 <script>
 description('Test the basic matching of the :any-link selector.');
 
-shouldBe('document.querySelectorAll(":any-link").length', '21');
-
 // Query Selector.
 var expectedIds = ['target-tag-2',
                    'target-tag-3',
@@ -96,11 +94,17 @@ var expectedIds = ['target-tag-2',
                    'target-tag-23',
                    'target-tag-24',
                    'target-tag-25',
+                   'target-tag-27',
+                   'target-tag-28',
+                   'target-tag-29',
+                   'target-tag-30',
                    'target-tag-31',
                    'target-tag-32',
                    'target-tag-33',
                    'target-tag-34'];
 
+shouldBe('document.querySelectorAll(":any-link").length', expectedIds.length.toString());
+
 for (var i = 0; i < expectedIds.length; ++i)
     shouldBe('document.querySelectorAll(":any-link")[' + i + ']', 'document.getElementById("' + expectedIds[i] + '")');
 
@@ -131,10 +135,10 @@ var expectedStyles = [['target-tag-1', 'rgb(255, 255, 255)'],
                       ['target-tag-24', 'rgb(1, 2, 3)'],
                       ['target-tag-25', 'rgb(1, 2, 3)'],
                       ['target-tag-26', 'rgb(255, 255, 255)'],
-                      ['target-tag-27', 'rgb(255, 255, 255)'],
-                      ['target-tag-28', 'rgb(255, 255, 255)'],
-                      ['target-tag-29', 'rgb(255, 255, 255)'],
-                      ['target-tag-30', 'rgb(255, 255, 255)'],
+                      ['target-tag-27', 'rgb(1, 2, 3)'],
+                      ['target-tag-28', 'rgb(1, 2, 3)'],
+                      ['target-tag-29', 'rgb(1, 2, 3)'],
+                      ['target-tag-30', 'rgb(1, 2, 3)'],
                       ['target-tag-31', 'rgb(1, 2, 3)'],
                       ['target-tag-32', 'rgb(1, 2, 3)'],
                       ['target-tag-33', 'rgb(1, 2, 3)'],
diff --git a/LayoutTests/svg/custom/href-svg-namespace-animate-expected.svg b/LayoutTests/svg/custom/href-svg-namespace-animate-expected.svg
new file mode 100644 (file)
index 0000000..877ad99
--- /dev/null
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+    <rect x="10" y="10" width="100" height="100" fill="green" />
+    <rect x="120" y="10" width="100" height="100" fill="green" />
+    <rect x="230" y="10" width="100" height="100" fill="green" />
+    <rect x="340" y="10" width="100" height="100" fill="green" />
+</svg>
diff --git a/LayoutTests/svg/custom/href-svg-namespace-animate.svg b/LayoutTests/svg/custom/href-svg-namespace-animate.svg
new file mode 100644 (file)
index 0000000..d229371
--- /dev/null
@@ -0,0 +1,35 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <defs>
+        <rect id="red" width="100" height="100" fill="red"/>
+        <rect id="green" width="100" height="100" fill="green"/>
+    </defs>
+    <use x="10" y="10" width="100" height="100">
+        <animate attributeName="xlink:href" from="#red" dur="50ms" to="#green" fill="freeze"/>
+    </use>
+    <use x="120" y="10" width="100" height="100" xlink:href="#red">
+        <animate attributeName="xlink:href" from="#red" dur="60ms" to="#green" fill="freeze"/>
+    </use>
+    <use x="230" y="10" width="100" height="100">
+        <animate attributeName="href" from="#red" dur="70ms" to="#green" fill="freeze"/>
+    </use>
+    <use x="340" y="10" width="100" height="100" href="#red">
+        <animate attributeName="href" from="#red" dur="80ms" to="#green" fill="freeze"/>
+    </use>
+    <script>
+        if (window.testRunner)
+            testRunner.waitUntilDone();
+
+        var elements = document.querySelectorAll("animate");
+        var count = elements.length;
+
+        for (var i = count; i--; )
+            elements[i].addEventListener("endEvent", endAnimate, false);
+
+        function endAnimate() {
+            if (--count === 0) {
+                if (window.testRunner)
+                    testRunner.notifyDone();
+            }
+        }
+    </script>
+</svg>
diff --git a/LayoutTests/svg/custom/href-svg-namespace-dynamic-expected.svg b/LayoutTests/svg/custom/href-svg-namespace-dynamic-expected.svg
new file mode 100644 (file)
index 0000000..877ad99
--- /dev/null
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+    <rect x="10" y="10" width="100" height="100" fill="green" />
+    <rect x="120" y="10" width="100" height="100" fill="green" />
+    <rect x="230" y="10" width="100" height="100" fill="green" />
+    <rect x="340" y="10" width="100" height="100" fill="green" />
+</svg>
diff --git a/LayoutTests/svg/custom/href-svg-namespace-dynamic.svg b/LayoutTests/svg/custom/href-svg-namespace-dynamic.svg
new file mode 100644 (file)
index 0000000..9aac548
--- /dev/null
@@ -0,0 +1,17 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <defs>
+        <rect id="red" width="100" height="100" fill="red"/>
+        <rect id="green" width="100" height="100" fill="green"/>
+    </defs>
+    <use x="10" y="10" width="100" height="100" href="#red" />
+    <use x="120" y="10" width="100" height="100" href="#red" />
+    <use x="230" y="10" width="100" height="100" xmlns:href="#red" />
+    <use x="340" y="10" width="100" height="100" xmlns:href="#red" />
+    <script>
+        var elements = document.querySelectorAll("use");
+        elements[0].setAttribute("href", "#green");
+        elements[1].href.baseVal = "#green";
+        elements[2].setAttribute("href", "#green");
+        elements[3].href.baseVal = "#green";
+    </script>
+</svg>
diff --git a/LayoutTests/svg/custom/href-svg-namespace-elements-expected.txt b/LayoutTests/svg/custom/href-svg-namespace-elements-expected.txt
new file mode 100644 (file)
index 0000000..85118d7
--- /dev/null
@@ -0,0 +1,90 @@
+Ensures the svg href attribute can work without having to be prefixed by the xlink namespace.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS window.element.tagName is "a"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is "www.webkit.org"
+PASS window.element.getAttribute('href') is "www.webkit.org"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is null
+PASS window.element.getAttribute('href') is "www.build.webkit.org"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is null
+PASS window.element.getAttributeNS('http://www.w3.org/2000/svg', 'href') is null
+PASS window.element.getAttribute('href') is "www.build.webkit.org"
+PASS window.element.href.baseVal is "www.build.webkit.org"
+PASS window.element.tagName is "feImage"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is "resources/red-checker.png"
+PASS window.element.getAttribute('href') is "resources/red-checker.png"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is null
+PASS window.element.getAttribute('href') is "resources/green-checker.png"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is null
+PASS window.element.getAttributeNS('http://www.w3.org/2000/svg', 'href') is null
+PASS window.element.getAttribute('href') is "resources/green-checker.png"
+PASS window.element.href.baseVal is "resources/green-checker.png"
+PASS window.element.tagName is "filter"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is "base-filter-1"
+PASS window.element.getAttribute('href') is "base-filter-1"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is null
+PASS window.element.getAttribute('href') is "base-filter-2"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is null
+PASS window.element.getAttributeNS('http://www.w3.org/2000/svg', 'href') is null
+PASS window.element.getAttribute('href') is "base-filter-2"
+PASS window.element.href.baseVal is "base-filter-2"
+PASS window.element.tagName is "image"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is "resources/red-checker.png"
+PASS window.element.getAttribute('href') is "resources/red-checker.png"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is null
+PASS window.element.getAttribute('href') is "resources/green-checker.png"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is null
+PASS window.element.getAttributeNS('http://www.w3.org/2000/svg', 'href') is null
+PASS window.element.getAttribute('href') is "resources/green-checker.png"
+PASS window.element.href.baseVal is "resources/green-checker.png"
+PASS window.element.tagName is "linearGradient"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is "#base-linear-gradient-1"
+PASS window.element.getAttribute('href') is "#base-linear-gradient-1"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is null
+PASS window.element.getAttribute('href') is "#base-linear-gradient-2"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is null
+PASS window.element.getAttributeNS('http://www.w3.org/2000/svg', 'href') is null
+PASS window.element.getAttribute('href') is "#base-linear-gradient-2"
+PASS window.element.href.baseVal is "#base-linear-gradient-2"
+PASS window.element.tagName is "pattern"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is "#base-pattern-1"
+PASS window.element.getAttribute('href') is "#base-pattern-1"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is null
+PASS window.element.getAttribute('href') is "#base-pattern-2"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is null
+PASS window.element.getAttributeNS('http://www.w3.org/2000/svg', 'href') is null
+PASS window.element.getAttribute('href') is "#base-pattern-2"
+PASS window.element.href.baseVal is "#base-pattern-2"
+PASS window.element.tagName is "radialGradient"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is "#base-radial-gradient-1"
+PASS window.element.getAttribute('href') is "#base-radial-gradient-1"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is null
+PASS window.element.getAttribute('href') is "#base-radial-gradient-2"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is null
+PASS window.element.getAttributeNS('http://www.w3.org/2000/svg', 'href') is null
+PASS window.element.getAttribute('href') is "#base-radial-gradient-2"
+PASS window.element.href.baseVal is "#base-radial-gradient-2"
+PASS window.element.tagName is "textPath"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is "#text-path-1"
+PASS window.element.getAttribute('href') is "#text-path-1"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is null
+PASS window.element.getAttribute('href') is "#text-path-2"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is null
+PASS window.element.getAttributeNS('http://www.w3.org/2000/svg', 'href') is null
+PASS window.element.getAttribute('href') is "#text-path-2"
+PASS window.element.href.baseVal is "#text-path-2"
+PASS window.element.tagName is "use"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is "#red-rect"
+PASS window.element.getAttribute('href') is "#red-rect"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is null
+PASS window.element.getAttribute('href') is "#green-rect"
+PASS window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') is null
+PASS window.element.getAttributeNS('http://www.w3.org/2000/svg', 'href') is null
+PASS window.element.getAttribute('href') is "#green-rect"
+PASS window.element.href.baseVal is "#green-rect"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/custom/href-svg-namespace-elements.html b/LayoutTests/svg/custom/href-svg-namespace-elements.html
new file mode 100644 (file)
index 0000000..01b8263
--- /dev/null
@@ -0,0 +1,42 @@
+<head>
+    <script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+    <script>
+        description("Ensures the svg href attribute can work without having to be prefixed by the xlink namespace.");
+
+        var tagHrefTable = [
+            { tagName: "a",              xlinkValue: "www.webkit.org",            svgValue: "www.build.webkit.org" },
+            { tagName: "feImage",        xlinkValue: "resources/red-checker.png", svgValue: "resources/green-checker.png" },
+            { tagName: "filter",         xlinkValue: "base-filter-1",             svgValue: "base-filter-2" },
+            { tagName: "image",          xlinkValue: "resources/red-checker.png", svgValue: "resources/green-checker.png" },
+            { tagName: "linearGradient", xlinkValue: "#base-linear-gradient-1",   svgValue: "#base-linear-gradient-2" },
+            { tagName: "pattern",        xlinkValue: "#base-pattern-1",           svgValue: "#base-pattern-2" },
+            { tagName: "radialGradient", xlinkValue: "#base-radial-gradient-1",   svgValue: "#base-radial-gradient-2" },
+            { tagName: "textPath",       xlinkValue: "#text-path-1",              svgValue: "#text-path-2" },
+            { tagName: "use",            xlinkValue: "#red-rect",                 svgValue: "#green-rect" },
+        ];
+
+        tagHrefTable.forEach(function(tagHref) {
+            window.element = document.createElementNS("http://www.w3.org/2000/svg", tagHref.tagName);
+            shouldBeEqualToString("window.element.tagName", tagHref.tagName);
+
+            window.element.setAttributeNS("http://www.w3.org/1999/xlink", "href", tagHref.xlinkValue);
+            shouldBeEqualToString("window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href')", tagHref.xlinkValue);
+            shouldBeEqualToString("window.element.getAttribute('href')", tagHref.xlinkValue);
+            window.element.removeAttributeNS('http://www.w3.org/1999/xlink', "href");
+
+            window.element.setAttributeNS("http://www.w3.org/2000/svg", "href", tagHref.svgValue);
+            shouldBeNull("window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href')");
+            shouldBeEqualToString("window.element.getAttribute('href')", tagHref.svgValue);
+            window.element.removeAttributeNS("http://www.w3.org/2000/svg", "href");
+
+            window.element.setAttribute("href", tagHref.svgValue);
+            shouldBeNull("window.element.getAttributeNS('http://www.w3.org/1999/xlink', 'href')");
+            shouldBeNull("window.element.getAttributeNS('http://www.w3.org/2000/svg', 'href')");
+            shouldBeEqualToString("window.element.getAttribute('href')", tagHref.svgValue);
+            shouldBeEqualToString("window.element.href.baseVal", tagHref.svgValue);
+        });
+    </script>
+    <script src="../../resources/js-test-post.js"></script>
+</body>
diff --git a/LayoutTests/svg/custom/href-svg-namespace-static-expected.svg b/LayoutTests/svg/custom/href-svg-namespace-static-expected.svg
new file mode 100644 (file)
index 0000000..877ad99
--- /dev/null
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+    <rect x="10" y="10" width="100" height="100" fill="green" />
+    <rect x="120" y="10" width="100" height="100" fill="green" />
+    <rect x="230" y="10" width="100" height="100" fill="green" />
+    <rect x="340" y="10" width="100" height="100" fill="green" />
+</svg>
diff --git a/LayoutTests/svg/custom/href-svg-namespace-static.svg b/LayoutTests/svg/custom/href-svg-namespace-static.svg
new file mode 100644 (file)
index 0000000..741faf7
--- /dev/null
@@ -0,0 +1,22 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+    <defs>
+        <linearGradient id="gradient1">
+            <stop offset="0%" stop-color="green" />
+            <stop offset="100%" stop-color="green" />
+        </linearGradient>
+        <linearGradient id="gradient2" x1="0%" y1="0%" x2="100%" y2="0%" href="#gradient1"/>
+        <pattern id="pattern1">
+            <rect width="100%" height="100%" fill="green"/>
+        </pattern>
+        <pattern id="pattern2" x="0" y="0" width="100" height="100"  href="#pattern1"/>
+        <rect id="rect" width="100" height="100"/>
+    </defs>
+    <rect x="10" y="10" width="100" height="100" fill="url(#gradient2)" />
+    <rect x="120" y="10" width="100" height="100" fill="url(#pattern2)" />
+    <image x="230" y="10" width="100" height="100"
+        href="data:image/svg+xml;base64,
+            PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgI
+            DxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDBweCIgaGVpZ2h0PSIxMDBweCIgZmlsbD0iZ3JlZW4iLz4KPC9zdmc+"
+    />
+    <use x="340" y="10" width="100" height="100" href="#rect" fill="green"/>
+</svg>
index aad7142..58ddcf6 100644 (file)
@@ -1,3 +1,76 @@
+2018-08-07  Said Abou-Hallawa  <sabouhallawa@apple.com>
+
+        Allow href attribute without xlink on SVG elements
+        https://bugs.webkit.org/show_bug.cgi?id=153854
+
+        Reviewed by Dean Jackson.
+
+        SVG 2 has moved the href attribute from xlink namespace to svg namespace.
+        Instead of using xlink:href, svg:href should be used or simply use href 
+        if the svg namespace is defined.
+
+        See https://www.w3.org/TR/SVG2/linking.html#XLinkRefAttrs.
+
+        For backward compatibility, xlink:href will be treated as an alias to href
+        till it is acceptable to completely remove the support for the deprecated 
+        xlink:href.
+
+        Tests: svg/custom/href-svg-namespace-animate.svg
+               svg/custom/href-svg-namespace-dynamic.svg
+               svg/custom/href-svg-namespace-elements.html
+               svg/custom/href-svg-namespace-expected.svg
+               svg/custom/href-svg-namespace-static.svg
+
+        * dom/Element.cpp:
+        (WebCore::Element::absoluteLinkURL const):
+        * dom/Element.h:
+        (WebCore::Element::getAttribute const): This new template function with
+        template pack parameter QualifiedNames is added to return the first none
+        empty attribute value given a set of attributes' names. This should be
+        useful for deprecated attributes. When we decide to remove the support 
+        for the deprecated attribute, all we need is to remove it as a parameter
+        to getAttribute(). In this case, the none template function will be called.
+        * dom/VisitedLinkState.cpp:
+        (WebCore::linkAttribute):
+        * html/parser/XSSAuditor.cpp:
+        (WebCore::XSSAuditor::filterScriptToken):
+        * svg/SVGAElement.cpp:
+        (WebCore::SVGAElement::isURLAttribute const):
+        * svg/SVGAltGlyphElement.cpp:
+        (WebCore::SVGAltGlyphElement::hasValidGlyphElements const):
+        * svg/SVGCursorElement.cpp:
+        * svg/SVGDocumentExtensions.cpp:
+        (WebCore::SVGDocumentExtensions::rebuildElements):
+        (WebCore::SVGDocumentExtensions::rebuildAllElementReferencesForTarget):
+        * svg/SVGElement.cpp:
+        (WebCore::SVGElement::animatableAttributeForName):
+        * svg/SVGFEImageElement.cpp:
+        * svg/SVGFilterElement.cpp:
+        * svg/SVGFontFaceUriElement.cpp:
+        (WebCore::SVGFontFaceUriElement::srcValue const):
+        (WebCore::SVGFontFaceUriElement::parseAttribute):
+        (WebCore::SVGFontFaceUriElement::loadFont):
+        * svg/SVGForeignObjectElement.cpp:
+        * svg/SVGGlyphRefElement.cpp:
+        (WebCore::SVGGlyphRefElement::hasValidGlyphElement const):
+        * svg/SVGGradientElement.cpp:
+        * svg/SVGImageElement.cpp:
+        (WebCore::SVGImageElement::imageSourceURL const):
+        * svg/SVGMPathElement.cpp:
+        * svg/SVGPatternElement.cpp:
+        * svg/SVGScriptElement.h:
+        * svg/SVGTRefElement.cpp:
+        * svg/SVGTextPathElement.cpp:
+        * svg/SVGURIReference.cpp:
+        (WebCore::SVGURIReference::registerAttributes):
+        (WebCore::SVGURIReference::parseAttribute):
+        * svg/SVGUseElement.cpp:
+        (WebCore::SVGUseElement::expandUseElementsInShadowTree const):
+        * svg/animation/SVGSMILElement.cpp:
+        (WebCore::SVGSMILElement::isSupportedAttribute):
+        (WebCore::SVGSMILElement::svgAttributeChanged):
+        * svg/svgattrs.in:
+
 2018-08-07  Ryosuke Niwa  <rniwa@webkit.org>
 
         document.open and document.write must throw while the HTML parser is synchronously constructing a custom element
index 8870d2d..69e6f90 100644 (file)
@@ -1472,7 +1472,7 @@ URL Element::absoluteLinkURL() const
 
     AtomicString linkAttribute;
     if (hasTagName(SVGNames::aTag))
-        linkAttribute = getAttribute(XLinkNames::hrefAttr);
+        linkAttribute = getAttribute(SVGNames::hrefAttr, XLinkNames::hrefAttr);
     else
         linkAttribute = getAttribute(HTMLNames::hrefAttr);
 
index 842a208..183c3fd 100644 (file)
@@ -76,6 +76,8 @@ public:
 
     WEBCORE_EXPORT bool hasAttribute(const QualifiedName&) const;
     WEBCORE_EXPORT const AtomicString& getAttribute(const QualifiedName&) const;
+    template<typename... QualifiedNames>
+    const AtomicString& getAttribute(const QualifiedName&, const QualifiedNames&...) const;
     WEBCORE_EXPORT void setAttribute(const QualifiedName&, const AtomicString& value);
     WEBCORE_EXPORT void setAttributeWithoutSynchronization(const QualifiedName&, const AtomicString& value);
     void setSynchronizedLazyAttribute(const QualifiedName&, const AtomicString& value);
@@ -817,6 +819,15 @@ inline void Element::setHasFocusWithin(bool flag)
         invalidateStyleForSubtree();
 }
 
+template<typename... QualifiedNames>
+inline const AtomicString& Element::getAttribute(const QualifiedName& name, const QualifiedNames&... names) const
+{
+    const AtomicString& value = getAttribute(name);
+    if (!value.isEmpty())
+        return value;
+    return getAttribute(names...);
+}
+
 } // namespace WebCore
 
 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::Element)
index 43564c1..c49c368 100644 (file)
@@ -33,6 +33,7 @@
 #include "Frame.h"
 #include "HTMLAnchorElement.h"
 #include "Page.h"
+#include "SVGNames.h"
 #include "VisitedLinkStore.h"
 #include "XLinkNames.h"
 
@@ -47,7 +48,7 @@ inline static const AtomicString* linkAttribute(const Element& element)
     if (element.isHTMLElement())
         return &element.attributeWithoutSynchronization(HTMLNames::hrefAttr);
     if (element.isSVGElement())
-        return &element.getAttribute(XLinkNames::hrefAttr);
+        return &element.getAttribute(SVGNames::hrefAttr, XLinkNames::hrefAttr);
     return 0;
 }
 
index 2ac8a2a..71928c7 100644 (file)
@@ -447,6 +447,7 @@ bool XSSAuditor::filterScriptToken(const FilterTokenRequest& request)
     bool didBlockScript = false;
     if (m_wasScriptTagFoundInRequest) {
         didBlockScript |= eraseAttributeIfInjected(request, srcAttr, blankURL().string(), TruncationStyle::SrcLikeAttribute);
+        didBlockScript |= eraseAttributeIfInjected(request, SVGNames::hrefAttr, blankURL().string(), TruncationStyle::SrcLikeAttribute);
         didBlockScript |= eraseAttributeIfInjected(request, XLinkNames::hrefAttr, blankURL().string(), TruncationStyle::SrcLikeAttribute);
     }
 
index cc3c09f..ca9cdf0 100644 (file)
@@ -171,7 +171,7 @@ bool SVGAElement::supportsFocus() const
 
 bool SVGAElement::isURLAttribute(const Attribute& attribute) const
 {
-    return attribute.name().localName() == XLinkNames::hrefAttr || SVGGraphicsElement::isURLAttribute(attribute);
+    return SVGURIReference::isKnownAttribute(attribute.name()) || SVGGraphicsElement::isURLAttribute(attribute);
 }
 
 bool SVGAElement::isMouseFocusable() const
index 782b245..9b2c7eb 100644 (file)
@@ -82,7 +82,7 @@ RenderPtr<RenderElement> SVGAltGlyphElement::createElementRenderer(RenderStyle&&
 bool SVGAltGlyphElement::hasValidGlyphElements(Vector<String>& glyphNames) const
 {
     String target;
-    auto element = makeRefPtr(targetElementFromIRIString(getAttribute(XLinkNames::hrefAttr), document(), &target));
+    auto element = makeRefPtr(targetElementFromIRIString(getAttribute(SVGNames::hrefAttr, XLinkNames::hrefAttr), document(), &target));
 
     if (is<SVGGlyphElement>(element)) {
         glyphNames.append(target);
index 8dd70f2..cd808c9 100644 (file)
@@ -26,7 +26,6 @@
 #include "Document.h"
 #include "SVGNames.h"
 #include "SVGStringList.h"
-#include "XLinkNames.h"
 #include <wtf/IsoMallocInlines.h>
 #include <wtf/NeverDestroyed.h>
 
index 65e246d..4ec1a8c 100644 (file)
@@ -35,7 +35,6 @@
 #include "SVGSVGElement.h"
 #include "ScriptableDocumentParser.h"
 #include "ShadowRoot.h"
-#include "XLinkNames.h"
 #include <wtf/text/AtomicString.h>
 
 namespace WebCore {
@@ -326,7 +325,7 @@ void SVGDocumentExtensions::rebuildElements()
 {
     Vector<SVGElement*> shadowRebuildElements = WTFMove(m_rebuildElements);
     for (auto* element : shadowRebuildElements)
-        element->svgAttributeChanged(XLinkNames::hrefAttr);
+        element->svgAttributeChanged(SVGNames::hrefAttr);
 }
 
 void SVGDocumentExtensions::clearTargetDependencies(SVGElement& referencedElement)
@@ -356,7 +355,7 @@ void SVGDocumentExtensions::rebuildAllElementReferencesForTarget(SVGElement& ref
         elementsToRebuild.uncheckedAppend(element);
 
     for (auto* element : elementsToRebuild)
-        element->svgAttributeChanged(XLinkNames::hrefAttr);
+        element->svgAttributeChanged(SVGNames::hrefAttr);
 }
 
 void SVGDocumentExtensions::removeAllElementReferencesForTarget(SVGElement* referencedElement)
index 1b7214b..fd59656 100644 (file)
@@ -50,7 +50,6 @@
 #include "SVGTitleElement.h"
 #include "SVGUseElement.h"
 #include "ShadowRoot.h"
-#include "XLinkNames.h"
 #include "XMLNames.h"
 #include <wtf/Assertions.h>
 #include <wtf/HashMap.h>
@@ -854,7 +853,7 @@ QualifiedName SVGElement::animatableAttributeForName(const AtomicString& localNa
             &SVGNames::yAttr.get(),
             &SVGNames::yChannelSelectorAttr.get(),
             &SVGNames::zAttr.get(),
-            &XLinkNames::hrefAttr.get(),
+            &SVGNames::hrefAttr.get(),
         };
         HashMap<AtomicString, QualifiedName> map;
         for (auto& name : names) {
index 3a41928..db7ef12 100644 (file)
@@ -32,7 +32,6 @@
 #include "RenderSVGResource.h"
 #include "SVGNames.h"
 #include "SVGPreserveAspectRatioValue.h"
-#include "XLinkNames.h"
 #include <wtf/IsoMallocInlines.h>
 
 namespace WebCore {
index f5a208a..781ce06 100644 (file)
@@ -31,7 +31,6 @@
 #include "SVGFilterPrimitiveStandardAttributes.h"
 #include "SVGNames.h"
 #include "SVGParserUtilities.h"
-#include "XLinkNames.h"
 #include <wtf/IsoMallocInlines.h>
 #include <wtf/NeverDestroyed.h>
 
index affaea4..57cb2db 100644 (file)
@@ -58,7 +58,7 @@ SVGFontFaceUriElement::~SVGFontFaceUriElement()
 
 Ref<CSSFontFaceSrcValue> SVGFontFaceUriElement::srcValue() const
 {
-    auto src = CSSFontFaceSrcValue::create(getAttribute(XLinkNames::hrefAttr));
+    auto src = CSSFontFaceSrcValue::create(getAttribute(SVGNames::hrefAttr, XLinkNames::hrefAttr));
     AtomicString value(attributeWithoutSynchronization(formatAttr));
     src.get().setFormat(value.isEmpty() ? "svg" : value); // Default format
     return src;
@@ -66,7 +66,7 @@ Ref<CSSFontFaceSrcValue> SVGFontFaceUriElement::srcValue() const
 
 void SVGFontFaceUriElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
 {
-    if (name == XLinkNames::hrefAttr)
+    if (name == SVGNames::hrefAttr || name == XLinkNames::hrefAttr)
         loadFont();
     else
         SVGElement::parseAttribute(name, value);
@@ -101,7 +101,7 @@ void SVGFontFaceUriElement::loadFont()
     if (m_cachedFont)
         m_cachedFont->removeClient(*this);
 
-    const AtomicString& href = getAttribute(XLinkNames::hrefAttr);
+    const AtomicString& href = getAttribute(SVGNames::hrefAttr, XLinkNames::hrefAttr);
     if (!href.isNull()) {
         ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
         options.contentSecurityPolicyImposition = isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck;
index 0492077..006a773 100644 (file)
@@ -27,7 +27,6 @@
 #include "RenderSVGResource.h"
 #include "SVGLengthValue.h"
 #include "SVGNames.h"
-#include "XLinkNames.h"
 #include <wtf/Assertions.h>
 #include <wtf/IsoMallocInlines.h>
 #include <wtf/NeverDestroyed.h>
index 24cdd40..9154417 100644 (file)
@@ -50,7 +50,7 @@ bool SVGGlyphRefElement::hasValidGlyphElement(String& glyphName) const
 {
     // FIXME: We only support xlink:href so far.
     // https://bugs.webkit.org/show_bug.cgi?id=64787
-    return is<SVGGlyphElement>(targetElementFromIRIString(getAttribute(XLinkNames::hrefAttr), document(), &glyphName));
+    return is<SVGGlyphElement>(targetElementFromIRIString(getAttribute(SVGNames::hrefAttr, XLinkNames::hrefAttr), document(), &glyphName));
 }
 
 static float parseFloat(const AtomicString& value)
index d65e0f8..d5814f2 100644 (file)
@@ -32,7 +32,6 @@
 #include "SVGTransformListValues.h"
 #include "SVGTransformable.h"
 #include "StyleResolver.h"
-#include "XLinkNames.h"
 #include <wtf/IsoMallocInlines.h>
 #include <wtf/NeverDestroyed.h>
 
index f939377..0559927 100644 (file)
@@ -167,7 +167,7 @@ Node::InsertedIntoAncestorResult SVGImageElement::insertedIntoAncestor(Insertion
 
 const AtomicString& SVGImageElement::imageSourceURL() const
 {
-    return getAttribute(XLinkNames::hrefAttr);
+    return getAttribute(SVGNames::hrefAttr, XLinkNames::hrefAttr);
 }
 
 void SVGImageElement::addSubresourceAttributeURLs(ListHashSet<URL>& urls) const
index 93c8d43..d17c591 100644 (file)
@@ -26,7 +26,6 @@
 #include "SVGDocumentExtensions.h"
 #include "SVGNames.h"
 #include "SVGPathElement.h"
-#include "XLinkNames.h"
 
 namespace WebCore {
 
index 172d6c6..700f26b 100644 (file)
@@ -38,7 +38,6 @@
 #include "SVGRenderSupport.h"
 #include "SVGStringList.h"
 #include "SVGTransformable.h"
-#include "XLinkNames.h"
 #include <wtf/IsoMallocInlines.h>
 #include <wtf/NeverDestroyed.h>
 
index 5264571..f8ced22 100644 (file)
@@ -67,7 +67,7 @@ private:
     bool hasAsyncAttribute() const final { return false; }
     bool hasDeferAttribute() const final { return false; }
     bool hasNoModuleAttribute() const final { return false; }
-    bool hasSourceAttribute() const final { return hasAttribute(XLinkNames::hrefAttr); }
+    bool hasSourceAttribute() const final { return hasAttribute(SVGNames::hrefAttr) || hasAttribute(XLinkNames::hrefAttr); }
 
     void dispatchLoadEvent() final { SVGExternalResourcesRequired::dispatchLoadEvent(); }
 
index 26becb2..3047daf 100644 (file)
@@ -36,7 +36,6 @@
 #include "ScriptDisallowedScope.h"
 #include "StyleInheritedData.h"
 #include "Text.h"
-#include "XLinkNames.h"
 #include <wtf/IsoMallocInlines.h>
 
 namespace WebCore {
index f922dab..e9a7005 100644 (file)
@@ -26,7 +26,6 @@
 #include "RenderSVGTextPath.h"
 #include "SVGDocumentExtensions.h"
 #include "SVGNames.h"
-#include "XLinkNames.h"
 #include <wtf/IsoMallocInlines.h>
 #include <wtf/NeverDestroyed.h>
 
index 9cb4da0..68504aa 100644 (file)
@@ -41,6 +41,7 @@ void SVGURIReference::registerAttributes()
     auto& registry = attributeRegistry();
     if (!registry.isEmpty())
         return;
+    registry.registerAttribute<SVGNames::hrefAttr, &SVGURIReference::m_href>();
     registry.registerAttribute<XLinkNames::hrefAttr, &SVGURIReference::m_href>();
 }
 
@@ -56,7 +57,7 @@ bool SVGURIReference::isKnownAttribute(const QualifiedName& attributeName)
 
 void SVGURIReference::parseAttribute(const QualifiedName& name, const AtomicString& value)
 {
-    if (name.matches(XLinkNames::hrefAttr))
+    if (isKnownAttribute(name))
         m_href.setValue(value);
 }
 
index f12c7d0..f7e2344 100644 (file)
@@ -480,6 +480,7 @@ void SVGUseElement::expandUseElementsInShadowTree() const
         replacementClone->removeAttribute(SVGNames::yAttr);
         replacementClone->removeAttribute(SVGNames::widthAttr);
         replacementClone->removeAttribute(SVGNames::heightAttr);
+        replacementClone->removeAttribute(SVGNames::hrefAttr);
         replacementClone->removeAttribute(XLinkNames::hrefAttr);
 
         if (target)
index 0601e5c..f508613 100644 (file)
@@ -467,6 +467,7 @@ bool SVGSMILElement::isSupportedAttribute(const QualifiedName& attrName)
         SVGNames::minAttr,
         SVGNames::maxAttr,
         SVGNames::attributeNameAttr,
+        SVGNames::hrefAttr,
         XLinkNames::hrefAttr,
     });
     return supportedAttributes.get().contains<SVGAttributeHashTranslator>(attrName);
@@ -519,7 +520,7 @@ void SVGSMILElement::svgAttributeChanged(const QualifiedName& attrName)
         m_cachedMax = invalidCachedTime;
     else if (attrName == SVGNames::attributeNameAttr)
         updateAttributeName();
-    else if (attrName.matches(XLinkNames::hrefAttr)) {
+    else if (attrName.matches(SVGNames::hrefAttr) || attrName.matches(XLinkNames::hrefAttr)) {
         InstanceInvalidationGuard guard(*this);
         buildPendingResource();
     } else if (isConnected()) {
index c7561c2..8a356f0 100644 (file)
@@ -87,6 +87,7 @@ height
 horiz-adv-x
 horiz-origin-x
 horiz-origin-y
+href
 ideographic
 image-rendering
 in