⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 179807 in webkit


Ignore:
Timestamp:
Feb 8, 2015, 3:22:24 PM (12 years ago)
Author:
Darin Adler
Message:

Make SVGUseElement work without creating any SVGElementInstance objects
https://bugs.webkit.org/show_bug.cgi?id=141374

Reviewed by Sam Weinig.

Source/WebCore:

  • dom/ElementIterator.h: Changed the * and -> operators to be const.

There is no need for the iterator itself to be modified just to dereference it.

  • dom/TypedElementDescendantIterator.h: Added DoubleTypedElementDescendantIterator.

This allows callers to call descendantsOfType on two elements, as long as the caller
can guarantee that both have the same number of descendants of that type. It's handy
for walking a tree of cloned elements to set up something between each original and
its clone. In the future we might instead change the cloning machinery so it can do
this work as we clone, and if so, we could consider deleting this.

  • svg/SVGElement.cpp:

(WebCore::SVGElement::correspondingElement): Made this const.
(WebCore::SVGElement::invalidateInstances): Got rid of the rule that said "this can
only be done for an element in a document", since it's useful to do this on an element
that has just been removed from a document. Removed the "updateStyleIfNeeded" call
here now that the other changes make it no longer needed. Removed an unimportant
assertion that we only invalidate use elements that are in a document; that's not
a necessary restriction. Streamlined the logic a bit.

  • svg/SVGElement.h: Made correspondingElement const.
  • svg/SVGUseElement.cpp:

(WebCore::SVGUseElement::insertedInto): Removed an assertion about
m_targetElementInstance since that's gone now.
(WebCore::SVGUseElement::svgAttributeChanged): Changed code that transfers
size attributes to the shadow tree to use shadowTreeTargetClone instead of
m_targetElementInstance.
(WebCore::SVGUseElement::clearResourceReferences): Removed code to detach
m_targetElementInstance, and also the call to removeAllTargetReferencesForElement,
because we no longer use those.
(WebCore::SVGUseElement::buildPendingResource): Moved the code to build the
shadow tree in here and deleted the buildShadowAndInstanceTree function.
Also changed logic so that we use a pending resource any time the target is not
a valid one. That helps us correctly handle cases where we initially have an
invalid target, but later get a value one
(WebCore::SVGUseElement::buildShadowAndInstanceTree): Deleted. The code here
was greatly simplified and moved into buildPendingResource.
(WebCore::SVGUseElement::buildInstanceTree): Deleted.
(WebCore::SVGUseElement::hasCycleUseReferencing): Deleted. Cycles are now
detected by the new isValidTarget function and so there's no need for a
separate explicit check for a cycle.
(WebCore::associateClonesWithOriginals): Added. Helper that makes
functions that build the shadow tree simpler and easier to read.
(WebCore::associateReplacementCloneWithOriginal): Added. Helper to
make associateReplacementClonesWithOriginals simple.
(WebCore::associateReplacementClonesWithOriginals): Added. Helper that
makes functions that build the shadow tree simpler and easier to read.
(WebCore::SVGUseElement::buildShadowTree): Call associateClonesWithOriginals
since associateInstancesWithShadowTreeElements no longer does this.
(WebCore::SVGUseElement::isValidTarget): Added. Covers all the different
reasons a target might not be valid: type of element, reference cycles, and
also "not in document" (refactored in here; not sure when that can happen
in practice, might be possible to remove it later).
(WebCore::SVGUseElement::expandUseElementsInShadowTree): Add checks for
documents that are still loading; this used to be checked when building the
instance tree. Added calls to associateReplacementClonesWithOriginals and
associateClonesWithOriginals; that used to be done by later in the
associateInstancesWithShadowTreeElements function. Use isValidTarget so
we handle cycles as well as invalid target types.
(WebCore::SVGUseElement::expandSymbolElementsInShadowTree): Added a call to
associateReplacementClonesWithOriginals, since we can no longer do that in
associateInstancesWithShadowTreeElements.
(WebCore::SVGUseElement::associateInstancesWithShadowTreeElements): Deleted.
(WebCore::SVGUseElement::instanceForShadowTreeElement): Deleted.
(WebCore::SVGUseElement::invalidateDependentShadowTrees): Removed a comment
that simply restated the name of the function.

  • svg/SVGUseElement.h: Removed instanceForShadowTreeElement,

buildShadowAndInstanceTree, detachInstance, buildInstanceTree,
hasCycleUseReferencing, associateInstancesWithShadowTreeElements,
instanceForShadowTreeElement, and m_targetElementInstance. Added isValidTarget.

LayoutTests:

