<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[179260] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/179260">179260</a></dd>
<dt>Author</dt> <dd>darin@apple.com</dd>
<dt>Date</dt> <dd>2015-01-28 09:59:50 -0800 (Wed, 28 Jan 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>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&amp;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.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorepageEventHandlercpp">trunk/Source/WebCore/page/EventHandler.cpp</a></li>
<li><a href="#trunkSourceWebCorepageEventHandlerh">trunk/Source/WebCore/page/EventHandler.h</a></li>
<li><a href="#trunkSourceWebCoresvgSVGAnimateElementBasecpp">trunk/Source/WebCore/svg/SVGAnimateElementBase.cpp</a></li>
<li><a href="#trunkSourceWebCoresvgSVGAnimateElementBaseh">trunk/Source/WebCore/svg/SVGAnimateElementBase.h</a></li>
<li><a href="#trunkSourceWebCoresvgSVGAnimateMotionElementcpp">trunk/Source/WebCore/svg/SVGAnimateMotionElement.cpp</a></li>
<li><a href="#trunkSourceWebCoresvgSVGAnimatedTypeAnimatorcpp">trunk/Source/WebCore/svg/SVGAnimatedTypeAnimator.cpp</a></li>
<li><a href="#trunkSourceWebCoresvgSVGAnimatedTypeAnimatorh">trunk/Source/WebCore/svg/SVGAnimatedTypeAnimator.h</a></li>
<li><a href="#trunkSourceWebCoresvgSVGAnimationElementcpp">trunk/Source/WebCore/svg/SVGAnimationElement.cpp</a></li>
<li><a href="#trunkSourceWebCoresvgSVGElementcpp">trunk/Source/WebCore/svg/SVGElement.cpp</a></li>
<li><a href="#trunkSourceWebCoresvgSVGElementh">trunk/Source/WebCore/svg/SVGElement.h</a></li>
<li><a href="#trunkSourceWebCoresvgSVGElementInstancecpp">trunk/Source/WebCore/svg/SVGElementInstance.cpp</a></li>
<li><a href="#trunkSourceWebCoresvgSVGElementRareDatah">trunk/Source/WebCore/svg/SVGElementRareData.h</a></li>
<li><a href="#trunkSourceWebCoresvgSVGTestscpp">trunk/Source/WebCore/svg/SVGTests.cpp</a></li>
<li><a href="#trunkSourceWebCoresvgSVGTestsh">trunk/Source/WebCore/svg/SVGTests.h</a></li>
<li><a href="#trunkSourceWebCoresvgSVGUseElementcpp">trunk/Source/WebCore/svg/SVGUseElement.cpp</a></li>
<li><a href="#trunkSourceWebCoresvgpropertiesSVGAnimatedPropertyMacrosh">trunk/Source/WebCore/svg/properties/SVGAnimatedPropertyMacros.h</a></li>
<li><a href="#trunkSourceWebCoresvgpropertiesSVGAttributeToPropertyMapcpp">trunk/Source/WebCore/svg/properties/SVGAttributeToPropertyMap.cpp</a></li>
<li><a href="#trunkSourceWebCoresvgpropertiesSVGAttributeToPropertyMaph">trunk/Source/WebCore/svg/properties/SVGAttributeToPropertyMap.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,5 +1,167 @@
</span><span class="cx"> 2015-01-28  Darin Adler  &lt;darin@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        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&amp;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  &lt;darin@apple.com&gt;
+
</ins><span class="cx">         REGRESSION (r173698): Leaks of selector lists in CSS parsing
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=140993
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorepageEventHandlercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/EventHandler.cpp (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -459,7 +459,6 @@
</span><span class="cx">     m_resizeLayer = nullptr;
</span><span class="cx">     m_elementUnderMouse = nullptr;
</span><span class="cx">     m_lastElementUnderMouse = nullptr;
</span><del>-    m_lastInstanceUnderMouse = nullptr;
</del><span class="cx">     m_lastMouseMoveEventSubframe = nullptr;
</span><span class="cx">     m_lastScrollbarUnderMouse = nullptr;
</span><span class="cx">     m_clickCount = 0;
</span><span class="lines">@@ -2352,22 +2351,6 @@
</span><span class="cx">     return m_frame.document()-&gt;prepareMouseEvent(request, documentPointForWindowPoint(m_frame, mouseEvent.position()), mouseEvent);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline SVGElementInstance* instanceAssociatedWithShadowTreeElement(Node* referenceNode)
-{
-    if (!referenceNode || !referenceNode-&gt;isSVGElement())
-        return nullptr;
-
-    ShadowRoot* shadowRoot = referenceNode-&gt;containingShadowRoot();
-    if (!shadowRoot)
-        return nullptr;
-
-    Element* shadowTreeParentElement = shadowRoot-&gt;hostElement();
-    if (!shadowTreeParentElement || !shadowTreeParentElement-&gt;hasTagName(useTag))
-        return nullptr;
-
-    return downcast&lt;SVGUseElement&gt;(*shadowTreeParentElement).instanceForShadowTreeElement(referenceNode);
-}
-
</del><span class="cx"> static RenderElement* nearestCommonHoverAncestor(RenderElement* obj1, RenderElement* obj2)
</span><span class="cx"> {
</span><span class="cx">     if (!obj1 || !obj2)
</span><span class="lines">@@ -2409,37 +2392,6 @@
</span><span class="cx"> 
</span><span class="cx">     m_elementUnderMouse = targetElement;
</span><span class="cx"> 
</span><del>-    // &lt;use&gt; shadow tree elements may have been recloned, update node under mouse in any case
-    if (m_lastInstanceUnderMouse) {
-        SVGElement* lastCorrespondingElement = m_lastInstanceUnderMouse-&gt;correspondingElement();
-        SVGElement* lastCorrespondingUseElement = m_lastInstanceUnderMouse-&gt;correspondingUseElement();
-
-        if (lastCorrespondingElement &amp;&amp; lastCorrespondingUseElement) {
-            HashSet&lt;SVGElementInstance*&gt; instances = lastCorrespondingElement-&gt;instancesForElement();
-
-            // Locate the recloned shadow tree element for our corresponding instance
-            HashSet&lt;SVGElementInstance*&gt;::iterator end = instances.end();
-            for (HashSet&lt;SVGElementInstance*&gt;::iterator it = instances.begin(); it != end; ++it) {
-                SVGElementInstance* instance = (*it);
-                ASSERT(instance-&gt;correspondingElement() == lastCorrespondingElement);
-
-                if (instance == m_lastInstanceUnderMouse)
-                    continue;
-
-                if (instance-&gt;correspondingUseElement() != lastCorrespondingUseElement)
-                    continue;
-
-                SVGElement* shadowTreeElement = instance-&gt;shadowTreeElement();
-                if (!shadowTreeElement-&gt;inDocument() || m_lastElementUnderMouse == shadowTreeElement)
-                    continue;
-
-                m_lastElementUnderMouse = shadowTreeElement;
-                m_lastInstanceUnderMouse = instance;
-                break;
-            }
-        }
-    }
-
</del><span class="cx">     // Fire mouseout/mouseover if the mouse has shifted to a different node.
</span><span class="cx">     if (fireMouseOverOut) {
</span><span class="cx">         RenderLayer* layerForLastNode = layerForNode(m_lastElementUnderMouse.get());
</span><span class="lines">@@ -2481,7 +2433,6 @@
</span><span class="cx">         if (m_lastElementUnderMouse &amp;&amp; &amp;m_lastElementUnderMouse-&gt;document() != m_frame.document()) {
</span><span class="cx">             m_lastElementUnderMouse = nullptr;
</span><span class="cx">             m_lastScrollbarUnderMouse = nullptr;
</span><del>-            m_lastInstanceUnderMouse = nullptr;
</del><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (m_lastElementUnderMouse != m_elementUnderMouse) {
</span><span class="lines">@@ -2539,7 +2490,6 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">         m_lastElementUnderMouse = m_elementUnderMouse;
</span><del>-        m_lastInstanceUnderMouse = instanceAssociatedWithShadowTreeElement(m_elementUnderMouse.get());
</del><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorepageEventHandlerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/EventHandler.h (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -92,7 +92,6 @@
</span><span class="cx"> class RenderLayer;
</span><span class="cx"> class RenderWidget;
</span><span class="cx"> class ScrollableArea;
</span><del>-class SVGElementInstance;
</del><span class="cx"> class Scrollbar;
</span><span class="cx"> class TextEvent;
</span><span class="cx"> class Touch;
</span><span class="lines">@@ -488,7 +487,6 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     bool m_svgPan;
</span><del>-    RefPtr&lt;SVGElementInstance&gt; m_lastInstanceUnderMouse;
</del><span class="cx"> 
</span><span class="cx">     RenderLayer* m_resizeLayer;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGAnimateElementBasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGAnimateElementBase.cpp (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -55,12 +55,9 @@
</span><span class="cx">     return m_animatedPropertyType != AnimatedUnknown &amp;&amp; !hasInvalidCSSAttributeType();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-AnimatedPropertyType SVGAnimateElementBase::determineAnimatedPropertyType(SVGElement* targetElement) const
</del><ins>+AnimatedPropertyType SVGAnimateElementBase::determineAnimatedPropertyType(SVGElement&amp; targetElement) const
</ins><span class="cx"> {
</span><del>-    ASSERT(targetElement);
-
-    Vector&lt;AnimatedPropertyType&gt; propertyTypes;
-    targetElement-&gt;animatedPropertyTypeForAttribute(attributeName(), propertyTypes);
</del><ins>+    auto propertyTypes = targetElement.animatedPropertyTypesForAttribute(attributeName());
</ins><span class="cx">     if (propertyTypes.isEmpty())
</span><span class="cx">         return AnimatedUnknown;
</span><span class="cx"> 
</span><span class="lines">@@ -77,7 +74,7 @@
</span><span class="cx">     // Fortunately there's just one special case needed here: SVGMarkerElements orientAttr, which
</span><span class="cx">     // corresponds to SVGAnimatedAngle orientAngle and SVGAnimatedEnumeration orientType. We have to
</span><span class="cx">     // figure out whose value to change here.
</span><del>-    if (targetElement-&gt;hasTagName(SVGNames::markerTag) &amp;&amp; type == AnimatedAngle) {
</del><ins>+    if (targetElement.hasTagName(SVGNames::markerTag) &amp;&amp; type == AnimatedAngle) {
</ins><span class="cx">         ASSERT(propertyTypes.size() == 2);
</span><span class="cx">         ASSERT(propertyTypes[0] == AnimatedAngle);
</span><span class="cx">         ASSERT(propertyTypes[1] == AnimatedEnumeration);
</span><span class="lines">@@ -94,7 +91,7 @@
</span><span class="cx">     if (!targetElement)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    ASSERT(m_animatedPropertyType == determineAnimatedPropertyType(targetElement));
</del><ins>+    ASSERT(m_animatedPropertyType == determineAnimatedPropertyType(*targetElement));
</ins><span class="cx"> 
</span><span class="cx">     ASSERT(percentage &gt;= 0 &amp;&amp; percentage &lt;= 1);
</span><span class="cx">     ASSERT(m_animatedPropertyType != AnimatedTransformList || hasTagName(SVGNames::animateTransformTag));
</span><span class="lines">@@ -196,6 +193,9 @@
</span><span class="cx">     ASSERT(m_animatedPropertyType == animator-&gt;type());
</span><span class="cx"> 
</span><span class="cx">     SVGElement* targetElement = this-&gt;targetElement();
</span><ins>+    if (!targetElement)
+        return;
+
</ins><span class="cx">     const QualifiedName&amp; attributeName = this-&gt;attributeName();
</span><span class="cx">     ShouldApplyAnimation shouldApply = shouldApplyAnimation(targetElement, attributeName);
</span><span class="cx"> 
</span><span class="lines">@@ -204,7 +204,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (shouldApply == ApplyXMLAnimation || shouldApply == ApplyXMLandCSSAnimation) {
</span><span class="cx">         // SVG DOM animVal animation code-path.
</span><del>-        m_animatedProperties = animator-&gt;findAnimatedPropertiesForAttributeName(targetElement, attributeName);
</del><ins>+        m_animatedProperties = animator-&gt;findAnimatedPropertiesForAttributeName(*targetElement, attributeName);
</ins><span class="cx">         if (m_animatedProperties.isEmpty())
</span><span class="cx">             return;
</span><span class="cx"> 
</span><span class="lines">@@ -233,85 +233,72 @@
</span><span class="cx">         m_animatedType-&gt;setValueAsString(attributeName, baseValue);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline void applyCSSPropertyToTarget(SVGElement* targetElement, CSSPropertyID id, const String&amp; value)
</del><ins>+static inline void applyCSSPropertyToTarget(SVGElement&amp; targetElement, CSSPropertyID id, const String&amp; value)
</ins><span class="cx"> {
</span><del>-    ASSERT(!targetElement-&gt;m_deletionHasBegun);
</del><ins>+    ASSERT(!targetElement.m_deletionHasBegun);
</ins><span class="cx"> 
</span><del>-    if (!targetElement-&gt;ensureAnimatedSMILStyleProperties().setProperty(id, value, false, 0))
</del><ins>+    if (!targetElement.ensureAnimatedSMILStyleProperties().setProperty(id, value, false, 0))
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    targetElement-&gt;setNeedsStyleRecalc(SyntheticStyleChange);
</del><ins>+    targetElement.setNeedsStyleRecalc(SyntheticStyleChange);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline void removeCSSPropertyFromTarget(SVGElement* targetElement, CSSPropertyID id)
</del><ins>+static inline void removeCSSPropertyFromTarget(SVGElement&amp; targetElement, CSSPropertyID id)
</ins><span class="cx"> {
</span><del>-    ASSERT(!targetElement-&gt;m_deletionHasBegun);
-    targetElement-&gt;ensureAnimatedSMILStyleProperties().removeProperty(id);
-    targetElement-&gt;setNeedsStyleRecalc(SyntheticStyleChange);
</del><ins>+    ASSERT(!targetElement.m_deletionHasBegun);
+    targetElement.ensureAnimatedSMILStyleProperties().removeProperty(id);
+    targetElement.setNeedsStyleRecalc(SyntheticStyleChange);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline void applyCSSPropertyToTargetAndInstances(SVGElement* targetElement, const QualifiedName&amp; attributeName, const String&amp; valueAsString)
</del><ins>+static inline void applyCSSPropertyToTargetAndInstances(SVGElement&amp; targetElement, const QualifiedName&amp; attributeName, const String&amp; valueAsString)
</ins><span class="cx"> {
</span><del>-    ASSERT(targetElement);
-    if (attributeName == anyQName() || !targetElement-&gt;inDocument() || !targetElement-&gt;parentNode())
</del><ins>+    // FIXME: Do we really need to check both inDocument and !parentNode?
+    if (attributeName == anyQName() || !targetElement.inDocument() || !targetElement.parentNode())
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     CSSPropertyID id = cssPropertyID(attributeName.localName());
</span><span class="cx"> 
</span><del>-    SVGElementInstance::InstanceUpdateBlocker blocker(targetElement);
</del><ins>+    SVGElementInstance::InstanceUpdateBlocker blocker(&amp;targetElement);
</ins><span class="cx">     applyCSSPropertyToTarget(targetElement, id, valueAsString);
</span><span class="cx"> 
</span><span class="cx">     // If the target element has instances, update them as well, w/o requiring the &lt;use&gt; tree to be rebuilt.
</span><del>-    const HashSet&lt;SVGElementInstance*&gt;&amp; instances = targetElement-&gt;instancesForElement();
-    const HashSet&lt;SVGElementInstance*&gt;::const_iterator end = instances.end();
-    for (HashSet&lt;SVGElementInstance*&gt;::const_iterator it = instances.begin(); it != end; ++it) {
-        if (SVGElement* shadowTreeElement = (*it)-&gt;shadowTreeElement())
-            applyCSSPropertyToTarget(shadowTreeElement, id, valueAsString);
-    }
</del><ins>+    for (auto* instance : targetElement.instances())
+        applyCSSPropertyToTarget(*instance, id, valueAsString);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline void removeCSSPropertyFromTargetAndInstances(SVGElement* targetElement, const QualifiedName&amp; attributeName)
</del><ins>+static inline void removeCSSPropertyFromTargetAndInstances(SVGElement&amp; targetElement, const QualifiedName&amp; attributeName)
</ins><span class="cx"> {
</span><del>-    ASSERT(targetElement);
-    if (attributeName == anyQName() || !targetElement-&gt;inDocument() || !targetElement-&gt;parentNode())
</del><ins>+    // FIXME: Do we really need to check both inDocument and !parentNode?
+    if (attributeName == anyQName() || !targetElement.inDocument() || !targetElement.parentNode())
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     CSSPropertyID id = cssPropertyID(attributeName.localName());
</span><span class="cx"> 
</span><del>-    SVGElementInstance::InstanceUpdateBlocker blocker(targetElement);
</del><ins>+    SVGElementInstance::InstanceUpdateBlocker blocker(&amp;targetElement);
</ins><span class="cx">     removeCSSPropertyFromTarget(targetElement, id);
</span><span class="cx"> 
</span><span class="cx">     // If the target element has instances, update them as well, w/o requiring the &lt;use&gt; tree to be rebuilt.
</span><del>-    const HashSet&lt;SVGElementInstance*&gt;&amp; instances = targetElement-&gt;instancesForElement();
-    const HashSet&lt;SVGElementInstance*&gt;::const_iterator end = instances.end();
-    for (HashSet&lt;SVGElementInstance*&gt;::const_iterator it = instances.begin(); it != end; ++it) {
-        if (SVGElement* shadowTreeElement = (*it)-&gt;shadowTreeElement())
-            removeCSSPropertyFromTarget(shadowTreeElement, id);
-    }
</del><ins>+    for (auto* instance : targetElement.instances())
+        removeCSSPropertyFromTarget(*instance, id);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline void notifyTargetAboutAnimValChange(SVGElement* targetElement, const QualifiedName&amp; attributeName)
</del><ins>+static inline void notifyTargetAboutAnimValChange(SVGElement&amp; targetElement, const QualifiedName&amp; attributeName)
</ins><span class="cx"> {
</span><del>-    ASSERT(!targetElement-&gt;m_deletionHasBegun);
-    targetElement-&gt;svgAttributeChanged(attributeName);
</del><ins>+    ASSERT(!targetElement.m_deletionHasBegun);
+    targetElement.svgAttributeChanged(attributeName);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline void notifyTargetAndInstancesAboutAnimValChange(SVGElement* targetElement, const QualifiedName&amp; attributeName)
</del><ins>+static inline void notifyTargetAndInstancesAboutAnimValChange(SVGElement&amp; targetElement, const QualifiedName&amp; attributeName)
</ins><span class="cx"> {
</span><del>-    ASSERT(targetElement);
-    if (attributeName == anyQName() || !targetElement-&gt;inDocument() || !targetElement-&gt;parentNode())
</del><ins>+    if (attributeName == anyQName() || !targetElement.inDocument() || !targetElement.parentNode())
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    SVGElementInstance::InstanceUpdateBlocker blocker(targetElement);
</del><ins>+    SVGElementInstance::InstanceUpdateBlocker blocker(&amp;targetElement);
</ins><span class="cx">     notifyTargetAboutAnimValChange(targetElement, attributeName);
</span><span class="cx"> 
</span><span class="cx">     // If the target element has instances, update them as well, w/o requiring the &lt;use&gt; tree to be rebuilt.
</span><del>-    const HashSet&lt;SVGElementInstance*&gt;&amp; instances = targetElement-&gt;instancesForElement();
-    const HashSet&lt;SVGElementInstance*&gt;::const_iterator end = instances.end();
-    for (HashSet&lt;SVGElementInstance*&gt;::const_iterator it = instances.begin(); it != end; ++it) {
-        if (SVGElement* shadowTreeElement = (*it)-&gt;shadowTreeElement())
-            notifyTargetAboutAnimValChange(shadowTreeElement, attributeName);
-    }
</del><ins>+    for (auto* instance : targetElement.instances())
+        notifyTargetAboutAnimValChange(*instance, attributeName);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SVGAnimateElementBase::clearAnimatedType(SVGElement* targetElement)
</span><span class="lines">@@ -326,19 +313,19 @@
</span><span class="cx"> 
</span><span class="cx">     if (m_animatedProperties.isEmpty()) {
</span><span class="cx">         // CSS properties animation code-path.
</span><del>-        removeCSSPropertyFromTargetAndInstances(targetElement, attributeName());
</del><ins>+        removeCSSPropertyFromTargetAndInstances(*targetElement, attributeName());
</ins><span class="cx">         m_animatedType = nullptr;
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ShouldApplyAnimation shouldApply = shouldApplyAnimation(targetElement, attributeName());
</span><span class="cx">     if (shouldApply == ApplyXMLandCSSAnimation)
</span><del>-        removeCSSPropertyFromTargetAndInstances(targetElement, attributeName());
</del><ins>+        removeCSSPropertyFromTargetAndInstances(*targetElement, attributeName());
</ins><span class="cx"> 
</span><span class="cx">     // SVG DOM animVal animation code-path.
</span><span class="cx">     if (m_animator) {
</span><span class="cx">         m_animator-&gt;stopAnimValAnimation(m_animatedProperties);
</span><del>-        notifyTargetAndInstancesAboutAnimValChange(targetElement, attributeName());
</del><ins>+        notifyTargetAndInstancesAboutAnimValChange(*targetElement, attributeName());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_animatedProperties.clear();
</span><span class="lines">@@ -351,29 +338,32 @@
</span><span class="cx">     ASSERT(m_animatedPropertyType != AnimatedUnknown);
</span><span class="cx">     ASSERT(m_animator);
</span><span class="cx"> 
</span><del>-    // Early exit if our animated type got destructed by a previous endedActiveInterval().
</del><ins>+    // Early exit if our animated type got destroyed by a previous endedActiveInterval().
</ins><span class="cx">     if (!m_animatedType)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     SVGElement* targetElement = this-&gt;targetElement();
</span><span class="cx">     const QualifiedName&amp; attributeName = this-&gt;attributeName();
</span><ins>+
+    ASSERT(targetElement);
+
</ins><span class="cx">     if (m_animatedProperties.isEmpty()) {
</span><span class="cx">         // CSS properties animation code-path.
</span><span class="cx">         // Convert the result of the animation to a String and apply it as CSS property on the target &amp; all instances.
</span><del>-        applyCSSPropertyToTargetAndInstances(targetElement, attributeName, m_animatedType-&gt;valueAsString());
</del><ins>+        applyCSSPropertyToTargetAndInstances(*targetElement, attributeName, m_animatedType-&gt;valueAsString());
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // We do update the style and the animation property independent of each other.
</span><span class="cx">     ShouldApplyAnimation shouldApply = shouldApplyAnimation(targetElement, attributeName);
</span><span class="cx">     if (shouldApply == ApplyXMLandCSSAnimation)
</span><del>-        applyCSSPropertyToTargetAndInstances(targetElement, attributeName, m_animatedType-&gt;valueAsString());
</del><ins>+        applyCSSPropertyToTargetAndInstances(*targetElement, attributeName, m_animatedType-&gt;valueAsString());
</ins><span class="cx"> 
</span><span class="cx">     // SVG DOM animVal animation code-path.
</span><span class="cx">     // At this point the SVG DOM values are already changed, unlike for CSS.
</span><span class="cx">     // We only have to trigger update notifications here.
</span><span class="cx">     m_animator-&gt;animValDidChange(m_animatedProperties);
</span><del>-    notifyTargetAndInstancesAboutAnimValChange(targetElement, attributeName);
</del><ins>+    notifyTargetAndInstancesAboutAnimValChange(*targetElement, attributeName);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool SVGAnimateElementBase::animatedPropertyTypeSupportsAddition() const
</span><span class="lines">@@ -445,7 +435,7 @@
</span><span class="cx">     m_toType = nullptr;
</span><span class="cx">     m_toAtEndOfDurationType = nullptr;
</span><span class="cx">     m_animator = nullptr;
</span><del>-    m_animatedPropertyType = targetElement() ? determineAnimatedPropertyType(targetElement()) : AnimatedString;
</del><ins>+    m_animatedPropertyType = targetElement() ? determineAnimatedPropertyType(*targetElement()) : AnimatedString;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> SVGAnimatedTypeAnimator* SVGAnimateElementBase::ensureAnimator()
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGAnimateElementBaseh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGAnimateElementBase.h (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -35,7 +35,7 @@
</span><span class="cx"> public:
</span><span class="cx">     virtual ~SVGAnimateElementBase();
</span><span class="cx"> 
</span><del>-    AnimatedPropertyType determineAnimatedPropertyType(SVGElement*) const;
</del><ins>+    AnimatedPropertyType determineAnimatedPropertyType(SVGElement&amp;) const;
</ins><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="cx">     SVGAnimateElementBase(const QualifiedName&amp;, Document&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGAnimateMotionElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGAnimateMotionElement.cpp (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -293,19 +293,17 @@
</span><span class="cx">     if (RenderElement* renderer = targetElement-&gt;renderer())
</span><span class="cx">         RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer);
</span><span class="cx"> 
</span><del>-    AffineTransform* t = targetElement-&gt;supplementalTransform();
-    if (!t)
</del><ins>+    AffineTransform* targetSupplementalTransform = targetElement-&gt;supplementalTransform();
+    if (!targetSupplementalTransform)
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     // ...except in case where we have additional instances in &lt;use&gt; trees.
</span><del>-    for (auto* instance : targetElement-&gt;instancesForElement()) {
-        SVGElement* shadowTreeElement = instance-&gt;shadowTreeElement();
-        ASSERT(shadowTreeElement);
-        AffineTransform* transform = shadowTreeElement-&gt;supplementalTransform();
-        if (!transform)
</del><ins>+    for (auto* instance : targetElement-&gt;instances()) {
+        AffineTransform* transform = instance-&gt;supplementalTransform();
+        if (!transform || *transform == *targetSupplementalTransform)
</ins><span class="cx">             continue;
</span><del>-        transform-&gt;setMatrix(t-&gt;a(), t-&gt;b(), t-&gt;c(), t-&gt;d(), t-&gt;e(), t-&gt;f());
-        if (RenderElement* renderer = shadowTreeElement-&gt;renderer()) {
</del><ins>+        *transform = *targetSupplementalTransform;
+        if (RenderElement* renderer = instance-&gt;renderer()) {
</ins><span class="cx">             renderer-&gt;setNeedsTransformUpdate();
</span><span class="cx">             RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer);
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGAnimatedTypeAnimatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGAnimatedTypeAnimator.cpp (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -27,15 +27,6 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-SVGElementAnimatedProperties::SVGElementAnimatedProperties()
-    : element(0)
-{ }
-
-SVGElementAnimatedProperties::SVGElementAnimatedProperties(SVGElement* element, Vector&lt;RefPtr&lt;SVGAnimatedProperty&gt;&gt;&amp; properties)
-    : element(element)
-    , properties(properties)
-{ }
-
</del><span class="cx"> SVGAnimatedTypeAnimator::SVGAnimatedTypeAnimator(AnimatedPropertyType type, SVGAnimationElement* animationElement, SVGElement* contextElement)
</span><span class="cx">     : m_type(type)
</span><span class="cx">     , m_animationElement(animationElement)
</span><span class="lines">@@ -44,7 +35,8 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> SVGAnimatedTypeAnimator::~SVGAnimatedTypeAnimator()
</span><del>-{ }
</del><ins>+{
+}
</ins><span class="cx"> 
</span><span class="cx"> void SVGAnimatedTypeAnimator::calculateFromAndToValues(std::unique_ptr&lt;SVGAnimatedType&gt;&amp; from, std::unique_ptr&lt;SVGAnimatedType&gt;&amp; to, const String&amp; fromString, const String&amp; toString)
</span><span class="cx"> {
</span><span class="lines">@@ -59,41 +51,27 @@
</span><span class="cx">     addAnimatedTypes(from.get(), to.get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-SVGElementAnimatedPropertyList SVGAnimatedTypeAnimator::findAnimatedPropertiesForAttributeName(SVGElement* targetElement, const QualifiedName&amp; attributeName)
</del><ins>+SVGElementAnimatedPropertyList SVGAnimatedTypeAnimator::findAnimatedPropertiesForAttributeName(SVGElement&amp; targetElement, const QualifiedName&amp; attributeName)
</ins><span class="cx"> {
</span><del>-    ASSERT(targetElement);
</del><ins>+    SVGElementAnimatedPropertyList result;
</ins><span class="cx"> 
</span><del>-    SVGElementAnimatedPropertyList propertiesByInstance;
</del><ins>+    if (!SVGAnimatedType::supportsAnimVal(m_type))
+        return result;
</ins><span class="cx"> 
</span><del>-    Vector&lt;RefPtr&lt;SVGAnimatedProperty&gt;&gt; targetProperties;
-    targetElement-&gt;localAttributeToPropertyMap().animatedPropertiesForAttribute(targetElement, attributeName, targetProperties);
</del><ins>+    auto&amp; propertyMap = targetElement.localAttributeToPropertyMap();
+    auto targetProperties = propertyMap.properties(targetElement, attributeName);
</ins><span class="cx"> 
</span><del>-    if (!SVGAnimatedType::supportsAnimVal(m_type) || targetProperties.isEmpty())
-        return SVGElementAnimatedPropertyList();
</del><ins>+    if (targetProperties.isEmpty())
+        return result;
</ins><span class="cx"> 
</span><del>-    SVGElementAnimatedProperties propertiesPair(targetElement, targetProperties);
-    propertiesByInstance.append(propertiesPair);
</del><ins>+    result.append(SVGElementAnimatedProperties { &amp;targetElement, WTF::move(targetProperties) });
</ins><span class="cx"> 
</span><del>-    const HashSet&lt;SVGElementInstance*&gt;&amp; instances = targetElement-&gt;instancesForElement();
-    const HashSet&lt;SVGElementInstance*&gt;::const_iterator end = instances.end();
-    for (HashSet&lt;SVGElementInstance*&gt;::const_iterator it = instances.begin(); it != end; ++it) {
-        SVGElement* shadowTreeElement = (*it)-&gt;shadowTreeElement();
-        if (!shadowTreeElement)
-            continue;
</del><ins>+    for (SVGElement* instance : targetElement.instances())
+        result.append(SVGElementAnimatedProperties { instance, propertyMap.properties(*instance, attributeName) });
</ins><span class="cx"> 
</span><del>-        Vector&lt;RefPtr&lt;SVGAnimatedProperty&gt;&gt; instanceProperties;
-        targetElement-&gt;localAttributeToPropertyMap().animatedPropertiesForAttribute(shadowTreeElement, attributeName, instanceProperties);
-
-        SVGElementAnimatedProperties instancePropertiesPair(shadowTreeElement, instanceProperties);
-        propertiesByInstance.append(instancePropertiesPair);
-    }
-
</del><span class="cx"> #if !ASSERT_DISABLED
</span><del>-    SVGElementAnimatedPropertyList::const_iterator propertiesEnd = propertiesByInstance.end();
-    for (SVGElementAnimatedPropertyList::const_iterator it = propertiesByInstance.begin(); it != propertiesEnd; ++it) {
-        size_t propertiesSize = it-&gt;properties.size();
-        for (size_t i = 0; i &lt; propertiesSize; ++i) {
-            RefPtr&lt;SVGAnimatedProperty&gt; property = it-&gt;properties[i];
</del><ins>+    for (auto&amp; animatedProperties : result) {
+        for (auto&amp; property : animatedProperties.properties) {
</ins><span class="cx">             if (property-&gt;animatedPropertyType() != m_type) {
</span><span class="cx">                 ASSERT(m_type == AnimatedAngle);
</span><span class="cx">                 ASSERT(property-&gt;animatedPropertyType() == AnimatedEnumeration);
</span><span class="lines">@@ -102,7 +80,7 @@
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    return propertiesByInstance;
</del><ins>+    return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGAnimatedTypeAnimatorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGAnimatedTypeAnimator.h (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -29,10 +29,6 @@
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> struct SVGElementAnimatedProperties {
</span><del>-    SVGElementAnimatedProperties();
-
-    SVGElementAnimatedProperties(SVGElement*, Vector&lt;RefPtr&lt;SVGAnimatedProperty&gt;&gt;&amp;);
-
</del><span class="cx">     SVGElement* element;
</span><span class="cx">     Vector&lt;RefPtr&lt;SVGAnimatedProperty&gt;&gt; properties;
</span><span class="cx"> };
</span><span class="lines">@@ -62,7 +58,7 @@
</span><span class="cx">     void setContextElement(SVGElement* contextElement) { m_contextElement = contextElement; }
</span><span class="cx">     AnimatedPropertyType type() const { return m_type; }
</span><span class="cx"> 
</span><del>-    SVGElementAnimatedPropertyList findAnimatedPropertiesForAttributeName(SVGElement*, const QualifiedName&amp;);
</del><ins>+    SVGElementAnimatedPropertyList findAnimatedPropertiesForAttributeName(SVGElement&amp;, const QualifiedName&amp;);
</ins><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="cx">     SVGAnimatedTypeAnimator(AnimatedPropertyType, SVGAnimationElement*, SVGElement*);
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGAnimationElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGAnimationElement.cpp (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -508,12 +508,9 @@
</span><span class="cx"> 
</span><span class="cx">     CalcMode calcMode = this-&gt;calcMode();
</span><span class="cx">     if (is&lt;SVGAnimateElement&gt;(*this) || is&lt;SVGAnimateColorElement&gt;(*this)) {
</span><del>-        AnimatedPropertyType attributeType = downcast&lt;SVGAnimateElementBase&gt;(*this).determineAnimatedPropertyType(targetElement());
-        // Fall back to discrete animations for Strings.
-        if (attributeType == AnimatedBoolean
-            || attributeType == AnimatedEnumeration
-            || attributeType == AnimatedPreserveAspectRatio
-            || attributeType == AnimatedString)
</del><ins>+        ASSERT(targetElement());
+        AnimatedPropertyType type = downcast&lt;SVGAnimateElementBase&gt;(*this).determineAnimatedPropertyType(*targetElement());
+        if (type == AnimatedBoolean || type == AnimatedEnumeration || type == AnimatedPreserveAspectRatio || type == AnimatedString)
</ins><span class="cx">             calcMode = CalcModeDiscrete;
</span><span class="cx">     }
</span><span class="cx">     if (!m_keyPoints.isEmpty() &amp;&amp; calcMode != CalcModePaced)
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGElement.cpp (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -281,11 +281,14 @@
</span><span class="cx"> SVGElement::~SVGElement()
</span><span class="cx"> {
</span><span class="cx">     if (m_svgRareData) {
</span><del>-        m_svgRareData-&gt;destroyAnimatedSMILStyleProperties();
</del><ins>+        for (SVGElement* instance : m_svgRareData-&gt;instances())
+            instance-&gt;m_svgRareData-&gt;setCorrespondingElement(nullptr);
</ins><span class="cx">         if (SVGCursorElement* cursorElement = m_svgRareData-&gt;cursorElement())
</span><span class="cx">             cursorElement-&gt;removeClient(this);
</span><span class="cx">         if (CSSCursorImageValue* cursorImageValue = m_svgRareData-&gt;cursorImageValue())
</span><span class="cx">             cursorImageValue-&gt;removeReferencedElement(this);
</span><ins>+        if (SVGElement* correspondingElement = m_svgRareData-&gt;correspondingElement())
+            correspondingElement-&gt;m_svgRareData-&gt;instances().remove(this);
</ins><span class="cx"> 
</span><span class="cx">         m_svgRareData = nullptr;
</span><span class="cx">     }
</span><span class="lines">@@ -420,34 +423,13 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx">  
</span><del>-void SVGElement::mapInstanceToElement(SVGElementInstance* instance)
</del><ins>+const HashSet&lt;SVGElement*&gt;&amp; SVGElement::instances() const
</ins><span class="cx"> {
</span><del>-    ASSERT(instance);
-
-    HashSet&lt;SVGElementInstance*&gt;&amp; instances = ensureSVGRareData().elementInstances();
-    ASSERT(!instances.contains(instance));
-
-    instances.add(instance);
-}

-void SVGElement::removeInstanceMapping(SVGElementInstance* instance)
-{
-    ASSERT(instance);
-    ASSERT(m_svgRareData);
-
-    HashSet&lt;SVGElementInstance*&gt;&amp; instances = m_svgRareData-&gt;elementInstances();
-    ASSERT(instances.contains(instance));
-
-    instances.remove(instance);
-}
-
-const HashSet&lt;SVGElementInstance*&gt;&amp; SVGElement::instancesForElement() const
-{
</del><span class="cx">     if (!m_svgRareData) {
</span><del>-        static NeverDestroyed&lt;HashSet&lt;SVGElementInstance*&gt;&gt; emptyInstances;
</del><ins>+        static NeverDestroyed&lt;HashSet&lt;SVGElement*&gt;&gt; emptyInstances;
</ins><span class="cx">         return emptyInstances;
</span><span class="cx">     }
</span><del>-    return m_svgRareData-&gt;elementInstances();
</del><ins>+    return m_svgRareData-&gt;instances();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool SVGElement::getBoundingBox(FloatRect&amp; rect, SVGLocatable::StyleUpdateStrategy styleUpdateStrategy)
</span><span class="lines">@@ -495,13 +477,32 @@
</span><span class="cx"> 
</span><span class="cx"> SVGElement* SVGElement::correspondingElement()
</span><span class="cx"> {
</span><del>-    ASSERT(!m_svgRareData || !m_svgRareData-&gt;correspondingElement() || containingShadowRoot());
-    return m_svgRareData ? m_svgRareData-&gt;correspondingElement() : 0;
</del><ins>+    ASSERT(!m_svgRareData || !m_svgRareData-&gt;correspondingElement() || correspondingUseElement());
+    return m_svgRareData ? m_svgRareData-&gt;correspondingElement() : nullptr;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+SVGUseElement* SVGElement::correspondingUseElement() const
+{
+    auto* root = containingShadowRoot();
+    if (!root)
+        return nullptr;
+    if (root-&gt;type() != ShadowRoot::UserAgentShadowRoot)
+        return nullptr;
+    auto* host = root-&gt;hostElement();
+    if (!is&lt;SVGUseElement&gt;(host))
+        return nullptr;
+    return &amp;downcast&lt;SVGUseElement&gt;(*host);
+}
+
</ins><span class="cx"> void SVGElement::setCorrespondingElement(SVGElement* correspondingElement)
</span><span class="cx"> {
</span><ins>+    if (m_svgRareData) {
+        if (SVGElement* oldCorrespondingElement = m_svgRareData-&gt;correspondingElement())
+            oldCorrespondingElement-&gt;m_svgRareData-&gt;instances().remove(this);
+    }
</ins><span class="cx">     ensureSVGRareData().setCorrespondingElement(correspondingElement);
</span><ins>+    if (correspondingElement)
+        correspondingElement-&gt;ensureSVGRareData().instances().add(this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SVGElement::parseAttribute(const QualifiedName&amp; name, const AtomicString&amp; value)
</span><span class="lines">@@ -533,23 +534,31 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SVGElement::animatedPropertyTypeForAttribute(const QualifiedName&amp; attributeName, Vector&lt;AnimatedPropertyType&gt;&amp; propertyTypes)
</del><ins>+Vector&lt;AnimatedPropertyType&gt; SVGElement::animatedPropertyTypesForAttribute(const QualifiedName&amp; attributeName)
</ins><span class="cx"> {
</span><del>-    localAttributeToPropertyMap().animatedPropertyTypeForAttribute(attributeName, propertyTypes);
-    if (!propertyTypes.isEmpty())
-        return;
</del><ins>+    auto types = localAttributeToPropertyMap().types(attributeName);
+    if (!types.isEmpty())
+        return types;
</ins><span class="cx"> 
</span><del>-    auto&amp; map = attributeNameToAnimatedPropertyTypeMap();
-    auto it = map.find(attributeName.impl());
-    if (it != map.end()) {
-        propertyTypes.append(it-&gt;value);
-        return;
</del><ins>+    {
+        auto&amp; map = attributeNameToAnimatedPropertyTypeMap();
+        auto it = map.find(attributeName.impl());
+        if (it != map.end()) {
+            types.append(it-&gt;value);
+            return types;
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    auto&amp; cssPropertyWithSVGDOMMap = cssPropertyWithSVGDOMNameToAnimatedPropertyTypeMap();
-    auto svgPropertyIterator = cssPropertyWithSVGDOMMap.find(attributeName.impl());
-    if (svgPropertyIterator != cssPropertyWithSVGDOMMap.end())
-        propertyTypes.append(svgPropertyIterator-&gt;value);
</del><ins>+    {
+        auto&amp; map = cssPropertyWithSVGDOMNameToAnimatedPropertyTypeMap();
+        auto it = map.find(attributeName.impl());
+        if (it != map.end()) {
+            types.append(it-&gt;value);
+            return types;
+        }
+    }
+
+    return types;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool SVGElement::haveLoadedRequiredResources()
</span><span class="lines">@@ -574,11 +583,9 @@
</span><span class="cx"> 
</span><span class="cx">     // Add event listener to all shadow tree DOM element instances
</span><span class="cx">     ASSERT(!instanceUpdatesBlocked());
</span><del>-    for (auto&amp; instance : instancesForElement()) {
-        ASSERT(instance-&gt;shadowTreeElement());
</del><ins>+    for (auto* instance : instances()) {
</ins><span class="cx">         ASSERT(instance-&gt;correspondingElement() == this);
</span><del>-
-        bool result = instance-&gt;shadowTreeElement()-&gt;Node::addEventListener(eventType, listener, useCapture);
</del><ins>+        bool result = instance-&gt;Node::addEventListener(eventType, listener, useCapture);
</ins><span class="cx">         ASSERT_UNUSED(result, result);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -603,13 +610,10 @@
</span><span class="cx"> 
</span><span class="cx">     // Remove event listener from all shadow tree DOM element instances
</span><span class="cx">     ASSERT(!instanceUpdatesBlocked());
</span><del>-    for (auto&amp; instance : instancesForElement()) {
</del><ins>+    for (auto&amp; instance : instances()) {
</ins><span class="cx">         ASSERT(instance-&gt;correspondingElement() == this);
</span><span class="cx"> 
</span><del>-        SVGElement* shadowTreeElement = instance-&gt;shadowTreeElement();
-        ASSERT(shadowTreeElement);
-
-        if (shadowTreeElement-&gt;Node::removeEventListener(eventType, listener, useCapture))
</del><ins>+        if (instance-&gt;Node::removeEventListener(eventType, listener, useCapture))
</ins><span class="cx">             continue;
</span><span class="cx"> 
</span><span class="cx">         // This case can only be hit for event listeners created from markup
</span><span class="lines">@@ -620,11 +624,9 @@
</span><span class="cx">         // has been created (read: it's not 0 anymore). During shadow tree creation, the event
</span><span class="cx">         // listener DOM attribute has been cloned, and another event listener has been setup in
</span><span class="cx">         // the shadow tree. If that event listener has not been used yet, m_jsFunction is still 0,
</span><del>-        // and tryRemoveEventListener() above will fail. Work around that very seldom problem.
-        EventTargetData* data = shadowTreeElement-&gt;eventTargetData();
-        ASSERT(data);
-
-        data-&gt;eventListenerMap.removeFirstEventListenerCreatedFromMarkup(eventType);
</del><ins>+        // and tryRemoveEventListener() above will fail. Work around that very rare problem.
+        ASSERT(instance-&gt;eventTargetData());
+        instance-&gt;eventTargetData()-&gt;eventListenerMap.removeFirstEventListenerCreatedFromMarkup(eventType);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     return true;
</span><span class="lines">@@ -754,7 +756,7 @@
</span><span class="cx">     ASSERT(svgElement-&gt;elementData());
</span><span class="cx">     ASSERT(svgElement-&gt;elementData()-&gt;animatedSVGAttributesAreDirty());
</span><span class="cx"> 
</span><del>-    svgElement-&gt;localAttributeToPropertyMap().synchronizeProperties(svgElement);
</del><ins>+    svgElement-&gt;localAttributeToPropertyMap().synchronizeProperties(*svgElement);
</ins><span class="cx">     svgElement-&gt;elementData()-&gt;setAnimatedSVGAttributesAreDirty(false);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -767,7 +769,7 @@
</span><span class="cx">     if (name == anyQName())
</span><span class="cx">         synchronizeAllAnimatedSVGAttribute(nonConstThis);
</span><span class="cx">     else
</span><del>-        nonConstThis-&gt;localAttributeToPropertyMap().synchronizeProperty(nonConstThis, name);
</del><ins>+        nonConstThis-&gt;localAttributeToPropertyMap().synchronizeProperty(*nonConstThis, name);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SVGElement::synchronizeRequiredFeatures(SVGElement* contextElement)
</span><span class="lines">@@ -1016,9 +1018,7 @@
</span><span class="cx"> 
</span><span class="cx"> bool SVGElement::isPresentationAttributeWithSVGDOM(const QualifiedName&amp; attributeName)
</span><span class="cx"> {
</span><del>-    Vector&lt;AnimatedPropertyType&gt; propertyTypes;
-    localAttributeToPropertyMap().animatedPropertyTypeForAttribute(attributeName, propertyTypes);
-    return !propertyTypes.isEmpty();
</del><ins>+    return !localAttributeToPropertyMap().types(attributeName).isEmpty();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool SVGElement::isPresentationAttribute(const QualifiedName&amp; name) const
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGElement.h (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -49,6 +49,7 @@
</span><span class="cx"> class SVGElementInstance;
</span><span class="cx"> class SVGElementRareData;
</span><span class="cx"> class SVGSVGElement;
</span><ins>+class SVGUseElement;
</ins><span class="cx"> 
</span><span class="cx"> void mapAttributeToCSSProperty(HashMap&lt;AtomicStringImpl*, CSSPropertyID&gt;* propertyNameToIdMap, const QualifiedName&amp; attrName);
</span><span class="cx"> 
</span><span class="lines">@@ -85,7 +86,7 @@
</span><span class="cx"> 
</span><span class="cx">     virtual void svgAttributeChanged(const QualifiedName&amp;);
</span><span class="cx"> 
</span><del>-    void animatedPropertyTypeForAttribute(const QualifiedName&amp;, Vector&lt;AnimatedPropertyType&gt;&amp;);
</del><ins>+    Vector&lt;AnimatedPropertyType&gt; animatedPropertyTypesForAttribute(const QualifiedName&amp;);
</ins><span class="cx"> 
</span><span class="cx">     void sendSVGLoadEventIfPossible(bool sendParentLoadEvents = false);
</span><span class="cx">     void sendSVGLoadEventIfPossibleAsynchronously();
</span><span class="lines">@@ -102,7 +103,8 @@
</span><span class="cx">         setNeedsStyleRecalc(InlineStyleChange);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    const HashSet&lt;SVGElementInstance*&gt;&amp; instancesForElement() const;
</del><ins>+    // The instances of an element are clones made in shadow trees to implement &lt;use&gt;.
+    const HashSet&lt;SVGElement*&gt;&amp; instances() const;
</ins><span class="cx"> 
</span><span class="cx">     bool getBoundingBox(FloatRect&amp;, SVGLocatable::StyleUpdateStrategy = SVGLocatable::AllowStyleUpdate);
</span><span class="cx"> 
</span><span class="lines">@@ -112,6 +114,8 @@
</span><span class="cx">     void cursorImageValueRemoved();
</span><span class="cx"> 
</span><span class="cx">     SVGElement* correspondingElement();
</span><ins>+    SVGUseElement* correspondingUseElement() const;
+
</ins><span class="cx">     void setCorrespondingElement(SVGElement*);
</span><span class="cx"> 
</span><span class="cx">     void synchronizeAnimatedSVGAttribute(const QualifiedName&amp;) const;
</span><span class="lines">@@ -189,9 +193,6 @@
</span><span class="cx"> 
</span><span class="cx">     virtual void clearTarget() { }
</span><span class="cx"> 
</span><del>-    void mapInstanceToElement(SVGElementInstance*);
-    void removeInstanceMapping(SVGElementInstance*);
-
</del><span class="cx">     void buildPendingResourcesIfNeeded();
</span><span class="cx">     virtual void accessKeyAction(bool sendMouseEvents) override;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGElementInstancecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGElementInstance.cpp (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -101,9 +101,6 @@
</span><span class="cx">     ASSERT(m_correspondingUseElement);
</span><span class="cx">     ASSERT(m_element);
</span><span class="cx"> 
</span><del>-    // Register as instance for passed element.
-    m_element-&gt;mapInstanceToElement(this);
-
</del><span class="cx"> #ifndef NDEBUG
</span><span class="cx">     instanceCounter.increment();
</span><span class="cx"> #endif
</span><span class="lines">@@ -144,9 +141,6 @@
</span><span class="cx">     for (SVGElementInstance* node = firstChild(); node; node = node-&gt;nextSibling())
</span><span class="cx">         node-&gt;detach();
</span><span class="cx"> 
</span><del>-    // Deregister as instance for passed element, if we haven't already.
-    if (m_element-&gt;instancesForElement().contains(this))
-        m_element-&gt;removeInstanceMapping(this);
</del><span class="cx">     // DO NOT clear ref to m_element because JavaScriptCore uses it for garbage collection
</span><span class="cx"> 
</span><span class="cx">     m_shadowTreeElement = 0;
</span><span class="lines">@@ -181,24 +175,19 @@
</span><span class="cx">     if (element-&gt;instanceUpdatesBlocked())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    const HashSet&lt;SVGElementInstance*&gt;&amp; set = element-&gt;instancesForElement();
-    if (set.isEmpty())
</del><ins>+    auto&amp; instances = element-&gt;instances();
+    if (instances.isEmpty())
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     // Mark all use elements referencing 'element' for rebuilding
</span><del>-    const HashSet&lt;SVGElementInstance*&gt;::const_iterator end = set.end();
-    for (HashSet&lt;SVGElementInstance*&gt;::const_iterator it = set.begin(); it != end; ++it) {
-        ASSERT((*it)-&gt;shadowTreeElement());
-        ASSERT((*it)-&gt;shadowTreeElement()-&gt;correspondingElement());
-        ASSERT((*it)-&gt;shadowTreeElement()-&gt;correspondingElement() == (*it)-&gt;correspondingElement());
-        ASSERT((*it)-&gt;correspondingElement() == element);
-        (*it)-&gt;shadowTreeElement()-&gt;setCorrespondingElement(0);
-
-        if (SVGUseElement* element = (*it)-&gt;correspondingUseElement()) {
</del><ins>+    do {
+        SVGElement* instance = *instances.begin();
+        if (SVGUseElement* element = instance-&gt;correspondingUseElement()) {
</ins><span class="cx">             ASSERT(element-&gt;inDocument());
</span><span class="cx">             element-&gt;invalidateShadowTree();
</span><span class="cx">         }
</span><del>-    }
</del><ins>+        instance-&gt;setCorrespondingElement(nullptr);
+    } while (!instances.isEmpty());
</ins><span class="cx"> 
</span><span class="cx">     element-&gt;document().updateStyleIfNeeded();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGElementRareDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGElementRareData.h (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -31,23 +31,19 @@
</span><span class="cx"> class CSSCursorImageValue;
</span><span class="cx"> class SVGCursorElement;
</span><span class="cx"> class SVGElement;
</span><del>-class SVGElementInstance;
</del><span class="cx"> 
</span><span class="cx"> class SVGElementRareData {
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(SVGElementRareData); WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><span class="cx">     SVGElementRareData()
</span><del>-        : m_cursorElement(0)
-        , m_cursorImageValue(0)
-        , m_correspondingElement(0)
-        , m_instancesUpdatesBlocked(false)
</del><ins>+        : m_instancesUpdatesBlocked(false)
</ins><span class="cx">         , m_useOverrideComputedStyle(false)
</span><span class="cx">         , m_needsOverrideComputedStyleUpdate(false)
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    HashSet&lt;SVGElementInstance*&gt;&amp; elementInstances() { return m_elementInstances; }
-    const HashSet&lt;SVGElementInstance*&gt;&amp; elementInstances() const { return m_elementInstances; }
</del><ins>+    HashSet&lt;SVGElement*&gt;&amp; instances() { return m_instances; }
+    const HashSet&lt;SVGElement*&gt;&amp; instances() const { return m_instances; }
</ins><span class="cx"> 
</span><span class="cx">     bool instanceUpdatesBlocked() const { return m_instancesUpdatesBlocked; }
</span><span class="cx">     void setInstanceUpdatesBlocked(bool value) { m_instancesUpdatesBlocked = value; }
</span><span class="lines">@@ -69,11 +65,6 @@
</span><span class="cx">         return *m_animatedSMILStyleProperties;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void destroyAnimatedSMILStyleProperties()
-    {
-        m_animatedSMILStyleProperties.clear();
-    }
-
</del><span class="cx">     RenderStyle* overrideComputedStyle(Element* element, RenderStyle* parentStyle)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(element);
</span><span class="lines">@@ -93,10 +84,10 @@
</span><span class="cx">     void setNeedsOverrideComputedStyleUpdate() { m_needsOverrideComputedStyleUpdate = true; }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    HashSet&lt;SVGElementInstance*&gt; m_elementInstances;
-    SVGCursorElement* m_cursorElement;
-    CSSCursorImageValue* m_cursorImageValue;
-    SVGElement* m_correspondingElement;
</del><ins>+    HashSet&lt;SVGElement*&gt; m_instances;
+    SVGCursorElement* m_cursorElement { nullptr };
+    CSSCursorImageValue* m_cursorImageValue { nullptr };
+    SVGElement* m_correspondingElement { nullptr };
</ins><span class="cx">     bool m_instancesUpdatesBlocked : 1;
</span><span class="cx">     bool m_useOverrideComputedStyle : 1;
</span><span class="cx">     bool m_needsOverrideComputedStyleUpdate : 1;
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGTestscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGTests.cpp (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,6 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann &lt;zimmermann@kde.org&gt;
</span><span class="cx">  * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis &lt;buis@kde.org&gt;
</span><ins>+ * Copyright (C) 2015 Apple Inc. All right reserved.
</ins><span class="cx">  *
</span><span class="cx">  * This library is free software; you can redistribute it and/or
</span><span class="cx">  * modify it under the terms of the GNU Library General Public
</span><span class="lines">@@ -36,77 +37,52 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-// 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(),
-                                             &amp;SVGElement::synchronizeRequiredFeatures,
-                                             0);
-    }
-    return s_propertyInfo;
-}
</del><ins>+using namespace SVGNames;
</ins><span class="cx"> 
</span><del>-// Define custom non-animated property 'requiredExtensions'.
-const SVGPropertyInfo* SVGTests::requiredExtensionsPropertyInfo()
</del><ins>+SVGTests::SVGTests()
+    : m_requiredFeatures(requiredFeaturesAttr)
+    , m_requiredExtensions(requiredExtensionsAttr)
+    , m_systemLanguage(systemLanguageAttr)
</ins><span class="cx"> {
</span><del>-    static const SVGPropertyInfo* s_propertyInfo = 0;
-    if (!s_propertyInfo) {
-        s_propertyInfo = new SVGPropertyInfo(AnimatedUnknown,
-                                             PropertyIsReadWrite,
-                                             SVGNames::requiredExtensionsAttr,
-                                             SVGNames::requiredExtensionsAttr.localName(),
-                                             &amp;SVGElement::synchronizeRequiredExtensions,
-                                             0);
-    }
-    return s_propertyInfo;
</del><span class="cx"> }
</span><span class="cx"> 
</span><del>-// Define custom non-animated property 'systemLanguage'.
-const SVGPropertyInfo* SVGTests::systemLanguagePropertyInfo()
</del><ins>+static SVGPropertyInfo createSVGTestPropertyInfo(const QualifiedName&amp; attributeName, SVGPropertyInfo::SynchronizeProperty synchronizeFunction)
</ins><span class="cx"> {
</span><del>-    static const SVGPropertyInfo* s_propertyInfo = 0;
-    if (!s_propertyInfo) {
-        s_propertyInfo = new SVGPropertyInfo(AnimatedUnknown,
-                                             PropertyIsReadWrite,
-                                             SVGNames::systemLanguageAttr,
-                                             SVGNames::systemLanguageAttr.localName(),
-                                             &amp;SVGElement::synchronizeSystemLanguage,
-                                             0);
-    }
-    return s_propertyInfo;
</del><ins>+    return { AnimatedUnknown, PropertyIsReadWrite, attributeName, attributeName.localName(), synchronizeFunction, nullptr };
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-SVGTests::SVGTests()
-    : m_requiredFeatures(SVGNames::requiredFeaturesAttr)
-    , m_requiredExtensions(SVGNames::requiredExtensionsAttr)
-    , m_systemLanguage(SVGNames::systemLanguageAttr)
</del><ins>+static SVGAttributeToPropertyMap createSVGTextAttributeToPropertyMap()
</ins><span class="cx"> {
</span><ins>+    typedef NeverDestroyed&lt;const SVGPropertyInfo&gt; 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;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-SVGAttributeToPropertyMap&amp; SVGTests::attributeToPropertyMap()
</del><ins>+const SVGAttributeToPropertyMap&amp; SVGTests::attributeToPropertyMap()
</ins><span class="cx"> {
</span><del>-    static NeverDestroyed&lt;SVGAttributeToPropertyMap&gt; map;
-    if (!map.get().isEmpty())
-        return map;
-    map.get().addProperty(requiredFeaturesPropertyInfo());
-    map.get().addProperty(requiredExtensionsPropertyInfo());
-    map.get().addProperty(systemLanguagePropertyInfo());
</del><ins>+    static NeverDestroyed&lt;SVGAttributeToPropertyMap&gt; map = createSVGTextAttributeToPropertyMap();
</ins><span class="cx">     return map;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool SVGTests::hasExtension(const String&amp; extension) const
</del><ins>+bool SVGTests::hasExtension(const String&amp; extension)
</ins><span class="cx"> {
</span><span class="cx">     // 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).
</span><span class="cx"> #if ENABLE(MATHML)
</span><del>-    return extension == HTMLNames::xhtmlNamespaceURI || extension == MathMLNames::mathmlNamespaceURI;
-#else
-    return extension == HTMLNames::xhtmlNamespaceURI;
</del><ins>+    if (extension == MathMLNames::mathmlNamespaceURI)
+        return true;
</ins><span class="cx"> #endif
</span><ins>+    return extension == HTMLNames::xhtmlNamespaceURI;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool SVGTests::isValid() const
</span><span class="lines">@@ -115,90 +91,80 @@
</span><span class="cx">         if (feature.isEmpty() || !DOMImplementation::hasFeature(feature, String()))
</span><span class="cx">             return false;
</span><span class="cx">     }
</span><del>-
</del><span class="cx">     for (auto&amp; language : m_systemLanguage.value) {
</span><span class="cx">         if (language != defaultLanguage().substring(0, 2))
</span><span class="cx">             return false;
</span><span class="cx">     }
</span><del>-
</del><span class="cx">     for (auto&amp; extension : m_requiredExtensions.value) {
</span><span class="cx">         if (!hasExtension(extension))
</span><span class="cx">             return false;
</span><span class="cx">     }
</span><del>-
</del><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool SVGTests::parseAttribute(const QualifiedName&amp; name, const AtomicString&amp; value)
</del><ins>+bool SVGTests::parseAttribute(const QualifiedName&amp; attributeName, const AtomicString&amp; value)
</ins><span class="cx"> {
</span><del>-    if (name == SVGNames::requiredFeaturesAttr) {
</del><ins>+    if (attributeName == requiredFeaturesAttr) {
</ins><span class="cx">         m_requiredFeatures.value.reset(value);
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><del>-    if (name == SVGNames::requiredExtensionsAttr) {
</del><ins>+    if (attributeName == requiredExtensionsAttr) {
</ins><span class="cx">         m_requiredExtensions.value.reset(value);
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><del>-    if (name == SVGNames::systemLanguageAttr) {
</del><ins>+    if (attributeName == systemLanguageAttr) {
</ins><span class="cx">         m_systemLanguage.value.reset(value);
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><del>-    
</del><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool SVGTests::isKnownAttribute(const QualifiedName&amp; attrName)
</del><ins>+bool SVGTests::isKnownAttribute(const QualifiedName&amp; attributeName)
</ins><span class="cx"> {
</span><del>-    return attrName == SVGNames::requiredFeaturesAttr
-        || attrName == SVGNames::requiredExtensionsAttr
-        || attrName == SVGNames::systemLanguageAttr;
</del><ins>+    return attributeName == requiredFeaturesAttr
+        || attributeName == requiredExtensionsAttr
+        || attributeName == systemLanguageAttr;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool SVGTests::handleAttributeChange(SVGElement* targetElement, const QualifiedName&amp; attrName)
</del><ins>+bool SVGTests::handleAttributeChange(SVGElement* targetElement, const QualifiedName&amp; attributeName)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(targetElement);
</span><del>-    if (!isKnownAttribute(attrName))
</del><ins>+    if (!isKnownAttribute(attributeName))
</ins><span class="cx">         return false;
</span><span class="cx">     if (!targetElement-&gt;inDocument())
</span><span class="cx">         return true;
</span><del>-
</del><span class="cx">     targetElement-&gt;setNeedsStyleRecalc(ReconstructRenderTree);
</span><del>-
</del><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SVGTests::addSupportedAttributes(HashSet&lt;QualifiedName&gt;&amp; supportedAttributes)
</span><span class="cx"> {
</span><del>-    supportedAttributes.add(SVGNames::requiredFeaturesAttr);
-    supportedAttributes.add(SVGNames::requiredExtensionsAttr);
-    supportedAttributes.add(SVGNames::systemLanguageAttr);
</del><ins>+    supportedAttributes.add(requiredFeaturesAttr);
+    supportedAttributes.add(requiredExtensionsAttr);
+    supportedAttributes.add(systemLanguageAttr);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SVGTests::synchronizeRequiredFeatures(SVGElement* contextElement)
</del><ins>+void SVGTests::synchronizeAttribute(SVGElement* contextElement, SVGSynchronizableAnimatedProperty&lt;SVGStringList&gt;&amp; property, const QualifiedName&amp; attributeName)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(contextElement);
</span><del>-    if (!m_requiredFeatures.shouldSynchronize)
</del><ins>+    if (!property.shouldSynchronize)
</ins><span class="cx">         return;
</span><del>-    AtomicString value(m_requiredFeatures.value.valueAsString());
-    m_requiredFeatures.synchronize(contextElement, requiredFeaturesPropertyInfo()-&gt;attributeName, value);
</del><ins>+    m_requiredFeatures.synchronize(contextElement, attributeName, property.value.valueAsString());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SVGTests::synchronizeRequiredFeatures(SVGElement* contextElement)
+{
+    synchronizeAttribute(contextElement, m_requiredFeatures, requiredFeaturesAttr);
+}
+
</ins><span class="cx"> void SVGTests::synchronizeRequiredExtensions(SVGElement* contextElement)
</span><span class="cx"> {
</span><del>-    ASSERT(contextElement);
-    if (!m_requiredExtensions.shouldSynchronize)
-        return;
-    AtomicString value(m_requiredExtensions.value.valueAsString());
-    m_requiredExtensions.synchronize(contextElement, requiredExtensionsPropertyInfo()-&gt;attributeName, value);
</del><ins>+    synchronizeAttribute(contextElement, m_requiredExtensions, requiredExtensionsAttr);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SVGTests::synchronizeSystemLanguage(SVGElement* contextElement)
</span><span class="cx"> {
</span><del>-    ASSERT(contextElement);
-    if (!m_systemLanguage.shouldSynchronize)
-        return;
-    AtomicString value(m_systemLanguage.value.valueAsString());
-    m_systemLanguage.synchronize(contextElement, systemLanguagePropertyInfo()-&gt;attributeName, value);
</del><ins>+    synchronizeAttribute(contextElement, m_systemLanguage, systemLanguageAttr);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> SVGStringList&amp; SVGTests::requiredFeatures()
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGTestsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGTests.h (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -26,8 +26,6 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-class Attribute;
-class QualifiedName;
</del><span class="cx"> class SVGElement;
</span><span class="cx"> 
</span><span class="cx"> class SVGTests {
</span><span class="lines">@@ -36,16 +34,16 @@
</span><span class="cx">     SVGStringList&amp; requiredExtensions();
</span><span class="cx">     SVGStringList&amp; systemLanguage();
</span><span class="cx"> 
</span><del>-    bool hasExtension(const String&amp;) const;
</del><ins>+    static bool hasExtension(const String&amp;);
</ins><span class="cx">     bool isValid() const;
</span><span class="cx"> 
</span><span class="cx">     bool parseAttribute(const QualifiedName&amp;, const AtomicString&amp;);
</span><del>-    bool isKnownAttribute(const QualifiedName&amp;);
</del><ins>+    static bool isKnownAttribute(const QualifiedName&amp;);
</ins><span class="cx"> 
</span><del>-    void addSupportedAttributes(HashSet&lt;QualifiedName&gt;&amp;);
-    bool handleAttributeChange(SVGElement*, const QualifiedName&amp;);
</del><ins>+    static void addSupportedAttributes(HashSet&lt;QualifiedName&gt;&amp;);
+    static bool handleAttributeChange(SVGElement*, const QualifiedName&amp;);
</ins><span class="cx"> 
</span><del>-    static SVGAttributeToPropertyMap&amp; attributeToPropertyMap();
</del><ins>+    static const SVGAttributeToPropertyMap&amp; attributeToPropertyMap();
</ins><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="cx">     SVGTests();
</span><span class="lines">@@ -55,16 +53,10 @@
</span><span class="cx">     void synchronizeSystemLanguage(SVGElement* contextElement);
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    // Custom 'requiredFeatures' property
-    static const SVGPropertyInfo* requiredFeaturesPropertyInfo();
-    SVGSynchronizableAnimatedProperty&lt;SVGStringList&gt; m_requiredFeatures;
</del><ins>+    void synchronizeAttribute(SVGElement* contextElement, SVGSynchronizableAnimatedProperty&lt;SVGStringList&gt;&amp;, const QualifiedName&amp; attributeName);
</ins><span class="cx"> 
</span><del>-    // Custom 'requiredExtensions' property
-    static const SVGPropertyInfo* requiredExtensionsPropertyInfo();
</del><ins>+    SVGSynchronizableAnimatedProperty&lt;SVGStringList&gt; m_requiredFeatures;
</ins><span class="cx">     SVGSynchronizableAnimatedProperty&lt;SVGStringList&gt; m_requiredExtensions;
</span><del>-
-    // Custom 'systemLanguage' property
-    static const SVGPropertyInfo* systemLanguagePropertyInfo();
</del><span class="cx">     SVGSynchronizableAnimatedProperty&lt;SVGStringList&gt; m_systemLanguage;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGUseElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGUseElement.cpp (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -776,10 +776,8 @@
</span><span class="cx"> void SVGUseElement::invalidateDependentShadowTrees()
</span><span class="cx"> {
</span><span class="cx">     // Recursively invalidate dependent &lt;use&gt; shadow trees
</span><del>-    const HashSet&lt;SVGElementInstance*&gt;&amp; instances = instancesForElement();
-    const HashSet&lt;SVGElementInstance*&gt;::const_iterator end = instances.end();
-    for (HashSet&lt;SVGElementInstance*&gt;::const_iterator it = instances.begin(); it != end; ++it) {
-        if (SVGUseElement* element = (*it)-&gt;correspondingUseElement()) {
</del><ins>+    for (auto* instance : instances()) {
+        if (SVGUseElement* element = instance-&gt;correspondingUseElement()) {
</ins><span class="cx">             ASSERT(element-&gt;inDocument());
</span><span class="cx">             element-&gt;invalidateShadowTree();
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceWebCoresvgpropertiesSVGAnimatedPropertyMacrosh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/properties/SVGAnimatedPropertyMacros.h (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #include &quot;SVGAnimatedProperty.h&quot;
</span><span class="cx"> #include &quot;SVGAttributeToPropertyMap.h&quot;
</span><span class="cx"> #include &quot;SVGPropertyTraits.h&quot;
</span><ins>+#include &lt;wtf/NeverDestroyed.h&gt;
</ins><span class="cx"> #include &lt;wtf/StdLibExtras.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="lines">@@ -70,23 +71,19 @@
</span><span class="cx"> #define BEGIN_REGISTER_ANIMATED_PROPERTIES(OwnerType) \
</span><span class="cx"> SVGAttributeToPropertyMap&amp; OwnerType::attributeToPropertyMap() \
</span><span class="cx"> { \
</span><del>-    DEPRECATED_DEFINE_STATIC_LOCAL(SVGAttributeToPropertyMap, s_attributeToPropertyMap, ()); \
-    return s_attributeToPropertyMap; \
</del><ins>+    static NeverDestroyed&lt;SVGAttributeToPropertyMap&gt; map; \
+    return map; \
</ins><span class="cx"> } \
</span><span class="cx"> \
</span><span class="cx"> static void registerAnimatedPropertiesFor##OwnerType() \
</span><span class="cx"> { \
</span><del>-    SVGAttributeToPropertyMap&amp; map = OwnerType::attributeToPropertyMap(); \
</del><ins>+    auto&amp; map = OwnerType::attributeToPropertyMap(); \
</ins><span class="cx">     if (!map.isEmpty()) \
</span><span class="cx">         return; \
</span><span class="cx">     typedef OwnerType UseOwnerType;
</span><span class="cx"> 
</span><del>-#define REGISTER_LOCAL_ANIMATED_PROPERTY(LowerProperty) \
-     map.addProperty(UseOwnerType::LowerProperty##PropertyInfo());
-
-#define REGISTER_PARENT_ANIMATED_PROPERTIES(ClassName) \
-     map.addProperties(ClassName::attributeToPropertyMap()); \
-
</del><ins>+#define REGISTER_LOCAL_ANIMATED_PROPERTY(LowerProperty) map.addProperty(*UseOwnerType::LowerProperty##PropertyInfo());
+#define REGISTER_PARENT_ANIMATED_PROPERTIES(ClassName) map.addProperties(ClassName::attributeToPropertyMap());
</ins><span class="cx"> #define END_REGISTER_ANIMATED_PROPERTIES }
</span><span class="cx"> 
</span><span class="cx"> // Property definition helpers (used in SVG*.cpp files)
</span></span></pre></div>
<a id="trunkSourceWebCoresvgpropertiesSVGAttributeToPropertyMapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/properties/SVGAttributeToPropertyMap.cpp (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,5 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
</span><ins>+ * Copyright (C) 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * This library is free software; you can redistribute it and/or
</span><span class="cx">  * modify it under the terms of the GNU Library General Public
</span><span class="lines">@@ -21,106 +22,65 @@
</span><span class="cx"> #include &quot;SVGAttributeToPropertyMap.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;SVGAnimatedProperty.h&quot;
</span><del>-#include &quot;SVGPropertyInfo.h&quot;
</del><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> void SVGAttributeToPropertyMap::addProperties(const SVGAttributeToPropertyMap&amp; map)
</span><span class="cx"> {
</span><del>-    AttributeToPropertiesMap::const_iterator end = map.m_map.end();
-    for (AttributeToPropertiesMap::const_iterator it = map.m_map.begin(); it != end; ++it) {
-        const PropertiesVector* vector = it-&gt;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-&gt;end();
-        for (PropertiesVector::const_iterator vectorIt = vector-&gt;begin(); vectorIt != vectorEnd; ++vectorIt)
-            addProperty(*vectorIt);
</del><ins>+    for (auto&amp; vector : map.m_map.values()) {
+        ASSERT(!vector.isEmpty());
+        auto&amp; properties = m_map.add(vector[0]-&gt;attributeName, PropertyInfoVector()).iterator-&gt;value;
+        properties.reserveCapacity(properties.size() + vector.size());
+        for (auto* property : vector)
+            properties.uncheckedAppend(property);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SVGAttributeToPropertyMap::addProperty(const SVGPropertyInfo* info)
</del><ins>+void SVGAttributeToPropertyMap::addProperty(const SVGPropertyInfo&amp; info)
</ins><span class="cx"> {
</span><del>-    ASSERT(info);
-    ASSERT(info-&gt;attributeName != anyQName());
-    if (PropertiesVector* vector = m_map.get(info-&gt;attributeName)) {
-        vector-&gt;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&lt;PropertiesVector&gt;();
-    vector-&gt;append(info);
-    m_map.set(info-&gt;attributeName, WTF::move(vector));
</del><ins>+    m_map.add(info.attributeName, PropertyInfoVector()).iterator-&gt;value.append(&amp;info);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SVGAttributeToPropertyMap::animatedPropertiesForAttribute(SVGElement* ownerType, const QualifiedName&amp; attributeName, Vector&lt;RefPtr&lt;SVGAnimatedProperty&gt;&gt;&amp; properties)
</del><ins>+Vector&lt;RefPtr&lt;SVGAnimatedProperty&gt;&gt; SVGAttributeToPropertyMap::properties(SVGElement&amp; contextElement, const QualifiedName&amp; attributeName) const
</ins><span class="cx"> {
</span><del>-    ASSERT(ownerType);
-    PropertiesVector* vector = m_map.get(attributeName);
-    if (!vector)
-        return;
-
-    PropertiesVector::iterator vectorEnd = vector-&gt;end();
-    for (PropertiesVector::iterator vectorIt = vector-&gt;begin(); vectorIt != vectorEnd; ++vectorIt)
-        properties.append(animatedProperty(ownerType, attributeName, *vectorIt));
</del><ins>+    Vector&lt;RefPtr&lt;SVGAnimatedProperty&gt;&gt; properties;
+    auto it = m_map.find(attributeName);
+    if (it == m_map.end())
+        return properties;
+    properties.reserveInitialCapacity(it-&gt;value.size());
+    for (auto* property : it-&gt;value)
+        properties.uncheckedAppend(property-&gt;lookupOrCreateWrapperForAnimatedProperty(&amp;contextElement));
+    return properties;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SVGAttributeToPropertyMap::animatedPropertyTypeForAttribute(const QualifiedName&amp; attributeName, Vector&lt;AnimatedPropertyType&gt;&amp; propertyTypes)
</del><ins>+Vector&lt;AnimatedPropertyType&gt; SVGAttributeToPropertyMap::types(const QualifiedName&amp; attributeName) const
</ins><span class="cx"> {
</span><del>-    PropertiesVector* vector = m_map.get(attributeName);
-    if (!vector)
-        return;
-
-    PropertiesVector::iterator vectorEnd = vector-&gt;end();
-    for (PropertiesVector::iterator vectorIt = vector-&gt;begin(); vectorIt != vectorEnd; ++vectorIt)
-        propertyTypes.append((*vectorIt)-&gt;animatedPropertyType);
</del><ins>+    Vector&lt;AnimatedPropertyType&gt; types;
+    auto it = m_map.find(attributeName);
+    if (it == m_map.end())
+        return types;
+    types.reserveInitialCapacity(it-&gt;value.size());
+    for (auto* property : it-&gt;value)
+        types.uncheckedAppend(property-&gt;animatedPropertyType);
+    return types;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SVGAttributeToPropertyMap::synchronizeProperties(SVGElement* contextElement)
</del><ins>+void SVGAttributeToPropertyMap::synchronizeProperties(SVGElement&amp; contextElement) const
</ins><span class="cx"> {
</span><del>-    ASSERT(contextElement);
-    AttributeToPropertiesMap::iterator end = m_map.end();
-    for (AttributeToPropertiesMap::iterator it = m_map.begin(); it != end; ++it) {
-        PropertiesVector* vector = it-&gt;value.get();
-        ASSERT(vector);
-
-        PropertiesVector::iterator vectorEnd = vector-&gt;end();
-        for (PropertiesVector::iterator vectorIt = vector-&gt;begin(); vectorIt != vectorEnd; ++vectorIt)
-            synchronizeProperty(contextElement, it-&gt;key, *vectorIt);
</del><ins>+    for (auto&amp; vector : m_map.values()) {
+        for (auto* property : vector)
+            property-&gt;synchronizeProperty(&amp;contextElement);
</ins><span class="cx">     } 
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool SVGAttributeToPropertyMap::synchronizeProperty(SVGElement* contextElement, const QualifiedName&amp; attributeName)
</del><ins>+bool SVGAttributeToPropertyMap::synchronizeProperty(SVGElement&amp; contextElement, const QualifiedName&amp; attributeName) const
</ins><span class="cx"> {
</span><del>-    ASSERT(contextElement);
-    PropertiesVector* vector = m_map.get(attributeName);
-    if (!vector)
</del><ins>+    auto it = m_map.find(attributeName);
+    if (it == m_map.end())
</ins><span class="cx">         return false;
</span><del>-
-    PropertiesVector::iterator vectorEnd = vector-&gt;end();
-    for (PropertiesVector::iterator vectorIt = vector-&gt;begin(); vectorIt != vectorEnd; ++vectorIt)
-        synchronizeProperty(contextElement, attributeName, *vectorIt);
-
</del><ins>+    for (auto* property : it-&gt;value)
+        property-&gt;synchronizeProperty(&amp;contextElement);
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SVGAttributeToPropertyMap::synchronizeProperty(SVGElement* contextElement, const QualifiedName&amp; attributeName, const SVGPropertyInfo* info)
-{
-    ASSERT(info);
-    ASSERT_UNUSED(attributeName, attributeName == info-&gt;attributeName);
-    ASSERT(info-&gt;synchronizeProperty);
-    (*info-&gt;synchronizeProperty)(contextElement);
</del><span class="cx"> }
</span><del>-
-PassRefPtr&lt;SVGAnimatedProperty&gt; SVGAttributeToPropertyMap::animatedProperty(SVGElement* contextElement, const QualifiedName&amp; attributeName, const SVGPropertyInfo* info)
-{
-    ASSERT(info);
-    ASSERT_UNUSED(attributeName, attributeName == info-&gt;attributeName);
-    ASSERT(info-&gt;lookupOrCreateWrapperForAnimatedProperty);
-    return (*info-&gt;lookupOrCreateWrapperForAnimatedProperty)(contextElement);
-}
-
-}
</del></span></pre></div>
<a id="trunkSourceWebCoresvgpropertiesSVGAttributeToPropertyMaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/properties/SVGAttributeToPropertyMap.h (179259 => 179260)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,5 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
</span><ins>+ * Copyright (C) 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * This library is free software; you can redistribute it and/or
</span><span class="cx">  * modify it under the terms of the GNU Library General Public
</span><span class="lines">@@ -32,24 +33,18 @@
</span><span class="cx"> public:
</span><span class="cx">     bool isEmpty() const { return m_map.isEmpty(); }
</span><span class="cx"> 
</span><ins>+    void addProperty(const SVGPropertyInfo&amp;);
</ins><span class="cx">     void addProperties(const SVGAttributeToPropertyMap&amp;);
</span><del>-    void addProperty(const SVGPropertyInfo*);
</del><span class="cx"> 
</span><del>-    // FIXME: To match WebKit coding style either these functions should have return values instead of out parameters,
-    // or the word &quot;get&quot; should be added as a prefix to their names.
-    void animatedPropertiesForAttribute(SVGElement* contextElement, const QualifiedName&amp; attributeName, Vector&lt;RefPtr&lt;SVGAnimatedProperty&gt;&gt;&amp;);
-    void animatedPropertyTypeForAttribute(const QualifiedName&amp; attributeName, Vector&lt;AnimatedPropertyType&gt;&amp;);
</del><ins>+    Vector&lt;RefPtr&lt;SVGAnimatedProperty&gt;&gt; properties(SVGElement&amp;, const QualifiedName&amp; attributeName) const;
+    Vector&lt;AnimatedPropertyType&gt; types(const QualifiedName&amp; attributeName) const;
</ins><span class="cx"> 
</span><del>-    void synchronizeProperties(SVGElement* contextElement);
-    bool synchronizeProperty(SVGElement* contextElement, const QualifiedName&amp; attributeName);
</del><ins>+    void synchronizeProperties(SVGElement&amp;) const;
+    bool synchronizeProperty(SVGElement&amp;, const QualifiedName&amp; attributeName) const;
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    void synchronizeProperty(SVGElement* contextElement, const QualifiedName&amp; attributeName, const SVGPropertyInfo*);
-    PassRefPtr&lt;SVGAnimatedProperty&gt; animatedProperty(SVGElement* contextElement, const QualifiedName&amp; attributeName, const SVGPropertyInfo*);
-
-    typedef Vector&lt;const SVGPropertyInfo*&gt; PropertiesVector;
-    typedef HashMap&lt;QualifiedName, std::unique_ptr&lt;PropertiesVector&gt;&gt; AttributeToPropertiesMap;
-    AttributeToPropertiesMap m_map;
</del><ins>+    typedef Vector&lt;const SVGPropertyInfo*&gt; PropertyInfoVector;
+    HashMap&lt;QualifiedName, PropertyInfoVector&gt; m_map;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre>
</div>
</div>

</body>
</html>