Title: [179260] trunk/Source/WebCore
Revision
179260
Author
[email protected]
Date
2015-01-28 09:59:50 -0800 (Wed, 28 Jan 2015)

Log Message

Make SVGElement::instancesForElement point to elements in the shadow tree, not SVGElementInstance objects
https://bugs.webkit.org/show_bug.cgi?id=140984

Reviewed by Anders Carlsson.

Refactoring of code that is pretty well covered by existing tests, so
not adding new tests.

Inspired by work Rob Buis did in Blink:

    http://src.chromium.org/viewvc/blink?view=revision&revision=173275

* page/EventHandler.cpp:
(WebCore::EventHandler::clear): Removed code to zero m_lastInstanceUnderMouse.
(WebCore::instanceAssociatedWithShadowTreeElement): Deleted.
(WebCore::EventHandler::updateMouseEventTargetNode): Removed code that used
m_lastInstanceUnderMouse to track events on an object after recloning.
This behavior doesn't seem to be needed to pass any existing tests, and Rob
removed it from Blink, so I'll take it out and we can bring if back, based
on the original element rather than on the SVGElementInstance, if we find we
need to restore the behavior in the future.

* page/EventHandler.h: Removed m_lastInstanceUnderMouse.

* svg/SVGAnimateElementBase.cpp:
(WebCore::SVGAnimateElementBase::determineAnimatedPropertyType):
Changed this function to take a reference and to call the updated version
of the targetElement.animatedPropertyTypesForAttribute function.
(WebCore::SVGAnimateElementBase::calculateAnimatedValue): Updated to pass
a reference rather than a pointer.
(WebCore::SVGAnimateElementBase::resetAnimatedType): Updated to pass
references rather than pointers.
(WebCore::applyCSSPropertyToTarget): Updated to take a reference.
(WebCore::removeCSSPropertyFromTarget): Ditto.
(WebCore::applyCSSPropertyToTargetAndInstances): Ditto. Also use a modern
for loop, and iterate over shadow tree instances, not over SVGElementInstance.
(WebCore::removeCSSPropertyFromTargetAndInstances): Ditto.
(WebCore::notifyTargetAboutAnimValChange): Ditto.
(WebCore::notifyTargetAndInstancesAboutAnimValChange): Ditto.
(WebCore::SVGAnimateElementBase::clearAnimatedType): More of the same.
(WebCore::SVGAnimateElementBase::applyResultsToTarget): Ditto.
(WebCore::SVGAnimateElementBase::resetAnimatedPropertyType): Ditto.

* svg/SVGAnimateElementBase.h: Changed determineAnimatedPropertyType to take
a reference rahter than a pointer.

* svg/SVGAnimateMotionElement.cpp:
(WebCore::SVGAnimateMotionElement::applyResultsToTarget): Updated to use the
new instances instead of SVGElementInstance. Also added code to skip work if
the transform is not changing, and use the assignment operator instead of
breaking one matrix down and calling setMatrix on the other.

* svg/SVGAnimatedTypeAnimator.cpp:
(WebCore::SVGAnimatedTypeAnimator::findAnimatedPropertiesForAttributeName):
Changed to take a reference rather than a pointer, and rewrote to streamline,
using modern for loops and using the new instances set.

* svg/SVGAnimatedTypeAnimator.h: Removed the constructors from the
SVGElementAnimatedProperties struct since we can build them just fine without
them. Changed findAnimatedPropertiesForAttributeName to take a reference.

* svg/SVGAnimationElement.cpp:
(WebCore::SVGAnimationElement::currentValuesForValuesAnimation): Pass a
reference rather than a pointer. Also streamlined the code a bit and removed
a comment that tried to say exactly what the code was doing, but was outdated.

* svg/SVGElement.cpp:
(WebCore::SVGElement::~SVGElement): Disconnect all instances from this element
and also disconnect the corresponding element from this element if it itself
is an instance. This guarantees we have no dangling pointers.
(WebCore::SVGElement::mapInstanceToElement): Deleted.
(WebCore::SVGElement::removeInstanceMapping): Deleted.
(WebCore::SVGElement::instances): Renamed from instancesForElement and changed
to be a set of SVG element instances in the shadow tree, rather than
SVGElementInstance objects.
(WebCore::SVGElement::correspondingElement): Tweaked assertion a little and use
nullptr instead of 0.
(WebCore::SVGElement::correspondingUseElement): Added. Finds the use element
that owns the shadow tree this element is in by following the host element
pointer from the shadow root.
(WebCore::SVGElement::setCorrespondingElement): Added code to insert or remove
this element from the instances set of the corresponding element.
(WebCore::SVGElement::animatedPropertyTypesForAttribute): Renamed from
animatedPropertyTypeForAttribute and switched to use a return value instead of
an out argument.
(WebCore::SVGElement::addEventListener): Updated to use instances rather than
the old instancesForElement.
(WebCore::SVGElement::removeEventListener): Ditto.
(WebCore::SVGElement::synchronizeAllAnimatedSVGAttribute): Pass a reference.
(WebCore::SVGElement::synchronizeAnimatedSVGAttribute): Ditto.
(WebCore::SVGElement::isPresentationAttributeWithSVGDOM): Updated to use the
new function from AttributeToPropertyMap.

* svg/SVGElement.h: Changed animatedPropertyTypesForAttribute name to be plural
since it returns a vector of types, and made it use a return value instead of
an out argument. Added the correspondingUseElement function, and removed the
mapInstanceToElement and removeInstanceMapping functions.

* svg/SVGElementInstance.cpp:
(WebCore::SVGElementInstance::SVGElementInstance): Removed now-unneeded call to
mapInstanceToElement. This is now handled entirely by the SVGElement itself.
(WebCore::SVGElementInstance::detach): Removed now-unneeded call to
removeInstanceMapping. This is now handled entirely by the SVGElement itself.
(WebCore::SVGElementInstance::invalidateAllInstancesOfElement): Rewrote to be
based on the instances set; logic is different now because we remove each
element from that set as we go.

* svg/SVGElementRareData.h:
(WebCore::SVGElementRareData::SVGElementRareData): Removed initialization of
pointers since we can do that where they are defined instead.
(WebCore::SVGElementRareData::instances): Renamed from elementInstances and
changed the type.
(WebCore::SVGElementRareData::destroyAnimatedSMILStyleProperties): Deleted.
Unneeded since it was already called just before deleting the rare data.

* svg/SVGTests.cpp:
(WebCore::SVGTests::SVGTests): Took advantage of using namespace.
(WebCore::createSVGTestPropertyInfo): Added. Helper for function below.
(WebCore::createSVGTextAttributeToPropertyMap): Ditto.
(WebCore::SVGTests::attributeToPropertyMap): Changed to use the create function
above. No longer allocates objects on the heap.
(WebCore::SVGTests::hasExtension): Reworked #if code to make the MathML part
independent rather than repeating the return statement.
(WebCore::SVGTests::synchronizeAttribute): Added. Helper for functions below.
(WebCore::SVGTests::synchronizeRequiredFeatures): Call synchronizeAttribute.
(WebCore::SVGTests::synchronizeRequiredExtensions): Ditto.
(WebCore::SVGTests::synchronizeSystemLanguage): Ditto.

* svg/SVGTests.h: Removed unneeded forward declarations. Mark the many functions
that do not depend on object state as static so the call sites don't wastefully
pass a this pointer. Removed the unneeded requiredFeaturesPropertyInfo,
requiredExtensionsPropertyInfo, and systemLanguagePropertyInfo functions.
Added synchronizeAttribute helper function.

* svg/SVGUseElement.cpp:
(WebCore::SVGUseElement::invalidateDependentShadowTrees): Updated to use the
new instances set and a modern for loop.

* svg/properties/SVGAnimatedPropertyMacros.h: Pass reference to addProperty and
made a few other small refinements.

* svg/properties/SVGAttributeToPropertyMap.cpp:
(WebCore::SVGAttributeToPropertyMap::addProperties): Fixed problems mentioned
in FIXME where we did too much hashing and vector resizing.
(WebCore::SVGAttributeToPropertyMap::addProperty): Streamlined to use a single
hash table lookup.
(WebCore::SVGAttributeToPropertyMap::properties): Renamed from
animatedPropertiesForAttribute and changed to return a vector rather than using
an out argument. Also had to change some since the vectors are in the hash table
now rather than allocated on the heap.
(WebCore::SVGAttributeToPropertyMap::types): Renamed from
animatedPropertyTypeForAttribute and made changes just like the ones above.
(WebCore::SVGAttributeToPropertyMap::synchronizeProperties): Use modern for
loops, take a reference rather than a pointer, and use the function pointer
directly instead of calling through a helper with various assertions.
(WebCore::SVGAttributeToPropertyMap::synchronizeProperty): Ditto.

* svg/properties/SVGAttributeToPropertyMap.h: Updated to match the changes
above. Also changed the map to contain vectors instead of pointers to vectors.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (179259 => 179260)


--- trunk/Source/WebCore/ChangeLog	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/ChangeLog	2015-01-28 17:59:50 UTC (rev 179260)
@@ -1,5 +1,167 @@
 2015-01-28  Darin Adler  <[email protected]>
 
