gecko-dev/layout/svg/tests/test_use_tree_cycle.html
Emilio Cobos Álvarez 2dd6a71b3e Bug 1531333 - Fix <svg:use> cycle detection. r=longsonr
With the current code we'll eventually detect the cycle, but will take much
more, creating many shadow trees unnecessarily. Take for example the following:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="133" height="232774">
    <style>
      symbol { display: block }
    </style>
    <symbol id="svg-sprite" viewBox="0 0 133 230866">
        <title>svg-sprite</title>
        <symbol id="svg-sprite" viewBox="0 0 133 230866">
            <title>svg-sprite</title>
            <use xlink:href="#svg-sprite" width="500" height="500" />
        </symbol>
        <use xlink:href="#svg-sprite" y="1601" width="133" height="228958" />
    </symbol>
    <use xlink:href="#svg-sprite" y="1601" width="133" height="230866" />
</svg>

Before this patch, we'd create an svg use element subtree for #svg-sprite. That
subtree will contain two other <use> elements, one under the <symbol>, one not
under it.

Both point to #svg-sprite, but we fail to detect we're an ancestor since the
element #svg-sprite we're looking at is the clone of the #svg-sprite element.

Thus we need to take a look at mOriginal instead (which is the <use> element
under #svg-sprite) rather than at the clone.

Yeah, I had to draw the trees, it's messy :)

Blink and WebKit do something slightly different (they check the element id
directly[1]). That's not 100% correct, since you can have multiple elements with
the same ID.

[1]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/svg/svg_use_element.cc?l=560&rcl=861855dcb8c39ba8d42497247d433277858df79b

Differential Revision: https://phabricator.services.mozilla.com/D24565

--HG--
extra : moz-landing-system : lando
2019-03-22 22:26:53 +00:00

38 lines
1.3 KiB
HTML

<!doctype html>
<title>Test for bug 1531333</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
<style>
symbol { display: block }
</style>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="10" height="10">
<symbol id="svg-sprite" viewBox="0 0 133 230866">
<title>svg-sprite</title>
<symbol id="svg-sprite" viewBox="0 0 133 230866">
<title>svg-sprite</title>
<use xlink:href="#svg-sprite" width="500" height="500" />
</symbol>
<use xlink:href="#svg-sprite" y="1601" width="133" height="228958" />
</symbol>
<use xlink:href="#svg-sprite" y="1601" width="133" height="230866" />
</svg>
<script>
function countUseElements(subtreeRoot) {
if (!subtreeRoot)
return 0;
let i = 0;
for (const use of subtreeRoot.querySelectorAll("use"))
i += 1 + countUseElements(SpecialPowers.wrap(use).openOrClosedShadowRoot);
return i;
}
SimpleTest.waitForExplicitFinish();
onload = function() {
document.body.offsetTop;
// The three in the document, plus the two created from the element that's
// not in the <symbol> subtree.
is(countUseElements(document), 5, "Shouldn't create more than 5 use elements");
SimpleTest.finish();
}
</script>