Changeset 179980 in webkit


Ignore:
Timestamp:
Feb 11, 2015 7:53:48 PM (9 years ago)
Author:
Darin Adler
Message:

SVGUseElement follow-up improvements
https://bugs.webkit.org/show_bug.cgi?id=141382

Reviewed by Antti Koivisto.

Source/WebCore:

  • loader/cache/CachedSVGDocumentClient.h: Removed unneeded forward declaration.
  • page/EventHandler.cpp: Removed unneeded include of SVGUseElement.h.
  • rendering/svg/RenderSVGViewportContainer.cpp: Ditto.
  • svg/SVGDocumentExtensions.cpp:

(WebCore::SVGDocumentExtensions::clearTargetDependencies): Removed too-specific
check that assumed that SVG elements in shadow trees are always for <use> elements.
This amounted to an unneeded optimization that could be removed with no bad effect.

  • svg/SVGElement.cpp:

(WebCore::SVGElement::correspondingElement): Removed the assertions so this could
be used more freely outside of cases where the shadow tree state is fully consistent.
It's fine to have this just be a mechanical getter; there's nothing super-tricky
here that needs to be caught by the assertion.
(WebCore::SVGElement::title): Removed unneeded special handling for titles inside
the shadow tree.

  • svg/SVGGElement.cpp:

(WebCore::SVGGElement::create): Added an overload that doesn't require explicitly
passing in the tag name.

  • svg/SVGGElement.h: Ditto.
  • svg/SVGSVGElement.cpp:

(WebCore::SVGSVGElement::create): Ditto.

  • svg/SVGSVGElement.h: Ditto.
  • svg/SVGUseElement.cpp: Removed a lot of unneeded includes.

(WebCore::SVGUseElement::SVGUseElement): Removed code to initialize some booleans.
We do that in the class definition now.
(WebCore::SVGUseElement::create): Removed the code that calls the
ensureUserAgentShadowRoot function unconditionally. That's properly done when
needed; no need to do it here.
(WebCore::SVGUseElement::~SVGUseElement): Removed unneeded code to destroy the
shadow tree (that happens automatically) and simplified the code to stop loading
the external document.
(WebCore::SVGUseElement::isSupportedAttribute): Deleted.
(WebCore::SVGUseElement::parseAttribute): Simplified this. Removed assumptions
about the intersection of various sets of attributes, and also removed the
isSupportedAttribute function. This seems to serve no purpose here, or in any
other SVG element class. I plan to remove it everywhere over time.
(WebCore::isWellFormedDocument): Deleted.
(WebCore::SVGUseElement::insertedInto): Simplified code by removing all the
special cases during initial parsing, and did the invalidation here rather than
deferring it to didNotifySubtreeInsertions. Added a call to the new function,
updateExternalDocument, since that won't do anything when the element is not
in a document.
(WebCore::SVGUseElement::didNotifySubtreeInsertions): Deleted.
(WebCore::SVGUseElement::removedFrom): Added code to call clearShadowTree and
updateExternalDocument. Both are efficient when doing nothing, and both are
appropriate since the element is no longer in a document.
(WebCore::SVGUseElement::referencedDocument): Deleted. No longer needed.
(WebCore::SVGUseElement::externalDocument): Streamlined the logic here, removing
multiple unneeded checks.
(WebCore::SVGUseElement::transferSizeAttributesToTargetClone): Renamed since
"target clone" is clear enough within this class, without explicitly stating
"shadow tree". All the clones are in the shadow tree.
(WebCore::SVGUseElement::svgAttributeChanged): Removed unneeded code calling
isSupportedAttribute. Changed the code that detects changes in href to just
call updateExternalDocument (for the document URL) and invalidateShadowTree
(for the fragment). Also updated the transferSizeAttributesToTargetClone logic
to only trigger on width and height and updated names.
(WebCore::SVGUseElement::willAttachRenderers): Updated for the new name of
m_shouldRebuildShadowTree and added a call through to the base class.
(WebCore::createAllowedElementSet): Added. A more efficient way to implement
the initialization of the set for isDisallowedElement.
(WebCore::isDisallowedElement): Simplified this by using the function above,
and also overloaded for both SVGElement and Element for a tiny efficiency boost.
(WebCore::SVGUseElement::clearShadowTree): Renamed form clearResourceReferences.
This is a much more straightforward name. Also deleted the code that sets the
m_needsShadowTreeRecreation flag to false. That should be done by the build
function, not here.
(WebCore::SVGUseElement::buildPendingResource): Made this just invalidate the
shadow tree now instead of explicitly building it.
(WebCore::SVGUseElement::updateShadowTree): Moved the code to create a shadow
tree here from buildPendingResource. ALso changed the logic so that we
always blow away the old shadow tree. Moved the comment about rebuilding things
every time here. Updated the code to use the findTarget and cloneTarget functions,
eliminating the buildShadowTree function entirely. Moved the call to
transferSizeAttributesToShadowTreeTargetClone inside cloneTarget. Also updated
for the name change for m_shouldRebuildShadowTree.
(WebCore::SVGUseElement::targetClone): Renamed from shadowTreeTargetClone.
No need to emphasize "shadow tree" since that's where all clones are.
(WebCore::isDirectReference): Streamlined a bit using "using namespace".
(WebCore::SVGUseElement::toClipPath): Rewrote to use early return and updated
for name changes. Also used ASCIILiteral.
(WebCore::SVGUseElement::rendererClipChild): Changed local variable names.
(WebCore::removeDisallowedElementsFromSubtree): Wrote the iteration in a
slightly more idiomatic style.
(WebCore::SVGUseElement::findTarget): Added. This new function implements
the rule for finding a valid target for a use element. This replaces logic
that was duplicated in two different places and it also includes all the
rules that were formerly in the isValidTarget function. Also, this implements
a correct check for a cycle that handles cases the code in isValidTarget did not.
(WebCore::SVGUseElement::isValidTarget): Deleted.
(WebCore::SVGUseElement::cloneTarget): Added. Helper function used both when
cloning the target of the top level <use> elements and for other <use> elements
inside the shadow tree.
(WebCore::cloneDataAndChildren): Added. Helper function that allows both the
<use> and <symbol> element expanding functions to be shorter and share more code.
(WebCore::SVGUseElement::expandUseElementsInShadowTree): Removed unneeded checks
of cachedDocumentIsStillLoading. Used the new findTarget function, which handles
finding the target cross-document correctly. Removed the incorrect use of
referencedDocument when creating new elements and finding targets. Refactored
to use the new cloneDataAndChildren function and also moved the code that removes
the special attributes here, replacing the transferAttributesToShadowTreeReplacement
function. Made a few other simplifications.
(WebCore::SVGUseElement::expandSymbolElementsInShadowTree): Ditto, just like the
<use> changes only simpler.
(WebCore::SVGUseElement::transferEventListenersToShadowTree): Made this const.
Removed unneeded assertions.
(WebCore::SVGUseElement::invalidateShadowTree): Updated for name change.
(WebCore::SVGUseElement::invalidateDependentShadowTrees): Removed assertion.
(WebCore::SVGUseElement::transferAttributesToShadowTreeReplacement): Deleted.
(WebCore::SVGUseElement::selfHasRelativeLengths): Tweaked names.
(WebCore::SVGUseElement::notifyFinished): Removed the inDocument check, since
this function will only be called for elements that are in a document.
(WebCore::SVGUseElement::cachedDocumentIsStillLoading): Deleted.
(WebCore::SVGUseElement::finishParsingChildren): Removed the code that calls
buildPendingResource here. Shadow tree updating is driven solely by renderer
generation now.
(WebCore::SVGUseElement::updateExternalDocument): Replaced setCachedDocument
with this. This function knows how to load a different document if the URL
has changed, or leave it alone if not, and also stop the load if it should.
(WebCore::SVGUseElement::isValid): Moved this here from the header, since it's
always being called virtually.
(WebCore::SVGUseElement::haveLoadedRequiredResources): Ditto.
(WebCore::SVGUseElement::setHaveFiredLoadEvent): Ditto.
(WebCore::SVGUseElement::haveFiredLoadEvent): Ditto.
(WebCore::SVGUseElement::svgLoadEventTimer): Ditto.

  • svg/SVGUseElement.h: Removed unneeded include. Moved the animated properties

to the top of the class because they are public DOM API and so are logical to
list first. I'd like to do that for other classes too over time. Changed to
derive privately from CachedSVGDocumentClient. Made the function
invalidateDependentShadowTrees private. Removed didNotifySubtreeInsertions,
isSupportedAttribute, clearResourceReferences, buildShadowTree,
transferAttributesToShadowTreeReplacement, isParserInserted, and
m_wasInsertedByParser. Added updateExternalDocument, cloneTarget, targetClone,
updateShadowTree, and clearShadowTree. Also did a couple other renames,
including renaming m_cachedDocument to m_externalDocument.

  • svg/svgtags.in: Removed constructorNeedsCreatedByParser from the <use>

element since we don't have to handle constructing by the parser specially.

LayoutTests:

Modified some tests to be reference tests since the change in implementation slightly changed
the behavior, but not in a way that matters. Other similar updates.

  • TestExpectations: Expect a progression in imported/mozilla/svg/dynamic-use-02.svg.
  • platform/gtk/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.png: Removed.
  • platform/gtk/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.txt: Removed.
  • platform/gtk/svg/custom/use-property-synchronization-crash-expected.png: Removed.
  • platform/ios-sim-deprecated/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.txt: Removed.
  • platform/ios-simulator/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.txt: Removed.
  • platform/mac-mountainlion/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.txt: Removed.
  • platform/mac/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.png: Removed.
  • platform/mac/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.txt: Removed.
  • platform/mac/svg/custom/use-property-synchronization-crash-expected.png: Removed.
  • svg/animations/use-animate-width-and-height-expected.txt: Updated to expect the new expression