+        Make SVGElement::instancesForElement point to elements in the shadow tree, not SVGElementInstance objects
+        https://bugs.webkit.org/show_bug.cgi?id=140984
+
+        Reviewed by Anders Carlsson.
+
+        Refactoring of code that is pretty well covered by existing tests, so
+        not adding new tests.
+
+        Inspired by work Rob Buis did in Blink:
+
+            http://src.chromium.org/viewvc/blink?view=revision&revision=173275
+
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::clear): Removed code to zero m_lastInstanceUnderMouse.
+        (WebCore::instanceAssociatedWithShadowTreeElement): Deleted.
+        (WebCore::EventHandler::updateMouseEventTargetNode): Removed code that used
+        m_lastInstanceUnderMouse to track events on an object after recloning.
+        This behavior doesn't seem to be needed to pass any existing tests, and Rob
+        removed it from Blink, so I'll take it out and we can bring if back, based
+        on the original element rather than on the SVGElementInstance, if we find we
+        need to restore the behavior in the future.
+
+        * page/EventHandler.h: Removed m_lastInstanceUnderMouse.
+
+        * svg/SVGAnimateElementBase.cpp:
+        (WebCore::SVGAnimateElementBase::determineAnimatedPropertyType):
+        Changed this function to take a reference and to call the updated version
+        of the targetElement.animatedPropertyTypesForAttribute function.
+        (WebCore::SVGAnimateElementBase::calculateAnimatedValue): Updated to pass
+        a reference rather than a pointer.
+        (WebCore::SVGAnimateElementBase::resetAnimatedType): Updated to pass
+        references rather than pointers.
+        (WebCore::applyCSSPropertyToTarget): Updated to take a reference.
+        (WebCore::removeCSSPropertyFromTarget): Ditto.
+        (WebCore::applyCSSPropertyToTargetAndInstances): Ditto. Also use a modern
+        for loop, and iterate over shadow tree instances, not over SVGElementInstance.
+        (WebCore::removeCSSPropertyFromTargetAndInstances): Ditto.
+        (WebCore::notifyTargetAboutAnimValChange): Ditto.
+        (WebCore::notifyTargetAndInstancesAboutAnimValChange): Ditto.
+        (WebCore::SVGAnimateElementBase::clearAnimatedType): More of the same.
+        (WebCore::SVGAnimateElementBase::applyResultsToTarget): Ditto.
+        (WebCore::SVGAnimateElementBase::resetAnimatedPropertyType): Ditto.
+
+        * svg/SVGAnimateElementBase.h: Changed determineAnimatedPropertyType to take
+        a reference rahter than a pointer.
+
+        * svg/SVGAnimateMotionElement.cpp:
+        (WebCore::SVGAnimateMotionElement::applyResultsToTarget): Updated to use the
+        new instances instead of SVGElementInstance. Also added code to skip work if
+        the transform is not changing, and use the assignment operator instead of
+        breaking one matrix down and calling setMatrix on the other.
+
+        * svg/SVGAnimatedTypeAnimator.cpp:
+        (WebCore::SVGAnimatedTypeAnimator::findAnimatedPropertiesForAttributeName):
+        Changed to take a reference rather than a pointer, and rewrote to streamline,
+        using modern for loops and using the new instances set.
+
+        * svg/SVGAnimatedTypeAnimator.h: Removed the constructors from the
+        SVGElementAnimatedProperties struct since we can build them just fine without
+        them. Changed findAnimatedPropertiesForAttributeName to take a reference.
+
+        * svg/SVGAnimationElement.cpp:
+        (WebCore::SVGAnimationElement::currentValuesForValuesAnimation): Pass a
+        reference rather than a pointer. Also streamlined the code a bit and removed
+        a comment that tried to say exactly what the code was doing, but was outdated.
+
+        * svg/SVGElement.cpp:
+        (WebCore::SVGElement::~SVGElement): Disconnect all instances from this element
+        and also disconnect the corresponding element from this element if it itself
+        is an instance. This guarantees we have no dangling pointers.
+        (WebCore::SVGElement::mapInstanceToElement): Deleted.
+        (WebCore::SVGElement::removeInstanceMapping): Deleted.
+        (WebCore::SVGElement::instances): Renamed from instancesForElement and changed
+        to be a set of SVG element instances in the shadow tree, rather than
+        SVGElementInstance objects.
+        (WebCore::SVGElement::correspondingElement): Tweaked assertion a little and use
+        nullptr instead of 0.
+        (WebCore::SVGElement::correspondingUseElement): Added. Finds the use element
+        that owns the shadow tree this element is in by following the host element
+        pointer from the shadow root.
+        (WebCore::SVGElement::setCorrespondingElement): Added code to insert or remove
+        this element from the instances set of the corresponding element.
+        (WebCore::SVGElement::animatedPropertyTypesForAttribute): Renamed from
+        animatedPropertyTypeForAttribute and switched to use a return value instead of
+        an out argument.
+        (WebCore::SVGElement::addEventListener): Updated to use instances rather than
+        the old instancesForElement.
+        (WebCore::SVGElement::removeEventListener): Ditto.
+        (WebCore::SVGElement::synchronizeAllAnimatedSVGAttribute): Pass a reference.
+        (WebCore::SVGElement::synchronizeAnimatedSVGAttribute): Ditto.
+        (WebCore::SVGElement::isPresentationAttributeWithSVGDOM): Updated to use the
+        new function from AttributeToPropertyMap.
+
+        * svg/SVGElement.h: Changed animatedPropertyTypesForAttribute name to be plural
+        since it returns a vector of types, and made it use a return value instead of
+        an out argument. Added the correspondingUseElement function, and removed the
+        mapInstanceToElement and removeInstanceMapping functions.
+
+        * svg/SVGElementInstance.cpp:
+        (WebCore::SVGElementInstance::SVGElementInstance): Removed now-unneeded call to
+        mapInstanceToElement. This is now handled entirely by the SVGElement itself.
+        (WebCore::SVGElementInstance::detach): Removed now-unneeded call to
+        removeInstanceMapping. This is now handled entirely by the SVGElement itself.
+        (WebCore::SVGElementInstance::invalidateAllInstancesOfElement): Rewrote to be
+        based on the instances set; logic is different now because we remove each
+        element from that set as we go.
+
+        * svg/SVGElementRareData.h:
+        (WebCore::SVGElementRareData::SVGElementRareData): Removed initialization of
+        pointers since we can do that where they are defined instead.
+        (WebCore::SVGElementRareData::instances): Renamed from elementInstances and
+        changed the type.
+        (WebCore::SVGElementRareData::destroyAnimatedSMILStyleProperties): Deleted.
+        Unneeded since it was already called just before deleting the rare data.
+
+        * svg/SVGTests.cpp:
+        (WebCore::SVGTests::SVGTests): Took advantage of using namespace.
+        (WebCore::createSVGTestPropertyInfo): Added. Helper for function below.
+        (WebCore::createSVGTextAttributeToPropertyMap): Ditto.
+        (WebCore::SVGTests::attributeToPropertyMap): Changed to use the create function
+        above. No longer allocates objects on the heap.
+        (WebCore::SVGTests::hasExtension): Reworked #if code to make the MathML part
+        independent rather than repeating the return statement.
+        (WebCore::SVGTests::synchronizeAttribute): Added. Helper for functions below.
+        (WebCore::SVGTests::synchronizeRequiredFeatures): Call synchronizeAttribute.
+        (WebCore::SVGTests::synchronizeRequiredExtensions): Ditto.
+        (WebCore::SVGTests::synchronizeSystemLanguage): Ditto.
+
+        * svg/SVGTests.h: Removed unneeded forward declarations. Mark the many functions
+        that do not depend on object state as static so the call sites don't wastefully
+        pass a this pointer. Removed the unneeded requiredFeaturesPropertyInfo,
+        requiredExtensionsPropertyInfo, and systemLanguagePropertyInfo functions.
+        Added synchronizeAttribute helper function.
+
+        * svg/SVGUseElement.cpp:
+        (WebCore::SVGUseElement::invalidateDependentShadowTrees): Updated to use the
+        new instances set and a modern for loop.
+
+        * svg/properties/SVGAnimatedPropertyMacros.h: Pass reference to addProperty and
+        made a few other small refinements.
+
+        * svg/properties/SVGAttributeToPropertyMap.cpp:
+        (WebCore::SVGAttributeToPropertyMap::addProperties): Fixed problems mentioned
+        in FIXME where we did too much hashing and vector resizing.
+        (WebCore::SVGAttributeToPropertyMap::addProperty): Streamlined to use a single
+        hash table lookup.
+        (WebCore::SVGAttributeToPropertyMap::properties): Renamed from
+        animatedPropertiesForAttribute and changed to return a vector rather than using
+        an out argument. Also had to change some since the vectors are in the hash table
+        now rather than allocated on the heap.
+        (WebCore::SVGAttributeToPropertyMap::types): Renamed from
+        animatedPropertyTypeForAttribute and made changes just like the ones above.
+        (WebCore::SVGAttributeToPropertyMap::synchronizeProperties): Use modern for
+        loops, take a reference rather than a pointer, and use the function pointer
+        directly instead of calling through a helper with various assertions.
+        (WebCore::SVGAttributeToPropertyMap::synchronizeProperty): Ditto.
+
+        * svg/properties/SVGAttributeToPropertyMap.h: Updated to match the changes
+        above. Also changed the map to contain vectors instead of pointers to vectors.
+
+2015-01-28  Darin Adler  <[email protected]>
+
         REGRESSION (r173698): Leaks of selector lists in CSS parsing
         https://bugs.webkit.org/show_bug.cgi?id=140993
 

Modified: trunk/Source/WebCore/page/EventHandler.cpp (179259 => 179260)


--- trunk/Source/WebCore/page/EventHandler.cpp	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/page/EventHandler.cpp	2015-01-28 17:59:50 UTC (rev 179260)
@@ -459,7 +459,6 @@
     m_resizeLayer = nullptr;
     m_elementUnderMouse = nullptr;
     m_lastElementUnderMouse = nullptr;
-    m_lastInstanceUnderMouse = nullptr;
     m_lastMouseMoveEventSubframe = nullptr;
     m_lastScrollbarUnderMouse = nullptr;
     m_clickCount = 0;
@@ -2352,22 +2351,6 @@
     return m_frame.document()->prepareMouseEvent(request, documentPointForWindowPoint(m_frame, mouseEvent.position()), mouseEvent);
 }
 
-static inline SVGElementInstance* instanceAssociatedWithShadowTreeElement(Node* referenceNode)
-{
-    if (!referenceNode || !referenceNode->isSVGElement())
-        return nullptr;
-
-    ShadowRoot* shadowRoot = referenceNode->containingShadowRoot();
-    if (!shadowRoot)
-        return nullptr;
-
-    Element* shadowTreeParentElement = shadowRoot->hostElement();
-    if (!shadowTreeParentElement || !shadowTreeParentElement->hasTagName(useTag))
-        return nullptr;
-
-    return downcast<SVGUseElement>(*shadowTreeParentElement).instanceForShadowTreeElement(referenceNode);
-}
-
 static RenderElement* nearestCommonHoverAncestor(RenderElement* obj1, RenderElement* obj2)
 {
     if (!obj1 || !obj2)
@@ -2409,37 +2392,6 @@
 
     m_elementUnderMouse = targetElement;
 
-    // <use> shadow tree elements may have been recloned, update node under mouse in any case
-    if (m_lastInstanceUnderMouse) {
-        SVGElement* lastCorrespondingElement = m_lastInstanceUnderMouse->correspondingElement();
-        SVGElement* lastCorrespondingUseElement = m_lastInstanceUnderMouse->correspondingUseElement();
-
-        if (lastCorrespondingElement && lastCorrespondingUseElement) {
-            HashSet<SVGElementInstance*> instances = lastCorrespondingElement->instancesForElement();
-
-            // Locate the recloned shadow tree element for our corresponding instance
-            HashSet<SVGElementInstance*>::iterator end = instances.end();
-            for (HashSet<SVGElementInstance*>::iterator it = instances.begin(); it != end; ++it) {
-                SVGElementInstance* instance = (*it);
-                ASSERT(instance->correspondingElement() == lastCorrespondingElement);
-
-                if (instance == m_lastInstanceUnderMouse)
-                    continue;
-
-                if (instance->correspondingUseElement() != lastCorrespondingUseElement)
-                    continue;
-
-                SVGElement* shadowTreeElement = instance->shadowTreeElement();
-                if (!shadowTreeElement->inDocument() || m_lastElementUnderMouse == shadowTreeElement)
-                    continue;
-
-                m_lastElementUnderMouse = shadowTreeElement;
-                m_lastInstanceUnderMouse = instance;
-                break;
-            }
-        }
-    }
-
     // Fire mouseout/mouseover if the mouse has shifted to a different node.
     if (fireMouseOverOut) {
         RenderLayer* layerForLastNode = layerForNode(m_lastElementUnderMouse.get());
@@ -2481,7 +2433,6 @@
         if (m_lastElementUnderMouse && &m_lastElementUnderMouse->document() != m_frame.document()) {
             m_lastElementUnderMouse = nullptr;
             m_lastScrollbarUnderMouse = nullptr;
-            m_lastInstanceUnderMouse = nullptr;
         }
 
         if (m_lastElementUnderMouse != m_elementUnderMouse) {
@@ -2539,7 +2490,6 @@
             }
         }
         m_lastElementUnderMouse = m_elementUnderMouse;
-        m_lastInstanceUnderMouse = instanceAssociatedWithShadowTreeElement(m_elementUnderMouse.get());
     }
 }
 

