Use is<>() / downcast<>() for Element
[WebKit-https.git] / Source / WebCore / svg / SVGUseElement.cpp
index baa7175..667cdfc 100644 (file)
@@ -51,6 +51,7 @@
 #include "XLinkNames.h"
 #include "XMLDocumentParser.h"
 #include "XMLSerializer.h"
+#include <wtf/NeverDestroyed.h>
 
 // Dump SVGElementInstance object tree - useful to debug instanceRoot problems
 // #define DUMP_INSTANCE_TREE
@@ -129,17 +130,17 @@ SVGElementInstance* SVGUseElement::animatedInstanceRoot() const
 
 bool SVGUseElement::isSupportedAttribute(const QualifiedName& attrName)
 {
-    DEPRECATED_DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
-    if (supportedAttributes.isEmpty()) {
+    static NeverDestroyed<HashSet<QualifiedName>> supportedAttributes;
+    if (supportedAttributes.get().isEmpty()) {
         SVGLangSpace::addSupportedAttributes(supportedAttributes);
         SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes);
         SVGURIReference::addSupportedAttributes(supportedAttributes);
-        supportedAttributes.add(SVGNames::xAttr);
-        supportedAttributes.add(SVGNames::yAttr);
-        supportedAttributes.add(SVGNames::widthAttr);
-        supportedAttributes.add(SVGNames::heightAttr);
+        supportedAttributes.get().add(SVGNames::xAttr);
+        supportedAttributes.get().add(SVGNames::yAttr);
+        supportedAttributes.get().add(SVGNames::widthAttr);
+        supportedAttributes.get().add(SVGNames::heightAttr);
     }
-    return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
+    return supportedAttributes.get().contains<SVGAttributeHashTranslator>(attrName);
 }
 
 void SVGUseElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
@@ -182,12 +183,17 @@ Node::InsertionNotificationRequest SVGUseElement::insertedInto(ContainerNode& ro
         return InsertionDone;
     ASSERT(!m_targetElementInstance || !isWellFormedDocument(document()));
     ASSERT(!hasPendingResources() || !isWellFormedDocument(document()));
-    if (!m_wasInsertedByParser)
-        buildPendingResource();
     SVGExternalResourcesRequired::insertedIntoDocument(this);
+    if (!m_wasInsertedByParser)
+        return InsertionShouldCallDidNotifySubtreeInsertions;
     return InsertionDone;
 }
 