Results changed on some tests that expected the old "remove all content if a cycle is detected"
behavior from the <use> element. The new behavior is to inhibit cycles, but render everything
else, which is much easier to implement correctly and also makes logical sense. Changed all
those tests to be reference tests, which makes sense since they are focusing on what gets
rendered in these complex cases, and the expected results are a lot easier to understand in
SVG form than they were in txt/png form. This also means we can remove a lot of platform-specific
results since reference tests aren't sensitive to small platform differences in rendering.

  • platform/efl/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-01-t-expected.png: Removed.
  • platform/efl/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-02-t-expected.png: Removed.
  • platform/efl/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-03-t-expected.png: Removed.
  • platform/efl/svg/hixie/error/017-expected.png: Removed.
  • platform/gtk/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-01-t-expected.png: Removed.
  • platform/gtk/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-02-t-expected.png: Removed.
  • platform/gtk/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-03-t-expected.png: Removed.
  • platform/gtk/svg/custom/use-on-disallowed-foreign-object-3-expected.png: Removed.
  • platform/gtk/svg/custom/use-on-disallowed-foreign-object-3-expected.txt: Removed.
  • platform/gtk/svg/custom/use-recursion-1-expected.png: Removed.
  • platform/gtk/svg/custom/use-recursion-1-expected.txt: Removed.
  • platform/gtk/svg/custom/use-recursion-2-expected.png: Removed.
  • platform/gtk/svg/custom/use-recursion-2-expected.txt: Removed.
  • platform/gtk/svg/custom/use-recursion-3-expected.png: Removed.
  • platform/gtk/svg/custom/use-recursion-3-expected.txt: Removed.
  • platform/gtk/svg/custom/use-recursion-4-expected.png: Removed.
  • platform/gtk/svg/custom/use-recursion-4-expected.txt: Removed.
  • platform/gtk/svg/hixie/error/017-expected.png: Removed.
  • platform/ios-sim-deprecated/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-01-t-expected.txt: Removed.
  • platform/ios-sim-deprecated/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-02-t-expected.txt: Removed.
  • platform/ios-sim-deprecated/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-03-t-expected.txt: Removed.
  • platform/ios-sim-deprecated/svg/custom/use-on-disallowed-foreign-object-3-expected.txt: Removed.
  • platform/ios-sim-deprecated/svg/custom/use-recursion-1-expected.txt: Removed.
  • platform/ios-sim-deprecated/svg/custom/use-recursion-2-expected.txt: Removed.
  • platform/ios-sim-deprecated/svg/custom/use-recursion-3-expected.txt: Removed.
  • platform/ios-sim-deprecated/svg/custom/use-recursion-4-expected.txt: Removed.
  • platform/ios-sim-deprecated/svg/hixie/error/017-expected.txt: Removed.
  • platform/ios-simulator/svg/custom/use-on-disallowed-foreign-object-3-expected.txt: Removed.
  • platform/ios-simulator/svg/custom/use-recursion-1-expected.txt: Removed.
  • platform/ios-simulator/svg/custom/use-recursion-2-expected.txt: Removed.
  • platform/ios-simulator/svg/custom/use-recursion-3-expected.txt: Removed.
  • platform/ios-simulator/svg/custom/use-recursion-4-expected.txt: Removed.
  • platform/mac-mountainlion/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-01-t-expected.txt: Removed.
  • platform/mac-mountainlion/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-02-t-expected.txt: Removed.
  • platform/mac-mountainlion/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-03-t-expected.txt: Removed.
  • platform/mac-mountainlion/svg/custom/use-on-disallowed-foreign-object-3-expected.txt: Removed.
  • platform/mac-mountainlion/svg/custom/use-recursion-1-expected.txt: Removed.
  • platform/mac-mountainlion/svg/custom/use-recursion-2-expected.txt: Removed.
  • platform/mac-mountainlion/svg/custom/use-recursion-3-expected.txt: Removed.
  • platform/mac-mountainlion/svg/custom/use-recursion-4-expected.txt: Removed.
  • platform/mac-mountainlion/svg/hixie/error/017-expected.txt: Removed.
  • platform/mac/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-01-t-expected.png: Removed.
  • platform/mac/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-01-t-expected.txt: Removed.
  • platform/mac/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-02-t-expected.png: Removed.
  • platform/mac/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-02-t-expected.txt: Removed.
  • platform/mac/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-03-t-expected.png: Removed.
  • platform/mac/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-03-t-expected.txt: Removed.
  • platform/mac/svg/custom/use-on-disallowed-foreign-object-3-expected.png: Removed.
  • platform/mac/svg/custom/use-on-disallowed-foreign-object-3-expected.txt: Removed.
  • platform/mac/svg/custom/use-recursion-1-expected.png: Removed.
  • platform/mac/svg/custom/use-recursion-1-expected.txt: Removed.
  • platform/mac/svg/custom/use-recursion-2-expected.png: Removed.
  • platform/mac/svg/custom/use-recursion-2-expected.txt: Removed.
  • platform/mac/svg/custom/use-recursion-3-expected.png: Removed.
  • platform/mac/svg/custom/use-recursion-3-expected.txt: Removed.
  • platform/mac/svg/custom/use-recursion-4-expected.png: Removed.
  • platform/mac/svg/custom/use-recursion-4-expected.txt: Removed.
  • platform/mac/svg/hixie/error/017-expected.png: Removed.
  • platform/mac/svg/hixie/error/017-expected.txt: Removed.
  • svg/W3C-SVG-1.2-Tiny/struct-use-recursion-01-t-expected.svg: Added. Made this be a reference test,

and made it expect more of the recursion to work.

  • svg/W3C-SVG-1.2-Tiny/struct-use-recursion-01-t-expected.txt: Removed.
  • svg/W3C-SVG-1.2-Tiny/struct-use-recursion-02-t-expected.svg: Added. More of the same.
  • svg/W3C-SVG-1.2-Tiny/struct-use-recursion-02-t-expected.txt: Removed.
  • svg/W3C-SVG-1.2-Tiny/struct-use-recursion-03-t-expected.svg: Added. More of the same.
  • svg/W3C-SVG-1.2-Tiny/struct-use-recursion-03-t-expected.txt: Removed.
  • svg/custom/use-on-disallowed-foreign-object-3-expected.svg: Added. More of the same.
  • svg/custom/use-recursion-1-expected.svg: Added. More of the same.
  • svg/custom/use-recursion-2-expected.svg: Added. More of the same.
  • svg/custom/use-recursion-3-expected.svg: Added. More of the same.
  • svg/custom/use-recursion-4-expected.svg: Added. More of the same.
  • svg/hixie/error/017-expected.txt: Removed.
  • svg/hixie/error/017-expected.xml: Added. More of the same.
  • svg/in-html/defs-after-use.html: Updated incorrect bug number in this test.