Modified: trunk/Source/WebCore/page/EventHandler.h (179259 => 179260)


--- trunk/Source/WebCore/page/EventHandler.h	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/page/EventHandler.h	2015-01-28 17:59:50 UTC (rev 179260)
@@ -92,7 +92,6 @@
 class RenderLayer;
 class RenderWidget;
 class ScrollableArea;
-class SVGElementInstance;
 class Scrollbar;
 class TextEvent;
 class Touch;
@@ -488,7 +487,6 @@
 #endif
 
     bool m_svgPan;
-    RefPtr<SVGElementInstance> m_lastInstanceUnderMouse;
 
     RenderLayer* m_resizeLayer;
 

Modified: trunk/Source/WebCore/svg/SVGAnimateElementBase.cpp (179259 => 179260)


--- trunk/Source/WebCore/svg/SVGAnimateElementBase.cpp	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/svg/SVGAnimateElementBase.cpp	2015-01-28 17:59:50 UTC (rev 179260)
@@ -55,12 +55,9 @@
     return m_animatedPropertyType != AnimatedUnknown && !hasInvalidCSSAttributeType();
 }
 
-AnimatedPropertyType SVGAnimateElementBase::determineAnimatedPropertyType(SVGElement* targetElement) const
+AnimatedPropertyType SVGAnimateElementBase::determineAnimatedPropertyType(SVGElement& targetElement) const
 {
-    ASSERT(targetElement);
-
-    Vector<AnimatedPropertyType> propertyTypes;
-    targetElement->animatedPropertyTypeForAttribute(attributeName(), propertyTypes);
+    auto propertyTypes = targetElement.animatedPropertyTypesForAttribute(attributeName());
     if (propertyTypes.isEmpty())
         return AnimatedUnknown;
 
@@ -77,7 +74,7 @@
     // Fortunately there's just one special case needed here: SVGMarkerElements orientAttr, which
     // corresponds to SVGAnimatedAngle orientAngle and SVGAnimatedEnumeration orientType. We have to
     // figure out whose value to change here.
-    if (targetElement->hasTagName(SVGNames::markerTag) && type == AnimatedAngle) {
+    if (targetElement.hasTagName(SVGNames::markerTag) && type == AnimatedAngle) {
         ASSERT(propertyTypes.size() == 2);
         ASSERT(propertyTypes[0] == AnimatedAngle);
         ASSERT(propertyTypes[1] == AnimatedEnumeration);
@@ -94,7 +91,7 @@
     if (!targetElement)
         return;
 
-    ASSERT(m_animatedPropertyType == determineAnimatedPropertyType(targetElement));
+    ASSERT(m_animatedPropertyType == determineAnimatedPropertyType(*targetElement));
 
     ASSERT(percentage >= 0 && percentage <= 1);
     ASSERT(m_animatedPropertyType != AnimatedTransformList || hasTagName(SVGNames::animateTransformTag));
@@ -196,6 +193,9 @@
     ASSERT(m_animatedPropertyType == animator->type());
 
     SVGElement* targetElement = this->targetElement();
+    if (!targetElement)
+        return;
+
     const QualifiedName& attributeName = this->attributeName();
     ShouldApplyAnimation shouldApply = shouldApplyAnimation(targetElement, attributeName);
 
@@ -204,7 +204,7 @@
 
     if (shouldApply == ApplyXMLAnimation || shouldApply == ApplyXMLandCSSAnimation) {
         // SVG DOM animVal animation code-path.
-        m_animatedProperties = animator->findAnimatedPropertiesForAttributeName(targetElement, attributeName);
+        m_animatedProperties = animator->findAnimatedPropertiesForAttributeName(*targetElement, attributeName);
         if (m_animatedProperties.isEmpty())
             return;
 
@@ -233,85 +233,72 @@
         m_animatedType->setValueAsString(attributeName, baseValue);
 }
 
-static inline void applyCSSPropertyToTarget(SVGElement* targetElement, CSSPropertyID id, const String& value)
+static inline void applyCSSPropertyToTarget(SVGElement& targetElement, CSSPropertyID id, const String& value)
 {
-    ASSERT(!targetElement->m_deletionHasBegun);
+    ASSERT(!targetElement.m_deletionHasBegun);
 
-    if (!targetElement->ensureAnimatedSMILStyleProperties().setProperty(id, value, false, 0))
+    if (!targetElement.ensureAnimatedSMILStyleProperties().setProperty(id, value, false, 0))
         return;
 
-    targetElement->setNeedsStyleRecalc(SyntheticStyleChange);
+    targetElement.setNeedsStyleRecalc(SyntheticStyleChange);
 }
 
-static inline void removeCSSPropertyFromTarget(SVGElement* targetElement, CSSPropertyID id)
+static inline void removeCSSPropertyFromTarget(SVGElement& targetElement, CSSPropertyID id)
 {
-    ASSERT(!targetElement->m_deletionHasBegun);
-    targetElement->ensureAnimatedSMILStyleProperties().removeProperty(id);
-    targetElement->setNeedsStyleRecalc(SyntheticStyleChange);
+    ASSERT(!targetElement.m_deletionHasBegun);
+    targetElement.ensureAnimatedSMILStyleProperties().removeProperty(id);
+    targetElement.setNeedsStyleRecalc(SyntheticStyleChange);
 }
 
-static inline void applyCSSPropertyToTargetAndInstances(SVGElement* targetElement, const QualifiedName& attributeName, const String& valueAsString)
+static inline void applyCSSPropertyToTargetAndInstances(SVGElement& targetElement, const QualifiedName& attributeName, const String& valueAsString)
 {
-    ASSERT(targetElement);
-    if (attributeName == anyQName() || !targetElement->inDocument() || !targetElement->parentNode())
+    // FIXME: Do we really need to check both inDocument and !parentNode?
+    if (attributeName == anyQName() || !targetElement.inDocument() || !targetElement.parentNode())
         return;
 
     CSSPropertyID id = cssPropertyID(attributeName.localName());
 
-    SVGElementInstance::InstanceUpdateBlocker blocker(targetElement);
+    SVGElementInstance::InstanceUpdateBlocker blocker(&targetElement);
     applyCSSPropertyToTarget(targetElement, id, valueAsString);
 
     // If the target element has instances, update them as well, w/o requiring the <use> tree to be rebuilt.
-    const HashSet<SVGElementInstance*>& instances = targetElement->instancesForElement();
-    const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
-    for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
-        if (SVGElement* shadowTreeElement = (*it)->shadowTreeElement())
-            applyCSSPropertyToTarget(shadowTreeElement, id, valueAsString);
-    }
+    for (auto* instance : targetElement.instances())
+        applyCSSPropertyToTarget(*instance, id, valueAsString);
 }
 
-static inline void removeCSSPropertyFromTargetAndInstances(SVGElement* targetElement, const QualifiedName& attributeName)
+static inline void removeCSSPropertyFromTargetAndInstances(SVGElement& targetElement, const QualifiedName& attributeName)
 {
-    ASSERT(targetElement);
-    if (attributeName == anyQName() || !targetElement->inDocument() || !targetElement->parentNode())
+    // FIXME: Do we really need to check both inDocument and !parentNode?
+    if (attributeName == anyQName() || !targetElement.inDocument() || !targetElement.parentNode())
         return;
 
     CSSPropertyID id = cssPropertyID(attributeName.localName());
 
-    SVGElementInstance::InstanceUpdateBlocker blocker(targetElement);
+    SVGElementInstance::InstanceUpdateBlocker blocker(&targetElement);
     removeCSSPropertyFromTarget(targetElement, id);
 
     // If the target element has instances, update them as well, w/o requiring the <use> tree to be rebuilt.
-    const HashSet<SVGElementInstance*>& instances = targetElement->instancesForElement();
-    const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
-    for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
-        if (SVGElement* shadowTreeElement = (*it)->shadowTreeElement())
-            removeCSSPropertyFromTarget(shadowTreeElement, id);
-    }
+    for (auto* instance : targetElement.instances())
+        removeCSSPropertyFromTarget(*instance, id);
 }
 
-static inline void notifyTargetAboutAnimValChange(SVGElement* targetElement, const QualifiedName& attributeName)
+static inline void notifyTargetAboutAnimValChange(SVGElement& targetElement, const QualifiedName& attributeName)
 {
-    ASSERT(!targetElement->m_deletionHasBegun);
-    targetElement->svgAttributeChanged(attributeName);
+    ASSERT(!targetElement.m_deletionHasBegun);
+    targetElement.svgAttributeChanged(attributeName);
 }
 
-static inline void notifyTargetAndInstancesAboutAnimValChange(SVGElement* targetElement, const QualifiedName& attributeName)
+static inline void notifyTargetAndInstancesAboutAnimValChange(SVGElement& targetElement, const QualifiedName& attributeName)
 {
-    ASSERT(targetElement);
-    if (attributeName == anyQName() || !targetElement->inDocument() || !targetElement->parentNode())
+    if (attributeName == anyQName() || !targetElement.inDocument() || !targetElement.parentNode())
         return;
 
-    SVGElementInstance::InstanceUpdateBlocker blocker(targetElement);
+    SVGElementInstance::InstanceUpdateBlocker blocker(&targetElement);
     notifyTargetAboutAnimValChange(targetElement, attributeName);
 
     // If the target element has instances, update them as well, w/o requiring the <use> tree to be rebuilt.
-    const HashSet<SVGElementInstance*>& instances = targetElement->instancesForElement();
-    const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
-    for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
-        if (SVGElement* shadowTreeElement = (*it)->shadowTreeElement())
-            notifyTargetAboutAnimValChange(shadowTreeElement, attributeName);
-    }
+    for (auto* instance : targetElement.instances())
+        notifyTargetAboutAnimValChange(*instance, attributeName);
 }
 
 void SVGAnimateElementBase::clearAnimatedType(SVGElement* targetElement)
