Make SVGElement::instancesForElement point to elements in the shadow tree, not SVGEle...
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 28 Jan 2015 17:59:50 +0000 (17:59 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 28 Jan 2015 17:59:50 +0000 (17:59 +0000)
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.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@179260 268f45cc-cd09-0410-ab3c-d52691b4dbfc

19 files changed:
Source/WebCore/ChangeLog
Source/WebCore/page/EventHandler.cpp
Source/WebCore/page/EventHandler.h
Source/WebCore/svg/SVGAnimateElementBase.cpp
Source/WebCore/svg/SVGAnimateElementBase.h
Source/WebCore/svg/SVGAnimateMotionElement.cpp
Source/WebCore/svg/SVGAnimatedTypeAnimator.cpp
Source/WebCore/svg/SVGAnimatedTypeAnimator.h
Source/WebCore/svg/SVGAnimationElement.cpp
Source/WebCore/svg/SVGElement.cpp
Source/WebCore/svg/SVGElement.h
Source/WebCore/svg/SVGElementInstance.cpp
Source/WebCore/svg/SVGElementRareData.h
Source/WebCore/svg/SVGTests.cpp
Source/WebCore/svg/SVGTests.h
Source/WebCore/svg/SVGUseElement.cpp
Source/WebCore/svg/properties/SVGAnimatedPropertyMacros.h
Source/WebCore/svg/properties/SVGAttributeToPropertyMap.cpp
Source/WebCore/svg/properties/SVGAttributeToPropertyMap.h

index 9e5a236ac1f43395dc08a11f96dd4d532e15a689..a86c9a7ec831c8531e56f0893dabd6acfd9a8131 100644 (file)
@@ -1,3 +1,165 @@
+2015-01-28  Darin Adler  <darin@apple.com>
+
+        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  <darin@apple.com>
 
         REGRESSION (r173698): Leaks of selector lists in CSS parsing
index 6061a395a112eb437fee8462b64cf02402f158f5..ddbc58275591be1915c70381cd323caaf5eeaf61 100644 (file)
@@ -459,7 +459,6 @@ void EventHandler::clear()
     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 @@ MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestReques
     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 @@ void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo
 
     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 @@ void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo
         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 @@ void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo
             }
         }
         m_lastElementUnderMouse = m_elementUnderMouse;
-        m_lastInstanceUnderMouse = instanceAssociatedWithShadowTreeElement(m_elementUnderMouse.get());
     }
 }
 
index 45f38d98f4a9599e88c7fc76c8d9d55eb721e9ac..d8ea748480b1768a493bc60ad5440c266373086f 100644 (file)
@@ -92,7 +92,6 @@ class RenderElement;
 class RenderLayer;
 class RenderWidget;
 class ScrollableArea;
-class SVGElementInstance;
 class Scrollbar;
 class TextEvent;
 class Touch;
@@ -488,7 +487,6 @@ private:
 #endif
 
     bool m_svgPan;
-    RefPtr<SVGElementInstance> m_lastInstanceUnderMouse;
 
     RenderLayer* m_resizeLayer;
 
index 7a412289ec32a4614fa8b7319ec0f9820c7ee851..bde2b719e5b3b0aa2903e566e7f47b528afdfb3a 100644 (file)
@@ -55,12 +55,9 @@ bool SVGAnimateElementBase::hasValidAttributeType()
     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 @@ AnimatedPropertyType SVGAnimateElementBase::determineAnimatedPropertyType(SVGEle
     // 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 @@ void SVGAnimateElementBase::calculateAnimatedValue(float percentage, unsigned re
     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 @@ void SVGAnimateElementBase::resetAnimatedType()
     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 @@ void SVGAnimateElementBase::resetAnimatedType()
 
     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 @@ void SVGAnimateElementBase::resetAnimatedType()
         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 @@ void SVGAnimateElementBase::clearAnimatedType(SVGElement* targetElement)
 
     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 @@ void SVGAnimateElementBase::applyResultsToTarget()
     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 @@ void SVGAnimateElementBase::resetAnimatedPropertyType()
     m_toType = nullptr;
     m_toAtEndOfDurationType = nullptr;
     m_animator = nullptr;
-    m_animatedPropertyType = targetElement() ? determineAnimatedPropertyType(targetElement()) : AnimatedString;
+    m_animatedPropertyType = targetElement() ? determineAnimatedPropertyType(*targetElement()) : AnimatedString;
 }
 
 SVGAnimatedTypeAnimator* SVGAnimateElementBase::ensureAnimator()
