Modified: trunk/Source/WebCore/ChangeLog (117085 => 117086)
--- trunk/Source/WebCore/ChangeLog 2012-05-15 16:38:03 UTC (rev 117085)
+++ trunk/Source/WebCore/ChangeLog 2012-05-15 16:59:12 UTC (rev 117086)
@@ -1,3 +1,30 @@
+2012-05-15 Rob Buis <[email protected]>
+
+ Refactor SVG parts of Node::addEventListener/removeEventListener
+ https://bugs.webkit.org/show_bug.cgi?id=86426
+
+ Reviewed by Nikolas Zimmermann.
+
+ Move SVG parts of Node::addEventListener/removeEventListener into svg/. Now we do not
+ have to check in Node::addEventListener/removeEventListener if we are dealing with an SVG
+ element. Make tryAddEventListener/tryRemoveEventListener protected methods on Node to be able to use
+ it in SVGElement.
+
+ No new tests, since no change in behavior, just refactoring.
+
+ * dom/Node.cpp:
+ (WebCore::tryAddEventListener):
+ (WebCore::Node::addEventListener):
+ (WebCore::tryRemoveEventListener):
+ (WebCore::Node::removeEventListener):
+ * svg/SVGElement.cpp:
+ (WebCore::collectInstancesForSVGElement):
+ (WebCore):
+ (WebCore::SVGElement::addEventListener):
+ (WebCore::SVGElement::removeEventListener):
+ * svg/SVGElement.h:
+ (SVGElement):
+
2012-05-15 Andreas Kling <[email protected]>
RuleSet::addToRuleSet wastes a bit of Vector capacity.
Modified: trunk/Source/WebCore/dom/Node.cpp (117085 => 117086)
--- trunk/Source/WebCore/dom/Node.cpp 2012-05-15 16:38:03 UTC (rev 117085)
+++ trunk/Source/WebCore/dom/Node.cpp 2012-05-15 16:59:12 UTC (rev 117086)
@@ -112,11 +112,6 @@
#include "InspectorController.h"
#endif
-#if ENABLE(SVG)
-#include "SVGElementInstance.h"
-#include "SVGUseElement.h"
-#endif
-
#if USE(JSC)
#include <runtime/JSGlobalData.h>
#endif
@@ -2443,26 +2438,6 @@
#endif
}
-#if ENABLE(SVG)
-static inline HashSet<SVGElementInstance*> instancesForSVGElement(Node* node)
-{
- HashSet<SVGElementInstance*> instances;
-
- ASSERT(node);
- if (!node->isSVGElement() || node->shadowTreeRootNode())
- return HashSet<SVGElementInstance*>();
-
- SVGElement* element = static_cast<SVGElement*>(node);
- if (!element->isStyled())
- return HashSet<SVGElementInstance*>();
-
- SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(element);
- ASSERT(!styledElement->instanceUpdatesBlocked());
-
- return styledElement->instancesForElement();
-}
-#endif
-
static inline bool tryAddEventListener(Node* targetNode, const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
{
if (!targetNode->EventTarget::addEventListener(eventType, listener, useCapture))
@@ -2475,42 +2450,13 @@
else if (eventNames().isTouchEventType(eventType))
document->didAddTouchEventHandler();
}
-
+
return true;
}
bool Node::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
{
-#if !ENABLE(SVG)
return tryAddEventListener(this, eventType, listener, useCapture);
-#else
- if (!isSVGElement())
- return tryAddEventListener(this, eventType, listener, useCapture);
-
- HashSet<SVGElementInstance*> instances = instancesForSVGElement(this);
- if (instances.isEmpty())
- return tryAddEventListener(this, eventType, listener, useCapture);
-
- RefPtr<EventListener> listenerForRegularTree = listener;
- RefPtr<EventListener> listenerForShadowTree = listenerForRegularTree;
-
- // Add event listener to regular DOM element
- if (!tryAddEventListener(this, eventType, listenerForRegularTree.release(), useCapture))
- return false;
-
- // Add event listener to all shadow tree DOM element instances
- const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
- for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
- ASSERT((*it)->shadowTreeElement());
- ASSERT((*it)->correspondingElement() == this);
-
- RefPtr<EventListener> listenerForCurrentShadowTreeElement = listenerForShadowTree;
- bool result = tryAddEventListener((*it)->shadowTreeElement(), eventType, listenerForCurrentShadowTreeElement.release(), useCapture);
- ASSERT_UNUSED(result, result);
- }
-
- return true;
-#endif
}
static inline bool tryRemoveEventListener(Node* targetNode, const AtomicString& eventType, EventListener* listener, bool useCapture)
@@ -2526,61 +2472,13 @@
else if (eventNames().isTouchEventType(eventType))
document->didRemoveTouchEventHandler();
}
-
+
return true;
}
bool Node::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
{
-#if !ENABLE(SVG)
return tryRemoveEventListener(this, eventType, listener, useCapture);
-#else
- if (!isSVGElement())
- return tryRemoveEventListener(this, eventType, listener, useCapture);
-
- HashSet<SVGElementInstance*> instances = instancesForSVGElement(this);
- if (instances.isEmpty())
- return tryRemoveEventListener(this, eventType, listener, useCapture);
-
- // EventTarget::removeEventListener creates a PassRefPtr around the given EventListener
- // object when creating a temporary RegisteredEventListener object used to look up the
- // event listener in a cache. If we want to be able to call removeEventListener() multiple
- // times on different nodes, we have to delay its immediate destruction, which would happen
- // after the first call below.
- RefPtr<EventListener> protector(listener);
-
- // Remove event listener from regular DOM element
- if (!tryRemoveEventListener(this, eventType, listener, useCapture))
- return false;
-
- // Remove event listener from all shadow tree DOM element instances
- const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
- for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
- ASSERT((*it)->correspondingElement() == this);
-
- SVGElement* shadowTreeElement = (*it)->shadowTreeElement();
- ASSERT(shadowTreeElement);
-
- if (tryRemoveEventListener(shadowTreeElement, eventType, listener, useCapture))
- continue;
-
- // This case can only be hit for event listeners created from markup
- ASSERT(listener->wasCreatedFromMarkup());
-
- // If the event listener 'listener' has been created from markup and has been fired before
- // then JSLazyEventListener::parseCode() has been called and m_jsFunction of that listener
- // has been created (read: it's not 0 anymore). During shadow tree creation, the event
- // listener DOM attribute has been cloned, and another event listener has been setup in
- // the shadow tree. If that event listener has not been used yet, m_jsFunction is still 0,
- // and tryRemoveEventListener() above will fail. Work around that very seldom problem.
- EventTargetData* data = ""
- ASSERT(data);
-
- data->eventListenerMap.removeFirstEventListenerCreatedFromMarkup(eventType);
- }
-
- return true;
-#endif
}
EventTargetData* Node::eventTargetData()
Modified: trunk/Source/WebCore/svg/SVGElement.cpp (117085 => 117086)
--- trunk/Source/WebCore/svg/SVGElement.cpp 2012-05-15 16:38:03 UTC (rev 117085)
+++ trunk/Source/WebCore/svg/SVGElement.cpp 2012-05-15 16:59:12 UTC (rev 117086)
@@ -348,6 +348,96 @@
return true;
}
+static inline void collectInstancesForSVGElement(SVGElement* element, HashSet<SVGElementInstance*>& instances)
+{
+ ASSERT(element);
+ if (element->shadowTreeRootNode())
+ return;
+
+ if (!element->isStyled())
+ return;
+
+ SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(element);
+ ASSERT(!styledElement->instanceUpdatesBlocked());
+
+ instances = styledElement->instancesForElement();
+}
+
+bool SVGElement::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
+{
+ HashSet<SVGElementInstance*> instances;
+ collectInstancesForSVGElement(this, instances);
+ if (instances.isEmpty())
+ return Node::addEventListener(eventType, listener, useCapture);
+
+ RefPtr<EventListener> listenerForRegularTree = listener;
+ RefPtr<EventListener> listenerForShadowTree = listenerForRegularTree;
+
+ // Add event listener to regular DOM element
+ if (!Node::addEventListener(eventType, listenerForRegularTree.release(), useCapture))
+ return false;
+
+ // Add event listener to all shadow tree DOM element instances
+ const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
+ for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
+ ASSERT((*it)->shadowTreeElement());
+ ASSERT((*it)->correspondingElement() == this);
+
+ RefPtr<EventListener> listenerForCurrentShadowTreeElement = listenerForShadowTree;
+ bool result = (*it)->shadowTreeElement()->Node::addEventListener(eventType, listenerForCurrentShadowTreeElement.release(), useCapture);
+ ASSERT_UNUSED(result, result);
+ }
+
+ return true;
+}
+
+bool SVGElement::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
+{
+ HashSet<SVGElementInstance*> instances;
+ collectInstancesForSVGElement(this, instances);
+ if (instances.isEmpty())
+ return Node::removeEventListener(eventType, listener, useCapture);
+
+ // EventTarget::removeEventListener creates a PassRefPtr around the given EventListener
+ // object when creating a temporary RegisteredEventListener object used to look up the
+ // event listener in a cache. If we want to be able to call removeEventListener() multiple
+ // times on different nodes, we have to delay its immediate destruction, which would happen
+ // after the first call below.
+ RefPtr<EventListener> protector(listener);
+
+ // Remove event listener from regular DOM element
+ if (!Node::removeEventListener(eventType, listener, useCapture))
+ return false;
+
+ // Remove event listener from all shadow tree DOM element instances
+ const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
+ for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
+ ASSERT((*it)->correspondingElement() == this);
+
+ SVGElement* shadowTreeElement = (*it)->shadowTreeElement();
+ ASSERT(shadowTreeElement);
+
+ if (shadowTreeElement->Node::removeEventListener(eventType, listener, useCapture))
+ continue;
+
+ // This case can only be hit for event listeners created from markup
+ ASSERT(listener->wasCreatedFromMarkup());
+
+ // If the event listener 'listener' has been created from markup and has been fired before
+ // then JSLazyEventListener::parseCode() has been called and m_jsFunction of that listener
+ // has been created (read: it's not 0 anymore). During shadow tree creation, the event
+ // listener DOM attribute has been cloned, and another event listener has been setup in
+ // the shadow tree. If that event listener has not been used yet, m_jsFunction is still 0,
+ // and tryRemoveEventListener() above will fail. Work around that very seldom problem.
+ EventTargetData* data = ""
+ ASSERT(data);
+
+ data->eventListenerMap.removeFirstEventListenerCreatedFromMarkup(eventType);
+ }
+
+ return true;
+}
+
static bool hasLoadListener(Element* element)
{
if (element->hasEventListeners(eventNames().loadEvent))
Modified: trunk/Source/WebCore/svg/SVGElement.h (117085 => 117086)
--- trunk/Source/WebCore/svg/SVGElement.h 2012-05-15 16:38:03 UTC (rev 117085)
+++ trunk/Source/WebCore/svg/SVGElement.h 2012-05-15 16:59:12 UTC (rev 117086)
@@ -113,6 +113,9 @@
virtual bool haveLoadedRequiredResources();
+ virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture) OVERRIDE;
+ virtual bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture) OVERRIDE;
+
protected:
SVGElement(const QualifiedName&, Document*, ConstructionType = CreateSVGElement);