name from the modified test.

  • svg/animations/use-animate-width-and-height.html: THe state of the shadow root now depends on

layout, so force layout before inspecting it.

  • svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.xhtml: Added.
  • svg/custom/relative-sized-shadow-tree-content-with-symbol.xhtml: Made this no longer be a

repaint test. Not sure why we are using those in so many cases. Also made it be a reference test.

  • svg/custom/use-property-synchronization-crash-expected.svg: Added.
  • svg/custom/use-property-synchronization-crash-expected.txt: Removed.
Location:
trunk
Files:
2 added
10 deleted
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r179979 r179980  
     12015-02-11  Darin Adler  <darin@apple.com>
     2
     3        SVGUseElement follow-up improvements
     4        https://bugs.webkit.org/show_bug.cgi?id=141382
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Modified some tests to be reference tests since the change in implementation slightly changed
     9        the behavior, but not in a way that matters. Other similar updates.
     10
     11        * TestExpectations: Expect a progression in imported/mozilla/svg/dynamic-use-02.svg.
     12
     13        * platform/gtk/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.png: Removed.
     14        * platform/gtk/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.txt: Removed.
     15        * platform/gtk/svg/custom/use-property-synchronization-crash-expected.png: Removed.
     16        * platform/ios-sim-deprecated/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.txt: Removed.
     17        * platform/ios-simulator/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.txt: Removed.
     18        * platform/mac-mountainlion/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.txt: Removed.
     19        * platform/mac/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.png: Removed.
     20        * platform/mac/svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.txt: Removed.
     21        * platform/mac/svg/custom/use-property-synchronization-crash-expected.png: Removed.
     22
     23        * svg/animations/use-animate-width-and-height-expected.txt: Updated to expect the new expression
     24        name from the modified test.
     25        * svg/animations/use-animate-width-and-height.html: THe state of the shadow root now depends on
     26        layout, so force layout before inspecting it.
     27
     28        * svg/custom/relative-sized-shadow-tree-content-with-symbol-expected.xhtml: Added.
     29        * svg/custom/relative-sized-shadow-tree-content-with-symbol.xhtml: Made this no longer be a
     30        repaint test. Not sure why we are using those in so many cases. Also made it be a reference test.
     31
     32        * svg/custom/use-property-synchronization-crash-expected.svg: Added.
     33        * svg/custom/use-property-synchronization-crash-expected.txt: Removed.
     34
    1352015-02-11  Gyuyoung Kim  <gyuyoung.kim@samsung.com>
    236
  • trunk/LayoutTests/TestExpectations

    r179955 r179980  
    400400webkit.org/b/139155 imported/mozilla/svg/dynamic-pattern-01.svg [ ImageOnlyFailure ]
    401401webkit.org/b/139155 imported/mozilla/svg/dynamic-use-01.svg [ ImageOnlyFailure ]
    402 webkit.org/b/139155 imported/mozilla/svg/dynamic-use-02.svg [ ImageOnlyFailure ]
    403402webkit.org/b/139155 imported/mozilla/svg/dynamic-use-03.svg [ ImageOnlyFailure ]
    404403webkit.org/b/139155 imported/mozilla/svg/dynamic-use-07.svg [ ImageOnlyFailure ]
  • trunk/LayoutTests/svg/animations/use-animate-width-and-height-expected.txt

    r179069 r179980  
    1010PASS use.getAttribute('width') is '100'
    1111PASS use.getAttribute('height') is '100'
    12 PASS shadowRoot.firstChild.width.animVal.value is 100
    13 PASS shadowRoot.firstChild.height.animVal.value is 100
     12PASS useElementTargetClone().width.animVal.value is 100
     13PASS useElementTargetClone().height.animVal.value is 100
    1414PASS use.width.animVal.value is 105
    1515PASS use.width.baseVal.value is 100
     
    1818FAIL use.getAttribute('width') should be 105. Was 100.
    1919FAIL use.getAttribute('height') should be 105. Was 100.
    20 PASS shadowRoot.firstChild.width.animVal.value is 105
    21 PASS shadowRoot.firstChild.height.animVal.value is 105
     20PASS useElementTargetClone().width.animVal.value is 105
     21PASS useElementTargetClone().height.animVal.value is 105
    2222PASS use.width.animVal.value is 115
    2323PASS use.width.baseVal.value is 100
     
    2626FAIL use.getAttribute('width') should be 115. Was 100.
    2727FAIL use.getAttribute('height') should be 115. Was 100.
    28 PASS shadowRoot.firstChild.width.animVal.value is 115
    29 PASS shadowRoot.firstChild.height.animVal.value is 115
     28PASS useElementTargetClone().width.animVal.value is 115
     29PASS useElementTargetClone().height.animVal.value is 115
    3030PASS use.width.animVal.value is 125
    3131PASS use.width.baseVal.value is 100
     
    3434FAIL use.getAttribute('width') should be 125. Was 100.
    3535FAIL use.getAttribute('height') should be 125. Was 100.
    36 PASS shadowRoot.firstChild.width.animVal.value is 125
    37 PASS shadowRoot.firstChild.height.animVal.value is 125
     36PASS useElementTargetClone().width.animVal.value is 125
     37PASS useElementTargetClone().height.animVal.value is 125
    3838PASS use.width.animVal.value is 135
    3939PASS use.width.baseVal.value is 100
     
    4242FAIL use.getAttribute('width') should be 135. Was 100.
    4343FAIL use.getAttribute('height') should be 135. Was 100.
    44 PASS shadowRoot.firstChild.width.animVal.value is 135
    45 PASS shadowRoot.firstChild.height.animVal.value is 135
     44PASS useElementTargetClone().width.animVal.value is 135
     45PASS useElementTargetClone().height.animVal.value is 135
    4646PASS successfullyParsed is true
    4747
  • trunk/LayoutTests/svg/animations/use-animate-width-and-height.html

    r179069 r179980  
    5959use.appendChild(animate2);
    6060
    61 var shadowRoot = internals.shadowRoot(use);
     61function useElementTargetClone()
     62{
     63    document.body.offsetWidth;
     64    return internals.shadowRoot(use).firstChild;
     65}
    6266
    6367function sample1()
     
    7074    shouldBe("use.getAttribute('width')", "'100'");
    7175    shouldBe("use.getAttribute('height')", "'100'");
    72     shouldBe("shadowRoot.firstChild.width.animVal.value", "100");
    73     shouldBe("shadowRoot.firstChild.height.animVal.value", "100");
     76    shouldBe("useElementTargetClone().width.animVal.value", "100");
     77    shouldBe("useElementTargetClone().height.animVal.value", "100");
    7478}
    7579
     
    8286    shouldBe("use.getAttribute('width')", "'105'");
    8387    shouldBe("use.getAttribute('height')", "'105'");
    84     shouldBe("shadowRoot.firstChild.width.animVal.value", "105");
    85     shouldBe("shadowRoot.firstChild.height.animVal.value", "105");
     88    shouldBe("useElementTargetClone().width.animVal.value", "105");
     89    shouldBe("useElementTargetClone().height.animVal.value", "105");
    8690}
    8791
     
    9498    shouldBe("use.getAttribute('width')", "'115'");
    9599    shouldBe("use.getAttribute('height')", "'115'");
    96     shouldBe("shadowRoot.firstChild.width.animVal.value", "115");
    97     shouldBe("shadowRoot.firstChild.height.animVal.value", "115");
     100    shouldBe("useElementTargetClone().width.animVal.value", "115");
     101    shouldBe("useElementTargetClone().height.animVal.value", "115");
    98102}
    99103
     
    105109    shouldBe("use.getAttribute('width')", "'125'");
    106110    shouldBe("use.getAttribute('height')", "'125'");
    107     shouldBe("shadowRoot.firstChild.width.animVal.value", "125");
    108     shouldBe("shadowRoot.firstChild.height.animVal.value", "125");
     111    shouldBe("useElementTargetClone().width.animVal.value", "125");
     112    shouldBe("useElementTargetClone().height.animVal.value", "125");
    109113}
    110114
     
    117121    shouldBe("use.getAttribute('width')", "'135'");
    118122    shouldBe("use.getAttribute('height')", "'135'");
    119     shouldBe("shadowRoot.firstChild.width.animVal.value", "135");
    120     shouldBe("shadowRoot.firstChild.height.animVal.value", "135");
     123    shouldBe("useElementTargetClone().width.animVal.value", "135");
     124    shouldBe("useElementTargetClone().height.animVal.value", "135");
    121125}
    122126
  • trunk/LayoutTests/svg/custom/relative-sized-shadow-tree-content-with-symbol.xhtml

    r168350 r179980  
    11<html xmlns="http://www.w3.org/1999/xhtml">
    22<head>
    3 <script src="../../fast/repaint/resources/repaint.js"></script>
    43</head>
    5 <body onload="runRepaintTest()">
     4<body>
    65    <p>The svg area contained in the div element (red box), should fill out the whole area (two green rectangles, first: (0,0)-(50%,50%), second: (50%,50%)-(100%,100%)), especially after resizing the content box to a different size</p>
    76    <div id="contentBox" style="width: 100px; height: 400px; border: 1px solid red;">
     
    1716    </div>
    1817    <script>
    19         function repaintTest() {
    20             document.getElementById("contentBox").style.setProperty("width", "400px");
    21         }
     18        document.getElementById("contentBox").style.setProperty("width", "400px");
    2219    </script>
    2320</body>
  • trunk/Source/WebCore/ChangeLog

    r179978 r179980  
     12015-02-11  Darin Adler  <darin@apple.com>
     2
     3        SVGUseElement follow-up improvements
     4        https://bugs.webkit.org/show_bug.cgi?id=141382
     5
     6        Reviewed by Antti Koivisto.
     7
     8        * loader/cache/CachedSVGDocumentClient.h: Removed unneeded forward declaration.
     9
     10        * page/EventHandler.cpp: Removed unneeded include of SVGUseElement.h.
     11        * rendering/svg/RenderSVGViewportContainer.cpp: Ditto.
     12
     13        * svg/SVGDocumentExtensions.cpp:
     14        (WebCore::SVGDocumentExtensions::clearTargetDependencies): Removed too-specific
     15        check that assumed that SVG elements in shadow trees are always for <use> elements.
     16        This amounted to an unneeded optimization that could be removed with no bad effect.
     17
     18        * svg/SVGElement.cpp:
     19        (WebCore::SVGElement::correspondingElement): Removed the assertions so this could
     20        be used more freely outside of cases where the shadow tree state is fully consistent.
     21        It's fine to have this just be a mechanical getter; there's nothing super-tricky
     22        here that needs to be caught by the assertion.
     23        (WebCore::SVGElement::title): Removed unneeded special handling for titles inside
     24        the shadow tree.
     25
     26        * svg/SVGGElement.cpp:
     27        (WebCore::SVGGElement::create): Added an overload that doesn't require explicitly
     28        passing in the tag name.
     29        * svg/SVGGElement.h: Ditto.
     30        * svg/SVGSVGElement.cpp:
     31        (WebCore::SVGSVGElement::create): Ditto.
     32        * svg/SVGSVGElement.h: Ditto.
     33
     34        * svg/SVGUseElement.cpp: Removed a lot of unneeded includes.
     35        (WebCore::SVGUseElement::SVGUseElement): Removed code to initialize some booleans.
     36        We do that in the class definition now.
     37        (WebCore::SVGUseElement::create): Removed the code that calls the
     38        ensureUserAgentShadowRoot function unconditionally. That's properly done when
     39        needed; no need to do it here.
     40        (WebCore::SVGUseElement::~SVGUseElement): Removed unneeded code to destroy the
     41        shadow tree (that happens automatically) and simplified the code to stop loading
     42        the external document.
     43        (WebCore::SVGUseElement::isSupportedAttribute): Deleted.
     44        (WebCore::SVGUseElement::parseAttribute): Simplified this. Removed assumptions
     45        about the intersection of various sets of attributes, and also removed the
     46        isSupportedAttribute function. This seems to serve no purpose here, or in any
     47        other SVG element class. I plan to remove it everywhere over time.
     48        (WebCore::isWellFormedDocument): Deleted.
     49        (WebCore::SVGUseElement::insertedInto): Simplified code by removing all the
     50        special cases during initial parsing, and did the invalidation here rather than
     51        deferring it to didNotifySubtreeInsertions. Added a call to the new function,
     52        updateExternalDocument, since that won't do anything when the element is not
     53        in a document.
     54        (WebCore::SVGUseElement::didNotifySubtreeInsertions): Deleted.
     55        (WebCore::SVGUseElement::removedFrom): Added code to call clearShadowTree and
     56        updateExternalDocument. Both are efficient when doing nothing, and both are
     57        appropriate since the element is no longer in a document.
     58        (WebCore::SVGUseElement::referencedDocument): Deleted. No longer needed.
     59        (WebCore::SVGUseElement::externalDocument): Streamlined the logic here, removing
     60        multiple unneeded checks.
     61        (WebCore::SVGUseElement::transferSizeAttributesToTargetClone): Renamed since
     62        "target clone" is clear enough within this class, without explicitly stating
     63        "shadow tree". All the clones are in the shadow tree.
     64        (WebCore::SVGUseElement::svgAttributeChanged): Removed unneeded code calling
     65        isSupportedAttribute. Changed the code that detects changes in href to just
     66        call updateExternalDocument (for the document URL) and invalidateShadowTree
     67        (for the fragment). Also updated the transferSizeAttributesToTargetClone logic
     68        to only trigger on width and height and updated names.
     69        (WebCore::SVGUseElement::willAttachRenderers): Updated for the new name of
     70        m_shouldRebuildShadowTree and added a call through to the base class.
     71        (WebCore::createAllowedElementSet): Added. A more efficient way to implement
     72        the initialization of the set for isDisallowedElement.
     73        (WebCore::isDisallowedElement): Simplified this by using the function above,
     74        and also overloaded for both SVGElement and Element for a tiny efficiency boost.
     75        (WebCore::SVGUseElement::clearShadowTree): Renamed form clearResourceReferences.
     76        This is a much more straightforward name. Also deleted the code that sets the
     77        m_needsShadowTreeRecreation flag to false. That should be done by the build
     78        function, not here.
     79        (WebCore::SVGUseElement::buildPendingResource): Made this just invalidate the
     80        shadow tree now instead of explicitly building it.
     81        (WebCore::SVGUseElement::updateShadowTree): Moved the code to create a shadow
     82        tree here from buildPendingResource. ALso changed the logic so that we
     83        always blow away the old shadow tree. Moved the comment about rebuilding things
     84        every time here. Updated the code to use the findTarget and cloneTarget functions,
     85        eliminating the buildShadowTree function entirely. Moved the call to
     86        transferSizeAttributesToShadowTreeTargetClone inside cloneTarget. Also updated
     87        for the name change for m_shouldRebuildShadowTree.
     88        (WebCore::SVGUseElement::targetClone): Renamed from shadowTreeTargetClone.
     89        No need to emphasize "shadow tree" since that's where all clones are.
     90        (WebCore::isDirectReference): Streamlined a bit using "using namespace".
     91        (WebCore::SVGUseElement::toClipPath): Rewrote to use early return and updated
     92        for name changes. Also used ASCIILiteral.
     93        (WebCore::SVGUseElement::rendererClipChild): Changed local variable names.
     94        (WebCore::removeDisallowedElementsFromSubtree): Wrote the iteration in a
     95        slightly more idiomatic style.
     96        (WebCore::SVGUseElement::findTarget): Added. This new function implements
     97        the rule for finding a valid target for a use element. This replaces logic
     98        that was duplicated in two different places and it also includes all the
     99        rules that were formerly in the isValidTarget function. Also, this implements
     100        a correct check for a cycle that handles cases the code in isValidTarget did not.
     101        (WebCore::SVGUseElement::isValidTarget): Deleted.
     102        (WebCore::SVGUseElement::cloneTarget): Added. Helper function used both when
     103        cloning the target of the top level <use> elements and for other <use> elements
     104        inside the shadow tree.
     105        (WebCore::cloneDataAndChildren): Added. Helper function that allows both the
     106        <use> and <symbol> element expanding functions to be shorter and share more code.
     107        (WebCore::SVGUseElement::expandUseElementsInShadowTree): Removed unneeded checks
     108        of cachedDocumentIsStillLoading. Used the new findTarget function, which handles
     109        finding the target cross-document correctly. Removed the incorrect use of
     110        referencedDocument when creating new elements and finding targets. Refactored
     111        to use the new cloneDataAndChildren function and also moved the code that removes
     112        the special attributes here, replacing the transferAttributesToShadowTreeReplacement
     113        function. Made a few other simplifications.
     114        (WebCore::SVGUseElement::expandSymbolElementsInShadowTree): Ditto, just like the
     115        <use> changes only simpler.
     116        (WebCore::SVGUseElement::transferEventListenersToShadowTree): Made this const.
     117        Removed unneeded assertions.
     118        (WebCore::SVGUseElement::invalidateShadowTree): Updated for name change.
     119        (WebCore::SVGUseElement::invalidateDependentShadowTrees): Removed assertion.
     120        (WebCore::SVGUseElement::transferAttributesToShadowTreeReplacement): Deleted.
     121        (WebCore::SVGUseElement::selfHasRelativeLengths): Tweaked names.
     122        (WebCore::SVGUseElement::notifyFinished): Removed the inDocument check, since
     123        this function will only be called for elements that are in a document.
     124        (WebCore::SVGUseElement::cachedDocumentIsStillLoading): Deleted.
     125        (WebCore::SVGUseElement::finishParsingChildren): Removed the code that calls
     126        buildPendingResource here. Shadow tree updating is driven solely by renderer
     127        generation now.
     128        (WebCore::SVGUseElement::updateExternalDocument): Replaced setCachedDocument
     129        with this. This function knows how to load a different document if the URL
     130        has changed, or leave it alone if not, and also stop the load if it should.
     131        (WebCore::SVGUseElement::isValid): Moved this here from the header, since it's
     132        always being called virtually.
     133        (WebCore::SVGUseElement::haveLoadedRequiredResources): Ditto.
     134        (WebCore::SVGUseElement::setHaveFiredLoadEvent): Ditto.
     135        (WebCore::SVGUseElement::haveFiredLoadEvent): Ditto.
     136        (WebCore::SVGUseElement::svgLoadEventTimer): Ditto.
     137
     138        * svg/SVGUseElement.h: Removed unneeded include. Moved the animated properties
     139        to the top of the class because they are public DOM API and so are logical to
     140        list first. I'd like to do that for other classes too over time. Changed to
     141        derive privately from CachedSVGDocumentClient. Made the function
     142        invalidateDependentShadowTrees private. Removed didNotifySubtreeInsertions,
     143        isSupportedAttribute, clearResourceReferences, buildShadowTree,
     144        transferAttributesToShadowTreeReplacement, isParserInserted, and
     145        m_wasInsertedByParser. Added updateExternalDocument, cloneTarget, targetClone,
     146        updateShadowTree, and clearShadowTree. Also did a couple other renames,
     147        including renaming m_cachedDocument to m_externalDocument.
     148
     149        * svg/svgtags.in: Removed constructorNeedsCreatedByParser from the <use>
     150        element since we don't have to handle constructing by the parser specially.
     151
    11522015-02-11  Dhi Aurrahman  <diorahman@rockybars.com>
    2153
  • trunk/Source/WebCore/loader/cache/CachedSVGDocumentClient.h

    r163440 r179980  
    2828namespace WebCore {
    2929
    30 class CachedSVGDocument;
    31 
    3230class CachedSVGDocumentClient : public CachedResourceClient {
    3331public:
  • trunk/Source/WebCore/page/EventHandler.cpp

    r179810 r179980  
    8282#include "SVGDocument.h"
    8383#include "SVGNames.h"
    84 #include "SVGUseElement.h"
    8584#include "ScrollAnimator.h"
    8685#include "ScrollLatchingState.h"
  • trunk/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp

    r179810 r179980  
    2828#include "SVGNames.h"
    2929#include "SVGSVGElement.h"
    30 #include "SVGUseElement.h"
    3130
    3231namespace WebCore {
  • trunk/Source/WebCore/svg/SVGDocumentExtensions.cpp

    r179599 r179980  
    342342void SVGDocumentExtensions::clearTargetDependencies(SVGElement& referencedElement)
    343343{
    344     if (referencedElement.isInShadowTree()) {
    345         // The host element (e.g. <use>) of the shadow root will rebuild the shadow tree
    346         // and all its references.
    347         ASSERT(referencedElement.shadowRoot());
    348         ASSERT(m_rebuildElements.contains(referencedElement.shadowRoot()->hostElement()));
    349         return;
    350     }
    351344    auto it = m_elementDependencies.find(&referencedElement);
    352345    if (it == m_elementDependencies.end())
  • trunk/Source/WebCore/svg/SVGElement.cpp

    r179829 r179980  
    483483SVGElement* SVGElement::correspondingElement() const
    484484{
    485     ASSERT(!m_svgRareData || !m_svgRareData->correspondingElement() || correspondingUseElement());
    486485    return m_svgRareData ? m_svgRareData->correspondingElement() : nullptr;
    487486}
     
    967966    if (isOutermostSVGSVGElement() && document().topDocument().isSVGDocument())
    968967        return String();
    969 
    970     // Walk up the tree, to find out whether we're inside a <use> shadow tree, to find the right title.
    971     if (isInShadowTree()) {
    972         Element* shadowHostElement = downcast<ShadowRoot>(treeScope().rootNode()).hostElement();
    973         // At this time, SVG nodes are not allowed in non-<use> shadow trees, so any shadow root we do
    974         // have should be a use. The assert and following test is here to catch future shadow DOM changes
    975         // that do enable SVG in a shadow tree.
    976         ASSERT(!shadowHostElement || shadowHostElement->hasTagName(SVGNames::useTag));
    977         if (shadowHostElement && shadowHostElement->hasTagName(SVGNames::useTag)) {
    978             SVGUseElement& useElement = downcast<SVGUseElement>(*shadowHostElement);
    979 
    980             // If the <use> title is not empty we found the title to use.
    981             String useTitle(useElement.title());
    982             if (!useTitle.isEmpty())
    983                 return useTitle;
    984         }
    985     }
    986 
    987     // If we aren't an instance in a <use> or the <use> title was not found, then find the first
    988     // <title> child of this element.
    989968    auto firstTitle = childrenOfType<SVGTitleElement>(*this).first();
    990969    return firstTitle ? const_cast<SVGTitleElement*>(firstTitle)->innerText() : String();
  • trunk/Source/WebCore/svg/SVGGElement.cpp

    r179810 r179980  
    4848{
    4949    return adoptRef(*new SVGGElement(tagName, document));
     50}
     51
     52Ref<SVGGElement> SVGGElement::create(Document& document)
     53{
     54    return create(SVGNames::gTag, document);
    5055}
    5156
  • trunk/Source/WebCore/svg/SVGGElement.h

    r178048 r179980  
    3232public:
    3333    static Ref<SVGGElement> create(const QualifiedName&, Document&);
     34    static Ref<SVGGElement> create(Document&);
    3435
    3536private:
  • trunk/Source/WebCore/svg/SVGSVGElement.cpp

    r179810 r179980  
    100100}
    101101
     102Ref<SVGSVGElement> SVGSVGElement::create(Document& document)
     103{
     104    return create(SVGNames::svgTag, document);
     105}
     106
    102107SVGSVGElement::~SVGSVGElement()
    103108{
  • trunk/Source/WebCore/svg/SVGSVGElement.h

    r178048 r179980  
    4646public:
    4747    static Ref<SVGSVGElement> create(const QualifiedName&, Document&);
     48    static Ref<SVGSVGElement> create(Document&);
    4849
    4950    using SVGGraphicsElement::ref;
  • trunk/Source/WebCore/svg/SVGUseElement.cpp

    r179810 r179980  
    2828
    2929#include "CachedResourceLoader.h"
    30 #include "CachedResourceRequest.h"
    3130#include "CachedSVGDocument.h"
    32 #include "Document.h"
    3331#include "ElementIterator.h"
    3432#include "Event.h"
    35 #include "EventListener.h"
    36 #include "HTMLNames.h"
    37 #include "NodeRenderStyle.h"
    38 #include "RegisteredEventListener.h"
    3933#include "RenderSVGResource.h"
    4034#include "RenderSVGTransformableContainer.h"
    4135#include "ShadowRoot.h"
    42 #include "SVGElementRareData.h"
    4336#include "SVGGElement.h"
    44 #include "SVGLengthContext.h"
    45 #include "SVGNames.h"
    46 #include "SVGSMILElement.h"
    4737#include "SVGSVGElement.h"
    4838#include "SVGSymbolElement.h"
    49 #include "StyleResolver.h"
    5039#include "XLinkNames.h"
    51 #include "XMLDocumentParser.h"
    52 #include "XMLSerializer.h"
    53 #include <wtf/NeverDestroyed.h>
    5440
    5541namespace WebCore {
    5642
    57 // Animated property definitions
    5843DEFINE_ANIMATED_LENGTH(SVGUseElement, SVGNames::xAttr, X, x)
    5944DEFINE_ANIMATED_LENGTH(SVGUseElement, SVGNames::yAttr, Y, y)
     
    7358END_REGISTER_ANIMATED_PROPERTIES
    7459
    75 inline SVGUseElement::SVGUseElement(const QualifiedName& tagName, Document& document, bool wasInsertedByParser)
     60inline SVGUseElement::SVGUseElement(const QualifiedName& tagName, Document& document)
    7661    : SVGGraphicsElement(tagName, document)
    7762    , m_x(LengthModeWidth)
     
    7964    , m_width(LengthModeWidth)
    8065    , m_height(LengthModeHeight)
    81     , m_wasInsertedByParser(wasInsertedByParser)
    82     , m_haveFiredLoadEvent(false)
    83     , m_needsShadowTreeRecreation(false)
    8466    , m_svgLoadEventTimer(*this, &SVGElement::svgLoadEventTimerFired)
    8567{
     
    8971}
    9072
    91 Ref<SVGUseElement> SVGUseElement::create(const QualifiedName& tagName, Document& document, bool wasInsertedByParser)
    92 {
    93     // Always build a #shadow-root for SVGUseElement.
    94     Ref<SVGUseElement> use = adoptRef(*new SVGUseElement(tagName, document, wasInsertedByParser));
    95     use->ensureUserAgentShadowRoot();
    96     return use;
     73Ref<SVGUseElement> SVGUseElement::create(const QualifiedName& tagName, Document& document)
     74{
     75    return adoptRef(*new SVGUseElement(tagName, document));
    9776}
    9877
    9978SVGUseElement::~SVGUseElement()
    10079{
    101     setCachedDocument(0);
    102 
    103     clearResourceReferences();
    104 }
    105 
    106 bool SVGUseElement::isSupportedAttribute(const QualifiedName& attrName)
    107 {
    108     static NeverDestroyed<HashSet<QualifiedName>> supportedAttributes;
    109     if (supportedAttributes.get().isEmpty()) {
    110         SVGLangSpace::addSupportedAttributes(supportedAttributes);
    111         SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes);
    112         SVGURIReference::addSupportedAttributes(supportedAttributes);
    113         supportedAttributes.get().add(SVGNames::xAttr);
    114         supportedAttributes.get().add(SVGNames::yAttr);
    115         supportedAttributes.get().add(SVGNames::widthAttr);
    116         supportedAttributes.get().add(SVGNames::heightAttr);
    117     }
    118     return supportedAttributes.get().contains<SVGAttributeHashTranslator>(attrName);
     80    if (m_externalDocument)
     81        m_externalDocument->removeClient(this);
    11982}
    12083
     
    12386    SVGParsingError parseError = NoError;
    12487
    125     if (!isSupportedAttribute(name))
    126         SVGGraphicsElement::parseAttribute(name, value);
    127     else if (name == SVGNames::xAttr)
     88    if (name == SVGNames::xAttr)
    12889        setXBaseValue(SVGLength::construct(LengthModeWidth, value, parseError));
    12990    else if (name == SVGNames::yAttr)
     
    13394    else if (name == SVGNames::heightAttr)
    13495        setHeightBaseValue(SVGLength::construct(LengthModeHeight, value, parseError, ForbidNegativeLengths));
    135     else if (SVGLangSpace::parseAttribute(name, value)
    136              || SVGExternalResourcesRequired::parseAttribute(name, value)
    137              || SVGURIReference::parseAttribute(name, value)) {
    138     } else
    139         ASSERT_NOT_REACHED();
    14096
    14197    reportAttributeParsingError(parseError, name, value);
    142 }
    143 
    144 #if !ASSERT_DISABLED
    145 static inline bool isWellFormedDocument(Document& document)
    146 {
    147     if (document.isSVGDocument() || document.isXHTMLDocument())
    148         return static_cast<XMLDocumentParser*>(document.parser())->wellFormed();
    149     return true;
    150 }
    151 #endif
     98
     99    SVGExternalResourcesRequired::parseAttribute(name, value);
     100    SVGGraphicsElement::parseAttribute(name, value);
     101    SVGLangSpace::parseAttribute(name, value);
     102    SVGURIReference::parseAttribute(name, value);
     103}
    152104
    153105Node::InsertionNotificationRequest SVGUseElement::insertedInto(ContainerNode& rootParent)
    154106{
    155107    SVGGraphicsElement::insertedInto(rootParent);
    156     if (!rootParent.inDocument())
    157         return InsertionDone;
    158     ASSERT(!hasPendingResources() || !isWellFormedDocument(document()));
    159     SVGExternalResourcesRequired::insertedIntoDocument(this);
    160     if (!m_wasInsertedByParser)
    161         return InsertionShouldCallDidNotifySubtreeInsertions;
     108    if (inDocument()) {
     109        SVGExternalResourcesRequired::insertedIntoDocument(this);
     110        invalidateShadowTree();
     111        updateExternalDocument();
     112    }
    162113    return InsertionDone;
    163114}
    164115
    165 void SVGUseElement::didNotifySubtreeInsertions(ContainerNode*)
    166 {
    167     buildPendingResource();
    168 }
    169 
    170116void SVGUseElement::removedFrom(ContainerNode& rootParent)
    171117{
    172118    SVGGraphicsElement::removedFrom(rootParent);
    173     if (rootParent.inDocument())
    174         clearResourceReferences();
    175 }
    176 
    177 Document* SVGUseElement::referencedDocument() const
    178 {
    179     if (!isExternalURIReference(href(), document()))
    180         return &document();
    181     return externalDocument();
    182 }
    183 
    184 Document* SVGUseElement::externalDocument() const
    185 {
    186     if (m_cachedDocument && m_cachedDocument->isLoaded()) {
    187         // Gracefully handle error condition.
    188         if (m_cachedDocument->errorOccurred())
    189             return 0;
    190         ASSERT(m_cachedDocument->document());
    191         return m_cachedDocument->document();
    192     }
    193     return 0;
    194 }
    195 
    196 void SVGUseElement::transferSizeAttributesToShadowTreeTargetClone(SVGElement& shadowElement) const
     119    clearShadowTree();
     120    updateExternalDocument();
     121}
     122
     123inline Document* SVGUseElement::externalDocument() const
     124{
     125    return m_externalDocument ? m_externalDocument->document() : nullptr;
     126}
     127
     128void SVGUseElement::transferSizeAttributesToTargetClone(SVGElement& shadowElement) const
    197129{
    198130    // FIXME: The check for valueInSpecifiedUnits being non-zero below is a workaround for the fact
     
    216148void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName)
    217149{
    218     if (!isSupportedAttribute(attrName)) {
    219         SVGGraphicsElement::svgAttributeChanged(attrName);
    220         return;
    221     }
    222 
    223150    InstanceInvalidationGuard guard(*this);
    224151
    225152    if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr || attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr) {
    226153        updateRelativeLengthsInformation();
    227         if (SVGElement* shadowTreeTargetClone = this->shadowTreeTargetClone()) {
    228             // FIXME: It's unnecessarily inefficient to do this work any time we change "x" or "y".
     154        if (attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr) {
    229155            // FIXME: It's unnecessarily inefficient to update both width and height each time either is changed.
    230             transferSizeAttributesToShadowTreeTargetClone(*shadowTreeTargetClone);
     156            if (auto* targetClone = this->targetClone())
     157                transferSizeAttributesToTargetClone(*targetClone);
    231158        }
    232159        if (auto* renderer = this->renderer())
     
    239166
    240167    if (SVGURIReference::isKnownAttribute(attrName)) {
    241         bool isExternalReference = isExternalURIReference(href(), document());
    242         if (isExternalReference) {
    243             URL url = document().completeURL(href());
    244             if (url.hasFragmentIdentifier()) {
    245                 CachedResourceRequest request(ResourceRequest(url.string()));
    246                 request.setInitiator(this);
    247                 setCachedDocument(document().cachedResourceLoader().requestSVGDocument(request));
    248             }
    249         } else
    250             setCachedDocument(0);
    251 
    252         if (!m_wasInsertedByParser)
    253             buildPendingResource();
    254 
    255         return;
    256     }
    257 
    258     if (SVGLangSpace::isKnownAttribute(attrName)
    259         || SVGExternalResourcesRequired::isKnownAttribute(attrName)) {
     168        updateExternalDocument();
    260169        invalidateShadowTree();
    261170        return;
    262171    }
    263172
    264     ASSERT_NOT_REACHED();
     173    if (SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName)) {
     174        invalidateShadowTree();
     175        return;
     176    }
     177
     178    SVGGraphicsElement::svgAttributeChanged(attrName);
    265179}
    266180
    267181void SVGUseElement::willAttachRenderers()
    268182{
    269     if (m_needsShadowTreeRecreation)
    270         buildPendingResource();
    271 }
    272 
    273 static bool isDisallowedElement(const Element& element)
     183    if (m_shadowTreeNeedsUpdate)
     184        updateShadowTree();
     185    SVGGraphicsElement::willAttachRenderers();
     186}
     187
     188static HashSet<AtomicString> createAllowedElementSet()
    274189{
    275190    // Spec: "Any 'svg', 'symbol', 'g', graphics element or other 'use' is potentially a template object that can be re-used
     
    277192    // "Graphics Element" is defined as 'circle', 'ellipse', 'image', 'line', 'path', 'polygon', 'polyline', 'rect', 'text'
    278193    // Excluded are anything that is used by reference or that only make sense to appear once in a document.
    279 
    280     if (!element.isSVGElement())
    281         return true;
    282 
    283     static NeverDestroyed<HashSet<QualifiedName>> allowedElementTags;
    284     if (allowedElementTags.get().isEmpty()) {
    285         allowedElementTags.get().add(SVGNames::aTag);
    286         allowedElementTags.get().add(SVGNames::circleTag);
    287         allowedElementTags.get().add(SVGNames::descTag);
    288         allowedElementTags.get().add(SVGNames::ellipseTag);
    289         allowedElementTags.get().add(SVGNames::gTag);
    290         allowedElementTags.get().add(SVGNames::imageTag);
    291         allowedElementTags.get().add(SVGNames::lineTag);
    292         allowedElementTags.get().add(SVGNames::metadataTag);
    293         allowedElementTags.get().add(SVGNames::pathTag);
    294         allowedElementTags.get().add(SVGNames::polygonTag);
    295         allowedElementTags.get().add(SVGNames::polylineTag);
    296         allowedElementTags.get().add(SVGNames::rectTag);
    297         allowedElementTags.get().add(SVGNames::svgTag);
    298         allowedElementTags.get().add(SVGNames::switchTag);
    299         allowedElementTags.get().add(SVGNames::symbolTag);
    300         allowedElementTags.get().add(SVGNames::textTag);
    301         allowedElementTags.get().add(SVGNames::textPathTag);
    302         allowedElementTags.get().add(SVGNames::titleTag);
    303         allowedElementTags.get().add(SVGNames::trefTag);
    304         allowedElementTags.get().add(SVGNames::tspanTag);
    305         allowedElementTags.get().add(SVGNames::useTag);
    306     }
    307     return !allowedElementTags.get().contains<SVGAttributeHashTranslator>(element.tagQName());
    308 }
    309 
    310 void SVGUseElement::clearResourceReferences()
    311 {
     194    using namespace SVGNames;
     195    HashSet<AtomicString> set;
     196    for (auto& tag : { aTag, circleTag, descTag, ellipseTag, gTag, imageTag, lineTag, metadataTag, pathTag, polygonTag, polylineTag, rectTag, svgTag, switchTag, symbolTag, textTag, textPathTag, titleTag, trefTag, tspanTag, useTag })
     197        set.add(tag.localName());
     198    return set;
     199}
     200
     201static inline bool isDisallowedElement(const SVGElement& element)
     202{
     203    static NeverDestroyed<HashSet<AtomicString>> set = createAllowedElementSet();
     204    return !set.get().contains(element.localName());
     205}
     206
     207static inline bool isDisallowedElement(const Element& element)
     208{
     209    return !element.isSVGElement() || isDisallowedElement(downcast<SVGElement>(element));
     210}
     211
     212void SVGUseElement::clearShadowTree()
     213{
     214    if (auto* root = userAgentShadowRoot())
     215        root->removeChildren();
     216}
     217
     218void SVGUseElement::buildPendingResource()
     219{
     220    invalidateShadowTree();
     221}
     222
     223void SVGUseElement::updateShadowTree()
     224{
     225    m_shadowTreeNeedsUpdate = false;
     226
    312227    // FIXME: It's expensive to re-clone the entire tree every time. We should find a more efficient way to handle this.
    313     if (ShadowRoot* root = userAgentShadowRoot())
    314         root->removeChildren();
    315     m_needsShadowTreeRecreation = false;
    316 }
    317 
    318 void SVGUseElement::buildPendingResource()
    319 {
    320     if (isInShadowTree())
    321         return;
    322     if (!referencedDocument())
    323         return;
    324     clearResourceReferences();
    325     if (!inDocument())
    326         return;
    327 
    328     String id;
    329     Element* target = SVGURIReference::targetElementFromIRIString(href(), document(), &id, externalDocument());
    330     if (!isValidTarget(target)) {
    331         if (externalDocument()) {
    332             // We can't find the target in an external document, so just give up and don't try to do it again.
    333             // We should not attempt to observe if an element with ID shows up in the external document later.
    334             return;
    335         }
    336         referencedDocument()->accessSVGExtensions().addPendingResource(id, this);
    337         return;
    338     }
    339 
    340     buildShadowTree(downcast<SVGElement>(*target));
     228    clearShadowTree();
     229
     230    if (isInShadowTree() || !inDocument())
     231        return;
     232
     233    String targetID;
     234    auto* target = findTarget(&targetID);
     235    if (!target) {
     236        document().accessSVGExtensions().addPendingResource(targetID, this);
     237        return;
     238    }
     239
     240    cloneTarget(ensureUserAgentShadowRoot(), *target);
    341241    expandUseElementsInShadowTree();
    342242    expandSymbolElementsInShadowTree();
    343     transferSizeAttributesToShadowTreeTargetClone(*shadowTreeTargetClone());
    344243    transferEventListenersToShadowTree();
     244
    345245    updateRelativeLengthsInformation();
    346246
    347247    // When we invalidate the other shadow trees, it's important that we don't
    348248    // follow any cycles and invalidate ourselves. To avoid that, we temporarily
    349     // set m_needsShadowTreeRecreation to true so invalidateShadowTree will
     249    // set m_shadowTreeNeedsUpdate to true so invalidateShadowTree will
    350250    // quickly return and do nothing.
    351     ASSERT(!m_needsShadowTreeRecreation);
    352     m_needsShadowTreeRecreation = true;
     251    ASSERT(!m_shadowTreeNeedsUpdate);
     252    m_shadowTreeNeedsUpdate = true;
    353253    invalidateDependentShadowTrees();
    354     m_needsShadowTreeRecreation = false;
    355 }
    356 
    357 SVGElement* SVGUseElement::shadowTreeTargetClone() const
     254    m_shadowTreeNeedsUpdate = false;
     255}
     256
     257SVGElement* SVGUseElement::targetClone() const
    358258{
    359259    auto* root = userAgentShadowRoot();
     
    370270static bool isDirectReference(const SVGElement& element)
    371271{
    372     return element.hasTagName(SVGNames::pathTag)
    373         || element.hasTagName(SVGNames::rectTag)
    374         || element.hasTagName(SVGNames::circleTag)
    375         || element.hasTagName(SVGNames::ellipseTag)
    376         || element.hasTagName(SVGNames::polygonTag)
    377         || element.hasTagName(SVGNames::polylineTag)
    378         || element.hasTagName(SVGNames::textTag);
     272    using namespace SVGNames;
     273    return element.hasTagName(circleTag)
     274        || element.hasTagName(ellipseTag)
     275        || element.hasTagName(pathTag)
     276        || element.hasTagName(polygonTag)
     277        || element.hasTagName(polylineTag)
     278        || element.hasTagName(rectTag)
     279        || element.hasTagName(textTag);
    379280}
    380281
     
    383284    ASSERT(path.isEmpty());
    384285
    385     SVGElement* element = shadowTreeTargetClone();
    386     if (is<SVGGraphicsElement>(element)) {
    387         if (!isDirectReference(*element)) {
    388             // Spec: Indirect references are an error (14.3.5)
    389             document().accessSVGExtensions().reportError("Not allowed to use indirect reference in <clip-path>");
    390         } else {
    391             downcast<SVGGraphicsElement>(*element).toClipPath(path);
    392             // FIXME: Avoid manual resolution of x/y here. Its potentially harmful.
    393             SVGLengthContext lengthContext(this);
    394             path.translate(FloatSize(x().value(lengthContext), y().value(lengthContext)));
    395             path.transform(animatedLocalTransform());
    396         }
    397     }
     286    auto* targetClone = this->targetClone();
     287    if (!is<SVGGraphicsElement>(targetClone))
     288        return;
     289
     290    if (!isDirectReference(*targetClone)) {
     291        // Spec: Indirect references are an error (14.3.5)
     292        document().accessSVGExtensions().reportError(ASCIILiteral("Not allowed to use indirect reference in <clip-path>"));
     293        return;
     294    }
     295
     296    downcast<SVGGraphicsElement>(*targetClone).toClipPath(path);
     297    SVGLengthContext lengthContext(this);
     298    // FIXME: Find a way to do this without manual resolution of x/y here. It's potentially incorrect.
     299    path.translate(FloatSize(x().value(lengthContext), y().value(lengthContext)));
     300    path.transform(animatedLocalTransform());
    398301}
    399302
    400303RenderElement* SVGUseElement::rendererClipChild() const
    401304{
    402     auto* element = shadowTreeTargetClone();
    403     if (!element)
     305    auto* targetClone = this->targetClone();
     306    if (!targetClone)
    404307        return nullptr;
    405     if (!isDirectReference(*element))
     308    if (!isDirectReference(*targetClone))
    406309        return nullptr;
    407     return element->renderer();
     310    return targetClone->renderer();
    408311}
    409312
     
    420323    Vector<Element*> disallowedElements;
    421324    auto descendants = descendantsOfType<Element>(subtree);
    422     auto end = descendants.end();
    423     for (auto it = descendants.begin(); it != end; ) {
     325    for (auto it = descendants.begin(), end = descendants.end(); it != end; ) {
    424326        if (isDisallowedElement(*it)) {
    425327            disallowedElements.append(&*it);
     
    429331        ++it;
    430332    }
    431     for (Element* element : disallowedElements)
     333    for (auto* element : disallowedElements)
    432334        element->parentNode()->removeChild(element);
    433335}
     
    448350static void associateReplacementCloneWithOriginal(SVGElement& replacementClone, SVGElement& originalClone)
    449351{
    450     SVGElement* correspondingElement = originalClone.correspondingElement();
     352    auto* correspondingElement = originalClone.correspondingElement();
    451353    ASSERT(correspondingElement);
    452354    originalClone.setCorrespondingElement(nullptr);
     
    467369}
    468370
    469 void SVGUseElement::buildShadowTree(SVGElement& target)
    470 {
    471     Ref<SVGElement> clonedTarget = static_pointer_cast<SVGElement>(target.cloneElementWithChildren(document())).releaseNonNull();
    472     associateClonesWithOriginals(clonedTarget.get(), target);
    473     removeDisallowedElementsFromSubtree(clonedTarget.get());
    474     ensureUserAgentShadowRoot().appendChild(WTF::move(clonedTarget));
    475 }
    476 
    477 bool SVGUseElement::isValidTarget(Element* target) const
    478 {
    479     if (!is<SVGElement>(target))
    480         return false;
    481     if (!target->inDocument())
    482         return false;
    483     SVGElement& castedTarget = downcast<SVGElement>(*target);
    484     if (&castedTarget == this)
    485         return false;
    486     if (isDisallowedElement(castedTarget))
    487         return false;
    488     // Reject any target that would create a cycle.
    489     for (auto& ancestor : lineageOfType<SVGElement>(*this)) {
    490         if (ancestor.correspondingElement() == &castedTarget)
    491             return false;
    492     }
    493     return true;
    494 }
    495 
    496 void SVGUseElement::expandUseElementsInShadowTree()
    497 {
    498     // FIXME: Combine this with buildShadowTree.
    499 
    500     if (cachedDocumentIsStillLoading())
    501         return;
    502 
     371SVGElement* SVGUseElement::findTarget(String* targetID) const
     372{
     373    auto* correspondingElement = this->correspondingElement();
     374    auto& original = correspondingElement ? downcast<SVGUseElement>(*correspondingElement) : *this;
     375
     376    auto* targetCandidate = targetElementFromIRIString(original.href(), original.document(), targetID, original.externalDocument());
     377    if (targetID && !targetID->isNull()) {
     378        // If the reference is external, don't return the target ID to the caller.
     379        // The caller would use the target ID to wait for a pending resource on the wrong document.
     380        // If we ever want the change that and let the caller to wait on the external document,
     381        // we should change this function so it returns the appropriate document to go with the ID.
     382        if (isExternalURIReference(original.href(), original.document()))
     383            *targetID = String();
     384    }
     385    if (!is<SVGElement>(targetCandidate))
     386        return nullptr;
     387    auto& target = downcast<SVGElement>(*targetCandidate);
     388
     389    if (!target.inDocument() || isDisallowedElement(target))
     390        return nullptr;
     391
     392    // Reject any target that has already been cloned to create one of the ancestors of this element,
     393    // already in the shadow tree. This is sufficient to prevent cycles.
     394    if (correspondingElement) {
     395        for (auto& ancestor : lineageOfType<SVGElement>(*this)) {
     396            if (ancestor.correspondingElement() == &target)
     397                return nullptr;
     398        }
     399    }
     400
     401    return &target;
     402}
     403
     404void SVGUseElement::cloneTarget(ContainerNode& container, SVGElement& target) const
     405{
     406    Ref<SVGElement> targetClone = static_pointer_cast<SVGElement>(target.cloneElementWithChildren(document())).releaseNonNull();
     407    associateClonesWithOriginals(targetClone.get(), target);
     408    removeDisallowedElementsFromSubtree(targetClone.get());
     409    transferSizeAttributesToTargetClone(targetClone.get());
     410    container.appendChild(WTF::move(targetClone));
     411}
     412
     413static void cloneDataAndChildren(SVGElement& replacementClone, SVGElement& originalClone)
     414{
     415    // This assertion checks that we don't call this with the arguments backwards.
     416    // The replacement clone is new and so it's not installed in a parent yet.
     417    ASSERT(!replacementClone.parentNode());
     418
     419    replacementClone.cloneDataFromElement(originalClone);
     420    originalClone.cloneChildNodes(&replacementClone);
     421    associateReplacementClonesWithOriginals(replacementClone, originalClone);
     422    removeDisallowedElementsFromSubtree(replacementClone);
     423}
     424
     425void SVGUseElement::expandUseElementsInShadowTree() const
     426{
    503427    auto descendants = descendantsOfType<SVGUseElement>(*userAgentShadowRoot());
    504     auto end = descendants.end();
    505     for (auto it = descendants.begin(); it != end; ) {
    506         Ref<SVGUseElement> original = *it;
     428    for (auto it = descendants.begin(), end = descendants.end(); it != end; ) {
     429        SVGUseElement& originalClone = *it;
    507430        it = end; // Efficiently quiets assertions due to the outstanding iterator.
    508431
    509         if (original->cachedDocumentIsStillLoading())
    510             return;
     432        auto* target = originalClone.findTarget();
    511433
    512434        // Spec: In the generated content, the 'use' will be replaced by 'g', where all attributes from the
    513435        // 'use' element except for x, y, width, height and xlink:href are transferred to the generated 'g' element.
    514436
    515         // FIXME: Is it right to use referencedDocument() here instead of just document()?
    516         // Can a shadow tree within this document really contain elements that are in a
    517         // different document?
    518         ASSERT(referencedDocument());
    519         auto replacement = SVGGElement::create(SVGNames::gTag, *referencedDocument());
    520         original->transferAttributesToShadowTreeReplacement(replacement.get());
    521         original->cloneChildNodes(replacement.ptr());
    522         associateReplacementClonesWithOriginals(replacement.get(), original.get());
    523 
    524         RefPtr<SVGElement> clonedTarget;
    525         Element* targetCandidate = SVGURIReference::targetElementFromIRIString(original->href(), *referencedDocument());
    526         if (original->isValidTarget(targetCandidate)) {
    527             SVGElement& originalTarget = downcast<SVGElement>(*targetCandidate);
    528             clonedTarget = static_pointer_cast<SVGElement>(originalTarget.cloneElementWithChildren(document()));
    529             associateClonesWithOriginals(*clonedTarget, originalTarget);
    530             replacement->appendChild(clonedTarget);
    531         }
    532 
    533         removeDisallowedElementsFromSubtree(replacement.get());
    534 
    535         // Replace <use> with the <g> element we created.
    536         original->parentNode()->replaceChild(replacement.ptr(), original.ptr());
    537 
    538         // Call transferSizeAttributesToShadowTreeTargetClone after putting the cloned elements into the
    539         // shadow tree so it can use SVGElement::correspondingElement without triggering an assertion.
    540         if (clonedTarget)
    541             original->transferSizeAttributesToShadowTreeTargetClone(*clonedTarget);
    542 
    543         // Continue iterating from the <g> element since the <use> element was replaced.
    544         it = descendants.from(replacement.get());
    545     }
    546 }
    547 
    548 void SVGUseElement::expandSymbolElementsInShadowTree()
     437        auto replacementClone = SVGGElement::create(document());
     438        cloneDataAndChildren(replacementClone.get(), originalClone);
     439
     440        replacementClone->removeAttribute(SVGNames::xAttr);
     441        replacementClone->removeAttribute(SVGNames::yAttr);
     442        replacementClone->removeAttribute(SVGNames::widthAttr);
     443        replacementClone->removeAttribute(SVGNames::heightAttr);
     444        replacementClone->removeAttribute(XLinkNames::hrefAttr);
     445
     446        if (target)
     447            originalClone.cloneTarget(replacementClone.get(), *target);
     448
     449        originalClone.parentNode()->replaceChild(replacementClone.ptr(), &originalClone);
     450
     451        // Resume iterating, starting just inside the replacement clone.
     452        it = descendants.from(replacementClone.get());
     453    }
     454}
     455
     456void SVGUseElement::expandSymbolElementsInShadowTree() const
    549457{
    550458    auto descendants = descendantsOfType<SVGSymbolElement>(*userAgentShadowRoot());
    551     auto end = descendants.end();
    552     for (auto it = descendants.begin(); it != end; ) {
    553         SVGSymbolElement& original = *it;
     459    for (auto it = descendants.begin(), end = descendants.end(); it != end; ) {
     460        SVGSymbolElement& originalClone = *it;
    554461        it = end; // Efficiently quiets assertions due to the outstanding iterator.
    555462
     
    561468        // 'svg' element will use values of 100% for these attributes.
    562469
    563         // FIXME: Is it right to use referencedDocument() here instead of just document()?
    564         // Can a shadow tree within this document really contain elements that are in a
    565         // different document?
    566         ASSERT(referencedDocument());
    567         auto replacement = SVGSVGElement::create(SVGNames::svgTag, *referencedDocument());
    568         replacement->cloneDataFromElement(original);
    569         original.cloneChildNodes(replacement.ptr());
    570         associateReplacementClonesWithOriginals(replacement.get(), original);
    571 
    572         removeDisallowedElementsFromSubtree(replacement.get());
    573 
    574         // Replace <symbol> with the <svg> element we created.
    575         original.parentNode()->replaceChild(replacement.ptr(), &original);
    576 
    577         // Continue iterating from the <svg> element since the <symbol> element was replaced.
    578         it = descendants.from(replacement.get());
    579     }
    580 }
    581 
    582 void SVGUseElement::transferEventListenersToShadowTree()
    583 {
    584     ASSERT(userAgentShadowRoot());
     470        auto replacementClone = SVGSVGElement::create(document());
     471        cloneDataAndChildren(replacementClone.get(), originalClone);
     472
     473        originalClone.parentNode()->replaceChild(replacementClone.ptr(), &originalClone);
     474
     475        // Resume iterating, starting just inside the replacement clone.
     476        it = descendants.from(replacementClone.get());
     477    }
     478}
     479
     480void SVGUseElement::transferEventListenersToShadowTree() const
     481{
    585482    for (auto& descendant : descendantsOfType<SVGElement>(*userAgentShadowRoot())) {
    586         ASSERT(descendant.correspondingElement());
    587483        if (EventTargetData* data = descendant.correspondingElement()->eventTargetData())
    588484            data->eventListenerMap.copyEventListenersNotCreatedFromMarkupToTarget(&descendant);
     
    592488void SVGUseElement::invalidateShadowTree()
    593489{
    594     if (m_needsShadowTreeRecreation)
    595         return;
    596     m_needsShadowTreeRecreation = true;
     490    if (m_shadowTreeNeedsUpdate)
     491        return;
     492    m_shadowTreeNeedsUpdate = true;
    597493    setNeedsStyleRecalc(ReconstructRenderTree);
    598494    invalidateDependentShadowTrees();
     
    602498{
    603499    for (auto* instance : instances()) {
    604         if (SVGUseElement* element = instance->correspondingUseElement()) {
    605             ASSERT(element->inDocument());
     500        if (auto* element = instance->correspondingUseElement())
    606501            element->invalidateShadowTree();
    607         }
    608     }
    609 }
    610 
    611 void SVGUseElement::transferAttributesToShadowTreeReplacement(SVGGElement& replacement) const
    612 {
    613     replacement.cloneDataFromElement(*this);
    614 
    615     replacement.removeAttribute(SVGNames::xAttr);
    616     replacement.removeAttribute(SVGNames::yAttr);
    617     replacement.removeAttribute(SVGNames::widthAttr);
    618     replacement.removeAttribute(SVGNames::heightAttr);
    619     replacement.removeAttribute(XLinkNames::hrefAttr);
     502    }
    620503}
    621504
     
    625508        return true;
    626509
    627     auto* target = shadowTreeTargetClone();
    628     return target && target->hasRelativeLengths();
     510    auto* targetClone = this->targetClone();
     511    return targetClone && targetClone->hasRelativeLengths();
    629512}
    630513
    631514void SVGUseElement::notifyFinished(CachedResource* resource)
    632515{
    633     if (!inDocument())
    634         return;
    635 
    636516    invalidateShadowTree();
    637517    if (resource->errorOccurred())
     
    641521}
    642522
    643 bool SVGUseElement::cachedDocumentIsStillLoading()
    644 {
    645     if (m_cachedDocument && m_cachedDocument->isLoading())
    646         return true;
    647     return false;
    648 }
    649 
    650523void SVGUseElement::finishParsingChildren()
    651524{
    652525    SVGGraphicsElement::finishParsingChildren();
    653526    SVGExternalResourcesRequired::finishParsingChildren();
    654     if (m_wasInsertedByParser) {
    655         buildPendingResource();
    656         m_wasInsertedByParser = false;
    657     }
    658 }
    659 
    660 void SVGUseElement::setCachedDocument(CachedResourceHandle<CachedSVGDocument> cachedDocument)
    661 {
    662     if (m_cachedDocument == cachedDocument)
    663         return;
    664 
    665     if (m_cachedDocument)
    666         m_cachedDocument->removeClient(this);
    667 
    668     m_cachedDocument = cachedDocument;
    669     if (m_cachedDocument) {
    670         // We don't need the SVG document to create a new frame because the new document belongs to the parent UseElement.
    671         m_cachedDocument->setShouldCreateFrameForDocument(false);
    672         m_cachedDocument->addClient(this);
    673     }
    674 }
    675 
    676 }
     527}
     528
     529void SVGUseElement::updateExternalDocument()
     530{
     531    URL externalDocumentURL;
     532    if (inDocument() && isExternalURIReference(href(), document())) {
     533        externalDocumentURL = document().completeURL(href());
     534        if (!externalDocumentURL.hasFragmentIdentifier())
     535            externalDocumentURL = URL();
     536    }
     537
     538    if (externalDocumentURL == (m_externalDocument ? m_externalDocument->url() : URL()))
     539        return;
     540
     541    if (m_externalDocument)
     542        m_externalDocument->removeClient(this);
     543
     544    if (externalDocumentURL.isNull())
     545        m_externalDocument = nullptr;
     546    else {
     547        CachedResourceRequest request { ResourceRequest { externalDocumentURL } };
     548        request.setInitiator(this);
     549        m_externalDocument = document().cachedResourceLoader().requestSVGDocument(request);
     550        if (m_externalDocument) {
     551            // FIXME: Is it really OK for us to set this to false for a document that might be shared by another client?
     552            m_externalDocument->setShouldCreateFrameForDocument(false); // No frame needed, we just want the elements.
     553            m_externalDocument->addClient(this);
     554        }
     555    }
     556
     557    invalidateShadowTree();
     558}
     559
     560bool SVGUseElement::isValid() const
     561{
     562    return SVGTests::isValid();
     563}
     564
     565bool SVGUseElement::haveLoadedRequiredResources()
     566{
     567    return SVGExternalResourcesRequired::haveLoadedRequiredResources();
     568}
     569
     570void SVGUseElement::setHaveFiredLoadEvent(bool haveFiredLoadEvent)
     571{
     572    m_haveFiredLoadEvent = haveFiredLoadEvent;
     573}
     574
     575bool SVGUseElement::haveFiredLoadEvent() const
     576{
     577    return m_haveFiredLoadEvent;
     578}
     579
     580Timer* SVGUseElement::svgLoadEventTimer()
     581{
     582    return &m_svgLoadEventTimer;
     583}
     584
     585}
  • trunk/Source/WebCore/svg/SVGUseElement.h

    r179810 r179980  
    2929#include "SVGExternalResourcesRequired.h"
    3030#include "SVGGraphicsElement.h"
    31 #include "SVGNames.h"
    3231#include "SVGURIReference.h"
    3332
     
    3736class SVGGElement;
    3837
    39 class SVGUseElement final : public SVGGraphicsElement,
    40                             public SVGExternalResourcesRequired,
    41                             public SVGURIReference,
    42                             public CachedSVGDocumentClient {
    43 public:
    44     static Ref<SVGUseElement> create(const QualifiedName&, Document&, bool wasInsertedByParser);
    45     virtual ~SVGUseElement();
    46 
    47     void invalidateShadowTree();
    48     void invalidateDependentShadowTrees();
    49 
    50     RenderElement* rendererClipChild() const;
    51 
    52 protected:
    53     virtual void didNotifySubtreeInsertions(ContainerNode*) override;
    54 
    55 private:
    56     SVGUseElement(const QualifiedName&, Document&, bool wasInsertedByParser);
    57 
    58     virtual bool isValid() const override { return SVGTests::isValid(); }
    59 
    60     virtual InsertionNotificationRequest insertedInto(ContainerNode&) override;
    61     virtual void removedFrom(ContainerNode&) override;
    62     virtual void buildPendingResource() override;
    63 
    64     bool isSupportedAttribute(const QualifiedName&);
    65     virtual void parseAttribute(const QualifiedName&, const AtomicString&) override;
    66     virtual void svgAttributeChanged(const QualifiedName&) override;
    67 
    68     virtual void willAttachRenderers() override;
    69 
    70     virtual RenderPtr<RenderElement> createElementRenderer(Ref<RenderStyle>&&) override;
    71     virtual void toClipPath(Path&) override;
    72 
    73     void clearResourceReferences();
    74 
    75     virtual bool haveLoadedRequiredResources() override { return SVGExternalResourcesRequired::haveLoadedRequiredResources(); }
    76 
    77     virtual void finishParsingChildren() override;
    78     virtual bool selfHasRelativeLengths() const override;
    79 
    80     // Shadow tree handling.
    81     void buildShadowTree(SVGElement& target);
    82     void expandUseElementsInShadowTree();
    83     void expandSymbolElementsInShadowTree();
    84     SVGElement* shadowTreeTargetClone() const;
    85     void transferEventListenersToShadowTree();
    86     void transferAttributesToShadowTreeReplacement(SVGGElement&) const;
    87     void transferSizeAttributesToShadowTreeTargetClone(SVGElement&) const;
    88     bool isValidTarget(Element*) const;
     38class SVGUseElement final : public SVGGraphicsElement, public SVGExternalResourcesRequired, public SVGURIReference, private CachedSVGDocumentClient {
    8939
    9040    BEGIN_DECLARE_ANIMATED_PROPERTIES(SVGUseElement)
     
    9747    END_DECLARE_ANIMATED_PROPERTIES
    9848
    99     bool cachedDocumentIsStillLoading();
     49public:
     50    static Ref<SVGUseElement> create(const QualifiedName&, Document&);
     51    virtual ~SVGUseElement();
     52
     53    void invalidateShadowTree();
     54
     55    RenderElement* rendererClipChild() const;
     56
     57private:
     58    SVGUseElement(const QualifiedName&, Document&);
     59
     60    virtual bool isValid() const override;
     61    virtual InsertionNotificationRequest insertedInto(ContainerNode&) override;
     62    virtual void removedFrom(ContainerNode&) override;
     63    virtual void buildPendingResource() override;
     64    virtual void parseAttribute(const QualifiedName&, const AtomicString&) override;
     65    virtual void svgAttributeChanged(const QualifiedName&) override;
     66    virtual void willAttachRenderers() override;
     67    virtual RenderPtr<RenderElement> createElementRenderer(Ref<RenderStyle>&&) override;
     68    virtual void toClipPath(Path&) override;
     69    virtual bool haveLoadedRequiredResources() override;
     70    virtual void finishParsingChildren() override;
     71    virtual bool selfHasRelativeLengths() const override;
     72    virtual void setHaveFiredLoadEvent(bool) override;
     73    virtual bool haveFiredLoadEvent() const override;
     74    virtual Timer* svgLoadEventTimer() override;
     75    virtual void notifyFinished(CachedResource*) override;
     76
    10077    Document* externalDocument() const;
    101     virtual void notifyFinished(CachedResource*) override;
    102     Document* referencedDocument() const;
    103     void setCachedDocument(CachedResourceHandle<CachedSVGDocument>);
     78    void updateExternalDocument();
    10479
    105     // SVGExternalResourcesRequired
    106     virtual void setHaveFiredLoadEvent(bool haveFiredLoadEvent) override { m_haveFiredLoadEvent = haveFiredLoadEvent; }
    107     virtual bool isParserInserted() const override { return m_wasInsertedByParser; }
    108     virtual bool haveFiredLoadEvent() const override { return m_haveFiredLoadEvent; }
    109     virtual Timer* svgLoadEventTimer() override { return &m_svgLoadEventTimer; }
     80    SVGElement* findTarget(String* targetID = nullptr) const;
    11081
    111     bool m_wasInsertedByParser;
    112     bool m_haveFiredLoadEvent;
    113     bool m_needsShadowTreeRecreation;
    114     CachedResourceHandle<CachedSVGDocument> m_cachedDocument;
     82    void cloneTarget(ContainerNode&, SVGElement& target) const;
     83    SVGElement* targetClone() const;
     84
     85    void updateShadowTree();
     86    void expandUseElementsInShadowTree() const;
     87    void expandSymbolElementsInShadowTree() const;
     88    void transferEventListenersToShadowTree() const;
     89    void transferSizeAttributesToTargetClone(SVGElement&) const;
     90
     91    void clearShadowTree();
     92    void invalidateDependentShadowTrees();
     93
     94    bool m_haveFiredLoadEvent { false };
     95    bool m_shadowTreeNeedsUpdate { true };
     96    CachedResourceHandle<CachedSVGDocument> m_externalDocument;
    11597    Timer m_svgLoadEventTimer;
    11698};
  • trunk/Source/WebCore/svg/svgtags.in

    r174050 r179980  
    9292tref interfaceName=SVGTRefElement
    9393tspan interfaceName=SVGTSpanElement
    94 use constructorNeedsCreatedByParser
     94use
    9595view
    9696#if ENABLE_SVG_FONTS
Note: See TracChangeset for help on using the changeset viewer.