@@ -326,19 +313,19 @@
 
     if (m_animatedProperties.isEmpty()) {
         // CSS properties animation code-path.
-        removeCSSPropertyFromTargetAndInstances(targetElement, attributeName());
+        removeCSSPropertyFromTargetAndInstances(*targetElement, attributeName());
         m_animatedType = nullptr;
         return;
     }
 
     ShouldApplyAnimation shouldApply = shouldApplyAnimation(targetElement, attributeName());
     if (shouldApply == ApplyXMLandCSSAnimation)
-        removeCSSPropertyFromTargetAndInstances(targetElement, attributeName());
+        removeCSSPropertyFromTargetAndInstances(*targetElement, attributeName());
 
     // SVG DOM animVal animation code-path.
     if (m_animator) {
         m_animator->stopAnimValAnimation(m_animatedProperties);
-        notifyTargetAndInstancesAboutAnimValChange(targetElement, attributeName());
+        notifyTargetAndInstancesAboutAnimValChange(*targetElement, attributeName());
     }
 
     m_animatedProperties.clear();
@@ -351,29 +338,32 @@
     ASSERT(m_animatedPropertyType != AnimatedUnknown);
     ASSERT(m_animator);
 
-    // Early exit if our animated type got destructed by a previous endedActiveInterval().
+    // Early exit if our animated type got destroyed by a previous endedActiveInterval().
     if (!m_animatedType)
         return;
 
     SVGElement* targetElement = this->targetElement();
     const QualifiedName& attributeName = this->attributeName();
+
+    ASSERT(targetElement);
+
     if (m_animatedProperties.isEmpty()) {
         // CSS properties animation code-path.
         // Convert the result of the animation to a String and apply it as CSS property on the target & all instances.
-        applyCSSPropertyToTargetAndInstances(targetElement, attributeName, m_animatedType->valueAsString());
+        applyCSSPropertyToTargetAndInstances(*targetElement, attributeName, m_animatedType->valueAsString());
         return;
     }
 
     // We do update the style and the animation property independent of each other.
     ShouldApplyAnimation shouldApply = shouldApplyAnimation(targetElement, attributeName);
     if (shouldApply == ApplyXMLandCSSAnimation)
-        applyCSSPropertyToTargetAndInstances(targetElement, attributeName, m_animatedType->valueAsString());
+        applyCSSPropertyToTargetAndInstances(*targetElement, attributeName, m_animatedType->valueAsString());
 
     // SVG DOM animVal animation code-path.
     // At this point the SVG DOM values are already changed, unlike for CSS.
     // We only have to trigger update notifications here.
     m_animator->animValDidChange(m_animatedProperties);
-    notifyTargetAndInstancesAboutAnimValChange(targetElement, attributeName);
+    notifyTargetAndInstancesAboutAnimValChange(*targetElement, attributeName);
 }
 
 bool SVGAnimateElementBase::animatedPropertyTypeSupportsAddition() const
@@ -445,7 +435,7 @@
     m_toType = nullptr;
     m_toAtEndOfDurationType = nullptr;
     m_animator = nullptr;
-    m_animatedPropertyType = targetElement() ? determineAnimatedPropertyType(targetElement()) : AnimatedString;
+    m_animatedPropertyType = targetElement() ? determineAnimatedPropertyType(*targetElement()) : AnimatedString;
 }
 
 SVGAnimatedTypeAnimator* SVGAnimateElementBase::ensureAnimator()

Modified: trunk/Source/WebCore/svg/SVGAnimateElementBase.h (179259 => 179260)


--- trunk/Source/WebCore/svg/SVGAnimateElementBase.h	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/svg/SVGAnimateElementBase.h	2015-01-28 17:59:50 UTC (rev 179260)
@@ -35,7 +35,7 @@
 public:
     virtual ~SVGAnimateElementBase();
 
-    AnimatedPropertyType determineAnimatedPropertyType(SVGElement*) const;
+    AnimatedPropertyType determineAnimatedPropertyType(SVGElement&) const;
 
 protected:
     SVGAnimateElementBase(const QualifiedName&, Document&);

Modified: trunk/Source/WebCore/svg/SVGAnimateMotionElement.cpp (179259 => 179260)


--- trunk/Source/WebCore/svg/SVGAnimateMotionElement.cpp	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/svg/SVGAnimateMotionElement.cpp	2015-01-28 17:59:50 UTC (rev 179260)
@@ -293,19 +293,17 @@
     if (RenderElement* renderer = targetElement->renderer())
         RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer);
 
-    AffineTransform* t = targetElement->supplementalTransform();
-    if (!t)
+    AffineTransform* targetSupplementalTransform = targetElement->supplementalTransform();
+    if (!targetSupplementalTransform)
         return;
 
     // ...except in case where we have additional instances in <use> trees.
