Index: third_party/WebKit/Source/core/svg/SVGUseElement.cpp |
diff --git a/third_party/WebKit/Source/core/svg/SVGUseElement.cpp b/third_party/WebKit/Source/core/svg/SVGUseElement.cpp |
index f3cad1adf6227e6d6736a3f9b35cf8f2a3a16be1..681abed9465765101428ab9ab9c9919a64bea4ea 100644 |
--- a/third_party/WebKit/Source/core/svg/SVGUseElement.cpp |
+++ b/third_party/WebKit/Source/core/svg/SVGUseElement.cpp |
@@ -364,6 +364,28 @@ static void associateCorrespondingElements(SVGElement& targetRoot, SVGElement& i |
ASSERT(!(targetIterator != targetRange.end())); |
} |
+// We don't walk the target tree element-by-element, and clone each element, |
+// but instead use cloneNode(deep=true). This is an optimization for the common |
+// case where <use> doesn't contain disallowed elements (ie. <foreignObject>). |
+// Though if there are disallowed elements in the subtree, we have to remove |
+// them. For instance: <use> on <g> containing <foreignObject> (indirect |
+// case). |
+static inline void removeDisallowedElementsFromSubtree(SVGElement& subtree) |
+{ |
+ ASSERT(!subtree.inDocument()); |
+ Element* element = ElementTraversal::firstWithin(subtree); |
+ while (element) { |
+ if (isDisallowedElement(*element)) { |
+ Element* next = ElementTraversal::nextSkippingChildren(*element, &subtree); |
+ // The subtree is not in document so this won't generate events that could mutate the tree. |
+ element->parentNode()->removeChild(element); |
+ element = next; |
+ } else { |
+ element = ElementTraversal::next(*element, &subtree); |
+ } |
+ } |
+} |
+ |
void SVGUseElement::buildShadowAndInstanceTree(SVGElement& target) |
{ |
ASSERT(!m_targetElementInstance); |
@@ -380,16 +402,15 @@ void SVGUseElement::buildShadowAndInstanceTree(SVGElement& target) |
return; |
// Set up root SVG element in shadow tree. |
- RefPtrWillBeRawPtr<Element> newChild = target.cloneElementWithoutChildren(); |
- m_targetElementInstance = toSVGElement(newChild.get()); |
- ShadowRoot* shadowTreeRootElement = userAgentShadowRoot(); |
- shadowTreeRootElement->appendChild(newChild.release()); |
- |
// Clone the target subtree into the shadow tree, not handling <use> and <symbol> yet. |
+ RefPtrWillBeRawPtr<Element> instanceRoot = target.cloneElementWithChildren(); |
+ ASSERT(instanceRoot->isSVGElement()); |
+ associateCorrespondingElements(target, toSVGElement(*instanceRoot)); |
+ removeDisallowedElementsFromSubtree(toSVGElement(*instanceRoot)); |
- // SVG specification does not say a word about <use> & cycles. My view on this is: just ignore it! |
- // Non-appearing <use> content is easier to debug, then half-appearing content. |
- buildShadowTree(target, *m_targetElementInstance); |
+ m_targetElementInstance = toSVGElement(instanceRoot.get()); |
+ ShadowRoot* shadowTreeRootElement = userAgentShadowRoot(); |
+ shadowTreeRootElement->appendChild(instanceRoot.release()); |
addReferencesToFirstDegreeNestedUseElements(target); |
@@ -496,26 +517,6 @@ void SVGUseElement::addReferencesToFirstDegreeNestedUseElements(SVGElement& targ |
addReferenceTo(useElement); |
} |
-void SVGUseElement::buildShadowTree(SVGElement& target, SVGElement& targetInstance) |
-{ |
- ASSERT(!isDisallowedElement(target)); |
- |
- targetInstance.setCorrespondingElement(&target); |
- |
- for (RefPtrWillBeRawPtr<Node> child = target.firstChild(); child; child = child->nextSibling()) { |
- // Skip any disallowed element. |
- if (isDisallowedElement(*child)) |
- continue; |
- |
- RefPtrWillBeRawPtr<Node> newChild = child->cloneNode(false); |
- targetInstance.appendChild(newChild.get()); |
- if (newChild->isSVGElement()) { |
- // Enter recursion, appending new instance tree nodes to the "instance" object. |
- buildShadowTree(toSVGElement(*child), toSVGElement(*newChild)); |
- } |
- } |
-} |
- |
void SVGUseElement::cloneNonMarkupEventListeners() |
{ |
for (SVGElement& element : Traversal<SVGElement>::descendantsOf(*userAgentShadowRoot())) { |
@@ -550,28 +551,6 @@ bool SVGUseElement::hasCycleUseReferencing(const SVGUseElement& use, const Conta |
return false; |
} |
-// We don't walk the target tree element-by-element, and clone each element, |
-// but instead use cloneNode(deep=true). This is an optimization for the common |
-// case where <use> doesn't contain disallowed elements (ie. <foreignObject>). |
-// Though if there are disallowed elements in the subtree, we have to remove |
-// them. For instance: <use> on <g> containing <foreignObject> (indirect |
-// case). |
-static inline void removeDisallowedElementsFromSubtree(SVGElement& subtree) |
-{ |
- ASSERT(!subtree.inDocument()); |
- Element* element = ElementTraversal::firstWithin(subtree); |
- while (element) { |
- if (isDisallowedElement(*element)) { |
- Element* next = ElementTraversal::nextSkippingChildren(*element, &subtree); |
- // The subtree is not in document so this won't generate events that could mutate the tree. |
- element->parentNode()->removeChild(element); |
- element = next; |
- } else { |
- element = ElementTraversal::next(*element, &subtree); |
- } |
- } |
-} |
- |
static void moveChildrenToReplacementElement(ContainerNode& sourceRoot, ContainerNode& destinationRoot) |
{ |
for (RefPtrWillBeRawPtr<Node> child = sourceRoot.firstChild(); child; ) { |