+void SVGUseElement::didNotifySubtreeInsertions(ContainerNode*)
+{
+    buildPendingResource();
+}
+
 void SVGUseElement::removedFrom(ContainerNode& rootParent)
 {
     SVGGraphicsElement::removedFrom(rootParent);
@@ -276,8 +282,8 @@ static void dumpInstanceTree(unsigned int& depth, String& text, SVGElementInstan
     SVGElement* element = targetInstance->correspondingElement();
     ASSERT(element);
 
-    if (element->hasTagName(SVGNames::useTag)) {
-        if (toSVGUseElement(element)->cachedDocumentIsStillLoading())
+    if (is<SVGUseElement>(element)) {
+        if (downcast<SVGUseElement>(*element).cachedDocumentIsStillLoading())
             return;
     }
 
@@ -334,31 +340,31 @@ static bool isDisallowedElement(const Element& element)
     if (!element.isSVGElement())
         return true;
 
-    DEPRECATED_DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, allowedElementTags, ());
-    if (allowedElementTags.isEmpty()) {
-        allowedElementTags.add(SVGNames::aTag);
-        allowedElementTags.add(SVGNames::circleTag);
-        allowedElementTags.add(SVGNames::descTag);
-        allowedElementTags.add(SVGNames::ellipseTag);
-        allowedElementTags.add(SVGNames::gTag);
-        allowedElementTags.add(SVGNames::imageTag);
-        allowedElementTags.add(SVGNames::lineTag);
-        allowedElementTags.add(SVGNames::metadataTag);
-        allowedElementTags.add(SVGNames::pathTag);
-        allowedElementTags.add(SVGNames::polygonTag);
-        allowedElementTags.add(SVGNames::polylineTag);
-        allowedElementTags.add(SVGNames::rectTag);
-        allowedElementTags.add(SVGNames::svgTag);
-        allowedElementTags.add(SVGNames::switchTag);
-        allowedElementTags.add(SVGNames::symbolTag);
-        allowedElementTags.add(SVGNames::textTag);
-        allowedElementTags.add(SVGNames::textPathTag);
-        allowedElementTags.add(SVGNames::titleTag);
-        allowedElementTags.add(SVGNames::trefTag);
-        allowedElementTags.add(SVGNames::tspanTag);
-        allowedElementTags.add(SVGNames::useTag);
+    static NeverDestroyed<HashSet<QualifiedName>> allowedElementTags;
+    if (allowedElementTags.get().isEmpty()) {
+        allowedElementTags.get().add(SVGNames::aTag);
+        allowedElementTags.get().add(SVGNames::circleTag);
+        allowedElementTags.get().add(SVGNames::descTag);
+        allowedElementTags.get().add(SVGNames::ellipseTag);
+        allowedElementTags.get().add(SVGNames::gTag);
+        allowedElementTags.get().add(SVGNames::imageTag);
+        allowedElementTags.get().add(SVGNames::lineTag);
+        allowedElementTags.get().add(SVGNames::metadataTag);
+        allowedElementTags.get().add(SVGNames::pathTag);
+        allowedElementTags.get().add(SVGNames::polygonTag);
+        allowedElementTags.get().add(SVGNames::polylineTag);
+        allowedElementTags.get().add(SVGNames::rectTag);
+        allowedElementTags.get().add(SVGNames::svgTag);
+        allowedElementTags.get().add(SVGNames::switchTag);
+        allowedElementTags.get().add(SVGNames::symbolTag);
+        allowedElementTags.get().add(SVGNames::textTag);
+        allowedElementTags.get().add(SVGNames::textPathTag);
+        allowedElementTags.get().add(SVGNames::titleTag);
+        allowedElementTags.get().add(SVGNames::trefTag);
+        allowedElementTags.get().add(SVGNames::tspanTag);
+        allowedElementTags.get().add(SVGNames::useTag);
     }
-    return !allowedElementTags.contains<SVGAttributeHashTranslator>(element.tagQName());
+    return !allowedElementTags.get().contains<SVGAttributeHashTranslator>(element.tagQName());
 }
 
 static bool subtreeContainsDisallowedElement(SVGElement& start)
@@ -384,7 +390,7 @@ void SVGUseElement::clearResourceReferences()
 
     m_needsShadowTreeRecreation = false;
 
-    document().accessSVGExtensions()->removeAllTargetReferencesForElement(this);
+    document().accessSVGExtensions().removeAllTargetReferencesForElement(this);
 }
 
 void SVGUseElement::buildPendingResource()
@@ -405,13 +411,13 @@ void SVGUseElement::buildPendingResource()
         if (id.isEmpty())
             return;
 
-        referencedDocument()->accessSVGExtensions()->addPendingResource(id, this);
+        referencedDocument()->accessSVGExtensions().addPendingResource(id, this);
         ASSERT(hasPendingResources());
         return;
     }
 
     if (target->isSVGElement()) {
-        buildShadowAndInstanceTree(toSVGElement(target));
+        buildShadowAndInstanceTree(downcast<SVGElement>(target));
         invalidateDependentShadowTrees();
     }
 
@@ -519,7 +525,7 @@ void SVGUseElement::buildShadowAndInstanceTree(SVGElement* target)
 
 RenderPtr<RenderElement> SVGUseElement::createElementRenderer(PassRef<RenderStyle> style)
 {
-    return createRenderer<RenderSVGTransformableContainer>(*this, std::move(style));
+    return createRenderer<RenderSVGTransformableContainer>(*this, WTF::move(style));
 }
 
 static bool isDirectReference(const SVGElement& element)
