Load event must be fired only for the SVG structurally external elements and the...
[WebKit-https.git] / Source / WebCore / svg / SVGExternalResourcesRequired.cpp
index c20016c..b233b55 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
  * Copyright (C) 2004, 2005, 2007 Rob Buis <buis@kde.org>
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 #include "config.h"
 #include "SVGExternalResourcesRequired.h"
 
-#include "Attr.h"
+#include "RenderSVGResource.h"
+#include "RenderSVGShape.h"
 #include "SVGElement.h"
 #include "SVGNames.h"
 
 namespace WebCore {
 
-bool SVGExternalResourcesRequired::parseAttribute(const QualifiedName& name, const AtomicString& value)
+SVGExternalResourcesRequired::SVGExternalResourcesRequired(SVGElement* contextElement)
+    : m_contextElement(*contextElement)
+    , m_externalResourcesRequired(SVGAnimatedBoolean::create(contextElement))
 {
-    if (name == SVGNames::externalResourcesRequiredAttr) {
-        setExternalResourcesRequiredBaseValue(value == "true");
-        return true;
-    }
-
-    return false;
-}
-
-bool SVGExternalResourcesRequired::isKnownAttribute(const QualifiedName& attrName)
-{
-    return attrName == SVGNames::externalResourcesRequiredAttr;
+    static std::once_flag onceFlag;
+    std::call_once(onceFlag, [] {
+        PropertyRegistry::registerProperty<SVGNames::externalResourcesRequiredAttr, &SVGExternalResourcesRequired::m_externalResourcesRequired>();
+    });
 }
 
-void SVGExternalResourcesRequired::addSupportedAttributes(HashSet<QualifiedName>& supportedAttributes)
+void SVGExternalResourcesRequired::parseAttribute(const QualifiedName& name, const AtomString& value)
 {
-    supportedAttributes.add(SVGNames::externalResourcesRequiredAttr);
+    if (name == SVGNames::externalResourcesRequiredAttr)
+        m_externalResourcesRequired->setBaseValInternal(value == "true");
 }
 
-bool SVGExternalResourcesRequired::handleAttributeChange(SVGElement* targetElement, const QualifiedName& attrName)
+void SVGExternalResourcesRequired::svgAttributeChanged(const QualifiedName& attrName)
 {
-    ASSERT(targetElement);
     if (!isKnownAttribute(attrName))
-        return false;
-    if (!targetElement->inDocument())
-        return true;
-
-    // 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(targetElement->haveLoadedRequiredResources());
-
-        targetElement->sendSVGLoadEventIfPossible();
-    }
-
-    return true;
-}
-
-void SVGExternalResourcesRequired::dispatchLoadEvent(SVGElement* targetElement)
-{
-    bool externalResourcesRequired = externalResourcesRequiredBaseValue();
-
-    if (isParserInserted())
-        ASSERT(externalResourcesRequired != haveFiredLoadEvent());
-    else if (haveFiredLoadEvent())
         return;
-
-    // HTML and SVG differ completely in the 'onload' event handling of <script> elements.
-    // HTML fires the 'load' event after it sucessfully loaded a remote resource, otherwise an error event.
-    // SVG fires the SVGLoad event immediately after parsing the <script> element, if externalResourcesRequired
-    // is set to 'false', otherwise it dispatches the 'SVGLoad' event just after loading the remote resource.
-    if (!externalResourcesRequired)
-        return;
-
-    ASSERT(!haveFiredLoadEvent());
-
-    // Dispatch SVGLoad event
-    setHaveFiredLoadEvent(true);
-    ASSERT(targetElement->haveLoadedRequiredResources());
-
-    targetElement->sendSVGLoadEventIfPossible();
-}
-
-void SVGExternalResourcesRequired::insertedIntoDocument(SVGElement* targetElement)
-{
-    if (isParserInserted())
+    if (!m_contextElement.isConnected())
         return;
 
-    // Eventually send SVGLoad event now for the dynamically inserted script element.
-    if (externalResourcesRequiredBaseValue())
-        return;
-    setHaveFiredLoadEvent(true);
-    targetElement->sendSVGLoadEventIfPossibleAsynchronously();
-}
-
-void SVGExternalResourcesRequired::finishParsingChildren()
-{
-    // A SVGLoad event has been fired by SVGElement::finishParsingChildren.
-    if (!externalResourcesRequiredBaseValue())
-        setHaveFiredLoadEvent(true);
+    auto* renderer = m_contextElement.renderer();
+    if (renderer && is<RenderSVGShape>(renderer)) {
+        SVGElement::InstanceInvalidationGuard guard(m_contextElement);
+        RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer);
+    }
 }
 
-bool SVGExternalResourcesRequired::haveLoadedRequiredResources() const
+void SVGExternalResourcesRequired::addSupportedAttributes(HashSet<QualifiedName>& supportedAttributes)
 {
-    return !externalResourcesRequiredBaseValue() || haveFiredLoadEvent();
+    supportedAttributes.add(SVGNames::externalResourcesRequiredAttr);
 }
 
 }