Location:
trunk
Files:
9 added
50 deleted
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r179806 r179807  
     12015-02-08  Darin Adler  <darin@apple.com>
     2
     3        Make SVGUseElement work without creating any SVGElementInstance objects
     4        https://bugs.webkit.org/show_bug.cgi?id=141374
     5
     6        Reviewed by Sam Weinig.
     7
     8        Results changed on some tests that expected the old "remove all content if a cycle is detected"
     9        behavior from the <use> element. The new behavior is to inhibit cycles, but render everything
     10        else, which is much easier to implement correctly and also makes logical sense. Changed all
     11        those tests to be reference tests, which makes sense since they are focusing on what gets
     12        rendered in these complex cases, and the expected results are a lot easier to understand in
     13        SVG form than they were in txt/png form. This also means we can remove a lot of platform-specific
     14        results since reference tests aren't sensitive to small platform differences in rendering.
     15
     16        * platform/efl/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-01-t-expected.png: Removed.
     17        * platform/efl/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-02-t-expected.png: Removed.
     18        * platform/efl/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-03-t-expected.png: Removed.
     19        * platform/efl/svg/hixie/error/017-expected.png: Removed.
     20        * platform/gtk/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-01-t-expected.png: Removed.
     21        * platform/gtk/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-02-t-expected.png: Removed.
     22        * platform/gtk/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-03-t-expected.png: Removed.
     23        * platform/gtk/svg/custom/use-on-disallowed-foreign-object-3-expected.png: Removed.
     24        * platform/gtk/svg/custom/use-on-disallowed-foreign-object-3-expected.txt: Removed.
     25        * platform/gtk/svg/custom/use-recursion-1-expected.png: Removed.
     26        * platform/gtk/svg/custom/use-recursion-1-expected.txt: Removed.
     27        * platform/gtk/svg/custom/use-recursion-2-expected.png: Removed.
     28        * platform/gtk/svg/custom/use-recursion-2-expected.txt: Removed.
     29        * platform/gtk/svg/custom/use-recursion-3-expected.png: Removed.
     30        * platform/gtk/svg/custom/use-recursion-3-expected.txt: Removed.
     31        * platform/gtk/svg/custom/use-recursion-4-expected.png: Removed.
     32        * platform/gtk/svg/custom/use-recursion-4-expected.txt: Removed.
     33        * platform/gtk/svg/hixie/error/017-expected.png: Removed.
     34        * platform/ios-sim-deprecated/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-01-t-expected.txt: Removed.
     35        * platform/ios-sim-deprecated/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-02-t-expected.txt: Removed.
     36        * platform/ios-sim-deprecated/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-03-t-expected.txt: Removed.
     37        * platform/ios-sim-deprecated/svg/custom/use-on-disallowed-foreign-object-3-expected.txt: Removed.
     38        * platform/ios-sim-deprecated/svg/custom/use-recursion-1-expected.txt: Removed.
     39        * platform/ios-sim-deprecated/svg/custom/use-recursion-2-expected.txt: Removed.
     40        * platform/ios-sim-deprecated/svg/custom/use-recursion-3-expected.txt: Removed.
     41        * platform/ios-sim-deprecated/svg/custom/use-recursion-4-expected.txt: Removed.
     42        * platform/ios-sim-deprecated/svg/hixie/error/017-expected.txt: Removed.
     43        * platform/ios-simulator/svg/custom/use-on-disallowed-foreign-object-3-expected.txt: Removed.
     44        * platform/ios-simulator/svg/custom/use-recursion-1-expected.txt: Removed.
     45        * platform/ios-simulator/svg/custom/use-recursion-2-expected.txt: Removed.
     46        * platform/ios-simulator/svg/custom/use-recursion-3-expected.txt: Removed.
     47        * platform/ios-simulator/svg/custom/use-recursion-4-expected.txt: Removed.
     48        * platform/mac-mountainlion/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-01-t-expected.txt: Removed.
     49        * platform/mac-mountainlion/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-02-t-expected.txt: Removed.
     50        * platform/mac-mountainlion/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-03-t-expected.txt: Removed.
     51        * platform/mac-mountainlion/svg/custom/use-on-disallowed-foreign-object-3-expected.txt: Removed.
     52        * platform/mac-mountainlion/svg/custom/use-recursion-1-expected.txt: Removed.
     53        * platform/mac-mountainlion/svg/custom/use-recursion-2-expected.txt: Removed.
     54        * platform/mac-mountainlion/svg/custom/use-recursion-3-expected.txt: Removed.
     55        * platform/mac-mountainlion/svg/custom/use-recursion-4-expected.txt: Removed.
     56        * platform/mac-mountainlion/svg/hixie/error/017-expected.txt: Removed.
     57        * platform/mac/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-01-t-expected.png: Removed.
     58        * platform/mac/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-01-t-expected.txt: Removed.
     59        * platform/mac/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-02-t-expected.png: Removed.
     60        * platform/mac/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-02-t-expected.txt: Removed.
     61        * platform/mac/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-03-t-expected.png: Removed.
     62        * platform/mac/svg/W3C-SVG-1.2-Tiny/struct-use-recursion-03-t-expected.txt: Removed.
     63        * platform/mac/svg/custom/use-on-disallowed-foreign-object-3-expected.png: Removed.
     64        * platform/mac/svg/custom/use-on-disallowed-foreign-object-3-expected.txt: Removed.
     65        * platform/mac/svg/custom/use-recursion-1-expected.png: Removed.
     66        * platform/mac/svg/custom/use-recursion-1-expected.txt: Removed.
     67        * platform/mac/svg/custom/use-recursion-2-expected.png: Removed.
     68        * platform/mac/svg/custom/use-recursion-2-expected.txt: Removed.
     69        * platform/mac/svg/custom/use-recursion-3-expected.png: Removed.
     70        * platform/mac/svg/custom/use-recursion-3-expected.txt: Removed.
     71        * platform/mac/svg/custom/use-recursion-4-expected.png: Removed.
     72        * platform/mac/svg/custom/use-recursion-4-expected.txt: Removed.
     73        * platform/mac/svg/hixie/error/017-expected.png: Removed.
     74        * platform/mac/svg/hixie/error/017-expected.txt: Removed.
     75
     76        * svg/W3C-SVG-1.2-Tiny/struct-use-recursion-01-t-expected.svg: Added. Made this be a reference test,
     77        and made it expect more of the recursion to work.
     78        * svg/W3C-SVG-1.2-Tiny/struct-use-recursion-01-t-expected.txt: Removed.
     79        * svg/W3C-SVG-1.2-Tiny/struct-use-recursion-02-t-expected.svg: Added. More of the same.
     80        * svg/W3C-SVG-1.2-Tiny/struct-use-recursion-02-t-expected.txt: Removed.
     81        * svg/W3C-SVG-1.2-Tiny/struct-use-recursion-03-t-expected.svg: Added. More of the same.
     82        * svg/W3C-SVG-1.2-Tiny/struct-use-recursion-03-t-expected.txt: Removed.
     83        * svg/custom/use-on-disallowed-foreign-object-3-expected.svg: Added. More of the same.
     84        * svg/custom/use-recursion-1-expected.svg: Added. More of the same.
     85        * svg/custom/use-recursion-2-expected.svg: Added. More of the same.
     86        * svg/custom/use-recursion-3-expected.svg: Added. More of the same.
     87        * svg/custom/use-recursion-4-expected.svg: Added. More of the same.
     88        * svg/hixie/error/017-expected.txt: Removed.
     89        * svg/hixie/error/017-expected.xml: Added. More of the same.
     90
     91        * svg/in-html/defs-after-use.html: Updated incorrect bug number in this test.
     92
    1932015-02-08  David Kilzer  <ddkilzer@apple.com>
    294
  • trunk/LayoutTests/svg/in-html/defs-after-use.html

    r177576 r179807  
    66    tree as well.
    77   
    8     https://bugs.webkit.org/show_bug.cgi?id=139469
     8    https://bugs.webkit.org/show_bug.cgi?id=139451
    99-->
    1010<html>
  • trunk/Source/WebCore/ChangeLog

    r179804 r179807  
     12015-02-08  Darin Adler  <darin@apple.com>
     2
     3        Make SVGUseElement work without creating any SVGElementInstance objects
     4        https://bugs.webkit.org/show_bug.cgi?id=141374
     5
     6        Reviewed by Sam Weinig.
     7
     8        * dom/ElementIterator.h: Changed the * and -> operators to be const.
     9        There is no need for the iterator itself to be modified just to dereference it.
     10
     11        * dom/TypedElementDescendantIterator.h: Added DoubleTypedElementDescendantIterator.
     12        This allows callers to call descendantsOfType on two elements, as long as the caller
     13        can guarantee that both have the same number of descendants of that type. It's handy
     14        for walking a tree of cloned elements to set up something between each original and
     15        its clone. In the future we might instead change the cloning machinery so it can do
     16        this work as we clone, and if so, we could consider deleting this.
     17
     18        * svg/SVGElement.cpp:
     19        (WebCore::SVGElement::correspondingElement): Made this const.
     20        (WebCore::SVGElement::invalidateInstances): Got rid of the rule that said "this can
     21        only be done for an element in a document", since it's useful to do this on an element
     22        that has just been removed from a document. Removed the "updateStyleIfNeeded" call
     23        here now that the other changes make it no longer needed. Removed an unimportant
     24        assertion that we only invalidate use elements that are in a document; that's not
     25        a necessary restriction. Streamlined the logic a bit.
     26
     27        * svg/SVGElement.h: Made correspondingElement const.
     28
     29        * svg/SVGUseElement.cpp:
     30        (WebCore::SVGUseElement::insertedInto): Removed an assertion about
     31        m_targetElementInstance since that's gone now.
     32        (WebCore::SVGUseElement::svgAttributeChanged): Changed code that transfers
     33        size attributes to the shadow tree to use shadowTreeTargetClone instead of
     34        m_targetElementInstance.
     35        (WebCore::SVGUseElement::clearResourceReferences): Removed code to detach
     36        m_targetElementInstance, and also the call to removeAllTargetReferencesForElement,
     37        because we no longer use those.
     38        (WebCore::SVGUseElement::buildPendingResource): Moved the code to build the
     39        shadow tree in here and deleted the buildShadowAndInstanceTree function.
     40        Also changed logic so that we use a pending resource any time the target is not
     41        a valid one. That helps us correctly handle cases where we initially have an
     42        invalid target, but later get a value one
     43        (WebCore::SVGUseElement::buildShadowAndInstanceTree): Deleted. The code here
     44        was greatly simplified and moved into buildPendingResource.
     45        (WebCore::SVGUseElement::buildInstanceTree): Deleted.
     46        (WebCore::SVGUseElement::hasCycleUseReferencing): Deleted. Cycles are now
     47        detected by the new isValidTarget function and so there's no need for a
     48        separate explicit check for a cycle.
     49        (WebCore::associateClonesWithOriginals): Added. Helper that makes
     50        functions that build the shadow tree simpler and easier to read.
     51        (WebCore::associateReplacementCloneWithOriginal): Added. Helper to
     52        make associateReplacementClonesWithOriginals simple.
     53        (WebCore::associateReplacementClonesWithOriginals): Added. Helper that
     54        makes functions that build the shadow tree simpler and easier to read.
     55        (WebCore::SVGUseElement::buildShadowTree): Call associateClonesWithOriginals
     56        since associateInstancesWithShadowTreeElements no longer does this.
     57        (WebCore::SVGUseElement::isValidTarget): Added. Covers all the different
     58        reasons a target might not be valid: type of element, reference cycles, and
     59        also "not in document" (refactored in here; not sure when that can happen
     60        in practice, might be possible to remove it later).
     61        (WebCore::SVGUseElement::expandUseElementsInShadowTree): Add checks for
     62        documents that are still loading; this used to be checked when building the
     63        instance tree. Added calls to associateReplacementClonesWithOriginals and
     64        associateClonesWithOriginals; that used to be done by later in the
     65        associateInstancesWithShadowTreeElements function. Use isValidTarget so
     66        we handle cycles as well as invalid target types.
     67        (WebCore::SVGUseElement::expandSymbolElementsInShadowTree): Added a call to
     68        associateReplacementClonesWithOriginals, since we can no longer do that in
     69        associateInstancesWithShadowTreeElements.
     70        (WebCore::SVGUseElement::associateInstancesWithShadowTreeElements): Deleted.
     71        (WebCore::SVGUseElement::instanceForShadowTreeElement): Deleted.
     72        (WebCore::SVGUseElement::invalidateDependentShadowTrees): Removed a comment
     73        that simply restated the name of the function.
     74
     75        * svg/SVGUseElement.h: Removed instanceForShadowTreeElement,
     76        buildShadowAndInstanceTree, detachInstance, buildInstanceTree,
     77        hasCycleUseReferencing, associateInstancesWithShadowTreeElements,
     78        instanceForShadowTreeElement, and m_targetElementInstance. Added isValidTarget.
     79
    1802015-02-08  Chris Dumez  <cdumez@apple.com>
    281
  • trunk/Source/WebCore/dom/ElementIterator.h

    r179143 r179807  
    4141    ElementIterator(const ContainerNode* root, ElementType* current);
    4242
    43     ElementType& operator*();
    44     ElementType* operator->();
     43    ElementType& operator*() const;
     44    ElementType* operator->() const;
    4545
    4646    bool operator==(const ElementIterator& other) const;
     
    212212
    213213template <typename ElementType>
    214 inline ElementType& ElementIterator<ElementType>::operator*()
     214inline ElementType& ElementIterator<ElementType>::operator*() const
    215215{
    216216    ASSERT(m_current);
     
    220220
    221221template <typename ElementType>
    222 inline ElementType* ElementIterator<ElementType>::operator->()
     222inline ElementType* ElementIterator<ElementType>::operator->() const
    223223{
    224224    ASSERT(m_current);
  • trunk/Source/WebCore/dom/TypedElementDescendantIterator.h

    r179143 r179807  
    3131namespace WebCore {
    3232
     33template<typename ElementType> class DoubleTypedElementDescendantIterator;
     34
    3335template <typename ElementType>
    3436class TypedElementDescendantIterator : public ElementIterator<ElementType> {
     
    7981};
    8082
     83template<typename ElementType> class DoubleTypedElementDescendantIteratorAdapter {
     84public:
     85    typedef TypedElementDescendantIteratorAdapter<ElementType> SingleAdapter;
     86    typedef DoubleTypedElementDescendantIterator<ElementType> Iterator;
     87
     88    DoubleTypedElementDescendantIteratorAdapter(SingleAdapter&&, SingleAdapter&&);
     89    Iterator begin();
     90    Iterator end();
     91
     92private:
     93    std::pair<SingleAdapter, SingleAdapter> m_pair;
     94};
     95
     96template<typename ElementType> class DoubleTypedElementDescendantIterator {
     97public:
     98    typedef TypedElementDescendantIterator<ElementType> SingleIterator;
     99    typedef std::pair<ElementType&, ElementType&> ReferenceProxy;
     100
     101    DoubleTypedElementDescendantIterator(SingleIterator&&, SingleIterator&&);
     102    ReferenceProxy operator*() const;
     103    bool operator==(const DoubleTypedElementDescendantIterator&) const;
     104    bool operator!=(const DoubleTypedElementDescendantIterator&) const;
     105    DoubleTypedElementDescendantIterator& operator++();
     106
     107private:
     108    std::pair<SingleIterator, SingleIterator> m_pair;
     109};
     110
    81111template <typename ElementType> TypedElementDescendantIteratorAdapter<ElementType> descendantsOfType(ContainerNode&);
    82112template <typename ElementType> TypedElementDescendantConstIteratorAdapter<ElementType> descendantsOfType(const ContainerNode&);
     113
     114// This must only be used when both sets of descendants are known to be the same length.
     115// If they are different lengths, this will stop when the shorter one reaches the end, but also an assertion will fail.
     116template<typename ElementType> DoubleTypedElementDescendantIteratorAdapter<ElementType> descendantsOfType(ContainerNode& firstRoot, ContainerNode& secondRoot);
    83117
    84118// TypedElementDescendantIterator
     
    221255}
    222256
     257// DoubleTypedElementDescendantIteratorAdapter
     258
     259template<typename ElementType> inline DoubleTypedElementDescendantIteratorAdapter<ElementType>::DoubleTypedElementDescendantIteratorAdapter(SingleAdapter&& first, SingleAdapter&& second)
     260    : m_pair(WTF::move(first), WTF::move(second))
     261{
     262}
     263
     264template<typename ElementType> inline auto DoubleTypedElementDescendantIteratorAdapter<ElementType>::begin() -> Iterator
     265{
     266    return { m_pair.first.begin(), m_pair.second.begin() };
     267}
     268
     269template<typename ElementType> inline auto DoubleTypedElementDescendantIteratorAdapter<ElementType>::end() -> Iterator
     270{
     271    return { m_pair.first.end(), m_pair.second.end() };
     272}
     273
     274// DoubleTypedElementDescendantIterator
     275
     276template<typename ElementType> inline DoubleTypedElementDescendantIterator<ElementType>::DoubleTypedElementDescendantIterator(SingleIterator&& first, SingleIterator&& second)
     277    : m_pair(WTF::move(first), WTF::move(second))
     278{
     279}
     280
     281template<typename ElementType> inline auto DoubleTypedElementDescendantIterator<ElementType>::operator*() const -> ReferenceProxy
     282{
     283    return { *m_pair.first, *m_pair.second };
     284}
     285
     286template<typename ElementType> inline bool DoubleTypedElementDescendantIterator<ElementType>::operator==(const DoubleTypedElementDescendantIterator& other) const
     287{
     288    ASSERT((m_pair.first == other.m_pair.first) == (m_pair.second == other.m_pair.second));
     289    return m_pair.first == other.m_pair.first || m_pair.second == other.m_pair.second;
     290}
     291
     292template<typename ElementType> inline bool DoubleTypedElementDescendantIterator<ElementType>::operator!=(const DoubleTypedElementDescendantIterator& other) const
     293{
     294    return !(*this == other);
     295}
     296
     297template<typename ElementType> inline DoubleTypedElementDescendantIterator<ElementType>& DoubleTypedElementDescendantIterator<ElementType>::operator++()
     298{
     299    ++m_pair.first;
     300    ++m_pair.second;
     301    return *this;
     302}
     303
    223304// Standalone functions
    224305
     
    235316}
    236317
     318template<typename ElementType> inline DoubleTypedElementDescendantIteratorAdapter<ElementType> descendantsOfType(ContainerNode& firstRoot, ContainerNode& secondRoot)
     319{
     320    return { descendantsOfType<ElementType>(firstRoot), descendantsOfType<ElementType>(secondRoot) };
     321}
     322
    237323}
    238324
  • trunk/Source/WebCore/svg/SVGElement.cpp

    r179695 r179807  
    476476}
    477477
    478 SVGElement* SVGElement::correspondingElement()
     478SVGElement* SVGElement::correspondingElement() const
    479479{
    480480    ASSERT(!m_svgRareData || !m_svgRareData->correspondingElement() || correspondingUseElement());
     
    12081208void SVGElement::invalidateInstances()
    12091209{
    1210     if (!inDocument())
    1211         return;
    1212 
    12131210    if (instanceUpdatesBlocked())
    12141211        return;
    12151212
    12161213    auto& instances = this->instances();
    1217     if (instances.isEmpty())
    1218         return;
    1219 
    1220     // Mark all use elements referencing 'element' for rebuilding
    1221     do {
     1214    while (!instances.isEmpty()) {
    12221215        SVGElement* instance = *instances.begin();
    1223         if (SVGUseElement* element = instance->correspondingUseElement()) {
    1224             ASSERT(element->inDocument());
    1225             element->invalidateShadowTree();
    1226         }
     1216        if (SVGUseElement* useElement = instance->correspondingUseElement())
     1217            useElement->invalidateShadowTree();
    12271218        instance->setCorrespondingElement(nullptr);
    12281219    } while (!instances.isEmpty());
    1229 
    1230     // FIXME: Why is this needed?
    1231     document().updateStyleIfNeeded();
    1232 }
    1233 
    1234 }
     1220}
     1221
     1222}
  • trunk/Source/WebCore/svg/SVGElement.h

    r179695 r179807  
    114114    void cursorImageValueRemoved();
    115115
    116     SVGElement* correspondingElement();
     116    SVGElement* correspondingElement() const;
    117117    SVGUseElement* correspondingUseElement() const;
    118118
  • trunk/Source/WebCore/svg/SVGUseElement.cpp

    r179695 r179807  
    158158    if (!rootParent.inDocument())
    159159        return InsertionDone;
    160     ASSERT(!m_targetElementInstance || !isWellFormedDocument(document()));
    161160    ASSERT(!hasPendingResources() || !isWellFormedDocument(document()));
    162161    SVGExternalResourcesRequired::insertedIntoDocument(this);
     
    228227    if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr || attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr) {
    229228        updateRelativeLengthsInformation();
    230         if (m_targetElementInstance) {
     229        if (SVGElement* shadowTreeTargetClone = this->shadowTreeTargetClone()) {
    231230            // FIXME: It's unnecessarily inefficient to do this work any time we change "x" or "y".
    232231            // FIXME: It's unnecessarily inefficient to update both width and height each time either is changed.
    233             ASSERT(m_targetElementInstance->shadowTreeElement());
    234             transferSizeAttributesToShadowTreeTargetClone(*m_targetElementInstance->shadowTreeElement());
     232            transferSizeAttributesToShadowTreeTargetClone(*shadowTreeTargetClone);
    235233        }
    236234        if (auto* renderer = this->renderer())
     
    314312void SVGUseElement::clearResourceReferences()
    315313{
    316     // FIXME: We should try to optimize this, to at least allow partial reclones.
     314    // FIXME: It's expensive to re-clone the entire tree every time. We should find a more efficient way to handle this.
    317315    if (ShadowRoot* root = userAgentShadowRoot())
    318316        root->removeChildren();
    319 
    320     if (m_targetElementInstance) {
    321         m_targetElementInstance->detach();
    322         m_targetElementInstance = 0;
    323     }
    324 
    325317    m_needsShadowTreeRecreation = false;
    326 
    327     document().accessSVGExtensions().removeAllTargetReferencesForElement(this);
    328318}
    329319
    330320void SVGUseElement::buildPendingResource()
    331321{
    332     if (!referencedDocument() || isInShadowTree())
     322    if (isInShadowTree())
     323        return;
     324    if (!referencedDocument())
    333325        return;
    334326    clearResourceReferences();
     
    338330    String id;
    339331    Element* target = SVGURIReference::targetElementFromIRIString(href(), document(), &id, externalDocument());
    340     if (!target || !target->inDocument()) {
    341         // If we can't find the target of an external element, just give up.
    342         // We can't observe if the target somewhen enters the external document, nor should we do it.
    343         if (externalDocument())
     332    if (!isValidTarget(target)) {
     333        if (externalDocument()) {
     334            // We can't find the target in an external document, so just give up and don't try to do it again.
     335            // We should not attempt to observe if an element with ID shows up in the external document later.
    344336            return;
    345         if (id.isEmpty())
    346             return;
    347 
     337        }
    348338        referencedDocument()->accessSVGExtensions().addPendingResource(id, this);
    349         ASSERT(hasPendingResources());
    350         return;
    351     }
    352 
    353     if (target->isSVGElement()) {
    354         buildShadowAndInstanceTree(downcast<SVGElement>(*target));
    355         invalidateDependentShadowTrees();
    356     }
    357 
     339        return;
     340    }
     341
     342    buildShadowTree(downcast<SVGElement>(*target));
     343    expandUseElementsInShadowTree();
     344    expandSymbolElementsInShadowTree();
     345    transferSizeAttributesToShadowTreeTargetClone(*shadowTreeTargetClone());
     346    transferEventListenersToShadowTree();
     347    updateRelativeLengthsInformation();
     348
     349    // When we invalidate the other shadow trees, it's important that we don't
     350    // follow any cycles and invalidate ourselves. To avoid that, we temporarily
     351    // set m_needsShadowTreeRecreation to true so invalidateShadowTree will
     352    // quickly return and do nothing.
    358353    ASSERT(!m_needsShadowTreeRecreation);
     354    m_needsShadowTreeRecreation = true;
     355    invalidateDependentShadowTrees();
     356    m_needsShadowTreeRecreation = false;
    359357}
    360358
     
    365363        return nullptr;
    366364    return downcast<SVGElement>(root->firstChild());
    367 }
    368 
    369 void SVGUseElement::buildShadowAndInstanceTree(SVGElement& target)
    370 {
    371     ASSERT(!m_targetElementInstance);
    372 
    373     // Do not build the shadow/instance tree for <use> elements living in a shadow tree.
    374     // The will be expanded soon anyway - see expandUseElementsInShadowTree().
    375     if (isInShadowTree())
    376         return;
    377 
    378     // Do not allow self-referencing.
    379     if (&target == this)
    380         return;
    381 
    382     // Build instance tree.
    383     // Spec: If the 'use' element references a simple graphics element such as a 'rect', then there is only a
    384     // single SVGElementInstance object, and the correspondingElement attribute on this SVGElementInstance object
    385     // is the SVGRectElement that corresponds to the referenced 'rect' element.
    386     m_targetElementInstance = SVGElementInstance::create(this, this, &target);
    387 
    388     // Eventually enter recursion to build SVGElementInstance objects for the sub-tree children
    389     bool foundProblem = false;
    390     buildInstanceTree(&target, m_targetElementInstance.get(), foundProblem, false);
    391 
    392     if (instanceTreeIsLoading(m_targetElementInstance.get()))
    393         return;
    394 
    395     // SVG specification does not say a word about <use> and cycles. My view on this is: just ignore it!
    396     // Non-appearing <use> content is easier to debug, then half-appearing content.
    397     if (foundProblem) {
    398         clearResourceReferences();
    399         return;
    400     }
    401 
    402     // Assure instance tree building was successful.
    403     ASSERT(m_targetElementInstance);
    404     ASSERT(!m_targetElementInstance->shadowTreeElement());
    405     ASSERT(m_targetElementInstance->correspondingUseElement() == this);
    406     ASSERT(m_targetElementInstance->directUseElement() == this);
    407     ASSERT(m_targetElementInstance->correspondingElement() == &target);
    408 
    409     if (isDisallowedElement(target)) {
    410         clearResourceReferences();
    411         return;
    412     }
    413 
    414     buildShadowTree(target);
    415     expandUseElementsInShadowTree();
    416     expandSymbolElementsInShadowTree();
    417 
    418     ASSERT(shadowTreeTargetClone());
    419     SVGElement& shadowTreeTargetClone = *this->shadowTreeTargetClone();
    420     associateInstancesWithShadowTreeElements(&shadowTreeTargetClone, m_targetElementInstance.get());
    421 
    422     transferSizeAttributesToShadowTreeTargetClone(shadowTreeTargetClone);
    423 
    424     transferEventListenersToShadowTree();
    425     updateRelativeLengthsInformation();
    426365}
    427366
     
    471410}
    472411
    473 void SVGUseElement::buildInstanceTree(SVGElement* target, SVGElementInstance* targetInstance, bool& foundProblem, bool foundUse)
    474 {
    475     ASSERT(target);
    476     ASSERT(targetInstance);
    477 
    478     // Spec: If the referenced object is itself a 'use', or if there are 'use' subelements within the referenced
    479     // object, the instance tree will contain recursive expansion of the indirect references to form a complete tree.
    480     bool targetHasUseTag = target->hasTagName(SVGNames::useTag);
    481     SVGElement* newTarget = nullptr;
    482     if (targetHasUseTag) {
    483         foundProblem = hasCycleUseReferencing(downcast<SVGUseElement>(target), targetInstance, newTarget);
    484         if (foundProblem)
    485             return;
    486 
    487         // We only need to track first degree <use> dependencies. Indirect references are handled
    488         // as the invalidation bubbles up the dependency chain.
    489         if (!foundUse) {
    490             document().accessSVGExtensions().addElementReferencingTarget(this, target);
    491             foundUse = true;
    492         }
    493     } else if (isDisallowedElement(*target)) {
    494         foundProblem = true;
    495         return;
    496     }
    497 
    498     // A general description from the SVG spec, describing what buildInstanceTree() actually does.
    499     //
    500     // Spec: If the 'use' element references a 'g' which contains two 'rect' elements, then the instance tree
    501     // contains three SVGElementInstance objects, a root SVGElementInstance object whose correspondingElement
    502     // is the SVGGElement object for the 'g', and then two child SVGElementInstance objects, each of which has
    503     // its correspondingElement that is an SVGRectElement object.
    504 
    505     for (auto& element : childrenOfType<SVGElement>(*target)) {
    506         // Skip any non-svg nodes or any disallowed element.
    507         if (isDisallowedElement(element))
    508             continue;
    509 
    510         // Create SVGElementInstance object, for both container/non-container nodes.
    511         RefPtr<SVGElementInstance> instance = SVGElementInstance::create(this, 0, &element);
    512         SVGElementInstance* instancePtr = instance.get();
    513         targetInstance->appendChild(instance.release());
    514 
    515         // Enter recursion, appending new instance tree nodes to the "instance" object.
    516         buildInstanceTree(&element, instancePtr, foundProblem, foundUse);
    517         if (foundProblem)
    518             return;
    519     }
    520 
    521     if (!targetHasUseTag || !newTarget)
    522         return;
    523 
    524     RefPtr<SVGElementInstance> newInstance = SVGElementInstance::create(this, downcast<SVGUseElement>(target), newTarget);
    525     SVGElementInstance* newInstancePtr = newInstance.get();
    526     targetInstance->appendChild(newInstance.release());
    527     buildInstanceTree(newTarget, newInstancePtr, foundProblem, foundUse);
    528 }
    529 
    530 bool SVGUseElement::hasCycleUseReferencing(SVGUseElement* use, SVGElementInstance* targetInstance, SVGElement*& newTarget)
    531 {
    532     ASSERT(referencedDocument());
    533     Element* targetElement = SVGURIReference::targetElementFromIRIString(use->href(), *referencedDocument());
    534     newTarget = nullptr;
    535     if (targetElement && targetElement->isSVGElement())
    536         newTarget = downcast<SVGElement>(targetElement);
    537 
    538     if (!newTarget)
    539         return false;
    540 
    541     // Shortcut for self-references
    542     if (newTarget == this)
    543         return true;
    544 
    545     AtomicString targetId = newTarget->getIdAttribute();
    546     SVGElementInstance* instance = targetInstance->parentNode();
    547     while (instance) {
    548         SVGElement* element = instance->correspondingElement();
    549 
    550         if (element->hasID() && element->getIdAttribute() == targetId && &element->document() == &newTarget->document())
    551             return true;
    552 
    553         instance = instance->parentNode();
    554     }
    555     return false;
    556 }
    557 
    558412static void removeDisallowedElementsFromSubtree(SVGElement& subtree)
    559413{
     
    581435}
    582436
     437static void associateClonesWithOriginals(SVGElement& clone, SVGElement& original)
     438{
     439    // This assertion checks that we don't call this with the arguments backwards.
     440    // The clone is new and so it's not installed in a parent yet.
     441    ASSERT(!clone.parentNode());
     442
     443    // The loop below works because we are associating these clones immediately, before
     444    // doing transformations like removing disallowed elements or expanding elements.
     445    clone.setCorrespondingElement(&original);
     446    for (auto pair : descendantsOfType<SVGElement>(clone, original))
     447        pair.first.setCorrespondingElement(&pair.second);
     448}
     449
     450static void associateReplacementCloneWithOriginal(SVGElement& replacementClone, SVGElement& originalClone)
     451{
     452    SVGElement* correspondingElement = originalClone.correspondingElement();
     453    ASSERT(correspondingElement);
     454    originalClone.setCorrespondingElement(nullptr);
     455    replacementClone.setCorrespondingElement(correspondingElement);
     456}
     457
     458static void associateReplacementClonesWithOriginals(SVGElement& replacementClone, SVGElement& originalClone)
     459{
     460    // This assertion checks that we don't call this with the arguments backwards.
     461    // The replacement clone is new and so it's not installed in a parent yet.
     462    ASSERT(!replacementClone.parentNode());
     463
     464    // The loop below works because we are associating these clones immediately, before
     465    // doing transformations like removing disallowed elements or expanding elements.
     466    associateReplacementCloneWithOriginal(replacementClone, originalClone);
     467    for (auto pair : descendantsOfType<SVGElement>(replacementClone, originalClone))
     468        associateReplacementCloneWithOriginal(pair.first, pair.second);
     469}
     470
    583471void SVGUseElement::buildShadowTree(SVGElement& target)
    584472{
    585473    Ref<SVGElement> clonedTarget = static_pointer_cast<SVGElement>(target.cloneElementWithChildren(document())).releaseNonNull();
     474    associateClonesWithOriginals(clonedTarget.get(), target);
    586475    removeDisallowedElementsFromSubtree(clonedTarget.get());
    587476    ensureUserAgentShadowRoot().appendChild(WTF::move(clonedTarget));
    588477}
    589478
     479bool SVGUseElement::isValidTarget(Element* target) const
     480{
     481    if (!is<SVGElement>(target))
     482        return false;
     483    if (!target->inDocument())
     484        return false;
     485    SVGElement& castedTarget = downcast<SVGElement>(*target);
     486    if (&castedTarget == this)
     487        return false;
     488    if (isDisallowedElement(castedTarget))
     489        return false;
     490    // Reject any target that would create a cycle.
     491    for (auto& ancestor : lineageOfType<SVGElement>(*this)) {
     492        if (ancestor.correspondingElement() == &castedTarget)
     493            return false;
     494    }
     495    return true;
     496}
     497
    590498void SVGUseElement::expandUseElementsInShadowTree()
    591499{
    592     // Why expand the <use> elements in the shadow tree here, and not just
    593     // do this directly in buildShadowTree, as we encounter each <use> element?
    594     // Because we might miss expanding some elements if we did it then. If a <symbol>
    595     // contained <use> elements, we'd miss those.
     500    // FIXME: Combine this with buildShadowTree.
     501
     502    if (cachedDocumentIsStillLoading())
     503        return;
    596504
    597505    auto descendants = descendantsOfType<SVGUseElement>(*userAgentShadowRoot());
     
    601509        it = end; // Efficiently quiets assertions due to the outstanding iterator.
    602510
    603         ASSERT(!original->cachedDocumentIsStillLoading());
     511        if (original->cachedDocumentIsStillLoading())
     512            return;
    604513
    605514        // Spec: In the generated content, the 'use' will be replaced by 'g', where all attributes from the
     
    611520        ASSERT(referencedDocument());
    612521        auto replacement = SVGGElement::create(SVGNames::gTag, *referencedDocument());
    613 
    614522        original->transferAttributesToShadowTreeReplacement(replacement.get());
    615523        original->cloneChildNodes(replacement.ptr());
     524        associateReplacementClonesWithOriginals(replacement.get(), original.get());
    616525
    617526        RefPtr<SVGElement> clonedTarget;
    618527        Element* targetCandidate = SVGURIReference::targetElementFromIRIString(original->href(), *referencedDocument());
    619         if (is<SVGElement>(targetCandidate) && !isDisallowedElement(downcast<SVGElement>(*targetCandidate))) {
     528        if (original->isValidTarget(targetCandidate)) {
    620529            SVGElement& originalTarget = downcast<SVGElement>(*targetCandidate);
    621530            clonedTarget = static_pointer_cast<SVGElement>(originalTarget.cloneElementWithChildren(document()));
    622             // Set the corresponding element here so transferSizeAttributesToShadowTreeTargetClone
    623             // can use it. It will be set again later in associateInstancesWithShadowTreeElements,
    624             // but it does no harm to set it twice.
    625             clonedTarget->setCorrespondingElement(&originalTarget);
     531            associateClonesWithOriginals(*clonedTarget, originalTarget);
    626532            replacement->appendChild(clonedTarget);
    627533        }
     
    664570        replacement->cloneDataFromElement(original);
    665571        original.cloneChildNodes(replacement.ptr());
     572        associateReplacementClonesWithOriginals(replacement.get(), original);
     573
    666574        removeDisallowedElementsFromSubtree(replacement.get());
    667575
     
    684592}
    685593
    686 void SVGUseElement::associateInstancesWithShadowTreeElements(Node* target, SVGElementInstance* targetInstance)
    687 {
    688     if (!target || !targetInstance)
    689         return;
    690 
    691     SVGElement* originalElement = targetInstance->correspondingElement();
    692 
    693     if (originalElement->hasTagName(SVGNames::useTag)) {
    694         // <use> gets replaced by <g>
    695         ASSERT(target->nodeName() == SVGNames::gTag);
    696     } else if (originalElement->hasTagName(SVGNames::symbolTag)) {
    697         // <symbol> gets replaced by <svg>
    698         ASSERT(target->nodeName() == SVGNames::svgTag);
    699     } else
    700         ASSERT(target->nodeName() == originalElement->nodeName());
    701 
    702     SVGElement* element = nullptr;
    703     if (target->isSVGElement())
    704         element = downcast<SVGElement>(target);
    705 
    706     ASSERT(!targetInstance->shadowTreeElement());
    707     targetInstance->setShadowTreeElement(element);
    708     element->setCorrespondingElement(originalElement);
    709 
    710     Node* node = target->firstChild();
    711     for (SVGElementInstance* instance = targetInstance->firstChild(); node && instance; instance = instance->nextSibling()) {
    712         // Skip any non-svg elements in shadow tree
    713         while (node && !node->isSVGElement())
    714            node = node->nextSibling();
    715 
    716         if (!node)
    717             break;
    718 
    719         associateInstancesWithShadowTreeElements(node, instance);
    720         node = node->nextSibling();
    721     }
    722 }
    723 
    724 SVGElementInstance* SVGUseElement::instanceForShadowTreeElement(Node* element) const
    725 {
    726     if (!m_targetElementInstance) {
    727         ASSERT(!inDocument());
    728         return 0;
    729     }
    730 
    731     return instanceForShadowTreeElement(element, m_targetElementInstance.get());
    732 }
    733 
    734 SVGElementInstance* SVGUseElement::instanceForShadowTreeElement(Node* element, SVGElementInstance* instance) const
    735 {
    736     ASSERT(element);
    737     ASSERT(instance);
    738 
    739     // We're dispatching a mutation event during shadow tree construction
    740     // this instance hasn't yet been associated to a shadowTree element.
    741     if (!instance->shadowTreeElement())
    742         return 0;
    743 
    744     if (element == instance->shadowTreeElement())
    745         return instance;
    746 
    747     for (SVGElementInstance* current = instance->firstChild(); current; current = current->nextSibling()) {
    748         if (SVGElementInstance* search = instanceForShadowTreeElement(element, current))
    749             return search;
    750     }
    751 
    752     return 0;
    753 }
    754 
    755594void SVGUseElement::invalidateShadowTree()
    756595{
     
    764603void SVGUseElement::invalidateDependentShadowTrees()
    765604{
    766     // Recursively invalidate dependent <use> shadow trees
    767605    for (auto* instance : instances()) {
    768606        if (SVGUseElement* element = instance->correspondingUseElement()) {
  • trunk/Source/WebCore/svg/SVGUseElement.h

    r179391 r179807  
    3535
    3636class CachedSVGDocument;
    37 class SVGElementInstance;
    3837class SVGGElement;
    3938
     
    4645    virtual ~SVGUseElement();
    4746
    48     SVGElementInstance* instanceForShadowTreeElement(Node*) const;
    4947    void invalidateShadowTree();
    5048    void invalidateDependentShadowTrees();
     
    7472
    7573    void clearResourceReferences();
    76     void buildShadowAndInstanceTree(SVGElement& target);
    77     void detachInstance();
    7874
    7975    virtual bool haveLoadedRequiredResources() override { return SVGExternalResourcesRequired::haveLoadedRequiredResources(); }
     
    8177    virtual void finishParsingChildren() override;
    8278    virtual bool selfHasRelativeLengths() const override;
    83 
    84     // Instance tree handling
    85     void buildInstanceTree(SVGElement* target, SVGElementInstance* targetInstance, bool& foundCycle, bool foundUse);
    86     bool hasCycleUseReferencing(SVGUseElement*, SVGElementInstance* targetInstance, SVGElement*& newTarget);
    8779
    8880    // Shadow tree handling.
     
    9486    void transferAttributesToShadowTreeReplacement(SVGGElement&) const;
    9587    void transferSizeAttributesToShadowTreeTargetClone(SVGElement&) const;
    96 
    97     // "Tree connector"
    98     void associateInstancesWithShadowTreeElements(Node* target, SVGElementInstance* targetInstance);
    99     SVGElementInstance* instanceForShadowTreeElement(Node* element, SVGElementInstance* instance) const;
     88    bool isValidTarget(Element*) const;
    10089
    10190    BEGIN_DECLARE_ANIMATED_PROPERTIES(SVGUseElement)
     
    124113    bool m_haveFiredLoadEvent;
    125114    bool m_needsShadowTreeRecreation;
    126     RefPtr<SVGElementInstance> m_targetElementInstance;
    127115    CachedResourceHandle<CachedSVGDocument> m_cachedDocument;
    128116    Timer m_svgLoadEventTimer;
Note: See TracChangeset for help on using the changeset viewer.