@@ -537,16 +543,16 @@ void SVGUseElement::toClipPath(Path& path)
 {
     ASSERT(path.isEmpty());
 
-    Node* n = m_targetElementInstance ? m_targetElementInstance->shadowTreeElement() : 0;
-    if (!n)
+    SVGElement* element = m_targetElementInstance ? m_targetElementInstance->shadowTreeElement() : nullptr;
+    if (!element)
         return;
 
-    if (n->isSVGElement() && toSVGElement(*n).isSVGGraphicsElement()) {
-        if (!isDirectReference(toSVGElement(*n))) {
+    if (is<SVGGraphicsElement>(element)) {
+        if (!isDirectReference(*element)) {
             // Spec: Indirect references are an error (14.3.5)
-            document().accessSVGExtensions()->reportError("Not allowed to use indirect reference in <clip-path>");
+            document().accessSVGExtensions().reportError("Not allowed to use indirect reference in <clip-path>");
         } else {
-            toSVGGraphicsElement(*n).toClipPath(path);
+            downcast<SVGGraphicsElement>(*element).toClipPath(path);
             // FIXME: Avoid manual resolution of x/y here. Its potentially harmful.
             SVGLengthContext lengthContext(this);
             path.translate(FloatSize(x().value(lengthContext), y().value(lengthContext)));
@@ -578,16 +584,16 @@ void SVGUseElement::buildInstanceTree(SVGElement* target, SVGElementInstance* ta
     // Spec: If the referenced object is itself a 'use', or if there are 'use' subelements within the referenced
     // object, the instance tree will contain recursive expansion of the indirect references to form a complete tree.
     bool targetHasUseTag = target->hasTagName(SVGNames::useTag);
-    SVGElement* newTarget = 0;
+    SVGElement* newTarget = nullptr;
     if (targetHasUseTag) {
-        foundProblem = hasCycleUseReferencing(toSVGUseElement(target), targetInstance, newTarget);
+        foundProblem = hasCycleUseReferencing(downcast<SVGUseElement>(target), targetInstance, newTarget);
         if (foundProblem)
             return;
 
         // We only need to track first degree <use> dependencies. Indirect references are handled
         // as the invalidation bubbles up the dependency chain.
         if (!foundUse) {
-            document().accessSVGExtensions()->addElementReferencingTarget(this, target);
+            document().accessSVGExtensions().addElementReferencingTarget(this, target);
             foundUse = true;
         }
     } else if (isDisallowedElement(*target)) {
@@ -621,7 +627,7 @@ void SVGUseElement::buildInstanceTree(SVGElement* target, SVGElementInstance* ta
     if (!targetHasUseTag || !newTarget)
         return;
 
-    RefPtr<SVGElementInstance> newInstance = SVGElementInstance::create(this, toSVGUseElement(target), newTarget);
+    RefPtr<SVGElementInstance> newInstance = SVGElementInstance::create(this, downcast<SVGUseElement>(target), newTarget);
     SVGElementInstance* newInstancePtr = newInstance.get();
     targetInstance->appendChild(newInstance.release());
     buildInstanceTree(newTarget, newInstancePtr, foundProblem, foundUse);
@@ -631,9 +637,9 @@ bool SVGUseElement::hasCycleUseReferencing(SVGUseElement* use, SVGElementInstanc
 {
     ASSERT(referencedDocument());
     Element* targetElement = SVGURIReference::targetElementFromIRIString(use->href(), *referencedDocument());
-    newTarget = 0;
+    newTarget = nullptr;
     if (targetElement && targetElement->isSVGElement())
-        newTarget = toSVGElement(targetElement);
+        newTarget = downcast<SVGElement>(targetElement);
 
     if (!newTarget)
         return false;
@@ -704,24 +710,24 @@ void SVGUseElement::expandUseElementsInShadowTree(Node* element)
     // contains <use> tags, we'd miss them. So once we're done with settin' up the
     // actual shadow tree (after the special case modification for svg/symbol) we have
     // to walk it completely and expand all <use> elements.
-    if (element->hasTagName(SVGNames::useTag)) {
-        SVGUseElement* use = toSVGUseElement(element);
-        ASSERT(!use->cachedDocumentIsStillLoading());
+    if (is<SVGUseElement>(element)) {
+        SVGUseElement& use = downcast<SVGUseElement>(*element);
+        ASSERT(!use.cachedDocumentIsStillLoading());
 
         ASSERT(referencedDocument());
-        Element* targetElement = SVGURIReference::targetElementFromIRIString(use->href(), *referencedDocument());
-        SVGElement* target = 0;
+        Element* targetElement = SVGURIReference::targetElementFromIRIString(use.href(), *referencedDocument());
+        SVGElement* target = nullptr;
         if (targetElement && targetElement->isSVGElement())
-            target = toSVGElement(targetElement);
+            target = downcast<SVGElement>(targetElement);
 
         // Don't ASSERT(target) here, it may be "pending", too.
         // Setup sub-shadow tree root node
         RefPtr<SVGGElement> cloneParent = SVGGElement::create(SVGNames::gTag, *referencedDocument());
-        use->cloneChildNodes(cloneParent.get());
+        use.cloneChildNodes(cloneParent.get());
 
         // Spec: In the generated content, the 'use' will be replaced by 'g', where all attributes from the
         // 'use' element except for x, y, width, height and xlink:href are transferred to the generated 'g' element.
-        transferUseAttributesToReplacedElement(use, cloneParent.get());
+        transferUseAttributesToReplacedElement(&use, cloneParent.get());
 
         if (target && !isDisallowedElement(*target)) {
             RefPtr<Element> newChild = target->cloneElementWithChildren();
@@ -740,8 +746,8 @@ void SVGUseElement::expandUseElementsInShadowTree(Node* element)
         RefPtr<Node> replacingElement(cloneParent.get());
 
         // Replace <use> with referenced content.
-        ASSERT(use->parentNode());
-        use->parentNode()->replaceChild(cloneParent.release(), use);
+        ASSERT(use.parentNode());
+        use.parentNode()->replaceChild(cloneParent.release(), &use);
 
         // Expand the siblings because the *element* is replaced and we will
         // lose the sibling chain when we are back from recursion.
@@ -754,9 +760,9 @@ void SVGUseElement::expandUseElementsInShadowTree(Node* element)
         expandUseElementsInShadowTree(child.get());
 }
 
-void SVGUseElement::expandSymbolElementsInShadowTree(Node* element)
+void SVGUseElement::expandSymbolElementsInShadowTree(Node* node)
 {
-    if (element->hasTagName(SVGNames::symbolTag)) {
+    if (is<SVGSymbolElement>(node)) {
         // Spec: The referenced 'symbol' and its contents are deep-cloned into the generated tree,
         // with the exception that the 'symbol' is replaced by an 'svg'. This generated 'svg' will
         // always have explicit values for attributes width and height. If attributes width and/or
@@ -766,10 +772,10 @@ void SVGUseElement::expandSymbolElementsInShadowTree(Node* element)
         RefPtr<SVGSVGElement> svgElement = SVGSVGElement::create(SVGNames::svgTag, *referencedDocument());
 
         // Transfer all data (attributes, etc.) from <symbol> to the new <svg> element.
-        svgElement->cloneDataFromElement(*toElement(element));
+        svgElement->cloneDataFromElement(downcast<SVGSymbolElement>(*node));
 
         // Only clone symbol children, and add them to the new <svg> element
-        for (Node* child = element->firstChild(); child; child = child->nextSibling()) {
+        for (Node* child = node->firstChild(); child; child = child->nextSibling()) {
             RefPtr<Node> newChild = child->cloneNode(true);
             svgElement->appendChild(newChild.release());
         }
@@ -782,19 +788,19 @@ void SVGUseElement::expandSymbolElementsInShadowTree(Node* element)
         if (subtreeContainsDisallowedElement(*svgElement))
             removeDisallowedElementsFromSubtree(*svgElement);
 
-        RefPtr<Node> replacingElement(svgElement.get());
+        RefPtr<SVGSVGElement> replacingElement(svgElement.get());
 
         // Replace <symbol> with <svg>.
-        element->parentNode()->replaceChild(svgElement.release(), element);
+        node->parentNode()->replaceChild(svgElement.release(), node);
 
         // Expand the siblings because the *element* is replaced and we will
         // lose the sibling chain when we are back from recursion.
-        element = replacingElement.get();
-        for (RefPtr<Node> sibling = element->nextSibling(); sibling; sibling = sibling->nextSibling())
+        node = replacingElement.get();
+        for (RefPtr<Node> sibling = node->nextSibling(); sibling; sibling = sibling->nextSibling())
             expandSymbolElementsInShadowTree(sibling.get());
     }
 
-    for (RefPtr<Node> child = element->firstChild(); child; child = child->nextSibling())
+    for (RefPtr<Node> child = node->firstChild(); child; child = child->nextSibling())
         expandSymbolElementsInShadowTree(child.get());
 }
 
@@ -831,9 +837,9 @@ void SVGUseElement::associateInstancesWithShadowTreeElements(Node* target, SVGEl
     } else
         ASSERT(target->nodeName() == originalElement->nodeName());
 
-    SVGElement* element = 0;
+    SVGElement* element = nullptr;
     if (target->isSVGElement())
-        element = toSVGElement(target);
+        element = downcast<SVGElement>(target);
 
     ASSERT(!targetInstance->shadowTreeElement());
     targetInstance->setShadowTreeElement(element);