-    for (auto* instance : targetElement->instancesForElement()) {
-        SVGElement* shadowTreeElement = instance->shadowTreeElement();
-        ASSERT(shadowTreeElement);
-        AffineTransform* transform = shadowTreeElement->supplementalTransform();
-        if (!transform)
+    for (auto* instance : targetElement->instances()) {
+        AffineTransform* transform = instance->supplementalTransform();
+        if (!transform || *transform == *targetSupplementalTransform)
             continue;
-        transform->setMatrix(t->a(), t->b(), t->c(), t->d(), t->e(), t->f());
-        if (RenderElement* renderer = shadowTreeElement->renderer()) {
+        *transform = *targetSupplementalTransform;
+        if (RenderElement* renderer = instance->renderer()) {
             renderer->setNeedsTransformUpdate();
             RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer);
         }

Modified: trunk/Source/WebCore/svg/SVGAnimatedTypeAnimator.cpp (179259 => 179260)


--- trunk/Source/WebCore/svg/SVGAnimatedTypeAnimator.cpp	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/svg/SVGAnimatedTypeAnimator.cpp	2015-01-28 17:59:50 UTC (rev 179260)
@@ -27,15 +27,6 @@
 
 namespace WebCore {
 
-SVGElementAnimatedProperties::SVGElementAnimatedProperties()
-    : element(0)
-{ }
-
-SVGElementAnimatedProperties::SVGElementAnimatedProperties(SVGElement* element, Vector<RefPtr<SVGAnimatedProperty>>& properties)
-    : element(element)
-    , properties(properties)
-{ }
-
 SVGAnimatedTypeAnimator::SVGAnimatedTypeAnimator(AnimatedPropertyType type, SVGAnimationElement* animationElement, SVGElement* contextElement)
     : m_type(type)
     , m_animationElement(animationElement)
@@ -44,7 +35,8 @@
 }
 
 SVGAnimatedTypeAnimator::~SVGAnimatedTypeAnimator()
-{ }
+{
+}
 
 void SVGAnimatedTypeAnimator::calculateFromAndToValues(std::unique_ptr<SVGAnimatedType>& from, std::unique_ptr<SVGAnimatedType>& to, const String& fromString, const String& toString)
 {
@@ -59,41 +51,27 @@
     addAnimatedTypes(from.get(), to.get());
 }
 
-SVGElementAnimatedPropertyList SVGAnimatedTypeAnimator::findAnimatedPropertiesForAttributeName(SVGElement* targetElement, const QualifiedName& attributeName)
+SVGElementAnimatedPropertyList SVGAnimatedTypeAnimator::findAnimatedPropertiesForAttributeName(SVGElement& targetElement, const QualifiedName& attributeName)
 {
-    ASSERT(targetElement);
+    SVGElementAnimatedPropertyList result;
 
-    SVGElementAnimatedPropertyList propertiesByInstance;
+    if (!SVGAnimatedType::supportsAnimVal(m_type))
+        return result;
 
-    Vector<RefPtr<SVGAnimatedProperty>> targetProperties;
-    targetElement->localAttributeToPropertyMap().animatedPropertiesForAttribute(targetElement, attributeName, targetProperties);
+    auto& propertyMap = targetElement.localAttributeToPropertyMap();
+    auto targetProperties = propertyMap.properties(targetElement, attributeName);
 
-    if (!SVGAnimatedType::supportsAnimVal(m_type) || targetProperties.isEmpty())
-        return SVGElementAnimatedPropertyList();
+    if (targetProperties.isEmpty())
+        return result;
 
-    SVGElementAnimatedProperties propertiesPair(targetElement, targetProperties);
-    propertiesByInstance.append(propertiesPair);
+    result.append(SVGElementAnimatedProperties { &targetElement, WTF::move(targetProperties) });
 
-    const HashSet<SVGElementInstance*>& instances = targetElement->instancesForElement();
-    const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
-    for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
-        SVGElement* shadowTreeElement = (*it)->shadowTreeElement();
-        if (!shadowTreeElement)
-            continue;
+    for (SVGElement* instance : targetElement.instances())
+        result.append(SVGElementAnimatedProperties { instance, propertyMap.properties(*instance, attributeName) });
 
-        Vector<RefPtr<SVGAnimatedProperty>> instanceProperties;
-        targetElement->localAttributeToPropertyMap().animatedPropertiesForAttribute(shadowTreeElement, attributeName, instanceProperties);
-
-        SVGElementAnimatedProperties instancePropertiesPair(shadowTreeElement, instanceProperties);
-        propertiesByInstance.append(instancePropertiesPair);
-    }
-
 #if !ASSERT_DISABLED
-    SVGElementAnimatedPropertyList::const_iterator propertiesEnd = propertiesByInstance.end();
-    for (SVGElementAnimatedPropertyList::const_iterator it = propertiesByInstance.begin(); it != propertiesEnd; ++it) {
-        size_t propertiesSize = it->properties.size();
-        for (size_t i = 0; i < propertiesSize; ++i) {
-            RefPtr<SVGAnimatedProperty> property = it->properties[i];
+    for (auto& animatedProperties : result) {
+        for (auto& property : animatedProperties.properties) {
             if (property->animatedPropertyType() != m_type) {
                 ASSERT(m_type == AnimatedAngle);
                 ASSERT(property->animatedPropertyType() == AnimatedEnumeration);
@@ -102,7 +80,7 @@
     }
 #endif
 
-    return propertiesByInstance;
+    return result;
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/svg/SVGAnimatedTypeAnimator.h (179259 => 179260)


--- trunk/Source/WebCore/svg/SVGAnimatedTypeAnimator.h	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/svg/SVGAnimatedTypeAnimator.h	2015-01-28 17:59:50 UTC (rev 179260)
@@ -29,10 +29,6 @@
 namespace WebCore {
 
 struct SVGElementAnimatedProperties {
-    SVGElementAnimatedProperties();
-
-    SVGElementAnimatedProperties(SVGElement*, Vector<RefPtr<SVGAnimatedProperty>>&);
-
     SVGElement* element;
     Vector<RefPtr<SVGAnimatedProperty>> properties;
 };
@@ -62,7 +58,7 @@
     void setContextElement(SVGElement* contextElement) { m_contextElement = contextElement; }
     AnimatedPropertyType type() const { return m_type; }
 
-    SVGElementAnimatedPropertyList findAnimatedPropertiesForAttributeName(SVGElement*, const QualifiedName&);
+    SVGElementAnimatedPropertyList findAnimatedPropertiesForAttributeName(SVGElement&, const QualifiedName&);
 
 protected:
     SVGAnimatedTypeAnimator(AnimatedPropertyType, SVGAnimationElement*, SVGElement*);

Modified: trunk/Source/WebCore/svg/SVGAnimationElement.cpp (179259 => 179260)


--- trunk/Source/WebCore/svg/SVGAnimationElement.cpp	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/svg/SVGAnimationElement.cpp	2015-01-28 17:59:50 UTC (rev 179260)
@@ -508,12 +508,9 @@
 
     CalcMode calcMode = this->calcMode();
     if (is<SVGAnimateElement>(*this) || is<SVGAnimateColorElement>(*this)) {
-        AnimatedPropertyType attributeType = downcast<SVGAnimateElementBase>(*this).determineAnimatedPropertyType(targetElement());
-        // Fall back to discrete animations for Strings.
-        if (attributeType == AnimatedBoolean
-            || attributeType == AnimatedEnumeration
-            || attributeType == AnimatedPreserveAspectRatio
-            || attributeType == AnimatedString)
+        ASSERT(targetElement());
+        AnimatedPropertyType type = downcast<SVGAnimateElementBase>(*this).determineAnimatedPropertyType(*targetElement());
+        if (type == AnimatedBoolean || type == AnimatedEnumeration || type == AnimatedPreserveAspectRatio || type == AnimatedString)
             calcMode = CalcModeDiscrete;
     }
     if (!m_keyPoints.isEmpty() && calcMode != CalcModePaced)

Modified: trunk/Source/WebCore/svg/SVGElement.cpp (179259 => 179260)


--- trunk/Source/WebCore/svg/SVGElement.cpp	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/svg/SVGElement.cpp	2015-01-28 17:59:50 UTC (rev 179260)
@@ -281,11 +281,14 @@
 SVGElement::~SVGElement()
 {
     if (m_svgRareData) {
-        m_svgRareData->destroyAnimatedSMILStyleProperties();
+        for (SVGElement* instance : m_svgRareData->instances())
+            instance->m_svgRareData->setCorrespondingElement(nullptr);
         if (SVGCursorElement* cursorElement = m_svgRareData->cursorElement())
             cursorElement->removeClient(this);
         if (CSSCursorImageValue* cursorImageValue = m_svgRareData->cursorImageValue())
             cursorImageValue->removeReferencedElement(this);
+        if (SVGElement* correspondingElement = m_svgRareData->correspondingElement())
+            correspondingElement->m_svgRareData->instances().remove(this);
 
         m_svgRareData = nullptr;
     }
@@ -420,34 +423,13 @@
     return nullptr;
 }
  
-void SVGElement::mapInstanceToElement(SVGElementInstance* instance)
+const HashSet<SVGElement*>& SVGElement::instances() const
 {
-    ASSERT(instance);
-
-    HashSet<SVGElementInstance*>& instances = ensureSVGRareData().elementInstances();
-    ASSERT(!instances.contains(instance));
-
-    instances.add(instance);
-}
- 
-void SVGElement::removeInstanceMapping(SVGElementInstance* instance)
-{
-    ASSERT(instance);
-    ASSERT(m_svgRareData);
-
-    HashSet<SVGElementInstance*>& instances = m_svgRareData->elementInstances();
-    ASSERT(instances.contains(instance));
-
-    instances.remove(instance);
-}
-
-const HashSet<SVGElementInstance*>& SVGElement::instancesForElement() const
-{
     if (!m_svgRareData) {
-        static NeverDestroyed<HashSet<SVGElementInstance*>> emptyInstances;
+        static NeverDestroyed<HashSet<SVGElement*>> emptyInstances;
         return emptyInstances;
     }
-    return m_svgRareData->elementInstances();
+    return m_svgRareData->instances();
 }
 
 bool SVGElement::getBoundingBox(FloatRect& rect, SVGLocatable::StyleUpdateStrategy styleUpdateStrategy)
@@ -495,13 +477,32 @@
 
 SVGElement* SVGElement::correspondingElement()
 {
-    ASSERT(!m_svgRareData || !m_svgRareData->correspondingElement() || containingShadowRoot());
-    return m_svgRareData ? m_svgRareData->correspondingElement() : 0;
+    ASSERT(!m_svgRareData || !m_svgRareData->correspondingElement() || correspondingUseElement());
+    return m_svgRareData ? m_svgRareData->correspondingElement() : nullptr;
 }
 
+SVGUseElement* SVGElement::correspondingUseElement() const
+{
+    auto* root = containingShadowRoot();
+    if (!root)
+        return nullptr;
+    if (root->type() != ShadowRoot::UserAgentShadowRoot)
+        return nullptr;
+    auto* host = root->hostElement();
+    if (!is<SVGUseElement>(host))
+        return nullptr;
+    return &downcast<SVGUseElement>(*host);
+}
+
 void SVGElement::setCorrespondingElement(SVGElement* correspondingElement)
 {
+    if (m_svgRareData) {
+        if (SVGElement* oldCorrespondingElement = m_svgRareData->correspondingElement())
+            oldCorrespondingElement->m_svgRareData->instances().remove(this);
+    }
     ensureSVGRareData().setCorrespondingElement(correspondingElement);
+    if (correspondingElement)
+        correspondingElement->ensureSVGRareData().instances().add(this);
 }
 
 void SVGElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
@@ -533,23 +534,31 @@
     }
 }
 
-void SVGElement::animatedPropertyTypeForAttribute(const QualifiedName& attributeName, Vector<AnimatedPropertyType>& propertyTypes)
+Vector<AnimatedPropertyType> SVGElement::animatedPropertyTypesForAttribute(const QualifiedName& attributeName)
 {
-    localAttributeToPropertyMap().animatedPropertyTypeForAttribute(attributeName, propertyTypes);
-    if (!propertyTypes.isEmpty())
-        return;
+    auto types = localAttributeToPropertyMap().types(attributeName);
+    if (!types.isEmpty())
+        return types;
 
-    auto& map = attributeNameToAnimatedPropertyTypeMap();
-    auto it = map.find(attributeName.impl());
-    if (it != map.end()) {
-        propertyTypes.append(it->value);
-        return;
+    {
+        auto& map = attributeNameToAnimatedPropertyTypeMap();
+        auto it = map.find(attributeName.impl());
+        if (it != map.end()) {
+            types.append(it->value);
+            return types;
+        }
     }
 
-    auto& cssPropertyWithSVGDOMMap = cssPropertyWithSVGDOMNameToAnimatedPropertyTypeMap();
-    auto svgPropertyIterator = cssPropertyWithSVGDOMMap.find(attributeName.impl());
-    if (svgPropertyIterator != cssPropertyWithSVGDOMMap.end())
-        propertyTypes.append(svgPropertyIterator->value);
+    {
+        auto& map = cssPropertyWithSVGDOMNameToAnimatedPropertyTypeMap();
+        auto it = map.find(attributeName.impl());
+        if (it != map.end()) {
+            types.append(it->value);
+            return types;
+        }
+    }
+
+    return types;
 }
 
 bool SVGElement::haveLoadedRequiredResources()
@@ -574,11 +583,9 @@
 
     // Add event listener to all shadow tree DOM element instances
     ASSERT(!instanceUpdatesBlocked());
-    for (auto& instance : instancesForElement()) {
-        ASSERT(instance->shadowTreeElement());
+    for (auto* instance : instances()) {
         ASSERT(instance->correspondingElement() == this);
-
-        bool result = instance->shadowTreeElement()->Node::addEventListener(eventType, listener, useCapture);
+        bool result = instance->Node::addEventListener(eventType, listener, useCapture);
         ASSERT_UNUSED(result, result);
     }
 
@@ -603,13 +610,10 @@
 
     // Remove event listener from all shadow tree DOM element instances
     ASSERT(!instanceUpdatesBlocked());
-    for (auto& instance : instancesForElement()) {
+    for (auto& instance : instances()) {
         ASSERT(instance->correspondingElement() == this);
 
-        SVGElement* shadowTreeElement = instance->shadowTreeElement();
-        ASSERT(shadowTreeElement);
-
-        if (shadowTreeElement->Node::removeEventListener(eventType, listener, useCapture))
+        if (instance->Node::removeEventListener(eventType, listener, useCapture))
             continue;
 
         // This case can only be hit for event listeners created from markup
@@ -620,11 +624,9 @@
         // 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);
+        // and tryRemoveEventListener() above will fail. Work around that very rare problem.
+        ASSERT(instance->eventTargetData());
+        instance->eventTargetData()->eventListenerMap.removeFirstEventListenerCreatedFromMarkup(eventType);
     }
 
     return true;
@@ -754,7 +756,7 @@
     ASSERT(svgElement->elementData());
     ASSERT(svgElement->elementData()->animatedSVGAttributesAreDirty());
 
-    svgElement->localAttributeToPropertyMap().synchronizeProperties(svgElement);
+    svgElement->localAttributeToPropertyMap().synchronizeProperties(*svgElement);
     svgElement->elementData()->setAnimatedSVGAttributesAreDirty(false);
 }
 
@@ -767,7 +769,7 @@
     if (name == anyQName())
         synchronizeAllAnimatedSVGAttribute(nonConstThis);
     else
-        nonConstThis->localAttributeToPropertyMap().synchronizeProperty(nonConstThis, name);
+        nonConstThis->localAttributeToPropertyMap().synchronizeProperty(*nonConstThis, name);
 }
 
 void SVGElement::synchronizeRequiredFeatures(SVGElement* contextElement)
@@ -1016,9 +1018,7 @@
 
 bool SVGElement::isPresentationAttributeWithSVGDOM(const QualifiedName& attributeName)
 {
-    Vector<AnimatedPropertyType> propertyTypes;
-    localAttributeToPropertyMap().animatedPropertyTypeForAttribute(attributeName, propertyTypes);
-    return !propertyTypes.isEmpty();
+    return !localAttributeToPropertyMap().types(attributeName).isEmpty();
 }
 
 bool SVGElement::isPresentationAttribute(const QualifiedName& name) const

Modified: trunk/Source/WebCore/svg/SVGElement.h (179259 => 179260)


--- trunk/Source/WebCore/svg/SVGElement.h	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/svg/SVGElement.h	2015-01-28 17:59:50 UTC (rev 179260)
@@ -49,6 +49,7 @@
 class SVGElementInstance;
 class SVGElementRareData;
 class SVGSVGElement;
+class SVGUseElement;
 
 void mapAttributeToCSSProperty(HashMap<AtomicStringImpl*, CSSPropertyID>* propertyNameToIdMap, const QualifiedName& attrName);
 
@@ -85,7 +86,7 @@
 
     virtual void svgAttributeChanged(const QualifiedName&);
 
-    void animatedPropertyTypeForAttribute(const QualifiedName&, Vector<AnimatedPropertyType>&);
+    Vector<AnimatedPropertyType> animatedPropertyTypesForAttribute(const QualifiedName&);
 
     void sendSVGLoadEventIfPossible(bool sendParentLoadEvents = false);
     void sendSVGLoadEventIfPossibleAsynchronously();
@@ -102,7 +103,8 @@
         setNeedsStyleRecalc(InlineStyleChange);
     }
 
-    const HashSet<SVGElementInstance*>& instancesForElement() const;
+    // The instances of an element are clones made in shadow trees to implement <use>.
+    const HashSet<SVGElement*>& instances() const;
 
     bool getBoundingBox(FloatRect&, SVGLocatable::StyleUpdateStrategy = SVGLocatable::AllowStyleUpdate);
 
@@ -112,6 +114,8 @@
     void cursorImageValueRemoved();
 
     SVGElement* correspondingElement();
+    SVGUseElement* correspondingUseElement() const;
+
     void setCorrespondingElement(SVGElement*);
 
     void synchronizeAnimatedSVGAttribute(const QualifiedName&) const;
@@ -189,9 +193,6 @@
 
     virtual void clearTarget() { }
 
-    void mapInstanceToElement(SVGElementInstance*);
-    void removeInstanceMapping(SVGElementInstance*);
-
     void buildPendingResourcesIfNeeded();
     virtual void accessKeyAction(bool sendMouseEvents) override;
 

Modified: trunk/Source/WebCore/svg/SVGElementInstance.cpp (179259 => 179260)


--- trunk/Source/WebCore/svg/SVGElementInstance.cpp	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/svg/SVGElementInstance.cpp	2015-01-28 17:59:50 UTC (rev 179260)
@@ -101,9 +101,6 @@
     ASSERT(m_correspondingUseElement);
     ASSERT(m_element);
 
-    // Register as instance for passed element.
-    m_element->mapInstanceToElement(this);
-
 #ifndef NDEBUG
     instanceCounter.increment();
 #endif
@@ -144,9 +141,6 @@
     for (SVGElementInstance* node = firstChild(); node; node = node->nextSibling())
         node->detach();
 
-    // Deregister as instance for passed element, if we haven't already.
-    if (m_element->instancesForElement().contains(this))
-        m_element->removeInstanceMapping(this);
     // DO NOT clear ref to m_element because _javascript_Core uses it for garbage collection
 
     m_shadowTreeElement = 0;
@@ -181,24 +175,19 @@
     if (element->instanceUpdatesBlocked())
         return;
 
-    const HashSet<SVGElementInstance*>& set = element->instancesForElement();
-    if (set.isEmpty())
+    auto& instances = element->instances();
+    if (instances.isEmpty())
         return;
 
     // Mark all use elements referencing 'element' for rebuilding
-    const HashSet<SVGElementInstance*>::const_iterator end = set.end();
-    for (HashSet<SVGElementInstance*>::const_iterator it = set.begin(); it != end; ++it) {
-        ASSERT((*it)->shadowTreeElement());
-        ASSERT((*it)->shadowTreeElement()->correspondingElement());
-        ASSERT((*it)->shadowTreeElement()->correspondingElement() == (*it)->correspondingElement());
-        ASSERT((*it)->correspondingElement() == element);
-        (*it)->shadowTreeElement()->setCorrespondingElement(0);
-
-        if (SVGUseElement* element = (*it)->correspondingUseElement()) {
+    do {
+        SVGElement* instance = *instances.begin();
+        if (SVGUseElement* element = instance->correspondingUseElement()) {
             ASSERT(element->inDocument());
             element->invalidateShadowTree();
         }
-    }
+        instance->setCorrespondingElement(nullptr);
+    } while (!instances.isEmpty());
 
     element->document().updateStyleIfNeeded();
 }

Modified: trunk/Source/WebCore/svg/SVGElementRareData.h (179259 => 179260)


--- trunk/Source/WebCore/svg/SVGElementRareData.h	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/svg/SVGElementRareData.h	2015-01-28 17:59:50 UTC (rev 179260)
@@ -31,23 +31,19 @@
 class CSSCursorImageValue;
 class SVGCursorElement;
 class SVGElement;
-class SVGElementInstance;
 
 class SVGElementRareData {
     WTF_MAKE_NONCOPYABLE(SVGElementRareData); WTF_MAKE_FAST_ALLOCATED;
 public:
     SVGElementRareData()
-        : m_cursorElement(0)
-        , m_cursorImageValue(0)
-        , m_correspondingElement(0)
-        , m_instancesUpdatesBlocked(false)
+        : m_instancesUpdatesBlocked(false)
         , m_useOverrideComputedStyle(false)
         , m_needsOverrideComputedStyleUpdate(false)
     {
     }
 
-    HashSet<SVGElementInstance*>& elementInstances() { return m_elementInstances; }
-    const HashSet<SVGElementInstance*>& elementInstances() const { return m_elementInstances; }
+    HashSet<SVGElement*>& instances() { return m_instances; }
+    const HashSet<SVGElement*>& instances() const { return m_instances; }
 
     bool instanceUpdatesBlocked() const { return m_instancesUpdatesBlocked; }
     void setInstanceUpdatesBlocked(bool value) { m_instancesUpdatesBlocked = value; }
@@ -69,11 +65,6 @@
         return *m_animatedSMILStyleProperties;
     }
 
-    void destroyAnimatedSMILStyleProperties()
-    {
-        m_animatedSMILStyleProperties.clear();
-    }
-
     RenderStyle* overrideComputedStyle(Element* element, RenderStyle* parentStyle)
     {
         ASSERT(element);
@@ -93,10 +84,10 @@
     void setNeedsOverrideComputedStyleUpdate() { m_needsOverrideComputedStyleUpdate = true; }
 
 private:
-    HashSet<SVGElementInstance*> m_elementInstances;
-    SVGCursorElement* m_cursorElement;
-    CSSCursorImageValue* m_cursorImageValue;
-    SVGElement* m_correspondingElement;
+    HashSet<SVGElement*> m_instances;
+    SVGCursorElement* m_cursorElement { nullptr };
+    CSSCursorImageValue* m_cursorImageValue { nullptr };
+    SVGElement* m_correspondingElement { nullptr };
     bool m_instancesUpdatesBlocked : 1;
     bool m_useOverrideComputedStyle : 1;
     bool m_needsOverrideComputedStyleUpdate : 1;

Modified: trunk/Source/WebCore/svg/SVGTests.cpp (179259 => 179260)


--- trunk/Source/WebCore/svg/SVGTests.cpp	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/svg/SVGTests.cpp	2015-01-28 17:59:50 UTC (rev 179260)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <[email protected]>
  * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <[email protected]>
+ * Copyright (C) 2015 Apple Inc. All right reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -36,77 +37,52 @@
 
 namespace WebCore {
 
-// Define custom non-animated property 'requiredFeatures'.
-const SVGPropertyInfo* SVGTests::requiredFeaturesPropertyInfo()
-{
-    static const SVGPropertyInfo* s_propertyInfo = 0;
-    if (!s_propertyInfo) {
-        s_propertyInfo = new SVGPropertyInfo(AnimatedUnknown,
-                                             PropertyIsReadWrite,
-                                             SVGNames::requiredFeaturesAttr,
-                                             SVGNames::requiredFeaturesAttr.localName(),
-                                             &SVGElement::synchronizeRequiredFeatures,
-                                             0);
-    }
-    return s_propertyInfo;
-}
+using namespace SVGNames;
 
-// Define custom non-animated property 'requiredExtensions'.
-const SVGPropertyInfo* SVGTests::requiredExtensionsPropertyInfo()
+SVGTests::SVGTests()
+    : m_requiredFeatures(requiredFeaturesAttr)
+    , m_requiredExtensions(requiredExtensionsAttr)
+    , m_systemLanguage(systemLanguageAttr)
 {
-    static const SVGPropertyInfo* s_propertyInfo = 0;
-    if (!s_propertyInfo) {
-        s_propertyInfo = new SVGPropertyInfo(AnimatedUnknown,
-                                             PropertyIsReadWrite,
-                                             SVGNames::requiredExtensionsAttr,
-                                             SVGNames::requiredExtensionsAttr.localName(),
-                                             &SVGElement::synchronizeRequiredExtensions,
-                                             0);
-    }
-    return s_propertyInfo;
 }
 
-// Define custom non-animated property 'systemLanguage'.
-const SVGPropertyInfo* SVGTests::systemLanguagePropertyInfo()
+static SVGPropertyInfo createSVGTestPropertyInfo(const QualifiedName& attributeName, SVGPropertyInfo::SynchronizeProperty synchronizeFunction)
 {
-    static const SVGPropertyInfo* s_propertyInfo = 0;
-    if (!s_propertyInfo) {
-        s_propertyInfo = new SVGPropertyInfo(AnimatedUnknown,
-                                             PropertyIsReadWrite,
-                                             SVGNames::systemLanguageAttr,
-                                             SVGNames::systemLanguageAttr.localName(),
-                                             &SVGElement::synchronizeSystemLanguage,
-                                             0);
-    }
-    return s_propertyInfo;
+    return { AnimatedUnknown, PropertyIsReadWrite, attributeName, attributeName.localName(), synchronizeFunction, nullptr };
 }
 
-SVGTests::SVGTests()
-    : m_requiredFeatures(SVGNames::requiredFeaturesAttr)
-    , m_requiredExtensions(SVGNames::requiredExtensionsAttr)
-    , m_systemLanguage(SVGNames::systemLanguageAttr)
+static SVGAttributeToPropertyMap createSVGTextAttributeToPropertyMap()
 {
+    typedef NeverDestroyed<const SVGPropertyInfo> Info;
+
+    SVGAttributeToPropertyMap map;
+
+    static Info requiredFeatures = createSVGTestPropertyInfo(requiredFeaturesAttr, SVGElement::synchronizeRequiredFeatures);
+    map.addProperty(requiredFeatures.get());
+
+    static Info requiredExtensions = createSVGTestPropertyInfo(requiredExtensionsAttr, SVGElement::synchronizeRequiredExtensions);
+    map.addProperty(requiredExtensions.get());
+
+    static Info systemLanguage = createSVGTestPropertyInfo(systemLanguageAttr, SVGElement::synchronizeSystemLanguage);
+    map.addProperty(systemLanguage.get());
+
+    return map;
 }
 
-SVGAttributeToPropertyMap& SVGTests::attributeToPropertyMap()
+const SVGAttributeToPropertyMap& SVGTests::attributeToPropertyMap()
 {
-    static NeverDestroyed<SVGAttributeToPropertyMap> map;
-    if (!map.get().isEmpty())
-        return map;
-    map.get().addProperty(requiredFeaturesPropertyInfo());
-    map.get().addProperty(requiredExtensionsPropertyInfo());
-    map.get().addProperty(systemLanguagePropertyInfo());
+    static NeverDestroyed<SVGAttributeToPropertyMap> map = createSVGTextAttributeToPropertyMap();
     return map;
 }
 
-bool SVGTests::hasExtension(const String& extension) const
+bool SVGTests::hasExtension(const String& extension)
 {
     // We recognize XHTML and MathML, as implemented in Gecko and suggested in the SVG Tiny recommendation (http://www.w3.org/TR/SVG11/struct.html#RequiredExtensionsAttribute).
 #if ENABLE(MATHML)
-    return extension == HTMLNames::xhtmlNamespaceURI || extension == MathMLNames::mathmlNamespaceURI;
-#else
-    return extension == HTMLNames::xhtmlNamespaceURI;
+    if (extension == MathMLNames::mathmlNamespaceURI)
+        return true;
 #endif
+    return extension == HTMLNames::xhtmlNamespaceURI;
 }
 
 bool SVGTests::isValid() const
@@ -115,90 +91,80 @@
         if (feature.isEmpty() || !DOMImplementation::hasFeature(feature, String()))
             return false;
     }
-
     for (auto& language : m_systemLanguage.value) {
         if (language != defaultLanguage().substring(0, 2))
             return false;
     }
-
     for (auto& extension : m_requiredExtensions.value) {
         if (!hasExtension(extension))
             return false;
     }
-
     return true;
 }
 
-bool SVGTests::parseAttribute(const QualifiedName& name, const AtomicString& value)
+bool SVGTests::parseAttribute(const QualifiedName& attributeName, const AtomicString& value)
 {
-    if (name == SVGNames::requiredFeaturesAttr) {
+    if (attributeName == requiredFeaturesAttr) {
         m_requiredFeatures.value.reset(value);
         return true;
     }
-    if (name == SVGNames::requiredExtensionsAttr) {
+    if (attributeName == requiredExtensionsAttr) {
         m_requiredExtensions.value.reset(value);
         return true;
     }
-    if (name == SVGNames::systemLanguageAttr) {
+    if (attributeName == systemLanguageAttr) {
         m_systemLanguage.value.reset(value);
         return true;
     }
-    
     return false;
 }
 
-bool SVGTests::isKnownAttribute(const QualifiedName& attrName)
+bool SVGTests::isKnownAttribute(const QualifiedName& attributeName)
 {
-    return attrName == SVGNames::requiredFeaturesAttr
-        || attrName == SVGNames::requiredExtensionsAttr
-        || attrName == SVGNames::systemLanguageAttr;
+    return attributeName == requiredFeaturesAttr
+        || attributeName == requiredExtensionsAttr
+        || attributeName == systemLanguageAttr;
 }
 
-bool SVGTests::handleAttributeChange(SVGElement* targetElement, const QualifiedName& attrName)
+bool SVGTests::handleAttributeChange(SVGElement* targetElement, const QualifiedName& attributeName)
 {
     ASSERT(targetElement);
-    if (!isKnownAttribute(attrName))
+    if (!isKnownAttribute(attributeName))
         return false;
     if (!targetElement->inDocument())
         return true;
-
     targetElement->setNeedsStyleRecalc(ReconstructRenderTree);
-
     return true;
 }
 
 void SVGTests::addSupportedAttributes(HashSet<QualifiedName>& supportedAttributes)
 {
-    supportedAttributes.add(SVGNames::requiredFeaturesAttr);
-    supportedAttributes.add(SVGNames::requiredExtensionsAttr);
-    supportedAttributes.add(SVGNames::systemLanguageAttr);
+    supportedAttributes.add(requiredFeaturesAttr);
+    supportedAttributes.add(requiredExtensionsAttr);
+    supportedAttributes.add(systemLanguageAttr);
 }
 
-void SVGTests::synchronizeRequiredFeatures(SVGElement* contextElement)
+void SVGTests::synchronizeAttribute(SVGElement* contextElement, SVGSynchronizableAnimatedProperty<SVGStringList>& property, const QualifiedName& attributeName)
 {
     ASSERT(contextElement);
-    if (!m_requiredFeatures.shouldSynchronize)
+    if (!property.shouldSynchronize)
         return;
-    AtomicString value(m_requiredFeatures.value.valueAsString());
-    m_requiredFeatures.synchronize(contextElement, requiredFeaturesPropertyInfo()->attributeName, value);
+    m_requiredFeatures.synchronize(contextElement, attributeName, property.value.valueAsString());
 }
 
+void SVGTests::synchronizeRequiredFeatures(SVGElement* contextElement)
+{
+    synchronizeAttribute(contextElement, m_requiredFeatures, requiredFeaturesAttr);
+}
+
 void SVGTests::synchronizeRequiredExtensions(SVGElement* contextElement)
 {
-    ASSERT(contextElement);
-    if (!m_requiredExtensions.shouldSynchronize)
-        return;
-    AtomicString value(m_requiredExtensions.value.valueAsString());
-    m_requiredExtensions.synchronize(contextElement, requiredExtensionsPropertyInfo()->attributeName, value);
+    synchronizeAttribute(contextElement, m_requiredExtensions, requiredExtensionsAttr);
 }
 
 void SVGTests::synchronizeSystemLanguage(SVGElement* contextElement)
 {
-    ASSERT(contextElement);
-    if (!m_systemLanguage.shouldSynchronize)
-        return;
-    AtomicString value(m_systemLanguage.value.valueAsString());
-    m_systemLanguage.synchronize(contextElement, systemLanguagePropertyInfo()->attributeName, value);
+    synchronizeAttribute(contextElement, m_systemLanguage, systemLanguageAttr);
 }
 
 SVGStringList& SVGTests::requiredFeatures()

Modified: trunk/Source/WebCore/svg/SVGTests.h (179259 => 179260)


--- trunk/Source/WebCore/svg/SVGTests.h	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/svg/SVGTests.h	2015-01-28 17:59:50 UTC (rev 179260)
@@ -26,8 +26,6 @@
 
 namespace WebCore {
 
-class Attribute;
-class QualifiedName;
 class SVGElement;
 
 class SVGTests {
@@ -36,16 +34,16 @@
     SVGStringList& requiredExtensions();
     SVGStringList& systemLanguage();
 
-    bool hasExtension(const String&) const;
+    static bool hasExtension(const String&);
     bool isValid() const;
 
     bool parseAttribute(const QualifiedName&, const AtomicString&);
-    bool isKnownAttribute(const QualifiedName&);
+    static bool isKnownAttribute(const QualifiedName&);
 
-    void addSupportedAttributes(HashSet<QualifiedName>&);
-    bool handleAttributeChange(SVGElement*, const QualifiedName&);
+    static void addSupportedAttributes(HashSet<QualifiedName>&);
+    static bool handleAttributeChange(SVGElement*, const QualifiedName&);
 
-    static SVGAttributeToPropertyMap& attributeToPropertyMap();
+    static const SVGAttributeToPropertyMap& attributeToPropertyMap();
 
 protected:
     SVGTests();
@@ -55,16 +53,10 @@
     void synchronizeSystemLanguage(SVGElement* contextElement);
 
 private:
-    // Custom 'requiredFeatures' property
-    static const SVGPropertyInfo* requiredFeaturesPropertyInfo();
-    SVGSynchronizableAnimatedProperty<SVGStringList> m_requiredFeatures;
+    void synchronizeAttribute(SVGElement* contextElement, SVGSynchronizableAnimatedProperty<SVGStringList>&, const QualifiedName& attributeName);
 
-    // Custom 'requiredExtensions' property
-    static const SVGPropertyInfo* requiredExtensionsPropertyInfo();
+    SVGSynchronizableAnimatedProperty<SVGStringList> m_requiredFeatures;
     SVGSynchronizableAnimatedProperty<SVGStringList> m_requiredExtensions;
-
-    // Custom 'systemLanguage' property
-    static const SVGPropertyInfo* systemLanguagePropertyInfo();
     SVGSynchronizableAnimatedProperty<SVGStringList> m_systemLanguage;
 };
 

Modified: trunk/Source/WebCore/svg/SVGUseElement.cpp (179259 => 179260)


--- trunk/Source/WebCore/svg/SVGUseElement.cpp	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/svg/SVGUseElement.cpp	2015-01-28 17:59:50 UTC (rev 179260)
@@ -776,10 +776,8 @@
 void SVGUseElement::invalidateDependentShadowTrees()
 {
     // Recursively invalidate dependent <use> shadow trees
-    const HashSet<SVGElementInstance*>& instances = instancesForElement();
-    const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
-    for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
-        if (SVGUseElement* element = (*it)->correspondingUseElement()) {
+    for (auto* instance : instances()) {
+        if (SVGUseElement* element = instance->correspondingUseElement()) {
             ASSERT(element->inDocument());
             element->invalidateShadowTree();
         }

Modified: trunk/Source/WebCore/svg/properties/SVGAnimatedPropertyMacros.h (179259 => 179260)


--- trunk/Source/WebCore/svg/properties/SVGAnimatedPropertyMacros.h	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/svg/properties/SVGAnimatedPropertyMacros.h	2015-01-28 17:59:50 UTC (rev 179260)
@@ -26,6 +26,7 @@
 #include "SVGAnimatedProperty.h"
 #include "SVGAttributeToPropertyMap.h"
 #include "SVGPropertyTraits.h"
+#include <wtf/NeverDestroyed.h>
 #include <wtf/StdLibExtras.h>
 
 namespace WebCore {
@@ -70,23 +71,19 @@
 #define BEGIN_REGISTER_ANIMATED_PROPERTIES(OwnerType) \
 SVGAttributeToPropertyMap& OwnerType::attributeToPropertyMap() \
 { \
-    DEPRECATED_DEFINE_STATIC_LOCAL(SVGAttributeToPropertyMap, s_attributeToPropertyMap, ()); \
-    return s_attributeToPropertyMap; \
+    static NeverDestroyed<SVGAttributeToPropertyMap> map; \
+    return map; \
 } \
 \
 static void registerAnimatedPropertiesFor##OwnerType() \
 { \
-    SVGAttributeToPropertyMap& map = OwnerType::attributeToPropertyMap(); \
+    auto& map = OwnerType::attributeToPropertyMap(); \
     if (!map.isEmpty()) \
         return; \
     typedef OwnerType UseOwnerType;
 
-#define REGISTER_LOCAL_ANIMATED_PROPERTY(LowerProperty) \
-     map.addProperty(UseOwnerType::LowerProperty##PropertyInfo());
-
-#define REGISTER_PARENT_ANIMATED_PROPERTIES(ClassName) \
-     map.addProperties(ClassName::attributeToPropertyMap()); \
-
+#define REGISTER_LOCAL_ANIMATED_PROPERTY(LowerProperty) map.addProperty(*UseOwnerType::LowerProperty##PropertyInfo());
+#define REGISTER_PARENT_ANIMATED_PROPERTIES(ClassName) map.addProperties(ClassName::attributeToPropertyMap());
 #define END_REGISTER_ANIMATED_PROPERTIES }
 
 // Property definition helpers (used in SVG*.cpp files)

Modified: trunk/Source/WebCore/svg/properties/SVGAttributeToPropertyMap.cpp (179259 => 179260)


--- trunk/Source/WebCore/svg/properties/SVGAttributeToPropertyMap.cpp	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/svg/properties/SVGAttributeToPropertyMap.cpp	2015-01-28 17:59:50 UTC (rev 179260)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
+ * Copyright (C) 2015 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
@@ -21,106 +22,65 @@
 #include "SVGAttributeToPropertyMap.h"
 
 #include "SVGAnimatedProperty.h"
-#include "SVGPropertyInfo.h"
 
 namespace WebCore {
 
 void SVGAttributeToPropertyMap::addProperties(const SVGAttributeToPropertyMap& map)
 {
-    AttributeToPropertiesMap::const_iterator end = map.m_map.end();
-    for (AttributeToPropertiesMap::const_iterator it = map.m_map.begin(); it != end; ++it) {
-        const PropertiesVector* vector = it->value.get();
-        ASSERT(vector);
-
-        // FIXME: This looks up the attribute name in the hash table for each property, even though all the
-        // properties in a single vector are guaranteed to have the same attribute name.
-        // FIXME: This grows the vector one item at a time, even though we know up front exactly how many
-        // elements we are adding to the vector.
-        PropertiesVector::const_iterator vectorEnd = vector->end();
-        for (PropertiesVector::const_iterator vectorIt = vector->begin(); vectorIt != vectorEnd; ++vectorIt)
-            addProperty(*vectorIt);
+    for (auto& vector : map.m_map.values()) {
+        ASSERT(!vector.isEmpty());
+        auto& properties = m_map.add(vector[0]->attributeName, PropertyInfoVector()).iterator->value;
+        properties.reserveCapacity(properties.size() + vector.size());
+        for (auto* property : vector)
+            properties.uncheckedAppend(property);
     }
 }
 
-void SVGAttributeToPropertyMap::addProperty(const SVGPropertyInfo* info)
+void SVGAttributeToPropertyMap::addProperty(const SVGPropertyInfo& info)
 {
-    ASSERT(info);
-    ASSERT(info->attributeName != anyQName());
-    if (PropertiesVector* vector = m_map.get(info->attributeName)) {
-        vector->append(info);
-        return;
-    }
-    // FIXME: This does a second hash table lookup, but with HashMap::add we could instead do only one.
-    auto vector = std::make_unique<PropertiesVector>();
-    vector->append(info);
-    m_map.set(info->attributeName, WTF::move(vector));
+    m_map.add(info.attributeName, PropertyInfoVector()).iterator->value.append(&info);
 }
 
-void SVGAttributeToPropertyMap::animatedPropertiesForAttribute(SVGElement* ownerType, const QualifiedName& attributeName, Vector<RefPtr<SVGAnimatedProperty>>& properties)
+Vector<RefPtr<SVGAnimatedProperty>> SVGAttributeToPropertyMap::properties(SVGElement& contextElement, const QualifiedName& attributeName) const
 {
-    ASSERT(ownerType);
-    PropertiesVector* vector = m_map.get(attributeName);
-    if (!vector)
-        return;
-
-    PropertiesVector::iterator vectorEnd = vector->end();
-    for (PropertiesVector::iterator vectorIt = vector->begin(); vectorIt != vectorEnd; ++vectorIt)
-        properties.append(animatedProperty(ownerType, attributeName, *vectorIt));
+    Vector<RefPtr<SVGAnimatedProperty>> properties;
+    auto it = m_map.find(attributeName);
+    if (it == m_map.end())
+        return properties;
+    properties.reserveInitialCapacity(it->value.size());
+    for (auto* property : it->value)
+        properties.uncheckedAppend(property->lookupOrCreateWrapperForAnimatedProperty(&contextElement));
+    return properties;
 }
 
-void SVGAttributeToPropertyMap::animatedPropertyTypeForAttribute(const QualifiedName& attributeName, Vector<AnimatedPropertyType>& propertyTypes)
+Vector<AnimatedPropertyType> SVGAttributeToPropertyMap::types(const QualifiedName& attributeName) const
 {
-    PropertiesVector* vector = m_map.get(attributeName);
-    if (!vector)
-        return;
-
-    PropertiesVector::iterator vectorEnd = vector->end();
-    for (PropertiesVector::iterator vectorIt = vector->begin(); vectorIt != vectorEnd; ++vectorIt)
-        propertyTypes.append((*vectorIt)->animatedPropertyType);
+    Vector<AnimatedPropertyType> types;
+    auto it = m_map.find(attributeName);
+    if (it == m_map.end())
+        return types;
+    types.reserveInitialCapacity(it->value.size());
+    for (auto* property : it->value)
+        types.uncheckedAppend(property->animatedPropertyType);
+    return types;
 }
 
-void SVGAttributeToPropertyMap::synchronizeProperties(SVGElement* contextElement)
+void SVGAttributeToPropertyMap::synchronizeProperties(SVGElement& contextElement) const
 {
-    ASSERT(contextElement);
-    AttributeToPropertiesMap::iterator end = m_map.end();
-    for (AttributeToPropertiesMap::iterator it = m_map.begin(); it != end; ++it) {
-        PropertiesVector* vector = it->value.get();
-        ASSERT(vector);
-
-        PropertiesVector::iterator vectorEnd = vector->end();
-        for (PropertiesVector::iterator vectorIt = vector->begin(); vectorIt != vectorEnd; ++vectorIt)
-            synchronizeProperty(contextElement, it->key, *vectorIt);
+    for (auto& vector : m_map.values()) {
+        for (auto* property : vector)
+            property->synchronizeProperty(&contextElement);
     } 
 }
 
-bool SVGAttributeToPropertyMap::synchronizeProperty(SVGElement* contextElement, const QualifiedName& attributeName)
+bool SVGAttributeToPropertyMap::synchronizeProperty(SVGElement& contextElement, const QualifiedName& attributeName) const
 {
-    ASSERT(contextElement);
-    PropertiesVector* vector = m_map.get(attributeName);
-    if (!vector)
+    auto it = m_map.find(attributeName);
+    if (it == m_map.end())
         return false;
-
-    PropertiesVector::iterator vectorEnd = vector->end();
-    for (PropertiesVector::iterator vectorIt = vector->begin(); vectorIt != vectorEnd; ++vectorIt)
-        synchronizeProperty(contextElement, attributeName, *vectorIt);
-
+    for (auto* property : it->value)
+        property->synchronizeProperty(&contextElement);
     return true;
 }
 
-void SVGAttributeToPropertyMap::synchronizeProperty(SVGElement* contextElement, const QualifiedName& attributeName, const SVGPropertyInfo* info)
-{
-    ASSERT(info);
-    ASSERT_UNUSED(attributeName, attributeName == info->attributeName);
-    ASSERT(info->synchronizeProperty);
-    (*info->synchronizeProperty)(contextElement);
 }
-
-PassRefPtr<SVGAnimatedProperty> SVGAttributeToPropertyMap::animatedProperty(SVGElement* contextElement, const QualifiedName& attributeName, const SVGPropertyInfo* info)
-{
-    ASSERT(info);
-    ASSERT_UNUSED(attributeName, attributeName == info->attributeName);
-    ASSERT(info->lookupOrCreateWrapperForAnimatedProperty);
-    return (*info->lookupOrCreateWrapperForAnimatedProperty)(contextElement);
-}
-
-}

Modified: trunk/Source/WebCore/svg/properties/SVGAttributeToPropertyMap.h (179259 => 179260)


--- trunk/Source/WebCore/svg/properties/SVGAttributeToPropertyMap.h	2015-01-28 17:54:27 UTC (rev 179259)
+++ trunk/Source/WebCore/svg/properties/SVGAttributeToPropertyMap.h	2015-01-28 17:59:50 UTC (rev 179260)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
+ * Copyright (C) 2015 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
@@ -32,24 +33,18 @@
 public:
     bool isEmpty() const { return m_map.isEmpty(); }
 
+    void addProperty(const SVGPropertyInfo&);
     void addProperties(const SVGAttributeToPropertyMap&);
-    void addProperty(const SVGPropertyInfo*);
 
-    // FIXME: To match WebKit coding style either these functions should have return values instead of out parameters,
-    // or the word "get" should be added as a prefix to their names.
-    void animatedPropertiesForAttribute(SVGElement* contextElement, const QualifiedName& attributeName, Vector<RefPtr<SVGAnimatedProperty>>&);
-    void animatedPropertyTypeForAttribute(const QualifiedName& attributeName, Vector<AnimatedPropertyType>&);
+    Vector<RefPtr<SVGAnimatedProperty>> properties(SVGElement&, const QualifiedName& attributeName) const;
+    Vector<AnimatedPropertyType> types(const QualifiedName& attributeName) const;
 
-    void synchronizeProperties(SVGElement* contextElement);
-    bool synchronizeProperty(SVGElement* contextElement, const QualifiedName& attributeName);
+    void synchronizeProperties(SVGElement&) const;
+    bool synchronizeProperty(SVGElement&, const QualifiedName& attributeName) const;
 
 private:
-    void synchronizeProperty(SVGElement* contextElement, const QualifiedName& attributeName, const SVGPropertyInfo*);
-    PassRefPtr<SVGAnimatedProperty> animatedProperty(SVGElement* contextElement, const QualifiedName& attributeName, const SVGPropertyInfo*);
-
-    typedef Vector<const SVGPropertyInfo*> PropertiesVector;
-    typedef HashMap<QualifiedName, std::unique_ptr<PropertiesVector>> AttributeToPropertiesMap;
-    AttributeToPropertiesMap m_map;
+    typedef Vector<const SVGPropertyInfo*> PropertyInfoVector;
+    HashMap<QualifiedName, PropertyInfoVector> m_map;
 };
 
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to