Node::document() should return a reference.
[WebKit-https.git] / Source / WebCore / svg / SVGScriptElement.cpp
index b812d5d..325e4a0 100644 (file)
 #include "Event.h"
 #include "EventNames.h"
 #include "HTMLNames.h"
-#include "SVGNames.h"
+#include "SVGAnimatedStaticPropertyTearOff.h"
+#include "SVGElementInstance.h"
 #include "ScriptEventListener.h"
+#include "XLinkNames.h"
 
 namespace WebCore {
 
@@ -37,11 +39,18 @@ namespace WebCore {
 DEFINE_ANIMATED_STRING(SVGScriptElement, XLinkNames::hrefAttr, Href, href)
 DEFINE_ANIMATED_BOOLEAN(SVGScriptElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
 
+BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGScriptElement)
+    REGISTER_LOCAL_ANIMATED_PROPERTY(href)
+    REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired)
+END_REGISTER_ANIMATED_PROPERTIES
+
 inline SVGScriptElement::SVGScriptElement(const QualifiedName& tagName, Document* document, bool wasInsertedByParser, bool alreadyStarted)
     : SVGElement(tagName, document)
     , ScriptElement(this, wasInsertedByParser, alreadyStarted)
+    , m_svgLoadEventTimer(this, &SVGElement::svgLoadEventTimerFired)
 {
     ASSERT(hasTagName(SVGNames::scriptTag));
+    registerAnimatedPropertiesForSVGScriptElement();
 }
 
 PassRefPtr<SVGScriptElement> SVGScriptElement::create(const QualifiedName& tagName, Document* document, bool insertedByParser)
@@ -49,109 +58,90 @@ PassRefPtr<SVGScriptElement> SVGScriptElement::create(const QualifiedName& tagNa
     return adoptRef(new SVGScriptElement(tagName, document, insertedByParser, false));
 }
 
-void SVGScriptElement::parseMappedAttribute(Attribute* attr)
+bool SVGScriptElement::isSupportedAttribute(const QualifiedName& attrName)
 {
-    const QualifiedName& attrName = attr->name();
-
-    if (attrName == SVGNames::typeAttr)
-        setType(attr->value());
-    else if (attr->name() == HTMLNames::onerrorAttr)
-        setAttributeEventListener(eventNames().errorEvent, createAttributeEventListener(this, attr));
-    else {
-        if (SVGURIReference::parseMappedAttribute(attr))
-            return;
-        if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
-            return;
-
-        SVGElement::parseMappedAttribute(attr);
+    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
+    if (supportedAttributes.isEmpty()) {
+        SVGURIReference::addSupportedAttributes(supportedAttributes);
+        SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes);
+        supportedAttributes.add(SVGNames::typeAttr);
+        supportedAttributes.add(HTMLNames::onerrorAttr);
     }
+    return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
 }
 
-void SVGScriptElement::svgAttributeChanged(const QualifiedName& attrName)
+void SVGScriptElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
 {
-    SVGElement::svgAttributeChanged(attrName);
-
-    if (SVGURIReference::isKnownAttribute(attrName))
-        handleSourceAttribute(href());
-    else if (SVGExternalResourcesRequired::isKnownAttribute(attrName)) {
-        // Handle dynamic updates of the 'externalResourcesRequired' attribute. Only possible case: changing from 'true' to 'false'
-        // causes an immediate dispatch of the SVGLoad event. If the attribute value was 'false' before inserting the script element
-        // in the document, the SVGLoad event has already been dispatched.
-        if (!externalResourcesRequiredBaseValue() && !haveFiredLoadEvent() && !isParserInserted()) {
-            setHaveFiredLoadEvent(true);
-            ASSERT(haveLoadedRequiredResources());
-
-            sendSVGLoadEventIfPossible();
-        }
+    if (!isSupportedAttribute(name)) {
+        SVGElement::parseAttribute(name, value);
+        return;
     }
-}
 
-void SVGScriptElement::synchronizeProperty(const QualifiedName& attrName)
-{
-    SVGElement::synchronizeProperty(attrName);
+    if (name == SVGNames::typeAttr) {
+        setType(value);
+        return;
+    }
 
-    if (attrName == anyQName()) {
-        synchronizeExternalResourcesRequired();
-        synchronizeHref();
+    if (name == HTMLNames::onerrorAttr) {
+        setAttributeEventListener(eventNames().errorEvent, createAttributeEventListener(this, name, value));
         return;
     }
 
-    if (SVGExternalResourcesRequired::isKnownAttribute(attrName))
-        synchronizeExternalResourcesRequired();
-    else if (SVGURIReference::isKnownAttribute(attrName))
-        synchronizeHref();
-}
+    if (SVGURIReference::parseAttribute(name, value))
+        return;
+    if (SVGExternalResourcesRequired::parseAttribute(name, value))
+        return;
 
-AttributeToPropertyTypeMap& SVGScriptElement::attributeToPropertyTypeMap()
-{
-    DEFINE_STATIC_LOCAL(AttributeToPropertyTypeMap, s_attributeToPropertyTypeMap, ());
-    return s_attributeToPropertyTypeMap;
+    ASSERT_NOT_REACHED();
 }
 
-void SVGScriptElement::fillAttributeToPropertyTypeMap()
+void SVGScriptElement::svgAttributeChanged(const QualifiedName& attrName)
 {
-    attributeToPropertyTypeMap().set(XLinkNames::hrefAttr, AnimatedString);
-}
+    if (!isSupportedAttribute(attrName)) {
+        SVGElement::svgAttributeChanged(attrName);
+        return;
+    }
 
-void SVGScriptElement::insertedIntoDocument()
-{
-    SVGElement::insertedIntoDocument();
-    ScriptElement::insertedIntoDocument();
+    SVGElementInstance::InvalidationGuard invalidationGuard(this);
 
-    if (isParserInserted())
+    if (attrName == SVGNames::typeAttr || attrName == HTMLNames::onerrorAttr)
         return;
 
-    // Eventually send SVGLoad event now for the dynamically inserted script element
-    if (!externalResourcesRequiredBaseValue()) {
-        setHaveFiredLoadEvent(true);
-        sendSVGLoadEventIfPossible();
+    if (SVGURIReference::isKnownAttribute(attrName)) {
+        handleSourceAttribute(href());
+        return;
     }
+
+    if (SVGExternalResourcesRequired::handleAttributeChange(this, attrName))
+        return;
+
+    ASSERT_NOT_REACHED();
 }
 
-void SVGScriptElement::removedFromDocument()
+Node::InsertionNotificationRequest SVGScriptElement::insertedInto(ContainerNode* rootParent)
 {
-    SVGElement::removedFromDocument();
-    ScriptElement::removedFromDocument();
+    SVGElement::insertedInto(rootParent);
+    ScriptElement::insertedInto(rootParent);
+    if (rootParent->inDocument())
+        SVGExternalResourcesRequired::insertedIntoDocument(this);
+    return InsertionDone;
 }
 
 void SVGScriptElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
 {
-    ScriptElement::childrenChanged();
     SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
+    ScriptElement::childrenChanged();
 }
 
-bool SVGScriptElement::isURLAttribute(Attribute* attr) const
+bool SVGScriptElement::isURLAttribute(const Attribute& attribute) const
 {
-    return attr->name() == sourceAttributeValue();
+    return attribute.name() == sourceAttributeValue();
 }
 
 void SVGScriptElement::finishParsingChildren()
 {
     SVGElement::finishParsingChildren();
-
-    // A SVGLoad event has been fired by SVGElement::finishParsingChildren.
-    if (!externalResourcesRequiredBaseValue())
-        setHaveFiredLoadEvent(true);
+    SVGExternalResourcesRequired::finishParsingChildren();
 }
 
 String SVGScriptElement::type() const
@@ -168,12 +158,7 @@ void SVGScriptElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) cons
 {
     SVGElement::addSubresourceAttributeURLs(urls);
 
-    addSubresourceURL(urls, document()->completeURL(href()));
-}
-
-bool SVGScriptElement::haveLoadedRequiredResources()
-{
-    return !externalResourcesRequiredBaseValue() || haveFiredLoadEvent();
+    addSubresourceURL(urls, document().completeURL(href()));
 }
 
 String SVGScriptElement::sourceAttributeValue() const
@@ -221,37 +206,9 @@ bool SVGScriptElement::hasSourceAttribute() const
     return hasAttribute(XLinkNames::hrefAttr);
 }
 
-void SVGScriptElement::dispatchLoadEvent()
-{
-    bool externalResourcesRequired = externalResourcesRequiredBaseValue();
-
-    if (isParserInserted())
-        ASSERT(externalResourcesRequired != haveFiredLoadEvent());
-    else if (haveFiredLoadEvent()) {
-        // If we've already fired an load event and externalResourcesRequired is set to 'true'
-        // externalResourcesRequired has been modified while loading the <script>. Don't dispatch twice.
-        if (externalResourcesRequired)
-            return;
-    }
-
-    // HTML and SVG differ completly in the 'onload' event handling of <script> elements.
-    // HTML fires the 'load' event after it sucessfully loaded a remote resource, otherwhise an error event.
-    // SVG fires the SVGLoad event immediately after parsing the <script> element, if externalResourcesRequired
-    // is set to 'false', otherwhise it dispatches the 'SVGLoad' event just after loading the remote resource.
-    if (externalResourcesRequired) {
-        ASSERT(!haveFiredLoadEvent());
-
-        // Dispatch SVGLoad event
-        setHaveFiredLoadEvent(true);
-        ASSERT(haveLoadedRequiredResources());
-
-        sendSVGLoadEventIfPossible();
-    }
-}
-
-PassRefPtr<Element> SVGScriptElement::cloneElementWithoutAttributesAndChildren() const
+PassRefPtr<Element> SVGScriptElement::cloneElementWithoutAttributesAndChildren()
 {
-    return adoptRef(new SVGScriptElement(tagQName(), document(), false, alreadyStarted()));
+    return adoptRef(new SVGScriptElement(tagQName(), &document(), false, alreadyStarted()));
 }
 
 }