index e7211b3929f19608e52cebe90da95e27b5228d33..f2418a4a1f06fe845a326dc6352847fd6ec9c92d 100644 (file)
@@ -35,7 +35,7 @@ class SVGAnimateElementBase : public SVGAnimationElement {
 public:
     virtual ~SVGAnimateElementBase();
 
-    AnimatedPropertyType determineAnimatedPropertyType(SVGElement*) const;
+    AnimatedPropertyType determineAnimatedPropertyType(SVGElement&) const;
 
 protected:
     SVGAnimateElementBase(const QualifiedName&, Document&);
index 89e9221d6c286dcff2ba61c4615a5c86a2765637..d1cc6ecbf39d4793f22b9a1486f0becc47bb5ad3 100644 (file)
@@ -293,19 +293,17 @@ void SVGAnimateMotionElement::applyResultsToTarget()
     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);
         }
index e30e31a6287f0ccec171009499f3cbe2e6f7d779..6c4ebb48019741e3dbb50880492c383a93abd9af 100644 (file)
 
 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(AnimatedPropertyType type, SVGA
 }
 
 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 @@ void SVGAnimatedTypeAnimator::calculateFromAndByValues(std::unique_ptr<SVGAnimat
     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;
-
-        Vector<RefPtr<SVGAnimatedProperty>> instanceProperties;
-        targetElement->localAttributeToPropertyMap().animatedPropertiesForAttribute(shadowTreeElement, attributeName, instanceProperties);
-
-        SVGElementAnimatedProperties instancePropertiesPair(shadowTreeElement, instanceProperties);
-        propertiesByInstance.append(instancePropertiesPair);
-    }
+    for (SVGElement* instance : targetElement.instances())
+        result.append(SVGElementAnimatedProperties { instance, propertyMap.properties(*instance, attributeName) });
 
 #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 @@ SVGElementAnimatedPropertyList SVGAnimatedTypeAnimator::findAnimatedPropertiesFo
     }
 #endif
 
-    return propertiesByInstance;
+    return result;
 }
 
 } // namespace WebCore
index 6ad746bfba8ad1f77634b1e055e24bc7c157050f..c9336f8455f72ad2ec8bae762ac1aa2042519ef0 100644 (file)
 namespace WebCore {
 
 struct SVGElementAnimatedProperties {
-    SVGElementAnimatedProperties();
-
-    SVGElementAnimatedProperties(SVGElement*, Vector<RefPtr<SVGAnimatedProperty>>&);
-
     SVGElement* element;
     Vector<RefPtr<SVGAnimatedProperty>> properties;
 };
@@ -62,7 +58,7 @@ public:
     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*);
index 00bc0b9196bd837d437288b8141f1afa107aedfc..2c7f51f7800002b22549033f75d7968c9f07c5ae 100644 (file)
@@ -508,12 +508,9 @@ void SVGAnimationElement::currentValuesForValuesAnimation(float percent, float&
 
     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)
index d83905e7a59f27cbb6481342ae1693b7d9049dcc..a3256cf5bdaea8f0b530f4af75c01f4bd801d7ff 100644 (file)
@@ -281,11 +281,14 @@ SVGElement::SVGElement(const QualifiedName& tagName, Document& document)
 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 @@ SVGElement* SVGElement::viewportElement() const
     return nullptr;
 }
  
-void SVGElement::mapInstanceToElement(SVGElementInstance* instance)
-{
-    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
+const HashSet<SVGElement*>& SVGElement::instances() 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 @@ void SVGElement::cursorImageValueRemoved()
 
 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::parseAttribute(const QualifiedName& name, const AtomicString& v
     }
 }
 
-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 @@ bool SVGElement::addEventListener(const AtomicString& eventType, PassRefPtr<Even
 
     // 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 @@ bool SVGElement::removeEventListener(const AtomicString& eventType, EventListene
 
     // 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 @@ bool SVGElement::removeEventListener(const AtomicString& eventType, EventListene
         // 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 = shadowTreeElement->eventTargetData();
-        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 @@ void SVGElement::synchronizeAllAnimatedSVGAttribute(SVGElement* svgElement)
     ASSERT(svgElement->elementData());
     ASSERT(svgElement->elementData()->animatedSVGAttributesAreDirty());
 
-    svgElement->localAttributeToPropertyMap().synchronizeProperties(svgElement);
+    svgElement->localAttributeToPropertyMap().synchronizeProperties(*svgElement);
     svgElement->elementData()->setAnimatedSVGAttributesAreDirty(false);
 }
 
@@ -767,7 +769,7 @@ void SVGElement::synchronizeAnimatedSVGAttribute(const QualifiedName& name) cons
     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::isAnimatableCSSProperty(const QualifiedName& attributeName)
 
 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
index 3b2443a1f33723b84234f9873e9b9b88cfc1bc71..5c85ca7bd0e58e9a6175bcb3f311bf6a20cd9919 100644 (file)
@@ -49,6 +49,7 @@ class SVGDocumentExtensions;
 class SVGElementInstance;
 class SVGElementRareData;
 class SVGSVGElement;
+class SVGUseElement;
 
 void mapAttributeToCSSProperty(HashMap<AtomicStringImpl*, CSSPropertyID>* propertyNameToIdMap, const QualifiedName& attrName);
 
@@ -85,7 +86,7 @@ public:
 
     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 @@ public:
         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 @@ public:
     void cursorImageValueRemoved();
 
     SVGElement* correspondingElement();
+    SVGUseElement* correspondingUseElement() const;
+
     void setCorrespondingElement(SVGElement*);
 
     void synchronizeAnimatedSVGAttribute(const QualifiedName&) const;
@@ -189,9 +193,6 @@ private:
 
     virtual void clearTarget() { }
 
-    void mapInstanceToElement(SVGElementInstance*);
-    void removeInstanceMapping(SVGElementInstance*);
-
     void buildPendingResourcesIfNeeded();
     virtual void accessKeyAction(bool sendMouseEvents) override;
 
index 5a3a8e41144fab2863c7cf9441510d4fe0feacee..abdf58faf8b4aee04bb571edcb3ec435489c49fc 100644 (file)
@@ -101,9 +101,6 @@ SVGElementInstance::SVGElementInstance(SVGUseElement* correspondingUseElement, S
     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 @@ void SVGElementInstance::detach()
     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 JavaScriptCore uses it for garbage collection
 
     m_shadowTreeElement = 0;
@@ -181,24 +175,19 @@ void SVGElementInstance::invalidateAllInstancesOfElement(SVGElement* element)
     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();
 }
index 981481b97527ce1d3bd41a005349853c827c8b4b..1770edf2d819023f7eac7445c4d8b89e3129bbce 100644 (file)
@@ -31,23 +31,19 @@ namespace WebCore {
 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 @@ public:
         return *m_animatedSMILStyleProperties;
     }
 
-    void destroyAnimatedSMILStyleProperties()
-    {
-        m_animatedSMILStyleProperties.clear();
-    }
-
     RenderStyle* overrideComputedStyle(Element* element, RenderStyle* parentStyle)
     {
         ASSERT(element);
@@ -93,10 +84,10 @@ public:
     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;
index 3251141ae98dc45d2eedacaf2a8bf2019926c5aa..eb33cde190804ceab1783e6a8d62a8bed03d70d3 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
  * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
+ * 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
 
 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 @@ bool SVGTests::isValid() const
         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()
index 5d178a51ac074bf027df10ea1a8c0d64849a1b18..8ff60e5a768715ab552706768fe72cd7f33d4efd 100644 (file)
@@ -26,8 +26,6 @@
 
 namespace WebCore {
 
-class Attribute;
-class QualifiedName;
 class SVGElement;
 
 class SVGTests {
@@ -36,16 +34,16 @@ public:
     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 @@ protected:
     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;
 };
 
index 3c13ea9e0a3a6e689fd4ef06794d76feab23fb3e..72929b9d11f4a218312c827e1d0ab7a6fa678c5e 100644 (file)
@@ -776,10 +776,8 @@ void SVGUseElement::invalidateShadowTree()
 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();
         }
index 4845a2063e13490dd637d2b4fac2d6cba17766c7..bd2b00f0d8af784c26707be3b5f5c345bda4ee34 100644 (file)
@@ -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 @@ struct SVGSynchronizableAnimatedProperty {
 #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)
index 7c4fc1b751f61540a436a93aea6d952052bb918f..9629e58ca27e14ce67d1927ade9351f0e1894989 100644 (file)
@@ -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
 #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);
-}
-
 }
index 379fb974b958e22511ff78236f5793f3fe6dafbd..06b0c73402e3459c415ba490b660e3a22c5333e4 100644 (file)
@@ -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 @@ class SVGAttributeToPropertyMap {
 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;
 };
 
 }